aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DwarfUnit.cpp')
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfUnit.cpp167
1 files changed, 76 insertions, 91 deletions
diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 919d9d2..b0c7d48 100644
--- a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -12,10 +12,10 @@
//===----------------------------------------------------------------------===//
#include "DwarfUnit.h"
-
#include "DwarfAccelTable.h"
#include "DwarfCompileUnit.h"
#include "DwarfDebug.h"
+#include "DwarfExpression.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DIBuilder.h"
@@ -43,6 +43,20 @@ GenerateDwarfTypeUnits("generate-type-units", cl::Hidden,
cl::desc("Generate DWARF4 type units."),
cl::init(false));
+void DIEDwarfExpression::EmitOp(uint8_t Op, const char* Comment) {
+ DU.addUInt(DIE, dwarf::DW_FORM_data1, Op);
+}
+void DIEDwarfExpression::EmitSigned(int Value) {
+ DU.addSInt(DIE, dwarf::DW_FORM_sdata, Value);
+}
+void DIEDwarfExpression::EmitUnsigned(unsigned Value) {
+ DU.addUInt(DIE, dwarf::DW_FORM_udata, Value);
+}
+bool DIEDwarfExpression::isFrameRegister(unsigned MachineReg) {
+ return MachineReg == getTRI()->getFrameRegister(*AP.MF);
+}
+
+
/// Unit - Unit constructor.
DwarfUnit::DwarfUnit(unsigned UID, dwarf::Tag UnitTag, DICompileUnit Node,
AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU)
@@ -116,6 +130,30 @@ int64_t DwarfUnit::getDefaultLowerBound() const {
if (dwarf::DWARF_VERSION >= 4)
return 1;
break;
+
+ // The languages below have valid values only if the DWARF version >= 5.
+ case dwarf::DW_LANG_OpenCL:
+ case dwarf::DW_LANG_Go:
+ case dwarf::DW_LANG_Haskell:
+ case dwarf::DW_LANG_C_plus_plus_03:
+ case dwarf::DW_LANG_C_plus_plus_11:
+ case dwarf::DW_LANG_OCaml:
+ case dwarf::DW_LANG_Rust:
+ case dwarf::DW_LANG_C11:
+ case dwarf::DW_LANG_Swift:
+ case dwarf::DW_LANG_Dylan:
+ case dwarf::DW_LANG_C_plus_plus_14:
+ if (dwarf::DWARF_VERSION >= 5)
+ return 0;
+ break;
+
+ case dwarf::DW_LANG_Modula3:
+ case dwarf::DW_LANG_Julia:
+ case dwarf::DW_LANG_Fortran03:
+ case dwarf::DW_LANG_Fortran08:
+ if (dwarf::DWARF_VERSION >= 5)
+ return 1;
+ break;
}
return -1;
@@ -399,85 +437,18 @@ void DwarfUnit::addSourceLine(DIE &Die, DINameSpace NS) {
}
/// addRegisterOp - Add register operand.
-// FIXME: Ideally, this would share the implementation with
-// AsmPrinter::EmitDwarfRegOpPiece.
-void DwarfUnit::addRegisterOpPiece(DIELoc &TheDie, unsigned Reg,
+bool DwarfUnit::addRegisterOpPiece(DIELoc &TheDie, unsigned Reg,
unsigned SizeInBits, unsigned OffsetInBits) {
- const TargetRegisterInfo *RI = Asm->TM.getSubtargetImpl()->getRegisterInfo();
- int DWReg = RI->getDwarfRegNum(Reg, false);
- bool isSubRegister = DWReg < 0;
-
- unsigned Idx = 0;
-
- // Go up the super-register chain until we hit a valid dwarf register number.
- for (MCSuperRegIterator SR(Reg, RI); SR.isValid() && DWReg < 0; ++SR) {
- DWReg = RI->getDwarfRegNum(*SR, false);
- if (DWReg >= 0)
- Idx = RI->getSubRegIndex(*SR, Reg);
- }
-
- if (DWReg < 0) {
- DEBUG(dbgs() << "Invalid Dwarf register number.\n");
- addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_nop);
- return;
- }
-
- // Emit register.
- if (DWReg < 32)
- addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + DWReg);
- else {
- addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_regx);
- addUInt(TheDie, dwarf::DW_FORM_udata, DWReg);
- }
-
- // Emit mask.
- bool isPiece = SizeInBits > 0;
- if (isSubRegister || isPiece) {
- const unsigned SizeOfByte = 8;
- unsigned RegSizeInBits = RI->getSubRegIdxSize(Idx);
- unsigned RegOffsetInBits = RI->getSubRegIdxOffset(Idx);
- unsigned PieceSizeInBits = std::max(SizeInBits, RegSizeInBits);
- unsigned PieceOffsetInBits = OffsetInBits ? OffsetInBits : RegOffsetInBits;
- assert(RegSizeInBits >= SizeInBits && "register smaller than value");
-
- if (RegOffsetInBits != PieceOffsetInBits) {
- // Manually shift the value into place, since the DW_OP_piece
- // describes the part of the variable, not the position of the
- // subregister.
- addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
- addUInt(TheDie, dwarf::DW_FORM_data1, RegOffsetInBits);
- addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_shr);
- }
-
- if (PieceOffsetInBits > 0 || PieceSizeInBits % SizeOfByte) {
- assert(PieceSizeInBits > 0 && "piece has zero size");
- addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_bit_piece);
- addUInt(TheDie, dwarf::DW_FORM_data1, PieceSizeInBits);
- addUInt(TheDie, dwarf::DW_FORM_data1, PieceOffsetInBits);
- } else {
- assert(PieceSizeInBits > 0 && "piece has zero size");
- addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_piece);
- addUInt(TheDie, dwarf::DW_FORM_data1, PieceSizeInBits/SizeOfByte);
- }
- }
+ DIEDwarfExpression Expr(*Asm, *this, TheDie);
+ Expr.AddMachineRegPiece(Reg, SizeInBits, OffsetInBits);
+ return true;
}
/// addRegisterOffset - Add register offset.
-void DwarfUnit::addRegisterOffset(DIELoc &TheDie, unsigned Reg,
+bool DwarfUnit::addRegisterOffset(DIELoc &TheDie, unsigned Reg,
int64_t Offset) {
- const TargetRegisterInfo *RI = Asm->TM.getSubtargetImpl()->getRegisterInfo();
- unsigned DWReg = RI->getDwarfRegNum(Reg, false);
- const TargetRegisterInfo *TRI = Asm->TM.getSubtargetImpl()->getRegisterInfo();
- if (Reg == TRI->getFrameRegister(*Asm->MF))
- // If variable offset is based in frame register then use fbreg.
- addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_fbreg);
- else if (DWReg < 32)
- addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + DWReg);
- else {
- addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx);
- addUInt(TheDie, dwarf::DW_FORM_udata, DWReg);
- }
- addSInt(TheDie, dwarf::DW_FORM_sdata, Offset);
+ DIEDwarfExpression Expr(*Asm, *this, TheDie);
+ return Expr.AddMachineRegIndirect(Reg, Offset);
}
/* Byref variables, in Blocks, are declared by the programmer as "SomeType
@@ -581,10 +552,14 @@ void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE &Die,
// variable's location.
DIELoc *Loc = new (DIEValueAllocator) DIELoc();
+ bool validReg;
if (Location.isReg())
- addRegisterOpPiece(*Loc, Location.getReg());
+ validReg = addRegisterOpPiece(*Loc, Location.getReg());
else
- addRegisterOffset(*Loc, Location.getReg(), Location.getOffset());
+ validReg = addRegisterOffset(*Loc, Location.getReg(), Location.getOffset());
+
+ if (!validReg)
+ return;
// If we started with a pointer to the __Block_byref... struct, then
// the first thing we need to do is dereference the pointer (DW_OP_deref).
@@ -622,13 +597,19 @@ static bool isUnsignedDIType(DwarfDebug *DD, DIType Ty) {
dwarf::Tag T = (dwarf::Tag)Ty.getTag();
// Encode pointer constants as unsigned bytes. This is used at least for
// null pointer constant emission.
+ // (Pieces of) aggregate types that get hacked apart by SROA may also be
+ // represented by a constant. Encode them as unsigned bytes.
// FIXME: reference and rvalue_reference /probably/ shouldn't be allowed
// here, but accept them for now due to a bug in SROA producing bogus
// dbg.values.
- if (T == dwarf::DW_TAG_pointer_type ||
+ if (T == dwarf::DW_TAG_array_type ||
+ T == dwarf::DW_TAG_class_type ||
+ T == dwarf::DW_TAG_pointer_type ||
T == dwarf::DW_TAG_ptr_to_member_type ||
T == dwarf::DW_TAG_reference_type ||
- T == dwarf::DW_TAG_rvalue_reference_type)
+ T == dwarf::DW_TAG_rvalue_reference_type ||
+ T == dwarf::DW_TAG_structure_type ||
+ T == dwarf::DW_TAG_union_type)
return true;
assert(T == dwarf::DW_TAG_typedef || T == dwarf::DW_TAG_const_type ||
T == dwarf::DW_TAG_volatile_type ||
@@ -649,11 +630,15 @@ static bool isUnsignedDIType(DwarfDebug *DD, DIType Ty) {
Encoding == dwarf::DW_ATE_unsigned_char ||
Encoding == dwarf::DW_ATE_signed ||
Encoding == dwarf::DW_ATE_signed_char ||
- Encoding == dwarf::DW_ATE_UTF || Encoding == dwarf::DW_ATE_boolean) &&
+ Encoding == dwarf::DW_ATE_float ||
+ Encoding == dwarf::DW_ATE_UTF || Encoding == dwarf::DW_ATE_boolean ||
+ (Ty.getTag() == dwarf::DW_TAG_unspecified_type &&
+ Ty.getName() == "decltype(nullptr)")) &&
"Unsupported encoding");
return (Encoding == dwarf::DW_ATE_unsigned ||
Encoding == dwarf::DW_ATE_unsigned_char ||
- Encoding == dwarf::DW_ATE_UTF || Encoding == dwarf::DW_ATE_boolean);
+ Encoding == dwarf::DW_ATE_UTF || Encoding == dwarf::DW_ATE_boolean ||
+ Ty.getTag() == dwarf::DW_TAG_unspecified_type);
}
/// If this type is derived from a base type then return base type size.
@@ -667,10 +652,7 @@ static uint64_t getBaseTypeSize(DwarfDebug *DD, DIDerivedType Ty) {
DIType BaseType = DD->resolve(Ty.getTypeDerivedFrom());
- // If this type is not derived from any type or the type is a declaration then
- // take conservative approach.
- if (!BaseType.isValid() || BaseType.isForwardDecl())
- return Ty.getSizeInBits();
+ assert(BaseType.isValid() && "Unexpected invalid base type");
// If this is a derived type, go ahead and get the base type, unless it's a
// reference then it's just the size of the field. Pointer types have no need
@@ -977,7 +959,8 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) {
addString(Buffer, dwarf::DW_AT_name, Name);
// Add size if non-zero (derived types might be zero-sized.)
- if (Size && Tag != dwarf::DW_TAG_pointer_type)
+ if (Size && Tag != dwarf::DW_TAG_pointer_type
+ && Tag != dwarf::DW_TAG_ptr_to_member_type)
addUInt(Buffer, dwarf::DW_AT_byte_size, None, Size);
if (Tag == dwarf::DW_TAG_ptr_to_member_type)
@@ -1110,6 +1093,8 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
if (CTy.isAppleBlockExtension())
addFlag(Buffer, dwarf::DW_AT_APPLE_block);
+ // This is outside the DWARF spec, but GDB expects a DW_AT_containing_type
+ // inside C++ composite types to point to the base class with the vtable.
DICompositeType ContainingType(resolve(CTy.getContainingType()));
if (ContainingType)
addDIEEntry(Buffer, dwarf::DW_AT_containing_type,
@@ -1187,10 +1172,10 @@ DwarfUnit::constructTemplateValueParameterDIE(DIE &Buffer,
addType(ParamDIE, resolve(VP.getType()));
if (!VP.getName().empty())
addString(ParamDIE, dwarf::DW_AT_name, VP.getName());
- if (Value *Val = VP.getValue()) {
- if (ConstantInt *CI = dyn_cast<ConstantInt>(Val))
+ if (Metadata *Val = VP.getValue()) {
+ if (ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(Val))
addConstantValue(ParamDIE, CI, resolve(VP.getType()));
- else if (GlobalValue *GV = dyn_cast<GlobalValue>(Val)) {
+ else if (GlobalValue *GV = mdconst::dyn_extract<GlobalValue>(Val)) {
// For declaration non-type template parameters (such as global values and
// functions)
DIELoc *Loc = new (DIEValueAllocator) DIELoc();
@@ -1359,7 +1344,7 @@ void DwarfUnit::applySubprogramAttributes(DISubprogram SP, DIE &SPDie,
if (SP.isOptimized())
addFlag(SPDie, dwarf::DW_AT_APPLE_optimized);
- if (unsigned isa = Asm->getISAEncoding()) {
+ if (unsigned isa = Asm->getISAEncoding(SP.getFunction())) {
addUInt(SPDie, dwarf::DW_AT_APPLE_isa, dwarf::DW_FORM_flag, isa);
}
@@ -1511,7 +1496,7 @@ void DwarfUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) {
uint64_t FieldSize = getBaseTypeSize(DD, DT);
uint64_t OffsetInBytes;
- if (Size != FieldSize) {
+ if (FieldSize && Size != FieldSize) {
// Handle bitfield, assume bytes are 8 bits.
addUInt(MemberDie, dwarf::DW_AT_byte_size, None, FieldSize/8);
addUInt(MemberDie, dwarf::DW_AT_bit_size, None, Size);