#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
using namespace llvm;
DIEValue *Value;
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
Value = new (DIEValueAllocator) DIELabel(Symb);
- else {
- MCSymbol *StringPool = DU->getStringPool().getSectionSymbol();
- Value = new (DIEValueAllocator) DIEDelta(Symb, StringPool);
- }
+ else
+ Value = new (DIEValueAllocator) DIEDelta(Symb, DD->getDebugStrSym());
DIEValue *Str = new (DIEValueAllocator) DIEString(Value, String);
Die.addValue(Attribute, dwarf::DW_FORM_strp, Str);
}
void DwarfCompileUnit::addLabelAddress(DIE &Die, dwarf::Attribute Attribute,
const MCSymbol *Label) {
- if (!DD->useSplitDwarf())
+ // Don't use the address pool in non-fission or in the skeleton unit itself.
+ // FIXME: Once GDB supports this, it's probably worthwhile using the address
+ // pool from the skeleton - maybe even in non-fission (possibly fewer
+ // relocations by sharing them in the pool, but we have other ideas about how
+ // to reduce the number of relocations as well/instead).
+ if (!DD->useSplitDwarf() || !Skeleton)
return addLocalLabelAddress(Die, Attribute, Label);
if (Label)
}
/// addRegisterOp - Add register operand.
-void DwarfUnit::addRegisterOp(DIELoc &TheDie, unsigned Reg) {
- const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
+// FIXME: Ideally, this would share the implementation with
+// AsmPrinter::EmitDwarfRegOpPiece.
+void 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;
return;
}
- // Emit register
+ // Emit register.
if (DWReg < 32)
addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + DWReg);
else {
addUInt(TheDie, dwarf::DW_FORM_udata, DWReg);
}
- // Emit Mask
- if (isSubRegister) {
- unsigned Size = RI->getSubRegIdxSize(Idx);
- unsigned Offset = RI->getSubRegIdxOffset(Idx);
- if (Offset > 0) {
+ // 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, Size);
- addUInt(TheDie, dwarf::DW_FORM_data1, Offset);
- } else {
- unsigned ByteSize = Size / 8; // Assuming 8 bits per byte.
+ 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, ByteSize);
+ addUInt(TheDie, dwarf::DW_FORM_data1, PieceSizeInBits/SizeOfByte);
}
}
}
/// addRegisterOffset - Add register offset.
void DwarfUnit::addRegisterOffset(DIELoc &TheDie, unsigned Reg,
int64_t Offset) {
- const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
+ const TargetRegisterInfo *RI = Asm->TM.getSubtargetImpl()->getRegisterInfo();
unsigned DWReg = RI->getDwarfRegNum(Reg, false);
- const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo();
+ 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);
DIELoc *Loc = new (DIEValueAllocator) DIELoc();
if (Location.isReg() && !Indirect)
- addRegisterOp(*Loc, Location.getReg());
+ addRegisterOpPiece(*Loc, Location.getReg());
else {
addRegisterOffset(*Loc, Location.getReg(), Location.getOffset());
if (Indirect && !Location.isReg()) {
// DW_OP_breg + Offset instead of DW_OP_reg + Offset.
addRegisterOffset(*Loc, Location.getReg(), DV.getAddrElement(1));
i = 2;
+ } else if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpDeref) {
+ addRegisterOpPiece(*Loc, Location.getReg(),
+ DV.getVariable().getPieceSize(),
+ DV.getVariable().getPieceOffset());
+ i = 3;
} else
- addRegisterOp(*Loc, Location.getReg());
+ addRegisterOpPiece(*Loc, Location.getReg());
} else
addRegisterOffset(*Loc, Location.getReg(), Location.getOffset());
if (Element == DIBuilder::OpPlus) {
addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
addUInt(*Loc, dwarf::DW_FORM_udata, DV.getAddrElement(++i));
+
} else if (Element == DIBuilder::OpDeref) {
if (!Location.isReg())
addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
+
+ } else if (Element == DIBuilder::OpPiece) {
+ const unsigned SizeOfByte = 8;
+ unsigned PieceOffsetInBits = DV.getAddrElement(++i)*SizeOfByte;
+ unsigned PieceSizeInBits = DV.getAddrElement(++i)*SizeOfByte;
+ // Emit DW_OP_bit_piece Size Offset.
+ assert(PieceSizeInBits > 0 && "piece has zero size");
+ addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_bit_piece);
+ addUInt(*Loc, dwarf::DW_FORM_udata, PieceSizeInBits);
+ addUInt(*Loc, dwarf::DW_FORM_udata, PieceOffsetInBits);
+
} else
llvm_unreachable("unknown DIBuilder Opcode");
}
DIELoc *Loc = new (DIEValueAllocator) DIELoc();
if (Location.isReg())
- addRegisterOp(*Loc, Location.getReg());
+ addRegisterOpPiece(*Loc, Location.getReg());
else
addRegisterOffset(*Loc, Location.getReg(), Location.getOffset());
bool isPrototyped = true;
if (Elements.getNumElements() == 2 &&
- !resolve(Elements.getElement(1)))
+ !Elements.getElement(1))
isPrototyped = false;
constructSubprogramArguments(Buffer, Elements);
if (!SP.getName().empty())
addString(SPDie, dwarf::DW_AT_name, SP.getName());
+ // Skip the rest of the attributes under -gmlt to save space.
+ if(getCUNode().getEmissionKind() == DIBuilder::LineTablesOnly)
+ return;
+
addSourceLine(SPDie, SP);
// Add the prototype if we have a prototype and we have a C like
else if (SP.isPrivate())
addUInt(SPDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
dwarf::DW_ACCESS_private);
- else
+ else if (SP.isPublic())
addUInt(SPDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
dwarf::DW_ACCESS_public);
return CE;
}
-/// createGlobalVariableDIE - create global variable DIE.
-void DwarfCompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) {
+/// getOrCreateGlobalVariableDIE - get or create global variable DIE.
+DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(DIGlobalVariable GV) {
// Check for pre-existence.
- if (getDIE(GV))
- return;
+ if (DIE *Die = getDIE(GV))
+ return Die;
assert(GV.isGlobalVariable());
DD->addArangeLabel(SymbolCU(this, Sym));
addOpAddress(*Loc, Sym);
}
+ // A static member's declaration is already flagged as such.
+ if (!SDMDecl.Verify() && !GV.isDefinition())
+ addFlag(*VariableDIE, dwarf::DW_AT_declaration);
// Do not create specification DIE if context is either compile unit
// or a subprogram.
if (GVContext && GV.isDefinition() && !GVContext.isCompileUnit() &&
addBlock(*VariableDIE, dwarf::DW_AT_location, Loc);
}
+ DIE *ResultDIE = VariableSpecDIE ? VariableSpecDIE : VariableDIE;
+
if (addToAccelTable) {
- DIE &AddrDIE = VariableSpecDIE ? *VariableSpecDIE : *VariableDIE;
- DD->addAccelName(GV.getName(), AddrDIE);
+ DD->addAccelName(GV.getName(), *ResultDIE);
// If the linkage name is different than the name, go ahead and output
// that as well into the name table.
if (GV.getLinkageName() != "" && GV.getName() != GV.getLinkageName())
- DD->addAccelName(GV.getLinkageName(), AddrDIE);
+ DD->addAccelName(GV.getLinkageName(), *ResultDIE);
}
- addGlobalName(GV.getName(), VariableSpecDIE ? *VariableSpecDIE : *VariableDIE,
- GV.getContext());
+ addGlobalName(GV.getName(), *ResultDIE, GV.getContext());
+ return ResultDIE;
}
/// constructSubrangeDIE - Construct subrange DIE from DISubrange.
// The LowerBound value defines the lower bounds which is typically zero for
// C/C++. The Count value is the number of elements. Values are 64 bit. If
// Count == -1 then the array is unbounded and we do not emit
- // DW_AT_lower_bound and DW_AT_upper_bound attributes. If LowerBound == 0 and
- // Count == 0, then the array has zero elements in which case we do not emit
- // an upper bound.
+ // DW_AT_lower_bound and DW_AT_count attributes.
int64_t LowerBound = SR.getLo();
int64_t DefaultLowerBound = getDefaultLowerBound();
int64_t Count = SR.getCount();
if (DefaultLowerBound == -1 || LowerBound != DefaultLowerBound)
addUInt(DW_Subrange, dwarf::DW_AT_lower_bound, None, LowerBound);
- if (Count != -1 && Count != 0)
+ if (Count != -1)
// FIXME: An unbounded array should reference the expression that defines
// the array.
- addUInt(DW_Subrange, dwarf::DW_AT_upper_bound, None,
- LowerBound + Count - 1);
+ addUInt(DW_Subrange, dwarf::DW_AT_count, None, Count);
}
/// constructArrayTypeDIE - Construct array type DIE from DICompositeType.
int FI = DV.getFrameIndex();
if (FI != ~0) {
unsigned FrameReg = 0;
- const TargetFrameLowering *TFI = Asm->TM.getFrameLowering();
+ const TargetFrameLowering *TFI =
+ Asm->TM.getSubtargetImpl()->getFrameLowering();
int Offset = TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg);
MachineLocation Location(FrameReg, Offset);
addVariableAddress(DV, *VariableDie, Location);
addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
dwarf::DW_ACCESS_private);
// Otherwise C++ member and base classes are considered public.
- else
+ else if (DT.isPublic())
addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
dwarf::DW_ACCESS_public);
if (DT.isVirtual())
else if (DT.isPrivate())
addUInt(StaticMemberDIE, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
dwarf::DW_ACCESS_private);
- else
+ else if (DT.isPublic())
addUInt(StaticMemberDIE, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
dwarf::DW_ACCESS_public);
Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
}
-void DwarfUnit::addRange(RangeSpan Range) {
- // Only add a range for this unit if we're emitting full debug.
- if (getCUNode().getEmissionKind() == DIBuilder::FullDebug) {
- // If we have no current ranges just add the range and return, otherwise,
- // check the current section and CU against the previous section and CU we
- // emitted into and the subprogram was contained within. If these are the
- // same then extend our current range, otherwise add this as a new range.
- if (CURanges.size() == 0 ||
- this != DD->getPrevCU() ||
- Asm->getCurrentSection() != DD->getPrevSection()) {
- CURanges.push_back(Range);
- return;
- }
-
- assert(&(CURanges.back().getEnd()->getSection()) ==
- &(Range.getEnd()->getSection()) &&
- "We can only append to a range in the same section!");
- CURanges.back().setEnd(Range.getEnd());
+void DwarfCompileUnit::addRange(RangeSpan Range) {
+ bool SameAsPrevCU = this == DD->getPrevCU();
+ DD->setPrevCU(this);
+ // If we have no current ranges just add the range and return, otherwise,
+ // check the current section and CU against the previous section and CU we
+ // emitted into and the subprogram was contained within. If these are the
+ // same then extend our current range, otherwise add this as a new range.
+ if (CURanges.empty() || !SameAsPrevCU ||
+ (&CURanges.back().getEnd()->getSection() !=
+ &Range.getEnd()->getSection())) {
+ CURanges.push_back(Range);
+ return;
}
+
+ CURanges.back().setEnd(Range.getEnd());
}
void DwarfCompileUnit::initStmtList(MCSymbol *DwarfLineSectionSym) {