[RISCV] Match vcompress during shuffle lowering (#117748)
[llvm-project.git] / llvm / lib / DWARFLinker / Classic / DWARFLinkerCompileUnit.cpp
blob1eb3a70a551359d0e57e0aae8c83ca4444ea0fb1
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 //===----------------------------------------------------------------------===//
9 #include "llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h"
10 #include "llvm/ADT/StringExtras.h"
11 #include "llvm/DWARFLinker/Classic/DWARFLinkerDeclContext.h"
12 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
13 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
14 #include "llvm/Support/FormatVariadic.h"
16 namespace llvm {
18 using namespace dwarf_linker;
19 using namespace dwarf_linker::classic;
21 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
22 LLVM_DUMP_METHOD void CompileUnit::DIEInfo::dump() {
23 llvm::errs() << "{\n";
24 llvm::errs() << " AddrAdjust: " << AddrAdjust << '\n';
25 llvm::errs() << " Ctxt: " << formatv("{0:x}", Ctxt) << '\n';
26 llvm::errs() << " Clone: " << formatv("{0:x}", Clone) << '\n';
27 llvm::errs() << " ParentIdx: " << ParentIdx << '\n';
28 llvm::errs() << " Keep: " << Keep << '\n';
29 llvm::errs() << " InDebugMap: " << InDebugMap << '\n';
30 llvm::errs() << " Prune: " << Prune << '\n';
31 llvm::errs() << " Incomplete: " << Incomplete << '\n';
32 llvm::errs() << " InModuleScope: " << InModuleScope << '\n';
33 llvm::errs() << " ODRMarkingDone: " << ODRMarkingDone << '\n';
34 llvm::errs() << " UnclonedReference: " << UnclonedReference << '\n';
35 llvm::errs() << "}\n";
37 #endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
39 /// Check if the DIE at \p Idx is in the scope of a function.
40 static bool inFunctionScope(CompileUnit &U, unsigned Idx) {
41 while (Idx) {
42 if (U.getOrigUnit().getDIEAtIndex(Idx).getTag() == dwarf::DW_TAG_subprogram)
43 return true;
44 Idx = U.getInfo(Idx).ParentIdx;
46 return false;
49 uint16_t CompileUnit::getLanguage() {
50 if (!Language) {
51 DWARFDie CU = getOrigUnit().getUnitDIE();
52 Language = dwarf::toUnsigned(CU.find(dwarf::DW_AT_language), 0);
54 return Language;
57 StringRef CompileUnit::getSysRoot() {
58 if (SysRoot.empty()) {
59 DWARFDie CU = getOrigUnit().getUnitDIE();
60 SysRoot = dwarf::toStringRef(CU.find(dwarf::DW_AT_LLVM_sysroot)).str();
62 return SysRoot;
65 void CompileUnit::markEverythingAsKept() {
66 unsigned Idx = 0;
68 for (auto &I : Info) {
69 // Mark everything that wasn't explicit marked for pruning.
70 I.Keep = !I.Prune;
71 auto DIE = OrigUnit.getDIEAtIndex(Idx++);
72 DWARFUnit *U = DIE.getDwarfUnit();
74 // Try to guess which DIEs must go to the accelerator tables. We do that
75 // just for variables, because functions will be handled depending on
76 // whether they carry a DW_AT_low_pc attribute or not.
77 if (DIE.getTag() != dwarf::DW_TAG_variable &&
78 DIE.getTag() != dwarf::DW_TAG_constant)
79 continue;
81 std::optional<DWARFFormValue> Value;
82 if (!(Value = DIE.find(dwarf::DW_AT_location))) {
83 if ((Value = DIE.find(dwarf::DW_AT_const_value)) &&
84 !inFunctionScope(*this, I.ParentIdx))
85 I.InDebugMap = true;
86 continue;
89 if (auto ExprLockBlock = Value->getAsBlock()) {
90 // Parse 'exprloc' expression.
91 DataExtractor Data(toStringRef(*ExprLockBlock),
92 U->getContext().isLittleEndian(),
93 U->getAddressByteSize());
94 DWARFExpression Expression(Data, U->getAddressByteSize(),
95 U->getFormParams().Format);
97 for (DWARFExpression::iterator It = Expression.begin();
98 (It != Expression.end()) && !I.InDebugMap; ++It) {
99 DWARFExpression::iterator NextIt = It;
100 ++NextIt;
102 switch (It->getCode()) {
103 case dwarf::DW_OP_const2u:
104 case dwarf::DW_OP_const4u:
105 case dwarf::DW_OP_const8u:
106 case dwarf::DW_OP_const2s:
107 case dwarf::DW_OP_const4s:
108 case dwarf::DW_OP_const8s:
109 if (NextIt == Expression.end() ||
110 NextIt->getCode() != dwarf::DW_OP_form_tls_address)
111 break;
112 [[fallthrough]];
113 case dwarf::DW_OP_constx:
114 case dwarf::DW_OP_addr:
115 case dwarf::DW_OP_addrx:
116 I.InDebugMap = true;
117 break;
118 default:
119 // Nothing to do.
120 break;
127 uint64_t CompileUnit::computeNextUnitOffset(uint16_t DwarfVersion) {
128 NextUnitOffset = StartOffset;
129 if (NewUnit) {
130 NextUnitOffset += (DwarfVersion >= 5) ? 12 : 11; // Header size
131 NextUnitOffset += NewUnit->getUnitDie().getSize();
133 return NextUnitOffset;
136 /// Keep track of a forward cross-cu reference from this unit
137 /// to \p Die that lives in \p RefUnit.
138 void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
139 DeclContext *Ctxt, PatchLocation Attr) {
140 ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr);
143 void CompileUnit::fixupForwardReferences() {
144 for (const auto &Ref : ForwardDIEReferences) {
145 DIE *RefDie;
146 const CompileUnit *RefUnit;
147 PatchLocation Attr;
148 DeclContext *Ctxt;
149 std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref;
150 if (Ctxt && Ctxt->hasCanonicalDIE()) {
151 assert(Ctxt->getCanonicalDIEOffset() &&
152 "Canonical die offset is not set");
153 Attr.set(Ctxt->getCanonicalDIEOffset());
154 } else {
155 assert(RefDie->getOffset() && "Referenced die offset is not set");
156 Attr.set(RefDie->getOffset() + RefUnit->getStartOffset());
161 void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
162 Labels.insert({LabelLowPc, PcOffset});
165 void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
166 int64_t PcOffset) {
167 Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset);
168 if (LowPc)
169 LowPc = std::min(*LowPc, FuncLowPc + PcOffset);
170 else
171 LowPc = FuncLowPc + PcOffset;
172 this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
175 void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) {
176 if (Die.getTag() == dwarf::DW_TAG_compile_unit) {
177 UnitRangeAttribute = Attr;
178 return;
181 RangeAttributes.emplace_back(Attr);
184 void CompileUnit::noteLocationAttribute(PatchLocation Attr) {
185 LocationAttributes.emplace_back(Attr);
188 void CompileUnit::addNamespaceAccelerator(const DIE *Die,
189 DwarfStringPoolEntryRef Name) {
190 Namespaces.emplace_back(Name, Die);
193 void CompileUnit::addObjCAccelerator(const DIE *Die,
194 DwarfStringPoolEntryRef Name,
195 bool SkipPubSection) {
196 ObjC.emplace_back(Name, Die, SkipPubSection);
199 void CompileUnit::addNameAccelerator(const DIE *Die,
200 DwarfStringPoolEntryRef Name,
201 bool SkipPubSection) {
202 Pubnames.emplace_back(Name, Die, SkipPubSection);
205 void CompileUnit::addTypeAccelerator(const DIE *Die,
206 DwarfStringPoolEntryRef Name,
207 bool ObjcClassImplementation,
208 uint32_t QualifiedNameHash) {
209 Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation);
212 } // namespace llvm