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
;
60 NextUnitOffset
+= 11 /* Header size */;
61 NextUnitOffset
+= NewUnit
->getUnitDie().getSize();
63 return NextUnitOffset
;
66 /// Keep track of a forward cross-cu reference from this unit
67 /// to \p Die that lives in \p RefUnit.
68 void CompileUnit::noteForwardReference(DIE
*Die
, const CompileUnit
*RefUnit
,
69 DeclContext
*Ctxt
, PatchLocation Attr
) {
70 ForwardDIEReferences
.emplace_back(Die
, RefUnit
, Ctxt
, Attr
);
73 void CompileUnit::fixupForwardReferences() {
74 for (const auto &Ref
: ForwardDIEReferences
) {
76 const CompileUnit
*RefUnit
;
79 std::tie(RefDie
, RefUnit
, Ctxt
, Attr
) = Ref
;
80 if (Ctxt
&& Ctxt
->getCanonicalDIEOffset())
81 Attr
.set(Ctxt
->getCanonicalDIEOffset());
83 Attr
.set(RefDie
->getOffset() + RefUnit
->getStartOffset());
87 void CompileUnit::addLabelLowPc(uint64_t LabelLowPc
, int64_t PcOffset
) {
88 Labels
.insert({LabelLowPc
, PcOffset
});
91 void CompileUnit::addFunctionRange(uint64_t FuncLowPc
, uint64_t FuncHighPc
,
93 // Don't add empty ranges to the interval map. They are a problem because
94 // the interval map expects half open intervals. This is safe because they
96 if (FuncHighPc
!= FuncLowPc
)
97 Ranges
.insert(FuncLowPc
, FuncHighPc
, PcOffset
);
98 this->LowPc
= std::min(LowPc
, FuncLowPc
+ PcOffset
);
99 this->HighPc
= std::max(HighPc
, FuncHighPc
+ PcOffset
);
102 void CompileUnit::noteRangeAttribute(const DIE
&Die
, PatchLocation Attr
) {
103 if (Die
.getTag() != dwarf::DW_TAG_compile_unit
)
104 RangeAttributes
.push_back(Attr
);
106 UnitRangeAttribute
= Attr
;
109 void CompileUnit::noteLocationAttribute(PatchLocation Attr
, int64_t PcOffset
) {
110 LocationAttributes
.emplace_back(Attr
, PcOffset
);
113 void CompileUnit::addNamespaceAccelerator(const DIE
*Die
,
114 DwarfStringPoolEntryRef Name
) {
115 Namespaces
.emplace_back(Name
, Die
);
118 void CompileUnit::addObjCAccelerator(const DIE
*Die
,
119 DwarfStringPoolEntryRef Name
,
120 bool SkipPubSection
) {
121 ObjC
.emplace_back(Name
, Die
, SkipPubSection
);
124 void CompileUnit::addNameAccelerator(const DIE
*Die
,
125 DwarfStringPoolEntryRef Name
,
126 bool SkipPubSection
) {
127 Pubnames
.emplace_back(Name
, Die
, SkipPubSection
);
130 void CompileUnit::addTypeAccelerator(const DIE
*Die
,
131 DwarfStringPoolEntryRef Name
,
132 bool ObjcClassImplementation
,
133 uint32_t QualifiedNameHash
) {
134 Pubtypes
.emplace_back(Name
, Die
, QualifiedNameHash
, ObjcClassImplementation
);
137 } // namespace dsymutil