aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp212
1 files changed, 212 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp b/contrib/llvm-project/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp
new file mode 100644
index 000000000000..1eb3a70a5513
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp
@@ -0,0 +1,212 @@
+//===- DWARFLinkerCompileUnit.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/DWARFLinker/Classic/DWARFLinkerDeclContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
+#include "llvm/Support/FormatVariadic.h"
+
+namespace llvm {
+
+using namespace dwarf_linker;
+using namespace dwarf_linker::classic;
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void CompileUnit::DIEInfo::dump() {
+ llvm::errs() << "{\n";
+ llvm::errs() << " AddrAdjust: " << AddrAdjust << '\n';
+ llvm::errs() << " Ctxt: " << formatv("{0:x}", Ctxt) << '\n';
+ llvm::errs() << " Clone: " << formatv("{0:x}", Clone) << '\n';
+ llvm::errs() << " ParentIdx: " << ParentIdx << '\n';
+ llvm::errs() << " Keep: " << Keep << '\n';
+ llvm::errs() << " InDebugMap: " << InDebugMap << '\n';
+ llvm::errs() << " Prune: " << Prune << '\n';
+ llvm::errs() << " Incomplete: " << Incomplete << '\n';
+ llvm::errs() << " InModuleScope: " << InModuleScope << '\n';
+ llvm::errs() << " ODRMarkingDone: " << ODRMarkingDone << '\n';
+ llvm::errs() << " UnclonedReference: " << UnclonedReference << '\n';
+ llvm::errs() << "}\n";
+}
+#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+
+/// Check if the DIE at \p Idx is in the scope of a function.
+static bool inFunctionScope(CompileUnit &U, unsigned Idx) {
+ while (Idx) {
+ if (U.getOrigUnit().getDIEAtIndex(Idx).getTag() == dwarf::DW_TAG_subprogram)
+ return true;
+ Idx = U.getInfo(Idx).ParentIdx;
+ }
+ return false;
+}
+
+uint16_t CompileUnit::getLanguage() {
+ if (!Language) {
+ DWARFDie CU = getOrigUnit().getUnitDIE();
+ Language = dwarf::toUnsigned(CU.find(dwarf::DW_AT_language), 0);
+ }
+ return Language;
+}
+
+StringRef CompileUnit::getSysRoot() {
+ if (SysRoot.empty()) {
+ DWARFDie CU = getOrigUnit().getUnitDIE();
+ SysRoot = dwarf::toStringRef(CU.find(dwarf::DW_AT_LLVM_sysroot)).str();
+ }
+ return SysRoot;
+}
+
+void CompileUnit::markEverythingAsKept() {
+ unsigned Idx = 0;
+
+ for (auto &I : Info) {
+ // Mark everything that wasn't explicit marked for pruning.
+ I.Keep = !I.Prune;
+ auto DIE = OrigUnit.getDIEAtIndex(Idx++);
+ DWARFUnit *U = DIE.getDwarfUnit();
+
+ // Try to guess which DIEs must go to the accelerator tables. We do that
+ // just for variables, because functions will be handled depending on
+ // whether they carry a DW_AT_low_pc attribute or not.
+ if (DIE.getTag() != dwarf::DW_TAG_variable &&
+ DIE.getTag() != dwarf::DW_TAG_constant)
+ continue;
+
+ std::optional<DWARFFormValue> Value;
+ if (!(Value = DIE.find(dwarf::DW_AT_location))) {
+ if ((Value = DIE.find(dwarf::DW_AT_const_value)) &&
+ !inFunctionScope(*this, I.ParentIdx))
+ I.InDebugMap = true;
+ continue;
+ }
+
+ if (auto ExprLockBlock = Value->getAsBlock()) {
+ // Parse 'exprloc' expression.
+ DataExtractor Data(toStringRef(*ExprLockBlock),
+ U->getContext().isLittleEndian(),
+ U->getAddressByteSize());
+ DWARFExpression Expression(Data, U->getAddressByteSize(),
+ U->getFormParams().Format);
+
+ for (DWARFExpression::iterator It = Expression.begin();
+ (It != Expression.end()) && !I.InDebugMap; ++It) {
+ DWARFExpression::iterator NextIt = It;
+ ++NextIt;
+
+ switch (It->getCode()) {
+ case dwarf::DW_OP_const2u:
+ case dwarf::DW_OP_const4u:
+ case dwarf::DW_OP_const8u:
+ case dwarf::DW_OP_const2s:
+ case dwarf::DW_OP_const4s:
+ case dwarf::DW_OP_const8s:
+ if (NextIt == Expression.end() ||
+ NextIt->getCode() != dwarf::DW_OP_form_tls_address)
+ break;
+ [[fallthrough]];
+ case dwarf::DW_OP_constx:
+ case dwarf::DW_OP_addr:
+ case dwarf::DW_OP_addrx:
+ I.InDebugMap = true;
+ break;
+ default:
+ // Nothing to do.
+ break;
+ }
+ }
+ }
+ }
+}
+
+uint64_t CompileUnit::computeNextUnitOffset(uint16_t DwarfVersion) {
+ NextUnitOffset = StartOffset;
+ if (NewUnit) {
+ NextUnitOffset += (DwarfVersion >= 5) ? 12 : 11; // Header size
+ NextUnitOffset += NewUnit->getUnitDie().getSize();
+ }
+ return NextUnitOffset;
+}
+
+/// Keep track of a forward cross-cu reference from this unit
+/// to \p Die that lives in \p RefUnit.
+void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
+ DeclContext *Ctxt, PatchLocation Attr) {
+ ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr);
+}
+
+void CompileUnit::fixupForwardReferences() {
+ for (const auto &Ref : ForwardDIEReferences) {
+ DIE *RefDie;
+ const CompileUnit *RefUnit;
+ PatchLocation Attr;
+ DeclContext *Ctxt;
+ std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref;
+ if (Ctxt && Ctxt->hasCanonicalDIE()) {
+ assert(Ctxt->getCanonicalDIEOffset() &&
+ "Canonical die offset is not set");
+ Attr.set(Ctxt->getCanonicalDIEOffset());
+ } else {
+ assert(RefDie->getOffset() && "Referenced die offset is not set");
+ Attr.set(RefDie->getOffset() + RefUnit->getStartOffset());
+ }
+ }
+}
+
+void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
+ Labels.insert({LabelLowPc, PcOffset});
+}
+
+void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
+ int64_t PcOffset) {
+ Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset);
+ if (LowPc)
+ LowPc = std::min(*LowPc, FuncLowPc + PcOffset);
+ else
+ LowPc = FuncLowPc + PcOffset;
+ this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
+}
+
+void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) {
+ if (Die.getTag() == dwarf::DW_TAG_compile_unit) {
+ UnitRangeAttribute = Attr;
+ return;
+ }
+
+ RangeAttributes.emplace_back(Attr);
+}
+
+void CompileUnit::noteLocationAttribute(PatchLocation Attr) {
+ LocationAttributes.emplace_back(Attr);
+}
+
+void CompileUnit::addNamespaceAccelerator(const DIE *Die,
+ DwarfStringPoolEntryRef Name) {
+ Namespaces.emplace_back(Name, Die);
+}
+
+void CompileUnit::addObjCAccelerator(const DIE *Die,
+ DwarfStringPoolEntryRef Name,
+ bool SkipPubSection) {
+ ObjC.emplace_back(Name, Die, SkipPubSection);
+}
+
+void CompileUnit::addNameAccelerator(const DIE *Die,
+ DwarfStringPoolEntryRef Name,
+ bool SkipPubSection) {
+ Pubnames.emplace_back(Name, Die, SkipPubSection);
+}
+
+void CompileUnit::addTypeAccelerator(const DIE *Die,
+ DwarfStringPoolEntryRef Name,
+ bool ObjcClassImplementation,
+ uint32_t QualifiedNameHash) {
+ Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation);
+}
+
+} // namespace llvm