Skip to content

Commit a6dd01a

Browse files
committed
[DebugInfo] Support for DW_TAG_generic_subrange
This is needed to support fortran assumed rank arrays which have runtime rank. Summary: Fortran assumed rank arrays have dynamic rank. DWARF TAG DW_TAG_generic_subrange is needed to support that. Testing: unit test cases added (hand-written) check llvm check debug-info Reviewed By: aprantl Differential Revision: https://reviews.llvm.org/D89218
1 parent 3b2256a commit a6dd01a

27 files changed

+856
-7
lines changed

llvm/include/llvm-c/DebugInfo.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,8 @@ enum {
160160
LLVMDIMacroMetadataKind,
161161
LLVMDIMacroFileMetadataKind,
162162
LLVMDICommonBlockMetadataKind,
163-
LLVMDIStringTypeMetadataKind
163+
LLVMDIStringTypeMetadataKind,
164+
LLVMDIGenericSubrangeMetadataKind
164165
};
165166
typedef unsigned LLVMMetadataKind;
166167

llvm/include/llvm/Bitcode/LLVMBitCodes.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,8 @@ enum MetadataCodes {
341341
METADATA_STRING_TYPE = 41, // [distinct, name, size, align,...]
342342
// Codes 42 and 43 are reserved for support for Fortran array specific debug
343343
// info.
344-
METADATA_COMMON_BLOCK = 44 // [distinct, scope, name, variable,...]
344+
METADATA_COMMON_BLOCK = 44, // [distinct, scope, name, variable,...]
345+
METADATA_GENERIC_SUBRANGE = 45 // [distinct, count, lo, up, stride]
345346
};
346347

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

llvm/include/llvm/IR/DIBuilder.h

+6
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,12 @@ namespace llvm {
582582
DISubrange *getOrCreateSubrange(Metadata *Count, Metadata *LowerBound,
583583
Metadata *UpperBound, Metadata *Stride);
584584

585+
DIGenericSubrange *
586+
getOrCreateGenericSubrange(DIGenericSubrange::BoundType Count,
587+
DIGenericSubrange::BoundType LowerBound,
588+
DIGenericSubrange::BoundType UpperBound,
589+
DIGenericSubrange::BoundType Stride);
590+
585591
/// Create a new descriptor for the specified variable.
586592
/// \param Context Variable scope.
587593
/// \param Name Name of the variable.

llvm/include/llvm/IR/DebugInfoMetadata.h

+50
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ class DINode : public MDNode {
201201
case DIObjCPropertyKind:
202202
case DIImportedEntityKind:
203203
case DIModuleKind:
204+
case DIGenericSubrangeKind:
204205
return true;
205206
}
206207
}
@@ -351,6 +352,52 @@ class DISubrange : public DINode {
351352
}
352353
};
353354

355+
class DIGenericSubrange : public DINode {
356+
friend class LLVMContextImpl;
357+
friend class MDNode;
358+
359+
DIGenericSubrange(LLVMContext &C, StorageType Storage,
360+
ArrayRef<Metadata *> Ops)
361+
: DINode(C, DIGenericSubrangeKind, Storage,
362+
dwarf::DW_TAG_generic_subrange, Ops) {}
363+
364+
~DIGenericSubrange() = default;
365+
366+
static DIGenericSubrange *getImpl(LLVMContext &Context, Metadata *CountNode,
367+
Metadata *LowerBound, Metadata *UpperBound,
368+
Metadata *Stride, StorageType Storage,
369+
bool ShouldCreate = true);
370+
371+
TempDIGenericSubrange cloneImpl() const {
372+
return getTemporary(getContext(), getRawCountNode(), getRawLowerBound(),
373+
getRawUpperBound(), getRawStride());
374+
}
375+
376+
public:
377+
DEFINE_MDNODE_GET(DIGenericSubrange,
378+
(Metadata * CountNode, Metadata *LowerBound,
379+
Metadata *UpperBound, Metadata *Stride),
380+
(CountNode, LowerBound, UpperBound, Stride))
381+
382+
TempDIGenericSubrange clone() const { return cloneImpl(); }
383+
384+
Metadata *getRawCountNode() const { return getOperand(0).get(); }
385+
Metadata *getRawLowerBound() const { return getOperand(1).get(); }
386+
Metadata *getRawUpperBound() const { return getOperand(2).get(); }
387+
Metadata *getRawStride() const { return getOperand(3).get(); }
388+
389+
using BoundType = PointerUnion<DIVariable *, DIExpression *>;
390+
391+
BoundType getCount() const;
392+
BoundType getLowerBound() const;
393+
BoundType getUpperBound() const;
394+
BoundType getStride() const;
395+
396+
static bool classof(const Metadata *MD) {
397+
return MD->getMetadataID() == DIGenericSubrangeKind;
398+
}
399+
};
400+
354401
/// Enumeration value.
355402
///
356403
/// TODO: Add a pointer to the context (DW_TAG_enumeration_type) once that no
@@ -2524,6 +2571,9 @@ class DIExpression : public MDNode {
25242571
/// Determine whether this represents a standalone constant value.
25252572
bool isConstant() const;
25262573

2574+
/// Determine whether this represents a standalone signed constant value.
2575+
bool isSignedConstant() const;
2576+
25272577
using element_iterator = ArrayRef<uint64_t>::iterator;
25282578

25292579
element_iterator elements_begin() const { return getElements().begin(); }

llvm/include/llvm/IR/Metadata.def

+1
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacro)
115115
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacroFile)
116116
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICommonBlock)
117117
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIStringType)
118+
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGenericSubrange)
118119

119120
#undef HANDLE_METADATA
120121
#undef HANDLE_METADATA_LEAF

llvm/lib/AsmParser/LLParser.cpp

+33
Original file line numberDiff line numberDiff line change
@@ -4670,6 +4670,39 @@ bool LLParser::parseDISubrange(MDNode *&Result, bool IsDistinct) {
46704670
return false;
46714671
}
46724672

4673+
/// parseDIGenericSubrange:
4674+
/// ::= !DIGenericSubrange(lowerBound: !node1, upperBound: !node2, stride:
4675+
/// !node3)
4676+
bool LLParser::parseDIGenericSubrange(MDNode *&Result, bool IsDistinct) {
4677+
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
4678+
OPTIONAL(count, MDSignedOrMDField, ); \
4679+
OPTIONAL(lowerBound, MDSignedOrMDField, ); \
4680+
OPTIONAL(upperBound, MDSignedOrMDField, ); \
4681+
OPTIONAL(stride, MDSignedOrMDField, );
4682+
PARSE_MD_FIELDS();
4683+
#undef VISIT_MD_FIELDS
4684+
4685+
auto ConvToMetadata = [&](MDSignedOrMDField Bound) -> Metadata * {
4686+
if (Bound.isMDSignedField())
4687+
return DIExpression::get(
4688+
Context, {dwarf::DW_OP_consts,
4689+
static_cast<uint64_t>(Bound.getMDSignedValue())});
4690+
if (Bound.isMDField())
4691+
return Bound.getMDFieldValue();
4692+
return nullptr;
4693+
};
4694+
4695+
Metadata *Count = ConvToMetadata(count);
4696+
Metadata *LowerBound = ConvToMetadata(lowerBound);
4697+
Metadata *UpperBound = ConvToMetadata(upperBound);
4698+
Metadata *Stride = ConvToMetadata(stride);
4699+
4700+
Result = GET_OR_DISTINCT(DIGenericSubrange,
4701+
(Context, Count, LowerBound, UpperBound, Stride));
4702+
4703+
return false;
4704+
}
4705+
46734706
/// parseDIEnumerator:
46744707
/// ::= !DIEnumerator(value: 30, isUnsigned: true, name: "SomeKind")
46754708
bool LLParser::parseDIEnumerator(MDNode *&Result, bool IsDistinct) {

llvm/lib/Bitcode/Reader/MetadataLoader.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,7 @@ MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() {
875875
case bitc::METADATA_OBJC_PROPERTY:
876876
case bitc::METADATA_IMPORTED_ENTITY:
877877
case bitc::METADATA_GLOBAL_VAR_EXPR:
878+
case bitc::METADATA_GENERIC_SUBRANGE:
878879
// We don't expect to see any of these, if we see one, give up on
879880
// lazy-loading and fallback.
880881
MDStringRef.clear();
@@ -1371,6 +1372,18 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
13711372
NextMetadataNo++;
13721373
break;
13731374
}
1375+
case bitc::METADATA_GENERIC_SUBRANGE: {
1376+
Metadata *Val = nullptr;
1377+
Val = GET_OR_DISTINCT(DIGenericSubrange,
1378+
(Context, getMDOrNull(Record[1]),
1379+
getMDOrNull(Record[2]), getMDOrNull(Record[3]),
1380+
getMDOrNull(Record[4])));
1381+
1382+
MetadataList.assignValue(Val, NextMetadataNo);
1383+
IsDistinct = Record[0] & 1;
1384+
NextMetadataNo++;
1385+
break;
1386+
}
13741387
case bitc::METADATA_ENUMERATOR: {
13751388
if (Record.size() < 3)
13761389
return error("Invalid record");

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,9 @@ class ModuleBitcodeWriter : public ModuleBitcodeWriterBase {
300300
SmallVectorImpl<uint64_t> &Record, unsigned &Abbrev);
301301
void writeDISubrange(const DISubrange *N, SmallVectorImpl<uint64_t> &Record,
302302
unsigned Abbrev);
303+
void writeDIGenericSubrange(const DIGenericSubrange *N,
304+
SmallVectorImpl<uint64_t> &Record,
305+
unsigned Abbrev);
303306
void writeDIEnumerator(const DIEnumerator *N,
304307
SmallVectorImpl<uint64_t> &Record, unsigned Abbrev);
305308
void writeDIBasicType(const DIBasicType *N, SmallVectorImpl<uint64_t> &Record,
@@ -1553,6 +1556,19 @@ void ModuleBitcodeWriter::writeDISubrange(const DISubrange *N,
15531556
Record.clear();
15541557
}
15551558

1559+
void ModuleBitcodeWriter::writeDIGenericSubrange(
1560+
const DIGenericSubrange *N, SmallVectorImpl<uint64_t> &Record,
1561+
unsigned Abbrev) {
1562+
Record.push_back((uint64_t)N->isDistinct());
1563+
Record.push_back(VE.getMetadataOrNullID(N->getRawCountNode()));
1564+
Record.push_back(VE.getMetadataOrNullID(N->getRawLowerBound()));
1565+
Record.push_back(VE.getMetadataOrNullID(N->getRawUpperBound()));
1566+
Record.push_back(VE.getMetadataOrNullID(N->getRawStride()));
1567+
1568+
Stream.EmitRecord(bitc::METADATA_GENERIC_SUBRANGE, Record, Abbrev);
1569+
Record.clear();
1570+
}
1571+
15561572
static void emitSignedInt64(SmallVectorImpl<uint64_t> &Vals, uint64_t V) {
15571573
if ((int64_t)V >= 0)
15581574
Vals.push_back(V << 1);

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,19 @@ static SmallVector<const DIVariable *, 2> dependencies(DbgVariable *Var) {
812812
if (auto ST = Subrange->getStride())
813813
if (auto *Dependency = ST.dyn_cast<DIVariable *>())
814814
Result.push_back(Dependency);
815+
} else if (auto *GenericSubrange = dyn_cast<DIGenericSubrange>(El)) {
816+
if (auto Count = GenericSubrange->getCount())
817+
if (auto *Dependency = Count.dyn_cast<DIVariable *>())
818+
Result.push_back(Dependency);
819+
if (auto LB = GenericSubrange->getLowerBound())
820+
if (auto *Dependency = LB.dyn_cast<DIVariable *>())
821+
Result.push_back(Dependency);
822+
if (auto UB = GenericSubrange->getUpperBound())
823+
if (auto *Dependency = UB.dyn_cast<DIVariable *>())
824+
Result.push_back(Dependency);
825+
if (auto ST = GenericSubrange->getStride())
826+
if (auto *Dependency = ST.dyn_cast<DIVariable *>())
827+
Result.push_back(Dependency);
815828
}
816829
}
817830
return Result;

llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,10 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
541541
assert(!isRegisterLocation());
542542
emitConstu(Op->getArg(0));
543543
break;
544+
case dwarf::DW_OP_consts:
545+
assert(!isRegisterLocation());
546+
emitSigned(Op->getArg(0));
547+
break;
544548
case dwarf::DW_OP_LLVM_convert: {
545549
unsigned BitSize = Op->getArg(0);
546550
dwarf::TypeKind Encoding = static_cast<dwarf::TypeKind>(Op->getArg(1));

llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp

+45-5
Original file line numberDiff line numberDiff line change
@@ -1357,7 +1357,7 @@ void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR,
13571357
if (auto *CI = SR->getCount().dyn_cast<ConstantInt*>())
13581358
Count = CI->getSExtValue();
13591359

1360-
auto addBoundTypeEntry = [&](dwarf::Attribute Attr,
1360+
auto AddBoundTypeEntry = [&](dwarf::Attribute Attr,
13611361
DISubrange::BoundType Bound) -> void {
13621362
if (auto *BV = Bound.dyn_cast<DIVariable *>()) {
13631363
if (auto *VarDIE = getDIE(BV))
@@ -1375,17 +1375,53 @@ void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR,
13751375
}
13761376
};
13771377

1378-
addBoundTypeEntry(dwarf::DW_AT_lower_bound, SR->getLowerBound());
1378+
AddBoundTypeEntry(dwarf::DW_AT_lower_bound, SR->getLowerBound());
13791379

13801380
if (auto *CV = SR->getCount().dyn_cast<DIVariable*>()) {
13811381
if (auto *CountVarDIE = getDIE(CV))
13821382
addDIEEntry(DW_Subrange, dwarf::DW_AT_count, *CountVarDIE);
13831383
} else if (Count != -1)
13841384
addUInt(DW_Subrange, dwarf::DW_AT_count, None, Count);
13851385

1386-
addBoundTypeEntry(dwarf::DW_AT_upper_bound, SR->getUpperBound());
1386+
AddBoundTypeEntry(dwarf::DW_AT_upper_bound, SR->getUpperBound());
13871387

1388-
addBoundTypeEntry(dwarf::DW_AT_byte_stride, SR->getStride());
1388+
AddBoundTypeEntry(dwarf::DW_AT_byte_stride, SR->getStride());
1389+
}
1390+
1391+
void DwarfUnit::constructGenericSubrangeDIE(DIE &Buffer,
1392+
const DIGenericSubrange *GSR,
1393+
DIE *IndexTy) {
1394+
DIE &DwGenericSubrange =
1395+
createAndAddDIE(dwarf::DW_TAG_generic_subrange, Buffer);
1396+
addDIEEntry(DwGenericSubrange, dwarf::DW_AT_type, *IndexTy);
1397+
1398+
int64_t DefaultLowerBound = getDefaultLowerBound();
1399+
1400+
auto AddBoundTypeEntry = [&](dwarf::Attribute Attr,
1401+
DIGenericSubrange::BoundType Bound) -> void {
1402+
if (auto *BV = Bound.dyn_cast<DIVariable *>()) {
1403+
if (auto *VarDIE = getDIE(BV))
1404+
addDIEEntry(DwGenericSubrange, Attr, *VarDIE);
1405+
} else if (auto *BE = Bound.dyn_cast<DIExpression *>()) {
1406+
if (BE->isSignedConstant()) {
1407+
if (Attr != dwarf::DW_AT_lower_bound || DefaultLowerBound == -1 ||
1408+
static_cast<int64_t>(BE->getElement(1)) != DefaultLowerBound)
1409+
addSInt(DwGenericSubrange, Attr, dwarf::DW_FORM_sdata,
1410+
BE->getElement(1));
1411+
} else {
1412+
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
1413+
DIEDwarfExpression DwarfExpr(*Asm, getCU(), *Loc);
1414+
DwarfExpr.setMemoryLocationKind();
1415+
DwarfExpr.addExpression(BE);
1416+
addBlock(DwGenericSubrange, Attr, DwarfExpr.finalize());
1417+
}
1418+
}
1419+
};
1420+
1421+
AddBoundTypeEntry(dwarf::DW_AT_lower_bound, GSR->getLowerBound());
1422+
AddBoundTypeEntry(dwarf::DW_AT_count, GSR->getCount());
1423+
AddBoundTypeEntry(dwarf::DW_AT_upper_bound, GSR->getUpperBound());
1424+
AddBoundTypeEntry(dwarf::DW_AT_byte_stride, GSR->getStride());
13891425
}
13901426

13911427
DIE *DwarfUnit::getIndexTyDie() {
@@ -1495,9 +1531,13 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
14951531
DINodeArray Elements = CTy->getElements();
14961532
for (unsigned i = 0, N = Elements.size(); i < N; ++i) {
14971533
// FIXME: Should this really be such a loose cast?
1498-
if (auto *Element = dyn_cast_or_null<DINode>(Elements[i]))
1534+
if (auto *Element = dyn_cast_or_null<DINode>(Elements[i])) {
14991535
if (Element->getTag() == dwarf::DW_TAG_subrange_type)
15001536
constructSubrangeDIE(Buffer, cast<DISubrange>(Element), IdxTy);
1537+
else if (Element->getTag() == dwarf::DW_TAG_generic_subrange)
1538+
constructGenericSubrangeDIE(Buffer, cast<DIGenericSubrange>(Element),
1539+
IdxTy);
1540+
}
15011541
}
15021542
}
15031543

llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h

+2
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,8 @@ class DwarfUnit : public DIEUnit {
301301
void constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy);
302302
void constructTypeDIE(DIE &Buffer, const DISubroutineType *CTy);
303303
void constructSubrangeDIE(DIE &Buffer, const DISubrange *SR, DIE *IndexTy);
304+
void constructGenericSubrangeDIE(DIE &Buffer, const DIGenericSubrange *SR,
305+
DIE *IndexTy);
304306
void constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy);
305307
void constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy);
306308
DIE &constructMemberDIE(DIE &Buffer, const DIDerivedType *DT);

llvm/lib/IR/AsmWriter.cpp

+51
Original file line numberDiff line numberDiff line change
@@ -1910,6 +1910,57 @@ static void writeDISubrange(raw_ostream &Out, const DISubrange *N,
19101910
Out << ")";
19111911
}
19121912

1913+
static void writeDIGenericSubrange(raw_ostream &Out, const DIGenericSubrange *N,
1914+
TypePrinting *TypePrinter,
1915+
SlotTracker *Machine,
1916+
const Module *Context) {
1917+
Out << "!DIGenericSubrange(";
1918+
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
1919+
1920+
auto IsConstant = [&](Metadata *Bound) -> bool {
1921+
if (auto *BE = dyn_cast_or_null<DIExpression>(Bound)) {
1922+
return BE->isSignedConstant();
1923+
}
1924+
return false;
1925+
};
1926+
1927+
auto GetConstant = [&](Metadata *Bound) -> int64_t {
1928+
assert(IsConstant(Bound) && "Expected constant");
1929+
auto *BE = dyn_cast_or_null<DIExpression>(Bound);
1930+
return static_cast<int64_t>(BE->getElement(1));
1931+
};
1932+
1933+
auto *Count = N->getRawCountNode();
1934+
if (IsConstant(Count))
1935+
Printer.printInt("count", GetConstant(Count),
1936+
/* ShouldSkipZero */ false);
1937+
else
1938+
Printer.printMetadata("count", Count, /*ShouldSkipNull */ true);
1939+
1940+
auto *LBound = N->getRawLowerBound();
1941+
if (IsConstant(LBound))
1942+
Printer.printInt("lowerBound", GetConstant(LBound),
1943+
/* ShouldSkipZero */ false);
1944+
else
1945+
Printer.printMetadata("lowerBound", LBound, /*ShouldSkipNull */ true);
1946+
1947+
auto *UBound = N->getRawUpperBound();
1948+
if (IsConstant(UBound))
1949+
Printer.printInt("upperBound", GetConstant(UBound),
1950+
/* ShouldSkipZero */ false);
1951+
else
1952+
Printer.printMetadata("upperBound", UBound, /*ShouldSkipNull */ true);
1953+
1954+
auto *Stride = N->getRawStride();
1955+
if (IsConstant(Stride))
1956+
Printer.printInt("stride", GetConstant(Stride),
1957+
/* ShouldSkipZero */ false);
1958+
else
1959+
Printer.printMetadata("stride", Stride, /*ShouldSkipNull */ true);
1960+
1961+
Out << ")";
1962+
}
1963+
19131964
static void writeDIEnumerator(raw_ostream &Out, const DIEnumerator *N,
19141965
TypePrinting *, SlotTracker *, const Module *) {
19151966
Out << "!DIEnumerator(";

0 commit comments

Comments
 (0)