aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DIEGenerator.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DIEGenerator.h')
-rw-r--r--contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DIEGenerator.h180
1 files changed, 180 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DIEGenerator.h b/contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DIEGenerator.h
new file mode 100644
index 000000000000..42bf00f55ff1
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DIEGenerator.h
@@ -0,0 +1,180 @@
+//===- DIEGenerator.h -------------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_DWARFLINKERPARALLEL_DIEGENERATOR_H
+#define LLVM_LIB_DWARFLINKERPARALLEL_DIEGENERATOR_H
+
+#include "DWARFLinkerGlobalData.h"
+#include "DWARFLinkerUnit.h"
+#include "llvm/CodeGen/DIE.h"
+#include "llvm/Support/LEB128.h"
+
+namespace llvm {
+namespace dwarflinker_parallel {
+
+/// This class is a helper to create output DIE tree.
+class DIEGenerator {
+public:
+ DIEGenerator(BumpPtrAllocator &Allocator, DwarfUnit &CU)
+ : Allocator(Allocator), CU(CU) {}
+
+ DIEGenerator(DIE *OutputDIE, BumpPtrAllocator &Allocator, DwarfUnit &CU)
+ : Allocator(Allocator), CU(CU), OutputDIE(OutputDIE) {}
+
+ /// Creates a DIE of specified tag \p DieTag and \p OutOffset.
+ DIE *createDIE(dwarf::Tag DieTag, uint32_t OutOffset) {
+ OutputDIE = DIE::get(Allocator, DieTag);
+
+ OutputDIE->setOffset(OutOffset);
+
+ return OutputDIE;
+ }
+
+ DIE *getDIE() { return OutputDIE; }
+
+ /// Adds a specified \p Child to the current DIE.
+ void addChild(DIE *Child) {
+ assert(Child != nullptr);
+ assert(OutputDIE != nullptr);
+
+ OutputDIE->addChild(Child);
+ }
+
+ /// Adds specified scalar attribute to the current DIE.
+ std::pair<DIEValue &, size_t> addScalarAttribute(dwarf::Attribute Attr,
+ dwarf::Form AttrForm,
+ uint64_t Value) {
+ return addAttribute(Attr, AttrForm, DIEInteger(Value));
+ }
+
+ /// Adds specified location attribute to the current DIE.
+ std::pair<DIEValue &, size_t> addLocationAttribute(dwarf::Attribute Attr,
+ dwarf::Form AttrForm,
+ ArrayRef<uint8_t> Bytes) {
+ DIELoc *Loc = new (Allocator) DIELoc;
+ for (auto Byte : Bytes)
+ static_cast<DIEValueList *>(Loc)->addValue(
+ Allocator, static_cast<dwarf::Attribute>(0), dwarf::DW_FORM_data1,
+ DIEInteger(Byte));
+ Loc->setSize(Bytes.size());
+
+ return addAttribute(Attr, AttrForm, Loc);
+ }
+
+ /// Adds specified block or exprloc attribute to the current DIE.
+ std::pair<DIEValue &, size_t> addBlockAttribute(dwarf::Attribute Attr,
+ dwarf::Form AttrForm,
+ ArrayRef<uint8_t> Bytes) {
+ // The expression location data might be updated and exceed the original
+ // size. Check whether the new data fits into the original form.
+ assert((AttrForm == dwarf::DW_FORM_block) ||
+ (AttrForm == dwarf::DW_FORM_exprloc) ||
+ (AttrForm == dwarf::DW_FORM_block1 && Bytes.size() <= UINT8_MAX) ||
+ (AttrForm == dwarf::DW_FORM_block2 && Bytes.size() <= UINT16_MAX) ||
+ (AttrForm == dwarf::DW_FORM_block4 && Bytes.size() <= UINT32_MAX));
+
+ DIEBlock *Block = new (Allocator) DIEBlock;
+ for (auto Byte : Bytes)
+ static_cast<DIEValueList *>(Block)->addValue(
+ Allocator, static_cast<dwarf::Attribute>(0), dwarf::DW_FORM_data1,
+ DIEInteger(Byte));
+ Block->setSize(Bytes.size());
+
+ return addAttribute(Attr, AttrForm, Block);
+ }
+
+ /// Adds specified location list attribute to the current DIE.
+ std::pair<DIEValue &, size_t> addLocListAttribute(dwarf::Attribute Attr,
+ dwarf::Form AttrForm,
+ uint64_t Value) {
+ return addAttribute(Attr, AttrForm, DIELocList(Value));
+ }
+
+ /// Adds indexed string attribute.
+ std::pair<DIEValue &, size_t> addIndexedStringAttribute(dwarf::Attribute Attr,
+ dwarf::Form AttrForm,
+ uint64_t Idx) {
+ assert(AttrForm == dwarf::DW_FORM_strx);
+ return addAttribute(Attr, AttrForm, DIEInteger(Idx));
+ }
+
+ /// Adds string attribute with dummy offset to the current DIE.
+ std::pair<DIEValue &, size_t>
+ addStringPlaceholderAttribute(dwarf::Attribute Attr, dwarf::Form AttrForm) {
+ assert(AttrForm == dwarf::DW_FORM_strp ||
+ AttrForm == dwarf::DW_FORM_line_strp);
+ return addAttribute(Attr, AttrForm, DIEInteger(0xBADDEF));
+ }
+
+ /// Adds inplace string attribute to the current DIE.
+ std::pair<DIEValue &, size_t> addInplaceString(dwarf::Attribute Attr,
+ StringRef String) {
+ DIEBlock *Block = new (Allocator) DIEBlock;
+ for (auto Byte : String.bytes())
+ static_cast<DIEValueList *>(Block)->addValue(
+ Allocator, static_cast<dwarf::Attribute>(0), dwarf::DW_FORM_data1,
+ DIEInteger(Byte));
+
+ static_cast<DIEValueList *>(Block)->addValue(
+ Allocator, static_cast<dwarf::Attribute>(0), dwarf::DW_FORM_data1,
+ DIEInteger(0));
+ Block->setSize(String.size() + 1);
+
+ DIEValue &ValueRef =
+ *OutputDIE->addValue(Allocator, Attr, dwarf::DW_FORM_string, Block);
+ return std::pair<DIEValue &, size_t>(ValueRef, String.size() + 1);
+ }
+
+ /// Creates appreviations for the current DIE. Returns value of
+ /// abbreviation number. Updates offsets with the size of abbreviation
+ /// number.
+ size_t finalizeAbbreviations(bool CHILDREN_yes,
+ OffsetsPtrVector *OffsetsList) {
+ // Create abbreviations for output DIE.
+ DIEAbbrev NewAbbrev = OutputDIE->generateAbbrev();
+ if (CHILDREN_yes)
+ NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
+
+ CU.assignAbbrev(NewAbbrev);
+ OutputDIE->setAbbrevNumber(NewAbbrev.getNumber());
+
+ size_t AbbrevNumberSize = getULEB128Size(OutputDIE->getAbbrevNumber());
+
+ // Add size of abbreviation number to the offsets.
+ if (OffsetsList != nullptr) {
+ for (uint64_t *OffsetPtr : *OffsetsList)
+ *OffsetPtr += AbbrevNumberSize;
+ }
+
+ return AbbrevNumberSize;
+ }
+
+protected:
+ template <typename T>
+ std::pair<DIEValue &, size_t> addAttribute(dwarf::Attribute Attr,
+ dwarf::Form AttrForm, T &&Value) {
+ DIEValue &ValueRef =
+ *OutputDIE->addValue(Allocator, Attr, AttrForm, std::forward<T>(Value));
+ unsigned ValueSize = ValueRef.sizeOf(CU.getFormParams());
+ return std::pair<DIEValue &, size_t>(ValueRef, ValueSize);
+ }
+
+ // Allocator for output DIEs and values.
+ BumpPtrAllocator &Allocator;
+
+ // Unit for the output DIE.
+ DwarfUnit &CU;
+
+ // OutputDIE.
+ DIE *OutputDIE = nullptr;
+};
+
+} // end of namespace dwarflinker_parallel
+} // end namespace llvm
+
+#endif // LLVM_LIB_DWARFLINKERPARALLEL_DIEGENERATOR_H