Skip to content

Commit

Permalink
[DebugInfo] Upgrade DISubrange to support Fortran dynamic arrays
Browse files Browse the repository at this point in the history
This patch upgrades DISubrange to support fortran requirements.

Summary:
Below are the updates/addition of fields.
lowerBound - Now accepts signed integer or DIVariable or DIExpression,
earlier it accepted only signed integer.
upperBound - This field is now added and accepts signed interger or
DIVariable or DIExpression.
stride - This field is now added and accepts signed interger or
DIVariable or DIExpression.
This is required to describe bounds of array which are known at runtime.

Testing:
unit test cases added (hand-written)
check clang
check llvm
check debug-info

Reviewed By: aprantl

Differential Revision: https://reviews.llvm.org/D80197
  • Loading branch information
alokkrsharma authored and SouraVX committed May 28, 2020
1 parent 213c6cd commit d20bf5a
Show file tree
Hide file tree
Showing 34 changed files with 815 additions and 86 deletions.
43 changes: 34 additions & 9 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Expand Up @@ -2732,9 +2732,17 @@ llvm::DIType *CGDebugInfo::CreateType(const VectorType *Ty,
QualType QTy(Ty, 0);
auto SizeExpr = SizeExprCache.find(QTy);
if (SizeExpr != SizeExprCache.end())
Subscript = DBuilder.getOrCreateSubrange(0, SizeExpr->getSecond());
else
Subscript = DBuilder.getOrCreateSubrange(0, Count ? Count : -1);
Subscript = DBuilder.getOrCreateSubrange(
SizeExpr->getSecond() /*count*/, nullptr /*lowerBound*/,
nullptr /*upperBound*/, nullptr /*stride*/);
else {
auto *CountNode =
llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
llvm::Type::getInt64Ty(CGM.getLLVMContext()), Count ? Count : -1));
Subscript = DBuilder.getOrCreateSubrange(
CountNode /*count*/, nullptr /*lowerBound*/, nullptr /*upperBound*/,
nullptr /*stride*/);
}
llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscript);

uint64_t Size = CGM.getContext().getTypeSize(Ty);
Expand All @@ -2754,8 +2762,18 @@ llvm::DIType *CGDebugInfo::CreateType(const ConstantMatrixType *Ty,

// Create ranges for both dimensions.
llvm::SmallVector<llvm::Metadata *, 2> Subscripts;
Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Ty->getNumColumns()));
Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Ty->getNumRows()));
auto *ColumnCountNode =
llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
llvm::Type::getInt64Ty(CGM.getLLVMContext()), Ty->getNumColumns()));
auto *RowCountNode =
llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
llvm::Type::getInt64Ty(CGM.getLLVMContext()), Ty->getNumRows()));
Subscripts.push_back(DBuilder.getOrCreateSubrange(
ColumnCountNode /*count*/, nullptr /*lowerBound*/, nullptr /*upperBound*/,
nullptr /*stride*/));
Subscripts.push_back(DBuilder.getOrCreateSubrange(
RowCountNode /*count*/, nullptr /*lowerBound*/, nullptr /*upperBound*/,
nullptr /*stride*/));
llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscripts);
return DBuilder.createArrayType(Size, Align, ElementTy, SubscriptArray);
}
Expand Down Expand Up @@ -2810,10 +2828,17 @@ llvm::DIType *CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile *Unit) {

auto SizeNode = SizeExprCache.find(EltTy);
if (SizeNode != SizeExprCache.end())
Subscripts.push_back(
DBuilder.getOrCreateSubrange(0, SizeNode->getSecond()));
else
Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count));
Subscripts.push_back(DBuilder.getOrCreateSubrange(
SizeNode->getSecond() /*count*/, nullptr /*lowerBound*/,
nullptr /*upperBound*/, nullptr /*stride*/));
else {
auto *CountNode =
llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
llvm::Type::getInt64Ty(CGM.getLLVMContext()), Count));
Subscripts.push_back(DBuilder.getOrCreateSubrange(
CountNode /*count*/, nullptr /*lowerBound*/, nullptr /*upperBound*/,
nullptr /*stride*/));
}
EltTy = Ty->getElementType();
}

Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/IR/DIBuilder.h
Expand Up @@ -573,6 +573,8 @@ namespace llvm {
/// implicitly uniques the values returned.
DISubrange *getOrCreateSubrange(int64_t Lo, int64_t Count);
DISubrange *getOrCreateSubrange(int64_t Lo, Metadata *CountNode);
DISubrange *getOrCreateSubrange(Metadata *Count, Metadata *LowerBound,
Metadata *UpperBound, Metadata *Stride);

/// Create a new descriptor for the specified variable.
/// \param Context Variable scope.
Expand Down
42 changes: 26 additions & 16 deletions llvm/include/llvm/IR/DebugInfoMetadata.h
Expand Up @@ -287,12 +287,8 @@ class DISubrange : public DINode {
friend class LLVMContextImpl;
friend class MDNode;

int64_t LowerBound;

DISubrange(LLVMContext &C, StorageType Storage, Metadata *Node,
int64_t LowerBound, ArrayRef<Metadata *> Ops)
: DINode(C, DISubrangeKind, Storage, dwarf::DW_TAG_subrange_type, Ops),
LowerBound(LowerBound) {}
DISubrange(LLVMContext &C, StorageType Storage, ArrayRef<Metadata *> Ops)
: DINode(C, DISubrangeKind, Storage, dwarf::DW_TAG_subrange_type, Ops) {}

~DISubrange() = default;

Expand All @@ -304,8 +300,14 @@ class DISubrange : public DINode {
int64_t LowerBound, StorageType Storage,
bool ShouldCreate = true);

static DISubrange *getImpl(LLVMContext &Context, Metadata *CountNode,
Metadata *LowerBound, Metadata *UpperBound,
Metadata *Stride, StorageType Storage,
bool ShouldCreate = true);

TempDISubrange cloneImpl() const {
return getTemporary(getContext(), getRawCountNode(), getLowerBound());
return getTemporary(getContext(), getRawCountNode(), getRawLowerBound(),
getRawUpperBound(), getRawStride());
}

public:
Expand All @@ -315,25 +317,33 @@ class DISubrange : public DINode {
DEFINE_MDNODE_GET(DISubrange, (Metadata *CountNode, int64_t LowerBound = 0),
(CountNode, LowerBound))

TempDISubrange clone() const { return cloneImpl(); }
DEFINE_MDNODE_GET(DISubrange,
(Metadata * CountNode, Metadata *LowerBound,
Metadata *UpperBound, Metadata *Stride),
(CountNode, LowerBound, UpperBound, Stride))

int64_t getLowerBound() const { return LowerBound; }
TempDISubrange clone() const { return cloneImpl(); }

Metadata *getRawCountNode() const {
return getOperand(0).get();
}

Metadata *getRawLowerBound() const { return getOperand(1).get(); }

Metadata *getRawUpperBound() const { return getOperand(2).get(); }

Metadata *getRawStride() const { return getOperand(3).get(); }

typedef PointerUnion<ConstantInt*, DIVariable*> CountType;
typedef PointerUnion<ConstantInt *, DIVariable *, DIExpression *> BoundType;

CountType getCount() const {
if (auto *MD = dyn_cast<ConstantAsMetadata>(getRawCountNode()))
return CountType(cast<ConstantInt>(MD->getValue()));
CountType getCount() const;

if (auto *DV = dyn_cast<DIVariable>(getRawCountNode()))
return CountType(DV);
BoundType getLowerBound() const;

return CountType();
}
BoundType getUpperBound() const;

BoundType getStride() const;

static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DISubrangeKind;
Expand Down
36 changes: 28 additions & 8 deletions llvm/lib/AsmParser/LLParser.cpp
Expand Up @@ -4500,21 +4500,41 @@ bool LLParser::ParseGenericDINode(MDNode *&Result, bool IsDistinct) {
/// ParseDISubrange:
/// ::= !DISubrange(count: 30, lowerBound: 2)
/// ::= !DISubrange(count: !node, lowerBound: 2)
/// ::= !DISubrange(lowerBound: !node1, upperBound: !node2, stride: !node3)
bool LLParser::ParseDISubrange(MDNode *&Result, bool IsDistinct) {
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
REQUIRED(count, MDSignedOrMDField, (-1, -1, INT64_MAX, false)); \
OPTIONAL(lowerBound, MDSignedField, );
OPTIONAL(count, MDSignedOrMDField, (-1, -1, INT64_MAX, false)); \
OPTIONAL(lowerBound, MDSignedOrMDField, ); \
OPTIONAL(upperBound, MDSignedOrMDField, ); \
OPTIONAL(stride, MDSignedOrMDField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS

Metadata *Count = nullptr;
Metadata *LowerBound = nullptr;
Metadata *UpperBound = nullptr;
Metadata *Stride = nullptr;
if (count.isMDSignedField())
Result = GET_OR_DISTINCT(
DISubrange, (Context, count.getMDSignedValue(), lowerBound.Val));
Count = ConstantAsMetadata::get(ConstantInt::getSigned(
Type::getInt64Ty(Context), count.getMDSignedValue()));
else if (count.isMDField())
Result = GET_OR_DISTINCT(
DISubrange, (Context, count.getMDFieldValue(), lowerBound.Val));
else
return true;
Count = count.getMDFieldValue();

auto convToMetadata = [&](MDSignedOrMDField Bound) -> Metadata * {
if (Bound.isMDSignedField())
return ConstantAsMetadata::get(ConstantInt::getSigned(
Type::getInt64Ty(Context), Bound.getMDSignedValue()));
if (Bound.isMDField())
return Bound.getMDFieldValue();
return nullptr;
};

LowerBound = convToMetadata(lowerBound);
UpperBound = convToMetadata(upperBound);
Stride = convToMetadata(stride);

Result = GET_OR_DISTINCT(DISubrange,
(Context, Count, LowerBound, UpperBound, Stride));

return false;
}
Expand Down
14 changes: 12 additions & 2 deletions llvm/lib/Bitcode/Reader/MetadataLoader.cpp
Expand Up @@ -1258,14 +1258,24 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
// Operand 'count' is interpreted as:
// - Signed integer (version 0)
// - Metadata node (version 1)
// Operand 'lowerBound' is interpreted as:
// - Signed integer (version 0 and 1)
// - Metadata node (version 2)
// Operands 'upperBound' and 'stride' are interpreted as:
// - Metadata node (version 2)
switch (Record[0] >> 1) {
case 0:
Val = GET_OR_DISTINCT(DISubrange,
(Context, Record[1], unrotateSign(Record.back())));
(Context, Record[1], unrotateSign(Record[2])));
break;
case 1:
Val = GET_OR_DISTINCT(DISubrange, (Context, getMDOrNull(Record[1]),
unrotateSign(Record.back())));
unrotateSign(Record[2])));
break;
case 2:
Val = GET_OR_DISTINCT(
DISubrange, (Context, getMDOrNull(Record[1]), getMDOrNull(Record[2]),
getMDOrNull(Record[3]), getMDOrNull(Record[4])));
break;
default:
return error("Invalid record: Unsupported version of DISubrange");
Expand Down
6 changes: 4 additions & 2 deletions llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
Expand Up @@ -1527,10 +1527,12 @@ static uint64_t rotateSign(int64_t I) {
void ModuleBitcodeWriter::writeDISubrange(const DISubrange *N,
SmallVectorImpl<uint64_t> &Record,
unsigned Abbrev) {
const uint64_t Version = 1 << 1;
const uint64_t Version = 2 << 1;
Record.push_back((uint64_t)N->isDistinct() | Version);
Record.push_back(VE.getMetadataOrNullID(N->getRawCountNode()));
Record.push_back(rotateSign(N->getLowerBound()));
Record.push_back(VE.getMetadataOrNullID(N->getRawLowerBound()));
Record.push_back(VE.getMetadataOrNullID(N->getRawUpperBound()));
Record.push_back(VE.getMetadataOrNullID(N->getRawStride()));

Stream.EmitRecord(bitc::METADATA_SUBRANGE, Record, Abbrev);
Record.clear();
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
Expand Up @@ -1592,7 +1592,7 @@ TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) {
assert(Element->getTag() == dwarf::DW_TAG_subrange_type);

const DISubrange *Subrange = cast<DISubrange>(Element);
assert(Subrange->getLowerBound() == 0 &&
assert(!Subrange->getRawLowerBound() &&
"codeview doesn't support subranges with lower bounds");
int64_t Count = -1;
if (auto *CI = Subrange->getCount().dyn_cast<ConstantInt*>())
Expand Down
15 changes: 12 additions & 3 deletions llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
Expand Up @@ -768,9 +768,18 @@ static SmallVector<const DIVariable *, 2> dependencies(DbgVariable *Var) {
Result.push_back(DLVar);
for (auto *El : Array->getElements()) {
if (auto *Subrange = dyn_cast<DISubrange>(El)) {
auto Count = Subrange->getCount();
if (auto *Dependency = Count.dyn_cast<DIVariable *>())
Result.push_back(Dependency);
if (auto Count = Subrange->getCount())
if (auto *Dependency = Count.dyn_cast<DIVariable *>())
Result.push_back(Dependency);
if (auto LB = Subrange->getLowerBound())
if (auto *Dependency = LB.dyn_cast<DIVariable *>())
Result.push_back(Dependency);
if (auto UB = Subrange->getUpperBound())
if (auto *Dependency = UB.dyn_cast<DIVariable *>())
Result.push_back(Dependency);
if (auto ST = Subrange->getStride())
if (auto *Dependency = ST.dyn_cast<DIVariable *>())
Result.push_back(Dependency);
}
}
return Result;
Expand Down
26 changes: 23 additions & 3 deletions llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
Expand Up @@ -1349,20 +1349,40 @@ void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR,
// C/C++. The Count value is the number of elements. Values are 64 bit. If
// Count == -1 then the array is unbounded and we do not emit
// DW_AT_lower_bound and DW_AT_count attributes.
int64_t LowerBound = SR->getLowerBound();
int64_t DefaultLowerBound = getDefaultLowerBound();
int64_t Count = -1;
if (auto *CI = SR->getCount().dyn_cast<ConstantInt*>())
Count = CI->getSExtValue();

if (DefaultLowerBound == -1 || LowerBound != DefaultLowerBound)
addUInt(DW_Subrange, dwarf::DW_AT_lower_bound, None, LowerBound);
auto addBoundTypeEntry = [&](dwarf::Attribute Attr,
DISubrange::BoundType Bound) -> void {
if (auto *BV = Bound.dyn_cast<DIVariable *>()) {
if (auto *VarDIE = getDIE(BV))
addDIEEntry(DW_Subrange, Attr, *VarDIE);
} else if (auto *BE = Bound.dyn_cast<DIExpression *>()) {
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
DIEDwarfExpression DwarfExpr(*Asm, getCU(), *Loc);
DwarfExpr.setMemoryLocationKind();
DwarfExpr.addExpression(BE);
addBlock(DW_Subrange, Attr, DwarfExpr.finalize());
} else if (auto *BI = Bound.dyn_cast<ConstantInt *>()) {
if (Attr != dwarf::DW_AT_lower_bound || DefaultLowerBound == -1 ||
BI->getSExtValue() != DefaultLowerBound)
addSInt(DW_Subrange, Attr, dwarf::DW_FORM_sdata, BI->getSExtValue());
}
};

addBoundTypeEntry(dwarf::DW_AT_lower_bound, SR->getLowerBound());

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

addBoundTypeEntry(dwarf::DW_AT_upper_bound, SR->getUpperBound());

addBoundTypeEntry(dwarf::DW_AT_byte_stride, SR->getStride());
}

DIE *DwarfUnit::getIndexTyDie() {
Expand Down
31 changes: 28 additions & 3 deletions llvm/lib/IR/AsmWriter.cpp
Expand Up @@ -1858,9 +1858,34 @@ static void writeDISubrange(raw_ostream &Out, const DISubrange *N,
if (auto *CE = N->getCount().dyn_cast<ConstantInt*>())
Printer.printInt("count", CE->getSExtValue(), /* ShouldSkipZero */ false);
else
Printer.printMetadata("count", N->getCount().dyn_cast<DIVariable*>(),
/*ShouldSkipNull */ false);
Printer.printInt("lowerBound", N->getLowerBound());
Printer.printMetadata("count", N->getCount().dyn_cast<DIVariable *>(),
/*ShouldSkipNull */ true);

// A lowerBound of constant 0 should not be skipped, since it is different
// from an unspecified lower bound (= nullptr).
auto *LBound = N->getRawLowerBound();
if (auto *LE = dyn_cast_or_null<ConstantAsMetadata>(LBound)) {
auto *LV = cast<ConstantInt>(LE->getValue());
Printer.printInt("lowerBound", LV->getSExtValue(),
/* ShouldSkipZero */ false);
} else
Printer.printMetadata("lowerBound", LBound, /*ShouldSkipNull */ true);

auto *UBound = N->getRawUpperBound();
if (auto *UE = dyn_cast_or_null<ConstantAsMetadata>(UBound)) {
auto *UV = cast<ConstantInt>(UE->getValue());
Printer.printInt("upperBound", UV->getSExtValue(),
/* ShouldSkipZero */ false);
} else
Printer.printMetadata("upperBound", UBound, /*ShouldSkipNull */ true);

auto *Stride = N->getRawStride();
if (auto *SE = dyn_cast_or_null<ConstantAsMetadata>(Stride)) {
auto *SV = cast<ConstantInt>(SE->getValue());
Printer.printInt("stride", SV->getSExtValue(), /* ShouldSkipZero */ false);
} else
Printer.printMetadata("stride", Stride, /*ShouldSkipNull */ true);

Out << ")";
}

Expand Down
15 changes: 13 additions & 2 deletions llvm/lib/IR/DIBuilder.cpp
Expand Up @@ -625,11 +625,22 @@ DITypeRefArray DIBuilder::getOrCreateTypeArray(ArrayRef<Metadata *> Elements) {
}

DISubrange *DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Count) {
return DISubrange::get(VMContext, Count, Lo);
auto *LB = ConstantAsMetadata::get(
ConstantInt::getSigned(Type::getInt64Ty(VMContext), Lo));
auto *CountNode = ConstantAsMetadata::get(
ConstantInt::getSigned(Type::getInt64Ty(VMContext), Count));
return DISubrange::get(VMContext, CountNode, LB, nullptr, nullptr);
}

DISubrange *DIBuilder::getOrCreateSubrange(int64_t Lo, Metadata *CountNode) {
return DISubrange::get(VMContext, CountNode, Lo);
auto *LB = ConstantAsMetadata::get(
ConstantInt::getSigned(Type::getInt64Ty(VMContext), Lo));
return DISubrange::get(VMContext, CountNode, LB, nullptr, nullptr);
}

DISubrange *DIBuilder::getOrCreateSubrange(Metadata *CountNode, Metadata *LB,
Metadata *UB, Metadata *Stride) {
return DISubrange::get(VMContext, CountNode, LB, UB, Stride);
}

static void checkGlobalVariableScope(DIScope *Context) {
Expand Down

0 comments on commit d20bf5a

Please sign in to comment.