xref: /openbsd/gnu/llvm/llvm/lib/MC/MCDwarf.cpp (revision d415bd75)
109467b48Spatrick //===- lib/MC/MCDwarf.cpp - MCDwarf implementation ------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick 
909467b48Spatrick #include "llvm/MC/MCDwarf.h"
1009467b48Spatrick #include "llvm/ADT/ArrayRef.h"
1109467b48Spatrick #include "llvm/ADT/DenseMap.h"
1209467b48Spatrick #include "llvm/ADT/Hashing.h"
1309467b48Spatrick #include "llvm/ADT/STLExtras.h"
1409467b48Spatrick #include "llvm/ADT/SmallString.h"
1509467b48Spatrick #include "llvm/ADT/SmallVector.h"
1609467b48Spatrick #include "llvm/ADT/StringRef.h"
1709467b48Spatrick #include "llvm/ADT/Twine.h"
1809467b48Spatrick #include "llvm/BinaryFormat/Dwarf.h"
1909467b48Spatrick #include "llvm/Config/config.h"
2009467b48Spatrick #include "llvm/MC/MCAsmInfo.h"
2109467b48Spatrick #include "llvm/MC/MCContext.h"
2209467b48Spatrick #include "llvm/MC/MCExpr.h"
2309467b48Spatrick #include "llvm/MC/MCObjectFileInfo.h"
2409467b48Spatrick #include "llvm/MC/MCObjectStreamer.h"
2509467b48Spatrick #include "llvm/MC/MCRegisterInfo.h"
2609467b48Spatrick #include "llvm/MC/MCSection.h"
2709467b48Spatrick #include "llvm/MC/MCStreamer.h"
2809467b48Spatrick #include "llvm/MC/MCSymbol.h"
2909467b48Spatrick #include "llvm/Support/Casting.h"
3009467b48Spatrick #include "llvm/Support/Endian.h"
3109467b48Spatrick #include "llvm/Support/EndianStream.h"
3209467b48Spatrick #include "llvm/Support/ErrorHandling.h"
3309467b48Spatrick #include "llvm/Support/LEB128.h"
3409467b48Spatrick #include "llvm/Support/MathExtras.h"
3509467b48Spatrick #include "llvm/Support/Path.h"
3609467b48Spatrick #include "llvm/Support/SourceMgr.h"
3709467b48Spatrick #include "llvm/Support/raw_ostream.h"
3809467b48Spatrick #include <cassert>
3909467b48Spatrick #include <cstdint>
40*d415bd75Srobert #include <optional>
4109467b48Spatrick #include <string>
4209467b48Spatrick #include <utility>
4309467b48Spatrick #include <vector>
4409467b48Spatrick 
4509467b48Spatrick using namespace llvm;
4609467b48Spatrick 
emitListsTableHeaderStart(MCStreamer & S)47097a140dSpatrick MCSymbol *mcdwarf::emitListsTableHeaderStart(MCStreamer &S) {
4873471bf0Spatrick   MCSymbol *Start = S.getContext().createTempSymbol("debug_list_header_start");
4973471bf0Spatrick   MCSymbol *End = S.getContext().createTempSymbol("debug_list_header_end");
50097a140dSpatrick   auto DwarfFormat = S.getContext().getDwarfFormat();
51097a140dSpatrick   if (DwarfFormat == dwarf::DWARF64) {
52097a140dSpatrick     S.AddComment("DWARF64 mark");
53097a140dSpatrick     S.emitInt32(dwarf::DW_LENGTH_DWARF64);
54097a140dSpatrick   }
55097a140dSpatrick   S.AddComment("Length");
56097a140dSpatrick   S.emitAbsoluteSymbolDiff(End, Start,
57097a140dSpatrick                            dwarf::getDwarfOffsetByteSize(DwarfFormat));
58097a140dSpatrick   S.emitLabel(Start);
59097a140dSpatrick   S.AddComment("Version");
60097a140dSpatrick   S.emitInt16(S.getContext().getDwarfVersion());
61097a140dSpatrick   S.AddComment("Address size");
62097a140dSpatrick   S.emitInt8(S.getContext().getAsmInfo()->getCodePointerSize());
63097a140dSpatrick   S.AddComment("Segment selector size");
64097a140dSpatrick   S.emitInt8(0);
65097a140dSpatrick   return End;
66097a140dSpatrick }
67097a140dSpatrick 
ScaleAddrDelta(MCContext & Context,uint64_t AddrDelta)6809467b48Spatrick static inline uint64_t ScaleAddrDelta(MCContext &Context, uint64_t AddrDelta) {
6909467b48Spatrick   unsigned MinInsnLength = Context.getAsmInfo()->getMinInstAlignment();
7009467b48Spatrick   if (MinInsnLength == 1)
7109467b48Spatrick     return AddrDelta;
7209467b48Spatrick   if (AddrDelta % MinInsnLength != 0) {
7309467b48Spatrick     // TODO: report this error, but really only once.
7409467b48Spatrick     ;
7509467b48Spatrick   }
7609467b48Spatrick   return AddrDelta / MinInsnLength;
7709467b48Spatrick }
7809467b48Spatrick 
MCDwarfLineStr(MCContext & Ctx)79*d415bd75Srobert MCDwarfLineStr::MCDwarfLineStr(MCContext &Ctx) {
80*d415bd75Srobert   UseRelocs = Ctx.getAsmInfo()->doesDwarfUseRelocationsAcrossSections();
81*d415bd75Srobert   if (UseRelocs)
82*d415bd75Srobert     LineStrLabel =
83*d415bd75Srobert         Ctx.getObjectFileInfo()->getDwarfLineStrSection()->getBeginSymbol();
84*d415bd75Srobert }
85*d415bd75Srobert 
8609467b48Spatrick //
8709467b48Spatrick // This is called when an instruction is assembled into the specified section
8809467b48Spatrick // and if there is information from the last .loc directive that has yet to have
8909467b48Spatrick // a line entry made for it is made.
9009467b48Spatrick //
make(MCStreamer * MCOS,MCSection * Section)9173471bf0Spatrick void MCDwarfLineEntry::make(MCStreamer *MCOS, MCSection *Section) {
9209467b48Spatrick   if (!MCOS->getContext().getDwarfLocSeen())
9309467b48Spatrick     return;
9409467b48Spatrick 
9509467b48Spatrick   // Create a symbol at in the current section for use in the line entry.
9609467b48Spatrick   MCSymbol *LineSym = MCOS->getContext().createTempSymbol();
9709467b48Spatrick   // Set the value of the symbol to use for the MCDwarfLineEntry.
98097a140dSpatrick   MCOS->emitLabel(LineSym);
9909467b48Spatrick 
10009467b48Spatrick   // Get the current .loc info saved in the context.
10109467b48Spatrick   const MCDwarfLoc &DwarfLoc = MCOS->getContext().getCurrentDwarfLoc();
10209467b48Spatrick 
10309467b48Spatrick   // Create a (local) line entry with the symbol and the current .loc info.
10409467b48Spatrick   MCDwarfLineEntry LineEntry(LineSym, DwarfLoc);
10509467b48Spatrick 
10609467b48Spatrick   // clear DwarfLocSeen saying the current .loc info is now used.
10709467b48Spatrick   MCOS->getContext().clearDwarfLocSeen();
10809467b48Spatrick 
10909467b48Spatrick   // Add the line entry to this section's entries.
11009467b48Spatrick   MCOS->getContext()
11109467b48Spatrick       .getMCDwarfLineTable(MCOS->getContext().getDwarfCompileUnitID())
11209467b48Spatrick       .getMCLineSections()
11309467b48Spatrick       .addLineEntry(LineEntry, Section);
11409467b48Spatrick }
11509467b48Spatrick 
11609467b48Spatrick //
117*d415bd75Srobert // This helper routine returns an expression of End - Start - IntVal .
11809467b48Spatrick //
makeEndMinusStartExpr(MCContext & Ctx,const MCSymbol & Start,const MCSymbol & End,int IntVal)119097a140dSpatrick static inline const MCExpr *makeEndMinusStartExpr(MCContext &Ctx,
12009467b48Spatrick                                                   const MCSymbol &Start,
12109467b48Spatrick                                                   const MCSymbol &End,
12209467b48Spatrick                                                   int IntVal) {
12309467b48Spatrick   MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
124097a140dSpatrick   const MCExpr *Res = MCSymbolRefExpr::create(&End, Variant, Ctx);
125097a140dSpatrick   const MCExpr *RHS = MCSymbolRefExpr::create(&Start, Variant, Ctx);
126097a140dSpatrick   const MCExpr *Res1 = MCBinaryExpr::create(MCBinaryExpr::Sub, Res, RHS, Ctx);
127097a140dSpatrick   const MCExpr *Res2 = MCConstantExpr::create(IntVal, Ctx);
128097a140dSpatrick   const MCExpr *Res3 = MCBinaryExpr::create(MCBinaryExpr::Sub, Res1, Res2, Ctx);
12909467b48Spatrick   return Res3;
13009467b48Spatrick }
13109467b48Spatrick 
13209467b48Spatrick //
13309467b48Spatrick // This helper routine returns an expression of Start + IntVal .
13409467b48Spatrick //
13509467b48Spatrick static inline const MCExpr *
makeStartPlusIntExpr(MCContext & Ctx,const MCSymbol & Start,int IntVal)13609467b48Spatrick makeStartPlusIntExpr(MCContext &Ctx, const MCSymbol &Start, int IntVal) {
13709467b48Spatrick   MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
13809467b48Spatrick   const MCExpr *LHS = MCSymbolRefExpr::create(&Start, Variant, Ctx);
13909467b48Spatrick   const MCExpr *RHS = MCConstantExpr::create(IntVal, Ctx);
14009467b48Spatrick   const MCExpr *Res = MCBinaryExpr::create(MCBinaryExpr::Add, LHS, RHS, Ctx);
14109467b48Spatrick   return Res;
14209467b48Spatrick }
14309467b48Spatrick 
addEndEntry(MCSymbol * EndLabel)144*d415bd75Srobert void MCLineSection::addEndEntry(MCSymbol *EndLabel) {
145*d415bd75Srobert   auto *Sec = &EndLabel->getSection();
146*d415bd75Srobert   // The line table may be empty, which we should skip adding an end entry.
147*d415bd75Srobert   // There are two cases:
148*d415bd75Srobert   // (1) MCAsmStreamer - emitDwarfLocDirective emits a location directive in
149*d415bd75Srobert   //     place instead of adding a line entry if the target has
150*d415bd75Srobert   //     usesDwarfFileAndLocDirectives.
151*d415bd75Srobert   // (2) MCObjectStreamer - if a function has incomplete debug info where
152*d415bd75Srobert   //     instructions don't have DILocations, the line entries are missing.
153*d415bd75Srobert   auto I = MCLineDivisions.find(Sec);
154*d415bd75Srobert   if (I != MCLineDivisions.end()) {
155*d415bd75Srobert     auto &Entries = I->second;
156*d415bd75Srobert     auto EndEntry = Entries.back();
157*d415bd75Srobert     EndEntry.setEndLabel(EndLabel);
158*d415bd75Srobert     Entries.push_back(EndEntry);
159*d415bd75Srobert   }
160*d415bd75Srobert }
161*d415bd75Srobert 
16209467b48Spatrick //
16309467b48Spatrick // This emits the Dwarf line table for the specified section from the entries
16409467b48Spatrick // in the LineSection.
16509467b48Spatrick //
emitOne(MCStreamer * MCOS,MCSection * Section,const MCLineSection::MCDwarfLineEntryCollection & LineEntries)166*d415bd75Srobert void MCDwarfLineTable::emitOne(
16773471bf0Spatrick     MCStreamer *MCOS, MCSection *Section,
16809467b48Spatrick     const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
169*d415bd75Srobert 
170*d415bd75Srobert   unsigned FileNum, LastLine, Column, Flags, Isa, Discriminator;
171*d415bd75Srobert   MCSymbol *LastLabel;
172*d415bd75Srobert   auto init = [&]() {
173*d415bd75Srobert     FileNum = 1;
174*d415bd75Srobert     LastLine = 1;
175*d415bd75Srobert     Column = 0;
176*d415bd75Srobert     Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
177*d415bd75Srobert     Isa = 0;
178*d415bd75Srobert     Discriminator = 0;
179*d415bd75Srobert     LastLabel = nullptr;
180*d415bd75Srobert   };
181*d415bd75Srobert   init();
18209467b48Spatrick 
18309467b48Spatrick   // Loop through each MCDwarfLineEntry and encode the dwarf line number table.
184*d415bd75Srobert   bool EndEntryEmitted = false;
18509467b48Spatrick   for (const MCDwarfLineEntry &LineEntry : LineEntries) {
186*d415bd75Srobert     MCSymbol *Label = LineEntry.getLabel();
187*d415bd75Srobert     const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo();
188*d415bd75Srobert     if (LineEntry.IsEndEntry) {
189*d415bd75Srobert       MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, Label,
190*d415bd75Srobert                                      asmInfo->getCodePointerSize());
191*d415bd75Srobert       init();
192*d415bd75Srobert       EndEntryEmitted = true;
193*d415bd75Srobert       continue;
194*d415bd75Srobert     }
195*d415bd75Srobert 
19609467b48Spatrick     int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;
19709467b48Spatrick 
19809467b48Spatrick     if (FileNum != LineEntry.getFileNum()) {
19909467b48Spatrick       FileNum = LineEntry.getFileNum();
200097a140dSpatrick       MCOS->emitInt8(dwarf::DW_LNS_set_file);
201097a140dSpatrick       MCOS->emitULEB128IntValue(FileNum);
20209467b48Spatrick     }
20309467b48Spatrick     if (Column != LineEntry.getColumn()) {
20409467b48Spatrick       Column = LineEntry.getColumn();
205097a140dSpatrick       MCOS->emitInt8(dwarf::DW_LNS_set_column);
206097a140dSpatrick       MCOS->emitULEB128IntValue(Column);
20709467b48Spatrick     }
20809467b48Spatrick     if (Discriminator != LineEntry.getDiscriminator() &&
20909467b48Spatrick         MCOS->getContext().getDwarfVersion() >= 4) {
21009467b48Spatrick       Discriminator = LineEntry.getDiscriminator();
21109467b48Spatrick       unsigned Size = getULEB128Size(Discriminator);
212097a140dSpatrick       MCOS->emitInt8(dwarf::DW_LNS_extended_op);
213097a140dSpatrick       MCOS->emitULEB128IntValue(Size + 1);
214097a140dSpatrick       MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
215097a140dSpatrick       MCOS->emitULEB128IntValue(Discriminator);
21609467b48Spatrick     }
21709467b48Spatrick     if (Isa != LineEntry.getIsa()) {
21809467b48Spatrick       Isa = LineEntry.getIsa();
219097a140dSpatrick       MCOS->emitInt8(dwarf::DW_LNS_set_isa);
220097a140dSpatrick       MCOS->emitULEB128IntValue(Isa);
22109467b48Spatrick     }
22209467b48Spatrick     if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
22309467b48Spatrick       Flags = LineEntry.getFlags();
224097a140dSpatrick       MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
22509467b48Spatrick     }
22609467b48Spatrick     if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)
227097a140dSpatrick       MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
22809467b48Spatrick     if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)
229097a140dSpatrick       MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
23009467b48Spatrick     if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
231097a140dSpatrick       MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
23209467b48Spatrick 
23309467b48Spatrick     // At this point we want to emit/create the sequence to encode the delta in
23409467b48Spatrick     // line numbers and the increment of the address from the previous Label
23509467b48Spatrick     // and the current Label.
236097a140dSpatrick     MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
23709467b48Spatrick                                    asmInfo->getCodePointerSize());
23809467b48Spatrick 
23909467b48Spatrick     Discriminator = 0;
24009467b48Spatrick     LastLine = LineEntry.getLine();
24109467b48Spatrick     LastLabel = Label;
24209467b48Spatrick   }
24309467b48Spatrick 
24473471bf0Spatrick   // Generate DWARF line end entry.
245*d415bd75Srobert   // We do not need this for DwarfDebug that explicitly terminates the line
246*d415bd75Srobert   // table using ranges whenever CU or section changes. However, the MC path
247*d415bd75Srobert   // does not track ranges nor terminate the line table. In that case,
248*d415bd75Srobert   // conservatively use the section end symbol to end the line table.
249*d415bd75Srobert   if (!EndEntryEmitted)
25073471bf0Spatrick     MCOS->emitDwarfLineEndEntry(Section, LastLabel);
25109467b48Spatrick }
25209467b48Spatrick 
25309467b48Spatrick //
25409467b48Spatrick // This emits the Dwarf file and the line tables.
25509467b48Spatrick //
emit(MCStreamer * MCOS,MCDwarfLineTableParams Params)25673471bf0Spatrick void MCDwarfLineTable::emit(MCStreamer *MCOS, MCDwarfLineTableParams Params) {
25709467b48Spatrick   MCContext &context = MCOS->getContext();
25809467b48Spatrick 
25909467b48Spatrick   auto &LineTables = context.getMCDwarfLineTables();
26009467b48Spatrick 
26109467b48Spatrick   // Bail out early so we don't switch to the debug_line section needlessly and
26209467b48Spatrick   // in doing so create an unnecessary (if empty) section.
26309467b48Spatrick   if (LineTables.empty())
26409467b48Spatrick     return;
26509467b48Spatrick 
26609467b48Spatrick   // In a v5 non-split line table, put the strings in a separate section.
267*d415bd75Srobert   std::optional<MCDwarfLineStr> LineStr;
26809467b48Spatrick   if (context.getDwarfVersion() >= 5)
269*d415bd75Srobert     LineStr.emplace(context);
27009467b48Spatrick 
27109467b48Spatrick   // Switch to the section where the table will be emitted into.
272*d415bd75Srobert   MCOS->switchSection(context.getObjectFileInfo()->getDwarfLineSection());
27309467b48Spatrick 
27409467b48Spatrick   // Handle the rest of the Compile Units.
27509467b48Spatrick   for (const auto &CUIDTablePair : LineTables) {
27673471bf0Spatrick     CUIDTablePair.second.emitCU(MCOS, Params, LineStr);
27709467b48Spatrick   }
27809467b48Spatrick 
27909467b48Spatrick   if (LineStr)
28009467b48Spatrick     LineStr->emitSection(MCOS);
28109467b48Spatrick }
28209467b48Spatrick 
Emit(MCStreamer & MCOS,MCDwarfLineTableParams Params,MCSection * Section) const28309467b48Spatrick void MCDwarfDwoLineTable::Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params,
28409467b48Spatrick                                MCSection *Section) const {
28509467b48Spatrick   if (!HasSplitLineTable)
28609467b48Spatrick     return;
287*d415bd75Srobert   std::optional<MCDwarfLineStr> NoLineStr(std::nullopt);
288*d415bd75Srobert   MCOS.switchSection(Section);
289*d415bd75Srobert   MCOS.emitLabel(Header.Emit(&MCOS, Params, std::nullopt, NoLineStr).second);
29009467b48Spatrick }
29109467b48Spatrick 
29209467b48Spatrick std::pair<MCSymbol *, MCSymbol *>
Emit(MCStreamer * MCOS,MCDwarfLineTableParams Params,std::optional<MCDwarfLineStr> & LineStr) const29309467b48Spatrick MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
294*d415bd75Srobert                              std::optional<MCDwarfLineStr> &LineStr) const {
29509467b48Spatrick   static const char StandardOpcodeLengths[] = {
29609467b48Spatrick       0, // length of DW_LNS_copy
29709467b48Spatrick       1, // length of DW_LNS_advance_pc
29809467b48Spatrick       1, // length of DW_LNS_advance_line
29909467b48Spatrick       1, // length of DW_LNS_set_file
30009467b48Spatrick       1, // length of DW_LNS_set_column
30109467b48Spatrick       0, // length of DW_LNS_negate_stmt
30209467b48Spatrick       0, // length of DW_LNS_set_basic_block
30309467b48Spatrick       0, // length of DW_LNS_const_add_pc
30409467b48Spatrick       1, // length of DW_LNS_fixed_advance_pc
30509467b48Spatrick       0, // length of DW_LNS_set_prologue_end
30609467b48Spatrick       0, // length of DW_LNS_set_epilogue_begin
30709467b48Spatrick       1  // DW_LNS_set_isa
30809467b48Spatrick   };
309*d415bd75Srobert   assert(std::size(StandardOpcodeLengths) >=
31009467b48Spatrick          (Params.DWARF2LineOpcodeBase - 1U));
311*d415bd75Srobert   return Emit(MCOS, Params,
312*d415bd75Srobert               ArrayRef(StandardOpcodeLengths, Params.DWARF2LineOpcodeBase - 1),
31309467b48Spatrick               LineStr);
31409467b48Spatrick }
31509467b48Spatrick 
forceExpAbs(MCStreamer & OS,const MCExpr * Expr)31609467b48Spatrick static const MCExpr *forceExpAbs(MCStreamer &OS, const MCExpr* Expr) {
31709467b48Spatrick   MCContext &Context = OS.getContext();
31809467b48Spatrick   assert(!isa<MCSymbolRefExpr>(Expr));
31909467b48Spatrick   if (Context.getAsmInfo()->hasAggressiveSymbolFolding())
32009467b48Spatrick     return Expr;
32109467b48Spatrick 
32209467b48Spatrick   MCSymbol *ABS = Context.createTempSymbol();
323097a140dSpatrick   OS.emitAssignment(ABS, Expr);
32409467b48Spatrick   return MCSymbolRefExpr::create(ABS, Context);
32509467b48Spatrick }
32609467b48Spatrick 
emitAbsValue(MCStreamer & OS,const MCExpr * Value,unsigned Size)32709467b48Spatrick static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size) {
32809467b48Spatrick   const MCExpr *ABS = forceExpAbs(OS, Value);
329097a140dSpatrick   OS.emitValue(ABS, Size);
33009467b48Spatrick }
33109467b48Spatrick 
emitSection(MCStreamer * MCOS)33209467b48Spatrick void MCDwarfLineStr::emitSection(MCStreamer *MCOS) {
33309467b48Spatrick   // Switch to the .debug_line_str section.
334*d415bd75Srobert   MCOS->switchSection(
33509467b48Spatrick       MCOS->getContext().getObjectFileInfo()->getDwarfLineStrSection());
336*d415bd75Srobert   SmallString<0> Data = getFinalizedData();
337*d415bd75Srobert   MCOS->emitBinaryData(Data.str());
338*d415bd75Srobert }
339*d415bd75Srobert 
getFinalizedData()340*d415bd75Srobert SmallString<0> MCDwarfLineStr::getFinalizedData() {
34109467b48Spatrick   // Emit the strings without perturbing the offsets we used.
342*d415bd75Srobert   if (!LineStrings.isFinalized())
34309467b48Spatrick     LineStrings.finalizeInOrder();
34409467b48Spatrick   SmallString<0> Data;
34509467b48Spatrick   Data.resize(LineStrings.getSize());
34609467b48Spatrick   LineStrings.write((uint8_t *)Data.data());
347*d415bd75Srobert   return Data;
34809467b48Spatrick }
34909467b48Spatrick 
emitRef(MCStreamer * MCOS,StringRef Path)35009467b48Spatrick void MCDwarfLineStr::emitRef(MCStreamer *MCOS, StringRef Path) {
351097a140dSpatrick   int RefSize =
352097a140dSpatrick       dwarf::getDwarfOffsetByteSize(MCOS->getContext().getDwarfFormat());
35309467b48Spatrick   size_t Offset = LineStrings.add(Path);
35409467b48Spatrick   if (UseRelocs) {
35509467b48Spatrick     MCContext &Ctx = MCOS->getContext();
356097a140dSpatrick     MCOS->emitValue(makeStartPlusIntExpr(Ctx, *LineStrLabel, Offset), RefSize);
35709467b48Spatrick   } else
358097a140dSpatrick     MCOS->emitIntValue(Offset, RefSize);
35909467b48Spatrick }
36009467b48Spatrick 
emitV2FileDirTables(MCStreamer * MCOS) const36109467b48Spatrick void MCDwarfLineTableHeader::emitV2FileDirTables(MCStreamer *MCOS) const {
36209467b48Spatrick   // First the directory table.
36309467b48Spatrick   for (auto &Dir : MCDwarfDirs) {
364097a140dSpatrick     MCOS->emitBytes(Dir);                // The DirectoryName, and...
365097a140dSpatrick     MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
36609467b48Spatrick   }
367097a140dSpatrick   MCOS->emitInt8(0); // Terminate the directory list.
36809467b48Spatrick 
36909467b48Spatrick   // Second the file table.
37009467b48Spatrick   for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
37109467b48Spatrick     assert(!MCDwarfFiles[i].Name.empty());
372097a140dSpatrick     MCOS->emitBytes(MCDwarfFiles[i].Name); // FileName and...
373097a140dSpatrick     MCOS->emitBytes(StringRef("\0", 1));   // its null terminator.
374097a140dSpatrick     MCOS->emitULEB128IntValue(MCDwarfFiles[i].DirIndex); // Directory number.
375097a140dSpatrick     MCOS->emitInt8(0); // Last modification timestamp (always 0).
376097a140dSpatrick     MCOS->emitInt8(0); // File size (always 0).
37709467b48Spatrick   }
378097a140dSpatrick   MCOS->emitInt8(0); // Terminate the file list.
37909467b48Spatrick }
38009467b48Spatrick 
emitOneV5FileEntry(MCStreamer * MCOS,const MCDwarfFile & DwarfFile,bool EmitMD5,bool HasSource,std::optional<MCDwarfLineStr> & LineStr)38109467b48Spatrick static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile,
38209467b48Spatrick                                bool EmitMD5, bool HasSource,
383*d415bd75Srobert                                std::optional<MCDwarfLineStr> &LineStr) {
38409467b48Spatrick   assert(!DwarfFile.Name.empty());
38509467b48Spatrick   if (LineStr)
38609467b48Spatrick     LineStr->emitRef(MCOS, DwarfFile.Name);
38709467b48Spatrick   else {
388097a140dSpatrick     MCOS->emitBytes(DwarfFile.Name);     // FileName and...
389097a140dSpatrick     MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
39009467b48Spatrick   }
391097a140dSpatrick   MCOS->emitULEB128IntValue(DwarfFile.DirIndex); // Directory number.
39209467b48Spatrick   if (EmitMD5) {
39309467b48Spatrick     const MD5::MD5Result &Cksum = *DwarfFile.Checksum;
394097a140dSpatrick     MCOS->emitBinaryData(
395*d415bd75Srobert         StringRef(reinterpret_cast<const char *>(Cksum.data()), Cksum.size()));
39609467b48Spatrick   }
39709467b48Spatrick   if (HasSource) {
39809467b48Spatrick     if (LineStr)
399*d415bd75Srobert       LineStr->emitRef(MCOS, DwarfFile.Source.value_or(StringRef()));
40009467b48Spatrick     else {
401*d415bd75Srobert       MCOS->emitBytes(DwarfFile.Source.value_or(StringRef())); // Source and...
402097a140dSpatrick       MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
40309467b48Spatrick     }
40409467b48Spatrick   }
40509467b48Spatrick }
40609467b48Spatrick 
emitV5FileDirTables(MCStreamer * MCOS,std::optional<MCDwarfLineStr> & LineStr) const40709467b48Spatrick void MCDwarfLineTableHeader::emitV5FileDirTables(
408*d415bd75Srobert     MCStreamer *MCOS, std::optional<MCDwarfLineStr> &LineStr) const {
40909467b48Spatrick   // The directory format, which is just a list of the directory paths.  In a
41009467b48Spatrick   // non-split object, these are references to .debug_line_str; in a split
41109467b48Spatrick   // object, they are inline strings.
412097a140dSpatrick   MCOS->emitInt8(1);
413097a140dSpatrick   MCOS->emitULEB128IntValue(dwarf::DW_LNCT_path);
414097a140dSpatrick   MCOS->emitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
41509467b48Spatrick                                     : dwarf::DW_FORM_string);
416097a140dSpatrick   MCOS->emitULEB128IntValue(MCDwarfDirs.size() + 1);
41709467b48Spatrick   // Try not to emit an empty compilation directory.
418*d415bd75Srobert   SmallString<256> Dir;
419*d415bd75Srobert   StringRef CompDir = MCOS->getContext().getCompilationDir();
420*d415bd75Srobert   if (!CompilationDir.empty()) {
421*d415bd75Srobert     Dir = CompilationDir;
422*d415bd75Srobert     MCOS->getContext().remapDebugPath(Dir);
423*d415bd75Srobert     CompDir = Dir.str();
424*d415bd75Srobert     if (LineStr)
425*d415bd75Srobert       CompDir = LineStr->getSaver().save(CompDir);
426*d415bd75Srobert   }
42709467b48Spatrick   if (LineStr) {
42809467b48Spatrick     // Record path strings, emit references here.
42909467b48Spatrick     LineStr->emitRef(MCOS, CompDir);
43009467b48Spatrick     for (const auto &Dir : MCDwarfDirs)
43109467b48Spatrick       LineStr->emitRef(MCOS, Dir);
43209467b48Spatrick   } else {
43309467b48Spatrick     // The list of directory paths.  Compilation directory comes first.
434097a140dSpatrick     MCOS->emitBytes(CompDir);
435097a140dSpatrick     MCOS->emitBytes(StringRef("\0", 1));
43609467b48Spatrick     for (const auto &Dir : MCDwarfDirs) {
437097a140dSpatrick       MCOS->emitBytes(Dir);                // The DirectoryName, and...
438097a140dSpatrick       MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
43909467b48Spatrick     }
44009467b48Spatrick   }
44109467b48Spatrick 
44209467b48Spatrick   // The file format, which is the inline null-terminated filename and a
44309467b48Spatrick   // directory index.  We don't track file size/timestamp so don't emit them
44409467b48Spatrick   // in the v5 table.  Emit MD5 checksums and source if we have them.
44509467b48Spatrick   uint64_t Entries = 2;
44609467b48Spatrick   if (HasAllMD5)
44709467b48Spatrick     Entries += 1;
44809467b48Spatrick   if (HasSource)
44909467b48Spatrick     Entries += 1;
450097a140dSpatrick   MCOS->emitInt8(Entries);
451097a140dSpatrick   MCOS->emitULEB128IntValue(dwarf::DW_LNCT_path);
452097a140dSpatrick   MCOS->emitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
45309467b48Spatrick                                     : dwarf::DW_FORM_string);
454097a140dSpatrick   MCOS->emitULEB128IntValue(dwarf::DW_LNCT_directory_index);
455097a140dSpatrick   MCOS->emitULEB128IntValue(dwarf::DW_FORM_udata);
45609467b48Spatrick   if (HasAllMD5) {
457097a140dSpatrick     MCOS->emitULEB128IntValue(dwarf::DW_LNCT_MD5);
458097a140dSpatrick     MCOS->emitULEB128IntValue(dwarf::DW_FORM_data16);
45909467b48Spatrick   }
46009467b48Spatrick   if (HasSource) {
461097a140dSpatrick     MCOS->emitULEB128IntValue(dwarf::DW_LNCT_LLVM_source);
462097a140dSpatrick     MCOS->emitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
46309467b48Spatrick                                       : dwarf::DW_FORM_string);
46409467b48Spatrick   }
46509467b48Spatrick   // Then the counted list of files. The root file is file #0, then emit the
46609467b48Spatrick   // files as provide by .file directives.
46709467b48Spatrick   // MCDwarfFiles has an unused element [0] so use size() not size()+1.
46809467b48Spatrick   // But sometimes MCDwarfFiles is empty, in which case we still emit one file.
469097a140dSpatrick   MCOS->emitULEB128IntValue(MCDwarfFiles.empty() ? 1 : MCDwarfFiles.size());
47009467b48Spatrick   // To accommodate assembler source written for DWARF v4 but trying to emit
47109467b48Spatrick   // v5: If we didn't see a root file explicitly, replicate file #1.
47209467b48Spatrick   assert((!RootFile.Name.empty() || MCDwarfFiles.size() >= 1) &&
47309467b48Spatrick          "No root file and no .file directives");
47409467b48Spatrick   emitOneV5FileEntry(MCOS, RootFile.Name.empty() ? MCDwarfFiles[1] : RootFile,
47509467b48Spatrick                      HasAllMD5, HasSource, LineStr);
47609467b48Spatrick   for (unsigned i = 1; i < MCDwarfFiles.size(); ++i)
47709467b48Spatrick     emitOneV5FileEntry(MCOS, MCDwarfFiles[i], HasAllMD5, HasSource, LineStr);
47809467b48Spatrick }
47909467b48Spatrick 
48009467b48Spatrick std::pair<MCSymbol *, MCSymbol *>
Emit(MCStreamer * MCOS,MCDwarfLineTableParams Params,ArrayRef<char> StandardOpcodeLengths,std::optional<MCDwarfLineStr> & LineStr) const48109467b48Spatrick MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
48209467b48Spatrick                              ArrayRef<char> StandardOpcodeLengths,
483*d415bd75Srobert                              std::optional<MCDwarfLineStr> &LineStr) const {
48409467b48Spatrick   MCContext &context = MCOS->getContext();
48509467b48Spatrick 
48609467b48Spatrick   // Create a symbol at the beginning of the line table.
48709467b48Spatrick   MCSymbol *LineStartSym = Label;
48809467b48Spatrick   if (!LineStartSym)
48909467b48Spatrick     LineStartSym = context.createTempSymbol();
49073471bf0Spatrick 
49109467b48Spatrick   // Set the value of the symbol, as we are at the start of the line table.
49273471bf0Spatrick   MCOS->emitDwarfLineStartLabel(LineStartSym);
49309467b48Spatrick 
494097a140dSpatrick   unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(context.getDwarfFormat());
495097a140dSpatrick 
49673471bf0Spatrick   MCSymbol *LineEndSym = MCOS->emitDwarfUnitLength("debug_line", "unit length");
49709467b48Spatrick 
49809467b48Spatrick   // Next 2 bytes is the Version.
49909467b48Spatrick   unsigned LineTableVersion = context.getDwarfVersion();
500097a140dSpatrick   MCOS->emitInt16(LineTableVersion);
50109467b48Spatrick 
50209467b48Spatrick   // In v5, we get address info next.
50309467b48Spatrick   if (LineTableVersion >= 5) {
504097a140dSpatrick     MCOS->emitInt8(context.getAsmInfo()->getCodePointerSize());
505097a140dSpatrick     MCOS->emitInt8(0); // Segment selector; same as EmitGenDwarfAranges.
50609467b48Spatrick   }
50709467b48Spatrick 
50873471bf0Spatrick   // Create symbols for the start/end of the prologue.
50973471bf0Spatrick   MCSymbol *ProStartSym = context.createTempSymbol("prologue_start");
51073471bf0Spatrick   MCSymbol *ProEndSym = context.createTempSymbol("prologue_end");
51109467b48Spatrick 
512097a140dSpatrick   // Length of the prologue, is the next 4 bytes (8 bytes for DWARF64). This is
513097a140dSpatrick   // actually the length from after the length word, to the end of the prologue.
51473471bf0Spatrick   MCOS->emitAbsoluteSymbolDiff(ProEndSym, ProStartSym, OffsetSize);
51573471bf0Spatrick 
51673471bf0Spatrick   MCOS->emitLabel(ProStartSym);
51709467b48Spatrick 
51809467b48Spatrick   // Parameters of the state machine, are next.
519097a140dSpatrick   MCOS->emitInt8(context.getAsmInfo()->getMinInstAlignment());
52009467b48Spatrick   // maximum_operations_per_instruction
52109467b48Spatrick   // For non-VLIW architectures this field is always 1.
52209467b48Spatrick   // FIXME: VLIW architectures need to update this field accordingly.
52309467b48Spatrick   if (LineTableVersion >= 4)
524097a140dSpatrick     MCOS->emitInt8(1);
525097a140dSpatrick   MCOS->emitInt8(DWARF2_LINE_DEFAULT_IS_STMT);
526097a140dSpatrick   MCOS->emitInt8(Params.DWARF2LineBase);
527097a140dSpatrick   MCOS->emitInt8(Params.DWARF2LineRange);
528097a140dSpatrick   MCOS->emitInt8(StandardOpcodeLengths.size() + 1);
52909467b48Spatrick 
53009467b48Spatrick   // Standard opcode lengths
53109467b48Spatrick   for (char Length : StandardOpcodeLengths)
532097a140dSpatrick     MCOS->emitInt8(Length);
53309467b48Spatrick 
53409467b48Spatrick   // Put out the directory and file tables.  The formats vary depending on
53509467b48Spatrick   // the version.
53609467b48Spatrick   if (LineTableVersion >= 5)
53709467b48Spatrick     emitV5FileDirTables(MCOS, LineStr);
53809467b48Spatrick   else
53909467b48Spatrick     emitV2FileDirTables(MCOS);
54009467b48Spatrick 
54109467b48Spatrick   // This is the end of the prologue, so set the value of the symbol at the
54209467b48Spatrick   // end of the prologue (that was used in a previous expression).
543097a140dSpatrick   MCOS->emitLabel(ProEndSym);
54409467b48Spatrick 
54509467b48Spatrick   return std::make_pair(LineStartSym, LineEndSym);
54609467b48Spatrick }
54709467b48Spatrick 
emitCU(MCStreamer * MCOS,MCDwarfLineTableParams Params,std::optional<MCDwarfLineStr> & LineStr) const54873471bf0Spatrick void MCDwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
549*d415bd75Srobert                               std::optional<MCDwarfLineStr> &LineStr) const {
55009467b48Spatrick   MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;
55109467b48Spatrick 
55209467b48Spatrick   // Put out the line tables.
55309467b48Spatrick   for (const auto &LineSec : MCLineSections.getMCLineEntries())
554*d415bd75Srobert     emitOne(MCOS, LineSec.first, LineSec.second);
55509467b48Spatrick 
55609467b48Spatrick   // This is the end of the section, so set the value of the symbol at the end
55709467b48Spatrick   // of this section (that was used in a previous expression).
558097a140dSpatrick   MCOS->emitLabel(LineEndSym);
55909467b48Spatrick }
56009467b48Spatrick 
561*d415bd75Srobert Expected<unsigned>
tryGetFile(StringRef & Directory,StringRef & FileName,std::optional<MD5::MD5Result> Checksum,std::optional<StringRef> Source,uint16_t DwarfVersion,unsigned FileNumber)562*d415bd75Srobert MCDwarfLineTable::tryGetFile(StringRef &Directory, StringRef &FileName,
563*d415bd75Srobert                              std::optional<MD5::MD5Result> Checksum,
564*d415bd75Srobert                              std::optional<StringRef> Source,
565*d415bd75Srobert                              uint16_t DwarfVersion, unsigned FileNumber) {
56609467b48Spatrick   return Header.tryGetFile(Directory, FileName, Checksum, Source, DwarfVersion,
56709467b48Spatrick                            FileNumber);
56809467b48Spatrick }
56909467b48Spatrick 
isRootFile(const MCDwarfFile & RootFile,StringRef & Directory,StringRef & FileName,std::optional<MD5::MD5Result> Checksum)57009467b48Spatrick static bool isRootFile(const MCDwarfFile &RootFile, StringRef &Directory,
571*d415bd75Srobert                        StringRef &FileName,
572*d415bd75Srobert                        std::optional<MD5::MD5Result> Checksum) {
573*d415bd75Srobert   if (RootFile.Name.empty() || StringRef(RootFile.Name) != FileName)
57409467b48Spatrick     return false;
57509467b48Spatrick   return RootFile.Checksum == Checksum;
57609467b48Spatrick }
57709467b48Spatrick 
57809467b48Spatrick Expected<unsigned>
tryGetFile(StringRef & Directory,StringRef & FileName,std::optional<MD5::MD5Result> Checksum,std::optional<StringRef> Source,uint16_t DwarfVersion,unsigned FileNumber)579*d415bd75Srobert MCDwarfLineTableHeader::tryGetFile(StringRef &Directory, StringRef &FileName,
580*d415bd75Srobert                                    std::optional<MD5::MD5Result> Checksum,
581*d415bd75Srobert                                    std::optional<StringRef> Source,
582*d415bd75Srobert                                    uint16_t DwarfVersion, unsigned FileNumber) {
58309467b48Spatrick   if (Directory == CompilationDir)
58409467b48Spatrick     Directory = "";
58509467b48Spatrick   if (FileName.empty()) {
58609467b48Spatrick     FileName = "<stdin>";
58709467b48Spatrick     Directory = "";
58809467b48Spatrick   }
58909467b48Spatrick   assert(!FileName.empty());
59009467b48Spatrick   // Keep track of whether any or all files have an MD5 checksum.
59109467b48Spatrick   // If any files have embedded source, they all must.
59209467b48Spatrick   if (MCDwarfFiles.empty()) {
593*d415bd75Srobert     trackMD5Usage(Checksum.has_value());
594*d415bd75Srobert     HasSource = (Source != std::nullopt);
59509467b48Spatrick   }
596*d415bd75Srobert   if (DwarfVersion >= 5 && isRootFile(RootFile, Directory, FileName, Checksum))
59709467b48Spatrick     return 0;
59809467b48Spatrick   if (FileNumber == 0) {
59909467b48Spatrick     // File numbers start with 1 and/or after any file numbers
60009467b48Spatrick     // allocated by inline-assembler .file directives.
60109467b48Spatrick     FileNumber = MCDwarfFiles.empty() ? 1 : MCDwarfFiles.size();
60209467b48Spatrick     SmallString<256> Buffer;
60309467b48Spatrick     auto IterBool = SourceIdMap.insert(
60409467b48Spatrick         std::make_pair((Directory + Twine('\0') + FileName).toStringRef(Buffer),
60509467b48Spatrick                        FileNumber));
60609467b48Spatrick     if (!IterBool.second)
60709467b48Spatrick       return IterBool.first->second;
60809467b48Spatrick   }
60909467b48Spatrick   // Make space for this FileNumber in the MCDwarfFiles vector if needed.
61009467b48Spatrick   if (FileNumber >= MCDwarfFiles.size())
61109467b48Spatrick     MCDwarfFiles.resize(FileNumber + 1);
61209467b48Spatrick 
61309467b48Spatrick   // Get the new MCDwarfFile slot for this FileNumber.
61409467b48Spatrick   MCDwarfFile &File = MCDwarfFiles[FileNumber];
61509467b48Spatrick 
61609467b48Spatrick   // It is an error to see the same number more than once.
61709467b48Spatrick   if (!File.Name.empty())
61809467b48Spatrick     return make_error<StringError>("file number already allocated",
61909467b48Spatrick                                    inconvertibleErrorCode());
62009467b48Spatrick 
62109467b48Spatrick   // If any files have embedded source, they all must.
622*d415bd75Srobert   if (HasSource != (Source != std::nullopt))
62309467b48Spatrick     return make_error<StringError>("inconsistent use of embedded source",
62409467b48Spatrick                                    inconvertibleErrorCode());
62509467b48Spatrick 
62609467b48Spatrick   if (Directory.empty()) {
62709467b48Spatrick     // Separate the directory part from the basename of the FileName.
62809467b48Spatrick     StringRef tFileName = sys::path::filename(FileName);
62909467b48Spatrick     if (!tFileName.empty()) {
63009467b48Spatrick       Directory = sys::path::parent_path(FileName);
63109467b48Spatrick       if (!Directory.empty())
63209467b48Spatrick         FileName = tFileName;
63309467b48Spatrick     }
63409467b48Spatrick   }
63509467b48Spatrick 
63609467b48Spatrick   // Find or make an entry in the MCDwarfDirs vector for this Directory.
63709467b48Spatrick   // Capture directory name.
63809467b48Spatrick   unsigned DirIndex;
63909467b48Spatrick   if (Directory.empty()) {
64009467b48Spatrick     // For FileNames with no directories a DirIndex of 0 is used.
64109467b48Spatrick     DirIndex = 0;
64209467b48Spatrick   } else {
64309467b48Spatrick     DirIndex = llvm::find(MCDwarfDirs, Directory) - MCDwarfDirs.begin();
64409467b48Spatrick     if (DirIndex >= MCDwarfDirs.size())
645097a140dSpatrick       MCDwarfDirs.push_back(std::string(Directory));
64609467b48Spatrick     // The DirIndex is one based, as DirIndex of 0 is used for FileNames with
64709467b48Spatrick     // no directories.  MCDwarfDirs[] is unlike MCDwarfFiles[] in that the
64809467b48Spatrick     // directory names are stored at MCDwarfDirs[DirIndex-1] where FileNames
64909467b48Spatrick     // are stored at MCDwarfFiles[FileNumber].Name .
65009467b48Spatrick     DirIndex++;
65109467b48Spatrick   }
65209467b48Spatrick 
653097a140dSpatrick   File.Name = std::string(FileName);
65409467b48Spatrick   File.DirIndex = DirIndex;
65509467b48Spatrick   File.Checksum = Checksum;
656*d415bd75Srobert   trackMD5Usage(Checksum.has_value());
65709467b48Spatrick   File.Source = Source;
65809467b48Spatrick   if (Source)
65909467b48Spatrick     HasSource = true;
66009467b48Spatrick 
66109467b48Spatrick   // return the allocated FileNumber.
66209467b48Spatrick   return FileNumber;
66309467b48Spatrick }
66409467b48Spatrick 
66509467b48Spatrick /// Utility function to emit the encoding to a streamer.
Emit(MCStreamer * MCOS,MCDwarfLineTableParams Params,int64_t LineDelta,uint64_t AddrDelta)66609467b48Spatrick void MCDwarfLineAddr::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
66709467b48Spatrick                            int64_t LineDelta, uint64_t AddrDelta) {
66809467b48Spatrick   MCContext &Context = MCOS->getContext();
66909467b48Spatrick   SmallString<256> Tmp;
67009467b48Spatrick   raw_svector_ostream OS(Tmp);
67109467b48Spatrick   MCDwarfLineAddr::Encode(Context, Params, LineDelta, AddrDelta, OS);
672097a140dSpatrick   MCOS->emitBytes(OS.str());
67309467b48Spatrick }
67409467b48Spatrick 
67509467b48Spatrick /// Given a special op, return the address skip amount (in units of
67609467b48Spatrick /// DWARF2_LINE_MIN_INSN_LENGTH).
SpecialAddr(MCDwarfLineTableParams Params,uint64_t op)67709467b48Spatrick static uint64_t SpecialAddr(MCDwarfLineTableParams Params, uint64_t op) {
67809467b48Spatrick   return (op - Params.DWARF2LineOpcodeBase) / Params.DWARF2LineRange;
67909467b48Spatrick }
68009467b48Spatrick 
68109467b48Spatrick /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.
Encode(MCContext & Context,MCDwarfLineTableParams Params,int64_t LineDelta,uint64_t AddrDelta,raw_ostream & OS)68209467b48Spatrick void MCDwarfLineAddr::Encode(MCContext &Context, MCDwarfLineTableParams Params,
68309467b48Spatrick                              int64_t LineDelta, uint64_t AddrDelta,
68409467b48Spatrick                              raw_ostream &OS) {
68509467b48Spatrick   uint64_t Temp, Opcode;
68609467b48Spatrick   bool NeedCopy = false;
68709467b48Spatrick 
68809467b48Spatrick   // The maximum address skip amount that can be encoded with a special op.
68909467b48Spatrick   uint64_t MaxSpecialAddrDelta = SpecialAddr(Params, 255);
69009467b48Spatrick 
69109467b48Spatrick   // Scale the address delta by the minimum instruction length.
69209467b48Spatrick   AddrDelta = ScaleAddrDelta(Context, AddrDelta);
69309467b48Spatrick 
69409467b48Spatrick   // A LineDelta of INT64_MAX is a signal that this is actually a
69509467b48Spatrick   // DW_LNE_end_sequence. We cannot use special opcodes here, since we want the
69609467b48Spatrick   // end_sequence to emit the matrix entry.
69709467b48Spatrick   if (LineDelta == INT64_MAX) {
69809467b48Spatrick     if (AddrDelta == MaxSpecialAddrDelta)
69909467b48Spatrick       OS << char(dwarf::DW_LNS_const_add_pc);
70009467b48Spatrick     else if (AddrDelta) {
70109467b48Spatrick       OS << char(dwarf::DW_LNS_advance_pc);
70209467b48Spatrick       encodeULEB128(AddrDelta, OS);
70309467b48Spatrick     }
70409467b48Spatrick     OS << char(dwarf::DW_LNS_extended_op);
70509467b48Spatrick     OS << char(1);
70609467b48Spatrick     OS << char(dwarf::DW_LNE_end_sequence);
70709467b48Spatrick     return;
70809467b48Spatrick   }
70909467b48Spatrick 
71009467b48Spatrick   // Bias the line delta by the base.
71109467b48Spatrick   Temp = LineDelta - Params.DWARF2LineBase;
71209467b48Spatrick 
71309467b48Spatrick   // If the line increment is out of range of a special opcode, we must encode
71409467b48Spatrick   // it with DW_LNS_advance_line.
71509467b48Spatrick   if (Temp >= Params.DWARF2LineRange ||
71609467b48Spatrick       Temp + Params.DWARF2LineOpcodeBase > 255) {
71709467b48Spatrick     OS << char(dwarf::DW_LNS_advance_line);
71809467b48Spatrick     encodeSLEB128(LineDelta, OS);
71909467b48Spatrick 
72009467b48Spatrick     LineDelta = 0;
72109467b48Spatrick     Temp = 0 - Params.DWARF2LineBase;
72209467b48Spatrick     NeedCopy = true;
72309467b48Spatrick   }
72409467b48Spatrick 
72509467b48Spatrick   // Use DW_LNS_copy instead of a "line +0, addr +0" special opcode.
72609467b48Spatrick   if (LineDelta == 0 && AddrDelta == 0) {
72709467b48Spatrick     OS << char(dwarf::DW_LNS_copy);
72809467b48Spatrick     return;
72909467b48Spatrick   }
73009467b48Spatrick 
73109467b48Spatrick   // Bias the opcode by the special opcode base.
73209467b48Spatrick   Temp += Params.DWARF2LineOpcodeBase;
73309467b48Spatrick 
73409467b48Spatrick   // Avoid overflow when addr_delta is large.
73509467b48Spatrick   if (AddrDelta < 256 + MaxSpecialAddrDelta) {
73609467b48Spatrick     // Try using a special opcode.
73709467b48Spatrick     Opcode = Temp + AddrDelta * Params.DWARF2LineRange;
73809467b48Spatrick     if (Opcode <= 255) {
73909467b48Spatrick       OS << char(Opcode);
74009467b48Spatrick       return;
74109467b48Spatrick     }
74209467b48Spatrick 
74309467b48Spatrick     // Try using DW_LNS_const_add_pc followed by special op.
74409467b48Spatrick     Opcode = Temp + (AddrDelta - MaxSpecialAddrDelta) * Params.DWARF2LineRange;
74509467b48Spatrick     if (Opcode <= 255) {
74609467b48Spatrick       OS << char(dwarf::DW_LNS_const_add_pc);
74709467b48Spatrick       OS << char(Opcode);
74809467b48Spatrick       return;
74909467b48Spatrick     }
75009467b48Spatrick   }
75109467b48Spatrick 
75209467b48Spatrick   // Otherwise use DW_LNS_advance_pc.
75309467b48Spatrick   OS << char(dwarf::DW_LNS_advance_pc);
75409467b48Spatrick   encodeULEB128(AddrDelta, OS);
75509467b48Spatrick 
75609467b48Spatrick   if (NeedCopy)
75709467b48Spatrick     OS << char(dwarf::DW_LNS_copy);
75809467b48Spatrick   else {
75909467b48Spatrick     assert(Temp <= 255 && "Buggy special opcode encoding.");
76009467b48Spatrick     OS << char(Temp);
76109467b48Spatrick   }
76209467b48Spatrick }
76309467b48Spatrick 
76409467b48Spatrick // Utility function to write a tuple for .debug_abbrev.
EmitAbbrev(MCStreamer * MCOS,uint64_t Name,uint64_t Form)76509467b48Spatrick static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) {
766097a140dSpatrick   MCOS->emitULEB128IntValue(Name);
767097a140dSpatrick   MCOS->emitULEB128IntValue(Form);
76809467b48Spatrick }
76909467b48Spatrick 
77009467b48Spatrick // When generating dwarf for assembly source files this emits
77109467b48Spatrick // the data for .debug_abbrev section which contains three DIEs.
EmitGenDwarfAbbrev(MCStreamer * MCOS)77209467b48Spatrick static void EmitGenDwarfAbbrev(MCStreamer *MCOS) {
77309467b48Spatrick   MCContext &context = MCOS->getContext();
774*d415bd75Srobert   MCOS->switchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
77509467b48Spatrick 
77609467b48Spatrick   // DW_TAG_compile_unit DIE abbrev (1).
777097a140dSpatrick   MCOS->emitULEB128IntValue(1);
778097a140dSpatrick   MCOS->emitULEB128IntValue(dwarf::DW_TAG_compile_unit);
779097a140dSpatrick   MCOS->emitInt8(dwarf::DW_CHILDREN_yes);
780097a140dSpatrick   dwarf::Form SecOffsetForm =
781097a140dSpatrick       context.getDwarfVersion() >= 4
78209467b48Spatrick           ? dwarf::DW_FORM_sec_offset
783097a140dSpatrick           : (context.getDwarfFormat() == dwarf::DWARF64 ? dwarf::DW_FORM_data8
78409467b48Spatrick                                                         : dwarf::DW_FORM_data4);
785097a140dSpatrick   EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, SecOffsetForm);
78609467b48Spatrick   if (context.getGenDwarfSectionSyms().size() > 1 &&
78709467b48Spatrick       context.getDwarfVersion() >= 3) {
788097a140dSpatrick     EmitAbbrev(MCOS, dwarf::DW_AT_ranges, SecOffsetForm);
78909467b48Spatrick   } else {
79009467b48Spatrick     EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
79109467b48Spatrick     EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr);
79209467b48Spatrick   }
79309467b48Spatrick   EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
79409467b48Spatrick   if (!context.getCompilationDir().empty())
79509467b48Spatrick     EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string);
79609467b48Spatrick   StringRef DwarfDebugFlags = context.getDwarfDebugFlags();
79709467b48Spatrick   if (!DwarfDebugFlags.empty())
79809467b48Spatrick     EmitAbbrev(MCOS, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string);
79909467b48Spatrick   EmitAbbrev(MCOS, dwarf::DW_AT_producer, dwarf::DW_FORM_string);
80009467b48Spatrick   EmitAbbrev(MCOS, dwarf::DW_AT_language, dwarf::DW_FORM_data2);
80109467b48Spatrick   EmitAbbrev(MCOS, 0, 0);
80209467b48Spatrick 
80309467b48Spatrick   // DW_TAG_label DIE abbrev (2).
804097a140dSpatrick   MCOS->emitULEB128IntValue(2);
805097a140dSpatrick   MCOS->emitULEB128IntValue(dwarf::DW_TAG_label);
806097a140dSpatrick   MCOS->emitInt8(dwarf::DW_CHILDREN_no);
80709467b48Spatrick   EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
80809467b48Spatrick   EmitAbbrev(MCOS, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data4);
80909467b48Spatrick   EmitAbbrev(MCOS, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data4);
81009467b48Spatrick   EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
81109467b48Spatrick   EmitAbbrev(MCOS, 0, 0);
81209467b48Spatrick 
81309467b48Spatrick   // Terminate the abbreviations for this compilation unit.
814097a140dSpatrick   MCOS->emitInt8(0);
81509467b48Spatrick }
81609467b48Spatrick 
81709467b48Spatrick // When generating dwarf for assembly source files this emits the data for
81809467b48Spatrick // .debug_aranges section. This section contains a header and a table of pairs
81909467b48Spatrick // of PointerSize'ed values for the address and size of section(s) with line
82009467b48Spatrick // table entries.
EmitGenDwarfAranges(MCStreamer * MCOS,const MCSymbol * InfoSectionSymbol)82109467b48Spatrick static void EmitGenDwarfAranges(MCStreamer *MCOS,
82209467b48Spatrick                                 const MCSymbol *InfoSectionSymbol) {
82309467b48Spatrick   MCContext &context = MCOS->getContext();
82409467b48Spatrick 
82509467b48Spatrick   auto &Sections = context.getGenDwarfSectionSyms();
82609467b48Spatrick 
827*d415bd75Srobert   MCOS->switchSection(context.getObjectFileInfo()->getDwarfARangesSection());
82809467b48Spatrick 
829097a140dSpatrick   unsigned UnitLengthBytes =
830097a140dSpatrick       dwarf::getUnitLengthFieldByteSize(context.getDwarfFormat());
831097a140dSpatrick   unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(context.getDwarfFormat());
832097a140dSpatrick 
83309467b48Spatrick   // This will be the length of the .debug_aranges section, first account for
83409467b48Spatrick   // the size of each item in the header (see below where we emit these items).
835097a140dSpatrick   int Length = UnitLengthBytes + 2 + OffsetSize + 1 + 1;
83609467b48Spatrick 
83709467b48Spatrick   // Figure the padding after the header before the table of address and size
83809467b48Spatrick   // pairs who's values are PointerSize'ed.
83909467b48Spatrick   const MCAsmInfo *asmInfo = context.getAsmInfo();
84009467b48Spatrick   int AddrSize = asmInfo->getCodePointerSize();
84109467b48Spatrick   int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1));
84209467b48Spatrick   if (Pad == 2 * AddrSize)
84309467b48Spatrick     Pad = 0;
84409467b48Spatrick   Length += Pad;
84509467b48Spatrick 
84609467b48Spatrick   // Add the size of the pair of PointerSize'ed values for the address and size
84709467b48Spatrick   // of each section we have in the table.
84809467b48Spatrick   Length += 2 * AddrSize * Sections.size();
84909467b48Spatrick   // And the pair of terminating zeros.
85009467b48Spatrick   Length += 2 * AddrSize;
85109467b48Spatrick 
85209467b48Spatrick   // Emit the header for this section.
853097a140dSpatrick   if (context.getDwarfFormat() == dwarf::DWARF64)
854097a140dSpatrick     // The DWARF64 mark.
855097a140dSpatrick     MCOS->emitInt32(dwarf::DW_LENGTH_DWARF64);
856097a140dSpatrick   // The 4 (8 for DWARF64) byte length not including the length of the unit
857097a140dSpatrick   // length field itself.
858097a140dSpatrick   MCOS->emitIntValue(Length - UnitLengthBytes, OffsetSize);
85909467b48Spatrick   // The 2 byte version, which is 2.
860097a140dSpatrick   MCOS->emitInt16(2);
861097a140dSpatrick   // The 4 (8 for DWARF64) byte offset to the compile unit in the .debug_info
862097a140dSpatrick   // from the start of the .debug_info.
86309467b48Spatrick   if (InfoSectionSymbol)
864097a140dSpatrick     MCOS->emitSymbolValue(InfoSectionSymbol, OffsetSize,
86509467b48Spatrick                           asmInfo->needsDwarfSectionOffsetDirective());
86609467b48Spatrick   else
867097a140dSpatrick     MCOS->emitIntValue(0, OffsetSize);
86809467b48Spatrick   // The 1 byte size of an address.
869097a140dSpatrick   MCOS->emitInt8(AddrSize);
87009467b48Spatrick   // The 1 byte size of a segment descriptor, we use a value of zero.
871097a140dSpatrick   MCOS->emitInt8(0);
87209467b48Spatrick   // Align the header with the padding if needed, before we put out the table.
87309467b48Spatrick   for(int i = 0; i < Pad; i++)
874097a140dSpatrick     MCOS->emitInt8(0);
87509467b48Spatrick 
87609467b48Spatrick   // Now emit the table of pairs of PointerSize'ed values for the section
87709467b48Spatrick   // addresses and sizes.
87809467b48Spatrick   for (MCSection *Sec : Sections) {
87909467b48Spatrick     const MCSymbol *StartSymbol = Sec->getBeginSymbol();
88009467b48Spatrick     MCSymbol *EndSymbol = Sec->getEndSymbol(context);
88109467b48Spatrick     assert(StartSymbol && "StartSymbol must not be NULL");
88209467b48Spatrick     assert(EndSymbol && "EndSymbol must not be NULL");
88309467b48Spatrick 
88409467b48Spatrick     const MCExpr *Addr = MCSymbolRefExpr::create(
88509467b48Spatrick       StartSymbol, MCSymbolRefExpr::VK_None, context);
886097a140dSpatrick     const MCExpr *Size =
887097a140dSpatrick         makeEndMinusStartExpr(context, *StartSymbol, *EndSymbol, 0);
888097a140dSpatrick     MCOS->emitValue(Addr, AddrSize);
88909467b48Spatrick     emitAbsValue(*MCOS, Size, AddrSize);
89009467b48Spatrick   }
89109467b48Spatrick 
89209467b48Spatrick   // And finally the pair of terminating zeros.
893097a140dSpatrick   MCOS->emitIntValue(0, AddrSize);
894097a140dSpatrick   MCOS->emitIntValue(0, AddrSize);
89509467b48Spatrick }
89609467b48Spatrick 
89709467b48Spatrick // When generating dwarf for assembly source files this emits the data for
89809467b48Spatrick // .debug_info section which contains three parts.  The header, the compile_unit
89909467b48Spatrick // DIE and a list of label DIEs.
EmitGenDwarfInfo(MCStreamer * MCOS,const MCSymbol * AbbrevSectionSymbol,const MCSymbol * LineSectionSymbol,const MCSymbol * RangesSymbol)90009467b48Spatrick static void EmitGenDwarfInfo(MCStreamer *MCOS,
90109467b48Spatrick                              const MCSymbol *AbbrevSectionSymbol,
90209467b48Spatrick                              const MCSymbol *LineSectionSymbol,
903097a140dSpatrick                              const MCSymbol *RangesSymbol) {
90409467b48Spatrick   MCContext &context = MCOS->getContext();
90509467b48Spatrick 
906*d415bd75Srobert   MCOS->switchSection(context.getObjectFileInfo()->getDwarfInfoSection());
90709467b48Spatrick 
90809467b48Spatrick   // Create a symbol at the start and end of this section used in here for the
90909467b48Spatrick   // expression to calculate the length in the header.
91009467b48Spatrick   MCSymbol *InfoStart = context.createTempSymbol();
911097a140dSpatrick   MCOS->emitLabel(InfoStart);
91209467b48Spatrick   MCSymbol *InfoEnd = context.createTempSymbol();
91309467b48Spatrick 
91409467b48Spatrick   // First part: the header.
91509467b48Spatrick 
916097a140dSpatrick   unsigned UnitLengthBytes =
917097a140dSpatrick       dwarf::getUnitLengthFieldByteSize(context.getDwarfFormat());
918097a140dSpatrick   unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(context.getDwarfFormat());
919097a140dSpatrick 
920097a140dSpatrick   if (context.getDwarfFormat() == dwarf::DWARF64)
921097a140dSpatrick     // Emit DWARF64 mark.
922097a140dSpatrick     MCOS->emitInt32(dwarf::DW_LENGTH_DWARF64);
923097a140dSpatrick 
924097a140dSpatrick   // The 4 (8 for DWARF64) byte total length of the information for this
925097a140dSpatrick   // compilation unit, not including the unit length field itself.
926097a140dSpatrick   const MCExpr *Length =
927097a140dSpatrick       makeEndMinusStartExpr(context, *InfoStart, *InfoEnd, UnitLengthBytes);
928097a140dSpatrick   emitAbsValue(*MCOS, Length, OffsetSize);
92909467b48Spatrick 
93009467b48Spatrick   // The 2 byte DWARF version.
931097a140dSpatrick   MCOS->emitInt16(context.getDwarfVersion());
93209467b48Spatrick 
93309467b48Spatrick   // The DWARF v5 header has unit type, address size, abbrev offset.
93409467b48Spatrick   // Earlier versions have abbrev offset, address size.
93509467b48Spatrick   const MCAsmInfo &AsmInfo = *context.getAsmInfo();
93609467b48Spatrick   int AddrSize = AsmInfo.getCodePointerSize();
93709467b48Spatrick   if (context.getDwarfVersion() >= 5) {
938097a140dSpatrick     MCOS->emitInt8(dwarf::DW_UT_compile);
939097a140dSpatrick     MCOS->emitInt8(AddrSize);
94009467b48Spatrick   }
941097a140dSpatrick   // The 4 (8 for DWARF64) byte offset to the debug abbrevs from the start of
942097a140dSpatrick   // the .debug_abbrev.
943097a140dSpatrick   if (AbbrevSectionSymbol)
944097a140dSpatrick     MCOS->emitSymbolValue(AbbrevSectionSymbol, OffsetSize,
94509467b48Spatrick                           AsmInfo.needsDwarfSectionOffsetDirective());
946097a140dSpatrick   else
947097a140dSpatrick     // Since the abbrevs are at the start of the section, the offset is zero.
948097a140dSpatrick     MCOS->emitIntValue(0, OffsetSize);
94909467b48Spatrick   if (context.getDwarfVersion() <= 4)
950097a140dSpatrick     MCOS->emitInt8(AddrSize);
95109467b48Spatrick 
95209467b48Spatrick   // Second part: the compile_unit DIE.
95309467b48Spatrick 
95409467b48Spatrick   // The DW_TAG_compile_unit DIE abbrev (1).
955097a140dSpatrick   MCOS->emitULEB128IntValue(1);
95609467b48Spatrick 
957097a140dSpatrick   // DW_AT_stmt_list, a 4 (8 for DWARF64) byte offset from the start of the
958097a140dSpatrick   // .debug_line section.
95909467b48Spatrick   if (LineSectionSymbol)
960097a140dSpatrick     MCOS->emitSymbolValue(LineSectionSymbol, OffsetSize,
96109467b48Spatrick                           AsmInfo.needsDwarfSectionOffsetDirective());
96209467b48Spatrick   else
963097a140dSpatrick     // The line table is at the start of the section, so the offset is zero.
964097a140dSpatrick     MCOS->emitIntValue(0, OffsetSize);
96509467b48Spatrick 
966097a140dSpatrick   if (RangesSymbol) {
967097a140dSpatrick     // There are multiple sections containing code, so we must use
968097a140dSpatrick     // .debug_ranges/.debug_rnglists. AT_ranges, the 4/8 byte offset from the
969097a140dSpatrick     // start of the .debug_ranges/.debug_rnglists.
970097a140dSpatrick     MCOS->emitSymbolValue(RangesSymbol, OffsetSize);
97109467b48Spatrick   } else {
97209467b48Spatrick     // If we only have one non-empty code section, we can use the simpler
97309467b48Spatrick     // AT_low_pc and AT_high_pc attributes.
97409467b48Spatrick 
97509467b48Spatrick     // Find the first (and only) non-empty text section
97609467b48Spatrick     auto &Sections = context.getGenDwarfSectionSyms();
97709467b48Spatrick     const auto TextSection = Sections.begin();
97809467b48Spatrick     assert(TextSection != Sections.end() && "No text section found");
97909467b48Spatrick 
98009467b48Spatrick     MCSymbol *StartSymbol = (*TextSection)->getBeginSymbol();
98109467b48Spatrick     MCSymbol *EndSymbol = (*TextSection)->getEndSymbol(context);
98209467b48Spatrick     assert(StartSymbol && "StartSymbol must not be NULL");
98309467b48Spatrick     assert(EndSymbol && "EndSymbol must not be NULL");
98409467b48Spatrick 
98509467b48Spatrick     // AT_low_pc, the first address of the default .text section.
98609467b48Spatrick     const MCExpr *Start = MCSymbolRefExpr::create(
98709467b48Spatrick         StartSymbol, MCSymbolRefExpr::VK_None, context);
988097a140dSpatrick     MCOS->emitValue(Start, AddrSize);
98909467b48Spatrick 
99009467b48Spatrick     // AT_high_pc, the last address of the default .text section.
99109467b48Spatrick     const MCExpr *End = MCSymbolRefExpr::create(
99209467b48Spatrick       EndSymbol, MCSymbolRefExpr::VK_None, context);
993097a140dSpatrick     MCOS->emitValue(End, AddrSize);
99409467b48Spatrick   }
99509467b48Spatrick 
99609467b48Spatrick   // AT_name, the name of the source file.  Reconstruct from the first directory
99709467b48Spatrick   // and file table entries.
99809467b48Spatrick   const SmallVectorImpl<std::string> &MCDwarfDirs = context.getMCDwarfDirs();
99909467b48Spatrick   if (MCDwarfDirs.size() > 0) {
1000097a140dSpatrick     MCOS->emitBytes(MCDwarfDirs[0]);
1001097a140dSpatrick     MCOS->emitBytes(sys::path::get_separator());
100209467b48Spatrick   }
100309467b48Spatrick   const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles = context.getMCDwarfFiles();
100409467b48Spatrick   // MCDwarfFiles might be empty if we have an empty source file.
100509467b48Spatrick   // If it's not empty, [0] is unused and [1] is the first actual file.
100609467b48Spatrick   assert(MCDwarfFiles.empty() || MCDwarfFiles.size() >= 2);
100709467b48Spatrick   const MCDwarfFile &RootFile =
100809467b48Spatrick       MCDwarfFiles.empty()
100909467b48Spatrick           ? context.getMCDwarfLineTable(/*CUID=*/0).getRootFile()
101009467b48Spatrick           : MCDwarfFiles[1];
1011097a140dSpatrick   MCOS->emitBytes(RootFile.Name);
1012097a140dSpatrick   MCOS->emitInt8(0); // NULL byte to terminate the string.
101309467b48Spatrick 
101409467b48Spatrick   // AT_comp_dir, the working directory the assembly was done in.
101509467b48Spatrick   if (!context.getCompilationDir().empty()) {
1016097a140dSpatrick     MCOS->emitBytes(context.getCompilationDir());
1017097a140dSpatrick     MCOS->emitInt8(0); // NULL byte to terminate the string.
101809467b48Spatrick   }
101909467b48Spatrick 
102009467b48Spatrick   // AT_APPLE_flags, the command line arguments of the assembler tool.
102109467b48Spatrick   StringRef DwarfDebugFlags = context.getDwarfDebugFlags();
102209467b48Spatrick   if (!DwarfDebugFlags.empty()){
1023097a140dSpatrick     MCOS->emitBytes(DwarfDebugFlags);
1024097a140dSpatrick     MCOS->emitInt8(0); // NULL byte to terminate the string.
102509467b48Spatrick   }
102609467b48Spatrick 
102709467b48Spatrick   // AT_producer, the version of the assembler tool.
102809467b48Spatrick   StringRef DwarfDebugProducer = context.getDwarfDebugProducer();
102909467b48Spatrick   if (!DwarfDebugProducer.empty())
1030097a140dSpatrick     MCOS->emitBytes(DwarfDebugProducer);
103109467b48Spatrick   else
1032097a140dSpatrick     MCOS->emitBytes(StringRef("llvm-mc (based on LLVM " PACKAGE_VERSION ")"));
1033097a140dSpatrick   MCOS->emitInt8(0); // NULL byte to terminate the string.
103409467b48Spatrick 
103509467b48Spatrick   // AT_language, a 4 byte value.  We use DW_LANG_Mips_Assembler as the dwarf2
103609467b48Spatrick   // draft has no standard code for assembler.
1037097a140dSpatrick   MCOS->emitInt16(dwarf::DW_LANG_Mips_Assembler);
103809467b48Spatrick 
103909467b48Spatrick   // Third part: the list of label DIEs.
104009467b48Spatrick 
104109467b48Spatrick   // Loop on saved info for dwarf labels and create the DIEs for them.
104209467b48Spatrick   const std::vector<MCGenDwarfLabelEntry> &Entries =
104309467b48Spatrick       MCOS->getContext().getMCGenDwarfLabelEntries();
104409467b48Spatrick   for (const auto &Entry : Entries) {
104509467b48Spatrick     // The DW_TAG_label DIE abbrev (2).
1046097a140dSpatrick     MCOS->emitULEB128IntValue(2);
104709467b48Spatrick 
104809467b48Spatrick     // AT_name, of the label without any leading underbar.
1049097a140dSpatrick     MCOS->emitBytes(Entry.getName());
1050097a140dSpatrick     MCOS->emitInt8(0); // NULL byte to terminate the string.
105109467b48Spatrick 
105209467b48Spatrick     // AT_decl_file, index into the file table.
1053097a140dSpatrick     MCOS->emitInt32(Entry.getFileNumber());
105409467b48Spatrick 
105509467b48Spatrick     // AT_decl_line, source line number.
1056097a140dSpatrick     MCOS->emitInt32(Entry.getLineNumber());
105709467b48Spatrick 
105809467b48Spatrick     // AT_low_pc, start address of the label.
105909467b48Spatrick     const MCExpr *AT_low_pc = MCSymbolRefExpr::create(Entry.getLabel(),
106009467b48Spatrick                                              MCSymbolRefExpr::VK_None, context);
1061097a140dSpatrick     MCOS->emitValue(AT_low_pc, AddrSize);
106209467b48Spatrick   }
106309467b48Spatrick 
106409467b48Spatrick   // Add the NULL DIE terminating the Compile Unit DIE's.
1065097a140dSpatrick   MCOS->emitInt8(0);
106609467b48Spatrick 
106709467b48Spatrick   // Now set the value of the symbol at the end of the info section.
1068097a140dSpatrick   MCOS->emitLabel(InfoEnd);
106909467b48Spatrick }
107009467b48Spatrick 
107109467b48Spatrick // When generating dwarf for assembly source files this emits the data for
107209467b48Spatrick // .debug_ranges section. We only emit one range list, which spans all of the
107309467b48Spatrick // executable sections of this file.
emitGenDwarfRanges(MCStreamer * MCOS)1074097a140dSpatrick static MCSymbol *emitGenDwarfRanges(MCStreamer *MCOS) {
107509467b48Spatrick   MCContext &context = MCOS->getContext();
107609467b48Spatrick   auto &Sections = context.getGenDwarfSectionSyms();
107709467b48Spatrick 
107809467b48Spatrick   const MCAsmInfo *AsmInfo = context.getAsmInfo();
107909467b48Spatrick   int AddrSize = AsmInfo->getCodePointerSize();
1080097a140dSpatrick   MCSymbol *RangesSymbol;
108109467b48Spatrick 
1082097a140dSpatrick   if (MCOS->getContext().getDwarfVersion() >= 5) {
1083*d415bd75Srobert     MCOS->switchSection(context.getObjectFileInfo()->getDwarfRnglistsSection());
1084097a140dSpatrick     MCSymbol *EndSymbol = mcdwarf::emitListsTableHeaderStart(*MCOS);
1085097a140dSpatrick     MCOS->AddComment("Offset entry count");
1086097a140dSpatrick     MCOS->emitInt32(0);
108773471bf0Spatrick     RangesSymbol = context.createTempSymbol("debug_rnglist0_start");
1088097a140dSpatrick     MCOS->emitLabel(RangesSymbol);
108909467b48Spatrick     for (MCSection *Sec : Sections) {
109009467b48Spatrick       const MCSymbol *StartSymbol = Sec->getBeginSymbol();
1091097a140dSpatrick       const MCSymbol *EndSymbol = Sec->getEndSymbol(context);
1092097a140dSpatrick       const MCExpr *SectionStartAddr = MCSymbolRefExpr::create(
1093097a140dSpatrick           StartSymbol, MCSymbolRefExpr::VK_None, context);
1094097a140dSpatrick       const MCExpr *SectionSize =
1095097a140dSpatrick           makeEndMinusStartExpr(context, *StartSymbol, *EndSymbol, 0);
1096097a140dSpatrick       MCOS->emitInt8(dwarf::DW_RLE_start_length);
1097097a140dSpatrick       MCOS->emitValue(SectionStartAddr, AddrSize);
1098097a140dSpatrick       MCOS->emitULEB128Value(SectionSize);
1099097a140dSpatrick     }
1100097a140dSpatrick     MCOS->emitInt8(dwarf::DW_RLE_end_of_list);
1101097a140dSpatrick     MCOS->emitLabel(EndSymbol);
1102097a140dSpatrick   } else {
1103*d415bd75Srobert     MCOS->switchSection(context.getObjectFileInfo()->getDwarfRangesSection());
110473471bf0Spatrick     RangesSymbol = context.createTempSymbol("debug_ranges_start");
1105097a140dSpatrick     MCOS->emitLabel(RangesSymbol);
1106097a140dSpatrick     for (MCSection *Sec : Sections) {
1107097a140dSpatrick       const MCSymbol *StartSymbol = Sec->getBeginSymbol();
1108097a140dSpatrick       const MCSymbol *EndSymbol = Sec->getEndSymbol(context);
110909467b48Spatrick 
1110097a140dSpatrick       // Emit a base address selection entry for the section start.
111109467b48Spatrick       const MCExpr *SectionStartAddr = MCSymbolRefExpr::create(
111209467b48Spatrick           StartSymbol, MCSymbolRefExpr::VK_None, context);
111309467b48Spatrick       MCOS->emitFill(AddrSize, 0xFF);
1114097a140dSpatrick       MCOS->emitValue(SectionStartAddr, AddrSize);
111509467b48Spatrick 
1116097a140dSpatrick       // Emit a range list entry spanning this section.
1117097a140dSpatrick       const MCExpr *SectionSize =
1118097a140dSpatrick           makeEndMinusStartExpr(context, *StartSymbol, *EndSymbol, 0);
1119097a140dSpatrick       MCOS->emitIntValue(0, AddrSize);
112009467b48Spatrick       emitAbsValue(*MCOS, SectionSize, AddrSize);
112109467b48Spatrick     }
112209467b48Spatrick 
112309467b48Spatrick     // Emit end of list entry
1124097a140dSpatrick     MCOS->emitIntValue(0, AddrSize);
1125097a140dSpatrick     MCOS->emitIntValue(0, AddrSize);
1126097a140dSpatrick   }
1127097a140dSpatrick 
1128097a140dSpatrick   return RangesSymbol;
112909467b48Spatrick }
113009467b48Spatrick 
113109467b48Spatrick //
113209467b48Spatrick // When generating dwarf for assembly source files this emits the Dwarf
113309467b48Spatrick // sections.
113409467b48Spatrick //
Emit(MCStreamer * MCOS)113509467b48Spatrick void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
113609467b48Spatrick   MCContext &context = MCOS->getContext();
113709467b48Spatrick 
113809467b48Spatrick   // Create the dwarf sections in this order (.debug_line already created).
113909467b48Spatrick   const MCAsmInfo *AsmInfo = context.getAsmInfo();
114009467b48Spatrick   bool CreateDwarfSectionSymbols =
114109467b48Spatrick       AsmInfo->doesDwarfUseRelocationsAcrossSections();
114209467b48Spatrick   MCSymbol *LineSectionSymbol = nullptr;
114309467b48Spatrick   if (CreateDwarfSectionSymbols)
114409467b48Spatrick     LineSectionSymbol = MCOS->getDwarfLineTableSymbol(0);
114509467b48Spatrick   MCSymbol *AbbrevSectionSymbol = nullptr;
114609467b48Spatrick   MCSymbol *InfoSectionSymbol = nullptr;
1147097a140dSpatrick   MCSymbol *RangesSymbol = nullptr;
114809467b48Spatrick 
114909467b48Spatrick   // Create end symbols for each section, and remove empty sections
115009467b48Spatrick   MCOS->getContext().finalizeDwarfSections(*MCOS);
115109467b48Spatrick 
115209467b48Spatrick   // If there are no sections to generate debug info for, we don't need
115309467b48Spatrick   // to do anything
115409467b48Spatrick   if (MCOS->getContext().getGenDwarfSectionSyms().empty())
115509467b48Spatrick     return;
115609467b48Spatrick 
115709467b48Spatrick   // We only use the .debug_ranges section if we have multiple code sections,
115809467b48Spatrick   // and we are emitting a DWARF version which supports it.
115909467b48Spatrick   const bool UseRangesSection =
116009467b48Spatrick       MCOS->getContext().getGenDwarfSectionSyms().size() > 1 &&
116109467b48Spatrick       MCOS->getContext().getDwarfVersion() >= 3;
116209467b48Spatrick   CreateDwarfSectionSymbols |= UseRangesSection;
116309467b48Spatrick 
1164*d415bd75Srobert   MCOS->switchSection(context.getObjectFileInfo()->getDwarfInfoSection());
116509467b48Spatrick   if (CreateDwarfSectionSymbols) {
116609467b48Spatrick     InfoSectionSymbol = context.createTempSymbol();
1167097a140dSpatrick     MCOS->emitLabel(InfoSectionSymbol);
116809467b48Spatrick   }
1169*d415bd75Srobert   MCOS->switchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
117009467b48Spatrick   if (CreateDwarfSectionSymbols) {
117109467b48Spatrick     AbbrevSectionSymbol = context.createTempSymbol();
1172097a140dSpatrick     MCOS->emitLabel(AbbrevSectionSymbol);
117309467b48Spatrick   }
117409467b48Spatrick 
1175*d415bd75Srobert   MCOS->switchSection(context.getObjectFileInfo()->getDwarfARangesSection());
117609467b48Spatrick 
117709467b48Spatrick   // Output the data for .debug_aranges section.
117809467b48Spatrick   EmitGenDwarfAranges(MCOS, InfoSectionSymbol);
117909467b48Spatrick 
1180097a140dSpatrick   if (UseRangesSection) {
1181097a140dSpatrick     RangesSymbol = emitGenDwarfRanges(MCOS);
1182097a140dSpatrick     assert(RangesSymbol);
1183097a140dSpatrick   }
118409467b48Spatrick 
118509467b48Spatrick   // Output the data for .debug_abbrev section.
118609467b48Spatrick   EmitGenDwarfAbbrev(MCOS);
118709467b48Spatrick 
118809467b48Spatrick   // Output the data for .debug_info section.
1189097a140dSpatrick   EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol, RangesSymbol);
119009467b48Spatrick }
119109467b48Spatrick 
119209467b48Spatrick //
119309467b48Spatrick // When generating dwarf for assembly source files this is called when symbol
119409467b48Spatrick // for a label is created.  If this symbol is not a temporary and is in the
119509467b48Spatrick // section that dwarf is being generated for, save the needed info to create
119609467b48Spatrick // a dwarf label.
119709467b48Spatrick //
Make(MCSymbol * Symbol,MCStreamer * MCOS,SourceMgr & SrcMgr,SMLoc & Loc)119809467b48Spatrick void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS,
119909467b48Spatrick                                      SourceMgr &SrcMgr, SMLoc &Loc) {
120009467b48Spatrick   // We won't create dwarf labels for temporary symbols.
120109467b48Spatrick   if (Symbol->isTemporary())
120209467b48Spatrick     return;
120309467b48Spatrick   MCContext &context = MCOS->getContext();
120409467b48Spatrick   // We won't create dwarf labels for symbols in sections that we are not
120509467b48Spatrick   // generating debug info for.
120609467b48Spatrick   if (!context.getGenDwarfSectionSyms().count(MCOS->getCurrentSectionOnly()))
120709467b48Spatrick     return;
120809467b48Spatrick 
120909467b48Spatrick   // The dwarf label's name does not have the symbol name's leading
121009467b48Spatrick   // underbar if any.
121109467b48Spatrick   StringRef Name = Symbol->getName();
121209467b48Spatrick   if (Name.startswith("_"))
121309467b48Spatrick     Name = Name.substr(1, Name.size()-1);
121409467b48Spatrick 
121509467b48Spatrick   // Get the dwarf file number to be used for the dwarf label.
121609467b48Spatrick   unsigned FileNumber = context.getGenDwarfFileNumber();
121709467b48Spatrick 
121809467b48Spatrick   // Finding the line number is the expensive part which is why we just don't
121909467b48Spatrick   // pass it in as for some symbols we won't create a dwarf label.
122009467b48Spatrick   unsigned CurBuffer = SrcMgr.FindBufferContainingLoc(Loc);
122109467b48Spatrick   unsigned LineNumber = SrcMgr.FindLineNumber(Loc, CurBuffer);
122209467b48Spatrick 
122309467b48Spatrick   // We create a temporary symbol for use for the AT_high_pc and AT_low_pc
122409467b48Spatrick   // values so that they don't have things like an ARM thumb bit from the
122509467b48Spatrick   // original symbol. So when used they won't get a low bit set after
122609467b48Spatrick   // relocation.
122709467b48Spatrick   MCSymbol *Label = context.createTempSymbol();
1228097a140dSpatrick   MCOS->emitLabel(Label);
122909467b48Spatrick 
123009467b48Spatrick   // Create and entry for the info and add it to the other entries.
123109467b48Spatrick   MCOS->getContext().addMCGenDwarfLabelEntry(
123209467b48Spatrick       MCGenDwarfLabelEntry(Name, FileNumber, LineNumber, Label));
123309467b48Spatrick }
123409467b48Spatrick 
getDataAlignmentFactor(MCStreamer & streamer)123509467b48Spatrick static int getDataAlignmentFactor(MCStreamer &streamer) {
123609467b48Spatrick   MCContext &context = streamer.getContext();
123709467b48Spatrick   const MCAsmInfo *asmInfo = context.getAsmInfo();
123809467b48Spatrick   int size = asmInfo->getCalleeSaveStackSlotSize();
123909467b48Spatrick   if (asmInfo->isStackGrowthDirectionUp())
124009467b48Spatrick     return size;
124109467b48Spatrick   else
124209467b48Spatrick     return -size;
124309467b48Spatrick }
124409467b48Spatrick 
getSizeForEncoding(MCStreamer & streamer,unsigned symbolEncoding)124509467b48Spatrick static unsigned getSizeForEncoding(MCStreamer &streamer,
124609467b48Spatrick                                    unsigned symbolEncoding) {
124709467b48Spatrick   MCContext &context = streamer.getContext();
124809467b48Spatrick   unsigned format = symbolEncoding & 0x0f;
124909467b48Spatrick   switch (format) {
125009467b48Spatrick   default: llvm_unreachable("Unknown Encoding");
125109467b48Spatrick   case dwarf::DW_EH_PE_absptr:
125209467b48Spatrick   case dwarf::DW_EH_PE_signed:
125309467b48Spatrick     return context.getAsmInfo()->getCodePointerSize();
125409467b48Spatrick   case dwarf::DW_EH_PE_udata2:
125509467b48Spatrick   case dwarf::DW_EH_PE_sdata2:
125609467b48Spatrick     return 2;
125709467b48Spatrick   case dwarf::DW_EH_PE_udata4:
125809467b48Spatrick   case dwarf::DW_EH_PE_sdata4:
125909467b48Spatrick     return 4;
126009467b48Spatrick   case dwarf::DW_EH_PE_udata8:
126109467b48Spatrick   case dwarf::DW_EH_PE_sdata8:
126209467b48Spatrick     return 8;
126309467b48Spatrick   }
126409467b48Spatrick }
126509467b48Spatrick 
emitFDESymbol(MCObjectStreamer & streamer,const MCSymbol & symbol,unsigned symbolEncoding,bool isEH)126609467b48Spatrick static void emitFDESymbol(MCObjectStreamer &streamer, const MCSymbol &symbol,
126709467b48Spatrick                        unsigned symbolEncoding, bool isEH) {
126809467b48Spatrick   MCContext &context = streamer.getContext();
126909467b48Spatrick   const MCAsmInfo *asmInfo = context.getAsmInfo();
127009467b48Spatrick   const MCExpr *v = asmInfo->getExprForFDESymbol(&symbol,
127109467b48Spatrick                                                  symbolEncoding,
127209467b48Spatrick                                                  streamer);
127309467b48Spatrick   unsigned size = getSizeForEncoding(streamer, symbolEncoding);
127409467b48Spatrick   if (asmInfo->doDwarfFDESymbolsUseAbsDiff() && isEH)
127509467b48Spatrick     emitAbsValue(streamer, v, size);
127609467b48Spatrick   else
1277097a140dSpatrick     streamer.emitValue(v, size);
127809467b48Spatrick }
127909467b48Spatrick 
EmitPersonality(MCStreamer & streamer,const MCSymbol & symbol,unsigned symbolEncoding)128009467b48Spatrick static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol,
128109467b48Spatrick                             unsigned symbolEncoding) {
128209467b48Spatrick   MCContext &context = streamer.getContext();
128309467b48Spatrick   const MCAsmInfo *asmInfo = context.getAsmInfo();
128409467b48Spatrick   const MCExpr *v = asmInfo->getExprForPersonalitySymbol(&symbol,
128509467b48Spatrick                                                          symbolEncoding,
128609467b48Spatrick                                                          streamer);
128709467b48Spatrick   unsigned size = getSizeForEncoding(streamer, symbolEncoding);
1288097a140dSpatrick   streamer.emitValue(v, size);
128909467b48Spatrick }
129009467b48Spatrick 
129109467b48Spatrick namespace {
129209467b48Spatrick 
129309467b48Spatrick class FrameEmitterImpl {
129409467b48Spatrick   int CFAOffset = 0;
129509467b48Spatrick   int InitialCFAOffset = 0;
129609467b48Spatrick   bool IsEH;
129709467b48Spatrick   MCObjectStreamer &Streamer;
129809467b48Spatrick 
129909467b48Spatrick public:
FrameEmitterImpl(bool IsEH,MCObjectStreamer & Streamer)130009467b48Spatrick   FrameEmitterImpl(bool IsEH, MCObjectStreamer &Streamer)
130109467b48Spatrick       : IsEH(IsEH), Streamer(Streamer) {}
130209467b48Spatrick 
130309467b48Spatrick   /// Emit the unwind information in a compact way.
130409467b48Spatrick   void EmitCompactUnwind(const MCDwarfFrameInfo &frame);
130509467b48Spatrick 
130609467b48Spatrick   const MCSymbol &EmitCIE(const MCDwarfFrameInfo &F);
130709467b48Spatrick   void EmitFDE(const MCSymbol &cieStart, const MCDwarfFrameInfo &frame,
130809467b48Spatrick                bool LastInSection, const MCSymbol &SectionStart);
1309097a140dSpatrick   void emitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,
131009467b48Spatrick                            MCSymbol *BaseLabel);
1311097a140dSpatrick   void emitCFIInstruction(const MCCFIInstruction &Instr);
131209467b48Spatrick };
131309467b48Spatrick 
131409467b48Spatrick } // end anonymous namespace
131509467b48Spatrick 
emitEncodingByte(MCObjectStreamer & Streamer,unsigned Encoding)131609467b48Spatrick static void emitEncodingByte(MCObjectStreamer &Streamer, unsigned Encoding) {
1317097a140dSpatrick   Streamer.emitInt8(Encoding);
131809467b48Spatrick }
131909467b48Spatrick 
emitCFIInstruction(const MCCFIInstruction & Instr)1320097a140dSpatrick void FrameEmitterImpl::emitCFIInstruction(const MCCFIInstruction &Instr) {
132109467b48Spatrick   int dataAlignmentFactor = getDataAlignmentFactor(Streamer);
132209467b48Spatrick   auto *MRI = Streamer.getContext().getRegisterInfo();
132309467b48Spatrick 
132409467b48Spatrick   switch (Instr.getOperation()) {
132509467b48Spatrick   case MCCFIInstruction::OpRegister: {
132609467b48Spatrick     unsigned Reg1 = Instr.getRegister();
132709467b48Spatrick     unsigned Reg2 = Instr.getRegister2();
132809467b48Spatrick     if (!IsEH) {
132909467b48Spatrick       Reg1 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg1);
133009467b48Spatrick       Reg2 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg2);
133109467b48Spatrick     }
1332097a140dSpatrick     Streamer.emitInt8(dwarf::DW_CFA_register);
1333097a140dSpatrick     Streamer.emitULEB128IntValue(Reg1);
1334097a140dSpatrick     Streamer.emitULEB128IntValue(Reg2);
133509467b48Spatrick     return;
133609467b48Spatrick   }
133709467b48Spatrick   case MCCFIInstruction::OpWindowSave:
1338097a140dSpatrick     Streamer.emitInt8(dwarf::DW_CFA_GNU_window_save);
133909467b48Spatrick     return;
134009467b48Spatrick 
134109467b48Spatrick   case MCCFIInstruction::OpNegateRAState:
1342097a140dSpatrick     Streamer.emitInt8(dwarf::DW_CFA_AARCH64_negate_ra_state);
134309467b48Spatrick     return;
134409467b48Spatrick 
134509467b48Spatrick   case MCCFIInstruction::OpUndefined: {
134609467b48Spatrick     unsigned Reg = Instr.getRegister();
1347097a140dSpatrick     Streamer.emitInt8(dwarf::DW_CFA_undefined);
1348097a140dSpatrick     Streamer.emitULEB128IntValue(Reg);
134909467b48Spatrick     return;
135009467b48Spatrick   }
135109467b48Spatrick   case MCCFIInstruction::OpAdjustCfaOffset:
135209467b48Spatrick   case MCCFIInstruction::OpDefCfaOffset: {
135309467b48Spatrick     const bool IsRelative =
135409467b48Spatrick       Instr.getOperation() == MCCFIInstruction::OpAdjustCfaOffset;
135509467b48Spatrick 
1356097a140dSpatrick     Streamer.emitInt8(dwarf::DW_CFA_def_cfa_offset);
135709467b48Spatrick 
135809467b48Spatrick     if (IsRelative)
135909467b48Spatrick       CFAOffset += Instr.getOffset();
136009467b48Spatrick     else
1361097a140dSpatrick       CFAOffset = Instr.getOffset();
136209467b48Spatrick 
1363097a140dSpatrick     Streamer.emitULEB128IntValue(CFAOffset);
136409467b48Spatrick 
136509467b48Spatrick     return;
136609467b48Spatrick   }
136709467b48Spatrick   case MCCFIInstruction::OpDefCfa: {
136809467b48Spatrick     unsigned Reg = Instr.getRegister();
136909467b48Spatrick     if (!IsEH)
137009467b48Spatrick       Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
1371097a140dSpatrick     Streamer.emitInt8(dwarf::DW_CFA_def_cfa);
1372097a140dSpatrick     Streamer.emitULEB128IntValue(Reg);
1373097a140dSpatrick     CFAOffset = Instr.getOffset();
1374097a140dSpatrick     Streamer.emitULEB128IntValue(CFAOffset);
137509467b48Spatrick 
137609467b48Spatrick     return;
137709467b48Spatrick   }
137809467b48Spatrick   case MCCFIInstruction::OpDefCfaRegister: {
137909467b48Spatrick     unsigned Reg = Instr.getRegister();
138009467b48Spatrick     if (!IsEH)
138109467b48Spatrick       Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
1382097a140dSpatrick     Streamer.emitInt8(dwarf::DW_CFA_def_cfa_register);
1383097a140dSpatrick     Streamer.emitULEB128IntValue(Reg);
138409467b48Spatrick 
138509467b48Spatrick     return;
138609467b48Spatrick   }
138773471bf0Spatrick   // TODO: Implement `_sf` variants if/when they need to be emitted.
138873471bf0Spatrick   case MCCFIInstruction::OpLLVMDefAspaceCfa: {
138973471bf0Spatrick     unsigned Reg = Instr.getRegister();
139073471bf0Spatrick     if (!IsEH)
139173471bf0Spatrick       Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
139273471bf0Spatrick     Streamer.emitIntValue(dwarf::DW_CFA_LLVM_def_aspace_cfa, 1);
139373471bf0Spatrick     Streamer.emitULEB128IntValue(Reg);
139473471bf0Spatrick     CFAOffset = Instr.getOffset();
139573471bf0Spatrick     Streamer.emitULEB128IntValue(CFAOffset);
139673471bf0Spatrick     Streamer.emitULEB128IntValue(Instr.getAddressSpace());
139773471bf0Spatrick 
139873471bf0Spatrick     return;
139973471bf0Spatrick   }
140009467b48Spatrick   case MCCFIInstruction::OpOffset:
140109467b48Spatrick   case MCCFIInstruction::OpRelOffset: {
140209467b48Spatrick     const bool IsRelative =
140309467b48Spatrick       Instr.getOperation() == MCCFIInstruction::OpRelOffset;
140409467b48Spatrick 
140509467b48Spatrick     unsigned Reg = Instr.getRegister();
140609467b48Spatrick     if (!IsEH)
140709467b48Spatrick       Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
140809467b48Spatrick 
140909467b48Spatrick     int Offset = Instr.getOffset();
141009467b48Spatrick     if (IsRelative)
141109467b48Spatrick       Offset -= CFAOffset;
141209467b48Spatrick     Offset = Offset / dataAlignmentFactor;
141309467b48Spatrick 
141409467b48Spatrick     if (Offset < 0) {
1415097a140dSpatrick       Streamer.emitInt8(dwarf::DW_CFA_offset_extended_sf);
1416097a140dSpatrick       Streamer.emitULEB128IntValue(Reg);
1417097a140dSpatrick       Streamer.emitSLEB128IntValue(Offset);
141809467b48Spatrick     } else if (Reg < 64) {
1419097a140dSpatrick       Streamer.emitInt8(dwarf::DW_CFA_offset + Reg);
1420097a140dSpatrick       Streamer.emitULEB128IntValue(Offset);
142109467b48Spatrick     } else {
1422097a140dSpatrick       Streamer.emitInt8(dwarf::DW_CFA_offset_extended);
1423097a140dSpatrick       Streamer.emitULEB128IntValue(Reg);
1424097a140dSpatrick       Streamer.emitULEB128IntValue(Offset);
142509467b48Spatrick     }
142609467b48Spatrick     return;
142709467b48Spatrick   }
142809467b48Spatrick   case MCCFIInstruction::OpRememberState:
1429097a140dSpatrick     Streamer.emitInt8(dwarf::DW_CFA_remember_state);
143009467b48Spatrick     return;
143109467b48Spatrick   case MCCFIInstruction::OpRestoreState:
1432097a140dSpatrick     Streamer.emitInt8(dwarf::DW_CFA_restore_state);
143309467b48Spatrick     return;
143409467b48Spatrick   case MCCFIInstruction::OpSameValue: {
143509467b48Spatrick     unsigned Reg = Instr.getRegister();
1436097a140dSpatrick     Streamer.emitInt8(dwarf::DW_CFA_same_value);
1437097a140dSpatrick     Streamer.emitULEB128IntValue(Reg);
143809467b48Spatrick     return;
143909467b48Spatrick   }
144009467b48Spatrick   case MCCFIInstruction::OpRestore: {
144109467b48Spatrick     unsigned Reg = Instr.getRegister();
144209467b48Spatrick     if (!IsEH)
144309467b48Spatrick       Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
144409467b48Spatrick     if (Reg < 64) {
1445097a140dSpatrick       Streamer.emitInt8(dwarf::DW_CFA_restore | Reg);
144609467b48Spatrick     } else {
1447097a140dSpatrick       Streamer.emitInt8(dwarf::DW_CFA_restore_extended);
1448097a140dSpatrick       Streamer.emitULEB128IntValue(Reg);
144909467b48Spatrick     }
145009467b48Spatrick     return;
145109467b48Spatrick   }
145209467b48Spatrick   case MCCFIInstruction::OpGnuArgsSize:
1453097a140dSpatrick     Streamer.emitInt8(dwarf::DW_CFA_GNU_args_size);
1454097a140dSpatrick     Streamer.emitULEB128IntValue(Instr.getOffset());
145509467b48Spatrick     return;
145609467b48Spatrick 
145709467b48Spatrick   case MCCFIInstruction::OpEscape:
1458097a140dSpatrick     Streamer.emitBytes(Instr.getValues());
145909467b48Spatrick     return;
146009467b48Spatrick   }
146109467b48Spatrick   llvm_unreachable("Unhandled case in switch");
146209467b48Spatrick }
146309467b48Spatrick 
146409467b48Spatrick /// Emit frame instructions to describe the layout of the frame.
emitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,MCSymbol * BaseLabel)1465097a140dSpatrick void FrameEmitterImpl::emitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,
146609467b48Spatrick                                            MCSymbol *BaseLabel) {
146709467b48Spatrick   for (const MCCFIInstruction &Instr : Instrs) {
146809467b48Spatrick     MCSymbol *Label = Instr.getLabel();
146909467b48Spatrick     // Throw out move if the label is invalid.
147009467b48Spatrick     if (Label && !Label->isDefined()) continue; // Not emitted, in dead code.
147109467b48Spatrick 
147209467b48Spatrick     // Advance row if new location.
147309467b48Spatrick     if (BaseLabel && Label) {
147409467b48Spatrick       MCSymbol *ThisSym = Label;
147509467b48Spatrick       if (ThisSym != BaseLabel) {
1476097a140dSpatrick         Streamer.emitDwarfAdvanceFrameAddr(BaseLabel, ThisSym);
147709467b48Spatrick         BaseLabel = ThisSym;
147809467b48Spatrick       }
147909467b48Spatrick     }
148009467b48Spatrick 
1481097a140dSpatrick     emitCFIInstruction(Instr);
148209467b48Spatrick   }
148309467b48Spatrick }
148409467b48Spatrick 
148509467b48Spatrick /// Emit the unwind information in a compact way.
EmitCompactUnwind(const MCDwarfFrameInfo & Frame)148609467b48Spatrick void FrameEmitterImpl::EmitCompactUnwind(const MCDwarfFrameInfo &Frame) {
148709467b48Spatrick   MCContext &Context = Streamer.getContext();
148809467b48Spatrick   const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();
148909467b48Spatrick 
149009467b48Spatrick   // range-start range-length  compact-unwind-enc personality-func   lsda
149109467b48Spatrick   //  _foo       LfooEnd-_foo  0x00000023          0                 0
149209467b48Spatrick   //  _bar       LbarEnd-_bar  0x00000025         __gxx_personality  except_tab1
149309467b48Spatrick   //
149409467b48Spatrick   //   .section __LD,__compact_unwind,regular,debug
149509467b48Spatrick   //
149609467b48Spatrick   //   # compact unwind for _foo
149709467b48Spatrick   //   .quad _foo
149809467b48Spatrick   //   .set L1,LfooEnd-_foo
149909467b48Spatrick   //   .long L1
150009467b48Spatrick   //   .long 0x01010001
150109467b48Spatrick   //   .quad 0
150209467b48Spatrick   //   .quad 0
150309467b48Spatrick   //
150409467b48Spatrick   //   # compact unwind for _bar
150509467b48Spatrick   //   .quad _bar
150609467b48Spatrick   //   .set L2,LbarEnd-_bar
150709467b48Spatrick   //   .long L2
150809467b48Spatrick   //   .long 0x01020011
150909467b48Spatrick   //   .quad __gxx_personality
151009467b48Spatrick   //   .quad except_tab1
151109467b48Spatrick 
151209467b48Spatrick   uint32_t Encoding = Frame.CompactUnwindEncoding;
151309467b48Spatrick   if (!Encoding) return;
151409467b48Spatrick   bool DwarfEHFrameOnly = (Encoding == MOFI->getCompactUnwindDwarfEHFrameOnly());
151509467b48Spatrick 
151609467b48Spatrick   // The encoding needs to know we have an LSDA.
151709467b48Spatrick   if (!DwarfEHFrameOnly && Frame.Lsda)
151809467b48Spatrick     Encoding |= 0x40000000;
151909467b48Spatrick 
152009467b48Spatrick   // Range Start
152109467b48Spatrick   unsigned FDEEncoding = MOFI->getFDEEncoding();
152209467b48Spatrick   unsigned Size = getSizeForEncoding(Streamer, FDEEncoding);
1523097a140dSpatrick   Streamer.emitSymbolValue(Frame.Begin, Size);
152409467b48Spatrick 
152509467b48Spatrick   // Range Length
1526097a140dSpatrick   const MCExpr *Range =
1527097a140dSpatrick       makeEndMinusStartExpr(Context, *Frame.Begin, *Frame.End, 0);
152809467b48Spatrick   emitAbsValue(Streamer, Range, 4);
152909467b48Spatrick 
153009467b48Spatrick   // Compact Encoding
153109467b48Spatrick   Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4);
1532097a140dSpatrick   Streamer.emitIntValue(Encoding, Size);
153309467b48Spatrick 
153409467b48Spatrick   // Personality Function
153509467b48Spatrick   Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_absptr);
153609467b48Spatrick   if (!DwarfEHFrameOnly && Frame.Personality)
1537097a140dSpatrick     Streamer.emitSymbolValue(Frame.Personality, Size);
153809467b48Spatrick   else
1539097a140dSpatrick     Streamer.emitIntValue(0, Size); // No personality fn
154009467b48Spatrick 
154109467b48Spatrick   // LSDA
154209467b48Spatrick   Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding);
154309467b48Spatrick   if (!DwarfEHFrameOnly && Frame.Lsda)
1544097a140dSpatrick     Streamer.emitSymbolValue(Frame.Lsda, Size);
154509467b48Spatrick   else
1546097a140dSpatrick     Streamer.emitIntValue(0, Size); // No LSDA
154709467b48Spatrick }
154809467b48Spatrick 
getCIEVersion(bool IsEH,unsigned DwarfVersion)154909467b48Spatrick static unsigned getCIEVersion(bool IsEH, unsigned DwarfVersion) {
155009467b48Spatrick   if (IsEH)
155109467b48Spatrick     return 1;
155209467b48Spatrick   switch (DwarfVersion) {
155309467b48Spatrick   case 2:
155409467b48Spatrick     return 1;
155509467b48Spatrick   case 3:
155609467b48Spatrick     return 3;
155709467b48Spatrick   case 4:
155809467b48Spatrick   case 5:
155909467b48Spatrick     return 4;
156009467b48Spatrick   }
156109467b48Spatrick   llvm_unreachable("Unknown version");
156209467b48Spatrick }
156309467b48Spatrick 
EmitCIE(const MCDwarfFrameInfo & Frame)156409467b48Spatrick const MCSymbol &FrameEmitterImpl::EmitCIE(const MCDwarfFrameInfo &Frame) {
156509467b48Spatrick   MCContext &context = Streamer.getContext();
156609467b48Spatrick   const MCRegisterInfo *MRI = context.getRegisterInfo();
156709467b48Spatrick   const MCObjectFileInfo *MOFI = context.getObjectFileInfo();
156809467b48Spatrick 
156909467b48Spatrick   MCSymbol *sectionStart = context.createTempSymbol();
1570097a140dSpatrick   Streamer.emitLabel(sectionStart);
157109467b48Spatrick 
157209467b48Spatrick   MCSymbol *sectionEnd = context.createTempSymbol();
157309467b48Spatrick 
1574097a140dSpatrick   dwarf::DwarfFormat Format = IsEH ? dwarf::DWARF32 : context.getDwarfFormat();
1575097a140dSpatrick   unsigned UnitLengthBytes = dwarf::getUnitLengthFieldByteSize(Format);
1576097a140dSpatrick   unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(Format);
1577097a140dSpatrick   bool IsDwarf64 = Format == dwarf::DWARF64;
1578097a140dSpatrick 
1579097a140dSpatrick   if (IsDwarf64)
1580097a140dSpatrick     // DWARF64 mark
1581097a140dSpatrick     Streamer.emitInt32(dwarf::DW_LENGTH_DWARF64);
1582097a140dSpatrick 
158309467b48Spatrick   // Length
1584097a140dSpatrick   const MCExpr *Length = makeEndMinusStartExpr(context, *sectionStart,
1585097a140dSpatrick                                                *sectionEnd, UnitLengthBytes);
1586097a140dSpatrick   emitAbsValue(Streamer, Length, OffsetSize);
158709467b48Spatrick 
158809467b48Spatrick   // CIE ID
1589097a140dSpatrick   uint64_t CIE_ID =
1590097a140dSpatrick       IsEH ? 0 : (IsDwarf64 ? dwarf::DW64_CIE_ID : dwarf::DW_CIE_ID);
1591097a140dSpatrick   Streamer.emitIntValue(CIE_ID, OffsetSize);
159209467b48Spatrick 
159309467b48Spatrick   // Version
159409467b48Spatrick   uint8_t CIEVersion = getCIEVersion(IsEH, context.getDwarfVersion());
1595097a140dSpatrick   Streamer.emitInt8(CIEVersion);
159609467b48Spatrick 
159709467b48Spatrick   if (IsEH) {
159809467b48Spatrick     SmallString<8> Augmentation;
159909467b48Spatrick     Augmentation += "z";
160009467b48Spatrick     if (Frame.Personality)
160109467b48Spatrick       Augmentation += "P";
160209467b48Spatrick     if (Frame.Lsda)
160309467b48Spatrick       Augmentation += "L";
160409467b48Spatrick     Augmentation += "R";
160509467b48Spatrick     if (Frame.IsSignalFrame)
160609467b48Spatrick       Augmentation += "S";
160709467b48Spatrick     if (Frame.IsBKeyFrame)
160809467b48Spatrick       Augmentation += "B";
1609*d415bd75Srobert     if (Frame.IsMTETaggedFrame)
1610*d415bd75Srobert       Augmentation += "G";
1611097a140dSpatrick     Streamer.emitBytes(Augmentation);
161209467b48Spatrick   }
1613097a140dSpatrick   Streamer.emitInt8(0);
161409467b48Spatrick 
161509467b48Spatrick   if (CIEVersion >= 4) {
161609467b48Spatrick     // Address Size
1617097a140dSpatrick     Streamer.emitInt8(context.getAsmInfo()->getCodePointerSize());
161809467b48Spatrick 
161909467b48Spatrick     // Segment Descriptor Size
1620097a140dSpatrick     Streamer.emitInt8(0);
162109467b48Spatrick   }
162209467b48Spatrick 
162309467b48Spatrick   // Code Alignment Factor
1624097a140dSpatrick   Streamer.emitULEB128IntValue(context.getAsmInfo()->getMinInstAlignment());
162509467b48Spatrick 
162609467b48Spatrick   // Data Alignment Factor
1627097a140dSpatrick   Streamer.emitSLEB128IntValue(getDataAlignmentFactor(Streamer));
162809467b48Spatrick 
162909467b48Spatrick   // Return Address Register
163009467b48Spatrick   unsigned RAReg = Frame.RAReg;
163109467b48Spatrick   if (RAReg == static_cast<unsigned>(INT_MAX))
163209467b48Spatrick     RAReg = MRI->getDwarfRegNum(MRI->getRARegister(), IsEH);
163309467b48Spatrick 
163409467b48Spatrick   if (CIEVersion == 1) {
163509467b48Spatrick     assert(RAReg <= 255 &&
163609467b48Spatrick            "DWARF 2 encodes return_address_register in one byte");
1637097a140dSpatrick     Streamer.emitInt8(RAReg);
163809467b48Spatrick   } else {
1639097a140dSpatrick     Streamer.emitULEB128IntValue(RAReg);
164009467b48Spatrick   }
164109467b48Spatrick 
164209467b48Spatrick   // Augmentation Data Length (optional)
164309467b48Spatrick   unsigned augmentationLength = 0;
164409467b48Spatrick   if (IsEH) {
164509467b48Spatrick     if (Frame.Personality) {
164609467b48Spatrick       // Personality Encoding
164709467b48Spatrick       augmentationLength += 1;
164809467b48Spatrick       // Personality
164909467b48Spatrick       augmentationLength +=
165009467b48Spatrick           getSizeForEncoding(Streamer, Frame.PersonalityEncoding);
165109467b48Spatrick     }
165209467b48Spatrick     if (Frame.Lsda)
165309467b48Spatrick       augmentationLength += 1;
165409467b48Spatrick     // Encoding of the FDE pointers
165509467b48Spatrick     augmentationLength += 1;
165609467b48Spatrick 
1657097a140dSpatrick     Streamer.emitULEB128IntValue(augmentationLength);
165809467b48Spatrick 
165909467b48Spatrick     // Augmentation Data (optional)
166009467b48Spatrick     if (Frame.Personality) {
166109467b48Spatrick       // Personality Encoding
166209467b48Spatrick       emitEncodingByte(Streamer, Frame.PersonalityEncoding);
166309467b48Spatrick       // Personality
166409467b48Spatrick       EmitPersonality(Streamer, *Frame.Personality, Frame.PersonalityEncoding);
166509467b48Spatrick     }
166609467b48Spatrick 
166709467b48Spatrick     if (Frame.Lsda)
166809467b48Spatrick       emitEncodingByte(Streamer, Frame.LsdaEncoding);
166909467b48Spatrick 
167009467b48Spatrick     // Encoding of the FDE pointers
167109467b48Spatrick     emitEncodingByte(Streamer, MOFI->getFDEEncoding());
167209467b48Spatrick   }
167309467b48Spatrick 
167409467b48Spatrick   // Initial Instructions
167509467b48Spatrick 
167609467b48Spatrick   const MCAsmInfo *MAI = context.getAsmInfo();
167709467b48Spatrick   if (!Frame.IsSimple) {
167809467b48Spatrick     const std::vector<MCCFIInstruction> &Instructions =
167909467b48Spatrick         MAI->getInitialFrameState();
1680097a140dSpatrick     emitCFIInstructions(Instructions, nullptr);
168109467b48Spatrick   }
168209467b48Spatrick 
168309467b48Spatrick   InitialCFAOffset = CFAOffset;
168409467b48Spatrick 
168509467b48Spatrick   // Padding
1686*d415bd75Srobert   Streamer.emitValueToAlignment(Align(IsEH ? 4 : MAI->getCodePointerSize()));
168709467b48Spatrick 
1688097a140dSpatrick   Streamer.emitLabel(sectionEnd);
168909467b48Spatrick   return *sectionStart;
169009467b48Spatrick }
169109467b48Spatrick 
EmitFDE(const MCSymbol & cieStart,const MCDwarfFrameInfo & frame,bool LastInSection,const MCSymbol & SectionStart)169209467b48Spatrick void FrameEmitterImpl::EmitFDE(const MCSymbol &cieStart,
169309467b48Spatrick                                const MCDwarfFrameInfo &frame,
169409467b48Spatrick                                bool LastInSection,
169509467b48Spatrick                                const MCSymbol &SectionStart) {
169609467b48Spatrick   MCContext &context = Streamer.getContext();
169709467b48Spatrick   MCSymbol *fdeStart = context.createTempSymbol();
169809467b48Spatrick   MCSymbol *fdeEnd = context.createTempSymbol();
169909467b48Spatrick   const MCObjectFileInfo *MOFI = context.getObjectFileInfo();
170009467b48Spatrick 
170109467b48Spatrick   CFAOffset = InitialCFAOffset;
170209467b48Spatrick 
1703097a140dSpatrick   dwarf::DwarfFormat Format = IsEH ? dwarf::DWARF32 : context.getDwarfFormat();
1704097a140dSpatrick   unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(Format);
170509467b48Spatrick 
1706097a140dSpatrick   if (Format == dwarf::DWARF64)
1707097a140dSpatrick     // DWARF64 mark
1708097a140dSpatrick     Streamer.emitInt32(dwarf::DW_LENGTH_DWARF64);
1709097a140dSpatrick 
1710097a140dSpatrick   // Length
1711097a140dSpatrick   const MCExpr *Length = makeEndMinusStartExpr(context, *fdeStart, *fdeEnd, 0);
1712097a140dSpatrick   emitAbsValue(Streamer, Length, OffsetSize);
1713097a140dSpatrick 
1714097a140dSpatrick   Streamer.emitLabel(fdeStart);
171509467b48Spatrick 
171609467b48Spatrick   // CIE Pointer
171709467b48Spatrick   const MCAsmInfo *asmInfo = context.getAsmInfo();
171809467b48Spatrick   if (IsEH) {
171909467b48Spatrick     const MCExpr *offset =
1720097a140dSpatrick         makeEndMinusStartExpr(context, cieStart, *fdeStart, 0);
1721097a140dSpatrick     emitAbsValue(Streamer, offset, OffsetSize);
172209467b48Spatrick   } else if (!asmInfo->doesDwarfUseRelocationsAcrossSections()) {
172309467b48Spatrick     const MCExpr *offset =
1724097a140dSpatrick         makeEndMinusStartExpr(context, SectionStart, cieStart, 0);
1725097a140dSpatrick     emitAbsValue(Streamer, offset, OffsetSize);
172609467b48Spatrick   } else {
1727097a140dSpatrick     Streamer.emitSymbolValue(&cieStart, OffsetSize,
172809467b48Spatrick                              asmInfo->needsDwarfSectionOffsetDirective());
172909467b48Spatrick   }
173009467b48Spatrick 
173109467b48Spatrick   // PC Begin
173209467b48Spatrick   unsigned PCEncoding =
173309467b48Spatrick       IsEH ? MOFI->getFDEEncoding() : (unsigned)dwarf::DW_EH_PE_absptr;
173409467b48Spatrick   unsigned PCSize = getSizeForEncoding(Streamer, PCEncoding);
173509467b48Spatrick   emitFDESymbol(Streamer, *frame.Begin, PCEncoding, IsEH);
173609467b48Spatrick 
173709467b48Spatrick   // PC Range
173809467b48Spatrick   const MCExpr *Range =
1739097a140dSpatrick       makeEndMinusStartExpr(context, *frame.Begin, *frame.End, 0);
174009467b48Spatrick   emitAbsValue(Streamer, Range, PCSize);
174109467b48Spatrick 
174209467b48Spatrick   if (IsEH) {
174309467b48Spatrick     // Augmentation Data Length
174409467b48Spatrick     unsigned augmentationLength = 0;
174509467b48Spatrick 
174609467b48Spatrick     if (frame.Lsda)
174709467b48Spatrick       augmentationLength += getSizeForEncoding(Streamer, frame.LsdaEncoding);
174809467b48Spatrick 
1749097a140dSpatrick     Streamer.emitULEB128IntValue(augmentationLength);
175009467b48Spatrick 
175109467b48Spatrick     // Augmentation Data
175209467b48Spatrick     if (frame.Lsda)
175309467b48Spatrick       emitFDESymbol(Streamer, *frame.Lsda, frame.LsdaEncoding, true);
175409467b48Spatrick   }
175509467b48Spatrick 
175609467b48Spatrick   // Call Frame Instructions
1757097a140dSpatrick   emitCFIInstructions(frame.Instructions, frame.Begin);
175809467b48Spatrick 
175909467b48Spatrick   // Padding
176009467b48Spatrick   // The size of a .eh_frame section has to be a multiple of the alignment
176109467b48Spatrick   // since a null CIE is interpreted as the end. Old systems overaligned
176209467b48Spatrick   // .eh_frame, so we do too and account for it in the last FDE.
1763*d415bd75Srobert   unsigned Alignment = LastInSection ? asmInfo->getCodePointerSize() : PCSize;
1764*d415bd75Srobert   Streamer.emitValueToAlignment(Align(Alignment));
176509467b48Spatrick 
1766097a140dSpatrick   Streamer.emitLabel(fdeEnd);
176709467b48Spatrick }
176809467b48Spatrick 
176909467b48Spatrick namespace {
177009467b48Spatrick 
177109467b48Spatrick struct CIEKey {
getEmptyKey__anon703b1a400311::CIEKey177209467b48Spatrick   static const CIEKey getEmptyKey() {
177309467b48Spatrick     return CIEKey(nullptr, 0, -1, false, false, static_cast<unsigned>(INT_MAX),
1774*d415bd75Srobert                   false, false);
177509467b48Spatrick   }
177609467b48Spatrick 
getTombstoneKey__anon703b1a400311::CIEKey177709467b48Spatrick   static const CIEKey getTombstoneKey() {
177809467b48Spatrick     return CIEKey(nullptr, -1, 0, false, false, static_cast<unsigned>(INT_MAX),
1779*d415bd75Srobert                   false, false);
178009467b48Spatrick   }
178109467b48Spatrick 
CIEKey__anon703b1a400311::CIEKey178209467b48Spatrick   CIEKey(const MCSymbol *Personality, unsigned PersonalityEncoding,
178309467b48Spatrick          unsigned LSDAEncoding, bool IsSignalFrame, bool IsSimple,
1784*d415bd75Srobert          unsigned RAReg, bool IsBKeyFrame, bool IsMTETaggedFrame)
178509467b48Spatrick       : Personality(Personality), PersonalityEncoding(PersonalityEncoding),
178609467b48Spatrick         LsdaEncoding(LSDAEncoding), IsSignalFrame(IsSignalFrame),
1787*d415bd75Srobert         IsSimple(IsSimple), RAReg(RAReg), IsBKeyFrame(IsBKeyFrame),
1788*d415bd75Srobert         IsMTETaggedFrame(IsMTETaggedFrame) {}
178909467b48Spatrick 
CIEKey__anon703b1a400311::CIEKey179009467b48Spatrick   explicit CIEKey(const MCDwarfFrameInfo &Frame)
179109467b48Spatrick       : Personality(Frame.Personality),
179209467b48Spatrick         PersonalityEncoding(Frame.PersonalityEncoding),
179309467b48Spatrick         LsdaEncoding(Frame.LsdaEncoding), IsSignalFrame(Frame.IsSignalFrame),
179409467b48Spatrick         IsSimple(Frame.IsSimple), RAReg(Frame.RAReg),
1795*d415bd75Srobert         IsBKeyFrame(Frame.IsBKeyFrame),
1796*d415bd75Srobert         IsMTETaggedFrame(Frame.IsMTETaggedFrame) {}
179709467b48Spatrick 
PersonalityName__anon703b1a400311::CIEKey179809467b48Spatrick   StringRef PersonalityName() const {
179909467b48Spatrick     if (!Personality)
180009467b48Spatrick       return StringRef();
180109467b48Spatrick     return Personality->getName();
180209467b48Spatrick   }
180309467b48Spatrick 
operator <__anon703b1a400311::CIEKey180409467b48Spatrick   bool operator<(const CIEKey &Other) const {
180509467b48Spatrick     return std::make_tuple(PersonalityName(), PersonalityEncoding, LsdaEncoding,
1806*d415bd75Srobert                            IsSignalFrame, IsSimple, RAReg, IsBKeyFrame,
1807*d415bd75Srobert                            IsMTETaggedFrame) <
180809467b48Spatrick            std::make_tuple(Other.PersonalityName(), Other.PersonalityEncoding,
180909467b48Spatrick                            Other.LsdaEncoding, Other.IsSignalFrame,
1810*d415bd75Srobert                            Other.IsSimple, Other.RAReg, Other.IsBKeyFrame,
1811*d415bd75Srobert                            Other.IsMTETaggedFrame);
181209467b48Spatrick   }
181309467b48Spatrick 
181409467b48Spatrick   const MCSymbol *Personality;
181509467b48Spatrick   unsigned PersonalityEncoding;
181609467b48Spatrick   unsigned LsdaEncoding;
181709467b48Spatrick   bool IsSignalFrame;
181809467b48Spatrick   bool IsSimple;
181909467b48Spatrick   unsigned RAReg;
182009467b48Spatrick   bool IsBKeyFrame;
1821*d415bd75Srobert   bool IsMTETaggedFrame;
182209467b48Spatrick };
182309467b48Spatrick 
182409467b48Spatrick } // end anonymous namespace
182509467b48Spatrick 
182609467b48Spatrick namespace llvm {
182709467b48Spatrick 
182809467b48Spatrick template <> struct DenseMapInfo<CIEKey> {
getEmptyKeyllvm::DenseMapInfo182909467b48Spatrick   static CIEKey getEmptyKey() { return CIEKey::getEmptyKey(); }
getTombstoneKeyllvm::DenseMapInfo183009467b48Spatrick   static CIEKey getTombstoneKey() { return CIEKey::getTombstoneKey(); }
183109467b48Spatrick 
getHashValuellvm::DenseMapInfo183209467b48Spatrick   static unsigned getHashValue(const CIEKey &Key) {
1833*d415bd75Srobert     return static_cast<unsigned>(
1834*d415bd75Srobert         hash_combine(Key.Personality, Key.PersonalityEncoding, Key.LsdaEncoding,
1835*d415bd75Srobert                      Key.IsSignalFrame, Key.IsSimple, Key.RAReg,
1836*d415bd75Srobert                      Key.IsBKeyFrame, Key.IsMTETaggedFrame));
183709467b48Spatrick   }
183809467b48Spatrick 
isEqualllvm::DenseMapInfo183909467b48Spatrick   static bool isEqual(const CIEKey &LHS, const CIEKey &RHS) {
184009467b48Spatrick     return LHS.Personality == RHS.Personality &&
184109467b48Spatrick            LHS.PersonalityEncoding == RHS.PersonalityEncoding &&
184209467b48Spatrick            LHS.LsdaEncoding == RHS.LsdaEncoding &&
184309467b48Spatrick            LHS.IsSignalFrame == RHS.IsSignalFrame &&
184409467b48Spatrick            LHS.IsSimple == RHS.IsSimple && LHS.RAReg == RHS.RAReg &&
1845*d415bd75Srobert            LHS.IsBKeyFrame == RHS.IsBKeyFrame &&
1846*d415bd75Srobert            LHS.IsMTETaggedFrame == RHS.IsMTETaggedFrame;
184709467b48Spatrick   }
184809467b48Spatrick };
184909467b48Spatrick 
185009467b48Spatrick } // end namespace llvm
185109467b48Spatrick 
Emit(MCObjectStreamer & Streamer,MCAsmBackend * MAB,bool IsEH)185209467b48Spatrick void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB,
185309467b48Spatrick                                bool IsEH) {
185409467b48Spatrick   MCContext &Context = Streamer.getContext();
185509467b48Spatrick   const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();
185609467b48Spatrick   const MCAsmInfo *AsmInfo = Context.getAsmInfo();
185709467b48Spatrick   FrameEmitterImpl Emitter(IsEH, Streamer);
185809467b48Spatrick   ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getDwarfFrameInfos();
185909467b48Spatrick 
186009467b48Spatrick   // Emit the compact unwind info if available.
186109467b48Spatrick   bool NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame();
186209467b48Spatrick   if (IsEH && MOFI->getCompactUnwindSection()) {
1863*d415bd75Srobert     Streamer.generateCompactUnwindEncodings(MAB);
186409467b48Spatrick     bool SectionEmitted = false;
186509467b48Spatrick     for (const MCDwarfFrameInfo &Frame : FrameArray) {
186609467b48Spatrick       if (Frame.CompactUnwindEncoding == 0) continue;
186709467b48Spatrick       if (!SectionEmitted) {
1868*d415bd75Srobert         Streamer.switchSection(MOFI->getCompactUnwindSection());
1869*d415bd75Srobert         Streamer.emitValueToAlignment(Align(AsmInfo->getCodePointerSize()));
187009467b48Spatrick         SectionEmitted = true;
187109467b48Spatrick       }
187209467b48Spatrick       NeedsEHFrameSection |=
187309467b48Spatrick         Frame.CompactUnwindEncoding ==
187409467b48Spatrick           MOFI->getCompactUnwindDwarfEHFrameOnly();
187509467b48Spatrick       Emitter.EmitCompactUnwind(Frame);
187609467b48Spatrick     }
187709467b48Spatrick   }
187809467b48Spatrick 
187909467b48Spatrick   if (!NeedsEHFrameSection) return;
188009467b48Spatrick 
188109467b48Spatrick   MCSection &Section =
188209467b48Spatrick       IsEH ? *const_cast<MCObjectFileInfo *>(MOFI)->getEHFrameSection()
188309467b48Spatrick            : *MOFI->getDwarfFrameSection();
188409467b48Spatrick 
1885*d415bd75Srobert   Streamer.switchSection(&Section);
188609467b48Spatrick   MCSymbol *SectionStart = Context.createTempSymbol();
1887097a140dSpatrick   Streamer.emitLabel(SectionStart);
188809467b48Spatrick 
188909467b48Spatrick   DenseMap<CIEKey, const MCSymbol *> CIEStarts;
189009467b48Spatrick 
189109467b48Spatrick   const MCSymbol *DummyDebugKey = nullptr;
189209467b48Spatrick   bool CanOmitDwarf = MOFI->getOmitDwarfIfHaveCompactUnwind();
189309467b48Spatrick   // Sort the FDEs by their corresponding CIE before we emit them.
189409467b48Spatrick   // This isn't technically necessary according to the DWARF standard,
189509467b48Spatrick   // but the Android libunwindstack rejects eh_frame sections where
189609467b48Spatrick   // an FDE refers to a CIE other than the closest previous CIE.
189709467b48Spatrick   std::vector<MCDwarfFrameInfo> FrameArrayX(FrameArray.begin(), FrameArray.end());
189809467b48Spatrick   llvm::stable_sort(FrameArrayX,
189909467b48Spatrick                     [](const MCDwarfFrameInfo &X, const MCDwarfFrameInfo &Y) {
190009467b48Spatrick                       return CIEKey(X) < CIEKey(Y);
190109467b48Spatrick                     });
190209467b48Spatrick   for (auto I = FrameArrayX.begin(), E = FrameArrayX.end(); I != E;) {
190309467b48Spatrick     const MCDwarfFrameInfo &Frame = *I;
190409467b48Spatrick     ++I;
190509467b48Spatrick     if (CanOmitDwarf && Frame.CompactUnwindEncoding !=
190609467b48Spatrick           MOFI->getCompactUnwindDwarfEHFrameOnly())
190709467b48Spatrick       // Don't generate an EH frame if we don't need one. I.e., it's taken care
190809467b48Spatrick       // of by the compact unwind encoding.
190909467b48Spatrick       continue;
191009467b48Spatrick 
191109467b48Spatrick     CIEKey Key(Frame);
191209467b48Spatrick     const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey;
191309467b48Spatrick     if (!CIEStart)
191409467b48Spatrick       CIEStart = &Emitter.EmitCIE(Frame);
191509467b48Spatrick 
191609467b48Spatrick     Emitter.EmitFDE(*CIEStart, Frame, I == E, *SectionStart);
191709467b48Spatrick   }
191809467b48Spatrick }
191909467b48Spatrick 
EmitAdvanceLoc(MCObjectStreamer & Streamer,uint64_t AddrDelta)192009467b48Spatrick void MCDwarfFrameEmitter::EmitAdvanceLoc(MCObjectStreamer &Streamer,
192109467b48Spatrick                                          uint64_t AddrDelta) {
192209467b48Spatrick   MCContext &Context = Streamer.getContext();
192309467b48Spatrick   SmallString<256> Tmp;
192409467b48Spatrick   raw_svector_ostream OS(Tmp);
192509467b48Spatrick   MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OS);
1926097a140dSpatrick   Streamer.emitBytes(OS.str());
192709467b48Spatrick }
192809467b48Spatrick 
EncodeAdvanceLoc(MCContext & Context,uint64_t AddrDelta,raw_ostream & OS)192909467b48Spatrick void MCDwarfFrameEmitter::EncodeAdvanceLoc(MCContext &Context,
193073471bf0Spatrick                                            uint64_t AddrDelta,
193173471bf0Spatrick                                            raw_ostream &OS) {
193209467b48Spatrick   // Scale the address delta by the minimum instruction length.
193309467b48Spatrick   AddrDelta = ScaleAddrDelta(Context, AddrDelta);
193473471bf0Spatrick   if (AddrDelta == 0)
193573471bf0Spatrick     return;
193609467b48Spatrick 
193709467b48Spatrick   support::endianness E =
193809467b48Spatrick       Context.getAsmInfo()->isLittleEndian() ? support::little : support::big;
193973471bf0Spatrick 
194073471bf0Spatrick   if (isUIntN(6, AddrDelta)) {
194109467b48Spatrick     uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta;
194209467b48Spatrick     OS << Opcode;
194309467b48Spatrick   } else if (isUInt<8>(AddrDelta)) {
194409467b48Spatrick     OS << uint8_t(dwarf::DW_CFA_advance_loc1);
194509467b48Spatrick     OS << uint8_t(AddrDelta);
194609467b48Spatrick   } else if (isUInt<16>(AddrDelta)) {
194709467b48Spatrick     OS << uint8_t(dwarf::DW_CFA_advance_loc2);
194809467b48Spatrick     support::endian::write<uint16_t>(OS, AddrDelta, E);
194909467b48Spatrick   } else {
195009467b48Spatrick     assert(isUInt<32>(AddrDelta));
195109467b48Spatrick     OS << uint8_t(dwarf::DW_CFA_advance_loc4);
195209467b48Spatrick     support::endian::write<uint32_t>(OS, AddrDelta, E);
195309467b48Spatrick   }
195409467b48Spatrick }
1955