[AMDGPU] Test codegen'ing True16 additions.
[llvm-project.git] / llvm / lib / DWARFLinkerParallel / OutputSections.cpp
blob91e89864836d41f5228c526fcb07fd1eecc9dd48
1 //=== OutputSections.cpp --------------------------------------------------===//
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 //===----------------------------------------------------------------------===//
9 #include "OutputSections.h"
10 #include "DWARFLinkerCompileUnit.h"
11 #include "llvm/ADT/StringSwitch.h"
13 namespace llvm {
14 namespace dwarflinker_parallel {
16 static constexpr StringLiteral SectionNames[SectionKindsNum] = {
17 "debug_info", "debug_line", "debug_frame", "debug_ranges",
18 "debug_rnglists", "debug_loc", "debug_loclists", "debug_aranges",
19 "debug_abbrev", "debug_macinfo", "debug_macro", "debug_addr",
20 "debug_str", "debug_line_str", "debug_str_offsets"};
22 const StringLiteral &getSectionName(DebugSectionKind SectionKind) {
23 return SectionNames[static_cast<uint8_t>(SectionKind)];
26 std::optional<DebugSectionKind> parseDebugTableName(llvm::StringRef SecName) {
27 return llvm::StringSwitch<std::optional<DebugSectionKind>>(
28 SecName.substr(SecName.find_first_not_of("._")))
29 .Case(getSectionName(DebugSectionKind::DebugInfo),
30 DebugSectionKind::DebugInfo)
31 .Case(getSectionName(DebugSectionKind::DebugLine),
32 DebugSectionKind::DebugLine)
33 .Case(getSectionName(DebugSectionKind::DebugFrame),
34 DebugSectionKind::DebugFrame)
35 .Case(getSectionName(DebugSectionKind::DebugRange),
36 DebugSectionKind::DebugRange)
37 .Case(getSectionName(DebugSectionKind::DebugRngLists),
38 DebugSectionKind::DebugRngLists)
39 .Case(getSectionName(DebugSectionKind::DebugLoc),
40 DebugSectionKind::DebugLoc)
41 .Case(getSectionName(DebugSectionKind::DebugLocLists),
42 DebugSectionKind::DebugLocLists)
43 .Case(getSectionName(DebugSectionKind::DebugARanges),
44 DebugSectionKind::DebugARanges)
45 .Case(getSectionName(DebugSectionKind::DebugAbbrev),
46 DebugSectionKind::DebugAbbrev)
47 .Case(getSectionName(DebugSectionKind::DebugMacinfo),
48 DebugSectionKind::DebugMacinfo)
49 .Case(getSectionName(DebugSectionKind::DebugMacro),
50 DebugSectionKind::DebugMacro)
51 .Case(getSectionName(DebugSectionKind::DebugAddr),
52 DebugSectionKind::DebugAddr)
53 .Case(getSectionName(DebugSectionKind::DebugStr),
54 DebugSectionKind::DebugStr)
55 .Case(getSectionName(DebugSectionKind::DebugLineStr),
56 DebugSectionKind::DebugLineStr)
57 .Case(getSectionName(DebugSectionKind::DebugStrOffsets),
58 DebugSectionKind::DebugStrOffsets)
59 .Default(std::nullopt);
61 return std::nullopt;
64 DebugDieRefPatch::DebugDieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU,
65 CompileUnit *RefCU, uint32_t RefIdx)
66 : SectionPatch({PatchOffset}),
67 RefCU(RefCU, (SrcCU != nullptr) &&
68 (SrcCU->getUniqueID() == RefCU->getUniqueID())),
69 RefDieIdxOrClonedOffset(RefIdx) {}
71 DebugULEB128DieRefPatch::DebugULEB128DieRefPatch(uint64_t PatchOffset,
72 CompileUnit *SrcCU,
73 CompileUnit *RefCU,
74 uint32_t RefIdx)
75 : SectionPatch({PatchOffset}),
76 RefCU(RefCU, SrcCU->getUniqueID() == RefCU->getUniqueID()),
77 RefDieIdxOrClonedOffset(RefIdx) {}
79 void SectionDescriptor::erase() {
80 StartOffset = 0;
81 Contents = OutSectionDataTy();
82 ListDebugStrPatch.erase();
83 ListDebugLineStrPatch.erase();
84 ListDebugRangePatch.erase();
85 ListDebugLocPatch.erase();
86 ListDebugDieRefPatch.erase();
87 ListDebugULEB128DieRefPatch.erase();
88 ListDebugOffsetPatch.erase();
91 void SectionDescriptor::setSizesForSectionCreatedByAsmPrinter() {
92 if (Contents.empty())
93 return;
95 MemoryBufferRef Mem(Contents, "obj");
96 Expected<std::unique_ptr<object::ObjectFile>> Obj =
97 object::ObjectFile::createObjectFile(Mem);
98 if (!Obj) {
99 consumeError(Obj.takeError());
100 Contents.clear();
101 return;
104 for (const object::SectionRef &Sect : (*Obj).get()->sections()) {
105 Expected<StringRef> SectNameOrErr = Sect.getName();
106 if (!SectNameOrErr) {
107 consumeError(SectNameOrErr.takeError());
108 continue;
111 if (std::optional<DebugSectionKind> SectKind =
112 parseDebugTableName(*SectNameOrErr)) {
113 if (*SectKind == SectionKind) {
114 Expected<StringRef> Data = Sect.getContents();
115 if (!Data) {
116 consumeError(SectNameOrErr.takeError());
117 Contents.clear();
118 return;
121 SectionOffsetInsideAsmPrinterOutputStart =
122 Data->data() - Contents.data();
123 SectionOffsetInsideAsmPrinterOutputEnd =
124 SectionOffsetInsideAsmPrinterOutputStart + Data->size();
130 void SectionDescriptor::emitIntVal(uint64_t Val, unsigned Size) {
131 switch (Size) {
132 case 1: {
133 OS.write(static_cast<uint8_t>(Val));
134 } break;
135 case 2: {
136 uint16_t ShortVal = static_cast<uint16_t>(Val);
137 if ((Endianess == support::endianness::little) != sys::IsLittleEndianHost)
138 sys::swapByteOrder(ShortVal);
139 OS.write(reinterpret_cast<const char *>(&ShortVal), Size);
140 } break;
141 case 4: {
142 uint32_t ShortVal = static_cast<uint32_t>(Val);
143 if ((Endianess == support::endianness::little) != sys::IsLittleEndianHost)
144 sys::swapByteOrder(ShortVal);
145 OS.write(reinterpret_cast<const char *>(&ShortVal), Size);
146 } break;
147 case 8: {
148 if ((Endianess == support::endianness::little) != sys::IsLittleEndianHost)
149 sys::swapByteOrder(Val);
150 OS.write(reinterpret_cast<const char *>(&Val), Size);
151 } break;
152 default:
153 llvm_unreachable("Unsupported integer type size");
157 void SectionDescriptor::emitString(dwarf::Form StringForm,
158 const char *StringVal) {
159 assert(StringVal != nullptr);
161 switch (StringForm) {
162 case dwarf::DW_FORM_string: {
163 emitInplaceString(GlobalData.translateString(StringVal));
164 } break;
165 case dwarf::DW_FORM_strp: {
166 notePatch(DebugStrPatch{
167 {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});
168 emitStringPlaceholder();
169 } break;
170 case dwarf::DW_FORM_line_strp: {
171 notePatch(DebugLineStrPatch{
172 {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});
173 emitStringPlaceholder();
174 } break;
175 default:
176 llvm_unreachable("Unsupported string form");
177 break;
181 void SectionDescriptor::apply(uint64_t PatchOffset, dwarf::Form AttrForm,
182 uint64_t Val) {
183 switch (AttrForm) {
184 case dwarf::DW_FORM_strp:
185 case dwarf::DW_FORM_line_strp: {
186 applyIntVal(PatchOffset, Val, Format.getDwarfOffsetByteSize());
187 } break;
189 case dwarf::DW_FORM_ref_addr: {
190 applyIntVal(PatchOffset, Val, Format.getRefAddrByteSize());
191 } break;
192 case dwarf::DW_FORM_ref1: {
193 applyIntVal(PatchOffset, Val, 1);
194 } break;
195 case dwarf::DW_FORM_ref2: {
196 applyIntVal(PatchOffset, Val, 2);
197 } break;
198 case dwarf::DW_FORM_ref4: {
199 applyIntVal(PatchOffset, Val, 4);
200 } break;
201 case dwarf::DW_FORM_ref8: {
202 applyIntVal(PatchOffset, Val, 8);
203 } break;
205 case dwarf::DW_FORM_data1: {
206 applyIntVal(PatchOffset, Val, 1);
207 } break;
208 case dwarf::DW_FORM_data2: {
209 applyIntVal(PatchOffset, Val, 2);
210 } break;
211 case dwarf::DW_FORM_data4: {
212 applyIntVal(PatchOffset, Val, 4);
213 } break;
214 case dwarf::DW_FORM_data8: {
215 applyIntVal(PatchOffset, Val, 8);
216 } break;
217 case dwarf::DW_FORM_udata: {
218 applyULEB128(PatchOffset, Val);
219 } break;
220 case dwarf::DW_FORM_sdata: {
221 applySLEB128(PatchOffset, Val);
222 } break;
223 case dwarf::DW_FORM_sec_offset: {
224 applyIntVal(PatchOffset, Val, Format.getDwarfOffsetByteSize());
225 } break;
226 case dwarf::DW_FORM_flag: {
227 applyIntVal(PatchOffset, Val, 1);
228 } break;
230 default:
231 llvm_unreachable("Unsupported attribute form");
232 break;
236 uint64_t SectionDescriptor::getIntVal(uint64_t PatchOffset, unsigned Size) {
237 assert(PatchOffset < getContents().size());
238 switch (Size) {
239 case 1: {
240 return *reinterpret_cast<const uint8_t *>(
241 (getContents().data() + PatchOffset));
243 case 2: {
244 return support::endian::read16(getContents().data() + PatchOffset,
245 Endianess);
247 case 4: {
248 return support::endian::read32(getContents().data() + PatchOffset,
249 Endianess);
251 case 8: {
252 return support::endian::read64(getContents().data() + PatchOffset,
253 Endianess);
256 llvm_unreachable("Unsupported integer type size");
257 return 0;
260 void SectionDescriptor::applyIntVal(uint64_t PatchOffset, uint64_t Val,
261 unsigned Size) {
262 assert(PatchOffset < getContents().size());
264 switch (Size) {
265 case 1: {
266 support::endian::write(
267 const_cast<char *>(getContents().data() + PatchOffset),
268 static_cast<uint8_t>(Val), Endianess);
269 } break;
270 case 2: {
271 support::endian::write(
272 const_cast<char *>(getContents().data() + PatchOffset),
273 static_cast<uint16_t>(Val), Endianess);
274 } break;
275 case 4: {
276 support::endian::write(
277 const_cast<char *>(getContents().data() + PatchOffset),
278 static_cast<uint32_t>(Val), Endianess);
279 } break;
280 case 8: {
281 support::endian::write(
282 const_cast<char *>(getContents().data() + PatchOffset),
283 static_cast<uint64_t>(Val), Endianess);
284 } break;
285 default:
286 llvm_unreachable("Unsupported integer type size");
290 void SectionDescriptor::applyULEB128(uint64_t PatchOffset, uint64_t Val) {
291 assert(PatchOffset < getContents().size());
293 uint8_t ULEB[16];
294 uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;
295 uint8_t RealSize = encodeULEB128(Val, ULEB, DestSize);
297 memcpy(const_cast<char *>(getContents().data() + PatchOffset), ULEB,
298 RealSize);
301 /// Writes integer value \p Val of SLEB128 format by specified \p PatchOffset.
302 void SectionDescriptor::applySLEB128(uint64_t PatchOffset, uint64_t Val) {
303 assert(PatchOffset < getContents().size());
305 uint8_t SLEB[16];
306 uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;
307 uint8_t RealSize = encodeSLEB128(Val, SLEB, DestSize);
309 memcpy(const_cast<char *>(getContents().data() + PatchOffset), SLEB,
310 RealSize);
313 void OutputSections::applyPatches(
314 SectionDescriptor &Section,
315 StringEntryToDwarfStringPoolEntryMap &DebugStrStrings,
316 StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings) {
318 Section.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
319 DwarfStringPoolEntryWithExtString *Entry =
320 DebugStrStrings.getExistingEntry(Patch.String);
321 assert(Entry != nullptr);
323 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_strp, Entry->Offset);
326 Section.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
327 DwarfStringPoolEntryWithExtString *Entry =
328 DebugLineStrStrings.getExistingEntry(Patch.String);
329 assert(Entry != nullptr);
331 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);
334 std::optional<SectionDescriptor *> RangeSection;
335 if (Format.Version >= 5)
336 RangeSection = getSectionDescriptor(DebugSectionKind::DebugRngLists);
337 else
338 RangeSection = getSectionDescriptor(DebugSectionKind::DebugRange);
340 if (RangeSection) {
341 Section.ListDebugRangePatch.forEach([&](DebugRangePatch &Patch) {
342 uint64_t FinalValue =
343 Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());
344 FinalValue += (*RangeSection)->StartOffset;
346 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);
350 std::optional<SectionDescriptor *> LocationSection;
351 if (Format.Version >= 5)
352 LocationSection = getSectionDescriptor(DebugSectionKind::DebugLocLists);
353 else
354 LocationSection = getSectionDescriptor(DebugSectionKind::DebugLoc);
356 if (LocationSection) {
357 Section.ListDebugLocPatch.forEach([&](DebugLocPatch &Patch) {
358 uint64_t FinalValue =
359 Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());
360 FinalValue += (*LocationSection)->StartOffset;
362 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);
366 Section.ListDebugDieRefPatch.forEach([&](DebugDieRefPatch &Patch) {
367 uint64_t FinalOffset = Patch.RefDieIdxOrClonedOffset;
368 dwarf::Form FinalForm = dwarf::DW_FORM_ref4;
370 if (!Patch.RefCU.getInt()) {
371 std::optional<SectionDescriptor *> ReferencedSectionDescriptor =
372 Patch.RefCU.getPointer()->getSectionDescriptor(
373 DebugSectionKind::DebugInfo);
374 if (!ReferencedSectionDescriptor) {
375 // Referenced section should be already created at this point.
376 llvm_unreachable("Referenced section does not exist");
379 FinalForm = dwarf::DW_FORM_ref_addr;
380 FinalOffset += (*ReferencedSectionDescriptor)->StartOffset;
383 Section.apply(Patch.PatchOffset, FinalForm, FinalOffset);
386 Section.ListDebugULEB128DieRefPatch.forEach(
387 [&](DebugULEB128DieRefPatch &Patch) {
388 assert(Patch.RefCU.getInt());
389 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_udata,
390 Patch.RefDieIdxOrClonedOffset);
393 Section.ListDebugOffsetPatch.forEach([&](DebugOffsetPatch &Patch) {
394 uint64_t FinalValue = Patch.SectionPtr.getPointer()->StartOffset;
395 if (Patch.SectionPtr.getInt())
396 FinalValue +=
397 Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());
399 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);
403 } // end of namespace dwarflinker_parallel
404 } // end of namespace llvm