From 3f63889d58c363348832eaf789e340f11d0d0ee8 Mon Sep 17 00:00:00 2001 From: Tobias Gysi Date: Fri, 18 Nov 2022 09:44:26 +0100 Subject: [PATCH] [mlir][llvm] Import additional debug info from LLVMIR. Add a DebugImporter to convert LLVMIR debug metadata into MLIR debug attributes. It is the counterpart to the DebugTranslation class and supports the same attributes. The revision only supports the translation of instruction, function, and module debug information. The import of intrinsics is left to a later revision. Depends on D138206 Reviewed By: rriddle Differential Revision: https://reviews.llvm.org/D138209 --- mlir/lib/Target/LLVMIR/CMakeLists.txt | 2 + mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp | 37 +++-- mlir/lib/Target/LLVMIR/DebugImporter.cpp | 209 ++++++++++++++++++++++++ mlir/lib/Target/LLVMIR/DebugImporter.h | 78 +++++++++ mlir/test/Target/LLVMIR/Import/debug-info.ll | 228 ++++++++++++++++++++++++--- 5 files changed, 514 insertions(+), 40 deletions(-) create mode 100644 mlir/lib/Target/LLVMIR/DebugImporter.cpp create mode 100644 mlir/lib/Target/LLVMIR/DebugImporter.h diff --git a/mlir/lib/Target/LLVMIR/CMakeLists.txt b/mlir/lib/Target/LLVMIR/CMakeLists.txt index 3ee8382..caf3621 100644 --- a/mlir/lib/Target/LLVMIR/CMakeLists.txt +++ b/mlir/lib/Target/LLVMIR/CMakeLists.txt @@ -4,6 +4,7 @@ set(LLVM_OPTIONAL_SOURCES ConvertFromLLVMIR.cpp ConvertToLLVMIR.cpp DebugTranslation.cpp + DebugImporter.cpp ModuleTranslation.cpp TypeToLLVM.cpp TypeFromLLVM.cpp @@ -50,6 +51,7 @@ add_mlir_translation_library(MLIRToLLVMIRTranslationRegistration add_mlir_translation_library(MLIRTargetLLVMIRImport ConvertFromLLVMIR.cpp + DebugImporter.cpp TypeFromLLVM.cpp ADDITIONAL_HEADER_DIRS diff --git a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp index 18cff0c..78b5e22 100644 --- a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp +++ b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "DebugImporter.h" #include "mlir/Target/LLVMIR/Import.h" #include "mlir/Dialect/DLTI/DLTI.h" @@ -42,6 +43,7 @@ using namespace mlir; using namespace mlir::LLVM; +using mlir::LLVM::detail::DebugImporter; #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsFromLLVM.inc" @@ -329,7 +331,7 @@ class Importer { public: Importer(MLIRContext *context, ModuleOp module) : builder(context), context(context), module(module), - typeTranslator(*context) { + typeTranslator(*context), debugImporter(context) { builder.setInsertionPointToStart(module.getBody()); } @@ -369,12 +371,15 @@ public: /// Converts `value` to an integer attribute. Asserts if the conversion fails. IntegerAttr matchIntegerAttr(Value value); - /// Translate the debug location to a FileLineColLoc, if `loc` is non-null. - /// Otherwise, return UnknownLoc. - Location translateLoc(llvm::DILocation *loc); + /// Translates the debug location. + Location translateLoc(llvm::DILocation *loc) { + return debugImporter.translateLoc(loc); + } /// Converts the type from LLVM to MLIR LLVM dialect. - Type convertType(llvm::Type *type); + Type convertType(llvm::Type *type) { + return typeTranslator.translateType(type); + } /// Converts an LLVM intrinsic to an MLIR LLVM dialect operation if an MLIR /// counterpart exists. Otherwise, returns failure. @@ -450,21 +455,11 @@ private: DenseMap globals; /// The stateful type translator (contains named structs). LLVM::TypeFromLLVMIRTranslator typeTranslator; + /// Stateful debug information importer. + DebugImporter debugImporter; }; } // namespace -Location Importer::translateLoc(llvm::DILocation *loc) { - if (!loc) - return UnknownLoc::get(context); - - return FileLineColLoc::get(context, loc->getFilename(), loc->getLine(), - loc->getColumn()); -} - -Type Importer::convertType(llvm::Type *type) { - return typeTranslator.translateType(type); -} - LogicalResult Importer::convertIntrinsic(OpBuilder &odsBuilder, llvm::CallInst *inst) { // Check if the callee is an intrinsic. @@ -1064,6 +1059,9 @@ LogicalResult Importer::processFunction(llvm::Function *func) { UnknownLoc::get(context), func->getName(), functionType, convertLinkageFromLLVM(func->getLinkage()), dsoLocal, cconv); + // Set the function debug information if available. + debugImporter.translate(func, funcOp); + for (const auto &it : llvm::enumerate(functionType.getParams())) { llvm::SmallVector argAttrs; if (auto *type = func->getParamByValType(it.index())) { @@ -1150,8 +1148,9 @@ mlir::translateLLVMIRToModule(std::unique_ptr llvmModule, MLIRContext *context) { context->loadDialect(); context->loadDialect(); - OwningOpRef module(ModuleOp::create( - FileLineColLoc::get(context, "", /*line=*/0, /*column=*/0))); + OwningOpRef module(ModuleOp::create(FileLineColLoc::get( + StringAttr::get(context, llvmModule->getSourceFileName()), /*line=*/0, + /*column=*/0))); DataLayoutSpecInterface dlSpec = translateDataLayout(llvmModule->getDataLayout(), context); diff --git a/mlir/lib/Target/LLVMIR/DebugImporter.cpp b/mlir/lib/Target/LLVMIR/DebugImporter.cpp new file mode 100644 index 0000000..cd1f58f --- /dev/null +++ b/mlir/lib/Target/LLVMIR/DebugImporter.cpp @@ -0,0 +1,209 @@ +//===- DebugImporter.cpp - LLVM to MLIR Debug conversion ------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "DebugImporter.h" +#include "mlir/Dialect/LLVMIR/LLVMAttrs.h" +#include "mlir/IR/Attributes.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/Location.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/Metadata.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace mlir; +using namespace mlir::LLVM; +using namespace mlir::LLVM::detail; + +void DebugImporter::translate(llvm::Function *func, LLVMFuncOp funcOp) { + if (!func->getSubprogram()) + return; + + // Add a fused location to link the subprogram information. + StringAttr name = StringAttr::get(context, func->getSubprogram()->getName()); + funcOp->setLoc(FusedLocWith::get( + {NameLoc::get(name)}, translate(func->getSubprogram()), context)); +} + +//===----------------------------------------------------------------------===// +// Attributes +//===----------------------------------------------------------------------===// + +DIBasicTypeAttr DebugImporter::translateImpl(llvm::DIBasicType *node) { + return DIBasicTypeAttr::get(context, node->getTag(), node->getName(), + node->getSizeInBits(), node->getEncoding()); +} + +DICompileUnitAttr DebugImporter::translateImpl(llvm::DICompileUnit *node) { + Optional emissionKind = + symbolizeDIEmissionKind(node->getEmissionKind()); + return DICompileUnitAttr::get(context, node->getSourceLanguage(), + translate(node->getFile()), + StringAttr::get(context, node->getProducer()), + node->isOptimized(), emissionKind.value()); +} + +DICompositeTypeAttr DebugImporter::translateImpl(llvm::DICompositeType *node) { + Optional flags = symbolizeDIFlags(node->getFlags()); + SmallVector elements; + for (llvm::DINode *element : node->getElements()) { + assert(element && "expected a non-null element type"); + elements.push_back(translate(element)); + } + return DICompositeTypeAttr::get( + context, node->getTag(), StringAttr::get(context, node->getName()), + translate(node->getFile()), node->getLine(), translate(node->getScope()), + translate(node->getBaseType()), flags.value_or(DIFlags::Zero), + node->getSizeInBits(), node->getAlignInBits(), elements); +} + +DIDerivedTypeAttr DebugImporter::translateImpl(llvm::DIDerivedType *node) { + return DIDerivedTypeAttr::get( + context, node->getTag(), + node->getRawName() ? StringAttr::get(context, node->getName()) : nullptr, + translate(node->getBaseType()), node->getSizeInBits(), + node->getAlignInBits(), node->getOffsetInBits()); +} + +DIFileAttr DebugImporter::translateImpl(llvm::DIFile *node) { + return DIFileAttr::get(context, node->getFilename(), node->getDirectory()); +} + +DILexicalBlockAttr DebugImporter::translateImpl(llvm::DILexicalBlock *node) { + return DILexicalBlockAttr::get(context, translate(node->getScope()), + translate(node->getFile()), node->getLine(), + node->getColumn()); +} + +DILexicalBlockFileAttr +DebugImporter::translateImpl(llvm::DILexicalBlockFile *node) { + return DILexicalBlockFileAttr::get(context, translate(node->getScope()), + translate(node->getFile()), + node->getDiscriminator()); +} + +DILocalVariableAttr DebugImporter::translateImpl(llvm::DILocalVariable *node) { + return DILocalVariableAttr::get(context, translate(node->getScope()), + StringAttr::get(context, node->getName()), + translate(node->getFile()), node->getLine(), + node->getArg(), node->getAlignInBits(), + translate(node->getType())); +} + +DIScopeAttr DebugImporter::translateImpl(llvm::DIScope *node) { + return cast(translate(static_cast(node))); +} + +DISubprogramAttr DebugImporter::translateImpl(llvm::DISubprogram *node) { + Optional subprogramFlags = + symbolizeDISubprogramFlags(node->getSubprogram()->getSPFlags()); + return DISubprogramAttr::get( + context, translate(node->getUnit()), translate(node->getScope()), + StringAttr::get(context, node->getName()), + node->getRawLinkageName() + ? StringAttr::get(context, node->getLinkageName()) + : nullptr, + translate(node->getFile()), node->getLine(), node->getScopeLine(), + subprogramFlags.value(), translate(node->getType())); +} + +DISubrangeAttr DebugImporter::translateImpl(llvm::DISubrange *node) { + auto getIntegerAttrOrNull = [&](llvm::DISubrange::BoundType data) { + if (auto *constInt = llvm::dyn_cast_or_null(data)) + return IntegerAttr::get(IntegerType::get(context, 64), + constInt->getSExtValue()); + return IntegerAttr(); + }; + return DISubrangeAttr::get(context, getIntegerAttrOrNull(node->getCount()), + getIntegerAttrOrNull(node->getLowerBound()), + getIntegerAttrOrNull(node->getUpperBound()), + getIntegerAttrOrNull(node->getStride())); +} + +DISubroutineTypeAttr +DebugImporter::translateImpl(llvm::DISubroutineType *node) { + // Separate the result type since it is null for void functions. + DITypeAttr resultType = translate(*node->getTypeArray().begin()); + SmallVector argumentTypes; + for (llvm::DIType *type : llvm::drop_begin(node->getTypeArray())) { + assert(type && "expected a non-null argument type"); + argumentTypes.push_back(translate(type)); + } + return DISubroutineTypeAttr::get(context, node->getCC(), resultType, + argumentTypes); +} + +DITypeAttr DebugImporter::translateImpl(llvm::DIType *node) { + return cast(translate(static_cast(node))); +} + +DINodeAttr DebugImporter::translate(llvm::DINode *node) { + if (!node) + return nullptr; + + // Check for a cached instance. + if (DINodeAttr attr = nodeToAttr.lookup(node)) + return attr; + + // Convert the debug metadata if possible. + auto translateNode = [this](llvm::DINode *node) -> DINodeAttr { + if (auto *casted = dyn_cast(node)) + return translateImpl(casted); + if (auto *casted = dyn_cast(node)) + return translateImpl(casted); + if (auto *casted = dyn_cast(node)) + return translateImpl(casted); + if (auto *casted = dyn_cast(node)) + return translateImpl(casted); + if (auto *casted = dyn_cast(node)) + return translateImpl(casted); + if (auto *casted = dyn_cast(node)) + return translateImpl(casted); + if (auto *casted = dyn_cast(node)) + return translateImpl(casted); + if (auto *casted = dyn_cast(node)) + return translateImpl(casted); + if (auto *casted = dyn_cast(node)) + return translateImpl(casted); + if (auto *casted = dyn_cast(node)) + return translateImpl(casted); + if (auto *casted = dyn_cast(node)) + return translateImpl(casted); + return nullptr; + }; + if (DINodeAttr attr = translateNode(node)) { + nodeToAttr.insert({node, attr}); + return attr; + } + return nullptr; +} + +//===----------------------------------------------------------------------===// +// Locations +//===----------------------------------------------------------------------===// + +Location DebugImporter::translateLoc(llvm::DILocation *loc) { + if (!loc) + return UnknownLoc::get(context); + + // Get the file location of the instruction. + Location result = FileLineColLoc::get(context, loc->getFilename(), + loc->getLine(), loc->getColumn()); + + // Add call site information, if available. + if (llvm::DILocation *inlinedAt = loc->getInlinedAt()) + result = CallSiteLoc::get(result, translateLoc(inlinedAt)); + + // Add scope information. + assert(loc->getScope() && "expected non-null scope"); + result = FusedLocWith::get({result}, translate(loc->getScope()), + context); + return result; +} diff --git a/mlir/lib/Target/LLVMIR/DebugImporter.h b/mlir/lib/Target/LLVMIR/DebugImporter.h new file mode 100644 index 0000000..4be4aa1 --- /dev/null +++ b/mlir/lib/Target/LLVMIR/DebugImporter.h @@ -0,0 +1,78 @@ +//===- DebugImporter.h - LLVM to MLIR Debug conversion -------*- C++ -*----===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the translation between LLVMIR debug information and +// the corresponding MLIR representation. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_LIB_TARGET_LLVMIR_DEBUGIMPORT_H_ +#define MLIR_LIB_TARGET_LLVMIR_DEBUGIMPORT_H_ + +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" +#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/MLIRContext.h" +#include "llvm/IR/DebugInfoMetadata.h" + +namespace mlir { +class Operation; + +namespace LLVM { +class LLVMFuncOp; + +namespace detail { + +class DebugImporter { +public: + DebugImporter(MLIRContext *context) : context(context) {} + + /// Translates the given LLVM debug location to an MLIR location. + Location translateLoc(llvm::DILocation *loc); + + /// Translates the debug information for the given function. + void translate(llvm::Function *func, LLVMFuncOp funcOp); + + /// Translates the given LLVM debug metadata to MLIR. + DINodeAttr translate(llvm::DINode *node); + + /// Infers the metadata type and translates it to MLIR. + template + auto translate(DINodeT *node) { + // Infer the MLIR type from the LLVM metadata type. + using MLIRTypeT = decltype(translateImpl(node)); + return cast_or_null( + translate(static_cast(node))); + } + +private: + /// Translates the given LLVM debug metadata to the corresponding attribute. + DIBasicTypeAttr translateImpl(llvm::DIBasicType *node); + DICompileUnitAttr translateImpl(llvm::DICompileUnit *node); + DICompositeTypeAttr translateImpl(llvm::DICompositeType *node); + DIDerivedTypeAttr translateImpl(llvm::DIDerivedType *node); + DIFileAttr translateImpl(llvm::DIFile *node); + DILexicalBlockAttr translateImpl(llvm::DILexicalBlock *node); + DILexicalBlockFileAttr translateImpl(llvm::DILexicalBlockFile *node); + DILocalVariableAttr translateImpl(llvm::DILocalVariable *node); + DIScopeAttr translateImpl(llvm::DIScope *node); + DISubprogramAttr translateImpl(llvm::DISubprogram *node); + DISubrangeAttr translateImpl(llvm::DISubrange *node); + DISubroutineTypeAttr translateImpl(llvm::DISubroutineType *node); + DITypeAttr translateImpl(llvm::DIType *node); + + /// A mapping between LLVM debug metadata and the corresponding attribute. + DenseMap nodeToAttr; + + MLIRContext *context; +}; + +} // namespace detail +} // namespace LLVM +} // namespace mlir + +#endif // MLIR_LIB_TARGET_LLVMIR_DEBUIMPORTN_H_ diff --git a/mlir/test/Target/LLVMIR/Import/debug-info.ll b/mlir/test/Target/LLVMIR/Import/debug-info.ll index 31f3f821..575ac01 100644 --- a/mlir/test/Target/LLVMIR/Import/debug-info.ll +++ b/mlir/test/Target/LLVMIR/Import/debug-info.ll @@ -17,26 +17,212 @@ next: ; // ----- -; 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: #[[$SP:.+]] = #llvm.di_subprogram["debug-info.ll":1:2]) +; CHECK #[[CALLSITE_LOC]] = loc(fused<#[[$CALLEE]]>[callsite("debug-info.ll":7:4 at fused<#[[$SP]]>["debug-info.ll":2:2])]) + +!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: "/") +!3 = distinct !DISubprogram(name: "instruction_loc", scope: !2, file: !2, line: 42, scopeLine: 42, spFlags: DISPFlagDefinition, unit: !1) +!4 = distinct !DISubprogram(name: "callee", scope: !2, file: !2, line: 43, scopeLine: 42, spFlags: DISPFlagDefinition, unit: !1) +!5 = !DILocation(line: 1, column: 2, scope: !3) +!6 = !DILocation(line: 2, column: 2, scope: !3) +!7 = !DILocation(line: 7, column: 4, scope: !4, inlinedAt: !6) + +; // ----- + +; CHECK: #[[FILE:.+]] = #llvm.di_file<"debug-info.ll" in "/"> +; CHECK: #[[SP:.+]] = #llvm.di_subprogram +; CHECK: #[[$LB1:.+]] = #llvm.di_lexical_block + +; CHECK-LABEL: @lexical_block +define i32 @lexical_block(i32 %arg1) { + ; CHECK llvm.add {{.*}} loc(#[[LOC0:.*]]) + %1 = add i32 %arg1, %arg1, !dbg !6 + + ; CHECK llvm.mul {{.*}} loc(#[[LOC1:.*]]) + %2 = mul i32 %arg1, %arg1, !dbg !7 + + ret i32 %2 +} +; CHECK #[[LOC0]] = loc(fused<#[[$LB0]]>["debug-info.ll":1:2]) +; CHECK #[[LOC1]] = loc(fused<#[[$LB1]]>["debug-info.ll":1:2]) + +!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: "/") +!3 = distinct !DISubprogram(name: "lexical_block", scope: !2, file: !2, line: 42, scopeLine: 42, spFlags: DISPFlagDefinition, unit: !1) +!4 = !DILexicalBlock(scope: !3) +!5 = !DILexicalBlock(scope: !3, file: !2, line: 2, column: 2) +!6 = !DILocation(line: 1, column: 2, scope: !4) +!7 = !DILocation(line: 2, column: 2, scope: !5) + +; // ----- + +; CHECK: #[[FILE:.+]] = #llvm.di_file<"debug-info.ll" in "/"> +; CHECK: #[[SP:.+]] = #llvm.di_subprogram +; CHECK: #[[$LB1:.+]] = #llvm.di_lexical_block_file + +; CHECK-LABEL: @lexical_block_file +define i32 @lexical_block_file(i32 %arg1) { + ; CHECK llvm.add {{.*}} loc(#[[LOC0:.*]]) + %1 = add i32 %arg1, %arg1, !dbg !6 + + ; CHECK llvm.mul {{.*}} loc(#[[LOC1:.*]]) + %2 = mul i32 %arg1, %arg1, !dbg !7 + + ret i32 %2 +} +; CHECK #[[LOC0]] = loc(fused<#[[$LB0]]>["debug-info.ll":1:2])) +; CHECK #[[LOC1]] = loc(fused<#[[$LB1]]>["debug-info.ll":2:2])) + +!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: "/") +!3 = distinct !DISubprogram(name: "lexical_block_file", scope: !2, file: !2, line: 42, scopeLine: 42, spFlags: DISPFlagDefinition, unit: !1) +!4 = !DILexicalBlockFile(scope: !3, discriminator: 0) +!5 = !DILexicalBlockFile(scope: !3, file: !2, discriminator: 0) +!6 = !DILocation(line: 1, column: 2, scope: !4) +!7 = !DILocation(line: 2, column: 2, scope: !5) + +; // ----- + +; CHECK: #[[INT1:.+]] = #llvm.di_basic_type +; CHECK: #[[INT2:.+]] = #llvm.di_basic_type +; CHECK: #llvm.di_subroutine_type + +define void @basic_type() !dbg !3 { + ret void +} + +!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: "/") +!3 = distinct !DISubprogram(name: "basic_type", scope: !2, file: !2, line: 42, scopeLine: 42, spFlags: DISPFlagDefinition, unit: !1, type: !4) +!4 = !DISubroutineType(types: !5) +!5 = !{null, !6, !7} +!6 = !DIBasicType(name: "int1") +!7 = !DIBasicType(name: "int2", encoding: DW_ATE_signed, size: 32) + +; // ----- + +; CHECK: #[[INT:.+]] = #llvm.di_basic_type +; CHECK: #[[PTR1:.+]] = #llvm.di_derived_type +; CHECK: #[[PTR2:.+]] = #llvm.di_derived_type +; CHECK: #llvm.di_subroutine_type + +define void @derived_type() !dbg !3 { + ret void } -; 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) +!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: "/") +!3 = distinct !DISubprogram(name: "derived_type", scope: !2, file: !2, line: 42, scopeLine: 42, spFlags: DISPFlagDefinition, unit: !1, type: !4) +!4 = !DISubroutineType(types: !5) +!5 = !{null, !7, !8} +!6 = !DIBasicType(name: "int") +!7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6) +!8 = !DIDerivedType(name: "mypointer", tag: DW_TAG_pointer_type, baseType: !6, size: 64, align: 32, offset: 4) + +; // ----- + +; CHECK: #[[INT:.+]] = #llvm.di_basic_type +; CHECK: #[[FILE:.+]] = #llvm.di_file<"debug-info.ll" in "/"> +; CHECK: #[[COMP1:.+]] = #llvm.di_composite_type +; CHECK: #[[COMP2:.+]] = #llvm.di_composite_type<{{.*}}, file = #[[FILE]], line = 0, scope = #[[FILE]], baseType = #[[INT]], sizeInBits = 0, alignInBits = 0> +; CHECK: #[[COMP3:.+]] = #llvm.di_composite_type<{{.*}}, flags = Vector, {{.*}}, elements = #llvm.di_subrange> +; CHECK: #[[COMP4:.+]] = #llvm.di_composite_type<{{.*}}, elements = #llvm.di_subrange> +; CHECK: #llvm.di_subroutine_type + +define void @composite_type() !dbg !3 { + ret void +} + +!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: "/") +!3 = distinct !DISubprogram(name: "composite_type", scope: !2, file: !2, line: 42, scopeLine: 42, spFlags: DISPFlagDefinition, unit: !1, type: !4) +!4 = !DISubroutineType(types: !5) +!5 = !{null, !7, !8, !9, !10} +!6 = !DIBasicType(name: "int") +!7 = !DICompositeType(tag: DW_TAG_array_type, name: "array1", line: 10, size: 128, align: 32) +!8 = !DICompositeType(tag: DW_TAG_array_type, name: "array2", file: !2, scope: !2, baseType: !6) +!9 = !DICompositeType(tag: DW_TAG_array_type, name: "array3", flags: DIFlagVector, elements: !13) +!10 = !DICompositeType(tag: DW_TAG_array_type, name: "array4", flags: DIFlagVector, elements: !14) +!11 = !DISubrange(count: 4) +!12 = !DISubrange(lowerBound: 0, upperBound: 4, stride: 1) +!13 = !{!11} +!14 = !{!12} + +; // ----- + +; CHECK: #[[INT:.+]] = #llvm.di_basic_type +; CHECK: #[[FILE:.+]] = #llvm.di_file<"debug-info.ll" in "/"> +; CHECK: #[[CU:.+]] = #llvm.di_compile_unit +; CHECK: #[[SP_TYPE:.+]] = #llvm.di_subroutine_type +; CHECK: #[[SP:.+]] = #llvm.di_subprogram + +define void @subprogram() !dbg !3 { + ret void +} + +!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: "/") +!3 = distinct !DISubprogram(name: "subprogram", linkageName: "subprogram", scope: !2, file: !2, line: 42, scopeLine: 42, spFlags: DISPFlagDefinition, unit: !1, type: !4) +!4 = !DISubroutineType(cc: DW_CC_normal, types: !5) +!5 = !{!6, !6} +!6 = !DIBasicType(name: "int") + +; // ----- + +; CHECK: #[[$SP:.+]] = #llvm.di_subprogram + +; CHECK-LABEL: @func_loc +define void @func_loc() !dbg !3 { + ret void +} +; CHECK: loc(fused<#[[$SP]]>["func_loc"]) + +!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: "/") +!3 = distinct !DISubprogram(name: "func_loc", scope: !2, file: !2, line: 42, scopeLine: 42, spFlags: DISPFlagDefinition, unit: !1) + +; // ----- + +; Verify the module location is set to the source filename. +; CHECK: loc("debug-info.ll":0:0) +source_filename = "debug-info.ll" -- 2.7.4