]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp
MFV: r363292
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / lib / DWARFLinker / DWARFLinkerCompileUnit.cpp
1 //===- DWARFLinkerCompileUnit.cpp -----------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
10 #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
11
12 namespace llvm {
13
14 /// Check if the DIE at \p Idx is in the scope of a function.
15 static bool inFunctionScope(CompileUnit &U, unsigned Idx) {
16   while (Idx) {
17     if (U.getOrigUnit().getDIEAtIndex(Idx).getTag() == dwarf::DW_TAG_subprogram)
18       return true;
19     Idx = U.getInfo(Idx).ParentIdx;
20   }
21   return false;
22 }
23
24 uint16_t CompileUnit::getLanguage() {
25   if (!Language) {
26     DWARFDie CU = getOrigUnit().getUnitDIE();
27     Language = dwarf::toUnsigned(CU.find(dwarf::DW_AT_language), 0);
28   }
29   return Language;
30 }
31
32 void CompileUnit::markEverythingAsKept() {
33   unsigned Idx = 0;
34
35   setHasInterestingContent();
36
37   for (auto &I : Info) {
38     // Mark everything that wasn't explicit marked for pruning.
39     I.Keep = !I.Prune;
40     auto DIE = OrigUnit.getDIEAtIndex(Idx++);
41
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)
47       continue;
48
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))
53         I.InDebugMap = true;
54       continue;
55     }
56     if (auto Block = Value->getAsBlock()) {
57       if (Block->size() > OrigUnit.getAddressByteSize() &&
58           (*Block)[0] == dwarf::DW_OP_addr)
59         I.InDebugMap = true;
60     }
61   }
62 }
63
64 uint64_t CompileUnit::computeNextUnitOffset() {
65   NextUnitOffset = StartOffset;
66   if (NewUnit) {
67     NextUnitOffset += 11 /* Header size */;
68     NextUnitOffset += NewUnit->getUnitDie().getSize();
69   }
70   return NextUnitOffset;
71 }
72
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);
78 }
79
80 void CompileUnit::fixupForwardReferences() {
81   for (const auto &Ref : ForwardDIEReferences) {
82     DIE *RefDie;
83     const CompileUnit *RefUnit;
84     PatchLocation Attr;
85     DeclContext *Ctxt;
86     std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref;
87     if (Ctxt && Ctxt->getCanonicalDIEOffset())
88       Attr.set(Ctxt->getCanonicalDIEOffset());
89     else
90       Attr.set(RefDie->getOffset() + RefUnit->getStartOffset());
91   }
92 }
93
94 void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
95   Labels.insert({LabelLowPc, PcOffset});
96 }
97
98 void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
99                                    int64_t PcOffset) {
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
102   //  are empty anyway.
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);
107 }
108
109 void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) {
110   if (Die.getTag() != dwarf::DW_TAG_compile_unit)
111     RangeAttributes.push_back(Attr);
112   else
113     UnitRangeAttribute = Attr;
114 }
115
116 void CompileUnit::noteLocationAttribute(PatchLocation Attr, int64_t PcOffset) {
117   LocationAttributes.emplace_back(Attr, PcOffset);
118 }
119
120 void CompileUnit::addNamespaceAccelerator(const DIE *Die,
121                                           DwarfStringPoolEntryRef Name) {
122   Namespaces.emplace_back(Name, Die);
123 }
124
125 void CompileUnit::addObjCAccelerator(const DIE *Die,
126                                      DwarfStringPoolEntryRef Name,
127                                      bool SkipPubSection) {
128   ObjC.emplace_back(Name, Die, SkipPubSection);
129 }
130
131 void CompileUnit::addNameAccelerator(const DIE *Die,
132                                      DwarfStringPoolEntryRef Name,
133                                      bool SkipPubSection) {
134   Pubnames.emplace_back(Name, Die, SkipPubSection);
135 }
136
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);
142 }
143
144 } // namespace llvm