diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DIEGenerator.h')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/DWARFLinkerParallel/DIEGenerator.h | 180 |
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 |
