///
/// \param OffsetInBits Offset of the piece in bits.
/// \param SizeInBits Size of the piece in bits.
- DIExpression *createBitPieceExpression(unsigned OffsetInBits,
+ DIExpression *createFragmentExpression(unsigned OffsetInBits,
unsigned SizeInBits);
/// Create an expression for a variable that does not have an address, but
}
/// Return whether this is a piece of an aggregate variable.
- bool isBitPiece() const;
+ bool isFragment() const;
- /// Return the offset of this piece in bits.
- uint64_t getBitPieceOffset() const;
+ /// Return the offset of this fragment in bits.
+ uint64_t getFragmentOffsetInBits() const;
- /// Return the size of this piece in bits.
- uint64_t getBitPieceSize() const;
+ /// Return the size of this fragment in bits.
+ uint64_t getFragmentSizeInBits() const;
typedef ArrayRef<uint64_t>::iterator element_iterator;
element_iterator elements_begin() const { return getElements().begin(); }
#define HANDLE_DW_OP(ID, NAME) DW_OP_##NAME = ID,
#include "llvm/Support/Dwarf.def"
DW_OP_lo_user = 0xe0,
- DW_OP_hi_user = 0xff
+ DW_OP_hi_user = 0xff,
+ DW_OP_LLVM_fragment = 0x1000 ///< Only used in LLVM metadata.
};
enum TypeKind {
if (Record.size() < 1)
return error("Invalid record");
- IsDistinct = Record[0];
+ IsDistinct = Record[0] & 1;
+ bool HasOpFragment = Record[0] & 2;
+ auto Elts = MutableArrayRef<uint64_t>(Record).slice(1);
+ if (!HasOpFragment)
+ if (unsigned N = Elts.size())
+ if (N >= 3 && Elts[N - 3] == dwarf::DW_OP_bit_piece)
+ Elts[N-3] = dwarf::DW_OP_LLVM_fragment;
+
MetadataList.assignValue(
GET_OR_DISTINCT(DIExpression,
(Context, makeArrayRef(Record).slice(1))),
unsigned Abbrev) {
Record.reserve(N->getElements().size() + 1);
- Record.push_back(N->isDistinct());
+ const uint64_t HasOpFragmentFlag = 1 << 1;
+ Record.push_back(N->isDistinct() | HasOpFragmentFlag);
Record.append(N->elements_begin(), N->elements_end());
Stream.EmitRecord(bitc::METADATA_EXPRESSION, Record, Abbrev);
OS << V->getName();
const DIExpression *Expr = MI->getDebugExpression();
- if (Expr->isBitPiece())
- OS << " [bit_piece offset=" << Expr->getBitPieceOffset()
- << " size=" << Expr->getBitPieceSize() << "]";
+ if (Expr->isFragment())
+ OS << " [fragment offset=" << Expr->getFragmentOffsetInBits()
+ << " size=" << Expr->getFragmentSizeInBits() << "]";
OS << " <- ";
// The second operand is only an offset if it's an immediate.
for (unsigned i = 0; i < Expr->getNumElements(); ++i) {
uint64_t Op = Expr->getElement(i);
- if (Op == dwarf::DW_OP_bit_piece) {
+ if (Op == dwarf::DW_OP_LLVM_fragment) {
// There can't be any operands after this in a valid expression
break;
} else if (Deref) {
"nop (could not find a dwarf register number)");
// Attempt to find a valid super- or sub-register.
- if (!Expr.AddMachineRegPiece(*MF->getSubtarget().getRegisterInfo(),
- MLoc.getReg()))
+ if (!Expr.AddMachineRegFragment(*MF->getSubtarget().getRegisterInfo(),
+ MLoc.getReg()))
Expr.EmitOp(dwarf::DW_OP_nop,
"nop (could not find a dwarf register number)");
return;
bool IsSubfield = false;
unsigned StructOffset = 0;
- // Handle bitpieces.
- if (DIExpr && DIExpr->isBitPiece()) {
+ // Handle fragments.
+ if (DIExpr && DIExpr->isFragment()) {
IsSubfield = true;
- StructOffset = DIExpr->getBitPieceOffset() / 8;
+ StructOffset = DIExpr->getFragmentOffsetInBits() / 8;
} else if (DIExpr && DIExpr->getNumElements() > 0) {
continue; // Ignore unrecognized exprs.
}
// This range is valid until the next overlapping bitpiece. In the
// common case, ranges will not be bitpieces, so they will overlap.
auto J = std::next(I);
- while (J != E && !piecesOverlap(DIExpr, J->first->getDebugExpression()))
+ while (J != E &&
+ !fragmentsOverlap(DIExpr, J->first->getDebugExpression()))
++J;
if (J != E)
End = getLabelBeforeInsn(J->first);
return LabelsAfterInsn.lookup(MI);
}
-// Determine the relative position of the pieces described by P1 and P2.
-// Returns -1 if P1 is entirely before P2, 0 if P1 and P2 overlap,
-// 1 if P1 is entirely after P2.
-int DebugHandlerBase::pieceCmp(const DIExpression *P1, const DIExpression *P2) {
- unsigned l1 = P1->getBitPieceOffset();
- unsigned l2 = P2->getBitPieceOffset();
- unsigned r1 = l1 + P1->getBitPieceSize();
- unsigned r2 = l2 + P2->getBitPieceSize();
+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();
if (r1 <= l2)
return -1;
else if (r2 <= l1)
return 0;
}
-/// Determine whether two variable pieces overlap.
-bool DebugHandlerBase::piecesOverlap(const DIExpression *P1, const DIExpression *P2) {
- if (!P1->isBitPiece() || !P2->isBitPiece())
+bool DebugHandlerBase::fragmentsOverlap(const DIExpression *P1,
+ const DIExpression *P2) {
+ if (!P1->isFragment() || !P2->isFragment())
return true;
- return pieceCmp(P1, P2) == 0;
+ return fragmentCmp(P1, P2) == 0;
}
/// If this type is derived from a base type then return base type size.
if (DIVar->isParameter() &&
getDISubprogram(DIVar->getScope())->describes(MF->getFunction())) {
LabelsBeforeInsn[Ranges.front().first] = Asm->getFunctionBegin();
- if (Ranges.front().first->getDebugExpression()->isBitPiece()) {
- // Mark all non-overlapping initial pieces.
+ if (Ranges.front().first->getDebugExpression()->isFragment()) {
+ // Mark all non-overlapping initial fragments.
for (auto I = Ranges.begin(); I != Ranges.end(); ++I) {
- const DIExpression *Piece = I->first->getDebugExpression();
+ const DIExpression *Fragment = I->first->getDebugExpression();
if (std::all_of(Ranges.begin(), I,
[&](DbgValueHistoryMap::InstrRange Pred) {
- return !piecesOverlap(Piece, Pred.first->getDebugExpression());
- }))
+ return !fragmentsOverlap(
+ Fragment, Pred.first->getDebugExpression());
+ }))
LabelsBeforeInsn[I->first] = Asm->getFunctionBegin();
else
break;
/// Return Label immediately following the instruction.
MCSymbol *getLabelAfterInsn(const MachineInstr *MI);
- /// Determine the relative position of the pieces described by P1 and P2.
- /// Returns -1 if P1 is entirely before P2, 0 if P1 and P2 overlap,
- /// 1 if P1 is entirely after P2.
- static int pieceCmp(const DIExpression *P1, const DIExpression *P2);
+ /// Determine the relative position of the fragments described by P1 and P2.
+ /// Returns -1 if P1 is entirely before P2, 0 if P1 and P2 overlap, 1 if P1 is
+ /// entirely after P2.
+ static int fragmentCmp(const DIExpression *P1, const DIExpression *P2);
- /// Determine whether two variable pieces overlap.
- static bool piecesOverlap(const DIExpression *P1, const DIExpression *P2);
+ /// Determine whether two variable fragments overlap.
+ static bool fragmentsOverlap(const DIExpression *P1, const DIExpression *P2);
/// If this type is derived from a base type then return base type size.
static uint64_t getBaseTypeSize(const DITypeRef TyRef);
const ConstantFP *getConstantFP() const { return Constant.CFP; }
const ConstantInt *getConstantInt() const { return Constant.CIP; }
MachineLocation getLoc() const { return Loc; }
- bool isBitPiece() const { return getExpression()->isBitPiece(); }
+ bool isFragment() const { return getExpression()->isFragment(); }
const DIExpression *getExpression() const { return Expression; }
friend bool operator==(const Value &, const Value &);
friend bool operator<(const Value &, const Value &);
Values.append(Vals.begin(), Vals.end());
sortUniqueValues();
assert(all_of(Values, [](DebugLocEntry::Value V) {
- return V.isBitPiece();
+ return V.isFragment();
}) && "value must be a piece");
}
llvm_unreachable("unhandled EntryKind");
}
-/// \brief Compare two pieces based on their offset.
+/// Compare two fragments based on their offset.
inline bool operator<(const DebugLocEntry::Value &A,
const DebugLocEntry::Value &B) {
- return A.getExpression()->getBitPieceOffset() <
- B.getExpression()->getBitPieceOffset();
+ return A.getExpression()->getFragmentOffsetInBits() <
+ B.getExpression()->getFragmentOffsetInBits();
}
}
bool validReg;
if (Location.isReg())
- validReg = addRegisterOpPiece(*Loc, Location.getReg());
+ validReg = addRegisterFragment(*Loc, Location.getReg());
else
validReg = addRegisterOffset(*Loc, Location.getReg(), Location.getOffset());
llvm_unreachable("Unexpected 4-operand DBG_VALUE instruction!");
}
-/// \brief If this and Next are describing different pieces of the same
+/// \brief If this and Next are describing different fragments of the same
/// variable, merge them by appending Next's values to the current
/// list of values.
/// Return true if the merge was successful.
if (Begin == Next.Begin) {
auto *FirstExpr = cast<DIExpression>(Values[0].Expression);
auto *FirstNextExpr = cast<DIExpression>(Next.Values[0].Expression);
- if (!FirstExpr->isBitPiece() || !FirstNextExpr->isBitPiece())
+ if (!FirstExpr->isFragment() || !FirstNextExpr->isFragment())
return false;
- // We can only merge entries if none of the pieces overlap any others.
+ // We can only merge entries if none of the fragments overlap any others.
// In doing so, we can take advantage of the fact that both lists are
// sorted.
for (unsigned i = 0, j = 0; i < Values.size(); ++i) {
for (; j < Next.Values.size(); ++j) {
- int res = DebugHandlerBase::pieceCmp(
+ int res = DebugHandlerBase::fragmentCmp(
cast<DIExpression>(Values[i].Expression),
cast<DIExpression>(Next.Values[j].Expression));
if (res == 0) // The two expressions overlap, we can't merge.
/// Build the location list for all DBG_VALUEs in the function that
/// describe the same variable. If the ranges of several independent
-/// pieces of the same variable overlap partially, split them up and
+/// fragments of the same variable overlap partially, split them up and
/// combine the ranges. The resulting DebugLocEntries are will have
/// strict monotonically increasing begin addresses and will never
/// overlap.
//
// Input:
//
-// Ranges History [var, loc, piece ofs size]
-// 0 | [x, (reg0, piece 0, 32)]
-// 1 | | [x, (reg1, piece 32, 32)] <- IsPieceOfPrevEntry
+// Ranges History [var, loc, fragment ofs size]
+// 0 | [x, (reg0, fragment 0, 32)]
+// 1 | | [x, (reg1, fragment 32, 32)] <- IsFragmentOfPrevEntry
// 2 | | ...
// 3 | [clobber reg0]
-// 4 [x, (mem, piece 0, 64)] <- overlapping with both previous pieces of
+// 4 [x, (mem, fragment 0, 64)] <- overlapping with both previous fragments of
// x.
//
// Output:
//
-// [0-1] [x, (reg0, piece 0, 32)]
-// [1-3] [x, (reg0, piece 0, 32), (reg1, piece 32, 32)]
-// [3-4] [x, (reg1, piece 32, 32)]
-// [4- ] [x, (mem, piece 0, 64)]
+// [0-1] [x, (reg0, fragment 0, 32)]
+// [1-3] [x, (reg0, fragment 0, 32), (reg1, fragment 32, 32)]
+// [3-4] [x, (reg1, fragment 32, 32)]
+// [4- ] [x, (mem, fragment 0, 64)]
void
DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
const DbgValueHistoryMap::InstrRanges &Ranges) {
continue;
}
- // If this piece overlaps with any open ranges, truncate them.
+ // If this fragment overlaps with any open ranges, truncate them.
const DIExpression *DIExpr = Begin->getDebugExpression();
auto Last = remove_if(OpenRanges, [&](DebugLocEntry::Value R) {
- return piecesOverlap(DIExpr, R.getExpression());
+ return fragmentsOverlap(DIExpr, R.getExpression());
});
OpenRanges.erase(Last, OpenRanges.end());
DebugLocEntry Loc(StartLabel, EndLabel, Value);
bool couldMerge = false;
- // If this is a piece, it may belong to the current DebugLocEntry.
- if (DIExpr->isBitPiece()) {
+ // If this is a fragment, it may belong to the current DebugLocEntry.
+ if (DIExpr->isFragment()) {
// Add this value to the list of open ranges.
OpenRanges.push_back(Value);
- // Attempt to add the piece to the last entry.
+ // Attempt to add the fragment to the last entry.
if (!DebugLoc.empty())
if (DebugLoc.back().MergeValues(Loc))
couldMerge = true;
if (!couldMerge) {
// Need to add a new DebugLocEntry. Add all values from still
- // valid non-overlapping pieces.
+ // valid non-overlapping fragments.
if (OpenRanges.size())
Loc.addValues(OpenRanges);
static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
ByteStreamer &Streamer,
const DebugLocEntry::Value &Value,
- unsigned PieceOffsetInBits) {
+ unsigned FragmentOffsetInBits) {
DIExpressionCursor ExprCursor(Value.getExpression());
DebugLocDwarfExpression DwarfExpr(AP.getDwarfVersion(), Streamer);
// Regular entry.
DwarfExpr.AddMachineRegIndirect(TRI, Loc.getReg(), Loc.getOffset());
else
DwarfExpr.AddMachineRegExpression(TRI, ExprCursor, Loc.getReg(),
- PieceOffsetInBits);
+ FragmentOffsetInBits);
}
} else if (Value.isConstantFP()) {
APInt RawBytes = Value.getConstantFP()->getValueAPF().bitcastToAPInt();
DwarfExpr.AddUnsignedConstant(RawBytes);
}
- DwarfExpr.AddExpression(std::move(ExprCursor), PieceOffsetInBits);
+ DwarfExpr.AddExpression(std::move(ExprCursor), FragmentOffsetInBits);
}
void DebugLocEntry::finalize(const AsmPrinter &AP,
DebugLocStream::EntryBuilder Entry(List, Begin, End);
BufferByteStreamer Streamer = Entry.getStreamer();
const DebugLocEntry::Value &Value = Values[0];
- if (Value.isBitPiece()) {
- // Emit all pieces that belong to the same variable and range.
+ if (Value.isFragment()) {
+ // Emit all fragments that belong to the same variable and range.
assert(all_of(Values, [](DebugLocEntry::Value P) {
- return P.isBitPiece();
- }) && "all values are expected to be pieces");
+ return P.isFragment();
+ }) && "all values are expected to be fragments");
assert(std::is_sorted(Values.begin(), Values.end()) &&
- "pieces are expected to be sorted");
+ "fragments are expected to be sorted");
unsigned Offset = 0;
- for (auto Piece : Values) {
- const DIExpression *Expr = Piece.getExpression();
- unsigned PieceOffset = Expr->getBitPieceOffset();
- unsigned PieceSize = Expr->getBitPieceSize();
- assert(Offset <= PieceOffset && "overlapping or duplicate pieces");
- if (Offset < PieceOffset) {
- // The DWARF spec seriously mandates pieces with no locations for gaps.
+ for (auto Fragment : Values) {
+ const DIExpression *Expr = Fragment.getExpression();
+ unsigned FragmentOffset = Expr->getFragmentOffsetInBits();
+ unsigned FragmentSize = Expr->getFragmentSizeInBits();
+ assert(Offset <= FragmentOffset && "overlapping or duplicate fragments");
+ if (Offset < FragmentOffset) {
+ // DWARF represents gaps as pieces with no locations.
DebugLocDwarfExpression Expr(AP.getDwarfVersion(), Streamer);
- Expr.AddOpPiece(PieceOffset-Offset, 0);
- Offset += PieceOffset-Offset;
+ Expr.AddOpPiece(FragmentOffset-Offset, 0);
+ Offset += FragmentOffset-Offset;
}
- Offset += PieceSize;
+ Offset += FragmentSize;
- emitDebugLocValue(AP, BT, Streamer, Piece, PieceOffset);
+ emitDebugLocValue(AP, BT, Streamer, Fragment, FragmentOffset);
}
} else {
- assert(Values.size() == 1 && "only pieces may have >1 value");
+ assert(Values.size() == 1 && "only fragments may have >1 value");
emitDebugLocValue(AP, BT, Streamer, Value, 0);
}
}
Expr.append(V.Expr.begin(), V.Expr.end());
FrameIndex.append(V.FrameIndex.begin(), V.FrameIndex.end());
assert(all_of(Expr, [](const DIExpression *E) {
- return E && E->isBitPiece();
+ return E && E->isFragment();
}) && "conflicting locations for variable");
}
return true;
}
-bool DwarfExpression::AddMachineRegPiece(const TargetRegisterInfo &TRI,
- unsigned MachineReg,
- unsigned PieceSizeInBits,
- unsigned PieceOffsetInBits) {
+bool DwarfExpression::AddMachineRegFragment(const TargetRegisterInfo &TRI,
+ unsigned MachineReg,
+ unsigned FragmentSizeInBits,
+ unsigned FragmentOffsetInBits) {
if (!TRI.isPhysicalRegister(MachineReg))
return false;
// If this is a valid register number, emit it.
if (Reg >= 0) {
AddReg(Reg);
- if (PieceSizeInBits)
- AddOpPiece(PieceSizeInBits, PieceOffsetInBits);
+ if (FragmentSizeInBits)
+ AddOpPiece(FragmentSizeInBits, FragmentOffsetInBits);
return true;
}
// Walk up the super-register chain until we find a valid number.
- // For example, EAX on x86_64 is a 32-bit piece of RAX with offset 0.
+ // For example, EAX on x86_64 is a 32-bit fragment of RAX with offset 0.
for (MCSuperRegIterator SR(MachineReg, &TRI); SR.isValid(); ++SR) {
Reg = TRI.getDwarfRegNum(*SR, false);
if (Reg >= 0) {
unsigned Size = TRI.getSubRegIdxSize(Idx);
unsigned RegOffset = TRI.getSubRegIdxOffset(Idx);
AddReg(Reg, "super-register");
- if (PieceOffsetInBits == RegOffset) {
+ if (FragmentOffsetInBits == RegOffset) {
AddOpPiece(Size, RegOffset);
} else {
- // If this is part of a variable in a sub-register at a
- // non-zero offset, we need to manually shift the value into
- // place, since the DW_OP_piece describes the part of the
- // variable, not the position of the subregister.
+ // If this is part of a variable in a sub-register at a non-zero offset,
+ // we need to manually shift the value into place, since the
+ // DW_OP_LLVM_fragment describes the part of the variable, not the
+ // position of the subregister.
if (RegOffset)
AddShr(RegOffset);
- AddOpPiece(Size, PieceOffsetInBits);
+ AddOpPiece(Size, FragmentOffsetInBits);
}
return true;
}
// Otherwise, attempt to find a covering set of sub-register numbers.
// For example, Q0 on ARM is a composition of D0+D1.
- //
- // Keep track of the current position so we can emit the more
- // efficient DW_OP_piece.
- unsigned CurPos = PieceOffsetInBits;
+ unsigned CurPos = FragmentOffsetInBits;
// The size of the register in bits, assuming 8 bits per byte.
unsigned RegSize = TRI.getMinimalPhysRegClass(MachineReg)->getSize() * 8;
// Keep track of the bits in the register we already emitted, so we
}
}
- return CurPos > PieceOffsetInBits;
+ return CurPos > FragmentOffsetInBits;
}
void DwarfExpression::AddStackValue() {
}
static unsigned getOffsetOrZero(unsigned OffsetInBits,
- unsigned PieceOffsetInBits) {
- if (OffsetInBits == PieceOffsetInBits)
+ unsigned FragmentOffsetInBits) {
+ if (OffsetInBits == FragmentOffsetInBits)
return 0;
- assert(OffsetInBits >= PieceOffsetInBits && "overlapping pieces");
+ assert(OffsetInBits >= FragmentOffsetInBits && "overlapping fragments");
return OffsetInBits;
}
bool DwarfExpression::AddMachineRegExpression(const TargetRegisterInfo &TRI,
DIExpressionCursor &ExprCursor,
unsigned MachineReg,
- unsigned PieceOffsetInBits) {
+ unsigned FragmentOffsetInBits) {
if (!ExprCursor)
- return AddMachineRegPiece(TRI, MachineReg);
+ return AddMachineRegFragment(TRI, MachineReg);
// Pattern-match combinations for which more efficient representations exist
// first.
bool ValidReg = false;
auto Op = ExprCursor.peek();
switch (Op->getOp()) {
- case dwarf::DW_OP_bit_piece: {
+ case dwarf::DW_OP_LLVM_fragment: {
unsigned OffsetInBits = Op->getArg(0);
unsigned SizeInBits = Op->getArg(1);
// Piece always comes at the end of the expression.
- AddMachineRegPiece(TRI, MachineReg, SizeInBits,
- getOffsetOrZero(OffsetInBits, PieceOffsetInBits));
+ AddMachineRegFragment(TRI, MachineReg, SizeInBits,
+ getOffsetOrZero(OffsetInBits, FragmentOffsetInBits));
ExprCursor.take();
break;
}
TRI, MachineReg, Op->getOp() == dwarf::DW_OP_plus ? Offset : -Offset);
ExprCursor.consume(2);
} else
- ValidReg = AddMachineRegPiece(TRI, MachineReg);
+ ValidReg = AddMachineRegFragment(TRI, MachineReg);
break;
}
case dwarf::DW_OP_deref:
}
void DwarfExpression::AddExpression(DIExpressionCursor &&ExprCursor,
- unsigned PieceOffsetInBits) {
+ unsigned FragmentOffsetInBits) {
while (ExprCursor) {
auto Op = ExprCursor.take();
switch (Op->getOp()) {
- case dwarf::DW_OP_bit_piece: {
+ case dwarf::DW_OP_LLVM_fragment: {
unsigned OffsetInBits = Op->getArg(0);
unsigned SizeInBits = Op->getArg(1);
- AddOpPiece(SizeInBits, getOffsetOrZero(OffsetInBits, PieceOffsetInBits));
+ AddOpPiece(SizeInBits,
+ getOffsetOrZero(OffsetInBits, FragmentOffsetInBits));
break;
}
case dwarf::DW_OP_plus:
/// entry.
class DwarfExpression {
protected:
- // Various convenience accessors that extract things out of AsmPrinter.
unsigned DwarfVersion;
public:
/// Emit an (double-)indirect dwarf register operation.
void AddRegIndirect(int DwarfReg, int Offset, bool Deref = false);
- /// Emit DW_OP_piece operation.
+ /// Emit a DW_OP_piece operation for a variable fragment.
+ /// \param OffsetInBits This is the offset where the fragment appears
+ /// inside the *source variable*.
void AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0);
+
/// Emit a shift-right dwarf expression.
void AddShr(unsigned ShiftBy);
+
/// Emit a DW_OP_stack_value, if supported.
///
/// The proper way to describe a constant value is DW_OP_constu <const>,
int Offset = 0);
/// Emit a partial DWARF register operation.
- /// \param MachineReg the register
- /// \param PieceSizeInBits size and
- /// \param PieceOffsetInBits offset of the piece in bits, if this is one
- /// piece of an aggregate value.
///
- /// If size and offset is zero an operation for the entire
- /// register is emitted: Some targets do not provide a DWARF
- /// register number for every register. If this is the case, this
- /// function will attempt to emit a DWARF register by emitting a
- /// piece of a super-register or by piecing together multiple
- /// subregisters that alias the register.
+ /// \param MachineReg the register,
+ /// \param FragmentSizeInBits size and
+ /// \param FragmentOffsetInBits offset of the fragment in bits, if this is
+ /// a fragment of an aggregate value.
+ ///
+ /// If size and offset is zero an operation for the entire register is
+ /// emitted: Some targets do not provide a DWARF register number for every
+ /// register. If this is the case, this function will attempt to emit a DWARF
+ /// register by emitting a fragment of a super-register or by piecing together
+ /// multiple subregisters that alias the register.
///
/// \return false if no DWARF register exists for MachineReg.
- bool AddMachineRegPiece(const TargetRegisterInfo &TRI, unsigned MachineReg,
- unsigned PieceSizeInBits = 0,
- unsigned PieceOffsetInBits = 0);
+ bool AddMachineRegFragment(const TargetRegisterInfo &TRI, unsigned MachineReg,
+ unsigned FragmentSizeInBits = 0,
+ unsigned FragmentOffsetInBits = 0);
/// Emit a signed constant.
void AddSignedConstant(int64_t Value);
/// the prefix of a DwarfExpression if a more efficient representation for
/// combining the register location and the first operation exists.
///
- /// \param PieceOffsetInBits If this is one piece out of a fragmented
- /// location, this is the offset of the piece inside the entire variable.
- /// \return false if no DWARF register exists for MachineReg.
+ /// \param FragmentOffsetInBits If this is one fragment out of a fragmented
+ /// location, this is the offset of the
+ /// fragment inside the entire variable.
+ /// \return false if no DWARF register exists
+ /// for MachineReg.
bool AddMachineRegExpression(const TargetRegisterInfo &TRI,
DIExpressionCursor &Expr, unsigned MachineReg,
- unsigned PieceOffsetInBits = 0);
+ unsigned FragmentOffsetInBits = 0);
/// Emit all remaining operations in the DIExpressionCursor.
- /// \param PieceOffsetInBits If this is one piece out of a fragmented
- /// location, this is the offset of the piece inside the entire variable.
+ ///
+ /// \param FragmentOffsetInBits If this is one fragment out of multiple
+ /// locations, this is the offset of the
+ /// fragment inside the entire variable.
void AddExpression(DIExpressionCursor &&Expr,
- unsigned PieceOffsetInBits = 0);
+ unsigned FragmentOffsetInBits = 0);
};
/// DwarfExpression implementation for .debug_loc entries.
addSourceLine(Die, NS->getLine(), NS->getFilename(), NS->getDirectory());
}
-bool DwarfUnit::addRegisterOpPiece(DIELoc &TheDie, unsigned Reg,
- unsigned SizeInBits, unsigned OffsetInBits) {
+bool DwarfUnit::addRegisterFragment(DIELoc &TheDie, unsigned Reg,
+ unsigned SizeInBits,
+ unsigned OffsetInBits) {
DIEDwarfExpression Expr(*Asm, *this, TheDie);
- Expr.AddMachineRegPiece(*Asm->MF->getSubtarget().getRegisterInfo(), Reg,
- SizeInBits, OffsetInBits);
+ Expr.AddMachineRegFragment(*Asm->MF->getSubtarget().getRegisterInfo(), Reg,
+ SizeInBits, OffsetInBits);
return true;
}
bool validReg;
if (Location.isReg())
- validReg = addRegisterOpPiece(*Loc, Location.getReg());
+ validReg = addRegisterFragment(*Loc, Location.getReg());
else
validReg = addRegisterOffset(*Loc, Location.getReg(), Location.getOffset());
/// Add template parameters in buffer.
void addTemplateParams(DIE &Buffer, DINodeArray TParams);
- /// Add register operand.
+ /// Add register operand for a source variable fragment of the specified size
+ /// and offset.
+ ///
/// \returns false if the register does not exist, e.g., because it was never
- /// materialized.
- bool addRegisterOpPiece(DIELoc &TheDie, unsigned Reg,
- unsigned SizeInBits = 0, unsigned OffsetInBits = 0);
+ /// materialized.
+ bool addRegisterFragment(DIELoc &TheDie, unsigned Reg,
+ unsigned SizeInBits = 0, unsigned OffsetInBits = 0);
/// Add register offset.
/// \returns false if the register does not exist, e.g., because it was never
return createExpression(Addr);
}
-DIExpression *DIBuilder::createBitPieceExpression(unsigned OffsetInBytes,
+DIExpression *DIBuilder::createFragmentExpression(unsigned OffsetInBytes,
unsigned SizeInBytes) {
- uint64_t Addr[] = {dwarf::DW_OP_bit_piece, OffsetInBytes, SizeInBytes};
+ uint64_t Addr[] = {dwarf::DW_OP_LLVM_fragment, OffsetInBytes, SizeInBytes};
return DIExpression::get(VMContext, Addr);
}
unsigned DIExpression::ExprOperand::getSize() const {
switch (getOp()) {
- case dwarf::DW_OP_bit_piece:
+ case dwarf::DW_OP_LLVM_fragment:
return 3;
case dwarf::DW_OP_constu:
case dwarf::DW_OP_plus:
switch (I->getOp()) {
default:
return false;
- case dwarf::DW_OP_bit_piece:
+ case dwarf::DW_OP_LLVM_fragment:
case dwarf::DW_OP_stack_value:
- // We only support bit piece and stack value expressions which appear at
+ // We only support fragment and stack value expressions which appear at
// the end.
return I->get() + I->getSize() == E->get();
case dwarf::DW_OP_constu:
return true;
}
-bool DIExpression::isBitPiece() const {
+bool DIExpression::isFragment() const {
assert(isValid() && "Expected valid expression");
if (unsigned N = getNumElements())
if (N >= 3)
- return getElement(N - 3) == dwarf::DW_OP_bit_piece;
+ return getElement(N - 3) == dwarf::DW_OP_LLVM_fragment;
return false;
}
-uint64_t DIExpression::getBitPieceOffset() const {
- assert(isBitPiece() && "Expected bit piece");
+uint64_t DIExpression::getFragmentOffsetInBits() const {
+ assert(isFragment() && "Expected fragment");
return getElement(getNumElements() - 2);
}
-uint64_t DIExpression::getBitPieceSize() const {
- assert(isBitPiece() && "Expected bit piece");
+uint64_t DIExpression::getFragmentSizeInBits() const {
+ assert(isFragment() && "Expected fragment");
return getElement(getNumElements() - 1);
}
void verifyFrameRecoverIndices();
void verifySiblingFuncletUnwinds();
- void verifyBitPieceExpression(const DbgInfoIntrinsic &I);
+ void verifyFragmentExpression(const DbgInfoIntrinsic &I);
/// Module-level debug info verification...
void verifyCompileUnits();
}
if (auto *DII = dyn_cast<DbgInfoIntrinsic>(&I))
- verifyBitPieceExpression(*DII);
+ verifyFragmentExpression(*DII);
InstsInThisBlock.insert(&I);
}
return 0;
}
-void Verifier::verifyBitPieceExpression(const DbgInfoIntrinsic &I) {
+void Verifier::verifyFragmentExpression(const DbgInfoIntrinsic &I) {
DILocalVariable *V;
DIExpression *E;
if (auto *DVI = dyn_cast<DbgValueInst>(&I)) {
return;
// Nothing to do if this isn't a bit piece expression.
- if (!E->isBitPiece())
+ if (!E->isFragment())
return;
// The frontend helps out GDB by emitting the members of local anonymous
if (!VarSize)
return;
- unsigned PieceSize = E->getBitPieceSize();
- unsigned PieceOffset = E->getBitPieceOffset();
- AssertDI(PieceSize + PieceOffset <= VarSize,
- "piece is larger than or outside of variable", &I, V, E);
- AssertDI(PieceSize != VarSize, "piece covers entire variable", &I, V, E);
+ unsigned FragSize = E->getFragmentSizeInBits();
+ unsigned FragOffset = E->getFragmentOffsetInBits();
+ 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);
}
void Verifier::verifyCompileUnits() {
case DW_OP_##NAME: \
return "DW_OP_" #NAME;
#include "llvm/Support/Dwarf.def"
+ case DW_OP_LLVM_fragment:
+ return "DW_OP_LLVM_fragment";
}
}
return StringSwitch<unsigned>(OperationEncodingString)
#define HANDLE_DW_OP(ID, NAME) .Case("DW_OP_" #NAME, DW_OP_##NAME)
#include "llvm/Support/Dwarf.def"
+ .Case("DW_OP_LLVM_fragment", DW_OP_LLVM_fragment)
.Default(0);
}
if (!IsSorted)
std::sort(AS.begin(), AS.end());
- /// \brief Describes the allocas introduced by rewritePartition
- /// in order to migrate the debug info.
- struct Piece {
+ /// Describes the allocas introduced by rewritePartition in order to migrate
+ /// the debug info.
+ struct Fragment {
AllocaInst *Alloca;
uint64_t Offset;
uint64_t Size;
- Piece(AllocaInst *AI, uint64_t O, uint64_t S)
+ Fragment(AllocaInst *AI, uint64_t O, uint64_t S)
: Alloca(AI), Offset(O), Size(S) {}
};
- SmallVector<Piece, 4> Pieces;
+ SmallVector<Fragment, 4> Fragments;
// Rewrite each partition.
for (auto &P : AS.partitions()) {
uint64_t AllocaSize = DL.getTypeSizeInBits(NewAI->getAllocatedType());
// Don't include any padding.
uint64_t Size = std::min(AllocaSize, P.size() * SizeOfByte);
- Pieces.push_back(Piece(NewAI, P.beginOffset() * SizeOfByte, Size));
+ Fragments.push_back(Fragment(NewAI, P.beginOffset() * SizeOfByte, Size));
}
}
++NumPartitions;
auto *Expr = DbgDecl->getExpression();
DIBuilder DIB(*AI.getModule(), /*AllowUnresolved*/ false);
uint64_t AllocaSize = DL.getTypeSizeInBits(AI.getAllocatedType());
- for (auto Piece : Pieces) {
- // Create a piece expression describing the new partition or reuse AI's
+ for (auto Fragment : Fragments) {
+ // Create a fragment expression describing the new partition or reuse AI's
// expression if there is only one partition.
- auto *PieceExpr = Expr;
- if (Piece.Size < AllocaSize || Expr->isBitPiece()) {
+ auto *FragmentExpr = Expr;
+ if (Fragment.Size < AllocaSize || Expr->isFragment()) {
// If this alloca is already a scalar replacement of a larger aggregate,
- // Piece.Offset describes the offset inside the scalar.
- uint64_t Offset = Expr->isBitPiece() ? Expr->getBitPieceOffset() : 0;
- uint64_t Start = Offset + Piece.Offset;
- uint64_t Size = Piece.Size;
- if (Expr->isBitPiece()) {
- uint64_t AbsEnd = Expr->getBitPieceOffset() + Expr->getBitPieceSize();
+ // Fragment.Offset describes the offset inside the scalar.
+ uint64_t Offset =
+ Expr->isFragment() ? Expr->getFragmentOffsetInBits() : 0;
+ uint64_t Start = Offset + Fragment.Offset;
+ uint64_t Size = Fragment.Size;
+ if (Expr->isFragment()) {
+ uint64_t AbsEnd =
+ Expr->getFragmentOffsetInBits() + Expr->getFragmentSizeInBits();
if (Start >= AbsEnd)
// No need to describe a SROAed padding.
continue;
Size = std::min(Size, AbsEnd - Start);
}
- PieceExpr = DIB.createBitPieceExpression(Start, Size);
+ FragmentExpr = DIB.createFragmentExpression(Start, Size);
}
// Remove any existing dbg.declare intrinsic describing the same alloca.
- if (DbgDeclareInst *OldDDI = FindAllocaDbgDeclare(Piece.Alloca))
+ if (DbgDeclareInst *OldDDI = FindAllocaDbgDeclare(Fragment.Alloca))
OldDDI->eraseFromParent();
- DIB.insertDeclare(Piece.Alloca, Var, PieceExpr, DbgDecl->getDebugLoc(),
- &AI);
+ DIB.insertDeclare(Fragment.Alloca, Var, FragmentExpr,
+ DbgDecl->getDebugLoc(), &AI);
}
}
return Changed;
if (SExtInst *SExt = dyn_cast<SExtInst>(SI->getOperand(0)))
ExtendedArg = dyn_cast<Argument>(SExt->getOperand(0));
if (ExtendedArg) {
- // We're now only describing a subset of the variable. The piece we're
+ // We're now only describing a subset of the variable. The fragment we're
// describing will always be smaller than the variable size, because
// VariableSize == Size of Alloca described by DDI. Since SI stores
// to the alloca described by DDI, if it's first operand is an extend,
// we're guaranteed that before extension, the value was narrower than
// the size of the alloca, hence the size of the described variable.
SmallVector<uint64_t, 3> Ops;
- unsigned PieceOffset = 0;
- // If this already is a bit piece, we drop the bit piece from the expression
- // and record the offset.
- if (DIExpr->isBitPiece()) {
+ 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()) {
Ops.append(DIExpr->elements_begin(), DIExpr->elements_end()-3);
- PieceOffset = DIExpr->getBitPieceOffset();
+ FragmentOffset = DIExpr->getFragmentOffsetInBits();
} else {
Ops.append(DIExpr->elements_begin(), DIExpr->elements_end());
}
- Ops.push_back(dwarf::DW_OP_bit_piece);
- Ops.push_back(PieceOffset); // Offset
+ Ops.push_back(dwarf::DW_OP_LLVM_fragment);
+ Ops.push_back(FragmentOffset);
const DataLayout &DL = DDI->getModule()->getDataLayout();
- Ops.push_back(DL.getTypeSizeInBits(ExtendedArg->getType())); // Size
+ Ops.push_back(DL.getTypeSizeInBits(ExtendedArg->getType()));
auto NewDIExpr = Builder.createExpression(Ops);
if (!LdStHasDebugValue(DIVar, NewDIExpr, SI))
Builder.insertDbgValueIntrinsic(ExtendedArg, 0, DIVar, NewDIExpr,
; CHECK: !0 = !DIExpression()
; CHECK-NEXT: !1 = !DIExpression(DW_OP_deref)
; CHECK-NEXT: !2 = !DIExpression(DW_OP_plus, 3)
-; CHECK-NEXT: !3 = !DIExpression(DW_OP_bit_piece, 3, 7)
-; CHECK-NEXT: !4 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_bit_piece, 3, 7)
+; CHECK-NEXT: !3 = !DIExpression(DW_OP_LLVM_fragment, 3, 7)
+; CHECK-NEXT: !4 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7)
!0 = !DIExpression()
!1 = !DIExpression(DW_OP_deref)
!2 = !DIExpression(DW_OP_plus, 3)
-!3 = !DIExpression(DW_OP_bit_piece, 3, 7)
-!4 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_bit_piece, 3, 7)
+!3 = !DIExpression(DW_OP_LLVM_fragment, 3, 7)
+!4 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7)
--- /dev/null
+; RUN: llvm-dis -o - %s.bc | FileCheck %s
+
+@g = common global i32 0, align 4, !dbg !0
+
+!llvm.dbg.cu = !{!1}
+!llvm.module.flags = !{!7, !8}
+
+!0 = distinct !DIGlobalVariable(name: "g", scope: !1, file: !2, line: 1, type: !5, isLocal: false, isDefinition: true, expr: !6)
+!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang (llvm/trunk 288154)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, globals: !4)
+!2 = !DIFile(filename: "a.c", directory: "/")
+!3 = !{}
+!4 = !{!0}
+!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+; Old-style DIExpression bitcode records using DW_OP_bit_piece should be
+; upgraded to DW_OP_LLVM_fragment.
+;
+; CHECK: !DIExpression(DW_OP_LLVM_fragment, 8, 32)
+!6 = !DIExpression(DW_OP_bit_piece, 8, 32)
+!7 = !{i32 2, !"Dwarf Version", i32 4}
+!8 = !{i32 2, !"Debug Info Version", i32 3}
!18 = !{!"clang version 3.8.0 (trunk 256088) (llvm/trunk 256097)"}
!19 = !DIExpression()
!20 = !DILocation(line: 4, column: 5, scope: !4)
-!21 = !DIExpression(DW_OP_bit_piece, 32, 32)
+!21 = !DIExpression(DW_OP_LLVM_fragment, 32, 32)
!22 = !DILocation(line: 6, column: 1, scope: !4)
!73 = !DILocation(line: 17, column: 27, scope: !31)
!74 = !DILocalVariable(name: "p1", line: 17, arg: 1, scope: !31, file: !26, type: !4)
!75 = distinct !DILocation(line: 22, column: 3, scope: !34)
-!76 = !DIExpression(DW_OP_bit_piece, 8, 120)
+!76 = !DIExpression(DW_OP_LLVM_fragment, 8, 120)
!77 = !DILocation(line: 17, column: 12, scope: !31, inlinedAt: !75)
-!78 = !DIExpression(DW_OP_bit_piece, 136, 56)
+!78 = !DIExpression(DW_OP_LLVM_fragment, 136, 56)
!79 = !DIExpression(DW_OP_deref)
!80 = !DILocation(line: 19, column: 5, scope: !34)
!81 = !DILocation(line: 20, column: 7, scope: !34)
!82 = !DILocation(line: 20, column: 5, scope: !34)
-!83 = !DIExpression(DW_OP_bit_piece, 0, 8)
-!84 = !DIExpression(DW_OP_bit_piece, 128, 8)
+!83 = !DIExpression(DW_OP_LLVM_fragment, 0, 8)
+!84 = !DIExpression(DW_OP_LLVM_fragment, 128, 8)
!85 = !DILocation(line: 13, column: 12, scope: !25, inlinedAt: !86)
!86 = distinct !DILocation(line: 17, column: 18, scope: !31, inlinedAt: !75)
!87 = !DILocation(line: 14, column: 37, scope: !25, inlinedAt: !86)
!27 = !DILocation(line: 11, scope: !11, inlinedAt: !28)
!28 = distinct !DILocation(line: 26, scope: !4)
!29 = !DILocation(line: 13, scope: !11, inlinedAt: !28)
-!30 = !DIExpression(DW_OP_bit_piece, 0, 64)
-!31 = !DIExpression(DW_OP_bit_piece, 0, 32)
+!30 = !DIExpression(DW_OP_LLVM_fragment, 0, 64)
+!31 = !DIExpression(DW_OP_LLVM_fragment, 0, 32)
!32 = !DILocation(line: 18, scope: !11, inlinedAt: !28)
!33 = !DILocation(line: 27, scope: !4)
!14 = !DILocalVariable(name: "c", arg: 1, scope: !4, file: !5, line: 1, type: !8)
!15 = !DIExpression()
!16 = !DILocation(line: 1, column: 24, scope: !4)
-!17 = !DIExpression(DW_OP_bit_piece, 0, 64)
-!18 = !DIExpression(DW_OP_bit_piece, 64, 64)
+!17 = !DIExpression(DW_OP_LLVM_fragment, 0, 64)
+!18 = !DIExpression(DW_OP_LLVM_fragment, 64, 64)
!19 = !DILocation(line: 1, column: 36, scope: !4)
; CHECK-SAME: metadata ![[C]], metadata ![[IMG:.*]])
ret void, !dbg !18
}
-; CHECK: ![[REAL]] = !DIExpression(DW_OP_bit_piece, 0, 64)
-; CHECK: ![[IMG]] = !DIExpression(DW_OP_bit_piece, 64, 64)
+; CHECK: ![[REAL]] = !DIExpression(DW_OP_LLVM_fragment, 0, 64)
+; CHECK: ![[IMG]] = !DIExpression(DW_OP_LLVM_fragment, 64, 64)
; Function Attrs: nounwind readnone
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
; }
; ASM-LABEL: loop_csr: # @loop_csr
-; ASM: #DEBUG_VALUE: loop_csr:o [bit_piece offset=0 size=32] <- 0
-; ASM: #DEBUG_VALUE: loop_csr:o [bit_piece offset=32 size=32] <- 0
+; ASM: #DEBUG_VALUE: loop_csr:o [fragment offset=0 size=32] <- 0
+; ASM: #DEBUG_VALUE: loop_csr:o [fragment offset=32 size=32] <- 0
; ASM: # BB#2: # %for.body.preheader
; ASM: xorl %edi, %edi
; ASM: xorl %esi, %esi
; ASM: .p2align 4, 0x90
; ASM: .LBB0_3: # %for.body
; ASM: [[ox_start:\.Ltmp[0-9]+]]:
-; ASM: #DEBUG_VALUE: loop_csr:o [bit_piece offset=0 size=32] <- %EDI
+; ASM: #DEBUG_VALUE: loop_csr:o [fragment offset=0 size=32] <- %EDI
; ASM: .cv_loc 0 1 13 11 # t.c:13:11
; ASM: movl %edi, %ecx
; ASM: callq g
; ASM: movl %eax, %edi
; ASM: [[oy_start:\.Ltmp[0-9]+]]:
-; ASM: #DEBUG_VALUE: loop_csr:o [bit_piece offset=0 size=32] <- %EDI
-; ASM: #DEBUG_VALUE: loop_csr:o [bit_piece offset=32 size=32] <- %ESI
+; ASM: #DEBUG_VALUE: loop_csr:o [fragment offset=0 size=32] <- %EDI
+; ASM: #DEBUG_VALUE: loop_csr:o [fragment offset=32 size=32] <- %ESI
; ASM: .cv_loc 0 1 14 11 # t.c:14:11
; ASM: movl %esi, %ecx
; ASM: callq g
; ASM: movl %eax, %esi
-; ASM: #DEBUG_VALUE: loop_csr:o [bit_piece offset=32 size=32] <- %ESI
+; ASM: #DEBUG_VALUE: loop_csr:o [fragment offset=32 size=32] <- %ESI
; ASM: cmpl n(%rip), %eax
; ASM: jl .LBB0_3
; ASM: [[oy_end:\.Ltmp[0-9]+]]:
; ASM-LABEL: pad_right: # @pad_right
-; ASM: #DEBUG_VALUE: pad_right:o [bit_piece offset=32 size=32] <- %ECX
+; ASM: #DEBUG_VALUE: pad_right:o [fragment offset=32 size=32] <- %ECX
; ASM: movl %ecx, %eax
; ASM: retq
; ASM-LABEL: pad_left: # @pad_left
-; ASM: #DEBUG_VALUE: pad_left:o [bit_piece offset=0 size=32] <- %ECX
+; ASM: #DEBUG_VALUE: pad_left:o [fragment offset=0 size=32] <- %ECX
; ASM: .cv_loc 2 1 24 3 # t.c:24:3
; ASM: movl %ecx, %eax
; ASM: retq
; ASM: #DEBUG_VALUE: nested:o <- [%RCX+0]
; ASM: movl 12(%rcx), %eax
; ASM: [[p_start:\.Ltmp[0-9]+]]:
-; ASM: #DEBUG_VALUE: nested:p [bit_piece offset=32 size=32] <- %EAX
+; ASM: #DEBUG_VALUE: nested:p [fragment offset=32 size=32] <- %EAX
; ASM: retq
; ASM-LABEL: bitpiece_spill: # @bitpiece_spill
-; ASM: #DEBUG_VALUE: bitpiece_spill:o [bit_piece offset=0 size=32] <- 0
+; ASM: #DEBUG_VALUE: bitpiece_spill:o [fragment offset=0 size=32] <- 0
; ASM: xorl %ecx, %ecx
; ASM: callq g
; ASM: movl %eax, [[offset_o_x:[0-9]+]](%rsp) # 4-byte Spill
; ASM: [[spill_o_x_start:\.Ltmp[0-9]+]]:
-; ASM: #DEBUG_VALUE: bitpiece_spill:o [bit_piece offset=32 size=32] <- [%RSP+[[offset_o_x]]]
+; ASM: #DEBUG_VALUE: bitpiece_spill:o [fragment offset=32 size=32] <- [%RSP+[[offset_o_x]]]
; ASM: #APP
; ASM: #NO_APP
; ASM: movl [[offset_o_x]](%rsp), %eax # 4-byte Reload
!16 = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: !13, file: !1, line: 1, baseType: !10, size: 32, align: 32, offset: 32)
!17 = !DIExpression()
!18 = !DILocation(line: 11, column: 18, scope: !7)
-!19 = !DIExpression(DW_OP_bit_piece, 0, 32)
-!20 = !DIExpression(DW_OP_bit_piece, 32, 32)
+!19 = !DIExpression(DW_OP_LLVM_fragment, 0, 32)
+!20 = !DIExpression(DW_OP_LLVM_fragment, 32, 32)
!21 = !DILocation(line: 12, column: 23, scope: !22)
!22 = distinct !DILexicalBlock(scope: !23, file: !1, line: 12, column: 3)
!23 = distinct !DILexicalBlock(scope: !7, file: !1, line: 12, column: 3)
!21 = !DILocation(line: 3, scope: !4)
!22 = !DILocalVariable(name: "s", line: 3, arg: 1, scope: !4, file: !5, type: !9)
!23 = !DILocation(line: 4, scope: !4)
-!24 = !DIExpression(DW_OP_deref, DW_OP_bit_piece, 0, 64)
+!24 = !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 0, 64)
!25 = !{}
-; This expression has elements after DW_OP_bit_piece.
+; This expression has elements after DW_OP_LLVM_fragment.
; CHECK: invalid expression
; CHECK-NEXT: !DIExpression({{[0-9]+}}, 64, 32, {{[0-9]+}})
; CHECK-NOT: invalid expression
-!27 = !DIExpression(DW_OP_bit_piece, 64, 32, DW_OP_deref)
+!27 = !DIExpression(DW_OP_LLVM_fragment, 64, 32, DW_OP_deref)
!27 = !DILocation(line: 5, column: 16, scope: !4)
!28 = !DILocation(line: 6, column: 13, scope: !4)
!29 = !DILocation(line: 6, column: 16, scope: !4)
-!30 = !DIExpression(DW_OP_bit_piece, 0, 32)
-!31 = !DIExpression(DW_OP_bit_piece, 32, 32)
-!32 = !DIExpression(DW_OP_bit_piece, 32, 16)
+!30 = !DIExpression(DW_OP_LLVM_fragment, 0, 32)
+!31 = !DIExpression(DW_OP_LLVM_fragment, 32, 32)
+!32 = !DIExpression(DW_OP_LLVM_fragment, 32, 16)
!33 = !DILocation(line: 8, column: 9, scope: !4)
!34 = !DILocation(line: 9, column: 1, scope: !4)
!35 = !DILocation(line: 11, column: 14, scope: !17)
; CHECK: define i32 @main
; CHECK: call void @llvm.dbg.value(metadata i32 42, i64 0, metadata ![[ARRAY:[0-9]+]], metadata ![[EXPR:[0-9]+]])
; CHECK: ![[ARRAY]] = !DILocalVariable(name: "array",{{.*}} line: 6
-; CHECK: ![[EXPR]] = !DIExpression(DW_OP_bit_piece, 0, 32)
+; CHECK: ![[EXPR]] = !DIExpression(DW_OP_LLVM_fragment, 0, 32)
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.9.0"
!13 = !DISubroutineType(types: !14)
!14 = !{null}
!15 = !DILocalVariable(name: "v", scope: !12, type: !6)
-!16 = !DIExpression(DW_OP_bit_piece, 32, 32)
+!16 = !DIExpression(DW_OP_LLVM_fragment, 32, 32)
!17 = !DILocation(line: 2755, column: 9, scope: !12)
!30 = !{i32 2, !"Debug Info Version", i32 3}
!31 = !{i32 1, !"PIC Level", i32 2}
!32 = !{!"clang version 3.7.0 (trunk 227088) (llvm/trunk 227091)"}
-!33 = !DIExpression(DW_OP_bit_piece, 0, 8)
+!33 = !DIExpression(DW_OP_LLVM_fragment, 0, 8)
!34 = !DILocation(line: 7, column: 42, scope: !11)
-!35 = !DIExpression(DW_OP_bit_piece, 8, 4)
+!35 = !DIExpression(DW_OP_LLVM_fragment, 8, 4)
!36 = !DIExpression()
!37 = !DILocation(line: 7, column: 48, scope: !11)
!38 = !DILocation(line: 7, column: 66, scope: !11)
!21 = !DILocation(line: 3, scope: !4)
!22 = !DILocalVariable(name: "s", line: 3, arg: 1, scope: !4, file: !5, type: !9)
!23 = !DILocation(line: 4, scope: !4)
-!24 = !DIExpression(DW_OP_bit_piece, 0, 64)
+!24 = !DIExpression(DW_OP_LLVM_fragment, 0, 64)
!25 = !{}
-!27 = !DIExpression(DW_OP_bit_piece, 64, 32)
+!27 = !DIExpression(DW_OP_LLVM_fragment, 64, 32)
!26 = !DILocation(line: 10, scope: !4)
!27 = !DILocation(line: 11, scope: !4)
!28 = !DILocalVariable(name: "i1", line: 11, scope: !4, file: !5, type: !14)
-!29 = !DIExpression(DW_OP_bit_piece, 0, 32)
+!29 = !DIExpression(DW_OP_LLVM_fragment, 0, 32)
!31 = !{i32 3, i32 0, i32 12}
!32 = !DILocation(line: 12, scope: !4)
!22 = !{i32 1, !"Debug Info Version", i32 3}
!23 = !{!"clang version 3.5.0 "}
!24 = !DILocalVariable(name: "outer", line: 10, arg: 1, scope: !4, file: !5, type: !9)
-!25 = !DIExpression(DW_OP_bit_piece, 0, 64)
+!25 = !DIExpression(DW_OP_LLVM_fragment, 0, 64)
!26 = !DILocation(line: 10, scope: !4)
!27 = !DILocalVariable(name: "outer", line: 10, arg: 1, scope: !4, file: !5, type: !9)
-!28 = !DIExpression(DW_OP_bit_piece, 64, 64)
+!28 = !DIExpression(DW_OP_LLVM_fragment, 64, 64)
!29 = !DILocalVariable(name: "outer", line: 10, arg: 1, scope: !4, file: !5, type: !9)
-!30 = !DIExpression(DW_OP_bit_piece, 96, 32)
+!30 = !DIExpression(DW_OP_LLVM_fragment, 96, 32)
!31 = !DILocalVariable(name: "outer", line: 10, arg: 1, scope: !4, file: !5, type: !9)
-!32 = !DIExpression(DW_OP_bit_piece, 64, 32)
+!32 = !DIExpression(DW_OP_LLVM_fragment, 64, 32)
!33 = !DILocation(line: 11, scope: !4)
!34 = !DILocalVariable(name: "i1", line: 11, scope: !4, file: !5, type: !14)
-!35 = !DIExpression(DW_OP_bit_piece, 0, 32)
+!35 = !DIExpression(DW_OP_LLVM_fragment, 0, 32)
!36 = !DILocation(line: 12, scope: !4)
; CHECK-LABEL: bitpiece_spill: # @bitpiece_spill
; CHECK: callq g
; CHECK: movl %eax, [[offs:[0-9]+]](%rsp) # 4-byte Spill
-; CHECK: #DEBUG_VALUE: bitpiece_spill:o [bit_piece offset=32 size=32] <- 0
-; CHECK: #DEBUG_VALUE: bitpiece_spill:o [bit_piece offset=0 size=32] <- [%RSP+[[offs]]]
+; CHECK: #DEBUG_VALUE: bitpiece_spill:o [fragment offset=32 size=32] <- 0
+; CHECK: #DEBUG_VALUE: bitpiece_spill:o [fragment offset=0 size=32] <- [%RSP+[[offs]]]
; CHECK: #APP
; CHECK: #NO_APP
; CHECK: movl [[offs]](%rsp), %eax # 4-byte Reload
!17 = !DIExpression()
!18 = !DILocation(line: 4, column: 18, scope: !7)
!19 = !DILocation(line: 4, column: 23, scope: !7)
-!20 = !DIExpression(DW_OP_bit_piece, 0, 32)
-!21 = !DIExpression(DW_OP_bit_piece, 32, 32)
+!20 = !DIExpression(DW_OP_LLVM_fragment, 0, 32)
+!21 = !DIExpression(DW_OP_LLVM_fragment, 32, 32)
!22 = !DILocation(line: 6, column: 3, scope: !7)
!23 = !{i32 138}
!24 = !DILocation(line: 8, column: 3, scope: !7)
; CHECK: ret i32 %[[A]]
; Read Var and Piece:
; CHECK: ![[VAR]] = !DILocalVariable(name: "i1",{{.*}} line: 11,
-; CHECK: ![[PIECE1]] = !DIExpression(DW_OP_bit_piece, 32, 96)
-; CHECK: ![[PIECE2]] = !DIExpression(DW_OP_bit_piece, 0, 32)
+; CHECK: ![[PIECE1]] = !DIExpression(DW_OP_LLVM_fragment, 32, 96)
+; CHECK: ![[PIECE2]] = !DIExpression(DW_OP_LLVM_fragment, 0, 32)
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.9.0"
; CHECK: call void @llvm.dbg.value(metadata i64 %outer.coerce1, i64 0, metadata ![[O]], metadata ![[PIECE2:[0-9]+]]),
; CHECK: call void @llvm.dbg.value({{.*}}, i64 0, metadata ![[I1:[0-9]+]], metadata ![[PIECE3:[0-9]+]]),
; CHECK-DAG: ![[O]] = !DILocalVariable(name: "outer",{{.*}} line: 10
-; CHECK-DAG: ![[PIECE1]] = !DIExpression(DW_OP_bit_piece, 0, 64)
-; CHECK-DAG: ![[PIECE2]] = !DIExpression(DW_OP_bit_piece, 64, 64)
+; CHECK-DAG: ![[PIECE1]] = !DIExpression(DW_OP_LLVM_fragment, 0, 64)
+; CHECK-DAG: ![[PIECE2]] = !DIExpression(DW_OP_LLVM_fragment, 64, 64)
; CHECK-DAG: ![[I1]] = !DILocalVariable(name: "i1",{{.*}} line: 11
-; CHECK-DAG: ![[PIECE3]] = !DIExpression(DW_OP_bit_piece, 0, 32)
+; CHECK-DAG: ![[PIECE3]] = !DIExpression(DW_OP_LLVM_fragment, 0, 32)
; ModuleID = 'sroasplit-2.c'
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
; CHECK: call void @llvm.dbg.value(metadata float %s.coerce, i64 0, metadata ![[VAR:[0-9]+]], metadata ![[EXPR:[0-9]+]])
; CHECK: ![[VAR]] = !DILocalVariable(name: "s",{{.*}} line: 3,
; CHECK: ![[EXPR]] = !DIExpression(
-; CHECK-NOT: DW_OP_bit_piece
+; CHECK-NOT: DW_OP_LLVM_fragment
;
; struct S { float f; };
; CHECK: call void @llvm.dbg.value(metadata i64 %[[T1]], i64 0, metadata ![[Y]], metadata ![[P2:.*]])
; CHECK: call void @llvm.dbg.value(metadata i64 %[[T]], i64 0, metadata ![[R:.*]], metadata ![[P3:.*]])
; CHECK: call void @llvm.dbg.value(metadata i64 %[[T1]], i64 0, metadata ![[R]], metadata ![[P4:.*]])
-; CHECK: ![[P1]] = !DIExpression(DW_OP_bit_piece, 0, 64)
-; CHECK: ![[P2]] = !DIExpression(DW_OP_bit_piece, 64, 64)
-; CHECK: ![[P3]] = !DIExpression(DW_OP_bit_piece, 192, 64)
-; CHECK: ![[P4]] = !DIExpression(DW_OP_bit_piece, 256, 64)
+; CHECK: ![[P1]] = !DIExpression(DW_OP_LLVM_fragment, 0, 64)
+; CHECK: ![[P2]] = !DIExpression(DW_OP_LLVM_fragment, 64, 64)
+; CHECK: ![[P3]] = !DIExpression(DW_OP_LLVM_fragment, 192, 64)
+; CHECK: ![[P4]] = !DIExpression(DW_OP_LLVM_fragment, 256, 64)
;
; struct p {
; __SIZE_TYPE__ s;
; When SROA is creating new smaller allocas, it may add padding.
;
; There should be no debug info for the padding.
-; CHECK-NOT: DW_OP_bit_piece, 56
-; CHECK: DIExpression(DW_OP_bit_piece, 32, 24)
-; CHECK-NOT: DW_OP_bit_piece, 56
-; CHECK: DIExpression(DW_OP_bit_piece, 0, 32)
-; CHECK-NOT: DW_OP_bit_piece, 56
+; CHECK-NOT: DW_OP_LLVM_fragment, 56
+; CHECK: DIExpression(DW_OP_LLVM_fragment, 32, 24)
+; CHECK-NOT: DW_OP_LLVM_fragment, 56
+; CHECK: DIExpression(DW_OP_LLVM_fragment, 0, 32)
+; CHECK-NOT: DW_OP_LLVM_fragment, 56
%struct.prog_src_register = type { i32, i24 }
; Function Attrs: nounwind
!19 = !DIExpression()
!20 = !DILocation(line: 2, column: 9, scope: !7)
!21 = !DILocation(line: 3, column: 5, scope: !7)
-!22 = !DIExpression(DW_OP_bit_piece, 0, 32)
-!23 = !DIExpression(DW_OP_bit_piece, 32, 32)
+!22 = !DIExpression(DW_OP_LLVM_fragment, 0, 32)
+!23 = !DIExpression(DW_OP_LLVM_fragment, 32, 32)
!24 = !DILocation(line: 5, column: 1, scope: !7)
!25 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 8, type: !26, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: true, unit: !0)
!26 = !DISubroutineType(types: !27)
!45 = !DILocation(line: 9, scope: !15)
!46 = !DILocalVariable(name: "p1", line: 6, arg: 1, scope: !15, file: !16, type: !4)
!47 = distinct !DILocation(line: 11, scope: !21)
-!48 = !DIExpression(DW_OP_bit_piece, 32, 160)
+!48 = !DIExpression(DW_OP_LLVM_fragment, 32, 160)
!49 = !DILocation(line: 6, scope: !15, inlinedAt: !47)
!50 = !DILocation(line: 11, scope: !21)
-!51 = !DIExpression(DW_OP_bit_piece, 0, 32)
+!51 = !DIExpression(DW_OP_LLVM_fragment, 0, 32)
!52 = !DILocation(line: 7, scope: !34, inlinedAt: !47)
!53 = !DILocation(line: 7, scope: !15, inlinedAt: !47)
!54 = !DILocation(line: 8, scope: !34, inlinedAt: !47)
; CHECK-NOT: call void @llvm.dbg.value
; CHECK: call void @llvm.dbg.value(metadata %foo* undef, i64 0, {{.*}}, metadata ![[BIT_PIECE:[0-9]+]]), !dbg
; CHECK-NOT: call void @llvm.dbg.value
-; CHECK: ![[BIT_PIECE]] = !DIExpression(DW_OP_bit_piece, 64, 64)
+; CHECK: ![[BIT_PIECE]] = !DIExpression(DW_OP_LLVM_fragment, 64, 64)
%0 = bitcast %foo* %retval to i8*
%1 = getelementptr inbounds i8, i8* %0, i64 8
%2 = bitcast i8* %1 to %foo**
%v2 = alloca i64, align 8
store i32 %hs, i32* %hs.addr, align 4
; CHECK: call void @llvm.dbg.value(metadata i32 %hs, i64 0, metadata !{{[0-9]+}}, metadata ![[EXPR:[0-9]+]])
-; CHECK: ![[EXPR]] = !DIExpression(DW_OP_bit_piece, 0
+; CHECK: ![[EXPR]] = !DIExpression(DW_OP_LLVM_fragment, 0
call void @llvm.dbg.declare(metadata i64* %v1, metadata !9, metadata !12), !dbg !13
%0 = load i32, i32* %hs.addr, align 4
%conv = sext i32 %0 to i64
// Valid constructions.
EXPECT_VALID(dwarf::DW_OP_plus, 6);
EXPECT_VALID(dwarf::DW_OP_deref);
- EXPECT_VALID(dwarf::DW_OP_bit_piece, 3, 7);
+ EXPECT_VALID(dwarf::DW_OP_LLVM_fragment, 3, 7);
EXPECT_VALID(dwarf::DW_OP_plus, 6, dwarf::DW_OP_deref);
EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus, 6);
- EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_bit_piece, 3, 7);
- EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus, 6, dwarf::DW_OP_bit_piece, 3, 7);
+ EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_LLVM_fragment, 3, 7);
+ EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus, 6,
+ dwarf::DW_OP_LLVM_fragment, 3, 7);
// Invalid constructions.
EXPECT_INVALID(~0u);
EXPECT_INVALID(dwarf::DW_OP_plus);
- EXPECT_INVALID(dwarf::DW_OP_bit_piece);
- EXPECT_INVALID(dwarf::DW_OP_bit_piece, 3);
- EXPECT_INVALID(dwarf::DW_OP_bit_piece, 3, 7, dwarf::DW_OP_plus, 3);
- EXPECT_INVALID(dwarf::DW_OP_bit_piece, 3, 7, dwarf::DW_OP_deref);
+ EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment);
+ EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3);
+ EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3, 7, dwarf::DW_OP_plus, 3);
+ EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3, 7, dwarf::DW_OP_deref);
#undef EXPECT_VALID
#undef EXPECT_INVALID