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