From 99bc9bdea6d117f788d67d199f00aac6f7685386 Mon Sep 17 00:00:00 2001 From: Sourabh Singh Tomar Date: Fri, 8 May 2020 11:31:41 +0530 Subject: [PATCH] [DebugInfo] Fortran module DebugInfo support in LLVM This patch extends DIModule Debug metadata in LLVM to support Fortran modules. DIModule is extended to contain File and Line fields, these fields will be used by Flang FE to create debug information necessary for representing Fortran modules at IR level. Furthermore DW_TAG_module is also extended to contain these fields. If these fields are missing, debuggers like GDB won't be able to show Fortran modules information correctly. Reviewed By: aprantl Differential Revision: https://reviews.llvm.org/D79484 --- include/llvm/IR/DIBuilder.h | 9 ++- include/llvm/IR/DebugInfoMetadata.h | 72 ++++++++++++--------- lib/AsmParser/LLParser.cpp | 15 +++-- lib/Bitcode/Reader/MetadataLoader.cpp | 14 ++-- lib/Bitcode/Writer/BitcodeWriter.cpp | 1 + lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 5 ++ lib/IR/AsmWriter.cpp | 2 + lib/IR/DIBuilder.cpp | 8 +-- lib/IR/DebugInfoMetadata.cpp | 18 +++--- lib/IR/LLVMContextImpl.h | 19 ++++-- test/Assembler/dimodule.ll | 4 +- test/Bitcode/DIModule-clang-module.ll | 22 +++++++ test/Bitcode/DIModule-clang-module.ll.bc | Bin 0 -> 1580 bytes test/Bitcode/DIModule-fortran-module.ll | 34 ++++++++++ test/Bitcode/DIModule-fortran-module.ll.bc | Bin 0 -> 1948 bytes test/DebugInfo/X86/Fortran-DIModule.ll | 44 +++++++++++++ unittests/IR/MetadataTest.cpp | 35 ++++++---- 17 files changed, 223 insertions(+), 79 deletions(-) create mode 100644 test/Bitcode/DIModule-clang-module.ll create mode 100644 test/Bitcode/DIModule-clang-module.ll.bc create mode 100644 test/Bitcode/DIModule-fortran-module.ll create mode 100644 test/Bitcode/DIModule-fortran-module.ll.bc create mode 100644 test/DebugInfo/X86/Fortran-DIModule.ll diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index 88851219761..d63ca34c573 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -742,9 +742,14 @@ namespace llvm { /// definitions as they would appear on a command line. /// \param IncludePath The path to the module map file. /// \param APINotesFile The path to an API notes file for this module. + /// \param File Source file of the module declaration. Used for + /// Fortran modules. + /// \param LineNo Source line number of the module declaration. + /// Used for Fortran modules. DIModule *createModule(DIScope *Scope, StringRef Name, - StringRef ConfigurationMacros, - StringRef IncludePath, StringRef APINotesFile = {}); + StringRef ConfigurationMacros, StringRef IncludePath, + StringRef APINotesFile = {}, DIFile *File = nullptr, + unsigned LineNo = 0); /// This creates a descriptor for a lexical block with a new file /// attached. This merely extends the existing diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index 718ecea5afe..26d6e12f0eb 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -2097,64 +2097,72 @@ public: } }; -/// A (clang) module that has been imported by the compile unit. -/// +/// Represents a module in the programming language, for example, a Clang +/// module, or a Fortran module. class DIModule : public DIScope { friend class LLVMContextImpl; friend class MDNode; + unsigned LineNo; - DIModule(LLVMContext &Context, StorageType Storage, ArrayRef Ops) - : DIScope(Context, DIModuleKind, Storage, dwarf::DW_TAG_module, Ops) {} + DIModule(LLVMContext &Context, StorageType Storage, unsigned LineNo, + ArrayRef Ops) + : DIScope(Context, DIModuleKind, Storage, dwarf::DW_TAG_module, Ops), + LineNo(LineNo) {} ~DIModule() = default; - static DIModule *getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, - StringRef ConfigurationMacros, StringRef IncludePath, - StringRef APINotesFile, StorageType Storage, + static DIModule *getImpl(LLVMContext &Context, DIFile *File, DIScope *Scope, + StringRef Name, StringRef ConfigurationMacros, + StringRef IncludePath, StringRef APINotesFile, + unsigned LineNo, StorageType Storage, bool ShouldCreate = true) { - return getImpl(Context, Scope, getCanonicalMDString(Context, Name), + return getImpl(Context, File, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, ConfigurationMacros), getCanonicalMDString(Context, IncludePath), - getCanonicalMDString(Context, APINotesFile), - Storage, ShouldCreate); + getCanonicalMDString(Context, APINotesFile), LineNo, Storage, + ShouldCreate); } - static DIModule *getImpl(LLVMContext &Context, Metadata *Scope, - MDString *Name, MDString *ConfigurationMacros, - MDString *IncludePath, MDString *APINotesFile, + static DIModule *getImpl(LLVMContext &Context, Metadata *File, + Metadata *Scope, MDString *Name, + MDString *ConfigurationMacros, MDString *IncludePath, + MDString *APINotesFile, unsigned LineNo, StorageType Storage, bool ShouldCreate = true); TempDIModule cloneImpl() const { - return getTemporary(getContext(), getScope(), getName(), + return getTemporary(getContext(), getFile(), getScope(), getName(), getConfigurationMacros(), getIncludePath(), - getAPINotesFile()); + getAPINotesFile(), getLineNo()); } public: DEFINE_MDNODE_GET(DIModule, - (DIScope * Scope, StringRef Name, + (DIFile * File, DIScope *Scope, StringRef Name, StringRef ConfigurationMacros, StringRef IncludePath, - StringRef APINotesFile), - (Scope, Name, ConfigurationMacros, IncludePath, - APINotesFile)) + StringRef APINotesFile, unsigned LineNo), + (File, Scope, Name, ConfigurationMacros, IncludePath, + APINotesFile, LineNo)) DEFINE_MDNODE_GET(DIModule, - (Metadata * Scope, MDString *Name, + (Metadata * File, Metadata *Scope, MDString *Name, MDString *ConfigurationMacros, MDString *IncludePath, - MDString *APINotesFile), - (Scope, Name, ConfigurationMacros, IncludePath, - APINotesFile)) + MDString *APINotesFile, unsigned LineNo), + (File, Scope, Name, ConfigurationMacros, IncludePath, + APINotesFile, LineNo)) TempDIModule clone() const { return cloneImpl(); } DIScope *getScope() const { return cast_or_null(getRawScope()); } - StringRef getName() const { return getStringOperand(1); } - StringRef getConfigurationMacros() const { return getStringOperand(2); } - StringRef getIncludePath() const { return getStringOperand(3); } - StringRef getAPINotesFile() const { return getStringOperand(4); } + StringRef getName() const { return getStringOperand(2); } + StringRef getConfigurationMacros() const { return getStringOperand(3); } + StringRef getIncludePath() const { return getStringOperand(4); } + StringRef getAPINotesFile() const { return getStringOperand(5); } + unsigned getLineNo() const { return LineNo; } - Metadata *getRawScope() const { return getOperand(0); } - MDString *getRawName() const { return getOperandAs(1); } - MDString *getRawConfigurationMacros() const { return getOperandAs(2); } - MDString *getRawIncludePath() const { return getOperandAs(3); } - MDString *getRawAPINotesFile() const { return getOperandAs(4); } + Metadata *getRawScope() const { return getOperand(1); } + MDString *getRawName() const { return getOperandAs(2); } + MDString *getRawConfigurationMacros() const { + return getOperandAs(3); + } + MDString *getRawIncludePath() const { return getOperandAs(4); } + MDString *getRawAPINotesFile() const { return getOperandAs(5); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == DIModuleKind; diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 0d9751939ab..8c9c53cbcca 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -4880,21 +4880,24 @@ bool LLParser::ParseDIMacroFile(MDNode *&Result, bool IsDistinct) { } /// ParseDIModule: -/// ::= !DIModule(scope: !0, name: "SomeModule", configMacros: "-DNDEBUG", -/// includePath: "/usr/include", apinotes: "module.apinotes") +/// ::= !DIModule(scope: !0, name: "SomeModule", configMacros: +/// "-DNDEBUG", includePath: "/usr/include", apinotes: "module.apinotes", +/// file: !1, line: 4) bool LLParser::ParseDIModule(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ REQUIRED(scope, MDField, ); \ REQUIRED(name, MDStringField, ); \ OPTIONAL(configMacros, MDStringField, ); \ OPTIONAL(includePath, MDStringField, ); \ - OPTIONAL(apinotes, MDStringField, ); + OPTIONAL(apinotes, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS - Result = - GET_OR_DISTINCT(DIModule, (Context, scope.Val, name.Val, configMacros.Val, - includePath.Val, apinotes.Val)); + Result = GET_OR_DISTINCT(DIModule, (Context, file.Val, scope.Val, name.Val, + configMacros.Val, includePath.Val, + apinotes.Val, line.Val)); return false; } diff --git a/lib/Bitcode/Reader/MetadataLoader.cpp b/lib/Bitcode/Reader/MetadataLoader.cpp index 735d802e822..33776bd1be6 100644 --- a/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1428,15 +1428,19 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( } case bitc::METADATA_MODULE: { - if (Record.size() < 5 || Record.size() > 7) + if (Record.size() < 5 || Record.size() > 8) return error("Invalid record"); + unsigned Offset = Record.size() >= 7 ? 2 : 1; IsDistinct = Record[0]; MetadataList.assignValue( - GET_OR_DISTINCT(DIModule, - (Context, getMDOrNull(Record[1]), - getMDString(Record[2]), getMDString(Record[3]), - getMDString(Record[4]), getMDString(Record[5]))), + GET_OR_DISTINCT( + DIModule, + (Context, Record.size() >= 7 ? getMDOrNull(Record[1]) : nullptr, + getMDOrNull(Record[0 + Offset]), getMDString(Record[1 + Offset]), + getMDString(Record[2 + Offset]), getMDString(Record[3 + Offset]), + getMDString(Record[4 + Offset]), + Record.size() <= 7 ? 0 : Record[7])), NextMetadataNo); NextMetadataNo++; break; diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 3c8e4b2e3ea..c70c5ac543b 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1809,6 +1809,7 @@ void ModuleBitcodeWriter::writeDIModule(const DIModule *N, Record.push_back(N->isDistinct()); for (auto &I : N->operands()) Record.push_back(VE.getMetadataOrNullID(I)); + Record.push_back(N->getLineNo()); Stream.EmitRecord(bitc::METADATA_MODULE, Record, Abbrev); Record.clear(); diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index ecf4a78f3be..ba20e08aae2 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1128,6 +1128,11 @@ DIE *DwarfUnit::getOrCreateModule(const DIModule *M) { addString(MDie, dwarf::DW_AT_LLVM_include_path, M->getIncludePath()); if (!M->getAPINotesFile().empty()) addString(MDie, dwarf::DW_AT_LLVM_apinotes, M->getAPINotesFile()); + if (M->getFile()) + addUInt(MDie, dwarf::DW_AT_decl_file, None, + getOrCreateSourceID(M->getFile())); + if (M->getLineNo()) + addUInt(MDie, dwarf::DW_AT_decl_line, None, M->getLineNo()); return &MDie; } diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index 1afc5c1fd92..83874e47a01 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -2103,6 +2103,8 @@ static void writeDIModule(raw_ostream &Out, const DIModule *N, Printer.printString("configMacros", N->getConfigurationMacros()); Printer.printString("includePath", N->getIncludePath()); Printer.printString("apinotes", N->getAPINotesFile()); + Printer.printMetadata("file", N->getRawFile()); + Printer.printInt("line", N->getLineNo()); Out << ")"; } diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp index 6ed621c407e..95841be5347 100644 --- a/lib/IR/DIBuilder.cpp +++ b/lib/IR/DIBuilder.cpp @@ -832,10 +832,10 @@ DINamespace *DIBuilder::createNameSpace(DIScope *Scope, StringRef Name, DIModule *DIBuilder::createModule(DIScope *Scope, StringRef Name, StringRef ConfigurationMacros, - StringRef IncludePath, - StringRef APINotesFile) { - return DIModule::get(VMContext, getNonCompileUnitScope(Scope), Name, - ConfigurationMacros, IncludePath, APINotesFile); + StringRef IncludePath, StringRef APINotesFile, + DIFile *File, unsigned LineNo) { + return DIModule::get(VMContext, File, getNonCompileUnitScope(Scope), Name, + ConfigurationMacros, IncludePath, APINotesFile, LineNo); } DILexicalBlockFile *DIBuilder::createLexicalBlockFile(DIScope *Scope, diff --git a/lib/IR/DebugInfoMetadata.cpp b/lib/IR/DebugInfoMetadata.cpp index db92c126ad7..c176d27a52a 100644 --- a/lib/IR/DebugInfoMetadata.cpp +++ b/lib/IR/DebugInfoMetadata.cpp @@ -732,16 +732,18 @@ DICommonBlock *DICommonBlock::getImpl(LLVMContext &Context, Metadata *Scope, DEFINE_GETIMPL_STORE(DICommonBlock, (LineNo), Ops); } -DIModule *DIModule::getImpl(LLVMContext &Context, Metadata *Scope, - MDString *Name, MDString *ConfigurationMacros, +DIModule *DIModule::getImpl(LLVMContext &Context, Metadata *File, + Metadata *Scope, MDString *Name, + MDString *ConfigurationMacros, MDString *IncludePath, MDString *APINotesFile, - StorageType Storage, bool ShouldCreate) { + unsigned LineNo, StorageType Storage, + bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); - DEFINE_GETIMPL_LOOKUP( - DIModule, (Scope, Name, ConfigurationMacros, IncludePath, APINotesFile)); - Metadata *Ops[] = {Scope, Name, ConfigurationMacros, IncludePath, - APINotesFile}; - DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DIModule, Ops); + DEFINE_GETIMPL_LOOKUP(DIModule, (File, Scope, Name, ConfigurationMacros, + IncludePath, APINotesFile, LineNo)); + Metadata *Ops[] = {File, Scope, Name, ConfigurationMacros, + IncludePath, APINotesFile}; + DEFINE_GETIMPL_STORE(DIModule, (LineNo), Ops); } DITemplateTypeParameter * diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index 705ffdc5872..543f2e964e7 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -816,27 +816,32 @@ template <> struct MDNodeKeyImpl { }; template <> struct MDNodeKeyImpl { + Metadata *File; Metadata *Scope; MDString *Name; MDString *ConfigurationMacros; MDString *IncludePath; MDString *APINotesFile; + unsigned LineNo; - MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *ConfigurationMacros, - MDString *IncludePath, MDString *APINotesFile) - : Scope(Scope), Name(Name), ConfigurationMacros(ConfigurationMacros), - IncludePath(IncludePath), APINotesFile(APINotesFile) {} + MDNodeKeyImpl(Metadata *File, Metadata *Scope, MDString *Name, + MDString *ConfigurationMacros, MDString *IncludePath, + MDString *APINotesFile, unsigned LineNo) + : File(File), Scope(Scope), Name(Name), + ConfigurationMacros(ConfigurationMacros), IncludePath(IncludePath), + APINotesFile(APINotesFile), LineNo(LineNo) {} MDNodeKeyImpl(const DIModule *N) - : Scope(N->getRawScope()), Name(N->getRawName()), + : File(N->getRawFile()), Scope(N->getRawScope()), Name(N->getRawName()), ConfigurationMacros(N->getRawConfigurationMacros()), IncludePath(N->getRawIncludePath()), - APINotesFile(N->getRawAPINotesFile()) {} + APINotesFile(N->getRawAPINotesFile()), LineNo(N->getLineNo()) {} bool isKeyOf(const DIModule *RHS) const { return Scope == RHS->getRawScope() && Name == RHS->getRawName() && ConfigurationMacros == RHS->getRawConfigurationMacros() && IncludePath == RHS->getRawIncludePath() && - APINotesFile == RHS->getRawAPINotesFile(); + APINotesFile == RHS->getRawAPINotesFile() && + File == RHS->getRawFile() && LineNo == RHS->getLineNo(); } unsigned getHashValue() const { diff --git a/test/Assembler/dimodule.ll b/test/Assembler/dimodule.ll index c3802ea1265..39d1d32ceeb 100644 --- a/test/Assembler/dimodule.ll +++ b/test/Assembler/dimodule.ll @@ -14,5 +14,5 @@ !3 = !DIModule(scope: !0, name: "Module", configMacros: "") -; CHECK: !3 = !DIModule(scope: !0, name: "Module", configMacros: "-DNDEBUG", includePath: "/usr/include", apinotes: "/tmp/m.apinotes") -!4 = !DIModule(scope: !0, name: "Module", configMacros: "-DNDEBUG", includePath: "/usr/include", apinotes: "/tmp/m.apinotes") +; CHECK: !3 = !DIModule(scope: !0, name: "Module", configMacros: "-DNDEBUG", includePath: "/usr/include", apinotes: "/tmp/m.apinotes", file: !0, line: 1) +!4 = !DIModule(scope: !0, name: "Module", configMacros: "-DNDEBUG", includePath: "/usr/include", apinotes: "/tmp/m.apinotes", file: !0, line: 1) diff --git a/test/Bitcode/DIModule-clang-module.ll b/test/Bitcode/DIModule-clang-module.ll new file mode 100644 index 00000000000..d83a0889718 --- /dev/null +++ b/test/Bitcode/DIModule-clang-module.ll @@ -0,0 +1,22 @@ +; RUN: llvm-dis -o - %s.bc | FileCheck %s + +; CHECK: DIModule(scope: null, name: "DebugModule", configMacros: "-DMODULES=0", includePath: "/", apinotes: "m.apinotes") + +; ModuleID = 'DIModule-clang-module.ll' + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux" + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!6, !7} +!llvm.ident = !{!8} + +!0 = distinct !DICompileUnit(language: DW_LANG_ObjC_plus_plus, file: !1, producer: "clang version 11.0.0", isOptimized: false, runtimeVersion: 2, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !3) +!1 = !DIFile(filename: "/test.cpp", directory: "/") +!2 = !{} +!3 = !{!4} +!4 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !0, entity: !5, file: !1, line: 5) +!5 = !DIModule(scope: null, name: "DebugModule", configMacros: "-DMODULES=0", includePath: "/", apinotes: "m.apinotes") +!6 = !{i32 2, !"Dwarf Version", i32 4} +!7 = !{i32 2, !"Debug Info Version", i32 3} +!8 = !{!"clang version 11.0.0"} diff --git a/test/Bitcode/DIModule-clang-module.ll.bc b/test/Bitcode/DIModule-clang-module.ll.bc new file mode 100644 index 0000000000000000000000000000000000000000..dc3647fb52552d7749fa546c5cb478ab0f6326e5 GIT binary patch literal 1580 zcmZ8hZ%k8H6u+g=`+)lTRCIK-&3l5TaRXipLQC5Pc!iY=V~uWMna;M*Dig}1Ev0~2 zT3YjJY?i|K&}1&7nIE?Kr79m>W(-i~D(MUo6C>nw3cY)Q1Rx(tbPXdr&gbr?E{70X4aK8HyIMn$ z!jQ3*z=Q&Kt_AE?o|_cvUgYVjZT9;hR(|uCiVG`@k;`*B`{>-mgA- zTKoOoiXRrbF6_u@`Vtl4T0HtAyScdFa`GKX(e_dW$(%j2nmr z-rmaKTg&*LllUerw58&*wYV&u<%?F?EG3%>$Y-sh2T?|wVzjX=zme38F`BSYHPqi?ov>fHkZ9h#KQIapf7f`^?6jnS3vQJV%92q zLdln=O}=?!jo_GwvktRT@X?vt`k5%lMiZe?c=Vk0|*@T$T}J zBeyo+f0)#uW+jr93rt;_sS7i8DC;@q9WX!w(1br%A8fJFovbn0;&k-9-a)aHVgh=Y$SuVJ z^w=Kb&j92Q8hqIZ2y_O7d+JFrDW3EP1i(lYKa+!LecoJ}sIL;=iKpqZl$xPaCd;tP z+J614o7$~&ORtpdZ&TZNwR5QSO8Z-GRePcCi;|}B<>Lzrn~zS+r)C$QH0K}SpZ^xk z82=X)7PyoMyKu0LjWGrU!33k7OAc?yZpU{#Y2Zg|gOYD!VsG`T1%GTtP?N0jfRj8n z-;&t)QDOU@%P#g@$3JRw?W@9Xhwum10N&e*K50N?LU4J`6@vw z@^y>f-R|k>P7kT3Yt-6ytF~I(-qF!v*E(wL)hcVXO>5U2s?u7uwRDZ@ki%~CX=+Z@ jRG0TT&pLbho#kDf&OV>9 + +@_dummy_0_ = common global %struct_dummy_0_ zeroinitializer, align 64, !dbg !0 + +; Function Attrs: noinline +define float @dummy_() #0 { +.L.entry: + ret float undef +} + +attributes #0 = { noinline "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" } + +!llvm.module.flags = !{!8, !9} +!llvm.dbg.cu = !{!4} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "foo", scope: !2, file: !3, type: !7, isLocal: false, isDefinition: true) +!2 = !DIModule(scope: !4, name: "dummy", file: !3, line: 2) +!3 = !DIFile(filename: "module.f90", directory: "/fortran") +!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5) +!5 = !{} +!6 = !{!0} +!7 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed) +!8 = !{i32 2, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} diff --git a/test/Bitcode/DIModule-fortran-module.ll.bc b/test/Bitcode/DIModule-fortran-module.ll.bc new file mode 100644 index 0000000000000000000000000000000000000000..4884e9a2d06c54daa701ab03a894242c7798f765 GIT binary patch literal 1948 zcmXw4VN4rG7M{h%V}iS02u!~LggiT zR01)_0C>7?rY$EwrJz{rWg@0}yi{4ElfTgyp`Iyezg*rPqu45ovikWWY;Xs-G}Cku+YI>z$z&b1?5E8X*cSdqP=8_rESbdg5vf z)JAMJSykB;Pn5@EU6f&5?yAfSh;0q}{1&wp!WCojiqEjhRfNn~hGGHq-Anc|Loq}(|GNGdv0nCMr%(h=@ zOGnMuaIgmlL*jW}G<(DVFNQOs*@A=D#7F+&CP$XZFleL}c+98qIE}*$7M2yeG!9b5 zcF}ndAf)l66Nf!Gu&nq7bg?_)Awvj}7a@3rDIcS8D7_b<^cDR% z*Gz@8E_Qq9$G?79_~55^dI#Tr`M*8nAohjy(Q-^SD=Lxh8T;kL;Zh&ag#ElSuALLRfHqXSz_5ldjwB~ z@OWxWwT0B*QRH5PG^yHk3-j7Lvl<^$S`3TU=4Fl?=SavL`A{OjkXOxU&;^8;jH0C9mR(BxlWW)>Kj7%v!E+mblDzCEEla{rRHpbD3=}tNPE7$oGf> z9}S$tA=vk7F_0E(?wnRXKidlPKCS-AP5LQvgCU{&!@A;|b#l{9?lW9rRj=Ke)$9_*%)OnTf0?zwX3b@rR=AUS z?qr-h2~{t1PoXIqAr3et=v*`xSJjjWtc$LjPRz`F+L5LV{dObU{#H`|w>Z6l-n>e` zY}6ps5%dZ^`VRxb_|T}oW1w$hkUr)2jUIYNM*Am*2O51=rpY%d1O%_2?zA#==djm5 zNH@^N#ul1ojI9k!O9NxZou&Q@p;ANp&inXX+PNH=&ZFJnA}LeOe*QxJ>fTB1DPvO#(%jPlzN@qVTv8 zTbW8HR#tXadso+T->xk6=2sT(Y;{)r=6A=<=8w$B+3Tjaum7{V#Fz6RREFMzb5;Rs zQhr1*0Dp0~hfi@1py3>6UCv(I(%hPTWV=l|UR!$Y0WXdrbIgR*KTqT zra+%U`qG)kdHdC + +@_dummy_0_ = common global %struct_dummy_0_ zeroinitializer, align 64, !dbg !0 + +; Function Attrs: noinline +define float @dummy_() #0 { +.L.entry: + ret float undef +} + +attributes #0 = { noinline "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" } + +!llvm.module.flags = !{!8, !9} +!llvm.dbg.cu = !{!3} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "foo", scope: !2, file: !4, type: !7, isLocal: false, isDefinition: true) +!2 = !DIModule(scope: !3, name: "dummy", file: !4, line: 2) +!3 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !4, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5) +!4 = !DIFile(filename: "module.f90", directory: "/fortran") +!5 = !{} +!6 = !{!0} +!7 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed) +!8 = !{i32 2, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} diff --git a/unittests/IR/MetadataTest.cpp b/unittests/IR/MetadataTest.cpp index b60bcac5501..39cd0edca6f 100644 --- a/unittests/IR/MetadataTest.cpp +++ b/unittests/IR/MetadataTest.cpp @@ -2062,32 +2062,41 @@ TEST_F(DINamespaceTest, get) { typedef MetadataTest DIModuleTest; TEST_F(DIModuleTest, get) { + DIFile *File = getFile(); DIScope *Scope = getFile(); StringRef Name = "module"; StringRef ConfigMacro = "-DNDEBUG"; StringRef Includes = "-I."; StringRef APINotes = "/tmp/m.apinotes"; + unsigned LineNo = 4; - auto *N = DIModule::get(Context, Scope, Name, ConfigMacro, Includes, APINotes); + auto *N = DIModule::get(Context, File, Scope, Name, ConfigMacro, Includes, + APINotes, LineNo); EXPECT_EQ(dwarf::DW_TAG_module, N->getTag()); + EXPECT_EQ(File, N->getFile()); EXPECT_EQ(Scope, N->getScope()); EXPECT_EQ(Name, N->getName()); EXPECT_EQ(ConfigMacro, N->getConfigurationMacros()); EXPECT_EQ(Includes, N->getIncludePath()); EXPECT_EQ(APINotes, N->getAPINotesFile()); - EXPECT_EQ( - N, DIModule::get(Context, Scope, Name, ConfigMacro, Includes, APINotes)); - EXPECT_NE(N, DIModule::get(Context, getFile(), Name, ConfigMacro, Includes, - APINotes)); - EXPECT_NE(N, DIModule::get(Context, Scope, "other", ConfigMacro, Includes, - APINotes)); - EXPECT_NE(N, - DIModule::get(Context, Scope, Name, "other", Includes, APINotes)); - EXPECT_NE( - N, DIModule::get(Context, Scope, Name, ConfigMacro, "other", APINotes)); - EXPECT_NE( - N, DIModule::get(Context, Scope, Name, ConfigMacro, Includes, "other")); + EXPECT_EQ(LineNo, N->getLineNo()); + EXPECT_EQ(N, DIModule::get(Context, File, Scope, Name, ConfigMacro, Includes, + APINotes, LineNo)); + EXPECT_NE(N, DIModule::get(Context, getFile(), getFile(), Name, ConfigMacro, + Includes, APINotes, LineNo)); + EXPECT_NE(N, DIModule::get(Context, File, Scope, "other", ConfigMacro, + Includes, APINotes, LineNo)); + EXPECT_NE(N, DIModule::get(Context, File, Scope, Name, "other", Includes, + APINotes, LineNo)); + EXPECT_NE(N, DIModule::get(Context, File, Scope, Name, ConfigMacro, "other", + APINotes, LineNo)); + EXPECT_NE(N, DIModule::get(Context, File, Scope, Name, ConfigMacro, Includes, + "other", LineNo)); + EXPECT_NE(N, DIModule::get(Context, getFile(), Scope, Name, ConfigMacro, + Includes, APINotes, LineNo)); + EXPECT_NE(N, DIModule::get(Context, File, Scope, Name, ConfigMacro, Includes, + APINotes, 5)); TempDIModule Temp = N->clone(); EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));