Skip to content

Commit

Permalink
Refactor the DIExpression fragment query interface (NFC)
Browse files Browse the repository at this point in the history
... so it becomes available to DIExpressionCursor.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@290322 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
adrian-prantl committed Dec 22, 2016
1 parent 27bb0f0 commit f53a7ab
Show file tree
Hide file tree
Showing 11 changed files with 59 additions and 50 deletions.
27 changes: 18 additions & 9 deletions include/llvm/IR/DebugInfoMetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -1973,15 +1973,6 @@ class DIExpression : public MDNode {
return Elements[I];
}

/// Return whether this is a piece of an aggregate variable.
bool isFragment() const;

/// Return the offset of this fragment in bits.
uint64_t getFragmentOffsetInBits() const;

/// Return the size of this fragment in bits.
uint64_t getFragmentSizeInBits() const;

/// Determine whether this represents a standalone constant value.
bool isConstant() const;

Expand Down Expand Up @@ -2085,6 +2076,24 @@ class DIExpression : public MDNode {
bool startsWithDeref() const {
return getNumElements() > 0 && getElement(0) == dwarf::DW_OP_deref;
}

/// Holds the characteristics of one fragment of a larger variable.
struct FragmentInfo {
uint64_t SizeInBits;
uint64_t OffsetInBits;
};

/// Retrieve the details of this fragment expression.
static Optional<FragmentInfo> getFragmentInfo(expr_op_iterator Start,
expr_op_iterator End);

/// Retrieve the details of this fragment expression.
Optional<FragmentInfo> getFragmentInfo() const {
return getFragmentInfo(expr_op_begin(), expr_op_end());
}

/// Return whether this is a piece of an aggregate variable.
bool isFragment() const { return getFragmentInfo().hasValue(); }
};

/// Global variables.
Expand Down
7 changes: 4 additions & 3 deletions lib/CodeGen/AsmPrinter/AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -713,9 +713,10 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
OS << V->getName();

const DIExpression *Expr = MI->getDebugExpression();
if (Expr->isFragment())
OS << " [fragment offset=" << Expr->getFragmentOffsetInBits()
<< " size=" << Expr->getFragmentSizeInBits() << "]";
auto Fragment = Expr->getFragmentInfo();
if (Fragment)
OS << " [fragment offset=" << Fragment->OffsetInBits
<< " size=" << Fragment->SizeInBits << "]";
OS << " <- ";

// The second operand is only an offset if it's an immediate.
Expand Down
5 changes: 3 additions & 2 deletions lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -944,9 +944,10 @@ void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {
unsigned StructOffset = 0;

// Handle fragments.
if (DIExpr && DIExpr->isFragment()) {
auto Fragment = DIExpr->getFragmentInfo();
if (DIExpr && Fragment) {
IsSubfield = true;
StructOffset = DIExpr->getFragmentOffsetInBits() / 8;
StructOffset = Fragment->OffsetInBits / 8;
} else if (DIExpr && DIExpr->getNumElements() > 0) {
continue; // Ignore unrecognized exprs.
}
Expand Down
10 changes: 6 additions & 4 deletions lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,12 @@ MCSymbol *DebugHandlerBase::getLabelAfterInsn(const MachineInstr *MI) {

int DebugHandlerBase::fragmentCmp(const DIExpression *P1,
const DIExpression *P2) {
unsigned l1 = P1->getFragmentOffsetInBits();
unsigned l2 = P2->getFragmentOffsetInBits();
unsigned r1 = l1 + P1->getFragmentSizeInBits();
unsigned r2 = l2 + P2->getFragmentSizeInBits();
auto Fragment1 = *P1->getFragmentInfo();
auto Fragment2 = *P2->getFragmentInfo();
unsigned l1 = Fragment1.OffsetInBits;
unsigned l2 = Fragment2.OffsetInBits;
unsigned r1 = l1 + Fragment1.SizeInBits;
unsigned r2 = l2 + Fragment2.SizeInBits;
if (r1 <= l2)
return -1;
else if (r2 <= l1)
Expand Down
4 changes: 2 additions & 2 deletions lib/CodeGen/AsmPrinter/DebugLocEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,8 @@ inline bool operator==(const DebugLocEntry::Value &A,
/// Compare two fragments based on their offset.
inline bool operator<(const DebugLocEntry::Value &A,
const DebugLocEntry::Value &B) {
return A.getExpression()->getFragmentOffsetInBits() <
B.getExpression()->getFragmentOffsetInBits();
return A.getExpression()->getFragmentInfo()->OffsetInBits <
B.getExpression()->getFragmentInfo()->OffsetInBits;
}

}
Expand Down
10 changes: 6 additions & 4 deletions lib/CodeGen/AsmPrinter/DwarfDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,10 +469,12 @@ static SmallVectorImpl<DwarfCompileUnit::GlobalExpr> &
sortGlobalExprs(SmallVectorImpl<DwarfCompileUnit::GlobalExpr> &GVEs) {
std::sort(GVEs.begin(), GVEs.end(),
[](DwarfCompileUnit::GlobalExpr A, DwarfCompileUnit::GlobalExpr B) {
if (A.Expr != B.Expr && A.Expr && B.Expr &&
A.Expr->isFragment() && B.Expr->isFragment())
return A.Expr->getFragmentOffsetInBits() <
B.Expr->getFragmentOffsetInBits();
if (A.Expr != B.Expr && A.Expr && B.Expr) {
auto FragmentA = A.Expr->getFragmentInfo();
auto FragmentB = B.Expr->getFragmentInfo();
if (FragmentA && FragmentB)
return FragmentA->OffsetInBits < FragmentB->OffsetInBits;
}
return false;
});
GVEs.erase(std::unique(GVEs.begin(), GVEs.end(),
Expand Down
2 changes: 1 addition & 1 deletion lib/CodeGen/AsmPrinter/DwarfExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ void DwarfExpression::addFragmentOffset(const DIExpression *Expr) {
if (!Expr || !Expr->isFragment())
return;

uint64_t FragmentOffset = Expr->getFragmentOffsetInBits();
uint64_t FragmentOffset = Expr->getFragmentInfo()->OffsetInBits;
assert(FragmentOffset >= OffsetInBits &&
"overlapping or duplicate fragments");
if (FragmentOffset > OffsetInBits)
Expand Down
24 changes: 8 additions & 16 deletions lib/IR/DebugInfoMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -601,22 +601,14 @@ bool DIExpression::isValid() const {
return true;
}

bool DIExpression::isFragment() const {
assert(isValid() && "Expected valid expression");
if (unsigned N = getNumElements())
if (N >= 3)
return getElement(N - 3) == dwarf::DW_OP_LLVM_fragment;
return false;
}

uint64_t DIExpression::getFragmentOffsetInBits() const {
assert(isFragment() && "Expected fragment");
return getElement(getNumElements() - 2);
}

uint64_t DIExpression::getFragmentSizeInBits() const {
assert(isFragment() && "Expected fragment");
return getElement(getNumElements() - 1);
Optional<DIExpression::FragmentInfo>
DIExpression::getFragmentInfo(expr_op_iterator Start, expr_op_iterator End) {
for (auto I = Start; I != End; ++I)
if (I->getOp() == dwarf::DW_OP_LLVM_fragment) {
DIExpression::FragmentInfo Info = {I->getArg(1), I->getArg(0)};
return Info;
}
return None;
}

bool DIExpression::isConstant() const {
Expand Down
7 changes: 4 additions & 3 deletions lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4344,7 +4344,8 @@ void Verifier::verifyFragmentExpression(const DbgInfoIntrinsic &I) {
return;

// Nothing to do if this isn't a bit piece expression.
if (!E->isFragment())
auto Fragment = E->getFragmentInfo();
if (!Fragment)
return;

// The frontend helps out GDB by emitting the members of local anonymous
Expand All @@ -4362,8 +4363,8 @@ void Verifier::verifyFragmentExpression(const DbgInfoIntrinsic &I) {
if (!VarSize)
return;

unsigned FragSize = E->getFragmentSizeInBits();
unsigned FragOffset = E->getFragmentOffsetInBits();
unsigned FragSize = Fragment->SizeInBits;
unsigned FragOffset = Fragment->OffsetInBits;
AssertDI(FragSize + FragOffset <= VarSize,
"fragment is larger than or outside of variable", &I, V, E);
AssertDI(FragSize != VarSize, "fragment covers entire variable", &I, V, E);
Expand Down
8 changes: 4 additions & 4 deletions lib/Transforms/Scalar/SROA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4026,13 +4026,13 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
if (Fragment.Size < AllocaSize || Expr->isFragment()) {
// If this alloca is already a scalar replacement of a larger aggregate,
// Fragment.Offset describes the offset inside the scalar.
uint64_t Offset =
Expr->isFragment() ? Expr->getFragmentOffsetInBits() : 0;
auto ExprFragment = Expr->getFragmentInfo();
uint64_t Offset = ExprFragment ? ExprFragment->OffsetInBits : 0;
uint64_t Start = Offset + Fragment.Offset;
uint64_t Size = Fragment.Size;
if (Expr->isFragment()) {
if (ExprFragment) {
uint64_t AbsEnd =
Expr->getFragmentOffsetInBits() + Expr->getFragmentSizeInBits();
ExprFragment->OffsetInBits + ExprFragment->SizeInBits;
if (Start >= AbsEnd)
// No need to describe a SROAed padding.
continue;
Expand Down
5 changes: 3 additions & 2 deletions lib/Transforms/Utils/Local.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1112,9 +1112,10 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
unsigned FragmentOffset = 0;
// If this already is a bit fragment, we drop the bit fragment from the
// expression and record the offset.
if (DIExpr->isFragment()) {
auto Fragment = DIExpr->getFragmentInfo();
if (Fragment) {
Ops.append(DIExpr->elements_begin(), DIExpr->elements_end()-3);
FragmentOffset = DIExpr->getFragmentOffsetInBits();
FragmentOffset = Fragment->OffsetInBits;
} else {
Ops.append(DIExpr->elements_begin(), DIExpr->elements_end());
}
Expand Down

0 comments on commit f53a7ab

Please sign in to comment.