Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 1 | //===- tools/dsymutil/CompileUnit.h - Dwarf compile unit ------------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| 10 | #include "CompileUnit.h" |
| 11 | #include "DeclContext.h" |
| 12 | |
| 13 | namespace llvm { |
| 14 | namespace dsymutil { |
| 15 | |
| 16 | /// Check if the DIE at \p Idx is in the scope of a function. |
| 17 | static bool inFunctionScope(CompileUnit &U, unsigned Idx) { |
| 18 | while (Idx) { |
| 19 | if (U.getOrigUnit().getDIEAtIndex(Idx).getTag() == dwarf::DW_TAG_subprogram) |
| 20 | return true; |
| 21 | Idx = U.getInfo(Idx).ParentIdx; |
| 22 | } |
| 23 | return false; |
| 24 | } |
| 25 | |
| 26 | void CompileUnit::markEverythingAsKept() { |
| 27 | unsigned Idx = 0; |
| 28 | |
| 29 | setHasInterestingContent(); |
| 30 | |
| 31 | for (auto &I : Info) { |
| 32 | // Mark everything that wasn't explicit marked for pruning. |
| 33 | I.Keep = !I.Prune; |
| 34 | auto DIE = OrigUnit.getDIEAtIndex(Idx++); |
| 35 | |
| 36 | // Try to guess which DIEs must go to the accelerator tables. We do that |
| 37 | // just for variables, because functions will be handled depending on |
| 38 | // whether they carry a DW_AT_low_pc attribute or not. |
| 39 | if (DIE.getTag() != dwarf::DW_TAG_variable && |
| 40 | DIE.getTag() != dwarf::DW_TAG_constant) |
| 41 | continue; |
| 42 | |
| 43 | Optional<DWARFFormValue> Value; |
| 44 | if (!(Value = DIE.find(dwarf::DW_AT_location))) { |
| 45 | if ((Value = DIE.find(dwarf::DW_AT_const_value)) && |
| 46 | !inFunctionScope(*this, I.ParentIdx)) |
| 47 | I.InDebugMap = true; |
| 48 | continue; |
| 49 | } |
| 50 | if (auto Block = Value->getAsBlock()) { |
| 51 | if (Block->size() > OrigUnit.getAddressByteSize() && |
| 52 | (*Block)[0] == dwarf::DW_OP_addr) |
| 53 | I.InDebugMap = true; |
| 54 | } |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | uint64_t CompileUnit::computeNextUnitOffset() { |
| 59 | NextUnitOffset = StartOffset + 11 /* Header size */; |
| 60 | // The root DIE might be null, meaning that the Unit had nothing to |
| 61 | // contribute to the linked output. In that case, we will emit the |
| 62 | // unit header without any actual DIE. |
| 63 | if (NewUnit) |
| 64 | NextUnitOffset += NewUnit->getUnitDie().getSize(); |
| 65 | return NextUnitOffset; |
| 66 | } |
| 67 | |
| 68 | /// Keep track of a forward cross-cu reference from this unit |
| 69 | /// to \p Die that lives in \p RefUnit. |
| 70 | void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit, |
| 71 | DeclContext *Ctxt, PatchLocation Attr) { |
| 72 | ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr); |
| 73 | } |
| 74 | |
| 75 | void CompileUnit::fixupForwardReferences() { |
| 76 | for (const auto &Ref : ForwardDIEReferences) { |
| 77 | DIE *RefDie; |
| 78 | const CompileUnit *RefUnit; |
| 79 | PatchLocation Attr; |
| 80 | DeclContext *Ctxt; |
| 81 | std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref; |
| 82 | if (Ctxt && Ctxt->getCanonicalDIEOffset()) |
| 83 | Attr.set(Ctxt->getCanonicalDIEOffset()); |
| 84 | else |
| 85 | Attr.set(RefDie->getOffset() + RefUnit->getStartOffset()); |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) { |
| 90 | Labels.insert({LabelLowPc, PcOffset}); |
| 91 | } |
| 92 | |
| 93 | void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc, |
| 94 | int64_t PcOffset) { |
Jonas Devlieghere | 8ece8d3 | 2019-01-08 01:08:09 +0000 | [diff] [blame] | 95 | // Don't add empty ranges to the interval map. They are a problem because |
| 96 | // the interval map expects half open intervals. This is safe because they |
| 97 | // are empty anyway. |
| 98 | if (FuncHighPc != FuncLowPc) |
| 99 | Ranges.insert(FuncLowPc, FuncHighPc, PcOffset); |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 100 | this->LowPc = std::min(LowPc, FuncLowPc + PcOffset); |
| 101 | this->HighPc = std::max(HighPc, FuncHighPc + PcOffset); |
| 102 | } |
| 103 | |
| 104 | void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) { |
| 105 | if (Die.getTag() != dwarf::DW_TAG_compile_unit) |
| 106 | RangeAttributes.push_back(Attr); |
| 107 | else |
| 108 | UnitRangeAttribute = Attr; |
| 109 | } |
| 110 | |
| 111 | void CompileUnit::noteLocationAttribute(PatchLocation Attr, int64_t PcOffset) { |
| 112 | LocationAttributes.emplace_back(Attr, PcOffset); |
| 113 | } |
| 114 | |
| 115 | void CompileUnit::addNamespaceAccelerator(const DIE *Die, |
| 116 | DwarfStringPoolEntryRef Name) { |
| 117 | Namespaces.emplace_back(Name, Die); |
| 118 | } |
| 119 | |
| 120 | void CompileUnit::addObjCAccelerator(const DIE *Die, |
| 121 | DwarfStringPoolEntryRef Name, |
| 122 | bool SkipPubSection) { |
| 123 | ObjC.emplace_back(Name, Die, SkipPubSection); |
| 124 | } |
| 125 | |
| 126 | void CompileUnit::addNameAccelerator(const DIE *Die, |
| 127 | DwarfStringPoolEntryRef Name, |
| 128 | bool SkipPubSection) { |
| 129 | Pubnames.emplace_back(Name, Die, SkipPubSection); |
| 130 | } |
| 131 | |
| 132 | void CompileUnit::addTypeAccelerator(const DIE *Die, |
| 133 | DwarfStringPoolEntryRef Name, |
| 134 | bool ObjcClassImplementation, |
| 135 | uint32_t QualifiedNameHash) { |
| 136 | Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation); |
| 137 | } |
| 138 | |
| 139 | } // namespace dsymutil |
| 140 | } // namespace llvm |