Skip to content

Commit 5f75dcf

Browse files
committed
[DebugInfo] Support Fortran 'use <external module>' statement.
The main change is to add a 'IsDecl' field to DIModule so that when IsDecl is set to true, the debug info entry generated for the module would be marked as a declaration. That way, the debugger would look up the definition of the module in the gloabl scope. Please see the comments in llvm/test/DebugInfo/X86/dimodule.ll for what the debug info entries would look like. Differential Revision: https://reviews.llvm.org/D93462
1 parent 5e5ef53 commit 5f75dcf

File tree

14 files changed

+217
-42
lines changed

14 files changed

+217
-42
lines changed

llvm/include/llvm/IR/DIBuilder.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -772,14 +772,18 @@ namespace llvm {
772772
/// definitions as they would appear on a command line.
773773
/// \param IncludePath The path to the module map file.
774774
/// \param APINotesFile The path to an API notes file for this module.
775-
/// \param File Source file of the module declaration. Used for
776-
/// Fortran modules.
777-
/// \param LineNo Source line number of the module declaration.
775+
/// \param File Source file of the module.
778776
/// Used for Fortran modules.
777+
/// \param LineNo Source line number of the module.
778+
/// Used for Fortran modules.
779+
/// \param IsDecl This is a module declaration; default to false;
780+
/// when set to true, only Scope and Name are required
781+
/// as this entry is just a hint for the debugger to find
782+
/// the corresponding definition in the global scope.
779783
DIModule *createModule(DIScope *Scope, StringRef Name,
780784
StringRef ConfigurationMacros, StringRef IncludePath,
781785
StringRef APINotesFile = {}, DIFile *File = nullptr,
782-
unsigned LineNo = 0);
786+
unsigned LineNo = 0, bool IsDecl = false);
783787

784788
/// This creates a descriptor for a lexical block with a new file
785789
/// attached. This merely extends the existing

llvm/include/llvm/IR/DebugInfoMetadata.h

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2297,49 +2297,52 @@ class DIModule : public DIScope {
22972297
friend class LLVMContextImpl;
22982298
friend class MDNode;
22992299
unsigned LineNo;
2300+
bool IsDecl;
23002301

23012302
DIModule(LLVMContext &Context, StorageType Storage, unsigned LineNo,
2302-
ArrayRef<Metadata *> Ops)
2303+
bool IsDecl, ArrayRef<Metadata *> Ops)
23032304
: DIScope(Context, DIModuleKind, Storage, dwarf::DW_TAG_module, Ops),
2304-
LineNo(LineNo) {}
2305+
LineNo(LineNo), IsDecl(IsDecl) {}
23052306
~DIModule() = default;
23062307

23072308
static DIModule *getImpl(LLVMContext &Context, DIFile *File, DIScope *Scope,
23082309
StringRef Name, StringRef ConfigurationMacros,
23092310
StringRef IncludePath, StringRef APINotesFile,
2310-
unsigned LineNo, StorageType Storage,
2311+
unsigned LineNo, bool IsDecl, StorageType Storage,
23112312
bool ShouldCreate = true) {
23122313
return getImpl(Context, File, Scope, getCanonicalMDString(Context, Name),
23132314
getCanonicalMDString(Context, ConfigurationMacros),
23142315
getCanonicalMDString(Context, IncludePath),
2315-
getCanonicalMDString(Context, APINotesFile), LineNo, Storage,
2316-
ShouldCreate);
2316+
getCanonicalMDString(Context, APINotesFile), LineNo, IsDecl,
2317+
Storage, ShouldCreate);
23172318
}
23182319
static DIModule *getImpl(LLVMContext &Context, Metadata *File,
23192320
Metadata *Scope, MDString *Name,
23202321
MDString *ConfigurationMacros, MDString *IncludePath,
2321-
MDString *APINotesFile, unsigned LineNo,
2322+
MDString *APINotesFile, unsigned LineNo, bool IsDecl,
23222323
StorageType Storage, bool ShouldCreate = true);
23232324

23242325
TempDIModule cloneImpl() const {
23252326
return getTemporary(getContext(), getFile(), getScope(), getName(),
23262327
getConfigurationMacros(), getIncludePath(),
2327-
getAPINotesFile(), getLineNo());
2328+
getAPINotesFile(), getLineNo(), getIsDecl());
23282329
}
23292330

23302331
public:
23312332
DEFINE_MDNODE_GET(DIModule,
23322333
(DIFile * File, DIScope *Scope, StringRef Name,
23332334
StringRef ConfigurationMacros, StringRef IncludePath,
2334-
StringRef APINotesFile, unsigned LineNo),
2335+
StringRef APINotesFile, unsigned LineNo,
2336+
bool IsDecl = false),
23352337
(File, Scope, Name, ConfigurationMacros, IncludePath,
2336-
APINotesFile, LineNo))
2338+
APINotesFile, LineNo, IsDecl))
23372339
DEFINE_MDNODE_GET(DIModule,
23382340
(Metadata * File, Metadata *Scope, MDString *Name,
23392341
MDString *ConfigurationMacros, MDString *IncludePath,
2340-
MDString *APINotesFile, unsigned LineNo),
2342+
MDString *APINotesFile, unsigned LineNo,
2343+
bool IsDecl = false),
23412344
(File, Scope, Name, ConfigurationMacros, IncludePath,
2342-
APINotesFile, LineNo))
2345+
APINotesFile, LineNo, IsDecl))
23432346

23442347
TempDIModule clone() const { return cloneImpl(); }
23452348

@@ -2349,6 +2352,7 @@ class DIModule : public DIScope {
23492352
StringRef getIncludePath() const { return getStringOperand(4); }
23502353
StringRef getAPINotesFile() const { return getStringOperand(5); }
23512354
unsigned getLineNo() const { return LineNo; }
2355+
bool getIsDecl() const { return IsDecl; }
23522356

23532357
Metadata *getRawScope() const { return getOperand(1); }
23542358
MDString *getRawName() const { return getOperandAs<MDString>(2); }

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5119,7 +5119,7 @@ bool LLParser::parseDIMacroFile(MDNode *&Result, bool IsDistinct) {
51195119
/// parseDIModule:
51205120
/// ::= !DIModule(scope: !0, name: "SomeModule", configMacros:
51215121
/// "-DNDEBUG", includePath: "/usr/include", apinotes: "module.apinotes",
5122-
/// file: !1, line: 4)
5122+
/// file: !1, line: 4, isDecl: false)
51235123
bool LLParser::parseDIModule(MDNode *&Result, bool IsDistinct) {
51245124
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
51255125
REQUIRED(scope, MDField, ); \
@@ -5128,13 +5128,14 @@ bool LLParser::parseDIModule(MDNode *&Result, bool IsDistinct) {
51285128
OPTIONAL(includePath, MDStringField, ); \
51295129
OPTIONAL(apinotes, MDStringField, ); \
51305130
OPTIONAL(file, MDField, ); \
5131-
OPTIONAL(line, LineField, );
5131+
OPTIONAL(line, LineField, ); \
5132+
OPTIONAL(isDecl, MDBoolField, );
51325133
PARSE_MD_FIELDS();
51335134
#undef VISIT_MD_FIELDS
51345135

51355136
Result = GET_OR_DISTINCT(DIModule, (Context, file.Val, scope.Val, name.Val,
51365137
configMacros.Val, includePath.Val,
5137-
apinotes.Val, line.Val));
5138+
apinotes.Val, line.Val, isDecl.Val));
51385139
return false;
51395140
}
51405141

llvm/lib/Bitcode/Reader/MetadataLoader.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,19 +1565,20 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
15651565
}
15661566

15671567
case bitc::METADATA_MODULE: {
1568-
if (Record.size() < 5 || Record.size() > 8)
1568+
if (Record.size() < 5 || Record.size() > 9)
15691569
return error("Invalid record");
15701570

1571-
unsigned Offset = Record.size() >= 7 ? 2 : 1;
1571+
unsigned Offset = Record.size() >= 8 ? 2 : 1;
15721572
IsDistinct = Record[0];
15731573
MetadataList.assignValue(
15741574
GET_OR_DISTINCT(
15751575
DIModule,
1576-
(Context, Record.size() >= 7 ? getMDOrNull(Record[1]) : nullptr,
1576+
(Context, Record.size() >= 8 ? getMDOrNull(Record[1]) : nullptr,
15771577
getMDOrNull(Record[0 + Offset]), getMDString(Record[1 + Offset]),
15781578
getMDString(Record[2 + Offset]), getMDString(Record[3 + Offset]),
15791579
getMDString(Record[4 + Offset]),
1580-
Record.size() <= 7 ? 0 : Record[7])),
1580+
Record.size() <= 7 ? 0 : Record[7],
1581+
Record.size() <= 8 ? false : Record[8])),
15811582
NextMetadataNo);
15821583
NextMetadataNo++;
15831584
break;

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1868,6 +1868,7 @@ void ModuleBitcodeWriter::writeDIModule(const DIModule *N,
18681868
for (auto &I : N->operands())
18691869
Record.push_back(VE.getMetadataOrNullID(I));
18701870
Record.push_back(N->getLineNo());
1871+
Record.push_back(N->getIsDecl());
18711872

18721873
Stream.EmitRecord(bitc::METADATA_MODULE, Record, Abbrev);
18731874
Record.clear();

llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,8 @@ DIE *DwarfUnit::getOrCreateModule(const DIModule *M) {
10671067
getOrCreateSourceID(M->getFile()));
10681068
if (M->getLineNo())
10691069
addUInt(MDie, dwarf::DW_AT_decl_line, None, M->getLineNo());
1070+
if (M->getIsDecl())
1071+
addFlag(MDie, dwarf::DW_AT_declaration);
10701072

10711073
return &MDie;
10721074
}

llvm/lib/IR/AsmWriter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2245,6 +2245,7 @@ static void writeDIModule(raw_ostream &Out, const DIModule *N,
22452245
Printer.printString("apinotes", N->getAPINotesFile());
22462246
Printer.printMetadata("file", N->getRawFile());
22472247
Printer.printInt("line", N->getLineNo());
2248+
Printer.printBool("isDecl", N->getIsDecl(), /* Default */ false);
22482249
Out << ")";
22492250
}
22502251

llvm/lib/IR/DIBuilder.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -874,9 +874,10 @@ DINamespace *DIBuilder::createNameSpace(DIScope *Scope, StringRef Name,
874874
DIModule *DIBuilder::createModule(DIScope *Scope, StringRef Name,
875875
StringRef ConfigurationMacros,
876876
StringRef IncludePath, StringRef APINotesFile,
877-
DIFile *File, unsigned LineNo) {
877+
DIFile *File, unsigned LineNo, bool IsDecl) {
878878
return DIModule::get(VMContext, File, getNonCompileUnitScope(Scope), Name,
879-
ConfigurationMacros, IncludePath, APINotesFile, LineNo);
879+
ConfigurationMacros, IncludePath, APINotesFile, LineNo,
880+
IsDecl);
880881
}
881882

882883
DILexicalBlockFile *DIBuilder::createLexicalBlockFile(DIScope *Scope,

llvm/lib/IR/DebugInfoMetadata.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -926,14 +926,14 @@ DIModule *DIModule::getImpl(LLVMContext &Context, Metadata *File,
926926
Metadata *Scope, MDString *Name,
927927
MDString *ConfigurationMacros,
928928
MDString *IncludePath, MDString *APINotesFile,
929-
unsigned LineNo, StorageType Storage,
929+
unsigned LineNo, bool IsDecl, StorageType Storage,
930930
bool ShouldCreate) {
931931
assert(isCanonical(Name) && "Expected canonical MDString");
932932
DEFINE_GETIMPL_LOOKUP(DIModule, (File, Scope, Name, ConfigurationMacros,
933-
IncludePath, APINotesFile, LineNo));
933+
IncludePath, APINotesFile, LineNo, IsDecl));
934934
Metadata *Ops[] = {File, Scope, Name, ConfigurationMacros,
935935
IncludePath, APINotesFile};
936-
DEFINE_GETIMPL_STORE(DIModule, (LineNo), Ops);
936+
DEFINE_GETIMPL_STORE(DIModule, (LineNo, IsDecl), Ops);
937937
}
938938

939939
DITemplateTypeParameter *

llvm/lib/IR/LLVMContextImpl.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -891,25 +891,28 @@ template <> struct MDNodeKeyImpl<DIModule> {
891891
MDString *IncludePath;
892892
MDString *APINotesFile;
893893
unsigned LineNo;
894+
bool IsDecl;
894895

895896
MDNodeKeyImpl(Metadata *File, Metadata *Scope, MDString *Name,
896897
MDString *ConfigurationMacros, MDString *IncludePath,
897-
MDString *APINotesFile, unsigned LineNo)
898+
MDString *APINotesFile, unsigned LineNo, bool IsDecl)
898899
: File(File), Scope(Scope), Name(Name),
899900
ConfigurationMacros(ConfigurationMacros), IncludePath(IncludePath),
900-
APINotesFile(APINotesFile), LineNo(LineNo) {}
901+
APINotesFile(APINotesFile), LineNo(LineNo), IsDecl(IsDecl) {}
901902
MDNodeKeyImpl(const DIModule *N)
902903
: File(N->getRawFile()), Scope(N->getRawScope()), Name(N->getRawName()),
903904
ConfigurationMacros(N->getRawConfigurationMacros()),
904905
IncludePath(N->getRawIncludePath()),
905-
APINotesFile(N->getRawAPINotesFile()), LineNo(N->getLineNo()) {}
906+
APINotesFile(N->getRawAPINotesFile()), LineNo(N->getLineNo()),
907+
IsDecl(N->getIsDecl()) {}
906908

907909
bool isKeyOf(const DIModule *RHS) const {
908910
return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
909911
ConfigurationMacros == RHS->getRawConfigurationMacros() &&
910912
IncludePath == RHS->getRawIncludePath() &&
911913
APINotesFile == RHS->getRawAPINotesFile() &&
912-
File == RHS->getRawFile() && LineNo == RHS->getLineNo();
914+
File == RHS->getRawFile() && LineNo == RHS->getLineNo() &&
915+
IsDecl == RHS->getIsDecl();
913916
}
914917

915918
unsigned getHashValue() const {

llvm/test/Assembler/dimodule.ll

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
22
; RUN: verify-uselistorder %s
33

4-
; CHECK: !named = !{!0, !1, !2, !1, !3}
5-
!named = !{!0, !1, !2, !3, !4}
4+
; CHECK: !named = !{!0, !1, !2, !1, !3, !4}
5+
!named = !{!0, !1, !2, !3, !4, !5}
66

77
!0 = distinct !{}
88

@@ -16,3 +16,6 @@
1616

1717
; CHECK: !3 = !DIModule(scope: !0, name: "Module", configMacros: "-DNDEBUG", includePath: "/usr/include", apinotes: "/tmp/m.apinotes", file: !0, line: 1)
1818
!4 = !DIModule(scope: !0, name: "Module", configMacros: "-DNDEBUG", includePath: "/usr/include", apinotes: "/tmp/m.apinotes", file: !0, line: 1)
19+
20+
; CHECK: !4 = !DIModule(scope: !0, name: "Module", isDecl: true)
21+
!5 = !DIModule(scope: !0, name: "Module", isDecl: true)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
; RUN: llvm-as -o - %s | llvm-dis -o - | FileCheck %s
2+
; CHECK: DIImportedEntity(tag: DW_TAG_imported_module, scope: !2, entity: !11, file: !3, line: 2)
3+
; CHECK: DIModule(scope: !2, name: "external_module", isDecl: true)
4+
5+
; ModuleID = 'em.f90'
6+
source_filename = "em.f90"
7+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
8+
target triple = "x86_64-unknown-linux-gnu"
9+
10+
@external_module_mp_dummy_ = available_externally global float 0.000000e+00, align 8, !dbg !0
11+
@0 = internal unnamed_addr constant i32 2
12+
13+
; Function Attrs: noinline nounwind uwtable
14+
define void @MAIN__() #0 !dbg !2 {
15+
alloca_0:
16+
%"var$1" = alloca [8 x i64], align 8
17+
%"use_external_module_$X" = alloca float, align 8
18+
call void @llvm.dbg.declare(metadata float* %"use_external_module_$X", metadata !13, metadata !DIExpression()), !dbg !17
19+
%func_result = call i32 @for_set_reentrancy(i32* @0), !dbg !18
20+
%external_module_mp_dummy__fetch = load float, float* @external_module_mp_dummy_, align 1, !dbg !19
21+
%add = fadd reassoc ninf nsz arcp contract afn float 2.000000e+00, %external_module_mp_dummy__fetch, !dbg !20
22+
store float %add, float* %"use_external_module_$X", align 1, !dbg !19
23+
ret void, !dbg !21
24+
}
25+
26+
; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
27+
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
28+
29+
declare i32 @for_set_reentrancy(i32*)
30+
31+
attributes #0 = { noinline nounwind uwtable "intel-lang"="fortran" "min-legal-vector-width"="0" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" }
32+
attributes #1 = { nofree nosync nounwind readnone speculatable willreturn }
33+
34+
!llvm.module.flags = !{!15, !16}
35+
!llvm.dbg.cu = !{!6}
36+
!omp_offload.info = !{}
37+
38+
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
39+
!1 = distinct !DIGlobalVariable(name: "dummy", linkageName: "external_module_mp_dummy_", scope: !2, file: !3, line: 1, type: !14, isLocal: false, isDefinition: true)
40+
!2 = distinct !DISubprogram(name: "use_external_module", linkageName: "MAIN__", scope: !3, file: !3, line: 1, type: !4, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !12)
41+
!3 = !DIFile(filename: "em.f90", directory: "tests")
42+
!4 = !DISubroutineType(types: !5)
43+
!5 = !{null}
44+
!6 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2165", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, globals: !8, imports: !9, splitDebugInlining: false, nameTableKind: None)
45+
!7 = !{}
46+
!8 = !{!0}
47+
!9 = !{!10}
48+
!10 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !2, entity: !11, file: !3, line: 2)
49+
!11 = !DIModule(scope: !2, name: "external_module", isDecl: true)
50+
!12 = !{!13}
51+
!13 = !DILocalVariable(name: "x", scope: !2, file: !3, line: 5, type: !14)
52+
!14 = !DIBasicType(name: "REAL*4", size: 32, encoding: DW_ATE_float)
53+
!15 = !{i32 2, !"Debug Info Version", i32 3}
54+
!16 = !{i32 2, !"Dwarf Version", i32 4}
55+
!17 = !DILocation(line: 5, column: 12, scope: !2)
56+
!18 = !DILocation(line: 1, column: 9, scope: !2)
57+
!19 = !DILocation(line: 6, column: 4, scope: !2)
58+
!20 = !DILocation(line: 6, column: 12, scope: !2)
59+
!21 = !DILocation(line: 8, column: 1, scope: !2)

0 commit comments

Comments
 (0)