1 //===- DWARFLinkerCompileUnit.cpp -----------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
10 #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
14 /// Check if the DIE at \p Idx is in the scope of a function.
15 static bool inFunctionScope(CompileUnit &U, unsigned Idx) {
17 if (U.getOrigUnit().getDIEAtIndex(Idx).getTag() == dwarf::DW_TAG_subprogram)
19 Idx = U.getInfo(Idx).ParentIdx;
24 uint16_t CompileUnit::getLanguage() {
26 DWARFDie CU = getOrigUnit().getUnitDIE();
27 Language = dwarf::toUnsigned(CU.find(dwarf::DW_AT_language), 0);
32 void CompileUnit::markEverythingAsKept() {
35 setHasInterestingContent();
37 for (auto &I : Info) {
38 // Mark everything that wasn't explicit marked for pruning.
40 auto DIE = OrigUnit.getDIEAtIndex(Idx++);
42 // Try to guess which DIEs must go to the accelerator tables. We do that
43 // just for variables, because functions will be handled depending on
44 // whether they carry a DW_AT_low_pc attribute or not.
45 if (DIE.getTag() != dwarf::DW_TAG_variable &&
46 DIE.getTag() != dwarf::DW_TAG_constant)
49 Optional<DWARFFormValue> Value;
50 if (!(Value = DIE.find(dwarf::DW_AT_location))) {
51 if ((Value = DIE.find(dwarf::DW_AT_const_value)) &&
52 !inFunctionScope(*this, I.ParentIdx))
56 if (auto Block = Value->getAsBlock()) {
57 if (Block->size() > OrigUnit.getAddressByteSize() &&
58 (*Block)[0] == dwarf::DW_OP_addr)
64 uint64_t CompileUnit::computeNextUnitOffset() {
65 NextUnitOffset = StartOffset;
67 NextUnitOffset += 11 /* Header size */;
68 NextUnitOffset += NewUnit->getUnitDie().getSize();
70 return NextUnitOffset;
73 /// Keep track of a forward cross-cu reference from this unit
74 /// to \p Die that lives in \p RefUnit.
75 void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
76 DeclContext *Ctxt, PatchLocation Attr) {
77 ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr);
80 void CompileUnit::fixupForwardReferences() {
81 for (const auto &Ref : ForwardDIEReferences) {
83 const CompileUnit *RefUnit;
86 std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref;
87 if (Ctxt && Ctxt->getCanonicalDIEOffset())
88 Attr.set(Ctxt->getCanonicalDIEOffset());
90 Attr.set(RefDie->getOffset() + RefUnit->getStartOffset());
94 void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
95 Labels.insert({LabelLowPc, PcOffset});
98 void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
100 // Don't add empty ranges to the interval map. They are a problem because
101 // the interval map expects half open intervals. This is safe because they
103 if (FuncHighPc != FuncLowPc)
104 Ranges.insert(FuncLowPc, FuncHighPc, PcOffset);
105 this->LowPc = std::min(LowPc, FuncLowPc + PcOffset);
106 this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
109 void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) {
110 if (Die.getTag() != dwarf::DW_TAG_compile_unit)
111 RangeAttributes.push_back(Attr);
113 UnitRangeAttribute = Attr;
116 void CompileUnit::noteLocationAttribute(PatchLocation Attr, int64_t PcOffset) {
117 LocationAttributes.emplace_back(Attr, PcOffset);
120 void CompileUnit::addNamespaceAccelerator(const DIE *Die,
121 DwarfStringPoolEntryRef Name) {
122 Namespaces.emplace_back(Name, Die);
125 void CompileUnit::addObjCAccelerator(const DIE *Die,
126 DwarfStringPoolEntryRef Name,
127 bool SkipPubSection) {
128 ObjC.emplace_back(Name, Die, SkipPubSection);
131 void CompileUnit::addNameAccelerator(const DIE *Die,
132 DwarfStringPoolEntryRef Name,
133 bool SkipPubSection) {
134 Pubnames.emplace_back(Name, Die, SkipPubSection);
137 void CompileUnit::addTypeAccelerator(const DIE *Die,
138 DwarfStringPoolEntryRef Name,
139 bool ObjcClassImplementation,
140 uint32_t QualifiedNameHash) {
141 Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation);