1//===- DIEGenerator.h -------------------------------------------*- C++ -*-===//
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//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIB_DWARFLINKER_PARALLEL_DIEGENERATOR_H
10#define LLVM_LIB_DWARFLINKER_PARALLEL_DIEGENERATOR_H
11
12#include "DWARFLinkerGlobalData.h"
13#include "DWARFLinkerUnit.h"
14#include "llvm/CodeGen/DIE.h"
15#include "llvm/Support/LEB128.h"
16
17namespace llvm {
18namespace dwarf_linker {
19namespace parallel {
20
21/// This class is a helper to create output DIE tree.
22class DIEGenerator {
23public:
24 DIEGenerator(BumpPtrAllocator &Allocator, DwarfUnit &CU)
25 : Allocator(Allocator), CU(CU) {}
26
27 DIEGenerator(DIE *OutputDIE, BumpPtrAllocator &Allocator, DwarfUnit &CU)
28 : Allocator(Allocator), CU(CU), OutputDIE(OutputDIE) {}
29
30 /// Creates a DIE of specified tag \p DieTag and \p OutOffset.
31 DIE *createDIE(dwarf::Tag DieTag, uint32_t OutOffset) {
32 OutputDIE = DIE::get(Alloc&: Allocator, Tag: DieTag);
33
34 OutputDIE->setOffset(OutOffset);
35
36 return OutputDIE;
37 }
38
39 DIE *getDIE() { return OutputDIE; }
40
41 /// Adds a specified \p Child to the current DIE.
42 void addChild(DIE *Child) {
43 assert(Child != nullptr);
44 assert(OutputDIE != nullptr);
45
46 OutputDIE->addChild(Child);
47 }
48
49 /// Adds specified scalar attribute to the current DIE.
50 std::pair<DIEValue &, size_t> addScalarAttribute(dwarf::Attribute Attr,
51 dwarf::Form AttrForm,
52 uint64_t Value) {
53 return addAttribute(Attr, AttrForm, Value: DIEInteger(Value));
54 }
55
56 /// Adds specified location attribute to the current DIE.
57 std::pair<DIEValue &, size_t> addLocationAttribute(dwarf::Attribute Attr,
58 dwarf::Form AttrForm,
59 ArrayRef<uint8_t> Bytes) {
60 DIELoc *Loc = new (Allocator) DIELoc;
61 for (auto Byte : Bytes)
62 static_cast<DIEValueList *>(Loc)->addValue(
63 Alloc&: Allocator, Attribute: static_cast<dwarf::Attribute>(0), Form: dwarf::DW_FORM_data1,
64 Value: DIEInteger(Byte));
65 Loc->setSize(Bytes.size());
66
67 return addAttribute(Attr, AttrForm, Value&: Loc);
68 }
69
70 /// Adds specified block or exprloc attribute to the current DIE.
71 std::pair<DIEValue &, size_t> addBlockAttribute(dwarf::Attribute Attr,
72 dwarf::Form AttrForm,
73 ArrayRef<uint8_t> Bytes) {
74 // The expression location data might be updated and exceed the original
75 // size. Check whether the new data fits into the original form.
76 assert((AttrForm == dwarf::DW_FORM_block) ||
77 (AttrForm == dwarf::DW_FORM_exprloc) ||
78 (AttrForm == dwarf::DW_FORM_block1 && Bytes.size() <= UINT8_MAX) ||
79 (AttrForm == dwarf::DW_FORM_block2 && Bytes.size() <= UINT16_MAX) ||
80 (AttrForm == dwarf::DW_FORM_block4 && Bytes.size() <= UINT32_MAX));
81
82 DIEBlock *Block = new (Allocator) DIEBlock;
83 for (auto Byte : Bytes)
84 static_cast<DIEValueList *>(Block)->addValue(
85 Alloc&: Allocator, Attribute: static_cast<dwarf::Attribute>(0), Form: dwarf::DW_FORM_data1,
86 Value: DIEInteger(Byte));
87 Block->setSize(Bytes.size());
88
89 return addAttribute(Attr, AttrForm, Value&: Block);
90 }
91
92 /// Adds specified location list attribute to the current DIE.
93 std::pair<DIEValue &, size_t> addLocListAttribute(dwarf::Attribute Attr,
94 dwarf::Form AttrForm,
95 uint64_t Value) {
96 return addAttribute(Attr, AttrForm, Value: DIELocList(Value));
97 }
98
99 /// Adds indexed string attribute.
100 std::pair<DIEValue &, size_t> addIndexedStringAttribute(dwarf::Attribute Attr,
101 dwarf::Form AttrForm,
102 uint64_t Idx) {
103 assert(AttrForm == dwarf::DW_FORM_strx);
104 return addAttribute(Attr, AttrForm, Value: DIEInteger(Idx));
105 }
106
107 /// Adds string attribute with dummy offset to the current DIE.
108 std::pair<DIEValue &, size_t>
109 addStringPlaceholderAttribute(dwarf::Attribute Attr, dwarf::Form AttrForm) {
110 assert(AttrForm == dwarf::DW_FORM_strp ||
111 AttrForm == dwarf::DW_FORM_line_strp);
112 return addAttribute(Attr, AttrForm, Value: DIEInteger(0xBADDEF));
113 }
114
115 /// Adds inplace string attribute to the current DIE.
116 std::pair<DIEValue &, size_t> addInplaceString(dwarf::Attribute Attr,
117 StringRef String) {
118 DIEBlock *Block = new (Allocator) DIEBlock;
119 for (auto Byte : String.bytes())
120 static_cast<DIEValueList *>(Block)->addValue(
121 Alloc&: Allocator, Attribute: static_cast<dwarf::Attribute>(0), Form: dwarf::DW_FORM_data1,
122 Value: DIEInteger(Byte));
123
124 static_cast<DIEValueList *>(Block)->addValue(
125 Alloc&: Allocator, Attribute: static_cast<dwarf::Attribute>(0), Form: dwarf::DW_FORM_data1,
126 Value: DIEInteger(0));
127 Block->setSize(String.size() + 1);
128
129 DIEValue &ValueRef =
130 *OutputDIE->addValue(Alloc&: Allocator, Attribute: Attr, Form: dwarf::DW_FORM_string, Value&: Block);
131 return std::pair<DIEValue &, size_t>(ValueRef, String.size() + 1);
132 }
133
134 /// Creates appreviations for the current DIE. Returns value of
135 /// abbreviation number. Updates offsets with the size of abbreviation
136 /// number.
137 size_t finalizeAbbreviations(bool CHILDREN_yes,
138 OffsetsPtrVector *OffsetsList) {
139 // Create abbreviations for output DIE.
140 DIEAbbrev NewAbbrev = OutputDIE->generateAbbrev();
141 if (CHILDREN_yes)
142 NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
143
144 CU.assignAbbrev(Abbrev&: NewAbbrev);
145 OutputDIE->setAbbrevNumber(NewAbbrev.getNumber());
146
147 size_t AbbrevNumberSize = getULEB128Size(Value: OutputDIE->getAbbrevNumber());
148
149 // Add size of abbreviation number to the offsets.
150 if (OffsetsList != nullptr) {
151 for (uint64_t *OffsetPtr : *OffsetsList)
152 *OffsetPtr += AbbrevNumberSize;
153 }
154
155 return AbbrevNumberSize;
156 }
157
158protected:
159 template <typename T>
160 std::pair<DIEValue &, size_t> addAttribute(dwarf::Attribute Attr,
161 dwarf::Form AttrForm, T &&Value) {
162 DIEValue &ValueRef =
163 *OutputDIE->addValue(Allocator, Attr, AttrForm, std::forward<T>(Value));
164 unsigned ValueSize = ValueRef.sizeOf(FormParams: CU.getFormParams());
165 return std::pair<DIEValue &, size_t>(ValueRef, ValueSize);
166 }
167
168 // Allocator for output DIEs and values.
169 BumpPtrAllocator &Allocator;
170
171 // Unit for the output DIE.
172 DwarfUnit &CU;
173
174 // OutputDIE.
175 DIE *OutputDIE = nullptr;
176};
177
178} // end of namespace parallel
179} // end of namespace dwarf_linker
180} // end of namespace llvm
181
182#endif // LLVM_LIB_DWARFLINKER_PARALLEL_DIEGENERATOR_H
183