David Blaikie | 37c5231 | 2014-10-04 15:49:50 +0000 | [diff] [blame] | 1 | #include "DwarfCompileUnit.h" |
| 2 | |
David Blaikie | cda2aa8 | 2014-10-04 16:24:00 +0000 | [diff] [blame] | 3 | #include "llvm/CodeGen/MachineFunction.h" |
David Blaikie | 37c5231 | 2014-10-04 15:49:50 +0000 | [diff] [blame] | 4 | #include "llvm/IR/DataLayout.h" |
| 5 | #include "llvm/IR/GlobalValue.h" |
| 6 | #include "llvm/IR/GlobalVariable.h" |
| 7 | #include "llvm/IR/Instruction.h" |
| 8 | #include "llvm/MC/MCAsmInfo.h" |
| 9 | #include "llvm/MC/MCStreamer.h" |
| 10 | #include "llvm/Target/TargetLoweringObjectFile.h" |
David Blaikie | cda2aa8 | 2014-10-04 16:24:00 +0000 | [diff] [blame] | 11 | #include "llvm/Target/TargetMachine.h" |
| 12 | #include "llvm/Target/TargetSubtargetInfo.h" |
| 13 | #include "llvm/Target/TargetRegisterInfo.h" |
David Blaikie | 37c5231 | 2014-10-04 15:49:50 +0000 | [diff] [blame] | 14 | |
| 15 | namespace llvm { |
| 16 | |
| 17 | DwarfCompileUnit::DwarfCompileUnit(unsigned UID, DICompileUnit Node, |
| 18 | AsmPrinter *A, DwarfDebug *DW, |
| 19 | DwarfFile *DWU) |
| 20 | : DwarfUnit(UID, dwarf::DW_TAG_compile_unit, Node, A, DW, DWU) { |
| 21 | insertDIE(Node, &getUnitDie()); |
| 22 | } |
| 23 | |
| 24 | /// addLabelAddress - Add a dwarf label attribute data and value using |
| 25 | /// DW_FORM_addr or DW_FORM_GNU_addr_index. |
| 26 | /// |
| 27 | void DwarfCompileUnit::addLabelAddress(DIE &Die, dwarf::Attribute Attribute, |
| 28 | const MCSymbol *Label) { |
| 29 | |
| 30 | // Don't use the address pool in non-fission or in the skeleton unit itself. |
| 31 | // FIXME: Once GDB supports this, it's probably worthwhile using the address |
| 32 | // pool from the skeleton - maybe even in non-fission (possibly fewer |
| 33 | // relocations by sharing them in the pool, but we have other ideas about how |
| 34 | // to reduce the number of relocations as well/instead). |
| 35 | if (!DD->useSplitDwarf() || !Skeleton) |
| 36 | return addLocalLabelAddress(Die, Attribute, Label); |
| 37 | |
| 38 | if (Label) |
| 39 | DD->addArangeLabel(SymbolCU(this, Label)); |
| 40 | |
| 41 | unsigned idx = DD->getAddressPool().getIndex(Label); |
| 42 | DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx); |
| 43 | Die.addValue(Attribute, dwarf::DW_FORM_GNU_addr_index, Value); |
| 44 | } |
| 45 | |
| 46 | void DwarfCompileUnit::addLocalLabelAddress(DIE &Die, |
| 47 | dwarf::Attribute Attribute, |
| 48 | const MCSymbol *Label) { |
| 49 | if (Label) |
| 50 | DD->addArangeLabel(SymbolCU(this, Label)); |
| 51 | |
| 52 | Die.addValue(Attribute, dwarf::DW_FORM_addr, |
| 53 | Label ? (DIEValue *)new (DIEValueAllocator) DIELabel(Label) |
| 54 | : new (DIEValueAllocator) DIEInteger(0)); |
| 55 | } |
| 56 | |
David Blaikie | 8945219 | 2014-10-04 16:00:26 +0000 | [diff] [blame] | 57 | unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName, |
| 58 | StringRef DirName) { |
David Blaikie | 37c5231 | 2014-10-04 15:49:50 +0000 | [diff] [blame] | 59 | // If we print assembly, we can't separate .file entries according to |
| 60 | // compile units. Thus all files will belong to the default compile unit. |
| 61 | |
| 62 | // FIXME: add a better feature test than hasRawTextSupport. Even better, |
| 63 | // extend .file to support this. |
| 64 | return Asm->OutStreamer.EmitDwarfFileDirective( |
| 65 | 0, DirName, FileName, |
| 66 | Asm->OutStreamer.hasRawTextSupport() ? 0 : getUniqueID()); |
| 67 | } |
| 68 | |
| 69 | // Return const expression if value is a GEP to access merged global |
| 70 | // constant. e.g. |
| 71 | // i8* getelementptr ({ i8, i8, i8, i8 }* @_MergedGlobals, i32 0, i32 0) |
| 72 | static const ConstantExpr *getMergedGlobalExpr(const Value *V) { |
| 73 | const ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(V); |
| 74 | if (!CE || CE->getNumOperands() != 3 || |
| 75 | CE->getOpcode() != Instruction::GetElementPtr) |
| 76 | return nullptr; |
| 77 | |
| 78 | // First operand points to a global struct. |
| 79 | Value *Ptr = CE->getOperand(0); |
| 80 | if (!isa<GlobalValue>(Ptr) || |
| 81 | !isa<StructType>(cast<PointerType>(Ptr->getType())->getElementType())) |
| 82 | return nullptr; |
| 83 | |
| 84 | // Second operand is zero. |
| 85 | const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CE->getOperand(1)); |
| 86 | if (!CI || !CI->isZero()) |
| 87 | return nullptr; |
| 88 | |
| 89 | // Third operand is offset. |
| 90 | if (!isa<ConstantInt>(CE->getOperand(2))) |
| 91 | return nullptr; |
| 92 | |
| 93 | return CE; |
| 94 | } |
| 95 | |
| 96 | /// getOrCreateGlobalVariableDIE - get or create global variable DIE. |
| 97 | DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(DIGlobalVariable GV) { |
| 98 | // Check for pre-existence. |
| 99 | if (DIE *Die = getDIE(GV)) |
| 100 | return Die; |
| 101 | |
| 102 | assert(GV.isGlobalVariable()); |
| 103 | |
| 104 | DIScope GVContext = GV.getContext(); |
| 105 | DIType GTy = DD->resolve(GV.getType()); |
| 106 | |
| 107 | // If this is a static data member definition, some attributes belong |
| 108 | // to the declaration DIE. |
| 109 | DIE *VariableDIE = nullptr; |
| 110 | bool IsStaticMember = false; |
| 111 | DIDerivedType SDMDecl = GV.getStaticDataMemberDeclaration(); |
| 112 | if (SDMDecl.Verify()) { |
| 113 | assert(SDMDecl.isStaticMember() && "Expected static member decl"); |
| 114 | // We need the declaration DIE that is in the static member's class. |
| 115 | VariableDIE = getOrCreateStaticMemberDIE(SDMDecl); |
| 116 | IsStaticMember = true; |
| 117 | } |
| 118 | |
| 119 | // If this is not a static data member definition, create the variable |
| 120 | // DIE and add the initial set of attributes to it. |
| 121 | if (!VariableDIE) { |
| 122 | // Construct the context before querying for the existence of the DIE in |
| 123 | // case such construction creates the DIE. |
| 124 | DIE *ContextDIE = getOrCreateContextDIE(GVContext); |
| 125 | |
| 126 | // Add to map. |
| 127 | VariableDIE = &createAndAddDIE(GV.getTag(), *ContextDIE, GV); |
| 128 | |
| 129 | // Add name and type. |
| 130 | addString(*VariableDIE, dwarf::DW_AT_name, GV.getDisplayName()); |
| 131 | addType(*VariableDIE, GTy); |
| 132 | |
| 133 | // Add scoping info. |
| 134 | if (!GV.isLocalToUnit()) |
| 135 | addFlag(*VariableDIE, dwarf::DW_AT_external); |
| 136 | |
| 137 | // Add line number info. |
| 138 | addSourceLine(*VariableDIE, GV); |
| 139 | } |
| 140 | |
| 141 | // Add location. |
| 142 | bool addToAccelTable = false; |
| 143 | DIE *VariableSpecDIE = nullptr; |
| 144 | bool isGlobalVariable = GV.getGlobal() != nullptr; |
| 145 | if (isGlobalVariable) { |
| 146 | addToAccelTable = true; |
| 147 | DIELoc *Loc = new (DIEValueAllocator) DIELoc(); |
| 148 | const MCSymbol *Sym = Asm->getSymbol(GV.getGlobal()); |
| 149 | if (GV.getGlobal()->isThreadLocal()) { |
| 150 | // FIXME: Make this work with -gsplit-dwarf. |
| 151 | unsigned PointerSize = Asm->getDataLayout().getPointerSize(); |
| 152 | assert((PointerSize == 4 || PointerSize == 8) && |
| 153 | "Add support for other sizes if necessary"); |
| 154 | // Based on GCC's support for TLS: |
| 155 | if (!DD->useSplitDwarf()) { |
| 156 | // 1) Start with a constNu of the appropriate pointer size |
| 157 | addUInt(*Loc, dwarf::DW_FORM_data1, |
| 158 | PointerSize == 4 ? dwarf::DW_OP_const4u : dwarf::DW_OP_const8u); |
| 159 | // 2) containing the (relocated) offset of the TLS variable |
| 160 | // within the module's TLS block. |
| 161 | addExpr(*Loc, dwarf::DW_FORM_udata, |
| 162 | Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym)); |
| 163 | } else { |
| 164 | addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_const_index); |
| 165 | addUInt(*Loc, dwarf::DW_FORM_udata, |
| 166 | DD->getAddressPool().getIndex(Sym, /* TLS */ true)); |
| 167 | } |
| 168 | // 3) followed by a custom OP to make the debugger do a TLS lookup. |
| 169 | addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_push_tls_address); |
| 170 | } else { |
| 171 | DD->addArangeLabel(SymbolCU(this, Sym)); |
| 172 | addOpAddress(*Loc, Sym); |
| 173 | } |
| 174 | // A static member's declaration is already flagged as such. |
| 175 | if (!SDMDecl.Verify() && !GV.isDefinition()) |
| 176 | addFlag(*VariableDIE, dwarf::DW_AT_declaration); |
| 177 | // Do not create specification DIE if context is either compile unit |
| 178 | // or a subprogram. |
| 179 | if (GVContext && GV.isDefinition() && !GVContext.isCompileUnit() && |
| 180 | !GVContext.isFile() && !DD->isSubprogramContext(GVContext)) { |
| 181 | // Create specification DIE. |
| 182 | VariableSpecDIE = &createAndAddDIE(dwarf::DW_TAG_variable, UnitDie); |
| 183 | addDIEEntry(*VariableSpecDIE, dwarf::DW_AT_specification, *VariableDIE); |
| 184 | addBlock(*VariableSpecDIE, dwarf::DW_AT_location, Loc); |
| 185 | // A static member's declaration is already flagged as such. |
| 186 | if (!SDMDecl.Verify()) |
| 187 | addFlag(*VariableDIE, dwarf::DW_AT_declaration); |
| 188 | } else { |
| 189 | addBlock(*VariableDIE, dwarf::DW_AT_location, Loc); |
| 190 | } |
| 191 | // Add the linkage name. |
| 192 | StringRef LinkageName = GV.getLinkageName(); |
| 193 | if (!LinkageName.empty()) |
| 194 | // From DWARF4: DIEs to which DW_AT_linkage_name may apply include: |
| 195 | // TAG_common_block, TAG_constant, TAG_entry_point, TAG_subprogram and |
| 196 | // TAG_variable. |
| 197 | addString(IsStaticMember && VariableSpecDIE ? *VariableSpecDIE |
| 198 | : *VariableDIE, |
| 199 | DD->getDwarfVersion() >= 4 ? dwarf::DW_AT_linkage_name |
| 200 | : dwarf::DW_AT_MIPS_linkage_name, |
| 201 | GlobalValue::getRealLinkageName(LinkageName)); |
| 202 | } else if (const ConstantInt *CI = |
| 203 | dyn_cast_or_null<ConstantInt>(GV.getConstant())) { |
| 204 | // AT_const_value was added when the static member was created. To avoid |
| 205 | // emitting AT_const_value multiple times, we only add AT_const_value when |
| 206 | // it is not a static member. |
| 207 | if (!IsStaticMember) |
| 208 | addConstantValue(*VariableDIE, CI, GTy); |
| 209 | } else if (const ConstantExpr *CE = getMergedGlobalExpr(GV.getConstant())) { |
| 210 | addToAccelTable = true; |
| 211 | // GV is a merged global. |
| 212 | DIELoc *Loc = new (DIEValueAllocator) DIELoc(); |
| 213 | Value *Ptr = CE->getOperand(0); |
| 214 | MCSymbol *Sym = Asm->getSymbol(cast<GlobalValue>(Ptr)); |
| 215 | DD->addArangeLabel(SymbolCU(this, Sym)); |
| 216 | addOpAddress(*Loc, Sym); |
| 217 | addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); |
| 218 | SmallVector<Value *, 3> Idx(CE->op_begin() + 1, CE->op_end()); |
| 219 | addUInt(*Loc, dwarf::DW_FORM_udata, |
| 220 | Asm->getDataLayout().getIndexedOffset(Ptr->getType(), Idx)); |
| 221 | addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); |
| 222 | addBlock(*VariableDIE, dwarf::DW_AT_location, Loc); |
| 223 | } |
| 224 | |
| 225 | DIE *ResultDIE = VariableSpecDIE ? VariableSpecDIE : VariableDIE; |
| 226 | |
| 227 | if (addToAccelTable) { |
| 228 | DD->addAccelName(GV.getName(), *ResultDIE); |
| 229 | |
| 230 | // If the linkage name is different than the name, go ahead and output |
| 231 | // that as well into the name table. |
| 232 | if (GV.getLinkageName() != "" && GV.getName() != GV.getLinkageName()) |
| 233 | DD->addAccelName(GV.getLinkageName(), *ResultDIE); |
| 234 | } |
| 235 | |
| 236 | addGlobalName(GV.getName(), *ResultDIE, GV.getContext()); |
| 237 | return ResultDIE; |
| 238 | } |
| 239 | |
| 240 | void DwarfCompileUnit::addRange(RangeSpan Range) { |
| 241 | bool SameAsPrevCU = this == DD->getPrevCU(); |
| 242 | DD->setPrevCU(this); |
| 243 | // If we have no current ranges just add the range and return, otherwise, |
| 244 | // check the current section and CU against the previous section and CU we |
| 245 | // emitted into and the subprogram was contained within. If these are the |
| 246 | // same then extend our current range, otherwise add this as a new range. |
| 247 | if (CURanges.empty() || !SameAsPrevCU || |
| 248 | (&CURanges.back().getEnd()->getSection() != |
| 249 | &Range.getEnd()->getSection())) { |
| 250 | CURanges.push_back(Range); |
| 251 | return; |
| 252 | } |
| 253 | |
| 254 | CURanges.back().setEnd(Range.getEnd()); |
| 255 | } |
| 256 | |
David Blaikie | 6c0ee4e | 2014-10-08 22:46:27 +0000 | [diff] [blame] | 257 | void DwarfCompileUnit::addSectionLabel(DIE &Die, dwarf::Attribute Attribute, |
| 258 | const MCSymbol *Label, |
| 259 | const MCSymbol *Sec) { |
| 260 | if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) |
| 261 | addLabel(Die, Attribute, |
| 262 | DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset |
| 263 | : dwarf::DW_FORM_data4, |
| 264 | Label); |
| 265 | else |
| 266 | addSectionDelta(Die, Attribute, Label, Sec); |
| 267 | } |
| 268 | |
David Blaikie | 37c5231 | 2014-10-04 15:49:50 +0000 | [diff] [blame] | 269 | void DwarfCompileUnit::initStmtList(MCSymbol *DwarfLineSectionSym) { |
| 270 | // Define start line table label for each Compile Unit. |
| 271 | MCSymbol *LineTableStartSym = |
| 272 | Asm->OutStreamer.getDwarfLineTableSymbol(getUniqueID()); |
| 273 | |
| 274 | stmtListIndex = UnitDie.getValues().size(); |
| 275 | |
| 276 | // DW_AT_stmt_list is a offset of line number information for this |
| 277 | // compile unit in debug_line section. For split dwarf this is |
| 278 | // left in the skeleton CU and so not included. |
| 279 | // The line table entries are not always emitted in assembly, so it |
| 280 | // is not okay to use line_table_start here. |
David Blaikie | 6c0ee4e | 2014-10-08 22:46:27 +0000 | [diff] [blame] | 281 | addSectionLabel(UnitDie, dwarf::DW_AT_stmt_list, LineTableStartSym, |
| 282 | DwarfLineSectionSym); |
David Blaikie | 37c5231 | 2014-10-04 15:49:50 +0000 | [diff] [blame] | 283 | } |
| 284 | |
| 285 | void DwarfCompileUnit::applyStmtList(DIE &D) { |
| 286 | D.addValue(dwarf::DW_AT_stmt_list, |
| 287 | UnitDie.getAbbrev().getData()[stmtListIndex].getForm(), |
| 288 | UnitDie.getValues()[stmtListIndex]); |
| 289 | } |
| 290 | |
David Blaikie | 14499a7 | 2014-10-04 15:58:47 +0000 | [diff] [blame] | 291 | void DwarfCompileUnit::attachLowHighPC(DIE &D, const MCSymbol *Begin, |
| 292 | const MCSymbol *End) { |
| 293 | assert(Begin && "Begin label should not be null!"); |
| 294 | assert(End && "End label should not be null!"); |
| 295 | assert(Begin->isDefined() && "Invalid starting label"); |
| 296 | assert(End->isDefined() && "Invalid end label"); |
| 297 | |
| 298 | addLabelAddress(D, dwarf::DW_AT_low_pc, Begin); |
| 299 | if (DD->getDwarfVersion() < 4) |
| 300 | addLabelAddress(D, dwarf::DW_AT_high_pc, End); |
| 301 | else |
| 302 | addLabelDelta(D, dwarf::DW_AT_high_pc, End, Begin); |
| 303 | } |
| 304 | |
David Blaikie | cda2aa8 | 2014-10-04 16:24:00 +0000 | [diff] [blame] | 305 | // Find DIE for the given subprogram and attach appropriate DW_AT_low_pc |
| 306 | // and DW_AT_high_pc attributes. If there are global variables in this |
| 307 | // scope then create and insert DIEs for these variables. |
| 308 | DIE &DwarfCompileUnit::updateSubprogramScopeDIE(DISubprogram SP) { |
| 309 | DIE *SPDie = getOrCreateSubprogramDIE(SP); |
| 310 | |
| 311 | attachLowHighPC(*SPDie, DD->getFunctionBeginSym(), DD->getFunctionEndSym()); |
| 312 | if (!DD->getCurrentFunction()->getTarget().Options.DisableFramePointerElim( |
| 313 | *DD->getCurrentFunction())) |
| 314 | addFlag(*SPDie, dwarf::DW_AT_APPLE_omit_frame_ptr); |
| 315 | |
| 316 | // Only include DW_AT_frame_base in full debug info |
| 317 | if (getCUNode().getEmissionKind() != DIBuilder::LineTablesOnly) { |
| 318 | const TargetRegisterInfo *RI = |
| 319 | Asm->TM.getSubtargetImpl()->getRegisterInfo(); |
| 320 | MachineLocation Location(RI->getFrameRegister(*Asm->MF)); |
| 321 | addAddress(*SPDie, dwarf::DW_AT_frame_base, Location); |
| 322 | } |
| 323 | |
| 324 | // Add name to the name table, we do this here because we're guaranteed |
| 325 | // to have concrete versions of our DW_TAG_subprogram nodes. |
| 326 | DD->addSubprogramNames(SP, *SPDie); |
| 327 | |
| 328 | return *SPDie; |
| 329 | } |
| 330 | |
David Blaikie | 9c65b13 | 2014-10-08 22:20:02 +0000 | [diff] [blame] | 331 | // Construct a DIE for this scope. |
| 332 | void DwarfCompileUnit::constructScopeDIE( |
| 333 | LexicalScope *Scope, SmallVectorImpl<std::unique_ptr<DIE>> &FinalChildren) { |
| 334 | if (!Scope || !Scope->getScopeNode()) |
| 335 | return; |
| 336 | |
| 337 | DIScope DS(Scope->getScopeNode()); |
| 338 | |
| 339 | assert((Scope->getInlinedAt() || !DS.isSubprogram()) && |
| 340 | "Only handle inlined subprograms here, use " |
| 341 | "constructSubprogramScopeDIE for non-inlined " |
| 342 | "subprograms"); |
| 343 | |
| 344 | SmallVector<std::unique_ptr<DIE>, 8> Children; |
| 345 | |
| 346 | // We try to create the scope DIE first, then the children DIEs. This will |
| 347 | // avoid creating un-used children then removing them later when we find out |
| 348 | // the scope DIE is null. |
| 349 | std::unique_ptr<DIE> ScopeDIE; |
| 350 | if (Scope->getParent() && DS.isSubprogram()) { |
| 351 | ScopeDIE = DD->constructInlinedScopeDIE(*this, Scope); |
| 352 | if (!ScopeDIE) |
| 353 | return; |
| 354 | // We create children when the scope DIE is not null. |
| 355 | DD->createScopeChildrenDIE(*this, Scope, Children); |
| 356 | } else { |
| 357 | // Early exit when we know the scope DIE is going to be null. |
| 358 | if (DD->isLexicalScopeDIENull(Scope)) |
| 359 | return; |
| 360 | |
| 361 | unsigned ChildScopeCount; |
| 362 | |
| 363 | // We create children here when we know the scope DIE is not going to be |
| 364 | // null and the children will be added to the scope DIE. |
| 365 | DD->createScopeChildrenDIE(*this, Scope, Children, &ChildScopeCount); |
| 366 | |
| 367 | // There is no need to emit empty lexical block DIE. |
| 368 | for (const auto &E : DD->findImportedEntitiesForScope(DS)) |
| 369 | Children.push_back( |
| 370 | constructImportedEntityDIE(DIImportedEntity(E.second))); |
| 371 | // If there are only other scopes as children, put them directly in the |
| 372 | // parent instead, as this scope would serve no purpose. |
| 373 | if (Children.size() == ChildScopeCount) { |
| 374 | FinalChildren.insert(FinalChildren.end(), |
| 375 | std::make_move_iterator(Children.begin()), |
| 376 | std::make_move_iterator(Children.end())); |
| 377 | return; |
| 378 | } |
| 379 | ScopeDIE = DD->constructLexicalScopeDIE(*this, Scope); |
| 380 | assert(ScopeDIE && "Scope DIE should not be null."); |
| 381 | } |
| 382 | |
| 383 | // Add children |
| 384 | for (auto &I : Children) |
| 385 | ScopeDIE->addChild(std::move(I)); |
| 386 | |
| 387 | FinalChildren.push_back(std::move(ScopeDIE)); |
| 388 | } |
| 389 | |
David Blaikie | e5feec5 | 2014-10-08 23:30:05 +0000 | [diff] [blame^] | 390 | void DwarfCompileUnit::addSectionDelta(DIE &Die, dwarf::Attribute Attribute, |
| 391 | const MCSymbol *Hi, const MCSymbol *Lo) { |
| 392 | DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo); |
| 393 | Die.addValue(Attribute, DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset |
| 394 | : dwarf::DW_FORM_data4, |
| 395 | Value); |
| 396 | } |
| 397 | |
David Blaikie | 37c5231 | 2014-10-04 15:49:50 +0000 | [diff] [blame] | 398 | } // end llvm namespace |