1 //===- tools/dsymutil/CompileUnit.h - Dwarf compile unit ------------------===//
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 "CompileUnit.h"
10 #include "DeclContext.h"
15 /// Check if the DIE at \p Idx is in the scope of a function.
16 static bool inFunctionScope(CompileUnit
&U
, unsigned Idx
) {
18 if (U
.getOrigUnit().getDIEAtIndex(Idx
).getTag() == dwarf::DW_TAG_subprogram
)
20 Idx
= U
.getInfo(Idx
).ParentIdx
;
25 void CompileUnit::markEverythingAsKept() {
28 setHasInterestingContent();
30 for (auto &I
: Info
) {
31 // Mark everything that wasn't explicit marked for pruning.
33 auto DIE
= OrigUnit
.getDIEAtIndex(Idx
++);
35 // Try to guess which DIEs must go to the accelerator tables. We do that
36 // just for variables, because functions will be handled depending on
37 // whether they carry a DW_AT_low_pc attribute or not.
38 if (DIE
.getTag() != dwarf::DW_TAG_variable
&&
39 DIE
.getTag() != dwarf::DW_TAG_constant
)
42 Optional
<DWARFFormValue
> Value
;
43 if (!(Value
= DIE
.find(dwarf::DW_AT_location
))) {
44 if ((Value
= DIE
.find(dwarf::DW_AT_const_value
)) &&
45 !inFunctionScope(*this, I
.ParentIdx
))
49 if (auto Block
= Value
->getAsBlock()) {
50 if (Block
->size() > OrigUnit
.getAddressByteSize() &&
51 (*Block
)[0] == dwarf::DW_OP_addr
)
57 uint64_t CompileUnit::computeNextUnitOffset() {
58 NextUnitOffset
= StartOffset
+ 11 /* Header size */;
59 // The root DIE might be null, meaning that the Unit had nothing to
60 // contribute to the linked output. In that case, we will emit the
61 // unit header without any actual DIE.
63 NextUnitOffset
+= NewUnit
->getUnitDie().getSize();
64 return NextUnitOffset
;
67 /// Keep track of a forward cross-cu reference from this unit
68 /// to \p Die that lives in \p RefUnit.
69 void CompileUnit::noteForwardReference(DIE
*Die
, const CompileUnit
*RefUnit
,
70 DeclContext
*Ctxt
, PatchLocation Attr
) {
71 ForwardDIEReferences
.emplace_back(Die
, RefUnit
, Ctxt
, Attr
);
74 void CompileUnit::fixupForwardReferences() {
75 for (const auto &Ref
: ForwardDIEReferences
) {
77 const CompileUnit
*RefUnit
;
80 std::tie(RefDie
, RefUnit
, Ctxt
, Attr
) = Ref
;
81 if (Ctxt
&& Ctxt
->getCanonicalDIEOffset())
82 Attr
.set(Ctxt
->getCanonicalDIEOffset());
84 Attr
.set(RefDie
->getOffset() + RefUnit
->getStartOffset());
88 void CompileUnit::addLabelLowPc(uint64_t LabelLowPc
, int64_t PcOffset
) {
89 Labels
.insert({LabelLowPc
, PcOffset
});
92 void CompileUnit::addFunctionRange(uint64_t FuncLowPc
, uint64_t FuncHighPc
,
94 // Don't add empty ranges to the interval map. They are a problem because
95 // the interval map expects half open intervals. This is safe because they
97 if (FuncHighPc
!= FuncLowPc
)
98 Ranges
.insert(FuncLowPc
, FuncHighPc
, PcOffset
);
99 this->LowPc
= std::min(LowPc
, FuncLowPc
+ PcOffset
);
100 this->HighPc
= std::max(HighPc
, FuncHighPc
+ PcOffset
);
103 void CompileUnit::noteRangeAttribute(const DIE
&Die
, PatchLocation Attr
) {
104 if (Die
.getTag() != dwarf::DW_TAG_compile_unit
)
105 RangeAttributes
.push_back(Attr
);
107 UnitRangeAttribute
= Attr
;
110 void CompileUnit::noteLocationAttribute(PatchLocation Attr
, int64_t PcOffset
) {
111 LocationAttributes
.emplace_back(Attr
, PcOffset
);
114 void CompileUnit::addNamespaceAccelerator(const DIE
*Die
,
115 DwarfStringPoolEntryRef Name
) {
116 Namespaces
.emplace_back(Name
, Die
);
119 void CompileUnit::addObjCAccelerator(const DIE
*Die
,
120 DwarfStringPoolEntryRef Name
,
121 bool SkipPubSection
) {
122 ObjC
.emplace_back(Name
, Die
, SkipPubSection
);
125 void CompileUnit::addNameAccelerator(const DIE
*Die
,
126 DwarfStringPoolEntryRef Name
,
127 bool SkipPubSection
) {
128 Pubnames
.emplace_back(Name
, Die
, SkipPubSection
);
131 void CompileUnit::addTypeAccelerator(const DIE
*Die
,
132 DwarfStringPoolEntryRef Name
,
133 bool ObjcClassImplementation
,
134 uint32_t QualifiedNameHash
) {
135 Pubtypes
.emplace_back(Name
, Die
, QualifiedNameHash
, ObjcClassImplementation
);
138 } // namespace dsymutil