1 //===- DIEGenerator.h -------------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIB_DWARFLINKERPARALLEL_DIEGENERATOR_H
10 #define LLVM_LIB_DWARFLINKERPARALLEL_DIEGENERATOR_H
12 #include "DWARFLinkerGlobalData.h"
13 #include "DWARFLinkerUnit.h"
14 #include "llvm/CodeGen/DIE.h"
15 #include "llvm/Support/LEB128.h"
18 namespace dwarflinker_parallel
{
20 /// This class is a helper to create output DIE tree.
23 DIEGenerator(BumpPtrAllocator
&Allocator
, DwarfUnit
&CU
)
24 : Allocator(Allocator
), CU(CU
) {}
26 /// Creates a DIE of specified tag \p DieTag and \p OutOffset.
27 DIE
*createDIE(dwarf::Tag DieTag
, uint32_t OutOffset
) {
28 OutputDIE
= DIE::get(Allocator
, DieTag
);
30 OutputDIE
->setOffset(OutOffset
);
35 /// Adds a specified \p Child to the current DIE.
36 void addChild(DIE
*Child
) {
37 assert(Child
!= nullptr);
38 assert(OutputDIE
!= nullptr);
40 OutputDIE
->addChild(Child
);
43 /// Adds specified scalar attribute to the current DIE.
44 std::pair
<DIEValue
&, size_t> addScalarAttribute(dwarf::Attribute Attr
,
47 return addAttribute(Attr
, AttrForm
, DIEInteger(Value
));
50 /// Adds specified location attribute to the current DIE.
51 std::pair
<DIEValue
&, size_t> addLocationAttribute(dwarf::Attribute Attr
,
53 ArrayRef
<uint8_t> Bytes
) {
54 DIELoc
*Loc
= new (Allocator
) DIELoc
;
55 for (auto Byte
: Bytes
)
56 static_cast<DIEValueList
*>(Loc
)->addValue(
57 Allocator
, static_cast<dwarf::Attribute
>(0), dwarf::DW_FORM_data1
,
59 Loc
->setSize(Bytes
.size());
61 return addAttribute(Attr
, AttrForm
, Loc
);
64 /// Adds specified block or exprloc attribute to the current DIE.
65 std::pair
<DIEValue
&, size_t> addBlockAttribute(dwarf::Attribute Attr
,
67 ArrayRef
<uint8_t> Bytes
) {
68 // The expression location data might be updated and exceed the original
69 // size. Check whether the new data fits into the original form.
70 assert((AttrForm
== dwarf::DW_FORM_block
) ||
71 (AttrForm
== dwarf::DW_FORM_exprloc
) ||
72 (AttrForm
== dwarf::DW_FORM_block1
&& Bytes
.size() <= UINT8_MAX
) ||
73 (AttrForm
== dwarf::DW_FORM_block2
&& Bytes
.size() <= UINT16_MAX
) ||
74 (AttrForm
== dwarf::DW_FORM_block4
&& Bytes
.size() <= UINT32_MAX
));
76 DIEBlock
*Block
= new (Allocator
) DIEBlock
;
77 for (auto Byte
: Bytes
)
78 static_cast<DIEValueList
*>(Block
)->addValue(
79 Allocator
, static_cast<dwarf::Attribute
>(0), dwarf::DW_FORM_data1
,
81 Block
->setSize(Bytes
.size());
83 return addAttribute(Attr
, AttrForm
, Block
);
86 /// Adds specified location list attribute to the current DIE.
87 std::pair
<DIEValue
&, size_t> addLocListAttribute(dwarf::Attribute Attr
,
90 return addAttribute(Attr
, AttrForm
, DIELocList(Value
));
93 /// Adds indexed string attribute.
94 std::pair
<DIEValue
&, size_t> addIndexedStringAttribute(dwarf::Attribute Attr
,
97 assert(AttrForm
== dwarf::DW_FORM_strx
);
98 return addAttribute(Attr
, AttrForm
, DIEInteger(Idx
));
101 /// Adds string attribute with dummy offset to the current DIE.
102 std::pair
<DIEValue
&, size_t>
103 addStringPlaceholderAttribute(dwarf::Attribute Attr
, dwarf::Form AttrForm
) {
104 assert(AttrForm
== dwarf::DW_FORM_strp
||
105 AttrForm
== dwarf::DW_FORM_line_strp
);
106 return addAttribute(Attr
, AttrForm
, DIEInteger(0xBADDEF));
109 /// Adds inplace string attribute to the current DIE.
110 std::pair
<DIEValue
&, size_t> addInplaceString(dwarf::Attribute Attr
,
112 DIEBlock
*Block
= new (Allocator
) DIEBlock
;
113 for (auto Byte
: String
.bytes())
114 static_cast<DIEValueList
*>(Block
)->addValue(
115 Allocator
, static_cast<dwarf::Attribute
>(0), dwarf::DW_FORM_data1
,
118 static_cast<DIEValueList
*>(Block
)->addValue(
119 Allocator
, static_cast<dwarf::Attribute
>(0), dwarf::DW_FORM_data1
,
121 Block
->setSize(String
.size() + 1);
124 *OutputDIE
->addValue(Allocator
, Attr
, dwarf::DW_FORM_string
, Block
);
125 return std::pair
<DIEValue
&, size_t>(ValueRef
, String
.size() + 1);
128 /// Creates appreviations for the current DIE. Returns value of
129 /// abbreviation number.
130 size_t finalizeAbbreviations(bool CHILDREN_yes
) {
131 // Create abbreviations for output DIE.
132 DIEAbbrev NewAbbrev
= OutputDIE
->generateAbbrev();
134 NewAbbrev
.setChildrenFlag(dwarf::DW_CHILDREN_yes
);
136 CU
.assignAbbrev(NewAbbrev
);
137 OutputDIE
->setAbbrevNumber(NewAbbrev
.getNumber());
139 return getULEB128Size(OutputDIE
->getAbbrevNumber());
143 template <typename T
>
144 std::pair
<DIEValue
&, size_t> addAttribute(dwarf::Attribute Attr
,
145 dwarf::Form AttrForm
, T
&&Value
) {
147 *OutputDIE
->addValue(Allocator
, Attr
, AttrForm
, std::forward
<T
>(Value
));
148 unsigned ValueSize
= ValueRef
.sizeOf(CU
.getFormParams());
149 return std::pair
<DIEValue
&, size_t>(ValueRef
, ValueSize
);
152 // Allocator for output DIEs and values.
153 BumpPtrAllocator
&Allocator
;
155 // Unit for the output DIE.
159 DIE
*OutputDIE
= nullptr;
162 } // end of namespace dwarflinker_parallel
163 } // end namespace llvm
165 #endif // LLVM_LIB_DWARFLINKERPARALLEL_DIEGENERATOR_H