Refactor DebugLocDWARFExpression so it doesn't require access to the

TargetRegisterInfo. DebugLocEntry now holds a buffer with the raw bytes
of the pre-calculated DWARF expression.

Ought to be NFC, but it does slightly alter the output format of the
textual assembly.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@230930 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Adrian Prantl
2015-03-02 02:38:18 +00:00
parent 6cad61163a
commit d21acaf6a1
11 changed files with 169 additions and 153 deletions

View File

@ -105,6 +105,25 @@ DwarfPubSections("generate-dwarf-pub-sections", cl::Hidden,
static const char *const DWARFGroupName = "DWARF Emission";
static const char *const DbgTimerName = "DWARF Debug Writer";
void DebugLocDwarfExpression::EmitOp(uint8_t Op, const char *Comment) {
BS.EmitInt8(
Op, Comment ? Twine(Comment) + " " + dwarf::OperationEncodingString(Op)
: dwarf::OperationEncodingString(Op));
}
void DebugLocDwarfExpression::EmitSigned(int Value) {
BS.EmitSLEB128(Value, Twine(Value));
}
void DebugLocDwarfExpression::EmitUnsigned(unsigned Value) {
BS.EmitULEB128(Value, Twine(Value));
}
bool DebugLocDwarfExpression::isFrameRegister(unsigned MachineReg) {
// This information is not available while emitting .debug_loc entries.
return false;
}
//===----------------------------------------------------------------------===//
/// resolve - Look in the DwarfDebug map for the MDNode that
@ -927,6 +946,9 @@ DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, DISubprogram SP,
// Build the location list for this variable.
buildLocationList(LocList.List, Ranges);
// Finalize the entry by lowering it into a DWARF bytestream.
for (auto &Entry : LocList.List)
Entry.finalize(*Asm, TypeIdentifierMap);
}
// Collect info for variables that were optimized out.
@ -1600,62 +1622,27 @@ void DwarfDebug::emitDebugStr() {
Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection());
}
/// Emits an optimal (=sorted) sequence of DW_OP_pieces.
void DwarfDebug::emitLocPieces(ByteStreamer &Streamer,
const DITypeIdentifierMap &Map,
ArrayRef<DebugLocEntry::Value> Values) {
assert(std::all_of(Values.begin(), Values.end(), [](DebugLocEntry::Value P) {
return P.isBitPiece();
}) && "all values are expected to be pieces");
assert(std::is_sorted(Values.begin(), Values.end()) &&
"pieces are expected to be sorted");
unsigned Offset = 0;
for (auto Piece : Values) {
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.
Asm->EmitDwarfOpPiece(Streamer, PieceOffset-Offset);
Offset += PieceOffset-Offset;
}
Offset += PieceSize;
#ifndef NDEBUG
DIVariable Var = Piece.getVariable();
unsigned VarSize = Var.getSizeInBits(Map);
assert(PieceSize+PieceOffset <= VarSize
&& "piece is larger than or outside of variable");
assert(PieceSize != VarSize
&& "piece covers entire variable");
#endif
emitDebugLocValue(Streamer, Piece, PieceOffset);
}
}
void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
const DebugLocEntry &Entry) {
const DebugLocEntry::Value Value = Entry.getValues()[0];
if (Value.isBitPiece())
// Emit all pieces that belong to the same variable and range.
return emitLocPieces(Streamer, TypeIdentifierMap, Entry.getValues());
assert(Entry.getValues().size() == 1 && "only pieces may have >1 value");
emitDebugLocValue(Streamer, Value);
auto Comment = Entry.getComments().begin();
auto End = Entry.getComments().end();
for (uint8_t Byte : Entry.getDWARFBytes())
Streamer.EmitInt8(Byte, Comment != End ? *(Comment++) : "");
}
void DwarfDebug::emitDebugLocValue(ByteStreamer &Streamer,
const DebugLocEntry::Value &Value,
unsigned PieceOffsetInBits) {
static void emitDebugLocValue(const AsmPrinter &AP,
const DITypeIdentifierMap &TypeIdentifierMap,
ByteStreamer &Streamer,
const DebugLocEntry::Value &Value,
unsigned PieceOffsetInBits) {
DIVariable DV = Value.getVariable();
DebugLocDwarfExpression DwarfExpr(*Asm, Streamer);
DebugLocDwarfExpression DwarfExpr(
*AP.TM.getSubtargetImpl()->getRegisterInfo(),
AP.getDwarfDebug()->getDwarfVersion(), Streamer);
// Regular entry.
if (Value.isInt()) {
DIBasicType BTy(resolve(DV.getType()));
DIBasicType BTy(DV.getType().resolve(TypeIdentifierMap));
if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed ||
BTy.getEncoding() == dwarf::DW_ATE_signed_char))
DwarfExpr.AddSignedConstant(Value.getInt());
@ -1666,7 +1653,7 @@ void DwarfDebug::emitDebugLocValue(ByteStreamer &Streamer,
DIExpression Expr = Value.getExpression();
if (!Expr || (Expr.getNumElements() == 0))
// Regular entry.
Asm->EmitDwarfRegOp(Streamer, Loc);
AP.EmitDwarfRegOp(Streamer, Loc);
else {
// Complex address entry.
if (Loc.getOffset()) {
@ -1682,6 +1669,52 @@ void DwarfDebug::emitDebugLocValue(ByteStreamer &Streamer,
// FIXME: ^
}
void DebugLocEntry::finalize(const AsmPrinter &AP,
const DITypeIdentifierMap &TypeIdentifierMap) {
BufferByteStreamer Streamer(DWARFBytes, Comments);
const DebugLocEntry::Value Value = Values[0];
if (Value.isBitPiece()) {
// Emit all pieces that belong to the same variable and range.
assert(std::all_of(Values.begin(), Values.end(), [](DebugLocEntry::Value P) {
return P.isBitPiece();
}) && "all values are expected to be pieces");
assert(std::is_sorted(Values.begin(), Values.end()) &&
"pieces are expected to be sorted");
unsigned Offset = 0;
for (auto Piece : Values) {
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.
DebugLocDwarfExpression Expr(
*AP.TM.getSubtargetImpl()->getRegisterInfo(),
AP.getDwarfDebug()->getDwarfVersion(), Streamer);
Expr.AddOpPiece(PieceOffset-Offset, 0);
Offset += PieceOffset-Offset;
}
Offset += PieceSize;
#ifndef NDEBUG
DIVariable Var = Piece.getVariable();
unsigned VarSize = Var.getSizeInBits(TypeIdentifierMap);
assert(PieceSize+PieceOffset <= VarSize
&& "piece is larger than or outside of variable");
assert(PieceSize != VarSize
&& "piece covers entire variable");
#endif
emitDebugLocValue(AP, TypeIdentifierMap, Streamer, Piece, PieceOffset);
}
} else {
assert(Values.size() == 1 && "only pieces may have >1 value");
emitDebugLocValue(AP, TypeIdentifierMap, Streamer, Value, 0);
}
}
void DwarfDebug::emitDebugLocEntryLocation(const DebugLocEntry &Entry) {
Asm->OutStreamer.AddComment("Loc expr size");
MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol();