diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td @@ -303,7 +303,7 @@ let parameters = (ins LLVM_DILanguageParameter:$sourceLanguage, "DIFileAttr":$file, - "StringAttr":$producer, + OptionalParameter<"StringAttr">:$producer, "bool":$isOptimized, "DIEmissionKind":$emissionKind ); @@ -318,7 +318,7 @@ /*traits=*/[], "DITypeAttr"> { let parameters = (ins LLVM_DITagParameter:$tag, - "StringAttr":$name, + OptionalParameter<"StringAttr">:$name, OptionalParameter<"DIFileAttr">:$file, OptionalParameter<"uint32_t">:$line, OptionalParameter<"DIScopeAttr">:$scope, @@ -414,7 +414,7 @@ /*traits=*/[], "DINodeAttr"> { let parameters = (ins "DIScopeAttr":$scope, - "StringAttr":$name, + OptionalParameter<"StringAttr">:$name, OptionalParameter<"DIFileAttr">:$file, OptionalParameter<"unsigned">:$line, OptionalParameter<"unsigned">:$arg, diff --git a/mlir/lib/Target/LLVMIR/DebugImporter.h b/mlir/lib/Target/LLVMIR/DebugImporter.h --- a/mlir/lib/Target/LLVMIR/DebugImporter.h +++ b/mlir/lib/Target/LLVMIR/DebugImporter.h @@ -67,6 +67,10 @@ DISubroutineTypeAttr translateImpl(llvm::DISubroutineType *node); DITypeAttr translateImpl(llvm::DIType *node); + /// Constructs a StringAttr from the MDString if it is non-null. Returns a + /// null attribute otherwise. + StringAttr getStringAttrOrNull(llvm::MDString *stringNode); + /// A mapping between LLVM debug metadata and the corresponding attribute. DenseMap nodeToAttr; diff --git a/mlir/lib/Target/LLVMIR/DebugImporter.cpp b/mlir/lib/Target/LLVMIR/DebugImporter.cpp --- a/mlir/lib/Target/LLVMIR/DebugImporter.cpp +++ b/mlir/lib/Target/LLVMIR/DebugImporter.cpp @@ -47,7 +47,7 @@ symbolizeDIEmissionKind(node->getEmissionKind()); return DICompileUnitAttr::get(context, node->getSourceLanguage(), translate(node->getFile()), - StringAttr::get(context, node->getProducer()), + getStringAttrOrNull(node->getRawProducer()), node->isOptimized(), emissionKind.value()); } @@ -66,7 +66,7 @@ if (llvm::is_contained(elements, nullptr)) elements.clear(); return DICompositeTypeAttr::get( - context, node->getTag(), StringAttr::get(context, node->getName()), + context, node->getTag(), getStringAttrOrNull(node->getRawName()), translate(node->getFile()), node->getLine(), translate(node->getScope()), translate(node->getBaseType()), flags.value_or(DIFlags::Zero), node->getSizeInBits(), node->getAlignInBits(), elements); @@ -78,8 +78,7 @@ if (node->getBaseType() && !baseType) return nullptr; return DIDerivedTypeAttr::get( - context, node->getTag(), - node->getRawName() ? StringAttr::get(context, node->getName()) : nullptr, + context, node->getTag(), getStringAttrOrNull(node->getRawName()), baseType, node->getSizeInBits(), node->getAlignInBits(), node->getOffsetInBits()); } @@ -103,7 +102,7 @@ DILocalVariableAttr DebugImporter::translateImpl(llvm::DILocalVariable *node) { return DILocalVariableAttr::get(context, translate(node->getScope()), - StringAttr::get(context, node->getName()), + getStringAttrOrNull(node->getRawName()), translate(node->getFile()), node->getLine(), node->getArg(), node->getAlignInBits(), translate(node->getType())); @@ -114,9 +113,9 @@ } DINamespaceAttr DebugImporter::translateImpl(llvm::DINamespace *node) { - return DINamespaceAttr::get( - context, StringAttr::get(context, node->getName()), - translate(node->getScope()), node->getExportSymbols()); + return DINamespaceAttr::get(context, getStringAttrOrNull(node->getRawName()), + translate(node->getScope()), + node->getExportSymbols()); } DISubprogramAttr DebugImporter::translateImpl(llvm::DISubprogram *node) { @@ -129,14 +128,12 @@ DISubroutineTypeAttr type = translate(node->getType()); if (node->getType() && !type) return nullptr; - return DISubprogramAttr::get( - context, translate(node->getUnit()), scope, - StringAttr::get(context, node->getName()), - node->getRawLinkageName() - ? StringAttr::get(context, node->getLinkageName()) - : nullptr, - translate(node->getFile()), node->getLine(), node->getScopeLine(), - subprogramFlags.value(), type); + return DISubprogramAttr::get(context, translate(node->getUnit()), scope, + getStringAttrOrNull(node->getRawName()), + getStringAttrOrNull(node->getRawLinkageName()), + translate(node->getFile()), node->getLine(), + node->getScopeLine(), subprogramFlags.value(), + type); } DISubrangeAttr DebugImporter::translateImpl(llvm::DISubrange *node) { @@ -248,3 +245,9 @@ context); return result; } + +StringAttr DebugImporter::getStringAttrOrNull(llvm::MDString *stringNode) { + if (!stringNode) + return StringAttr(); + return StringAttr::get(context, stringNode->getString()); +} diff --git a/mlir/lib/Target/LLVMIR/DebugTranslation.h b/mlir/lib/Target/LLVMIR/DebugTranslation.h --- a/mlir/lib/Target/LLVMIR/DebugTranslation.h +++ b/mlir/lib/Target/LLVMIR/DebugTranslation.h @@ -78,6 +78,10 @@ llvm::DISubroutineType *translateImpl(DISubroutineTypeAttr attr); llvm::DIType *translateImpl(DITypeAttr attr); + /// Constructs a string metadata node from the string attribute. Returns + /// nullptr if `stringAttr` is null or contains and empty string. + llvm::MDString *getMDStringOrNull(StringAttr stringAttr); + /// A mapping between mlir location+scope and the corresponding llvm debug /// metadata. DenseMap, diff --git a/mlir/lib/Target/LLVMIR/DebugTranslation.cpp b/mlir/lib/Target/LLVMIR/DebugTranslation.cpp --- a/mlir/lib/Target/LLVMIR/DebugTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/DebugTranslation.cpp @@ -97,17 +97,26 @@ return nullptr; } +llvm::MDString *DebugTranslation::getMDStringOrNull(StringAttr stringAttr) { + if (!stringAttr || stringAttr.getValue().empty()) + return nullptr; + return llvm::MDString::get(llvmCtx, stringAttr); +} + llvm::DIBasicType *DebugTranslation::translateImpl(DIBasicTypeAttr attr) { return llvm::DIBasicType::get( - llvmCtx, attr.getTag(), attr.getName(), attr.getSizeInBits(), + llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()), + attr.getSizeInBits(), /*AlignInBits=*/0, attr.getEncoding(), llvm::DINode::FlagZero); } llvm::DICompileUnit *DebugTranslation::translateImpl(DICompileUnitAttr attr) { llvm::DIBuilder builder(llvmModule); return builder.createCompileUnit( - attr.getSourceLanguage(), translate(attr.getFile()), attr.getProducer(), - attr.getIsOptimized(), /*Flags=*/"", /*RV=*/0); + attr.getSourceLanguage(), translate(attr.getFile()), + attr.getProducer() ? attr.getProducer().getValue() : "", + attr.getIsOptimized(), + /*Flags=*/"", /*RV=*/0); } llvm::DICompositeType * @@ -116,9 +125,10 @@ for (auto member : attr.getElements()) elements.push_back(translate(member)); return llvm::DICompositeType::get( - llvmCtx, attr.getTag(), attr.getName(), translate(attr.getFile()), - attr.getLine(), translate(attr.getScope()), translate(attr.getBaseType()), - attr.getSizeInBits(), attr.getAlignInBits(), + llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()), + translate(attr.getFile()), attr.getLine(), translate(attr.getScope()), + translate(attr.getBaseType()), attr.getSizeInBits(), + attr.getAlignInBits(), /*OffsetInBits=*/0, /*Flags=*/static_cast(attr.getFlags()), llvm::MDNode::get(llvmCtx, elements), @@ -126,9 +136,6 @@ } llvm::DIDerivedType *DebugTranslation::translateImpl(DIDerivedTypeAttr attr) { - auto getMDStringOrNull = [&](StringAttr attr) -> llvm::MDString * { - return attr ? llvm::MDString::get(llvmCtx, attr) : nullptr; - }; return llvm::DIDerivedType::get( llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()), /*File=*/nullptr, /*Line=*/0, @@ -138,7 +145,8 @@ } llvm::DIFile *DebugTranslation::translateImpl(DIFileAttr attr) { - return llvm::DIFile::get(llvmCtx, attr.getName(), attr.getDirectory()); + return llvm::DIFile::get(llvmCtx, getMDStringOrNull(attr.getName()), + getMDStringOrNull(attr.getDirectory())); } llvm::DILexicalBlock *DebugTranslation::translateImpl(DILexicalBlockAttr attr) { @@ -161,9 +169,9 @@ llvm::DILocalVariable * DebugTranslation::translateImpl(DILocalVariableAttr attr) { return llvm::DILocalVariable::get( - llvmCtx, translate(attr.getScope()), - llvm::MDString::get(llvmCtx, attr.getName()), translate(attr.getFile()), - attr.getLine(), translate(attr.getType()), attr.getArg(), + llvmCtx, translate(attr.getScope()), getMDStringOrNull(attr.getName()), + translate(attr.getFile()), attr.getLine(), translate(attr.getType()), + attr.getArg(), /*Flags=*/llvm::DINode::FlagZero, attr.getAlignInBits(), /*Annotations=*/nullptr); } @@ -184,12 +192,9 @@ llvm::DISubprogram *DebugTranslation::translateImpl(DISubprogramAttr attr) { bool isDefinition = static_cast(attr.getSubprogramFlags() & LLVM::DISubprogramFlags::Definition); - auto getMDStringOrNull = [&](StringAttr attr) -> llvm::MDString * { - return attr ? llvm::MDString::get(llvmCtx, attr) : nullptr; - }; return getSubprogram( isDefinition, llvmCtx, translate(attr.getScope()), - llvm::MDString::get(llvmCtx, attr.getName()), + getMDStringOrNull(attr.getName()), getMDStringOrNull(attr.getLinkageName()), translate(attr.getFile()), attr.getLine(), translate(attr.getType()), attr.getScopeLine(), /*ContainingType=*/nullptr, /*VirtualIndex=*/0, @@ -200,7 +205,8 @@ llvm::DINamespace *DebugTranslation::translateImpl(DINamespaceAttr attr) { return llvm::DINamespace::get(llvmCtx, translate(attr.getScope()), - attr.getName(), attr.getExportSymbols()); + getMDStringOrNull(attr.getName()), + attr.getExportSymbols()); } llvm::DISubrange *DebugTranslation::translateImpl(DISubrangeAttr attr) { diff --git a/mlir/test/Target/LLVMIR/Import/debug-info.ll b/mlir/test/Target/LLVMIR/Import/debug-info.ll --- a/mlir/test/Target/LLVMIR/Import/debug-info.ll +++ b/mlir/test/Target/LLVMIR/Import/debug-info.ll @@ -190,7 +190,7 @@ ; // ----- ; CHECK-DAG: #[[FILE:.+]] = #llvm.di_file<"debug-info.ll" in "/"> -; CHECK-DAG: #[[CU:.+]] = #llvm.di_compile_unit +; CHECK-DAG: #[[CU:.+]] = #llvm.di_compile_unit ; Verify an empty subroutine types list is supported. ; CHECK-DAG: #[[SP_TYPE:.+]] = #llvm.di_subroutine_type ; CHECK-DAG: #[[SP:.+]] = #llvm.di_subprogram @@ -389,3 +389,24 @@ !8 = distinct !DISubprogram(name: "namespace", scope: !10, file: !2, unit: !1); !9 = !DILocation(line: 1, column: 2, scope: !8) !10 = !DINamespace(name: "std", scope: null) + +; // ----- + +; CHECK-DAG: #[[SUBPROGRAM:.+]] = #llvm.di_subprogram + +define void @noname_variable(ptr %arg) { + call void @llvm.dbg.value(metadata ptr %arg, metadata !7, metadata !DIExpression()), !dbg !9 + ret void +} + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!1} +!llvm.module.flags = !{!0} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DICompileUnit(language: DW_LANG_C, file: !2) +!2 = !DIFile(filename: "debug-info.ll", directory: "/") +!7 = !DILocalVariable(scope: !8) +!8 = distinct !DISubprogram(name: "noname_variable", scope: !2, file: !2, unit: !1); +!9 = !DILocation(line: 1, column: 2, scope: !8) diff --git a/mlir/test/Target/LLVMIR/llvmir-debug.mlir b/mlir/test/Target/LLVMIR/llvmir-debug.mlir --- a/mlir/test/Target/LLVMIR/llvmir-debug.mlir +++ b/mlir/test/Target/LLVMIR/llvmir-debug.mlir @@ -72,6 +72,7 @@ #blockScope = #llvm.di_lexical_block #variable = #llvm.di_local_variable #variableAddr = #llvm.di_local_variable +#noNameVariable = #llvm.di_local_variable #spType1 = #llvm.di_subroutine_type #sp1 = #llvm.di_subprogram< @@ -89,9 +90,11 @@ // CHECK: call void @llvm.dbg.value(metadata i64 %[[ARG]], metadata ![[VAR_LOC:[0-9]+]], metadata !DIExpression()) // CHECK: call void @llvm.dbg.addr(metadata ptr %[[ALLOC]], metadata ![[ADDR_LOC:[0-9]+]], metadata !DIExpression()) // CHECK: call void @llvm.dbg.declare(metadata ptr %[[ALLOC]], metadata ![[ADDR_LOC]], metadata !DIExpression()) + // CHECK: call void @llvm.dbg.value(metadata i64 %[[ARG]], metadata ![[NO_NAME_VAR:[0-9]+]], metadata !DIExpression()) llvm.intr.dbg.value #variable = %arg : i64 llvm.intr.dbg.addr #variableAddr = %alloc : !llvm.ptr llvm.intr.dbg.declare #variableAddr = %alloc : !llvm.ptr + llvm.intr.dbg.value #noNameVariable= %arg : i64 // CHECK: call void @func_no_debug(), !dbg ![[CALLSITE_LOC:[0-9]+]] llvm.call @func_no_debug() : () -> () loc(callsite("mysource.cc":3:4 at "mysource.cc":5:6)) @@ -139,6 +142,7 @@ // CHECK: ![[VAR_SCOPE]] = distinct !DILexicalBlockFile(scope: ![[FUNC_LOC]], file: ![[CU_FILE_LOC]], discriminator: 0) // CHECK: ![[ADDR_LOC]] = !DILocalVariable(name: "alloc", scope: ![[BLOCK_LOC:.*]]) // CHECK: ![[BLOCK_LOC]] = distinct !DILexicalBlock(scope: ![[FUNC_LOC]]) +// CHECK: ![[NO_NAME_VAR]] = !DILocalVariable(scope: ![[BLOCK_LOC]]) // CHECK-DAG: ![[CALLSITE_LOC]] = !DILocation(line: 3, column: 4, // CHECK-DAG: ![[FILE_LOC]] = !DILocation(line: 1, column: 2,