[AArch64] Add cost model for @experimental.vector.match (#118512)
[llvm-project.git] / llvm / unittests / DebugInfo / DWARF / DwarfGenerator.cpp
blob2cbd4cc55df959c8d03caddbbad988270a609ca5
1 //===--- unittests/DebugInfo/DWARF/DwarfGenerator.cpp -----------*- 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 //===----------------------------------------------------------------------===//
9 #include "DwarfGenerator.h"
10 #include "../lib/CodeGen/AsmPrinter/DwarfStringPool.h"
11 #include "llvm/BinaryFormat/Dwarf.h"
12 #include "llvm/CodeGen/AsmPrinter.h"
13 #include "llvm/CodeGen/DIE.h"
14 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
15 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
16 #include "llvm/MC/MCAsmBackend.h"
17 #include "llvm/MC/MCAsmInfo.h"
18 #include "llvm/MC/MCCodeEmitter.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCDwarf.h"
21 #include "llvm/MC/MCInstrInfo.h"
22 #include "llvm/MC/MCObjectFileInfo.h"
23 #include "llvm/MC/MCObjectWriter.h"
24 #include "llvm/MC/MCRegisterInfo.h"
25 #include "llvm/MC/MCStreamer.h"
26 #include "llvm/MC/MCSubtargetInfo.h"
27 #include "llvm/MC/MCTargetOptionsCommandFlags.h"
28 #include "llvm/MC/TargetRegistry.h"
29 #include "llvm/Pass.h"
30 #include "llvm/Support/FileSystem.h"
31 #include "llvm/Support/LEB128.h"
32 #include "llvm/Support/raw_ostream.h"
33 #include "llvm/Target/TargetLoweringObjectFile.h"
34 #include "llvm/Target/TargetMachine.h"
35 #include "llvm/Target/TargetOptions.h"
36 #include "llvm/TargetParser/Triple.h"
38 using namespace llvm;
39 using namespace dwarf;
41 mc::RegisterMCTargetOptionsFlags MOF;
43 namespace {} // end anonymous namespace
45 //===----------------------------------------------------------------------===//
46 /// dwarfgen::DIE implementation.
47 //===----------------------------------------------------------------------===//
48 unsigned dwarfgen::DIE::computeSizeAndOffsets(unsigned Offset) {
49 auto &DG = CU->getGenerator();
50 return Die->computeOffsetsAndAbbrevs(DG.getAsmPrinter()->getDwarfFormParams(),
51 DG.getAbbrevSet(), Offset);
54 void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form, uint64_t U) {
55 auto &DG = CU->getGenerator();
56 switch (Form) {
57 case DW_FORM_addrx:
58 case DW_FORM_addrx1:
59 case DW_FORM_addrx2:
60 case DW_FORM_addrx3:
61 case DW_FORM_addrx4:
62 U = DG.getAddressPool().getIndex(U);
63 break;
64 default:
65 break;
67 Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
68 DIEInteger(U));
71 void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form, const MCExpr &Expr) {
72 auto &DG = CU->getGenerator();
73 Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
74 DIEExpr(&Expr));
77 void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form,
78 StringRef String) {
79 auto &DG = CU->getGenerator();
80 switch (Form) {
81 case DW_FORM_string:
82 Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
83 new (DG.getAllocator())
84 DIEInlineString(String, DG.getAllocator()));
85 break;
87 case DW_FORM_strp:
88 Die->addValue(
89 DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
90 DIEString(DG.getStringPool().getEntry(*DG.getAsmPrinter(), String)));
91 break;
93 case DW_FORM_GNU_str_index:
94 case DW_FORM_strx:
95 case DW_FORM_strx1:
96 case DW_FORM_strx2:
97 case DW_FORM_strx3:
98 case DW_FORM_strx4:
99 Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
100 DIEString(DG.getStringPool().getIndexedEntry(
101 *DG.getAsmPrinter(), String)));
102 break;
104 default:
105 llvm_unreachable("Unhandled form!");
109 void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form,
110 dwarfgen::DIE &RefDie) {
111 auto &DG = CU->getGenerator();
112 Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
113 DIEEntry(*RefDie.Die));
116 void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form, const void *P,
117 size_t S) {
118 auto &DG = CU->getGenerator();
119 DIEBlock *Block = new (DG.getAllocator()) DIEBlock;
120 for (size_t I = 0; I < S; ++I)
121 Block->addValue(
122 DG.getAllocator(), (dwarf::Attribute)0, dwarf::DW_FORM_data1,
123 DIEInteger(
124 (const_cast<uint8_t *>(static_cast<const uint8_t *>(P)))[I]));
126 Block->computeSize(DG.getAsmPrinter()->getDwarfFormParams());
127 Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
128 Block);
131 void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form) {
132 auto &DG = CU->getGenerator();
133 assert(Form == DW_FORM_flag_present);
134 Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
135 DIEInteger(1));
138 void dwarfgen::DIE::addStrOffsetsBaseAttribute() {
139 auto &DG = CU->getGenerator();
140 auto &MC = *DG.getMCContext();
141 AsmPrinter *Asm = DG.getAsmPrinter();
143 const MCSymbol *SectionStart =
144 Asm->getObjFileLowering().getDwarfStrOffSection()->getBeginSymbol();
146 const MCExpr *Expr =
147 MCSymbolRefExpr::create(DG.getStringOffsetsStartSym(), MC);
149 if (!Asm->MAI->doesDwarfUseRelocationsAcrossSections())
150 Expr = MCBinaryExpr::createSub(
151 Expr, MCSymbolRefExpr::create(SectionStart, MC), MC);
153 addAttribute(dwarf::DW_AT_str_offsets_base, DW_FORM_sec_offset, *Expr);
156 // This is currently fixed to be the first address entry after the header.
157 void dwarfgen::DIE::addAddrBaseAttribute() {
158 auto &DG = CU->getGenerator();
159 auto &MC = *DG.getMCContext();
160 AsmPrinter *Asm = DG.getAsmPrinter();
162 const MCSymbol *SectionStart =
163 Asm->getObjFileLowering().getDwarfAddrSection()->getBeginSymbol();
165 const MCExpr *Expr = MCSymbolRefExpr::create(DG.getAddrTableStartSym(), MC);
167 if (!Asm->MAI->doesDwarfUseRelocationsAcrossSections())
168 Expr = MCBinaryExpr::createSub(
169 Expr, MCSymbolRefExpr::create(SectionStart, MC), MC);
171 addAttribute(dwarf::DW_AT_addr_base, DW_FORM_sec_offset, *Expr);
174 dwarfgen::DIE dwarfgen::DIE::addChild(dwarf::Tag Tag) {
175 auto &DG = CU->getGenerator();
176 return dwarfgen::DIE(CU,
177 &Die->addChild(llvm::DIE::get(DG.getAllocator(), Tag)));
180 dwarfgen::DIE dwarfgen::CompileUnit::getUnitDIE() {
181 return dwarfgen::DIE(this, &DU.getUnitDie());
184 //===----------------------------------------------------------------------===//
185 /// dwarfgen::LineTable implementation.
186 //===----------------------------------------------------------------------===//
187 DWARFDebugLine::Prologue dwarfgen::LineTable::createBasicPrologue() const {
188 DWARFDebugLine::Prologue P;
189 switch (Version) {
190 case 2:
191 case 3:
192 P.TotalLength = 41;
193 P.PrologueLength = 35;
194 break;
195 case 4:
196 P.TotalLength = 42;
197 P.PrologueLength = 36;
198 break;
199 case 5:
200 P.TotalLength = 50;
201 P.PrologueLength = 42;
202 P.FormParams.AddrSize = AddrSize;
203 break;
204 default:
205 llvm_unreachable("unsupported version");
207 if (Format == DWARF64) {
208 P.TotalLength += 4;
209 P.FormParams.Format = DWARF64;
211 P.TotalLength += getContentsSize();
212 P.FormParams.Version = Version;
213 P.MinInstLength = 1;
214 P.MaxOpsPerInst = 1;
215 P.DefaultIsStmt = 1;
216 P.LineBase = -5;
217 P.LineRange = 14;
218 P.OpcodeBase = 13;
219 P.StandardOpcodeLengths = {0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1};
220 P.IncludeDirectories.push_back(
221 DWARFFormValue::createFromPValue(DW_FORM_string, "a dir"));
222 P.FileNames.push_back(DWARFDebugLine::FileNameEntry());
223 P.FileNames.back().Name =
224 DWARFFormValue::createFromPValue(DW_FORM_string, "a file");
225 return P;
228 void dwarfgen::LineTable::setPrologue(DWARFDebugLine::Prologue NewPrologue) {
229 Prologue = NewPrologue;
230 CustomPrologue.clear();
233 void dwarfgen::LineTable::setCustomPrologue(
234 ArrayRef<ValueAndLength> NewPrologue) {
235 Prologue.reset();
236 CustomPrologue = NewPrologue;
239 void dwarfgen::LineTable::addByte(uint8_t Value) {
240 Contents.push_back({Value, Byte});
243 void dwarfgen::LineTable::addStandardOpcode(uint8_t Opcode,
244 ArrayRef<ValueAndLength> Operands) {
245 Contents.push_back({Opcode, Byte});
246 Contents.insert(Contents.end(), Operands.begin(), Operands.end());
249 void dwarfgen::LineTable::addExtendedOpcode(uint64_t Length, uint8_t Opcode,
250 ArrayRef<ValueAndLength> Operands) {
251 Contents.push_back({0, Byte});
252 Contents.push_back({Length, ULEB});
253 Contents.push_back({Opcode, Byte});
254 Contents.insert(Contents.end(), Operands.begin(), Operands.end());
257 void dwarfgen::LineTable::generate(MCContext &MC, AsmPrinter &Asm) const {
258 MC.setDwarfVersion(Version);
260 MCSymbol *EndSymbol = nullptr;
261 if (!CustomPrologue.empty()) {
262 writeData(CustomPrologue, Asm);
263 } else if (!Prologue) {
264 EndSymbol = writeDefaultPrologue(Asm);
265 } else {
266 writePrologue(Asm);
269 writeData(Contents, Asm);
270 if (EndSymbol != nullptr)
271 Asm.OutStreamer->emitLabel(EndSymbol);
274 void dwarfgen::LineTable::writeData(ArrayRef<ValueAndLength> Data,
275 AsmPrinter &Asm) const {
276 for (auto Entry : Data) {
277 switch (Entry.Length) {
278 case Byte:
279 case Half:
280 case Long:
281 case Quad:
282 Asm.OutStreamer->emitIntValue(Entry.Value, Entry.Length);
283 continue;
284 case ULEB:
285 Asm.emitULEB128(Entry.Value);
286 continue;
287 case SLEB:
288 Asm.emitSLEB128(Entry.Value);
289 continue;
291 llvm_unreachable("unsupported ValueAndLength Length value");
295 size_t dwarfgen::LineTable::getContentsSize() const {
296 size_t Size = 0;
297 for (auto Entry : Contents) {
298 switch (Entry.Length) {
299 case ULEB:
300 Size += getULEB128Size(Entry.Value);
301 break;
302 case SLEB:
303 Size += getSLEB128Size(Entry.Value);
304 break;
305 default:
306 Size += Entry.Length;
307 break;
310 return Size;
313 MCSymbol *dwarfgen::LineTable::writeDefaultPrologue(AsmPrinter &Asm) const {
314 MCSymbol *UnitStart = Asm.createTempSymbol("line_unit_start");
315 MCSymbol *UnitEnd = Asm.createTempSymbol("line_unit_end");
316 if (Format == DwarfFormat::DWARF64) {
317 Asm.emitInt32((int)dwarf::DW_LENGTH_DWARF64);
318 Asm.emitLabelDifference(UnitEnd, UnitStart, 8);
319 } else {
320 Asm.emitLabelDifference(UnitEnd, UnitStart, 4);
322 Asm.OutStreamer->emitLabel(UnitStart);
323 Asm.emitInt16(Version);
324 if (Version == 5) {
325 Asm.emitInt8(AddrSize);
326 Asm.emitInt8(SegSize);
329 MCSymbol *PrologueStart = Asm.createTempSymbol("line_prologue_start");
330 MCSymbol *PrologueEnd = Asm.createTempSymbol("line_prologue_end");
331 Asm.emitLabelDifference(PrologueEnd, PrologueStart,
332 Format == DwarfFormat::DWARF64 ? 8 : 4);
333 Asm.OutStreamer->emitLabel(PrologueStart);
335 DWARFDebugLine::Prologue DefaultPrologue = createBasicPrologue();
336 writeProloguePayload(DefaultPrologue, Asm);
337 Asm.OutStreamer->emitLabel(PrologueEnd);
338 return UnitEnd;
341 void dwarfgen::LineTable::writePrologue(AsmPrinter &Asm) const {
342 if (Format == DwarfFormat::DWARF64) {
343 Asm.emitInt32((int)dwarf::DW_LENGTH_DWARF64);
344 Asm.emitInt64(Prologue->TotalLength);
345 } else {
346 Asm.emitInt32(Prologue->TotalLength);
348 Asm.emitInt16(Prologue->getVersion());
349 if (Version == 5) {
350 Asm.emitInt8(Prologue->getAddressSize());
351 Asm.emitInt8(Prologue->SegSelectorSize);
353 if (Format == DwarfFormat::DWARF64)
354 Asm.emitInt64(Prologue->PrologueLength);
355 else
356 Asm.emitInt32(Prologue->PrologueLength);
358 writeProloguePayload(*Prologue, Asm);
361 static void writeCString(StringRef Str, AsmPrinter &Asm) {
362 Asm.OutStreamer->emitBytes(Str);
363 Asm.emitInt8(0);
366 static void writeV2IncludeAndFileTable(const DWARFDebugLine::Prologue &Prologue,
367 AsmPrinter &Asm) {
368 for (auto Include : Prologue.IncludeDirectories)
369 writeCString(*toString(Include), Asm);
371 Asm.emitInt8(0);
373 for (auto File : Prologue.FileNames) {
374 writeCString(*toString(File.Name), Asm);
375 Asm.emitULEB128(File.DirIdx);
376 Asm.emitULEB128(File.ModTime);
377 Asm.emitULEB128(File.Length);
379 Asm.emitInt8(0);
382 static void writeV5IncludeAndFileTable(const DWARFDebugLine::Prologue &Prologue,
383 AsmPrinter &Asm) {
384 Asm.emitInt8(1); // directory_entry_format_count.
385 // TODO: Add support for other content descriptions - we currently only
386 // support a single DW_LNCT_path/DW_FORM_string.
387 Asm.emitULEB128(DW_LNCT_path);
388 Asm.emitULEB128(DW_FORM_string);
389 Asm.emitULEB128(Prologue.IncludeDirectories.size());
390 for (auto Include : Prologue.IncludeDirectories)
391 writeCString(*toString(Include), Asm);
393 Asm.emitInt8(2); // file_name_entry_format_count.
394 Asm.emitULEB128(DW_LNCT_path);
395 Asm.emitULEB128(DW_FORM_string);
396 Asm.emitULEB128(DW_LNCT_directory_index);
397 Asm.emitULEB128(DW_FORM_data1);
398 Asm.emitULEB128(Prologue.FileNames.size());
399 for (auto File : Prologue.FileNames) {
400 writeCString(*toString(File.Name), Asm);
401 Asm.emitInt8(File.DirIdx);
405 void dwarfgen::LineTable::writeProloguePayload(
406 const DWARFDebugLine::Prologue &Prologue, AsmPrinter &Asm) const {
407 Asm.emitInt8(Prologue.MinInstLength);
408 if (Version >= 4)
409 Asm.emitInt8(Prologue.MaxOpsPerInst);
410 Asm.emitInt8(Prologue.DefaultIsStmt);
411 Asm.emitInt8(Prologue.LineBase);
412 Asm.emitInt8(Prologue.LineRange);
413 Asm.emitInt8(Prologue.OpcodeBase);
414 for (auto Length : Prologue.StandardOpcodeLengths) {
415 Asm.emitInt8(Length);
418 if (Version < 5)
419 writeV2IncludeAndFileTable(Prologue, Asm);
420 else
421 writeV5IncludeAndFileTable(Prologue, Asm);
424 //===----------------------------------------------------------------------===//
425 /// dwarfgen::Generator implementation.
426 //===----------------------------------------------------------------------===//
428 dwarfgen::Generator::Generator()
429 : MAB(nullptr), MCE(nullptr), MS(nullptr), TLOF(nullptr),
430 StringPool(nullptr), Abbreviations(Allocator),
431 StringOffsetsStartSym(nullptr), Version(0) {}
432 dwarfgen::Generator::~Generator() = default;
434 llvm::Expected<std::unique_ptr<dwarfgen::Generator>>
435 dwarfgen::Generator::create(Triple TheTriple, uint16_t DwarfVersion) {
436 std::unique_ptr<dwarfgen::Generator> GenUP(new dwarfgen::Generator());
437 llvm::Error error = GenUP->init(TheTriple, DwarfVersion);
438 if (error)
439 return Expected<std::unique_ptr<dwarfgen::Generator>>(std::move(error));
440 return Expected<std::unique_ptr<dwarfgen::Generator>>(std::move(GenUP));
443 llvm::Error dwarfgen::Generator::init(Triple TheTriple, uint16_t V) {
444 Version = V;
445 std::string ErrorStr;
446 std::string TripleName;
448 // Get the target.
449 const Target *TheTarget =
450 TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
451 if (!TheTarget)
452 return make_error<StringError>(ErrorStr, inconvertibleErrorCode());
454 TripleName = TheTriple.getTriple();
456 // Create all the MC Objects.
457 MRI.reset(TheTarget->createMCRegInfo(TripleName));
458 if (!MRI)
459 return make_error<StringError>(Twine("no register info for target ") +
460 TripleName,
461 inconvertibleErrorCode());
463 MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
464 MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
465 if (!MAI)
466 return make_error<StringError>("no asm info for target " + TripleName,
467 inconvertibleErrorCode());
469 MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
470 if (!MSTI)
471 return make_error<StringError>("no subtarget info for target " + TripleName,
472 inconvertibleErrorCode());
474 MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);
475 if (!MAB)
476 return make_error<StringError>("no asm backend for target " + TripleName,
477 inconvertibleErrorCode());
479 MII.reset(TheTarget->createMCInstrInfo());
480 if (!MII)
481 return make_error<StringError>("no instr info info for target " +
482 TripleName,
483 inconvertibleErrorCode());
485 TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
486 std::nullopt));
487 if (!TM)
488 return make_error<StringError>("no target machine for target " + TripleName,
489 inconvertibleErrorCode());
491 MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get()));
492 TLOF = TM->getObjFileLowering();
493 TLOF->Initialize(*MC, *TM);
494 MC->setObjectFileInfo(TLOF);
496 MCE = TheTarget->createMCCodeEmitter(*MII, *MC);
497 if (!MCE)
498 return make_error<StringError>("no code emitter for target " + TripleName,
499 inconvertibleErrorCode());
501 Stream = std::make_unique<raw_svector_ostream>(FileBytes);
503 MS = TheTarget->createMCObjectStreamer(
504 TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),
505 MAB->createObjectWriter(*Stream), std::unique_ptr<MCCodeEmitter>(MCE),
506 *MSTI);
507 if (!MS)
508 return make_error<StringError>("no object streamer for target " +
509 TripleName,
510 inconvertibleErrorCode());
513 // Finally create the AsmPrinter we'll use to emit the DIEs.
514 Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
515 if (!Asm)
516 return make_error<StringError>("no asm printer for target " + TripleName,
517 inconvertibleErrorCode());
519 // Set the DWARF version correctly on all classes that we use.
520 MC->setDwarfVersion(Version);
521 Asm->setDwarfVersion(Version);
523 StringPool = std::make_unique<DwarfStringPool>(Allocator, *Asm, StringRef());
524 StringOffsetsStartSym = Asm->createTempSymbol("str_offsets_base");
526 AddrTableStartSym = Asm->createTempSymbol("addr_table_base");
528 return Error::success();
531 unsigned dwarfgen::Generator::DummyAddressPool::getIndex(uint64_t Address) {
532 AddressValues.push_back(Address);
533 return static_cast<unsigned>(AddressValues.size() - 1);
536 void dwarfgen::Generator::DummyAddressPool::emit(AsmPrinter &Asm,
537 MCSection *AddrSection,
538 MCSymbol *StartSym) {
539 const uint8_t AddrSize = Asm.getPointerSize();
541 // Switch to .debug_addr section
542 Asm.OutStreamer->switchSection(AddrSection);
544 if (Asm.getDwarfVersion() >= 5) {
545 // Emit header
546 Asm.emitDwarfUnitLength(AddrSize * AddressValues.size() + 4,
547 "Length of contribution");
548 Asm.emitInt16(Asm.getDwarfVersion());
549 Asm.emitInt8(AddrSize);
550 Asm.emitInt8(0);
553 if (StartSym)
554 Asm.OutStreamer->emitLabel(StartSym);
556 // Emit addresses
557 for (uint64_t Addr : AddressValues)
558 Asm.OutStreamer->emitIntValue(Addr, AddrSize);
561 StringRef dwarfgen::Generator::generate() {
562 // Offset from the first CU in the debug info section is 0 initially.
563 uint64_t SecOffset = 0;
565 // Iterate over each compile unit and set the size and offsets for each
566 // DIE within each compile unit. All offsets are CU relative.
567 for (auto &CU : CompileUnits) {
568 // Set the absolute .debug_info offset for this compile unit.
569 CU->setOffset(SecOffset);
570 // The DIEs contain compile unit relative offsets and the offset depends
571 // on the Dwarf version.
572 unsigned CUOffset = 4 + // Length
573 2 + // Version
574 4 + // Abbreviation offset
575 1; // Address size
576 if (Asm->getDwarfVersion() >= 5)
577 CUOffset += 1; // DW_UT_compile tag.
579 CUOffset = CU->getUnitDIE().computeSizeAndOffsets(CUOffset);
580 // Update our absolute .debug_info offset.
581 SecOffset += CUOffset;
582 unsigned CUOffsetUnitLength = 4;
583 CU->setLength(CUOffset - CUOffsetUnitLength);
585 Abbreviations.Emit(Asm.get(), TLOF->getDwarfAbbrevSection());
587 StringPool->emitStringOffsetsTableHeader(*Asm, TLOF->getDwarfStrOffSection(),
588 StringOffsetsStartSym);
589 StringPool->emit(*Asm, TLOF->getDwarfStrSection(),
590 TLOF->getDwarfStrOffSection());
592 if (Asm->getDwarfVersion() >= 5)
593 AddressPool.emit(*Asm, TLOF->getDwarfAddrSection(), AddrTableStartSym);
595 MS->switchSection(TLOF->getDwarfInfoSection());
596 for (auto &CU : CompileUnits) {
597 uint16_t Version = CU->getVersion();
598 auto Length = CU->getLength();
599 MC->setDwarfVersion(Version);
600 assert(Length != -1U);
601 Asm->emitInt32(Length);
602 Asm->emitInt16(Version);
603 if (Version <= 4) {
604 Asm->emitInt32(0);
605 Asm->emitInt8(CU->getAddressSize());
606 } else {
607 Asm->emitInt8(dwarf::DW_UT_compile);
608 Asm->emitInt8(CU->getAddressSize());
609 Asm->emitInt32(0);
611 Asm->emitDwarfDIE(*CU->getUnitDIE().Die);
614 MS->switchSection(TLOF->getDwarfLineSection());
615 for (auto &LT : LineTables)
616 LT->generate(*MC, *Asm);
618 MS->finish();
619 if (FileBytes.empty())
620 return StringRef();
621 return StringRef(FileBytes.data(), FileBytes.size());
624 bool dwarfgen::Generator::saveFile(StringRef Path) {
625 if (FileBytes.empty())
626 return false;
627 std::error_code EC;
628 raw_fd_ostream Strm(Path, EC, sys::fs::OF_None);
629 if (EC)
630 return false;
631 Strm.write(FileBytes.data(), FileBytes.size());
632 Strm.close();
633 return true;
636 dwarfgen::CompileUnit &dwarfgen::Generator::addCompileUnit() {
637 CompileUnits.push_back(
638 std::make_unique<CompileUnit>(*this, Version, Asm->getPointerSize()));
639 return *CompileUnits.back();
642 dwarfgen::LineTable &dwarfgen::Generator::addLineTable(DwarfFormat Format) {
643 LineTables.push_back(
644 std::make_unique<LineTable>(Version, Format, Asm->getPointerSize()));
645 return *LineTables.back();