#include "llvm/ADT/TypeSwitch.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InlineAsm.h"
class Importer {
public:
Importer(MLIRContext *context, ModuleOp module)
- : b(context), context(context), module(module),
- unknownLoc(FileLineColLoc::get(context, "imported-bitcode", 0, 0)),
- typeTranslator(*context) {
+ : b(context), context(context), module(module), typeTranslator(*context) {
b.setInsertionPointToStart(module.getBody());
}
/// placeholder that will be remapped later if this is an instruction that
/// has not yet been visited.
Value processValue(llvm::Value *value);
- /// Create the most accurate Location possible using a llvm::DebugLoc and
- /// possibly an llvm::Instruction to narrow the Location if debug information
- /// is unavailable.
- Location processDebugLoc(const llvm::DebugLoc &loc,
- llvm::Instruction *inst = nullptr);
+ /// Translate the debug location to a FileLineColLoc, if `loc` is non-null.
+ /// Otherwise, return UnknownLoc.
+ Location processDebugLoc(llvm::DILocation *loc);
/// `br` branches to `target`. Append the block arguments to attach to the
/// generated branch op to `blockArguments`. These should be in the same order
/// as the PHIs in `target`.
DenseMap<llvm::Value *, Operation *> unknownInstMap;
/// Uniquing map of GlobalVariables.
DenseMap<llvm::GlobalVariable *, GlobalOp> globals;
- /// Cached FileLineColLoc::get("imported-bitcode", 0, 0).
- Location unknownLoc;
/// The stateful type translator (contains named structs).
LLVM::TypeFromLLVMIRTranslator typeTranslator;
};
} // namespace
-Location Importer::processDebugLoc(const llvm::DebugLoc &loc,
- llvm::Instruction *inst) {
+Location Importer::processDebugLoc(llvm::DILocation *loc) {
if (!loc)
- return unknownLoc;
+ return UnknownLoc::get(context);
- // FIXME: Obtain the filename from DILocationInfo.
- return FileLineColLoc::get(context, "imported-bitcode", loc.getLine(),
- loc.getCol());
+ return FileLineColLoc::get(context, loc->getFilename(), loc->getLine(),
+ loc->getColumn());
}
Type Importer::processType(llvm::Type *type) {
std::string s;
llvm::raw_string_ostream os(s);
os << *type;
- emitError(unknownLoc) << "unhandled type: " << os.str();
+ emitError(UnknownLoc::get(context)) << "unhandled type: " << os.str();
return nullptr;
}
if (LLVM::isCompatibleVectorType(type)) {
auto numElements = LLVM::getVectorNumElements(type);
if (numElements.isScalable()) {
- emitError(unknownLoc) << "scalable vectors not supported";
+ emitError(UnknownLoc::get(context)) << "scalable vectors not supported";
return nullptr;
}
Type elementType = getStdTypeForAttr(LLVM::getVectorElementType(type));
if (LLVM::isCompatibleVectorType(arrayType.getElementType())) {
auto numElements = LLVM::getVectorNumElements(arrayType.getElementType());
if (numElements.isScalable()) {
- emitError(unknownLoc) << "scalable vectors not supported";
+ emitError(UnknownLoc::get(context)) << "scalable vectors not supported";
return nullptr;
}
shape.push_back(numElements.getKnownMinValue());
if (!type)
return nullptr;
if (auto symbolRef = attr.dyn_cast<FlatSymbolRefAttr>())
- return bEntry.create<AddressOfOp>(unknownLoc, type, symbolRef.getValue());
- return bEntry.create<ConstantOp>(unknownLoc, type, attr);
+ return bEntry.create<AddressOfOp>(UnknownLoc::get(context), type,
+ symbolRef.getValue());
+ return bEntry.create<ConstantOp>(UnknownLoc::get(context), type, attr);
}
if (auto *cn = dyn_cast<llvm::ConstantPointerNull>(c)) {
Type type = processType(cn->getType());
if (!type)
return nullptr;
- return bEntry.create<NullOp>(unknownLoc, type);
+ return bEntry.create<NullOp>(UnknownLoc::get(context), type);
}
if (auto *gv = dyn_cast<llvm::GlobalVariable>(c))
return bEntry.create<AddressOfOp>(UnknownLoc::get(context),
bool useInsertValue = rootType.isa<LLVMArrayType, LLVMStructType>();
assert((useInsertValue || LLVM::isCompatibleVectorType(rootType)) &&
"unrecognized aggregate type");
- Value root = bEntry.create<UndefOp>(unknownLoc, rootType);
+ Value root = bEntry.create<UndefOp>(UnknownLoc::get(context), rootType);
for (unsigned i = 0; i < numElements; ++i) {
llvm::Constant *element = getElement(i);
Value elementValue = processConstant(element);
} else {
Attribute indexAttr = bEntry.getI32IntegerAttr(static_cast<int32_t>(i));
Value indexValue = bEntry.create<ConstantOp>(
- unknownLoc, bEntry.getI32Type(), indexAttr);
+ UnknownLoc::get(context), bEntry.getI32Type(), indexAttr);
if (!indexValue)
return nullptr;
root = bEntry.create<InsertElementOp>(
return root;
}
- emitError(unknownLoc) << "unhandled constant: " << diag(*c);
+ emitError(UnknownLoc::get(context)) << "unhandled constant: " << diag(*c);
return nullptr;
}
if (auto *c = dyn_cast<llvm::Constant>(value))
return processConstant(c);
- emitError(unknownLoc) << "unhandled value: " << diag(*value);
+ emitError(UnknownLoc::get(context)) << "unhandled value: " << diag(*value);
return nullptr;
}
LogicalResult Importer::processInstruction(llvm::Instruction *inst) {
// FIXME: Support uses of SubtargetData. Currently inbounds GEPs, fast-math
// flags and call / operand attributes are not supported.
- Location loc = processDebugLoc(inst->getDebugLoc(), inst);
+ Location loc = processDebugLoc(inst->getDebugLoc());
assert(!instMap.count(inst) &&
"processInstruction must be called only once per instruction!");
switch (inst->getOpcode()) {
if (!type)
return failure();
instMap[inst] = b.getInsertionBlock()->addArgument(
- type, processDebugLoc(inst->getDebugLoc(), inst));
+ type, processDebugLoc(inst->getDebugLoc()));
return success();
}
case llvm::Instruction::Call: {
--- /dev/null
+; RUN: mlir-translate -import-llvm -mlir-print-debuginfo -split-input-file %s | FileCheck %s
+
+; CHECK: #[[$UNKNOWNLOC:.+]] = loc(unknown)
+; CHECK-LABEL: @unknown(
+define i32 @unknown(i32 %0) {
+entry:
+ br label %next
+end:
+ ; CHECK: ^{{.*}}(%{{.+}}: i32 loc(unknown)):
+ %1 = phi i32 [ %2, %next ]
+ ret i32 %1
+next:
+ ; CHECK: = llvm.mul %{{.+}}, %{{.+}} : i32 loc(#[[$UNKNOWNLOC:.+]])
+ %2 = mul i32 %0, %0
+ br label %end
+}
+
+; // -----
+
+; CHECK-LABEL: @known_loc(
+define i32 @known_loc(i32 %0) {
+entry:
+ br label %next
+end:
+ ; CHECK: ^{{.*}}(%{{.+}}: i32 loc("known_loc.cpp":5:2)):
+ %1 = phi i32 [ %2, %next ], !dbg !4
+ ret i32 %1
+next:
+ ; CHECK: = llvm.mul %{{.+}}, %{{.+}} : i32 loc(#[[LOC:.+]])
+ %2 = mul i32 %0, %0, !dbg !5
+ br label %end
+}
+; CHECK: #[[LOC]] = loc("known_loc.cpp":8:3)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!1}
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !2)
+!1 = !{i32 2, !"Debug Info Version", i32 3}
+!2 = !DIFile(filename: "known_loc.cpp", directory: "/")
+!3 = distinct !DISubprogram(name: "known_loc", scope: !0, file: !2, line: 1, scopeLine: 1, unit: !0)
+!4 = !DILocation(line: 5, column: 2, scope: !3)
+!5 = !DILocation(line: 8, column: 3, scope: !3)