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 uint16_t CompileUnit::getLanguage() {
27 DWARFDie CU
= getOrigUnit().getUnitDIE();
28 Language
= dwarf::toUnsigned(CU
.find(dwarf::DW_AT_language
), 0);
33 void CompileUnit::markEverythingAsKept() {
36 setHasInterestingContent();
38 for (auto &I
: Info
) {
39 // Mark everything that wasn't explicit marked for pruning.
41 auto DIE
= OrigUnit
.getDIEAtIndex(Idx
++);
43 // Try to guess which DIEs must go to the accelerator tables. We do that
44 // just for variables, because functions will be handled depending on
45 // whether they carry a DW_AT_low_pc attribute or not.
46 if (DIE
.getTag() != dwarf::DW_TAG_variable
&&
47 DIE
.getTag() != dwarf::DW_TAG_constant
)
50 Optional
<DWARFFormValue
> Value
;
51 if (!(Value
= DIE
.find(dwarf::DW_AT_location
))) {
52 if ((Value
= DIE
.find(dwarf::DW_AT_const_value
)) &&
53 !inFunctionScope(*this, I
.ParentIdx
))
57 if (auto Block
= Value
->getAsBlock()) {
58 if (Block
->size() > OrigUnit
.getAddressByteSize() &&
59 (*Block
)[0] == dwarf::DW_OP_addr
)
65 uint64_t CompileUnit::computeNextUnitOffset() {
66 NextUnitOffset
= StartOffset
;
68 NextUnitOffset
+= 11 /* Header size */;
69 NextUnitOffset
+= NewUnit
->getUnitDie().getSize();
71 return NextUnitOffset
;
74 /// Keep track of a forward cross-cu reference from this unit
75 /// to \p Die that lives in \p RefUnit.
76 void CompileUnit::noteForwardReference(DIE
*Die
, const CompileUnit
*RefUnit
,
77 DeclContext
*Ctxt
, PatchLocation Attr
) {
78 ForwardDIEReferences
.emplace_back(Die
, RefUnit
, Ctxt
, Attr
);
81 void CompileUnit::fixupForwardReferences() {
82 for (const auto &Ref
: ForwardDIEReferences
) {
84 const CompileUnit
*RefUnit
;
87 std::tie(RefDie
, RefUnit
, Ctxt
, Attr
) = Ref
;
88 if (Ctxt
&& Ctxt
->getCanonicalDIEOffset())
89 Attr
.set(Ctxt
->getCanonicalDIEOffset());
91 Attr
.set(RefDie
->getOffset() + RefUnit
->getStartOffset());
95 void CompileUnit::addLabelLowPc(uint64_t LabelLowPc
, int64_t PcOffset
) {
96 Labels
.insert({LabelLowPc
, PcOffset
});
99 void CompileUnit::addFunctionRange(uint64_t FuncLowPc
, uint64_t FuncHighPc
,
101 // Don't add empty ranges to the interval map. They are a problem because
102 // the interval map expects half open intervals. This is safe because they
104 if (FuncHighPc
!= FuncLowPc
)
105 Ranges
.insert(FuncLowPc
, FuncHighPc
, PcOffset
);
106 this->LowPc
= std::min(LowPc
, FuncLowPc
+ PcOffset
);
107 this->HighPc
= std::max(HighPc
, FuncHighPc
+ PcOffset
);
110 void CompileUnit::noteRangeAttribute(const DIE
&Die
, PatchLocation Attr
) {
111 if (Die
.getTag() != dwarf::DW_TAG_compile_unit
)
112 RangeAttributes
.push_back(Attr
);
114 UnitRangeAttribute
= Attr
;
117 void CompileUnit::noteLocationAttribute(PatchLocation Attr
, int64_t PcOffset
) {
118 LocationAttributes
.emplace_back(Attr
, PcOffset
);
121 void CompileUnit::addNamespaceAccelerator(const DIE
*Die
,
122 DwarfStringPoolEntryRef Name
) {
123 Namespaces
.emplace_back(Name
, Die
);
126 void CompileUnit::addObjCAccelerator(const DIE
*Die
,
127 DwarfStringPoolEntryRef Name
,
128 bool SkipPubSection
) {
129 ObjC
.emplace_back(Name
, Die
, SkipPubSection
);
132 void CompileUnit::addNameAccelerator(const DIE
*Die
,
133 DwarfStringPoolEntryRef Name
,
134 bool SkipPubSection
) {
135 Pubnames
.emplace_back(Name
, Die
, SkipPubSection
);
138 void CompileUnit::addTypeAccelerator(const DIE
*Die
,
139 DwarfStringPoolEntryRef Name
,
140 bool ObjcClassImplementation
,
141 uint32_t QualifiedNameHash
) {
142 Pubtypes
.emplace_back(Name
, Die
, QualifiedNameHash
, ObjcClassImplementation
);
145 } // namespace dsymutil