/// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified.
virtual unsigned getISAEncoding(const Function *) { return 0; }
+ /// Emit a dwarf register operation for describing
+ /// - a small value occupying only part of a register or
+ /// - a register representing only part of a value.
+ void EmitDwarfOpPiece(ByteStreamer &Streamer, unsigned SizeInBits,
+ unsigned OffsetInBits = 0) const;
+
+
+ /// \brief Emit a partial DWARF register operation.
+ /// \param MLoc the register
+ /// \param PieceSize size and
+ /// \param PieceOffset 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.
+ void EmitDwarfRegOpPiece(ByteStreamer &BS, const MachineLocation &MLoc,
+ unsigned PieceSize = 0,
+ unsigned PieceOffset = 0) const;
+
/// EmitDwarfRegOp - Emit a dwarf register operation.
virtual void EmitDwarfRegOp(ByteStreamer &BS,
const MachineLocation &MLoc) const;
//===----------------------------------------------------------------------===//
#include "ByteStreamer.h"
-#include "DwarfDebug.h"
#include "DwarfExpression.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetSubtargetInfo.h"
using namespace llvm;
#define DEBUG_TYPE "asm-printer"
+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;
+}
+
//===----------------------------------------------------------------------===//
// Dwarf Emission Helper Routines
//===----------------------------------------------------------------------===//
EmitLabelDifference(Label, SectionLabel, 4);
}
+// Some targets do not provide a DWARF register number for every
+// register. This function attempts to emit a DWARF register by
+// emitting a piece of a super-register or by piecing together
+// multiple subregisters that alias the register.
+void AsmPrinter::EmitDwarfRegOpPiece(ByteStreamer &Streamer,
+ const MachineLocation &MLoc,
+ unsigned PieceSizeInBits,
+ unsigned PieceOffsetInBits) const {
+ assert(MLoc.isReg() && "MLoc must be a register");
+ DebugLocDwarfExpression Expr(*this, Streamer);
+ Expr.AddMachineRegPiece(MLoc.getReg(), PieceSizeInBits, PieceOffsetInBits);
+}
+
+void AsmPrinter::EmitDwarfOpPiece(ByteStreamer &Streamer,
+ unsigned PieceSizeInBits,
+ unsigned PieceOffsetInBits) const {
+ DebugLocDwarfExpression Expr(*this, Streamer);
+ Expr.AddOpPiece(PieceSizeInBits, PieceOffsetInBits);
+}
+
/// EmitDwarfRegOp - Emit dwarf register operation.
void AsmPrinter::EmitDwarfRegOp(ByteStreamer &Streamer,
const MachineLocation &MLoc) const {
- DebugLocDwarfExpression Expr(*TM.getSubtargetImpl()->getRegisterInfo(),
- getDwarfDebug()->getDwarfVersion(), Streamer);
+ DebugLocDwarfExpression Expr(*this, Streamer);
const MCRegisterInfo *MRI = MMI->getContext().getRegisterInfo();
int Reg = MRI->getDwarfRegNum(MLoc.getReg(), false);
if (Reg < 0) {
#include "llvm/ADT/ArrayRef.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/MC/MCStreamer.h"
-#include "llvm/Support/LEB128.h"
-#include <string>
namespace llvm {
class ByteStreamer {
Hash.addULEB128(DWord);
}
};
-
-class BufferByteStreamer : public ByteStreamer {
-private:
- SmallVectorImpl<char> &Buffer;
- // FIXME: This is actually only needed for textual asm output.
- SmallVectorImpl<std::string> &Comments;
-
-public:
- BufferByteStreamer(SmallVectorImpl<char> &Buffer,
- SmallVectorImpl<std::string> &Comments)
- : Buffer(Buffer), Comments(Comments) {}
- void EmitInt8(uint8_t Byte, const Twine &Comment) override {
- Buffer.push_back(Byte);
- Comments.push_back(Comment.str());
- }
- void EmitSLEB128(uint64_t DWord, const Twine &Comment) override {
- raw_svector_ostream OSE(Buffer);
- encodeSLEB128(DWord, OSE);
- Comments.push_back(Comment.str());
- }
- void EmitULEB128(uint64_t DWord, const Twine &Comment) override {
- raw_svector_ostream OSE(Buffer);
- encodeULEB128(DWord, OSE);
- Comments.push_back(Comment.str());
- }
-};
-
}
#endif
#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H
#define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H
-#include "llvm/ADT/SmallString.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MachineLocation.h"
namespace llvm {
-class AsmPrinter;
class MDNode;
/// \brief This struct describes location entries emitted in the .debug_loc
/// section.
/// A nonempty list of locations/constants belonging to this entry,
/// sorted by offset.
SmallVector<Value, 1> Values;
- SmallString<8> DWARFBytes;
- SmallVector<std::string, 1> Comments;
public:
DebugLocEntry(const MCSymbol *B, const MCSymbol *E, Value Val)
}),
Values.end());
}
-
- void finalize(const AsmPrinter &AP,
- const DITypeIdentifierMap &TypeIdentifierMap);
- StringRef getDWARFBytes() const {
- assert(!DWARFBytes.empty() && "DebugLocEntry not finalized?");
- return DWARFBytes;
- }
- const SmallVectorImpl<std::string> &getComments() const {
- return Comments;
- }
};
/// Compare two Values for equality.
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
// 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.
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) {
- auto Comment = Entry.getComments().begin();
- auto End = Entry.getComments().end();
- for (uint8_t Byte : Entry.getDWARFBytes())
- Streamer.EmitInt8(Byte, Comment != End ? *(Comment++) : "");
+ 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);
}
-static void emitDebugLocValue(const AsmPrinter &AP,
- const DITypeIdentifierMap &TypeIdentifierMap,
- ByteStreamer &Streamer,
- const DebugLocEntry::Value &Value,
- unsigned PieceOffsetInBits) {
+void DwarfDebug::emitDebugLocValue(ByteStreamer &Streamer,
+ const DebugLocEntry::Value &Value,
+ unsigned PieceOffsetInBits) {
DIVariable DV = Value.getVariable();
- DebugLocDwarfExpression DwarfExpr(
- *AP.TM.getSubtargetImpl()->getRegisterInfo(),
- AP.getDwarfDebug()->getDwarfVersion(), Streamer);
+ DebugLocDwarfExpression DwarfExpr(*Asm, Streamer);
+
// Regular entry.
if (Value.isInt()) {
- DIBasicType BTy(DV.getType().resolve(TypeIdentifierMap));
+ DIBasicType BTy(resolve(DV.getType()));
if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed ||
BTy.getEncoding() == dwarf::DW_ATE_signed_char))
DwarfExpr.AddSignedConstant(Value.getInt());
DIExpression Expr = Value.getExpression();
if (!Expr || (Expr.getNumElements() == 0))
// Regular entry.
- AP.EmitDwarfRegOp(Streamer, Loc);
+ Asm->EmitDwarfRegOp(Streamer, Loc);
else {
// Complex address entry.
if (Loc.getOffset()) {
// 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();
/// \brief Emit an entry for the debug loc section. This can be used to
/// handle an entry that's going to be emitted into the debug loc section.
- void emitDebugLocEntry(ByteStreamer &Streamer,
- const DebugLocEntry &Entry);
+ void emitDebugLocEntry(ByteStreamer &Streamer, const DebugLocEntry &Entry);
/// \brief emit a single value for the debug loc section.
void emitDebugLocValue(ByteStreamer &Streamer,
const DebugLocEntry::Value &Value,
using namespace llvm;
+const TargetRegisterInfo *DwarfExpression::getTRI() const {
+ return AP.TM.getSubtargetImpl()->getRegisterInfo();
+}
+
+unsigned DwarfExpression::getDwarfVersion() const {
+ return AP.getDwarfDebug()->getDwarfVersion();
+}
+
void DwarfExpression::AddReg(int DwarfReg, const char *Comment) {
assert(DwarfReg >= 0 && "invalid negative dwarf register number");
if (DwarfReg < 32) {
}
bool DwarfExpression::AddMachineRegIndirect(unsigned MachineReg, int Offset) {
- int DwarfReg = TRI.getDwarfRegNum(MachineReg, false);
+ int DwarfReg = getTRI()->getDwarfRegNum(MachineReg, false);
if (DwarfReg < 0)
return false;
bool DwarfExpression::AddMachineRegPiece(unsigned MachineReg,
unsigned PieceSizeInBits,
unsigned PieceOffsetInBits) {
- if (!TRI.isPhysicalRegister(MachineReg))
+ const TargetRegisterInfo *TRI = getTRI();
+ if (!TRI->isPhysicalRegister(MachineReg))
return false;
- int Reg = TRI.getDwarfRegNum(MachineReg, false);
+ int Reg = TRI->getDwarfRegNum(MachineReg, false);
// If this is a valid register number, emit it.
if (Reg >= 0) {
// 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 (MCSuperRegIterator SR(MachineReg, &TRI); SR.isValid(); ++SR) {
- Reg = TRI.getDwarfRegNum(*SR, false);
+ for (MCSuperRegIterator SR(MachineReg, TRI); SR.isValid(); ++SR) {
+ Reg = TRI->getDwarfRegNum(*SR, false);
if (Reg >= 0) {
- unsigned Idx = TRI.getSubRegIndex(*SR, MachineReg);
- unsigned Size = TRI.getSubRegIdxSize(Idx);
- unsigned RegOffset = TRI.getSubRegIdxOffset(Idx);
+ unsigned Idx = TRI->getSubRegIndex(*SR, MachineReg);
+ unsigned Size = TRI->getSubRegIdxSize(Idx);
+ unsigned RegOffset = TRI->getSubRegIdxOffset(Idx);
AddReg(Reg, "super-register");
if (PieceOffsetInBits == RegOffset) {
AddOpPiece(Size, RegOffset);
// efficient DW_OP_piece.
unsigned CurPos = PieceOffsetInBits;
// The size of the register in bits, assuming 8 bits per byte.
- unsigned RegSize = TRI.getMinimalPhysRegClass(MachineReg)->getSize() * 8;
+ unsigned RegSize = TRI->getMinimalPhysRegClass(MachineReg)->getSize() * 8;
// Keep track of the bits in the register we already emitted, so we
// can avoid emitting redundant aliasing subregs.
SmallBitVector Coverage(RegSize, false);
- for (MCSubRegIterator SR(MachineReg, &TRI); SR.isValid(); ++SR) {
- unsigned Idx = TRI.getSubRegIndex(MachineReg, *SR);
- unsigned Size = TRI.getSubRegIdxSize(Idx);
- unsigned Offset = TRI.getSubRegIdxOffset(Idx);
- Reg = TRI.getDwarfRegNum(*SR, false);
+ for (MCSubRegIterator SR(MachineReg, TRI); SR.isValid(); ++SR) {
+ unsigned Idx = TRI->getSubRegIndex(MachineReg, *SR);
+ unsigned Size = TRI->getSubRegIdxSize(Idx);
+ unsigned Offset = TRI->getSubRegIdxOffset(Idx);
+ Reg = TRI->getDwarfRegNum(*SR, false);
// Intersection between the bits we already emitted and the bits
// covered by this subregister.
// value, so the producers and consumers started to rely on heuristics
// to disambiguate the value vs. location status of the expression.
// See PR21176 for more details.
- if (DwarfVersion >= 4)
+ if (getDwarfVersion() >= 4)
EmitOp(dwarf::DW_OP_stack_value);
}
EmitOp(dwarf::DW_OP_constu);
EmitUnsigned(Value);
// cf. comment in DwarfExpression::AddSignedConstant().
- if (DwarfVersion >= 4)
+ if (getDwarfVersion() >= 4)
EmitOp(dwarf::DW_OP_stack_value);
}
/// entry.
class DwarfExpression {
protected:
+ const AsmPrinter &AP;
// Various convenience accessors that extract things out of AsmPrinter.
- const TargetRegisterInfo &TRI;
- unsigned DwarfVersion;
+ const TargetRegisterInfo *getTRI() const;
+ unsigned getDwarfVersion() const;
public:
- DwarfExpression(const TargetRegisterInfo &TRI,
- unsigned DwarfVersion)
- : TRI(TRI), DwarfVersion(DwarfVersion) {}
+ DwarfExpression(const AsmPrinter &AP) : AP(AP) {}
virtual ~DwarfExpression() {}
/// Output a dwarf operand and an optional assembler comment.
ByteStreamer &BS;
public:
- DebugLocDwarfExpression(const TargetRegisterInfo &TRI,
- unsigned DwarfVersion, ByteStreamer &BS)
- : DwarfExpression(TRI, DwarfVersion), BS(BS) {}
+ DebugLocDwarfExpression(const AsmPrinter &AP, ByteStreamer &BS)
+ : DwarfExpression(AP), BS(BS) {}
void EmitOp(uint8_t Op, const char *Comment = nullptr) override;
void EmitSigned(int Value) override;
/// DwarfExpression implementation for singular DW_AT_location.
class DIEDwarfExpression : public DwarfExpression {
-const AsmPrinter &AP;
DwarfUnit &DU;
DIELoc &DIE;
public:
- DIEDwarfExpression(const AsmPrinter &AP, DwarfUnit &DU, DIELoc &DIE);
+ DIEDwarfExpression(const AsmPrinter &AP, DwarfUnit &DU, DIELoc &DIE)
+ : DwarfExpression(AP), DU(DU), DIE(DIE) {}
+
void EmitOp(uint8_t Op, const char *Comment = nullptr) override;
void EmitSigned(int Value) override;
void EmitUnsigned(unsigned Value) override;
cl::desc("Generate DWARF4 type units."),
cl::init(false));
-DIEDwarfExpression::DIEDwarfExpression(const AsmPrinter &AP,
- DwarfUnit &DU, DIELoc &DIE)
- : DwarfExpression(*AP.TM.getSubtargetImpl()->getRegisterInfo(),
- AP.getDwarfDebug()->getDwarfVersion()),
- AP(AP), DU(DU), DIE(DIE) {}
-
void DIEDwarfExpression::EmitOp(uint8_t Op, const char* Comment) {
DU.addUInt(DIE, dwarf::DW_FORM_data1, Op);
}
DU.addUInt(DIE, dwarf::DW_FORM_udata, Value);
}
bool DIEDwarfExpression::isFrameRegister(unsigned MachineReg) {
- return MachineReg == TRI.getFrameRegister(*AP.MF);
+ return MachineReg == getTRI()->getFrameRegister(*AP.MF);
}
target triple = "thumbv7-apple-macosx10.6.7"
;CHECK: sub-register DW_OP_regx
-;CHECK-NEXT: 256
+;CHECK-NEXT: ascii
;CHECK-NEXT: DW_OP_piece
-;CHECK-NEXT: 8
+;CHECK-NEXT: byte 8
;CHECK-NEXT: sub-register DW_OP_regx
-;CHECK-NEXT: 257
+;CHECK-NEXT: ascii
;CHECK-NEXT: DW_OP_piece
-;CHECK-NEXT: 8
+;CHECK-NEXT: byte 8
@.str = external constant [13 x i8]
; Radar 9309221
; Test dwarf reg no for s16
;CHECK: super-register DW_OP_regx
-;CHECK-NEXT: 264
+;CHECK-NEXT: ascii
;CHECK-NEXT: DW_OP_piece
;CHECK-NEXT: 4