1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

[DebugInfo] Upgrade DISubragne::count to accept DIExpression also

This is needed for Fortran assumed shape arrays whose dimensions are
defined as,
  - 'count' is taken from array descriptor passed as parameter by
    caller, access from descriptor is defined by type DIExpression.
  - 'lowerBound' is defined by callee.
The current alternate way represents using upperBound in place of
count, where upperBound is calculated in callee in a temp variable
using lowerBound and count

Representation with count (DIExpression) is not only clearer as
compared to upperBound (DIVariable) but it has another advantage that
variable count is accessed by being parameter has better chance of
survival at higher optimization level than upperBound being local
variable.

Reviewed By: aprantl

Differential Revision: https://reviews.llvm.org/D99335
This commit is contained in:
Alok Kumar Sharma 2021-03-25 16:34:57 +05:30
parent 0e8cd3ced4
commit 298016b1b1
8 changed files with 79 additions and 33 deletions

View File

@ -335,10 +335,9 @@ public:
Metadata *getRawStride() const { return getOperand(3).get(); } Metadata *getRawStride() const { return getOperand(3).get(); }
typedef PointerUnion<ConstantInt*, DIVariable*> CountType;
typedef PointerUnion<ConstantInt *, DIVariable *, DIExpression *> BoundType; typedef PointerUnion<ConstantInt *, DIVariable *, DIExpression *> BoundType;
CountType getCount() const; BoundType getCount() const;
BoundType getLowerBound() const; BoundType getLowerBound() const;

View File

@ -4716,11 +4716,6 @@ bool LLParser::parseDISubrange(MDNode *&Result, bool IsDistinct) {
Metadata *LowerBound = nullptr; Metadata *LowerBound = nullptr;
Metadata *UpperBound = nullptr; Metadata *UpperBound = nullptr;
Metadata *Stride = nullptr; Metadata *Stride = nullptr;
if (count.isMDSignedField())
Count = ConstantAsMetadata::get(ConstantInt::getSigned(
Type::getInt64Ty(Context), count.getMDSignedValue()));
else if (count.isMDField())
Count = count.getMDFieldValue();
auto convToMetadata = [&](MDSignedOrMDField Bound) -> Metadata * { auto convToMetadata = [&](MDSignedOrMDField Bound) -> Metadata * {
if (Bound.isMDSignedField()) if (Bound.isMDSignedField())
@ -4731,6 +4726,7 @@ bool LLParser::parseDISubrange(MDNode *&Result, bool IsDistinct) {
return nullptr; return nullptr;
}; };
Count = convToMetadata(count);
LowerBound = convToMetadata(lowerBound); LowerBound = convToMetadata(lowerBound);
UpperBound = convToMetadata(upperBound); UpperBound = convToMetadata(upperBound);
Stride = convToMetadata(stride); Stride = convToMetadata(stride);

View File

@ -1313,9 +1313,6 @@ void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR,
// Count == -1 then the array is unbounded and we do not emit // Count == -1 then the array is unbounded and we do not emit
// DW_AT_lower_bound and DW_AT_count attributes. // DW_AT_lower_bound and DW_AT_count attributes.
int64_t DefaultLowerBound = getDefaultLowerBound(); int64_t DefaultLowerBound = getDefaultLowerBound();
int64_t Count = -1;
if (auto *CI = SR->getCount().dyn_cast<ConstantInt*>())
Count = CI->getSExtValue();
auto AddBoundTypeEntry = [&](dwarf::Attribute Attr, auto AddBoundTypeEntry = [&](dwarf::Attribute Attr,
DISubrange::BoundType Bound) -> void { DISubrange::BoundType Bound) -> void {
@ -1329,19 +1326,18 @@ void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR,
DwarfExpr.addExpression(BE); DwarfExpr.addExpression(BE);
addBlock(DW_Subrange, Attr, DwarfExpr.finalize()); addBlock(DW_Subrange, Attr, DwarfExpr.finalize());
} else if (auto *BI = Bound.dyn_cast<ConstantInt *>()) { } else if (auto *BI = Bound.dyn_cast<ConstantInt *>()) {
if (Attr != dwarf::DW_AT_lower_bound || DefaultLowerBound == -1 || if (Attr == dwarf::DW_AT_count) {
BI->getSExtValue() != DefaultLowerBound) if (BI->getSExtValue() != -1)
addUInt(DW_Subrange, Attr, None, BI->getSExtValue());
} else if (Attr != dwarf::DW_AT_lower_bound || DefaultLowerBound == -1 ||
BI->getSExtValue() != DefaultLowerBound)
addSInt(DW_Subrange, Attr, dwarf::DW_FORM_sdata, BI->getSExtValue()); addSInt(DW_Subrange, Attr, dwarf::DW_FORM_sdata, BI->getSExtValue());
} }
}; };
AddBoundTypeEntry(dwarf::DW_AT_lower_bound, SR->getLowerBound()); AddBoundTypeEntry(dwarf::DW_AT_lower_bound, SR->getLowerBound());
if (auto *CV = SR->getCount().dyn_cast<DIVariable*>()) { AddBoundTypeEntry(dwarf::DW_AT_count, SR->getCount());
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_upper_bound, SR->getUpperBound());

View File

@ -1889,11 +1889,14 @@ static void writeDISubrange(raw_ostream &Out, const DISubrange *N,
const Module *Context) { const Module *Context) {
Out << "!DISubrange("; Out << "!DISubrange(";
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
if (auto *CE = N->getCount().dyn_cast<ConstantInt*>())
Printer.printInt("count", CE->getSExtValue(), /* ShouldSkipZero */ false); auto *Count = N->getRawCountNode();
else if (auto *CE = dyn_cast_or_null<ConstantAsMetadata>(Count)) {
Printer.printMetadata("count", N->getCount().dyn_cast<DIVariable *>(), auto *CV = cast<ConstantInt>(CE->getValue());
/*ShouldSkipNull */ true); Printer.printInt("count", CV->getSExtValue(),
/* ShouldSkipZero */ false);
} else
Printer.printMetadata("count", Count, /*ShouldSkipNull */ true);
// A lowerBound of constant 0 should not be skipped, since it is different // A lowerBound of constant 0 should not be skipped, since it is different
// from an unspecified lower bound (= nullptr). // from an unspecified lower bound (= nullptr).

View File

@ -359,17 +359,25 @@ DISubrange *DISubrange::getImpl(LLVMContext &Context, Metadata *CountNode,
DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DISubrange, Ops); DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DISubrange, Ops);
} }
DISubrange::CountType DISubrange::getCount() const { DISubrange::BoundType DISubrange::getCount() const {
if (!getRawCountNode()) Metadata *CB = getRawCountNode();
return CountType(); if (!CB)
return BoundType();
if (auto *MD = dyn_cast<ConstantAsMetadata>(getRawCountNode())) assert((isa<ConstantAsMetadata>(CB) || isa<DIVariable>(CB) ||
return CountType(cast<ConstantInt>(MD->getValue())); isa<DIExpression>(CB)) &&
"Count must be signed constant or DIVariable or DIExpression");
if (auto *DV = dyn_cast<DIVariable>(getRawCountNode())) if (auto *MD = dyn_cast<ConstantAsMetadata>(CB))
return CountType(DV); return BoundType(cast<ConstantInt>(MD->getValue()));
return CountType(); if (auto *MD = dyn_cast<DIVariable>(CB))
return BoundType(MD);
if (auto *MD = dyn_cast<DIExpression>(CB))
return BoundType(MD);
return BoundType();
} }
DISubrange::BoundType DISubrange::getLowerBound() const { DISubrange::BoundType DISubrange::getLowerBound() const {

View File

@ -922,8 +922,10 @@ void Verifier::visitDISubrange(const DISubrange &N) {
"Subrange must contain count or upperBound", &N); "Subrange must contain count or upperBound", &N);
AssertDI(!N.getRawCountNode() || !N.getRawUpperBound(), AssertDI(!N.getRawCountNode() || !N.getRawUpperBound(),
"Subrange can have any one of count or upperBound", &N); "Subrange can have any one of count or upperBound", &N);
AssertDI(!N.getRawCountNode() || N.getCount(), auto *CBound = N.getRawCountNode();
"Count must either be a signed constant or a DIVariable", &N); AssertDI(!CBound || isa<ConstantAsMetadata>(CBound) ||
isa<DIVariable>(CBound) || isa<DIExpression>(CBound),
"Count must be signed constant or DIVariable or DIExpression", &N);
auto Count = N.getCount(); auto Count = N.getCount();
AssertDI(!Count || !Count.is<ConstantInt *>() || AssertDI(!Count || !Count.is<ConstantInt *>() ||
Count.get<ConstantInt *>()->getSExtValue() >= -1, Count.get<ConstantInt *>()->getSExtValue() >= -1,

View File

@ -0,0 +1,42 @@
;; This test checks DISubrange count bound for DIExpression
; REQUIRES: x86_64-linux
; RUN: %llc_dwarf %s -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s
;; Test whether bounds are generated correctly.
; CHECK-LABEL: DW_TAG_array_type
; CHECK: DW_TAG_subrange_type
; CHECK: DW_AT_lower_bound (DW_OP_push_object_address, DW_OP_plus_uconst 0x50, DW_OP_deref)
; CHECK-NEXT: DW_AT_count (DW_OP_push_object_address, DW_OP_plus_uconst 0x58, DW_OP_deref)
; ModuleID = 'fortsubrange.modified.strategy3check-in.ll'
source_filename = "fortsubrange.ll"
define void @MAIN_() !dbg !5 {
L.entry:
%"arr$sd1_349" = alloca [16 x i64], align 8
call void @llvm.dbg.declare(metadata [16 x i64]* %"arr$sd1_349", metadata !8, metadata !DIExpression()), !dbg !13
ret void, !dbg !14
}
; Function Attrs: nounwind readnone speculatable willreturn
declare void @llvm.dbg.declare(metadata, metadata, metadata)
!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}
!0 = !{i32 2, !"Dwarf Version", i32 4}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !4, globals: !4, imports: !4)
!3 = !DIFile(filename: "fortsubrange.f90", directory: "/dir")
!4 = !{}
!5 = distinct !DISubprogram(name: "main", scope: !2, file: !3, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2)
!6 = !DISubroutineType(cc: DW_CC_program, types: !7)
!7 = !{null}
!8 = !DILocalVariable(name: "arr", scope: !5, file: !3, type: !9)
!9 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 32, align: 32, elements: !11)
!10 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed)
!11 = !{!12}
!12 = !DISubrange(count: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 88, DW_OP_deref), lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 80, DW_OP_deref))
!13 = !DILocation(line: 0, scope: !5)
!14 = !DILocation(line: 6, column: 1, scope: !5)

View File

@ -33,5 +33,5 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
!19 = !DILocalVariable(name: "vla", scope: !7, file: !1, line: 21, type: !20) !19 = !DILocalVariable(name: "vla", scope: !7, file: !1, line: 21, type: !20)
!20 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, align: 32, elements: !21) !20 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, align: 32, elements: !21)
!21 = !{!22} !21 = !{!22}
; CHECK: Count must either be a signed constant or a DIVariable ; CHECK: Count must be signed constant or DIVariable or DIExpression
!22 = !DISubrange(count: !17) !22 = !DISubrange(count: !17)