[llvm] e59744f - [DebugInfo] Fortran module DebugInfo support in LLVM

Sourabh Singh Tomar via llvm-commits llvm-commits at lists.llvm.org
Wed May 13 00:37:06 PDT 2020


Author: Sourabh Singh Tomar
Date: 2020-05-13T12:52:30+05:30
New Revision: e59744fd9b4298c0527163748510a482a942eb54

URL: https://github.com/llvm/llvm-project/commit/e59744fd9b4298c0527163748510a482a942eb54
DIFF: https://github.com/llvm/llvm-project/commit/e59744fd9b4298c0527163748510a482a942eb54.diff

LOG: [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

Added: 
    llvm/test/Bitcode/DIModule-clang-module.ll
    llvm/test/Bitcode/DIModule-clang-module.ll.bc
    llvm/test/Bitcode/DIModule-fortran-module.ll
    llvm/test/Bitcode/DIModule-fortran-module.ll.bc
    llvm/test/DebugInfo/X86/Fortran-DIModule.ll

Modified: 
    llvm/include/llvm/IR/DIBuilder.h
    llvm/include/llvm/IR/DebugInfoMetadata.h
    llvm/lib/AsmParser/LLParser.cpp
    llvm/lib/Bitcode/Reader/MetadataLoader.cpp
    llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
    llvm/lib/IR/AsmWriter.cpp
    llvm/lib/IR/DIBuilder.cpp
    llvm/lib/IR/DebugInfoMetadata.cpp
    llvm/lib/IR/LLVMContextImpl.h
    llvm/test/Assembler/dimodule.ll
    llvm/unittests/IR/MetadataTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index 888512197617..d63ca34c573b 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/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/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 718ecea5afeb..26d6e12f0eb4 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -2097,64 +2097,72 @@ class DINamespace : public DIScope {
   }
 };
 
-/// 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<Metadata *> Ops)
-      : DIScope(Context, DIModuleKind, Storage, dwarf::DW_TAG_module, Ops) {}
+  DIModule(LLVMContext &Context, StorageType Storage, unsigned LineNo,
+           ArrayRef<Metadata *> 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<DIScope>(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<MDString>(1); }
-  MDString *getRawConfigurationMacros() const { return getOperandAs<MDString>(2); }
-  MDString *getRawIncludePath() const { return getOperandAs<MDString>(3); }
-  MDString *getRawAPINotesFile() const { return getOperandAs<MDString>(4); }
+  Metadata *getRawScope() const { return getOperand(1); }
+  MDString *getRawName() const { return getOperandAs<MDString>(2); }
+  MDString *getRawConfigurationMacros() const {
+    return getOperandAs<MDString>(3);
+  }
+  MDString *getRawIncludePath() const { return getOperandAs<MDString>(4); }
+  MDString *getRawAPINotesFile() const { return getOperandAs<MDString>(5); }
 
   static bool classof(const Metadata *MD) {
     return MD->getMetadataID() == DIModuleKind;

diff  --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 0d9751939ab1..8c9c53cbcca4 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/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/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 735d802e8229..33776bd1be6b 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/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/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 3c8e4b2e3ea6..c70c5ac543b2 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/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/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index ecf4a78f3be6..ba20e08aae2e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/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/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 1afc5c1fd928..83874e47a015 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/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/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index 6ed621c407ec..95841be53477 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/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/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index db92c126ad74..c176d27a52ac 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/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/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 705ffdc58726..543f2e964e73 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -816,27 +816,32 @@ template <> struct MDNodeKeyImpl<DICommonBlock> {
 };
 
 template <> struct MDNodeKeyImpl<DIModule> {
+  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/llvm/test/Assembler/dimodule.ll b/llvm/test/Assembler/dimodule.ll
index c3802ea1265d..39d1d32ceeb6 100644
--- a/llvm/test/Assembler/dimodule.ll
+++ b/llvm/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/llvm/test/Bitcode/DIModule-clang-module.ll b/llvm/test/Bitcode/DIModule-clang-module.ll
new file mode 100644
index 000000000000..d83a0889718a
--- /dev/null
+++ b/llvm/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/llvm/test/Bitcode/DIModule-clang-module.ll.bc b/llvm/test/Bitcode/DIModule-clang-module.ll.bc
new file mode 100644
index 000000000000..dc3647fb5255
Binary files /dev/null and b/llvm/test/Bitcode/DIModule-clang-module.ll.bc 
diff er

diff  --git a/llvm/test/Bitcode/DIModule-fortran-module.ll b/llvm/test/Bitcode/DIModule-fortran-module.ll
new file mode 100644
index 000000000000..053a6d720f76
--- /dev/null
+++ b/llvm/test/Bitcode/DIModule-fortran-module.ll
@@ -0,0 +1,34 @@
+; RUN: llvm-dis -o - %s.bc | FileCheck %s
+
+; CHECK: DIModule(scope: !4, name: "dummy", file: !3, line: 2)
+
+; ModuleID = 'DIModule-fortran-module.bc'
+source_filename = "/tmp/module-b198fa.ll"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct_dummy_0_ = type <{ [4 x i8] }>
+
+ at _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/llvm/test/Bitcode/DIModule-fortran-module.ll.bc b/llvm/test/Bitcode/DIModule-fortran-module.ll.bc
new file mode 100644
index 000000000000..4884e9a2d06c
Binary files /dev/null and b/llvm/test/Bitcode/DIModule-fortran-module.ll.bc 
diff er

diff  --git a/llvm/test/DebugInfo/X86/Fortran-DIModule.ll b/llvm/test/DebugInfo/X86/Fortran-DIModule.ll
new file mode 100644
index 000000000000..33500dfb6de2
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/Fortran-DIModule.ll
@@ -0,0 +1,44 @@
+; This test checks attributes of a Fortran module.
+; RUN: %llc_dwarf  %s -filetype=obj -o - | \
+; RUN:   llvm-dwarfdump - | FileCheck %s
+
+; CHECK: DW_TAG_module
+; CHECK-NEXT: DW_AT_name      ("dummy")
+; CHECK-NEXT: DW_AT_decl_file ("/fortran/module.f90")
+; CHECK-NEXT: DW_AT_decl_line (2)
+
+; Generated from flang compiler, Fortran source to regenerate:
+; module dummy
+;         integer :: foo
+; end module dummy
+
+; ModuleID = '/tmp/module-b198fa.ll'
+source_filename = "/tmp/module-b198fa.ll"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct_dummy_0_ = type <{ [4 x i8] }>
+
+ at _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/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index b60bcac55013..39cd0edca6fc 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/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)));


        


More information about the llvm-commits mailing list