xref: /freebsd/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DIEGenerator.h (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
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 
17 namespace llvm {
18 namespace dwarf_linker {
19 namespace parallel {
20 
21 /// This class is a helper to create output DIE tree.
22 class DIEGenerator {
23 public:
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(Allocator, 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, 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           Allocator, static_cast<dwarf::Attribute>(0), dwarf::DW_FORM_data1,
64           DIEInteger(Byte));
65     Loc->setSize(Bytes.size());
66 
67     return addAttribute(Attr, AttrForm, 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           Allocator, static_cast<dwarf::Attribute>(0), dwarf::DW_FORM_data1,
86           DIEInteger(Byte));
87     Block->setSize(Bytes.size());
88 
89     return addAttribute(Attr, AttrForm, 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, 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, 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, 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           Allocator, static_cast<dwarf::Attribute>(0), dwarf::DW_FORM_data1,
122           DIEInteger(Byte));
123 
124     static_cast<DIEValueList *>(Block)->addValue(
125         Allocator, static_cast<dwarf::Attribute>(0), dwarf::DW_FORM_data1,
126         DIEInteger(0));
127     Block->setSize(String.size() + 1);
128 
129     DIEValue &ValueRef =
130         *OutputDIE->addValue(Allocator, Attr, dwarf::DW_FORM_string, 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(NewAbbrev);
145     OutputDIE->setAbbrevNumber(NewAbbrev.getNumber());
146 
147     size_t AbbrevNumberSize = getULEB128Size(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 
158 protected:
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(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