X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FAsmPrinter%2FDwarfUnit.cpp;h=c1f0538e4cf16cae1de8c6c1d53baa62baa05236;hb=4debb773263d74a2982c776ef3fe54f7f5ec5af1;hp=42c1cbf768a377470b140aa5f750023b5dc1834b;hpb=c6c93e96e991e15b6db37e038de8023dbc136a40;p=oota-llvm.git diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 42c1cbf768a..c1f0538e4cf 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -17,8 +17,8 @@ #include "DwarfAccelTable.h" #include "DwarfDebug.h" #include "llvm/ADT/APFloat.h" -#include "llvm/DIBuilder.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instructions.h" @@ -56,15 +56,20 @@ DwarfCompileUnit::DwarfCompileUnit(unsigned UID, DIE *D, DICompileUnit Node, } DwarfTypeUnit::DwarfTypeUnit(unsigned UID, DIE *D, DwarfCompileUnit &CU, - AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU) - : DwarfUnit(UID, D, CU.getCUNode(), A, DW, DWU), CU(CU) { - (void)CU; + AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU, + MCDwarfDwoLineTable *SplitLineTable) + : DwarfUnit(UID, D, CU.getCUNode(), A, DW, DWU), CU(CU), + SplitLineTable(SplitLineTable) { + if (SplitLineTable) + addSectionOffset(UnitDie.get(), dwarf::DW_AT_stmt_list, 0); } /// ~Unit - Destructor for compile unit. DwarfUnit::~DwarfUnit() { for (unsigned j = 0, M = DIEBlocks.size(); j < M; ++j) DIEBlocks[j]->~DIEBlock(); + for (unsigned j = 0, M = DIELocs.size(); j < M; ++j) + DIELocs[j]->~DIELoc(); } /// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug @@ -172,7 +177,7 @@ void DwarfUnit::addUInt(DIE *Die, dwarf::Attribute Attribute, Die->addValue(Attribute, *Form, Value); } -void DwarfUnit::addUInt(DIEBlock *Block, dwarf::Form Form, uint64_t Integer) { +void DwarfUnit::addUInt(DIE *Block, dwarf::Form Form, uint64_t Integer) { addUInt(Block, (dwarf::Attribute)0, Form, Integer); } @@ -186,7 +191,7 @@ void DwarfUnit::addSInt(DIE *Die, dwarf::Attribute Attribute, Die->addValue(Attribute, *Form, Value); } -void DwarfUnit::addSInt(DIEBlock *Die, Optional Form, +void DwarfUnit::addSInt(DIELoc *Die, Optional Form, int64_t Integer) { addSInt(Die, (dwarf::Attribute)0, Form, Integer); } @@ -226,11 +231,21 @@ void DwarfUnit::addLocalString(DIE *Die, dwarf::Attribute Attribute, /// addExpr - Add a Dwarf expression attribute data and value. /// -void DwarfUnit::addExpr(DIEBlock *Die, dwarf::Form Form, const MCExpr *Expr) { +void DwarfUnit::addExpr(DIELoc *Die, dwarf::Form Form, const MCExpr *Expr) { DIEValue *Value = new (DIEValueAllocator) DIEExpr(Expr); Die->addValue((dwarf::Attribute)0, Form, Value); } +/// addLocationList - Add a Dwarf loclistptr attribute data and value. +/// +void DwarfUnit::addLocationList(DIE *Die, dwarf::Attribute Attribute, + unsigned Index) { + DIEValue *Value = new (DIEValueAllocator) DIELocList(Index); + dwarf::Form Form = DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset + : dwarf::DW_FORM_data4; + Die->addValue(Attribute, Form, Value); +} + /// addLabel - Add a Dwarf label attribute data and value. /// void DwarfUnit::addLabel(DIE *Die, dwarf::Attribute Attribute, dwarf::Form Form, @@ -239,8 +254,7 @@ void DwarfUnit::addLabel(DIE *Die, dwarf::Attribute Attribute, dwarf::Form Form, Die->addValue(Attribute, Form, Value); } -void DwarfUnit::addLabel(DIEBlock *Die, dwarf::Form Form, - const MCSymbol *Label) { +void DwarfUnit::addLabel(DIELoc *Die, dwarf::Form Form, const MCSymbol *Label) { addLabel(Die, (dwarf::Attribute)0, Form, Label); } @@ -268,29 +282,54 @@ void DwarfUnit::addSectionOffset(DIE *Die, dwarf::Attribute Attribute, /// DW_FORM_addr or DW_FORM_GNU_addr_index. /// void DwarfCompileUnit::addLabelAddress(DIE *Die, dwarf::Attribute Attribute, - MCSymbol *Label) { + const MCSymbol *Label) { + + if (!DD->useSplitDwarf()) + return addLocalLabelAddress(Die, Attribute, Label); + if (Label) DD->addArangeLabel(SymbolCU(this, Label)); - if (!DD->useSplitDwarf()) { - if (Label) { - DIEValue *Value = new (DIEValueAllocator) DIELabel(Label); - Die->addValue(Attribute, dwarf::DW_FORM_addr, Value); - } else { - DIEValue *Value = new (DIEValueAllocator) DIEInteger(0); - Die->addValue(Attribute, dwarf::DW_FORM_addr, Value); - } + unsigned idx = DU->getAddrPoolIndex(Label); + DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx); + Die->addValue(Attribute, dwarf::DW_FORM_GNU_addr_index, Value); +} + +void DwarfCompileUnit::addLocalLabelAddress(DIE *Die, + dwarf::Attribute Attribute, + const MCSymbol *Label) { + if (Label) + DD->addArangeLabel(SymbolCU(this, Label)); + + if (Label) { + DIEValue *Value = new (DIEValueAllocator) DIELabel(Label); + Die->addValue(Attribute, dwarf::DW_FORM_addr, Value); } else { - unsigned idx = DU->getAddrPoolIndex(Label); - DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx); - Die->addValue(Attribute, dwarf::DW_FORM_GNU_addr_index, Value); + DIEValue *Value = new (DIEValueAllocator) DIEInteger(0); + Die->addValue(Attribute, dwarf::DW_FORM_addr, Value); } } +unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName, StringRef DirName) { + // If we print assembly, we can't separate .file entries according to + // compile units. Thus all files will belong to the default compile unit. + + // FIXME: add a better feature test than hasRawTextSupport. Even better, + // extend .file to support this. + return Asm->OutStreamer.EmitDwarfFileDirective( + 0, DirName, FileName, + Asm->OutStreamer.hasRawTextSupport() ? 0 : getUniqueID()); +} + +unsigned DwarfTypeUnit::getOrCreateSourceID(StringRef FileName, StringRef DirName) { + return SplitLineTable ? SplitLineTable->getFile(DirName, FileName) + : getCU().getOrCreateSourceID(FileName, DirName); +} + /// addOpAddress - Add a dwarf op address data and value using the /// form given and an op of either DW_FORM_addr or DW_FORM_GNU_addr_index. /// -void DwarfUnit::addOpAddress(DIEBlock *Die, const MCSymbol *Sym) { +void DwarfUnit::addOpAddress(DIELoc *Die, const MCSymbol *Sym) { if (!DD->useSplitDwarf()) { addUInt(Die, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); addLabel(Die, dwarf::DW_FORM_udata, Sym); @@ -311,6 +350,12 @@ void DwarfUnit::addSectionDelta(DIE *Die, dwarf::Attribute Attribute, Die->addValue(Attribute, dwarf::DW_FORM_data4, Value); } +void DwarfUnit::addLabelDelta(DIE *Die, dwarf::Attribute Attribute, + const MCSymbol *Hi, const MCSymbol *Lo) { + DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo); + Die->addValue(Attribute, dwarf::DW_FORM_data4, Value); +} + /// addDIEEntry - Add a DIE attribute data and value. /// void DwarfUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIE *Entry) { @@ -339,7 +384,9 @@ void DwarfUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute, /// Create a DIE with the given Tag, add the DIE to its parent, and /// call insertDIE if MD is not null. DIE *DwarfUnit::createAndAddDIE(unsigned Tag, DIE &Parent, DIDescriptor N) { - DIE *Die = new DIE(Tag); + assert(Tag != dwarf::DW_TAG_auto_variable && + Tag != dwarf::DW_TAG_arg_variable); + DIE *Die = new DIE((dwarf::Tag)Tag); Parent.addChild(Die); if (N) insertDIE(N, Die); @@ -348,6 +395,12 @@ DIE *DwarfUnit::createAndAddDIE(unsigned Tag, DIE &Parent, DIDescriptor N) { /// addBlock - Add block data. /// +void DwarfUnit::addBlock(DIE *Die, dwarf::Attribute Attribute, DIELoc *Loc) { + Loc->ComputeSize(Asm); + DIELocs.push_back(Loc); // Memoize so we can call the destructor later on. + Die->addValue(Attribute, Loc->BestForm(DD->getDwarfVersion()), Loc); +} + void DwarfUnit::addBlock(DIE *Die, dwarf::Attribute Attribute, DIEBlock *Block) { Block->ComputeSize(Asm); @@ -362,7 +415,7 @@ void DwarfUnit::addSourceLine(DIE *Die, unsigned Line, StringRef File, if (Line == 0) return; - unsigned FileID = DD->getOrCreateSourceID(File, Directory, getUniqueID()); + unsigned FileID = getOrCreateSourceID(File, Directory); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, None, FileID); addUInt(Die, dwarf::DW_AT_decl_line, None, Line); @@ -373,7 +426,8 @@ void DwarfUnit::addSourceLine(DIE *Die, unsigned Line, StringRef File, void DwarfUnit::addSourceLine(DIE *Die, DIVariable V) { assert(V.isVariable()); - addSourceLine(Die, V.getLineNumber(), V.getContext().getFilename(), V.getContext().getDirectory()); + addSourceLine(Die, V.getLineNumber(), V.getContext().getFilename(), + V.getContext().getDirectory()); } /// addSourceLine - Add location information to specified debug information @@ -432,7 +486,7 @@ void DwarfUnit::addVariableAddress(const DbgVariable &DV, DIE *Die, } /// addRegisterOp - Add register operand. -void DwarfUnit::addRegisterOp(DIEBlock *TheDie, unsigned Reg) { +void DwarfUnit::addRegisterOp(DIELoc *TheDie, unsigned Reg) { const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); int DWReg = RI->getDwarfRegNum(Reg, false); bool isSubRegister = DWReg < 0; @@ -447,7 +501,7 @@ void DwarfUnit::addRegisterOp(DIEBlock *TheDie, unsigned Reg) { } if (DWReg < 0) { - DEBUG(llvm::dbgs() << "Invalid Dwarf register number.\n"); + DEBUG(dbgs() << "Invalid Dwarf register number.\n"); addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_nop); return; } @@ -469,14 +523,15 @@ void DwarfUnit::addRegisterOp(DIEBlock *TheDie, unsigned Reg) { 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, dwarf::DW_OP_piece); - addUInt(TheDie, dwarf::DW_FORM_data1, Size); + addUInt(TheDie, dwarf::DW_FORM_data1, ByteSize); } } } /// addRegisterOffset - Add register offset. -void DwarfUnit::addRegisterOffset(DIEBlock *TheDie, unsigned Reg, +void DwarfUnit::addRegisterOffset(DIELoc *TheDie, unsigned Reg, int64_t Offset) { const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); unsigned DWReg = RI->getDwarfRegNum(Reg, false); @@ -497,19 +552,19 @@ void DwarfUnit::addRegisterOffset(DIEBlock *TheDie, unsigned Reg, /// provided. void DwarfUnit::addAddress(DIE *Die, dwarf::Attribute Attribute, const MachineLocation &Location, bool Indirect) { - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); if (Location.isReg() && !Indirect) - addRegisterOp(Block, Location.getReg()); + addRegisterOp(Loc, Location.getReg()); else { - addRegisterOffset(Block, Location.getReg(), Location.getOffset()); + addRegisterOffset(Loc, Location.getReg(), Location.getOffset()); if (Indirect && !Location.isReg()) { - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); } } // Now attach the location information to the DIE. - addBlock(Die, Attribute, Block); + addBlock(Die, Attribute, Loc); } /// addComplexAddress - Start with the address based on the location provided, @@ -520,34 +575,34 @@ void DwarfUnit::addAddress(DIE *Die, dwarf::Attribute Attribute, void DwarfUnit::addComplexAddress(const DbgVariable &DV, DIE *Die, dwarf::Attribute Attribute, const MachineLocation &Location) { - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); unsigned N = DV.getNumAddrElements(); unsigned i = 0; if (Location.isReg()) { if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) { // If first address element is OpPlus then emit // DW_OP_breg + Offset instead of DW_OP_reg + Offset. - addRegisterOffset(Block, Location.getReg(), DV.getAddrElement(1)); + addRegisterOffset(Loc, Location.getReg(), DV.getAddrElement(1)); i = 2; } else - addRegisterOp(Block, Location.getReg()); + addRegisterOp(Loc, Location.getReg()); } else - addRegisterOffset(Block, Location.getReg(), Location.getOffset()); + addRegisterOffset(Loc, Location.getReg(), Location.getOffset()); for (; i < N; ++i) { uint64_t Element = DV.getAddrElement(i); if (Element == DIBuilder::OpPlus) { - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - addUInt(Block, dwarf::DW_FORM_udata, DV.getAddrElement(++i)); + 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(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); } else llvm_unreachable("unknown DIBuilder Opcode"); } // Now attach the location information to the DIE. - addBlock(Die, Attribute, Block); + addBlock(Die, Attribute, Loc); } /* Byref variables, in Blocks, are declared by the programmer as "SomeType @@ -649,40 +704,40 @@ void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE *Die, // Decode the original location, and use that as the start of the byref // variable's location. - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); if (Location.isReg()) - addRegisterOp(Block, Location.getReg()); + addRegisterOp(Loc, Location.getReg()); else - addRegisterOffset(Block, Location.getReg(), Location.getOffset()); + addRegisterOffset(Loc, Location.getReg(), Location.getOffset()); // 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). if (isPointer) - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); // Next add the offset for the '__forwarding' field: // DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in // adding the offset if it's 0. if (forwardingFieldOffset > 0) { - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - addUInt(Block, dwarf::DW_FORM_udata, forwardingFieldOffset); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(Loc, dwarf::DW_FORM_udata, forwardingFieldOffset); } // Now dereference the __forwarding field to get to the real __Block_byref // struct: DW_OP_deref. - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); // Now that we've got the real __Block_byref... struct, add the offset // for the variable's field to get to the location of the actual variable: // DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0. if (varFieldOffset > 0) { - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - addUInt(Block, dwarf::DW_FORM_udata, varFieldOffset); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(Loc, dwarf::DW_FORM_udata, varFieldOffset); } // Now attach the location information to the DIE. - addBlock(Die, Attribute, Block); + addBlock(Die, Attribute, Loc); } /// isTypeSigned - Return true if the type is signed. @@ -727,8 +782,9 @@ static uint64_t getBaseTypeSize(DwarfDebug *DD, DIDerivedType Ty) { DIType BaseType = DD->resolve(Ty.getTypeDerivedFrom()); - // If this type is not derived from any type then take conservative approach. - if (!BaseType.isValid()) + // 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(); // If this is a derived type, go ahead and get the base type, unless it's a @@ -926,6 +982,8 @@ DIE *DwarfUnit::getOrCreateTypeDIE(const MDNode *TyNode) { DIType Ty(TyNode); assert(Ty.isType()); + assert(Ty == resolve(Ty.getRef()) && + "type was not uniqued, possible ODR violation."); // Construct the context before querying for the existence of the DIE in case // such construction creates the DIE. @@ -940,6 +998,8 @@ DIE *DwarfUnit::getOrCreateTypeDIE(const MDNode *TyNode) { // Create new type. TyDIE = createAndAddDIE(Ty.getTag(), *ContextDIE, Ty); + updateAcceleratorTables(Context, Ty, TyDIE); + if (Ty.isBasicType()) constructTypeDIE(*TyDIE, DIBasicType(Ty)); else if (Ty.isCompositeType()) { @@ -947,7 +1007,7 @@ DIE *DwarfUnit::getOrCreateTypeDIE(const MDNode *TyNode) { if (GenerateDwarfTypeUnits && !Ty.isForwardDecl()) if (MDString *TypeId = CTy.getIdentifier()) { DD->addDwarfTypeUnitType(getCU(), TypeId->getString(), TyDIE, CTy); - // Skip updating the accellerator tables since this is not the full type + // Skip updating the accelerator tables since this is not the full type. return TyDIE; } constructTypeDIE(*TyDIE, CTy); @@ -956,8 +1016,6 @@ DIE *DwarfUnit::getOrCreateTypeDIE(const MDNode *TyNode) { constructTypeDIE(*TyDIE, DIDerivedType(Ty)); } - updateAcceleratorTables(Context, Ty, TyDIE); - return TyDIE; } @@ -974,8 +1032,9 @@ void DwarfUnit::updateAcceleratorTables(DIScope Context, DIType Ty, unsigned Flags = IsImplementation ? dwarf::DW_FLAG_type_implementation : 0; addAccelType(Ty.getName(), std::make_pair(TyDIE, Flags)); - if (!Context || Context.isCompileUnit() || Context.isFile() || - Context.isNameSpace()) + if ((!Context || Context.isCompileUnit() || Context.isFile() || + Context.isNameSpace()) && + getCUNode().getEmissionKind() != DIBuilder::LineTablesOnly) GlobalTypes[getParentContextString(Context) + Ty.getName().str()] = TyDIE; } } @@ -1006,21 +1065,24 @@ void DwarfUnit::addType(DIE *Entity, DIType Ty, dwarf::Attribute Attribute) { // to reference is in the string table. We do this since the names we // add may not only be identical to the names in the DIE. void DwarfUnit::addAccelName(StringRef Name, const DIE *Die) { - if (!DD->useDwarfAccelTables()) return; + if (!DD->useDwarfAccelTables()) + return; DU->getStringPoolEntry(Name); std::vector &DIEs = AccelNames[Name]; DIEs.push_back(Die); } void DwarfUnit::addAccelObjC(StringRef Name, const DIE *Die) { - if (!DD->useDwarfAccelTables()) return; + if (!DD->useDwarfAccelTables()) + return; DU->getStringPoolEntry(Name); std::vector &DIEs = AccelObjC[Name]; DIEs.push_back(Die); } void DwarfUnit::addAccelNamespace(StringRef Name, const DIE *Die) { - if (!DD->useDwarfAccelTables()) return; + if (!DD->useDwarfAccelTables()) + return; DU->getStringPoolEntry(Name); std::vector &DIEs = AccelNamespace[Name]; DIEs.push_back(Die); @@ -1028,7 +1090,8 @@ void DwarfUnit::addAccelNamespace(StringRef Name, const DIE *Die) { void DwarfUnit::addAccelType(StringRef Name, std::pair Die) { - if (!DD->useDwarfAccelTables()) return; + if (!DD->useDwarfAccelTables()) + return; DU->getStringPoolEntry(Name); std::vector > &DIEs = AccelTypes[Name]; DIEs.push_back(Die); @@ -1036,6 +1099,8 @@ void DwarfUnit::addAccelType(StringRef Name, /// addGlobalName - Add a new global name to the compile unit. void DwarfUnit::addGlobalName(StringRef Name, DIE *Die, DIScope Context) { + if (getCUNode().getEmissionKind() == DIBuilder::LineTablesOnly) + return; std::string FullName = getParentContextString(Context) + Name.str(); GlobalNames[FullName] = Die; } @@ -1127,6 +1192,22 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) { addSourceLine(&Buffer, DTy); } +/// constructSubprogramArguments - Construct function argument DIEs. +void DwarfUnit::constructSubprogramArguments(DIE &Buffer, DIArray Args) { + for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { + DIDescriptor Ty = Args.getElement(i); + if (Ty.isUnspecifiedParameter()) { + assert(i == N-1 && "Unspecified parameter must be the last argument"); + createAndAddDIE(dwarf::DW_TAG_unspecified_parameters, Buffer); + } else { + DIE *Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, Buffer); + addType(Arg, DIType(Ty)); + if (DIType(Ty).isArtificial()) + addFlag(Arg, dwarf::DW_AT_artificial); + } + } +} + /// constructTypeDIE - Construct type DIE from DICompositeType. void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { // Add name if not anonymous or intermediate type. @@ -1150,19 +1231,12 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { addType(&Buffer, RTy); bool isPrototyped = true; - // Add arguments. - for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) { - DIDescriptor Ty = Elements.getElement(i); - if (Ty.isUnspecifiedParameter()) { - createAndAddDIE(dwarf::DW_TAG_unspecified_parameters, Buffer); - isPrototyped = false; - } else { - DIE *Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, Buffer); - addType(Arg, DIType(Ty)); - if (DIType(Ty).isArtificial()) - addFlag(Arg, dwarf::DW_AT_artificial); - } - } + if (Elements.getNumElements() == 2 && + Elements.getElement(1).isUnspecifiedParameter()) + isPrototyped = false; + + constructSubprogramArguments(Buffer, Elements); + // Add prototype flag if we're dealing with a C language and the // function has been prototyped. uint16_t Language = getLanguage(); @@ -1325,12 +1399,12 @@ DwarfUnit::constructTemplateValueParameterDIE(DIE &Buffer, else if (GlobalValue *GV = dyn_cast(Val)) { // For declaration non-type template parameters (such as global values and // functions) - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - addOpAddress(Block, Asm->getSymbol(GV)); + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); + addOpAddress(Loc, Asm->getSymbol(GV)); // Emit DW_OP_stack_value to use the address as the immediate value of the // parameter, rather than a pointer to it. - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_stack_value); - addBlock(ParamDIE, dwarf::DW_AT_location, Block); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_stack_value); + addBlock(ParamDIE, dwarf::DW_AT_location, Loc); } else if (VP.getTag() == dwarf::DW_TAG_GNU_template_template_param) { assert(isa(Val)); addString(ParamDIE, dwarf::DW_AT_GNU_template_name, @@ -1369,7 +1443,12 @@ DIE *DwarfUnit::getOrCreateSubprogramDIE(DISubprogram SP) { // Construct the context before querying for the existence of the DIE in case // such construction creates the DIE (as is the case for member function // declarations). - DIE *ContextDIE = getOrCreateContextDIE(resolve(SP.getContext())); + DIScope Context = resolve(SP.getContext()); + DIE *ContextDIE = getOrCreateContextDIE(Context); + + // Unique declarations based on the ODR, where applicable. + SP = DISubprogram(DD->resolve(SP.getRef())); + assert(SP.Verify()); DIE *SPDie = getDIE(SP); if (SPDie) @@ -1432,7 +1511,7 @@ DIE *DwarfUnit::getOrCreateSubprogramDIE(DISubprogram SP) { unsigned VK = SP.getVirtuality(); if (VK) { addUInt(SPDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_data1, VK); - DIEBlock *Block = getDIEBlock(); + DIELoc *Block = getDIELoc(); addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); addUInt(Block, dwarf::DW_FORM_udata, SP.getVirtualIndex()); addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, Block); @@ -1445,13 +1524,7 @@ DIE *DwarfUnit::getOrCreateSubprogramDIE(DISubprogram SP) { // Add arguments. Do not add arguments for subprogram definition. They will // be handled while processing variables. - for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { - DIE *Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, *SPDie); - DIType ATy(Args.getElement(i)); - addType(Arg, ATy); - if (ATy.isArtificial()) - addFlag(Arg, dwarf::DW_AT_artificial); - } + constructSubprogramArguments(*SPDie, Args); } if (SP.isArtificial()) @@ -1525,7 +1598,7 @@ void DwarfCompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { assert(GV.isGlobalVariable()); DIScope GVContext = GV.getContext(); - DIType GTy = GV.getType(); + DIType GTy = DD->resolve(GV.getType()); // If this is a static data member definition, some attributes belong // to the declaration DIE. @@ -1567,32 +1640,32 @@ void DwarfCompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { bool isGlobalVariable = GV.getGlobal() != NULL; if (isGlobalVariable) { addToAccelTable = true; - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); const MCSymbol *Sym = Asm->getSymbol(GV.getGlobal()); if (GV.getGlobal()->isThreadLocal()) { // FIXME: Make this work with -gsplit-dwarf. unsigned PointerSize = Asm->getDataLayout().getPointerSize(); assert((PointerSize == 4 || PointerSize == 8) && "Add support for other sizes if necessary"); - const MCExpr *Expr = - Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym); // Based on GCC's support for TLS: if (!DD->useSplitDwarf()) { // 1) Start with a constNu of the appropriate pointer size - addUInt(Block, dwarf::DW_FORM_data1, + addUInt(Loc, dwarf::DW_FORM_data1, PointerSize == 4 ? dwarf::DW_OP_const4u : dwarf::DW_OP_const8u); // 2) containing the (relocated) offset of the TLS variable // within the module's TLS block. - addExpr(Block, dwarf::DW_FORM_udata, Expr); + addExpr(Loc, dwarf::DW_FORM_udata, + Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym)); } else { - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_const_index); - addUInt(Block, dwarf::DW_FORM_udata, DU->getAddrPoolIndex(Expr)); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_const_index); + addUInt(Loc, dwarf::DW_FORM_udata, + DU->getAddrPoolIndex(Sym, /* TLS */ true)); } // 3) followed by a custom OP to make the debugger do a TLS lookup. - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_push_tls_address); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_push_tls_address); } else { DD->addArangeLabel(SymbolCU(this, Sym)); - addOpAddress(Block, Sym); + addOpAddress(Loc, Sym); } // Do not create specification DIE if context is either compile unit // or a subprogram. @@ -1601,12 +1674,12 @@ void DwarfCompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { // Create specification DIE. VariableSpecDIE = createAndAddDIE(dwarf::DW_TAG_variable, *UnitDie); addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification, VariableDIE); - addBlock(VariableSpecDIE, dwarf::DW_AT_location, Block); + addBlock(VariableSpecDIE, dwarf::DW_AT_location, Loc); // A static member's declaration is already flagged as such. if (!SDMDecl.Verify()) addFlag(VariableDIE, dwarf::DW_AT_declaration); } else { - addBlock(VariableDIE, dwarf::DW_AT_location, Block); + addBlock(VariableDIE, dwarf::DW_AT_location, Loc); } // Add the linkage name. StringRef LinkageName = GV.getLinkageName(); @@ -1616,7 +1689,8 @@ void DwarfCompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { // TAG_variable. addString(IsStaticMember && VariableSpecDIE ? VariableSpecDIE : VariableDIE, - dwarf::DW_AT_MIPS_linkage_name, + DD->getDwarfVersion() >= 4 ? dwarf::DW_AT_linkage_name + : dwarf::DW_AT_MIPS_linkage_name, GlobalValue::getRealLinkageName(LinkageName)); } else if (const ConstantInt *CI = dyn_cast_or_null(GV.getConstant())) { @@ -1628,17 +1702,17 @@ void DwarfCompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { } else if (const ConstantExpr *CE = getMergedGlobalExpr(GV->getOperand(11))) { addToAccelTable = true; // GV is a merged global. - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); Value *Ptr = CE->getOperand(0); MCSymbol *Sym = Asm->getSymbol(cast(Ptr)); DD->addArangeLabel(SymbolCU(this, Sym)); - addOpAddress(Block, Sym); - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); + addOpAddress(Loc, Sym); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); SmallVector Idx(CE->op_begin() + 1, CE->op_end()); - addUInt(Block, dwarf::DW_FORM_udata, + addUInt(Loc, dwarf::DW_FORM_udata, Asm->getDataLayout().getIndexedOffset(Ptr->getType(), Idx)); - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); - addBlock(VariableDIE, dwarf::DW_AT_location, Block); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); + addBlock(VariableDIE, dwarf::DW_AT_location, Loc); } if (addToAccelTable) { @@ -1694,12 +1768,12 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, DICompositeType CTy) { // as different languages may have different sizes for indexes. DIE *IdxTy = getIndexTyDie(); if (!IdxTy) { - // Construct an anonymous type for index type. + // Construct an integer type to use for indexes. IdxTy = createAndAddDIE(dwarf::DW_TAG_base_type, *UnitDie); - addString(IdxTy, dwarf::DW_AT_name, "int"); - addUInt(IdxTy, dwarf::DW_AT_byte_size, None, sizeof(int32_t)); + addString(IdxTy, dwarf::DW_AT_name, "sizetype"); + addUInt(IdxTy, dwarf::DW_AT_byte_size, None, sizeof(int64_t)); addUInt(IdxTy, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, - dwarf::DW_ATE_signed); + dwarf::DW_ATE_unsigned); setIndexTyDie(IdxTy); } @@ -1781,8 +1855,7 @@ DIE *DwarfUnit::constructVariableDIE(DbgVariable &DV, bool isScopeAbstract) { unsigned Offset = DV.getDotDebugLocOffset(); if (Offset != ~0U) { - addSectionLabel(VariableDie, dwarf::DW_AT_location, - Asm->GetTempSymbol("debug_loc", Offset)); + addLocationList(VariableDie, dwarf::DW_AT_location, Offset); DV.setDIE(VariableDie); return VariableDie; } @@ -1842,7 +1915,7 @@ void DwarfUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) { // expression to extract appropriate offset from vtable. // BaseAddr = ObAddr + *((*ObAddr) - Offset) - DIEBlock *VBaseLocationDie = new (DIEValueAllocator) DIEBlock(); + DIELoc *VBaseLocationDie = new (DIEValueAllocator) DIELoc(); addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_dup); addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); @@ -1858,10 +1931,9 @@ void DwarfUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) { uint64_t OffsetInBytes; if (Size != FieldSize) { - // Handle bitfield. - addUInt(MemberDie, dwarf::DW_AT_byte_size, None, - getBaseTypeSize(DD, DT) >> 3); - addUInt(MemberDie, dwarf::DW_AT_bit_size, None, DT.getSizeInBits()); + // 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); uint64_t Offset = DT.getOffsetInBits(); uint64_t AlignMask = ~(DT.getAlignInBits() - 1); @@ -1882,7 +1954,7 @@ void DwarfUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) { OffsetInBytes = DT.getOffsetInBits() >> 3; if (DD->getDwarfVersion() <= 2) { - DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock(); + DIELoc *MemLocationDie = new (DIEValueAllocator) DIELoc(); addUInt(MemLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); addUInt(MemLocationDie, dwarf::DW_FORM_udata, OffsetInBytes); addBlock(MemberDie, dwarf::DW_AT_data_member_location, MemLocationDie); @@ -1960,25 +2032,70 @@ DIE *DwarfUnit::getOrCreateStaticMemberDIE(DIDerivedType DT) { return StaticMemberDIE; } -void DwarfUnit::emitHeader(const MCSection *ASection, - const MCSymbol *ASectionSym) const { +void DwarfUnit::emitHeader(const MCSymbol *ASectionSym) const { Asm->OutStreamer.AddComment("DWARF version number"); Asm->EmitInt16(DD->getDwarfVersion()); Asm->OutStreamer.AddComment("Offset Into Abbrev. Section"); // We share one abbreviations table across all units so it's always at the // start of the section. Use a relocatable offset where needed to ensure // linking doesn't invalidate that offset. - Asm->EmitSectionOffset(ASectionSym, ASectionSym); + if (ASectionSym) + Asm->EmitSectionOffset(ASectionSym, ASectionSym); + else + // Use a constant value when no symbol is provided. + Asm->EmitInt32(0); Asm->OutStreamer.AddComment("Address Size (in bytes)"); Asm->EmitInt8(Asm->getDataLayout().getPointerSize()); } -DwarfCompileUnit::~DwarfCompileUnit() {} -DwarfTypeUnit::~DwarfTypeUnit() {} +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::initStmtList(MCSymbol *DwarfLineSectionSym) { + // Define start line table label for each Compile Unit. + MCSymbol *LineTableStartSym = + Asm->OutStreamer.getDwarfLineTableSymbol(getUniqueID()); + + stmtListIndex = UnitDie->getValues().size(); + + // DW_AT_stmt_list is a offset of line number information for this + // compile unit in debug_line section. For split dwarf this is + // left in the skeleton CU and so not included. + // The line table entries are not always emitted in assembly, so it + // is not okay to use line_table_start here. + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) + addSectionLabel(UnitDie.get(), dwarf::DW_AT_stmt_list, LineTableStartSym); + else + addSectionDelta(UnitDie.get(), dwarf::DW_AT_stmt_list, LineTableStartSym, + DwarfLineSectionSym); +} + +void DwarfCompileUnit::applyStmtList(DIE &D) { + D.addValue(dwarf::DW_AT_stmt_list, + UnitDie->getAbbrev().getData()[stmtListIndex].getForm(), + UnitDie->getValues()[stmtListIndex]); +} -void DwarfTypeUnit::emitHeader(const MCSection *ASection, - const MCSymbol *ASectionSym) const { - DwarfUnit::emitHeader(ASection, ASectionSym); +void DwarfTypeUnit::emitHeader(const MCSymbol *ASectionSym) const { + DwarfUnit::emitHeader(ASectionSym); Asm->OutStreamer.AddComment("Type Signature"); Asm->OutStreamer.EmitIntValue(TypeSignature, sizeof(TypeSignature)); Asm->OutStreamer.AddComment("Type DIE Offset");