Skip to content

Commit 6ed5706

Browse files
committed
Add LLVM IR debug info support for Fortran COMMON blocks
COMMON blocks are a feature of Fortran that has no direct analog in C languages, but they are similar to data sections in assembly language programming. A COMMON block is a named area of memory that holds a collection of variables. Fortran subprograms may map the COMMON block memory area to their own, possibly distinct, non-empty list of variables. A Fortran COMMON block might look like the following example. COMMON /ALPHA/ I, J For this construct, the compiler generates a new scope-like DI construct (!DICommonBlock) into which variables (see I, J above) can be placed. As the common block implies a range of storage with global lifetime, the !DICommonBlock refers to a !DIGlobalVariable. The Fortran variable that comprise the COMMON block are also linked via metadata to offsets within the global variable that stands for the entire common block. @alpha_ = common global %alphabytes_ zeroinitializer, align 64, !dbg !27, !dbg !30, !dbg !33 !14 = distinct !DISubprogram(…) !20 = distinct !DICommonBlock(scope: !14, declaration: !25, name: "alpha") !25 = distinct !DIGlobalVariable(scope: !20, name: "common alpha", type: !24) !27 = !DIGlobalVariableExpression(var: !25, expr: !DIExpression()) !29 = distinct !DIGlobalVariable(scope: !20, name: "i", file: !3, type: !28) !30 = !DIGlobalVariableExpression(var: !29, expr: !DIExpression()) !31 = distinct !DIGlobalVariable(scope: !20, name: "j", file: !3, type: !28) !32 = !DIExpression(DW_OP_plus_uconst, 4) !33 = !DIGlobalVariableExpression(var: !31, expr: !32) The DWARF generated for this is as follows. DW_TAG_common_block: DW_AT_name: alpha DW_AT_location: @alpha_+0 DW_TAG_variable: DW_AT_name: common alpha DW_AT_type: array of 8 bytes DW_AT_location: @alpha_+0 DW_TAG_variable: DW_AT_name: i DW_AT_type: integer*4 DW_AT_location: @Alpha+0 DW_TAG_variable: DW_AT_name: j DW_AT_type: integer*4 DW_AT_location: @Alpha+4 Patch by Eric Schweitz! Differential Revision: https://reviews.llvm.org/D54327 llvm-svn: 357934
1 parent 6cf7b71 commit 6ed5706

File tree

18 files changed

+293
-5
lines changed

18 files changed

+293
-5
lines changed

llvm/include/llvm-c/DebugInfo.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,8 @@ enum {
159159
LLVMDIObjCPropertyMetadataKind,
160160
LLVMDIImportedEntityMetadataKind,
161161
LLVMDIMacroMetadataKind,
162-
LLVMDIMacroFileMetadataKind
162+
LLVMDIMacroFileMetadataKind,
163+
LLVMDICommonBlockMetadataKind
163164
};
164165
typedef unsigned LLVMMetadataKind;
165166

llvm/include/llvm/Bitcode/LLVMBitCodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ enum MetadataCodes {
310310
METADATA_INDEX_OFFSET = 38, // [offset]
311311
METADATA_INDEX = 39, // [bitpos]
312312
METADATA_LABEL = 40, // [distinct, scope, name, file, line]
313+
METADATA_COMMON_BLOCK = 44, // [distinct, scope, name, variable,...]
313314
};
314315

315316
// The constants block (CONSTANTS_BLOCK_ID) describes emission for each

llvm/include/llvm/IR/DIBuilder.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,16 @@ namespace llvm {
706706
DITemplateParameterArray TParams = nullptr,
707707
DITypeArray ThrownTypes = nullptr);
708708

709+
/// Create common block entry for a Fortran common block
710+
/// \param Scope Scope of this common block
711+
/// \param Name The name of this common block
712+
/// \param File The file this common block is defined
713+
/// \param LineNo Line number
714+
/// \param VarList List of variables that a located in common block
715+
DICommonBlock *createCommonBlock(DIScope *Scope, DIGlobalVariable *decl,
716+
StringRef Name, DIFile *File,
717+
unsigned LineNo);
718+
709719
/// This creates new descriptor for a namespace with the specified
710720
/// parent scope.
711721
/// \param Scope Namespace scope

llvm/include/llvm/IR/DebugInfoMetadata.h

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ class DINode : public MDNode {
227227
case DILexicalBlockKind:
228228
case DILexicalBlockFileKind:
229229
case DINamespaceKind:
230+
case DICommonBlockKind:
230231
case DITemplateTypeParameterKind:
231232
case DITemplateValueParameterKind:
232233
case DIGlobalVariableKind:
@@ -485,6 +486,7 @@ class DIScope : public DINode {
485486
case DILexicalBlockKind:
486487
case DILexicalBlockFileKind:
487488
case DINamespaceKind:
489+
case DICommonBlockKind:
488490
case DIModuleKind:
489491
return true;
490492
}
@@ -2673,6 +2675,65 @@ class DIGlobalVariable : public DIVariable {
26732675
}
26742676
};
26752677

2678+
class DICommonBlock : public DIScope {
2679+
unsigned LineNo;
2680+
2681+
friend class LLVMContextImpl;
2682+
friend class MDNode;
2683+
2684+
DICommonBlock(LLVMContext &Context, StorageType Storage, unsigned LineNo,
2685+
ArrayRef<Metadata *> Ops)
2686+
: DIScope(Context, DICommonBlockKind, Storage, dwarf::DW_TAG_common_block,
2687+
Ops), LineNo(LineNo) {}
2688+
2689+
static DICommonBlock *getImpl(LLVMContext &Context, DIScope *Scope,
2690+
DIGlobalVariable *Decl, StringRef Name,
2691+
DIFile *File, unsigned LineNo,
2692+
StorageType Storage,
2693+
bool ShouldCreate = true) {
2694+
return getImpl(Context, Scope, Decl, getCanonicalMDString(Context, Name),
2695+
File, LineNo, Storage, ShouldCreate);
2696+
}
2697+
static DICommonBlock *getImpl(LLVMContext &Context, Metadata *Scope,
2698+
Metadata *Decl, MDString *Name, Metadata *File,
2699+
unsigned LineNo,
2700+
StorageType Storage, bool ShouldCreate = true);
2701+
2702+
TempDICommonBlock cloneImpl() const {
2703+
return getTemporary(getContext(), getScope(), getDecl(), getName(),
2704+
getFile(), getLineNo());
2705+
}
2706+
2707+
public:
2708+
DEFINE_MDNODE_GET(DICommonBlock,
2709+
(DIScope *Scope, DIGlobalVariable *Decl, StringRef Name,
2710+
DIFile *File, unsigned LineNo),
2711+
(Scope, Decl, Name, File, LineNo))
2712+
DEFINE_MDNODE_GET(DICommonBlock,
2713+
(Metadata *Scope, Metadata *Decl, MDString *Name,
2714+
Metadata *File, unsigned LineNo),
2715+
(Scope, Decl, Name, File, LineNo))
2716+
2717+
TempDICommonBlock clone() const { return cloneImpl(); }
2718+
2719+
DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); }
2720+
DIGlobalVariable *getDecl() const {
2721+
return cast_or_null<DIGlobalVariable>(getRawDecl());
2722+
}
2723+
StringRef getName() const { return getStringOperand(2); }
2724+
DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); }
2725+
unsigned getLineNo() const { return LineNo; }
2726+
2727+
Metadata *getRawScope() const { return getOperand(0); }
2728+
Metadata *getRawDecl() const { return getOperand(1); }
2729+
MDString *getRawName() const { return getOperandAs<MDString>(2); }
2730+
Metadata *getRawFile() const { return getOperand(3); }
2731+
2732+
static bool classof(const Metadata *MD) {
2733+
return MD->getMetadataID() == DICommonBlockKind;
2734+
}
2735+
};
2736+
26762737
/// Local variable.
26772738
///
26782739
/// TODO: Split up flags.

llvm/include/llvm/IR/Metadata.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIImportedEntity)
113113
HANDLE_SPECIALIZED_MDNODE_BRANCH(DIMacroNode)
114114
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacro)
115115
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacroFile)
116+
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICommonBlock)
116117

117118
#undef HANDLE_METADATA
118119
#undef HANDLE_METADATA_LEAF

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4664,6 +4664,24 @@ bool LLParser::ParseDILexicalBlockFile(MDNode *&Result, bool IsDistinct) {
46644664
return false;
46654665
}
46664666

4667+
/// ParseDICommonBlock:
4668+
/// ::= !DICommonBlock(scope: !0, file: !2, name: "COMMON name", line: 9)
4669+
bool LLParser::ParseDICommonBlock(MDNode *&Result, bool IsDistinct) {
4670+
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
4671+
REQUIRED(scope, MDField, ); \
4672+
OPTIONAL(declaration, MDField, ); \
4673+
OPTIONAL(name, MDStringField, ); \
4674+
OPTIONAL(file, MDField, ); \
4675+
OPTIONAL(line, LineField, );
4676+
PARSE_MD_FIELDS();
4677+
#undef VISIT_MD_FIELDS
4678+
4679+
Result = GET_OR_DISTINCT(DICommonBlock,
4680+
(Context, scope.Val, declaration.Val, name.Val,
4681+
file.Val, line.Val));
4682+
return false;
4683+
}
4684+
46674685
/// ParseDINamespace:
46684686
/// ::= !DINamespace(scope: !0, file: !2, name: "SomeNamespace", line: 9)
46694687
bool LLParser::ParseDINamespace(MDNode *&Result, bool IsDistinct) {

llvm/lib/Bitcode/Reader/MetadataLoader.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,7 @@ MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() {
811811
case bitc::METADATA_LEXICAL_BLOCK:
812812
case bitc::METADATA_LEXICAL_BLOCK_FILE:
813813
case bitc::METADATA_NAMESPACE:
814+
case bitc::METADATA_COMMON_BLOCK:
814815
case bitc::METADATA_MACRO:
815816
case bitc::METADATA_MACRO_FILE:
816817
case bitc::METADATA_TEMPLATE_TYPE:
@@ -1528,6 +1529,17 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
15281529
NextMetadataNo++;
15291530
break;
15301531
}
1532+
case bitc::METADATA_COMMON_BLOCK: {
1533+
IsDistinct = Record[0] & 1;
1534+
MetadataList.assignValue(
1535+
GET_OR_DISTINCT(DICommonBlock,
1536+
(Context, getMDOrNull(Record[1]),
1537+
getMDOrNull(Record[2]), getMDString(Record[3]),
1538+
getMDOrNull(Record[4]), Record[5])),
1539+
NextMetadataNo);
1540+
NextMetadataNo++;
1541+
break;
1542+
}
15311543
case bitc::METADATA_NAMESPACE: {
15321544
// Newer versions of DINamespace dropped file and line.
15331545
MDString *Name;

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,8 @@ class ModuleBitcodeWriter : public ModuleBitcodeWriterBase {
317317
void writeDILexicalBlockFile(const DILexicalBlockFile *N,
318318
SmallVectorImpl<uint64_t> &Record,
319319
unsigned Abbrev);
320+
void writeDICommonBlock(const DICommonBlock *N,
321+
SmallVectorImpl<uint64_t> &Record, unsigned Abbrev);
320322
void writeDINamespace(const DINamespace *N, SmallVectorImpl<uint64_t> &Record,
321323
unsigned Abbrev);
322324
void writeDIMacro(const DIMacro *N, SmallVectorImpl<uint64_t> &Record,
@@ -1686,6 +1688,20 @@ void ModuleBitcodeWriter::writeDILexicalBlockFile(
16861688
Record.clear();
16871689
}
16881690

1691+
void ModuleBitcodeWriter::writeDICommonBlock(const DICommonBlock *N,
1692+
SmallVectorImpl<uint64_t> &Record,
1693+
unsigned Abbrev) {
1694+
Record.push_back(N->isDistinct());
1695+
Record.push_back(VE.getMetadataOrNullID(N->getScope()));
1696+
Record.push_back(VE.getMetadataOrNullID(N->getDecl()));
1697+
Record.push_back(VE.getMetadataOrNullID(N->getRawName()));
1698+
Record.push_back(VE.getMetadataOrNullID(N->getFile()));
1699+
Record.push_back(N->getLineNo());
1700+
1701+
Stream.EmitRecord(bitc::METADATA_COMMON_BLOCK, Record, Abbrev);
1702+
Record.clear();
1703+
}
1704+
16891705
void ModuleBitcodeWriter::writeDINamespace(const DINamespace *N,
16901706
SmallVectorImpl<uint64_t> &Record,
16911707
unsigned Abbrev) {

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
123123

124124
// Construct the context before querying for the existence of the DIE in
125125
// case such construction creates the DIE.
126-
DIE *ContextDIE = getOrCreateContextDIE(GVContext);
126+
auto *CB = GVContext ? dyn_cast<DICommonBlock>(GVContext) : nullptr;
127+
DIE *ContextDIE = CB ? getOrCreateCommonBlock(CB, GlobalExprs)
128+
: getOrCreateContextDIE(GVContext);
127129

128130
// Add to map.
129131
DIE *VariableDIE = &createAndAddDIE(GV->getTag(), *ContextDIE, GV);
@@ -166,6 +168,13 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
166168
addTemplateParams(*VariableDIE, DINodeArray(TP));
167169

168170
// Add location.
171+
addLocationAttribute(VariableDIE, GV, GlobalExprs);
172+
173+
return VariableDIE;
174+
}
175+
176+
void DwarfCompileUnit::addLocationAttribute(
177+
DIE *VariableDIE, const DIGlobalVariable *GV, ArrayRef<GlobalExpr> GlobalExprs) {
169178
bool addToAccelTable = false;
170179
DIELoc *Loc = nullptr;
171180
Optional<unsigned> NVPTXAddressSpace;
@@ -288,8 +297,25 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
288297
DD->useAllLinkageNames())
289298
DD->addAccelName(*CUNode, GV->getLinkageName(), *VariableDIE);
290299
}
300+
}
291301

292-
return VariableDIE;
302+
DIE *DwarfCompileUnit::getOrCreateCommonBlock(
303+
const DICommonBlock *CB, ArrayRef<GlobalExpr> GlobalExprs) {
304+
// Construct the context before querying for the existence of the DIE in case
305+
// such construction creates the DIE.
306+
DIE *ContextDIE = getOrCreateContextDIE(CB->getScope());
307+
308+
if (DIE *NDie = getDIE(CB))
309+
return NDie;
310+
DIE &NDie = createAndAddDIE(dwarf::DW_TAG_common_block, *ContextDIE, CB);
311+
StringRef Name = CB->getName().empty() ? "_BLNK_" : CB->getName();
312+
addString(NDie, dwarf::DW_AT_name, Name);
313+
addGlobalName(Name, NDie, CB->getScope());
314+
if (CB->getFile())
315+
addSourceLine(NDie, CB->getLineNo(), CB->getFile());
316+
if (DIGlobalVariable *V = CB->getDecl())
317+
getCU().addLocationAttribute(&NDie, V, GlobalExprs);
318+
return &NDie;
293319
}
294320

295321
void DwarfCompileUnit::addRange(RangeSpan Range) {

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,12 @@ class DwarfCompileUnit final : public DwarfUnit {
139139
getOrCreateGlobalVariableDIE(const DIGlobalVariable *GV,
140140
ArrayRef<GlobalExpr> GlobalExprs);
141141

142+
DIE *getOrCreateCommonBlock(const DICommonBlock *CB,
143+
ArrayRef<GlobalExpr> GlobalExprs);
144+
145+
void addLocationAttribute(DIE *ToDIE, const DIGlobalVariable *GV,
146+
ArrayRef<GlobalExpr> GlobalExprs);
147+
142148
/// addLabelAddress - Add a dwarf label attribute data and value using
143149
/// either DW_FORM_addr or DW_FORM_GNU_addr_index.
144150
void addLabelAddress(DIE &Die, dwarf::Attribute Attribute,

0 commit comments

Comments
 (0)