diff options
| author | 2020-08-03 15:06:44 +0000 | |
|---|---|---|
| committer | 2020-08-03 15:06:44 +0000 | |
| commit | b64793999546ed8adebaeebd9d8345d18db8927d (patch) | |
| tree | 4357c27b561d73b0e089727c6ed659f2ceff5f47 /gnu/llvm/lib/MC/MCDwarf.cpp | |
| parent | Add support for UTF-8 DISPLAY-HINTs with octet length. For now only (diff) | |
| download | wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.tar.xz wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.zip | |
Remove LLVM 8.0.1 files.
Diffstat (limited to 'gnu/llvm/lib/MC/MCDwarf.cpp')
| -rw-r--r-- | gnu/llvm/lib/MC/MCDwarf.cpp | 1884 |
1 files changed, 0 insertions, 1884 deletions
diff --git a/gnu/llvm/lib/MC/MCDwarf.cpp b/gnu/llvm/lib/MC/MCDwarf.cpp deleted file mode 100644 index 38b02694d81..00000000000 --- a/gnu/llvm/lib/MC/MCDwarf.cpp +++ /dev/null @@ -1,1884 +0,0 @@ -//===- lib/MC/MCDwarf.cpp - MCDwarf implementation ------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCDwarf.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Hashing.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/Config/config.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCObjectStreamer.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSection.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/StringTableBuilder.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/EndianStream.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/LEB128.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> -#include <cstdint> -#include <string> -#include <utility> -#include <vector> - -using namespace llvm; - -/// Manage the .debug_line_str section contents, if we use it. -class llvm::MCDwarfLineStr { - MCSymbol *LineStrLabel = nullptr; - StringTableBuilder LineStrings{StringTableBuilder::DWARF}; - bool UseRelocs = false; - -public: - /// Construct an instance that can emit .debug_line_str (for use in a normal - /// v5 line table). - explicit MCDwarfLineStr(MCContext &Ctx) { - UseRelocs = Ctx.getAsmInfo()->doesDwarfUseRelocationsAcrossSections(); - if (UseRelocs) - LineStrLabel = - Ctx.getObjectFileInfo()->getDwarfLineStrSection()->getBeginSymbol(); - } - - /// Emit a reference to the string. - void emitRef(MCStreamer *MCOS, StringRef Path); - - /// Emit the .debug_line_str section if appropriate. - void emitSection(MCStreamer *MCOS); -}; - -static inline uint64_t ScaleAddrDelta(MCContext &Context, uint64_t AddrDelta) { - unsigned MinInsnLength = Context.getAsmInfo()->getMinInstAlignment(); - if (MinInsnLength == 1) - return AddrDelta; - if (AddrDelta % MinInsnLength != 0) { - // TODO: report this error, but really only once. - ; - } - return AddrDelta / MinInsnLength; -} - -// -// This is called when an instruction is assembled into the specified section -// and if there is information from the last .loc directive that has yet to have -// a line entry made for it is made. -// -void MCDwarfLineEntry::Make(MCObjectStreamer *MCOS, MCSection *Section) { - if (!MCOS->getContext().getDwarfLocSeen()) - return; - - // Create a symbol at in the current section for use in the line entry. - MCSymbol *LineSym = MCOS->getContext().createTempSymbol(); - // Set the value of the symbol to use for the MCDwarfLineEntry. - MCOS->EmitLabel(LineSym); - - // Get the current .loc info saved in the context. - const MCDwarfLoc &DwarfLoc = MCOS->getContext().getCurrentDwarfLoc(); - - // Create a (local) line entry with the symbol and the current .loc info. - MCDwarfLineEntry LineEntry(LineSym, DwarfLoc); - - // clear DwarfLocSeen saying the current .loc info is now used. - MCOS->getContext().clearDwarfLocSeen(); - - // Add the line entry to this section's entries. - MCOS->getContext() - .getMCDwarfLineTable(MCOS->getContext().getDwarfCompileUnitID()) - .getMCLineSections() - .addLineEntry(LineEntry, Section); -} - -// -// This helper routine returns an expression of End - Start + IntVal . -// -static inline const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS, - const MCSymbol &Start, - const MCSymbol &End, - int IntVal) { - MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; - const MCExpr *Res = - MCSymbolRefExpr::create(&End, Variant, MCOS.getContext()); - const MCExpr *RHS = - MCSymbolRefExpr::create(&Start, Variant, MCOS.getContext()); - const MCExpr *Res1 = - MCBinaryExpr::create(MCBinaryExpr::Sub, Res, RHS, MCOS.getContext()); - const MCExpr *Res2 = - MCConstantExpr::create(IntVal, MCOS.getContext()); - const MCExpr *Res3 = - MCBinaryExpr::create(MCBinaryExpr::Sub, Res1, Res2, MCOS.getContext()); - return Res3; -} - -// -// This helper routine returns an expression of Start + IntVal . -// -static inline const MCExpr * -makeStartPlusIntExpr(MCContext &Ctx, const MCSymbol &Start, int IntVal) { - MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; - const MCExpr *LHS = MCSymbolRefExpr::create(&Start, Variant, Ctx); - const MCExpr *RHS = MCConstantExpr::create(IntVal, Ctx); - const MCExpr *Res = MCBinaryExpr::create(MCBinaryExpr::Add, LHS, RHS, Ctx); - return Res; -} - -// -// This emits the Dwarf line table for the specified section from the entries -// in the LineSection. -// -static inline void -EmitDwarfLineTable(MCObjectStreamer *MCOS, MCSection *Section, - const MCLineSection::MCDwarfLineEntryCollection &LineEntries) { - unsigned FileNum = 1; - unsigned LastLine = 1; - unsigned Column = 0; - unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; - unsigned Isa = 0; - unsigned Discriminator = 0; - MCSymbol *LastLabel = nullptr; - - // Loop through each MCDwarfLineEntry and encode the dwarf line number table. - for (const MCDwarfLineEntry &LineEntry : LineEntries) { - int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine; - - if (FileNum != LineEntry.getFileNum()) { - FileNum = LineEntry.getFileNum(); - MCOS->EmitIntValue(dwarf::DW_LNS_set_file, 1); - MCOS->EmitULEB128IntValue(FileNum); - } - if (Column != LineEntry.getColumn()) { - Column = LineEntry.getColumn(); - MCOS->EmitIntValue(dwarf::DW_LNS_set_column, 1); - MCOS->EmitULEB128IntValue(Column); - } - if (Discriminator != LineEntry.getDiscriminator() && - MCOS->getContext().getDwarfVersion() >= 4) { - Discriminator = LineEntry.getDiscriminator(); - unsigned Size = getULEB128Size(Discriminator); - MCOS->EmitIntValue(dwarf::DW_LNS_extended_op, 1); - MCOS->EmitULEB128IntValue(Size + 1); - MCOS->EmitIntValue(dwarf::DW_LNE_set_discriminator, 1); - MCOS->EmitULEB128IntValue(Discriminator); - } - if (Isa != LineEntry.getIsa()) { - Isa = LineEntry.getIsa(); - MCOS->EmitIntValue(dwarf::DW_LNS_set_isa, 1); - MCOS->EmitULEB128IntValue(Isa); - } - if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { - Flags = LineEntry.getFlags(); - MCOS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1); - } - if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK) - MCOS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1); - if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END) - MCOS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1); - if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) - MCOS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1); - - MCSymbol *Label = LineEntry.getLabel(); - - // At this point we want to emit/create the sequence to encode the delta in - // line numbers and the increment of the address from the previous Label - // and the current Label. - const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo(); - MCOS->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, - asmInfo->getCodePointerSize()); - - Discriminator = 0; - LastLine = LineEntry.getLine(); - LastLabel = Label; - } - - // Emit a DW_LNE_end_sequence for the end of the section. - // Use the section end label to compute the address delta and use INT64_MAX - // as the line delta which is the signal that this is actually a - // DW_LNE_end_sequence. - MCSymbol *SectionEnd = MCOS->endSection(Section); - - // Switch back the dwarf line section, in case endSection had to switch the - // section. - MCContext &Ctx = MCOS->getContext(); - MCOS->SwitchSection(Ctx.getObjectFileInfo()->getDwarfLineSection()); - - const MCAsmInfo *AsmInfo = Ctx.getAsmInfo(); - MCOS->EmitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd, - AsmInfo->getCodePointerSize()); -} - -// -// This emits the Dwarf file and the line tables. -// -void MCDwarfLineTable::Emit(MCObjectStreamer *MCOS, - MCDwarfLineTableParams Params) { - MCContext &context = MCOS->getContext(); - - auto &LineTables = context.getMCDwarfLineTables(); - - // Bail out early so we don't switch to the debug_line section needlessly and - // in doing so create an unnecessary (if empty) section. - if (LineTables.empty()) - return; - - // In a v5 non-split line table, put the strings in a separate section. - Optional<MCDwarfLineStr> LineStr; - if (context.getDwarfVersion() >= 5) - LineStr = MCDwarfLineStr(context); - - // Switch to the section where the table will be emitted into. - MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection()); - - // Handle the rest of the Compile Units. - for (const auto &CUIDTablePair : LineTables) { - CUIDTablePair.second.EmitCU(MCOS, Params, LineStr); - } - - if (LineStr) - LineStr->emitSection(MCOS); -} - -void MCDwarfDwoLineTable::Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params, - MCSection *Section) const { - if (Header.MCDwarfFiles.empty()) - return; - Optional<MCDwarfLineStr> NoLineStr(None); - MCOS.SwitchSection(Section); - MCOS.EmitLabel(Header.Emit(&MCOS, Params, None, NoLineStr).second); -} - -std::pair<MCSymbol *, MCSymbol *> -MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, - Optional<MCDwarfLineStr> &LineStr) const { - static const char StandardOpcodeLengths[] = { - 0, // length of DW_LNS_copy - 1, // length of DW_LNS_advance_pc - 1, // length of DW_LNS_advance_line - 1, // length of DW_LNS_set_file - 1, // length of DW_LNS_set_column - 0, // length of DW_LNS_negate_stmt - 0, // length of DW_LNS_set_basic_block - 0, // length of DW_LNS_const_add_pc - 1, // length of DW_LNS_fixed_advance_pc - 0, // length of DW_LNS_set_prologue_end - 0, // length of DW_LNS_set_epilogue_begin - 1 // DW_LNS_set_isa - }; - assert(array_lengthof(StandardOpcodeLengths) >= - (Params.DWARF2LineOpcodeBase - 1U)); - return Emit( - MCOS, Params, - makeArrayRef(StandardOpcodeLengths, Params.DWARF2LineOpcodeBase - 1), - LineStr); -} - -static const MCExpr *forceExpAbs(MCStreamer &OS, const MCExpr* Expr) { - MCContext &Context = OS.getContext(); - assert(!isa<MCSymbolRefExpr>(Expr)); - if (Context.getAsmInfo()->hasAggressiveSymbolFolding()) - return Expr; - - MCSymbol *ABS = Context.createTempSymbol(); - OS.EmitAssignment(ABS, Expr); - return MCSymbolRefExpr::create(ABS, Context); -} - -static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size) { - const MCExpr *ABS = forceExpAbs(OS, Value); - OS.EmitValue(ABS, Size); -} - -void MCDwarfLineStr::emitSection(MCStreamer *MCOS) { - // Switch to the .debug_line_str section. - MCOS->SwitchSection( - MCOS->getContext().getObjectFileInfo()->getDwarfLineStrSection()); - // Emit the strings without perturbing the offsets we used. - LineStrings.finalizeInOrder(); - SmallString<0> Data; - Data.resize(LineStrings.getSize()); - LineStrings.write((uint8_t *)Data.data()); - MCOS->EmitBinaryData(Data.str()); -} - -void MCDwarfLineStr::emitRef(MCStreamer *MCOS, StringRef Path) { - int RefSize = 4; // FIXME: Support DWARF-64 - size_t Offset = LineStrings.add(Path); - if (UseRelocs) { - MCContext &Ctx = MCOS->getContext(); - MCOS->EmitValue(makeStartPlusIntExpr(Ctx, *LineStrLabel, Offset), RefSize); - } else - MCOS->EmitIntValue(Offset, RefSize); -} - -void MCDwarfLineTableHeader::emitV2FileDirTables(MCStreamer *MCOS) const { - // First the directory table. - for (auto &Dir : MCDwarfDirs) { - MCOS->EmitBytes(Dir); // The DirectoryName, and... - MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator. - } - MCOS->EmitIntValue(0, 1); // Terminate the directory list. - - // Second the file table. - for (unsigned i = 1; i < MCDwarfFiles.size(); i++) { - assert(!MCDwarfFiles[i].Name.empty()); - MCOS->EmitBytes(MCDwarfFiles[i].Name); // FileName and... - MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator. - MCOS->EmitULEB128IntValue(MCDwarfFiles[i].DirIndex); // Directory number. - MCOS->EmitIntValue(0, 1); // Last modification timestamp (always 0). - MCOS->EmitIntValue(0, 1); // File size (always 0). - } - MCOS->EmitIntValue(0, 1); // Terminate the file list. -} - -static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile, - bool EmitMD5, bool HasSource, - Optional<MCDwarfLineStr> &LineStr) { - assert(!DwarfFile.Name.empty()); - if (LineStr) - LineStr->emitRef(MCOS, DwarfFile.Name); - else { - MCOS->EmitBytes(DwarfFile.Name); // FileName and... - MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator. - } - MCOS->EmitULEB128IntValue(DwarfFile.DirIndex); // Directory number. - if (EmitMD5) { - MD5::MD5Result *Cksum = DwarfFile.Checksum; - MCOS->EmitBinaryData( - StringRef(reinterpret_cast<const char *>(Cksum->Bytes.data()), - Cksum->Bytes.size())); - } - if (HasSource) { - if (LineStr) - LineStr->emitRef(MCOS, DwarfFile.Source.getValueOr(StringRef())); - else { - MCOS->EmitBytes( - DwarfFile.Source.getValueOr(StringRef())); // Source and... - MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator. - } - } -} - -void MCDwarfLineTableHeader::emitV5FileDirTables( - MCStreamer *MCOS, Optional<MCDwarfLineStr> &LineStr, - StringRef CtxCompilationDir) const { - // The directory format, which is just a list of the directory paths. In a - // non-split object, these are references to .debug_line_str; in a split - // object, they are inline strings. - MCOS->EmitIntValue(1, 1); - MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path); - MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp - : dwarf::DW_FORM_string); - MCOS->EmitULEB128IntValue(MCDwarfDirs.size() + 1); - // Try not to emit an empty compilation directory. - const StringRef CompDir = - CompilationDir.empty() ? CtxCompilationDir : StringRef(CompilationDir); - if (LineStr) { - // Record path strings, emit references here. - LineStr->emitRef(MCOS, CompDir); - for (const auto &Dir : MCDwarfDirs) - LineStr->emitRef(MCOS, Dir); - } else { - // The list of directory paths. Compilation directory comes first. - MCOS->EmitBytes(CompDir); - MCOS->EmitBytes(StringRef("\0", 1)); - for (const auto &Dir : MCDwarfDirs) { - MCOS->EmitBytes(Dir); // The DirectoryName, and... - MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator. - } - } - - // The file format, which is the inline null-terminated filename and a - // directory index. We don't track file size/timestamp so don't emit them - // in the v5 table. Emit MD5 checksums and source if we have them. - uint64_t Entries = 2; - if (HasAllMD5) - Entries += 1; - if (HasSource) - Entries += 1; - MCOS->EmitIntValue(Entries, 1); - MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path); - MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp - : dwarf::DW_FORM_string); - MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_directory_index); - MCOS->EmitULEB128IntValue(dwarf::DW_FORM_udata); - if (HasAllMD5) { - MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_MD5); - MCOS->EmitULEB128IntValue(dwarf::DW_FORM_data16); - } - if (HasSource) { - MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_LLVM_source); - MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp - : dwarf::DW_FORM_string); - } - // Then the counted list of files. The root file is file #0, then emit the - // files as provide by .file directives. To accommodate assembler source - // written for DWARF v4 but trying to emit v5, if we didn't see a root file - // explicitly, replicate file #1. - MCOS->EmitULEB128IntValue(MCDwarfFiles.size()); - emitOneV5FileEntry(MCOS, RootFile.Name.empty() ? MCDwarfFiles[1] : RootFile, - HasAllMD5, HasSource, LineStr); - for (unsigned i = 1; i < MCDwarfFiles.size(); ++i) - emitOneV5FileEntry(MCOS, MCDwarfFiles[i], HasAllMD5, HasSource, LineStr); -} - -std::pair<MCSymbol *, MCSymbol *> -MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, - ArrayRef<char> StandardOpcodeLengths, - Optional<MCDwarfLineStr> &LineStr) const { - MCContext &context = MCOS->getContext(); - - // Create a symbol at the beginning of the line table. - MCSymbol *LineStartSym = Label; - if (!LineStartSym) - LineStartSym = context.createTempSymbol(); - // Set the value of the symbol, as we are at the start of the line table. - MCOS->EmitLabel(LineStartSym); - - // Create a symbol for the end of the section (to be set when we get there). - MCSymbol *LineEndSym = context.createTempSymbol(); - - // The first 4 bytes is the total length of the information for this - // compilation unit (not including these 4 bytes for the length). - emitAbsValue(*MCOS, - MakeStartMinusEndExpr(*MCOS, *LineStartSym, *LineEndSym, 4), 4); - - // Next 2 bytes is the Version. - unsigned LineTableVersion = context.getDwarfVersion(); - MCOS->EmitIntValue(LineTableVersion, 2); - - // Keep track of the bytes between the very start and where the header length - // comes out. - unsigned PreHeaderLengthBytes = 4 + 2; - - // In v5, we get address info next. - if (LineTableVersion >= 5) { - MCOS->EmitIntValue(context.getAsmInfo()->getCodePointerSize(), 1); - MCOS->EmitIntValue(0, 1); // Segment selector; same as EmitGenDwarfAranges. - PreHeaderLengthBytes += 2; - } - - // Create a symbol for the end of the prologue (to be set when we get there). - MCSymbol *ProEndSym = context.createTempSymbol(); // Lprologue_end - - // Length of the prologue, is the next 4 bytes. This is actually the length - // from after the length word, to the end of the prologue. - emitAbsValue(*MCOS, - MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym, - (PreHeaderLengthBytes + 4)), - 4); - - // Parameters of the state machine, are next. - MCOS->EmitIntValue(context.getAsmInfo()->getMinInstAlignment(), 1); - // maximum_operations_per_instruction - // For non-VLIW architectures this field is always 1. - // FIXME: VLIW architectures need to update this field accordingly. - if (LineTableVersion >= 4) - MCOS->EmitIntValue(1, 1); - MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1); - MCOS->EmitIntValue(Params.DWARF2LineBase, 1); - MCOS->EmitIntValue(Params.DWARF2LineRange, 1); - MCOS->EmitIntValue(StandardOpcodeLengths.size() + 1, 1); - - // Standard opcode lengths - for (char Length : StandardOpcodeLengths) - MCOS->EmitIntValue(Length, 1); - - // Put out the directory and file tables. The formats vary depending on - // the version. - if (LineTableVersion >= 5) - emitV5FileDirTables(MCOS, LineStr, context.getCompilationDir()); - else - emitV2FileDirTables(MCOS); - - // This is the end of the prologue, so set the value of the symbol at the - // end of the prologue (that was used in a previous expression). - MCOS->EmitLabel(ProEndSym); - - return std::make_pair(LineStartSym, LineEndSym); -} - -void MCDwarfLineTable::EmitCU(MCObjectStreamer *MCOS, - MCDwarfLineTableParams Params, - Optional<MCDwarfLineStr> &LineStr) const { - MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second; - - // Put out the line tables. - for (const auto &LineSec : MCLineSections.getMCLineEntries()) - EmitDwarfLineTable(MCOS, LineSec.first, LineSec.second); - - // This is the end of the section, so set the value of the symbol at the end - // of this section (that was used in a previous expression). - MCOS->EmitLabel(LineEndSym); -} - -Expected<unsigned> MCDwarfLineTable::tryGetFile(StringRef &Directory, - StringRef &FileName, - MD5::MD5Result *Checksum, - Optional<StringRef> Source, - unsigned FileNumber) { - return Header.tryGetFile(Directory, FileName, Checksum, Source, FileNumber); -} - -Expected<unsigned> -MCDwarfLineTableHeader::tryGetFile(StringRef &Directory, - StringRef &FileName, - MD5::MD5Result *Checksum, - Optional<StringRef> &Source, - unsigned FileNumber) { - if (Directory == CompilationDir) - Directory = ""; - if (FileName.empty()) { - FileName = "<stdin>"; - Directory = ""; - } - assert(!FileName.empty()); - // Keep track of whether any or all files have an MD5 checksum. - // If any files have embedded source, they all must. - if (MCDwarfFiles.empty()) { - trackMD5Usage(Checksum); - HasSource = (Source != None); - } - if (FileNumber == 0) { - // File numbers start with 1 and/or after any file numbers - // allocated by inline-assembler .file directives. - FileNumber = MCDwarfFiles.empty() ? 1 : MCDwarfFiles.size(); - SmallString<256> Buffer; - auto IterBool = SourceIdMap.insert( - std::make_pair((Directory + Twine('\0') + FileName).toStringRef(Buffer), - FileNumber)); - if (!IterBool.second) - return IterBool.first->second; - } - // Make space for this FileNumber in the MCDwarfFiles vector if needed. - if (FileNumber >= MCDwarfFiles.size()) - MCDwarfFiles.resize(FileNumber + 1); - - // Get the new MCDwarfFile slot for this FileNumber. - MCDwarfFile &File = MCDwarfFiles[FileNumber]; - - // It is an error to see the same number more than once. - if (!File.Name.empty()) - return make_error<StringError>("file number already allocated", - inconvertibleErrorCode()); - - // If any files have embedded source, they all must. - if (HasSource != (Source != None)) - return make_error<StringError>("inconsistent use of embedded source", - inconvertibleErrorCode()); - - if (Directory.empty()) { - // Separate the directory part from the basename of the FileName. - StringRef tFileName = sys::path::filename(FileName); - if (!tFileName.empty()) { - Directory = sys::path::parent_path(FileName); - if (!Directory.empty()) - FileName = tFileName; - } - } - - // Find or make an entry in the MCDwarfDirs vector for this Directory. - // Capture directory name. - unsigned DirIndex; - if (Directory.empty()) { - // For FileNames with no directories a DirIndex of 0 is used. - DirIndex = 0; - } else { - DirIndex = 0; - for (unsigned End = MCDwarfDirs.size(); DirIndex < End; DirIndex++) { - if (Directory == MCDwarfDirs[DirIndex]) - break; - } - if (DirIndex >= MCDwarfDirs.size()) - MCDwarfDirs.push_back(Directory); - // The DirIndex is one based, as DirIndex of 0 is used for FileNames with - // no directories. MCDwarfDirs[] is unlike MCDwarfFiles[] in that the - // directory names are stored at MCDwarfDirs[DirIndex-1] where FileNames - // are stored at MCDwarfFiles[FileNumber].Name . - DirIndex++; - } - - File.Name = FileName; - File.DirIndex = DirIndex; - File.Checksum = Checksum; - trackMD5Usage(Checksum); - File.Source = Source; - if (Source) - HasSource = true; - - // return the allocated FileNumber. - return FileNumber; -} - -/// Utility function to emit the encoding to a streamer. -void MCDwarfLineAddr::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, - int64_t LineDelta, uint64_t AddrDelta) { - MCContext &Context = MCOS->getContext(); - SmallString<256> Tmp; - raw_svector_ostream OS(Tmp); - MCDwarfLineAddr::Encode(Context, Params, LineDelta, AddrDelta, OS); - MCOS->EmitBytes(OS.str()); -} - -/// Given a special op, return the address skip amount (in units of -/// DWARF2_LINE_MIN_INSN_LENGTH). -static uint64_t SpecialAddr(MCDwarfLineTableParams Params, uint64_t op) { - return (op - Params.DWARF2LineOpcodeBase) / Params.DWARF2LineRange; -} - -/// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. -void MCDwarfLineAddr::Encode(MCContext &Context, MCDwarfLineTableParams Params, - int64_t LineDelta, uint64_t AddrDelta, - raw_ostream &OS) { - uint64_t Temp, Opcode; - bool NeedCopy = false; - - // The maximum address skip amount that can be encoded with a special op. - uint64_t MaxSpecialAddrDelta = SpecialAddr(Params, 255); - - // Scale the address delta by the minimum instruction length. - AddrDelta = ScaleAddrDelta(Context, AddrDelta); - - // A LineDelta of INT64_MAX is a signal that this is actually a - // DW_LNE_end_sequence. We cannot use special opcodes here, since we want the - // end_sequence to emit the matrix entry. - if (LineDelta == INT64_MAX) { - if (AddrDelta == MaxSpecialAddrDelta) - OS << char(dwarf::DW_LNS_const_add_pc); - else if (AddrDelta) { - OS << char(dwarf::DW_LNS_advance_pc); - encodeULEB128(AddrDelta, OS); - } - OS << char(dwarf::DW_LNS_extended_op); - OS << char(1); - OS << char(dwarf::DW_LNE_end_sequence); - return; - } - - // Bias the line delta by the base. - Temp = LineDelta - Params.DWARF2LineBase; - - // If the line increment is out of range of a special opcode, we must encode - // it with DW_LNS_advance_line. - if (Temp >= Params.DWARF2LineRange || - Temp + Params.DWARF2LineOpcodeBase > 255) { - OS << char(dwarf::DW_LNS_advance_line); - encodeSLEB128(LineDelta, OS); - - LineDelta = 0; - Temp = 0 - Params.DWARF2LineBase; - NeedCopy = true; - } - - // Use DW_LNS_copy instead of a "line +0, addr +0" special opcode. - if (LineDelta == 0 && AddrDelta == 0) { - OS << char(dwarf::DW_LNS_copy); - return; - } - - // Bias the opcode by the special opcode base. - Temp += Params.DWARF2LineOpcodeBase; - - // Avoid overflow when addr_delta is large. - if (AddrDelta < 256 + MaxSpecialAddrDelta) { - // Try using a special opcode. - Opcode = Temp + AddrDelta * Params.DWARF2LineRange; - if (Opcode <= 255) { - OS << char(Opcode); - return; - } - - // Try using DW_LNS_const_add_pc followed by special op. - Opcode = Temp + (AddrDelta - MaxSpecialAddrDelta) * Params.DWARF2LineRange; - if (Opcode <= 255) { - OS << char(dwarf::DW_LNS_const_add_pc); - OS << char(Opcode); - return; - } - } - - // Otherwise use DW_LNS_advance_pc. - OS << char(dwarf::DW_LNS_advance_pc); - encodeULEB128(AddrDelta, OS); - - if (NeedCopy) - OS << char(dwarf::DW_LNS_copy); - else { - assert(Temp <= 255 && "Buggy special opcode encoding."); - OS << char(Temp); - } -} - -bool MCDwarfLineAddr::FixedEncode(MCContext &Context, - MCDwarfLineTableParams Params, - int64_t LineDelta, uint64_t AddrDelta, - raw_ostream &OS, - uint32_t *Offset, uint32_t *Size) { - if (LineDelta != INT64_MAX) { - OS << char(dwarf::DW_LNS_advance_line); - encodeSLEB128(LineDelta, OS); - } - - // Use address delta to adjust address or use absolute address to adjust - // address. - bool SetDelta; - // According to DWARF spec., the DW_LNS_fixed_advance_pc opcode takes a - // single uhalf (unencoded) operand. So, the maximum value of AddrDelta - // is 65535. We set a conservative upper bound for it for relaxation. - if (AddrDelta > 60000) { - const MCAsmInfo *asmInfo = Context.getAsmInfo(); - unsigned AddrSize = asmInfo->getCodePointerSize(); - - OS << char(dwarf::DW_LNS_extended_op); - encodeULEB128(1 + AddrSize, OS); - OS << char(dwarf::DW_LNE_set_address); - // Generate fixup for the address. - *Offset = OS.tell(); - *Size = AddrSize; - SetDelta = false; - std::vector<uint8_t> FillData; - FillData.insert(FillData.begin(), AddrSize, 0); - OS.write(reinterpret_cast<char *>(FillData.data()), AddrSize); - } else { - OS << char(dwarf::DW_LNS_fixed_advance_pc); - // Generate fixup for 2-bytes address delta. - *Offset = OS.tell(); - *Size = 2; - SetDelta = true; - OS << char(0); - OS << char(0); - } - - if (LineDelta == INT64_MAX) { - OS << char(dwarf::DW_LNS_extended_op); - OS << char(1); - OS << char(dwarf::DW_LNE_end_sequence); - } else { - OS << char(dwarf::DW_LNS_copy); - } - - return SetDelta; -} - -// Utility function to write a tuple for .debug_abbrev. -static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) { - MCOS->EmitULEB128IntValue(Name); - MCOS->EmitULEB128IntValue(Form); -} - -// When generating dwarf for assembly source files this emits -// the data for .debug_abbrev section which contains three DIEs. -static void EmitGenDwarfAbbrev(MCStreamer *MCOS) { - MCContext &context = MCOS->getContext(); - MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection()); - - // DW_TAG_compile_unit DIE abbrev (1). - MCOS->EmitULEB128IntValue(1); - MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit); - MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1); - EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, context.getDwarfVersion() >= 4 - ? dwarf::DW_FORM_sec_offset - : dwarf::DW_FORM_data4); - if (context.getGenDwarfSectionSyms().size() > 1 && - context.getDwarfVersion() >= 3) { - EmitAbbrev(MCOS, dwarf::DW_AT_ranges, context.getDwarfVersion() >= 4 - ? dwarf::DW_FORM_sec_offset - : dwarf::DW_FORM_data4); - } else { - EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); - EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr); - } - EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string); - if (!context.getCompilationDir().empty()) - EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string); - StringRef DwarfDebugFlags = context.getDwarfDebugFlags(); - if (!DwarfDebugFlags.empty()) - EmitAbbrev(MCOS, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string); - EmitAbbrev(MCOS, dwarf::DW_AT_producer, dwarf::DW_FORM_string); - EmitAbbrev(MCOS, dwarf::DW_AT_language, dwarf::DW_FORM_data2); - EmitAbbrev(MCOS, 0, 0); - - // DW_TAG_label DIE abbrev (2). - MCOS->EmitULEB128IntValue(2); - MCOS->EmitULEB128IntValue(dwarf::DW_TAG_label); - MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1); - EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string); - EmitAbbrev(MCOS, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data4); - EmitAbbrev(MCOS, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data4); - EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); - EmitAbbrev(MCOS, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag); - EmitAbbrev(MCOS, 0, 0); - - // DW_TAG_unspecified_parameters DIE abbrev (3). - MCOS->EmitULEB128IntValue(3); - MCOS->EmitULEB128IntValue(dwarf::DW_TAG_unspecified_parameters); - MCOS->EmitIntValue(dwarf::DW_CHILDREN_no, 1); - EmitAbbrev(MCOS, 0, 0); - - // Terminate the abbreviations for this compilation unit. - MCOS->EmitIntValue(0, 1); -} - -// When generating dwarf for assembly source files this emits the data for -// .debug_aranges section. This section contains a header and a table of pairs -// of PointerSize'ed values for the address and size of section(s) with line -// table entries. -static void EmitGenDwarfAranges(MCStreamer *MCOS, - const MCSymbol *InfoSectionSymbol) { - MCContext &context = MCOS->getContext(); - - auto &Sections = context.getGenDwarfSectionSyms(); - - MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); - - // This will be the length of the .debug_aranges section, first account for - // the size of each item in the header (see below where we emit these items). - int Length = 4 + 2 + 4 + 1 + 1; - - // Figure the padding after the header before the table of address and size - // pairs who's values are PointerSize'ed. - const MCAsmInfo *asmInfo = context.getAsmInfo(); - int AddrSize = asmInfo->getCodePointerSize(); - int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1)); - if (Pad == 2 * AddrSize) - Pad = 0; - Length += Pad; - - // Add the size of the pair of PointerSize'ed values for the address and size - // of each section we have in the table. - Length += 2 * AddrSize * Sections.size(); - // And the pair of terminating zeros. - Length += 2 * AddrSize; - - // Emit the header for this section. - // The 4 byte length not including the 4 byte value for the length. - MCOS->EmitIntValue(Length - 4, 4); - // The 2 byte version, which is 2. - MCOS->EmitIntValue(2, 2); - // The 4 byte offset to the compile unit in the .debug_info from the start - // of the .debug_info. - if (InfoSectionSymbol) - MCOS->EmitSymbolValue(InfoSectionSymbol, 4, - asmInfo->needsDwarfSectionOffsetDirective()); - else - MCOS->EmitIntValue(0, 4); - // The 1 byte size of an address. - MCOS->EmitIntValue(AddrSize, 1); - // The 1 byte size of a segment descriptor, we use a value of zero. - MCOS->EmitIntValue(0, 1); - // Align the header with the padding if needed, before we put out the table. - for(int i = 0; i < Pad; i++) - MCOS->EmitIntValue(0, 1); - - // Now emit the table of pairs of PointerSize'ed values for the section - // addresses and sizes. - for (MCSection *Sec : Sections) { - const MCSymbol *StartSymbol = Sec->getBeginSymbol(); - MCSymbol *EndSymbol = Sec->getEndSymbol(context); - assert(StartSymbol && "StartSymbol must not be NULL"); - assert(EndSymbol && "EndSymbol must not be NULL"); - - const MCExpr *Addr = MCSymbolRefExpr::create( - StartSymbol, MCSymbolRefExpr::VK_None, context); - const MCExpr *Size = MakeStartMinusEndExpr(*MCOS, - *StartSymbol, *EndSymbol, 0); - MCOS->EmitValue(Addr, AddrSize); - emitAbsValue(*MCOS, Size, AddrSize); - } - - // And finally the pair of terminating zeros. - MCOS->EmitIntValue(0, AddrSize); - MCOS->EmitIntValue(0, AddrSize); -} - -// When generating dwarf for assembly source files this emits the data for -// .debug_info section which contains three parts. The header, the compile_unit -// DIE and a list of label DIEs. -static void EmitGenDwarfInfo(MCStreamer *MCOS, - const MCSymbol *AbbrevSectionSymbol, - const MCSymbol *LineSectionSymbol, - const MCSymbol *RangesSectionSymbol) { - MCContext &context = MCOS->getContext(); - - MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); - - // Create a symbol at the start and end of this section used in here for the - // expression to calculate the length in the header. - MCSymbol *InfoStart = context.createTempSymbol(); - MCOS->EmitLabel(InfoStart); - MCSymbol *InfoEnd = context.createTempSymbol(); - - // First part: the header. - - // The 4 byte total length of the information for this compilation unit, not - // including these 4 bytes. - const MCExpr *Length = MakeStartMinusEndExpr(*MCOS, *InfoStart, *InfoEnd, 4); - emitAbsValue(*MCOS, Length, 4); - - // The 2 byte DWARF version. - MCOS->EmitIntValue(context.getDwarfVersion(), 2); - - // The DWARF v5 header has unit type, address size, abbrev offset. - // Earlier versions have abbrev offset, address size. - const MCAsmInfo &AsmInfo = *context.getAsmInfo(); - int AddrSize = AsmInfo.getCodePointerSize(); - if (context.getDwarfVersion() >= 5) { - MCOS->EmitIntValue(dwarf::DW_UT_compile, 1); - MCOS->EmitIntValue(AddrSize, 1); - } - // The 4 byte offset to the debug abbrevs from the start of the .debug_abbrev, - // it is at the start of that section so this is zero. - if (AbbrevSectionSymbol == nullptr) - MCOS->EmitIntValue(0, 4); - else - MCOS->EmitSymbolValue(AbbrevSectionSymbol, 4, - AsmInfo.needsDwarfSectionOffsetDirective()); - if (context.getDwarfVersion() <= 4) - MCOS->EmitIntValue(AddrSize, 1); - - // Second part: the compile_unit DIE. - - // The DW_TAG_compile_unit DIE abbrev (1). - MCOS->EmitULEB128IntValue(1); - - // DW_AT_stmt_list, a 4 byte offset from the start of the .debug_line section, - // which is at the start of that section so this is zero. - if (LineSectionSymbol) - MCOS->EmitSymbolValue(LineSectionSymbol, 4, - AsmInfo.needsDwarfSectionOffsetDirective()); - else - MCOS->EmitIntValue(0, 4); - - if (RangesSectionSymbol) { - // There are multiple sections containing code, so we must use the - // .debug_ranges sections. - - // AT_ranges, the 4 byte offset from the start of the .debug_ranges section - // to the address range list for this compilation unit. - MCOS->EmitSymbolValue(RangesSectionSymbol, 4); - } else { - // If we only have one non-empty code section, we can use the simpler - // AT_low_pc and AT_high_pc attributes. - - // Find the first (and only) non-empty text section - auto &Sections = context.getGenDwarfSectionSyms(); - const auto TextSection = Sections.begin(); - assert(TextSection != Sections.end() && "No text section found"); - - MCSymbol *StartSymbol = (*TextSection)->getBeginSymbol(); - MCSymbol *EndSymbol = (*TextSection)->getEndSymbol(context); - assert(StartSymbol && "StartSymbol must not be NULL"); - assert(EndSymbol && "EndSymbol must not be NULL"); - - // AT_low_pc, the first address of the default .text section. - const MCExpr *Start = MCSymbolRefExpr::create( - StartSymbol, MCSymbolRefExpr::VK_None, context); - MCOS->EmitValue(Start, AddrSize); - - // AT_high_pc, the last address of the default .text section. - const MCExpr *End = MCSymbolRefExpr::create( - EndSymbol, MCSymbolRefExpr::VK_None, context); - MCOS->EmitValue(End, AddrSize); - } - - // AT_name, the name of the source file. Reconstruct from the first directory - // and file table entries. - const SmallVectorImpl<std::string> &MCDwarfDirs = context.getMCDwarfDirs(); - if (MCDwarfDirs.size() > 0) { - MCOS->EmitBytes(MCDwarfDirs[0]); - MCOS->EmitBytes(sys::path::get_separator()); - } - const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles = - MCOS->getContext().getMCDwarfFiles(); - MCOS->EmitBytes(MCDwarfFiles[1].Name); - MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. - - // AT_comp_dir, the working directory the assembly was done in. - if (!context.getCompilationDir().empty()) { - MCOS->EmitBytes(context.getCompilationDir()); - MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. - } - - // AT_APPLE_flags, the command line arguments of the assembler tool. - StringRef DwarfDebugFlags = context.getDwarfDebugFlags(); - if (!DwarfDebugFlags.empty()){ - MCOS->EmitBytes(DwarfDebugFlags); - MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. - } - - // AT_producer, the version of the assembler tool. - StringRef DwarfDebugProducer = context.getDwarfDebugProducer(); - if (!DwarfDebugProducer.empty()) - MCOS->EmitBytes(DwarfDebugProducer); - else - MCOS->EmitBytes(StringRef("llvm-mc (based on LLVM " PACKAGE_VERSION ")")); - MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. - - // AT_language, a 4 byte value. We use DW_LANG_Mips_Assembler as the dwarf2 - // draft has no standard code for assembler. - MCOS->EmitIntValue(dwarf::DW_LANG_Mips_Assembler, 2); - - // Third part: the list of label DIEs. - - // Loop on saved info for dwarf labels and create the DIEs for them. - const std::vector<MCGenDwarfLabelEntry> &Entries = - MCOS->getContext().getMCGenDwarfLabelEntries(); - for (const auto &Entry : Entries) { - // The DW_TAG_label DIE abbrev (2). - MCOS->EmitULEB128IntValue(2); - - // AT_name, of the label without any leading underbar. - MCOS->EmitBytes(Entry.getName()); - MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. - - // AT_decl_file, index into the file table. - MCOS->EmitIntValue(Entry.getFileNumber(), 4); - - // AT_decl_line, source line number. - MCOS->EmitIntValue(Entry.getLineNumber(), 4); - - // AT_low_pc, start address of the label. - const MCExpr *AT_low_pc = MCSymbolRefExpr::create(Entry.getLabel(), - MCSymbolRefExpr::VK_None, context); - MCOS->EmitValue(AT_low_pc, AddrSize); - - // DW_AT_prototyped, a one byte flag value of 0 saying we have no prototype. - MCOS->EmitIntValue(0, 1); - - // The DW_TAG_unspecified_parameters DIE abbrev (3). - MCOS->EmitULEB128IntValue(3); - - // Add the NULL DIE terminating the DW_TAG_unspecified_parameters DIE's. - MCOS->EmitIntValue(0, 1); - } - - // Add the NULL DIE terminating the Compile Unit DIE's. - MCOS->EmitIntValue(0, 1); - - // Now set the value of the symbol at the end of the info section. - MCOS->EmitLabel(InfoEnd); -} - -// When generating dwarf for assembly source files this emits the data for -// .debug_ranges section. We only emit one range list, which spans all of the -// executable sections of this file. -static void EmitGenDwarfRanges(MCStreamer *MCOS) { - MCContext &context = MCOS->getContext(); - auto &Sections = context.getGenDwarfSectionSyms(); - - const MCAsmInfo *AsmInfo = context.getAsmInfo(); - int AddrSize = AsmInfo->getCodePointerSize(); - - MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection()); - - for (MCSection *Sec : Sections) { - const MCSymbol *StartSymbol = Sec->getBeginSymbol(); - MCSymbol *EndSymbol = Sec->getEndSymbol(context); - assert(StartSymbol && "StartSymbol must not be NULL"); - assert(EndSymbol && "EndSymbol must not be NULL"); - - // Emit a base address selection entry for the start of this section - const MCExpr *SectionStartAddr = MCSymbolRefExpr::create( - StartSymbol, MCSymbolRefExpr::VK_None, context); - MCOS->emitFill(AddrSize, 0xFF); - MCOS->EmitValue(SectionStartAddr, AddrSize); - - // Emit a range list entry spanning this section - const MCExpr *SectionSize = MakeStartMinusEndExpr(*MCOS, - *StartSymbol, *EndSymbol, 0); - MCOS->EmitIntValue(0, AddrSize); - emitAbsValue(*MCOS, SectionSize, AddrSize); - } - - // Emit end of list entry - MCOS->EmitIntValue(0, AddrSize); - MCOS->EmitIntValue(0, AddrSize); -} - -// -// When generating dwarf for assembly source files this emits the Dwarf -// sections. -// -void MCGenDwarfInfo::Emit(MCStreamer *MCOS) { - MCContext &context = MCOS->getContext(); - - // Create the dwarf sections in this order (.debug_line already created). - const MCAsmInfo *AsmInfo = context.getAsmInfo(); - bool CreateDwarfSectionSymbols = - AsmInfo->doesDwarfUseRelocationsAcrossSections(); - MCSymbol *LineSectionSymbol = nullptr; - if (CreateDwarfSectionSymbols) - LineSectionSymbol = MCOS->getDwarfLineTableSymbol(0); - MCSymbol *AbbrevSectionSymbol = nullptr; - MCSymbol *InfoSectionSymbol = nullptr; - MCSymbol *RangesSectionSymbol = nullptr; - - // Create end symbols for each section, and remove empty sections - MCOS->getContext().finalizeDwarfSections(*MCOS); - - // If there are no sections to generate debug info for, we don't need - // to do anything - if (MCOS->getContext().getGenDwarfSectionSyms().empty()) - return; - - // We only use the .debug_ranges section if we have multiple code sections, - // and we are emitting a DWARF version which supports it. - const bool UseRangesSection = - MCOS->getContext().getGenDwarfSectionSyms().size() > 1 && - MCOS->getContext().getDwarfVersion() >= 3; - CreateDwarfSectionSymbols |= UseRangesSection; - - MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); - if (CreateDwarfSectionSymbols) { - InfoSectionSymbol = context.createTempSymbol(); - MCOS->EmitLabel(InfoSectionSymbol); - } - MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection()); - if (CreateDwarfSectionSymbols) { - AbbrevSectionSymbol = context.createTempSymbol(); - MCOS->EmitLabel(AbbrevSectionSymbol); - } - if (UseRangesSection) { - MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection()); - if (CreateDwarfSectionSymbols) { - RangesSectionSymbol = context.createTempSymbol(); - MCOS->EmitLabel(RangesSectionSymbol); - } - } - - assert((RangesSectionSymbol != nullptr) || !UseRangesSection); - - MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); - - // Output the data for .debug_aranges section. - EmitGenDwarfAranges(MCOS, InfoSectionSymbol); - - if (UseRangesSection) - EmitGenDwarfRanges(MCOS); - - // Output the data for .debug_abbrev section. - EmitGenDwarfAbbrev(MCOS); - - // Output the data for .debug_info section. - EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol, - RangesSectionSymbol); -} - -// -// When generating dwarf for assembly source files this is called when symbol -// for a label is created. If this symbol is not a temporary and is in the -// section that dwarf is being generated for, save the needed info to create -// a dwarf label. -// -void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS, - SourceMgr &SrcMgr, SMLoc &Loc) { - // We won't create dwarf labels for temporary symbols. - if (Symbol->isTemporary()) - return; - MCContext &context = MCOS->getContext(); - // We won't create dwarf labels for symbols in sections that we are not - // generating debug info for. - if (!context.getGenDwarfSectionSyms().count(MCOS->getCurrentSectionOnly())) - return; - - // The dwarf label's name does not have the symbol name's leading - // underbar if any. - StringRef Name = Symbol->getName(); - if (Name.startswith("_")) - Name = Name.substr(1, Name.size()-1); - - // Get the dwarf file number to be used for the dwarf label. - unsigned FileNumber = context.getGenDwarfFileNumber(); - - // Finding the line number is the expensive part which is why we just don't - // pass it in as for some symbols we won't create a dwarf label. - unsigned CurBuffer = SrcMgr.FindBufferContainingLoc(Loc); - unsigned LineNumber = SrcMgr.FindLineNumber(Loc, CurBuffer); - - // We create a temporary symbol for use for the AT_high_pc and AT_low_pc - // values so that they don't have things like an ARM thumb bit from the - // original symbol. So when used they won't get a low bit set after - // relocation. - MCSymbol *Label = context.createTempSymbol(); - MCOS->EmitLabel(Label); - - // Create and entry for the info and add it to the other entries. - MCOS->getContext().addMCGenDwarfLabelEntry( - MCGenDwarfLabelEntry(Name, FileNumber, LineNumber, Label)); -} - -static int getDataAlignmentFactor(MCStreamer &streamer) { - MCContext &context = streamer.getContext(); - const MCAsmInfo *asmInfo = context.getAsmInfo(); - int size = asmInfo->getCalleeSaveStackSlotSize(); - if (asmInfo->isStackGrowthDirectionUp()) - return size; - else - return -size; -} - -static unsigned getSizeForEncoding(MCStreamer &streamer, - unsigned symbolEncoding) { - MCContext &context = streamer.getContext(); - unsigned format = symbolEncoding & 0x0f; - switch (format) { - default: llvm_unreachable("Unknown Encoding"); - case dwarf::DW_EH_PE_absptr: - case dwarf::DW_EH_PE_signed: - return context.getAsmInfo()->getCodePointerSize(); - case dwarf::DW_EH_PE_udata2: - case dwarf::DW_EH_PE_sdata2: - return 2; - case dwarf::DW_EH_PE_udata4: - case dwarf::DW_EH_PE_sdata4: - return 4; - case dwarf::DW_EH_PE_udata8: - case dwarf::DW_EH_PE_sdata8: - return 8; - } -} - -static void emitFDESymbol(MCObjectStreamer &streamer, const MCSymbol &symbol, - unsigned symbolEncoding, bool isEH) { - MCContext &context = streamer.getContext(); - const MCAsmInfo *asmInfo = context.getAsmInfo(); - const MCExpr *v = asmInfo->getExprForFDESymbol(&symbol, - symbolEncoding, - streamer); - unsigned size = getSizeForEncoding(streamer, symbolEncoding); - if (asmInfo->doDwarfFDESymbolsUseAbsDiff() && isEH) - emitAbsValue(streamer, v, size); - else - streamer.EmitValue(v, size); -} - -static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol, - unsigned symbolEncoding) { - MCContext &context = streamer.getContext(); - const MCAsmInfo *asmInfo = context.getAsmInfo(); - const MCExpr *v = asmInfo->getExprForPersonalitySymbol(&symbol, - symbolEncoding, - streamer); - unsigned size = getSizeForEncoding(streamer, symbolEncoding); - streamer.EmitValue(v, size); -} - -namespace { - -class FrameEmitterImpl { - int CFAOffset = 0; - int InitialCFAOffset = 0; - bool IsEH; - MCObjectStreamer &Streamer; - -public: - FrameEmitterImpl(bool IsEH, MCObjectStreamer &Streamer) - : IsEH(IsEH), Streamer(Streamer) {} - - /// Emit the unwind information in a compact way. - void EmitCompactUnwind(const MCDwarfFrameInfo &frame); - - const MCSymbol &EmitCIE(const MCDwarfFrameInfo &F); - void EmitFDE(const MCSymbol &cieStart, const MCDwarfFrameInfo &frame, - bool LastInSection, const MCSymbol &SectionStart); - void EmitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs, - MCSymbol *BaseLabel); - void EmitCFIInstruction(const MCCFIInstruction &Instr); -}; - -} // end anonymous namespace - -static void emitEncodingByte(MCObjectStreamer &Streamer, unsigned Encoding) { - Streamer.EmitIntValue(Encoding, 1); -} - -void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) { - int dataAlignmentFactor = getDataAlignmentFactor(Streamer); - auto *MRI = Streamer.getContext().getRegisterInfo(); - - switch (Instr.getOperation()) { - case MCCFIInstruction::OpRegister: { - unsigned Reg1 = Instr.getRegister(); - unsigned Reg2 = Instr.getRegister2(); - if (!IsEH) { - Reg1 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg1); - Reg2 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg2); - } - Streamer.EmitIntValue(dwarf::DW_CFA_register, 1); - Streamer.EmitULEB128IntValue(Reg1); - Streamer.EmitULEB128IntValue(Reg2); - return; - } - case MCCFIInstruction::OpWindowSave: - Streamer.EmitIntValue(dwarf::DW_CFA_GNU_window_save, 1); - return; - - case MCCFIInstruction::OpNegateRAState: - Streamer.EmitIntValue(dwarf::DW_CFA_AARCH64_negate_ra_state, 1); - return; - - case MCCFIInstruction::OpUndefined: { - unsigned Reg = Instr.getRegister(); - Streamer.EmitIntValue(dwarf::DW_CFA_undefined, 1); - Streamer.EmitULEB128IntValue(Reg); - return; - } - case MCCFIInstruction::OpAdjustCfaOffset: - case MCCFIInstruction::OpDefCfaOffset: { - const bool IsRelative = - Instr.getOperation() == MCCFIInstruction::OpAdjustCfaOffset; - - Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1); - - if (IsRelative) - CFAOffset += Instr.getOffset(); - else - CFAOffset = -Instr.getOffset(); - - Streamer.EmitULEB128IntValue(CFAOffset); - - return; - } - case MCCFIInstruction::OpDefCfa: { - unsigned Reg = Instr.getRegister(); - if (!IsEH) - Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg); - Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1); - Streamer.EmitULEB128IntValue(Reg); - CFAOffset = -Instr.getOffset(); - Streamer.EmitULEB128IntValue(CFAOffset); - - return; - } - case MCCFIInstruction::OpDefCfaRegister: { - unsigned Reg = Instr.getRegister(); - if (!IsEH) - Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg); - Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1); - Streamer.EmitULEB128IntValue(Reg); - - return; - } - case MCCFIInstruction::OpOffset: - case MCCFIInstruction::OpRelOffset: { - const bool IsRelative = - Instr.getOperation() == MCCFIInstruction::OpRelOffset; - - unsigned Reg = Instr.getRegister(); - if (!IsEH) - Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg); - - int Offset = Instr.getOffset(); - if (IsRelative) - Offset -= CFAOffset; - Offset = Offset / dataAlignmentFactor; - - if (Offset < 0) { - Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1); - Streamer.EmitULEB128IntValue(Reg); - Streamer.EmitSLEB128IntValue(Offset); - } else if (Reg < 64) { - Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1); - Streamer.EmitULEB128IntValue(Offset); - } else { - Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1); - Streamer.EmitULEB128IntValue(Reg); - Streamer.EmitULEB128IntValue(Offset); - } - return; - } - case MCCFIInstruction::OpRememberState: - Streamer.EmitIntValue(dwarf::DW_CFA_remember_state, 1); - return; - case MCCFIInstruction::OpRestoreState: - Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1); - return; - case MCCFIInstruction::OpSameValue: { - unsigned Reg = Instr.getRegister(); - Streamer.EmitIntValue(dwarf::DW_CFA_same_value, 1); - Streamer.EmitULEB128IntValue(Reg); - return; - } - case MCCFIInstruction::OpRestore: { - unsigned Reg = Instr.getRegister(); - if (!IsEH) - Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg); - if (Reg < 64) { - Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1); - } else { - Streamer.EmitIntValue(dwarf::DW_CFA_restore_extended, 1); - Streamer.EmitULEB128IntValue(Reg); - } - return; - } - case MCCFIInstruction::OpGnuArgsSize: - Streamer.EmitIntValue(dwarf::DW_CFA_GNU_args_size, 1); - Streamer.EmitULEB128IntValue(Instr.getOffset()); - return; - - case MCCFIInstruction::OpEscape: - Streamer.EmitBytes(Instr.getValues()); - return; - } - llvm_unreachable("Unhandled case in switch"); -} - -/// Emit frame instructions to describe the layout of the frame. -void FrameEmitterImpl::EmitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs, - MCSymbol *BaseLabel) { - for (const MCCFIInstruction &Instr : Instrs) { - MCSymbol *Label = Instr.getLabel(); - // Throw out move if the label is invalid. - if (Label && !Label->isDefined()) continue; // Not emitted, in dead code. - - // Advance row if new location. - if (BaseLabel && Label) { - MCSymbol *ThisSym = Label; - if (ThisSym != BaseLabel) { - Streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym); - BaseLabel = ThisSym; - } - } - - EmitCFIInstruction(Instr); - } -} - -/// Emit the unwind information in a compact way. -void FrameEmitterImpl::EmitCompactUnwind(const MCDwarfFrameInfo &Frame) { - MCContext &Context = Streamer.getContext(); - const MCObjectFileInfo *MOFI = Context.getObjectFileInfo(); - - // range-start range-length compact-unwind-enc personality-func lsda - // _foo LfooEnd-_foo 0x00000023 0 0 - // _bar LbarEnd-_bar 0x00000025 __gxx_personality except_tab1 - // - // .section __LD,__compact_unwind,regular,debug - // - // # compact unwind for _foo - // .quad _foo - // .set L1,LfooEnd-_foo - // .long L1 - // .long 0x01010001 - // .quad 0 - // .quad 0 - // - // # compact unwind for _bar - // .quad _bar - // .set L2,LbarEnd-_bar - // .long L2 - // .long 0x01020011 - // .quad __gxx_personality - // .quad except_tab1 - - uint32_t Encoding = Frame.CompactUnwindEncoding; - if (!Encoding) return; - bool DwarfEHFrameOnly = (Encoding == MOFI->getCompactUnwindDwarfEHFrameOnly()); - - // The encoding needs to know we have an LSDA. - if (!DwarfEHFrameOnly && Frame.Lsda) - Encoding |= 0x40000000; - - // Range Start - unsigned FDEEncoding = MOFI->getFDEEncoding(); - unsigned Size = getSizeForEncoding(Streamer, FDEEncoding); - Streamer.EmitSymbolValue(Frame.Begin, Size); - - // Range Length - const MCExpr *Range = MakeStartMinusEndExpr(Streamer, *Frame.Begin, - *Frame.End, 0); - emitAbsValue(Streamer, Range, 4); - - // Compact Encoding - Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4); - Streamer.EmitIntValue(Encoding, Size); - - // Personality Function - Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_absptr); - if (!DwarfEHFrameOnly && Frame.Personality) - Streamer.EmitSymbolValue(Frame.Personality, Size); - else - Streamer.EmitIntValue(0, Size); // No personality fn - - // LSDA - Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding); - if (!DwarfEHFrameOnly && Frame.Lsda) - Streamer.EmitSymbolValue(Frame.Lsda, Size); - else - Streamer.EmitIntValue(0, Size); // No LSDA -} - -static unsigned getCIEVersion(bool IsEH, unsigned DwarfVersion) { - if (IsEH) - return 1; - switch (DwarfVersion) { - case 2: - return 1; - case 3: - return 3; - case 4: - case 5: - return 4; - } - llvm_unreachable("Unknown version"); -} - -const MCSymbol &FrameEmitterImpl::EmitCIE(const MCDwarfFrameInfo &Frame) { - MCContext &context = Streamer.getContext(); - const MCRegisterInfo *MRI = context.getRegisterInfo(); - const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); - - MCSymbol *sectionStart = context.createTempSymbol(); - Streamer.EmitLabel(sectionStart); - - MCSymbol *sectionEnd = context.createTempSymbol(); - - // Length - const MCExpr *Length = - MakeStartMinusEndExpr(Streamer, *sectionStart, *sectionEnd, 4); - emitAbsValue(Streamer, Length, 4); - - // CIE ID - unsigned CIE_ID = IsEH ? 0 : -1; - Streamer.EmitIntValue(CIE_ID, 4); - - // Version - uint8_t CIEVersion = getCIEVersion(IsEH, context.getDwarfVersion()); - Streamer.EmitIntValue(CIEVersion, 1); - - if (IsEH) { - SmallString<8> Augmentation; - Augmentation += "z"; - if (Frame.Personality) - Augmentation += "P"; - if (Frame.Lsda) - Augmentation += "L"; - Augmentation += "R"; - if (Frame.IsSignalFrame) - Augmentation += "S"; - if (Frame.IsBKeyFrame) - Augmentation += "B"; - Streamer.EmitBytes(Augmentation); - } - Streamer.EmitIntValue(0, 1); - - if (CIEVersion >= 4) { - // Address Size - Streamer.EmitIntValue(context.getAsmInfo()->getCodePointerSize(), 1); - - // Segment Descriptor Size - Streamer.EmitIntValue(0, 1); - } - - // Code Alignment Factor - Streamer.EmitULEB128IntValue(context.getAsmInfo()->getMinInstAlignment()); - - // Data Alignment Factor - Streamer.EmitSLEB128IntValue(getDataAlignmentFactor(Streamer)); - - // Return Address Register - unsigned RAReg = Frame.RAReg; - if (RAReg == static_cast<unsigned>(INT_MAX)) - RAReg = MRI->getDwarfRegNum(MRI->getRARegister(), IsEH); - - if (CIEVersion == 1) { - assert(RAReg <= 255 && - "DWARF 2 encodes return_address_register in one byte"); - Streamer.EmitIntValue(RAReg, 1); - } else { - Streamer.EmitULEB128IntValue(RAReg); - } - - // Augmentation Data Length (optional) - unsigned augmentationLength = 0; - if (IsEH) { - if (Frame.Personality) { - // Personality Encoding - augmentationLength += 1; - // Personality - augmentationLength += - getSizeForEncoding(Streamer, Frame.PersonalityEncoding); - } - if (Frame.Lsda) - augmentationLength += 1; - // Encoding of the FDE pointers - augmentationLength += 1; - - Streamer.EmitULEB128IntValue(augmentationLength); - - // Augmentation Data (optional) - if (Frame.Personality) { - // Personality Encoding - emitEncodingByte(Streamer, Frame.PersonalityEncoding); - // Personality - EmitPersonality(Streamer, *Frame.Personality, Frame.PersonalityEncoding); - } - - if (Frame.Lsda) - emitEncodingByte(Streamer, Frame.LsdaEncoding); - - // Encoding of the FDE pointers - emitEncodingByte(Streamer, MOFI->getFDEEncoding()); - } - - // Initial Instructions - - const MCAsmInfo *MAI = context.getAsmInfo(); - if (!Frame.IsSimple) { - const std::vector<MCCFIInstruction> &Instructions = - MAI->getInitialFrameState(); - EmitCFIInstructions(Instructions, nullptr); - } - - InitialCFAOffset = CFAOffset; - - // Padding - Streamer.EmitValueToAlignment(IsEH ? 4 : MAI->getCodePointerSize()); - - Streamer.EmitLabel(sectionEnd); - return *sectionStart; -} - -void FrameEmitterImpl::EmitFDE(const MCSymbol &cieStart, - const MCDwarfFrameInfo &frame, - bool LastInSection, - const MCSymbol &SectionStart) { - MCContext &context = Streamer.getContext(); - MCSymbol *fdeStart = context.createTempSymbol(); - MCSymbol *fdeEnd = context.createTempSymbol(); - const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); - - CFAOffset = InitialCFAOffset; - - // Length - const MCExpr *Length = MakeStartMinusEndExpr(Streamer, *fdeStart, *fdeEnd, 0); - emitAbsValue(Streamer, Length, 4); - - Streamer.EmitLabel(fdeStart); - - // CIE Pointer - const MCAsmInfo *asmInfo = context.getAsmInfo(); - if (IsEH) { - const MCExpr *offset = - MakeStartMinusEndExpr(Streamer, cieStart, *fdeStart, 0); - emitAbsValue(Streamer, offset, 4); - } else if (!asmInfo->doesDwarfUseRelocationsAcrossSections()) { - const MCExpr *offset = - MakeStartMinusEndExpr(Streamer, SectionStart, cieStart, 0); - emitAbsValue(Streamer, offset, 4); - } else { - Streamer.EmitSymbolValue(&cieStart, 4); - } - - // PC Begin - unsigned PCEncoding = - IsEH ? MOFI->getFDEEncoding() : (unsigned)dwarf::DW_EH_PE_absptr; - unsigned PCSize = getSizeForEncoding(Streamer, PCEncoding); - emitFDESymbol(Streamer, *frame.Begin, PCEncoding, IsEH); - - // PC Range - const MCExpr *Range = - MakeStartMinusEndExpr(Streamer, *frame.Begin, *frame.End, 0); - emitAbsValue(Streamer, Range, PCSize); - - if (IsEH) { - // Augmentation Data Length - unsigned augmentationLength = 0; - - if (frame.Lsda) - augmentationLength += getSizeForEncoding(Streamer, frame.LsdaEncoding); - - Streamer.EmitULEB128IntValue(augmentationLength); - - // Augmentation Data - if (frame.Lsda) - emitFDESymbol(Streamer, *frame.Lsda, frame.LsdaEncoding, true); - } - - // Call Frame Instructions - EmitCFIInstructions(frame.Instructions, frame.Begin); - - // Padding - // The size of a .eh_frame section has to be a multiple of the alignment - // since a null CIE is interpreted as the end. Old systems overaligned - // .eh_frame, so we do too and account for it in the last FDE. - unsigned Align = LastInSection ? asmInfo->getCodePointerSize() : PCSize; - Streamer.EmitValueToAlignment(Align); - - Streamer.EmitLabel(fdeEnd); -} - -namespace { - -struct CIEKey { - static const CIEKey getEmptyKey() { - return CIEKey(nullptr, 0, -1, false, false, static_cast<unsigned>(INT_MAX), - false); - } - - static const CIEKey getTombstoneKey() { - return CIEKey(nullptr, -1, 0, false, false, static_cast<unsigned>(INT_MAX), - false); - } - - CIEKey(const MCSymbol *Personality, unsigned PersonalityEncoding, - unsigned LSDAEncoding, bool IsSignalFrame, bool IsSimple, - unsigned RAReg, bool IsBKeyFrame) - : Personality(Personality), PersonalityEncoding(PersonalityEncoding), - LsdaEncoding(LSDAEncoding), IsSignalFrame(IsSignalFrame), - IsSimple(IsSimple), RAReg(RAReg), IsBKeyFrame(IsBKeyFrame) {} - - explicit CIEKey(const MCDwarfFrameInfo &Frame) - : Personality(Frame.Personality), - PersonalityEncoding(Frame.PersonalityEncoding), - LsdaEncoding(Frame.LsdaEncoding), IsSignalFrame(Frame.IsSignalFrame), - IsSimple(Frame.IsSimple), RAReg(Frame.RAReg), - IsBKeyFrame(Frame.IsBKeyFrame) {} - - const MCSymbol *Personality; - unsigned PersonalityEncoding; - unsigned LsdaEncoding; - bool IsSignalFrame; - bool IsSimple; - unsigned RAReg; - bool IsBKeyFrame; -}; - -} // end anonymous namespace - -namespace llvm { - -template <> struct DenseMapInfo<CIEKey> { - static CIEKey getEmptyKey() { return CIEKey::getEmptyKey(); } - static CIEKey getTombstoneKey() { return CIEKey::getTombstoneKey(); } - - static unsigned getHashValue(const CIEKey &Key) { - return static_cast<unsigned>(hash_combine( - Key.Personality, Key.PersonalityEncoding, Key.LsdaEncoding, - Key.IsSignalFrame, Key.IsSimple, Key.RAReg, Key.IsBKeyFrame)); - } - - static bool isEqual(const CIEKey &LHS, const CIEKey &RHS) { - return LHS.Personality == RHS.Personality && - LHS.PersonalityEncoding == RHS.PersonalityEncoding && - LHS.LsdaEncoding == RHS.LsdaEncoding && - LHS.IsSignalFrame == RHS.IsSignalFrame && - LHS.IsSimple == RHS.IsSimple && LHS.RAReg == RHS.RAReg && - LHS.IsBKeyFrame == RHS.IsBKeyFrame; - } -}; - -} // end namespace llvm - -void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB, - bool IsEH) { - Streamer.generateCompactUnwindEncodings(MAB); - - MCContext &Context = Streamer.getContext(); - const MCObjectFileInfo *MOFI = Context.getObjectFileInfo(); - const MCAsmInfo *AsmInfo = Context.getAsmInfo(); - FrameEmitterImpl Emitter(IsEH, Streamer); - ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getDwarfFrameInfos(); - - // Emit the compact unwind info if available. - bool NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame(); - if (IsEH && MOFI->getCompactUnwindSection()) { - bool SectionEmitted = false; - for (const MCDwarfFrameInfo &Frame : FrameArray) { - if (Frame.CompactUnwindEncoding == 0) continue; - if (!SectionEmitted) { - Streamer.SwitchSection(MOFI->getCompactUnwindSection()); - Streamer.EmitValueToAlignment(AsmInfo->getCodePointerSize()); - SectionEmitted = true; - } - NeedsEHFrameSection |= - Frame.CompactUnwindEncoding == - MOFI->getCompactUnwindDwarfEHFrameOnly(); - Emitter.EmitCompactUnwind(Frame); - } - } - - if (!NeedsEHFrameSection) return; - - MCSection &Section = - IsEH ? *const_cast<MCObjectFileInfo *>(MOFI)->getEHFrameSection() - : *MOFI->getDwarfFrameSection(); - - Streamer.SwitchSection(&Section); - MCSymbol *SectionStart = Context.createTempSymbol(); - Streamer.EmitLabel(SectionStart); - - DenseMap<CIEKey, const MCSymbol *> CIEStarts; - - const MCSymbol *DummyDebugKey = nullptr; - bool CanOmitDwarf = MOFI->getOmitDwarfIfHaveCompactUnwind(); - for (auto I = FrameArray.begin(), E = FrameArray.end(); I != E;) { - const MCDwarfFrameInfo &Frame = *I; - ++I; - if (CanOmitDwarf && Frame.CompactUnwindEncoding != - MOFI->getCompactUnwindDwarfEHFrameOnly()) - // Don't generate an EH frame if we don't need one. I.e., it's taken care - // of by the compact unwind encoding. - continue; - - CIEKey Key(Frame); - const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey; - if (!CIEStart) - CIEStart = &Emitter.EmitCIE(Frame); - - Emitter.EmitFDE(*CIEStart, Frame, I == E, *SectionStart); - } -} - -void MCDwarfFrameEmitter::EmitAdvanceLoc(MCObjectStreamer &Streamer, - uint64_t AddrDelta) { - MCContext &Context = Streamer.getContext(); - SmallString<256> Tmp; - raw_svector_ostream OS(Tmp); - MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OS); - Streamer.EmitBytes(OS.str()); -} - -void MCDwarfFrameEmitter::EncodeAdvanceLoc(MCContext &Context, - uint64_t AddrDelta, - raw_ostream &OS) { - // Scale the address delta by the minimum instruction length. - AddrDelta = ScaleAddrDelta(Context, AddrDelta); - - support::endianness E = - Context.getAsmInfo()->isLittleEndian() ? support::little : support::big; - if (AddrDelta == 0) { - } else if (isUIntN(6, AddrDelta)) { - uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta; - OS << Opcode; - } else if (isUInt<8>(AddrDelta)) { - OS << uint8_t(dwarf::DW_CFA_advance_loc1); - OS << uint8_t(AddrDelta); - } else if (isUInt<16>(AddrDelta)) { - OS << uint8_t(dwarf::DW_CFA_advance_loc2); - support::endian::write<uint16_t>(OS, AddrDelta, E); - } else { - assert(isUInt<32>(AddrDelta)); - OS << uint8_t(dwarf::DW_CFA_advance_loc4); - support::endian::write<uint32_t>(OS, AddrDelta, E); - } -} |
