diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
commit | 0b57cec536236d46e3dba9bd041533462f33dbb7 (patch) | |
tree | 56229dbdbbf76d18580f72f789003db17246c8d9 /contrib/llvm/lib/MC | |
parent | 718ef55ec7785aae63f98f8ca05dc07ed399c16d (diff) |
Move all sources from the llvm project into contrib/llvm-project.
This uses the new layout of the upstream repository, which was recently
migrated to GitHub, and converted into a "monorepo". That is, most of
the earlier separate sub-projects with their own branches and tags were
consolidated into one top-level directory, and are now branched and
tagged together.
Updating the vendor area to match this layout is next.
Notes
Notes:
svn path=/head/; revision=355940
Diffstat (limited to 'contrib/llvm/lib/MC')
76 files changed, 0 insertions, 33262 deletions
diff --git a/contrib/llvm/lib/MC/ConstantPools.cpp b/contrib/llvm/lib/MC/ConstantPools.cpp deleted file mode 100644 index 8cba6b3281a5..000000000000 --- a/contrib/llvm/lib/MC/ConstantPools.cpp +++ /dev/null @@ -1,115 +0,0 @@ -//===- ConstantPools.cpp - ConstantPool class -----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the ConstantPool and AssemblerConstantPools classes. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/ConstantPools.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDirectives.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/Support/Casting.h" - -using namespace llvm; - -// -// ConstantPool implementation -// -// Emit the contents of the constant pool using the provided streamer. -void ConstantPool::emitEntries(MCStreamer &Streamer) { - if (Entries.empty()) - return; - Streamer.EmitDataRegion(MCDR_DataRegion); - for (const ConstantPoolEntry &Entry : Entries) { - Streamer.EmitCodeAlignment(Entry.Size); // align naturally - Streamer.EmitLabel(Entry.Label); - Streamer.EmitValue(Entry.Value, Entry.Size, Entry.Loc); - } - Streamer.EmitDataRegion(MCDR_DataRegionEnd); - Entries.clear(); -} - -const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context, - unsigned Size, SMLoc Loc) { - const MCConstantExpr *C = dyn_cast<MCConstantExpr>(Value); - - // Check if there is existing entry for the same constant. If so, reuse it. - auto Itr = C ? CachedEntries.find(C->getValue()) : CachedEntries.end(); - if (Itr != CachedEntries.end()) - return Itr->second; - - MCSymbol *CPEntryLabel = Context.createTempSymbol(); - - Entries.push_back(ConstantPoolEntry(CPEntryLabel, Value, Size, Loc)); - const auto SymRef = MCSymbolRefExpr::create(CPEntryLabel, Context); - if (C) - CachedEntries[C->getValue()] = SymRef; - return SymRef; -} - -bool ConstantPool::empty() { return Entries.empty(); } - -void ConstantPool::clearCache() { - CachedEntries.clear(); -} - -// -// AssemblerConstantPools implementation -// -ConstantPool *AssemblerConstantPools::getConstantPool(MCSection *Section) { - ConstantPoolMapTy::iterator CP = ConstantPools.find(Section); - if (CP == ConstantPools.end()) - return nullptr; - - return &CP->second; -} - -ConstantPool & -AssemblerConstantPools::getOrCreateConstantPool(MCSection *Section) { - return ConstantPools[Section]; -} - -static void emitConstantPool(MCStreamer &Streamer, MCSection *Section, - ConstantPool &CP) { - if (!CP.empty()) { - Streamer.SwitchSection(Section); - CP.emitEntries(Streamer); - } -} - -void AssemblerConstantPools::emitAll(MCStreamer &Streamer) { - // Dump contents of assembler constant pools. - for (auto &CPI : ConstantPools) { - MCSection *Section = CPI.first; - ConstantPool &CP = CPI.second; - - emitConstantPool(Streamer, Section, CP); - } -} - -void AssemblerConstantPools::emitForCurrentSection(MCStreamer &Streamer) { - MCSection *Section = Streamer.getCurrentSectionOnly(); - if (ConstantPool *CP = getConstantPool(Section)) - emitConstantPool(Streamer, Section, *CP); -} - -void AssemblerConstantPools::clearCacheForCurrentSection(MCStreamer &Streamer) { - MCSection *Section = Streamer.getCurrentSectionOnly(); - if (ConstantPool *CP = getConstantPool(Section)) - CP->clearCache(); -} - -const MCExpr *AssemblerConstantPools::addEntry(MCStreamer &Streamer, - const MCExpr *Expr, - unsigned Size, SMLoc Loc) { - MCSection *Section = Streamer.getCurrentSectionOnly(); - return getOrCreateConstantPool(Section).addEntry(Expr, Streamer.getContext(), - Size, Loc); -} diff --git a/contrib/llvm/lib/MC/ELFObjectWriter.cpp b/contrib/llvm/lib/MC/ELFObjectWriter.cpp deleted file mode 100644 index 2c68723a12f8..000000000000 --- a/contrib/llvm/lib/MC/ELFObjectWriter.cpp +++ /dev/null @@ -1,1564 +0,0 @@ -//===- lib/MC/ELFObjectWriter.cpp - ELF File Writer -----------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements ELF object file writer information. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.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/ELF.h" -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCAsmLayout.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCELFObjectWriter.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFixup.h" -#include "llvm/MC/MCFixupKindInfo.h" -#include "llvm/MC/MCFragment.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSectionELF.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCSymbolELF.h" -#include "llvm/MC/MCValue.h" -#include "llvm/MC/StringTableBuilder.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Compression.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/LEB128.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/SMLoc.h" -#include "llvm/Support/StringSaver.h" -#include "llvm/Support/SwapByteOrder.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cassert> -#include <cstddef> -#include <cstdint> -#include <map> -#include <memory> -#include <string> -#include <utility> -#include <vector> - -using namespace llvm; - -#undef DEBUG_TYPE -#define DEBUG_TYPE "reloc-info" - -namespace { - -using SectionIndexMapTy = DenseMap<const MCSectionELF *, uint32_t>; - -class ELFObjectWriter; -struct ELFWriter; - -bool isDwoSection(const MCSectionELF &Sec) { - return Sec.getSectionName().endswith(".dwo"); -} - -class SymbolTableWriter { - ELFWriter &EWriter; - bool Is64Bit; - - // indexes we are going to write to .symtab_shndx. - std::vector<uint32_t> ShndxIndexes; - - // The numbel of symbols written so far. - unsigned NumWritten; - - void createSymtabShndx(); - - template <typename T> void write(T Value); - -public: - SymbolTableWriter(ELFWriter &EWriter, bool Is64Bit); - - void writeSymbol(uint32_t name, uint8_t info, uint64_t value, uint64_t size, - uint8_t other, uint32_t shndx, bool Reserved); - - ArrayRef<uint32_t> getShndxIndexes() const { return ShndxIndexes; } -}; - -struct ELFWriter { - ELFObjectWriter &OWriter; - support::endian::Writer W; - - enum DwoMode { - AllSections, - NonDwoOnly, - DwoOnly, - } Mode; - - static uint64_t SymbolValue(const MCSymbol &Sym, const MCAsmLayout &Layout); - static bool isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol, - bool Used, bool Renamed); - - /// Helper struct for containing some precomputed information on symbols. - struct ELFSymbolData { - const MCSymbolELF *Symbol; - uint32_t SectionIndex; - StringRef Name; - - // Support lexicographic sorting. - bool operator<(const ELFSymbolData &RHS) const { - unsigned LHSType = Symbol->getType(); - unsigned RHSType = RHS.Symbol->getType(); - if (LHSType == ELF::STT_SECTION && RHSType != ELF::STT_SECTION) - return false; - if (LHSType != ELF::STT_SECTION && RHSType == ELF::STT_SECTION) - return true; - if (LHSType == ELF::STT_SECTION && RHSType == ELF::STT_SECTION) - return SectionIndex < RHS.SectionIndex; - return Name < RHS.Name; - } - }; - - /// @} - /// @name Symbol Table Data - /// @{ - - StringTableBuilder StrTabBuilder{StringTableBuilder::ELF}; - - /// @} - - // This holds the symbol table index of the last local symbol. - unsigned LastLocalSymbolIndex; - // This holds the .strtab section index. - unsigned StringTableIndex; - // This holds the .symtab section index. - unsigned SymbolTableIndex; - - // Sections in the order they are to be output in the section table. - std::vector<const MCSectionELF *> SectionTable; - unsigned addToSectionTable(const MCSectionELF *Sec); - - // TargetObjectWriter wrappers. - bool is64Bit() const; - bool hasRelocationAddend() const; - - void align(unsigned Alignment); - - bool maybeWriteCompression(uint64_t Size, - SmallVectorImpl<char> &CompressedContents, - bool ZLibStyle, unsigned Alignment); - -public: - ELFWriter(ELFObjectWriter &OWriter, raw_pwrite_stream &OS, - bool IsLittleEndian, DwoMode Mode) - : OWriter(OWriter), - W(OS, IsLittleEndian ? support::little : support::big), Mode(Mode) {} - - void WriteWord(uint64_t Word) { - if (is64Bit()) - W.write<uint64_t>(Word); - else - W.write<uint32_t>(Word); - } - - template <typename T> void write(T Val) { - W.write(Val); - } - - void writeHeader(const MCAssembler &Asm); - - void writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex, - ELFSymbolData &MSD, const MCAsmLayout &Layout); - - // Start and end offset of each section - using SectionOffsetsTy = - std::map<const MCSectionELF *, std::pair<uint64_t, uint64_t>>; - - // Map from a signature symbol to the group section index - using RevGroupMapTy = DenseMap<const MCSymbol *, unsigned>; - - /// Compute the symbol table data - /// - /// \param Asm - The assembler. - /// \param SectionIndexMap - Maps a section to its index. - /// \param RevGroupMap - Maps a signature symbol to the group section. - void computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap, - const RevGroupMapTy &RevGroupMap, - SectionOffsetsTy &SectionOffsets); - - void writeAddrsigSection(); - - MCSectionELF *createRelocationSection(MCContext &Ctx, - const MCSectionELF &Sec); - - const MCSectionELF *createStringTable(MCContext &Ctx); - - void writeSectionHeader(const MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap, - const SectionOffsetsTy &SectionOffsets); - - void writeSectionData(const MCAssembler &Asm, MCSection &Sec, - const MCAsmLayout &Layout); - - void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, - uint64_t Address, uint64_t Offset, uint64_t Size, - uint32_t Link, uint32_t Info, uint64_t Alignment, - uint64_t EntrySize); - - void writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec); - - uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout); - void writeSection(const SectionIndexMapTy &SectionIndexMap, - uint32_t GroupSymbolIndex, uint64_t Offset, uint64_t Size, - const MCSectionELF &Section); -}; - -class ELFObjectWriter : public MCObjectWriter { - /// The target specific ELF writer instance. - std::unique_ptr<MCELFObjectTargetWriter> TargetObjectWriter; - - DenseMap<const MCSectionELF *, std::vector<ELFRelocationEntry>> Relocations; - - DenseMap<const MCSymbolELF *, const MCSymbolELF *> Renames; - - bool EmitAddrsigSection = false; - std::vector<const MCSymbol *> AddrsigSyms; - - bool hasRelocationAddend() const; - - bool shouldRelocateWithSymbol(const MCAssembler &Asm, - const MCSymbolRefExpr *RefA, - const MCSymbolELF *Sym, uint64_t C, - unsigned Type) const; - -public: - ELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW) - : TargetObjectWriter(std::move(MOTW)) {} - - void reset() override { - Relocations.clear(); - Renames.clear(); - MCObjectWriter::reset(); - } - - bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, - const MCSymbol &SymA, - const MCFragment &FB, bool InSet, - bool IsPCRel) const override; - - virtual bool checkRelocation(MCContext &Ctx, SMLoc Loc, - const MCSectionELF *From, - const MCSectionELF *To) { - return true; - } - - void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, - const MCFragment *Fragment, const MCFixup &Fixup, - MCValue Target, uint64_t &FixedValue) override; - - void executePostLayoutBinding(MCAssembler &Asm, - const MCAsmLayout &Layout) override; - - void emitAddrsigSection() override { EmitAddrsigSection = true; } - void addAddrsigSymbol(const MCSymbol *Sym) override { - AddrsigSyms.push_back(Sym); - } - - friend struct ELFWriter; -}; - -class ELFSingleObjectWriter : public ELFObjectWriter { - raw_pwrite_stream &OS; - bool IsLittleEndian; - -public: - ELFSingleObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW, - raw_pwrite_stream &OS, bool IsLittleEndian) - : ELFObjectWriter(std::move(MOTW)), OS(OS), - IsLittleEndian(IsLittleEndian) {} - - uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override { - return ELFWriter(*this, OS, IsLittleEndian, ELFWriter::AllSections) - .writeObject(Asm, Layout); - } - - friend struct ELFWriter; -}; - -class ELFDwoObjectWriter : public ELFObjectWriter { - raw_pwrite_stream &OS, &DwoOS; - bool IsLittleEndian; - -public: - ELFDwoObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW, - raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS, - bool IsLittleEndian) - : ELFObjectWriter(std::move(MOTW)), OS(OS), DwoOS(DwoOS), - IsLittleEndian(IsLittleEndian) {} - - virtual bool checkRelocation(MCContext &Ctx, SMLoc Loc, - const MCSectionELF *From, - const MCSectionELF *To) override { - if (isDwoSection(*From)) { - Ctx.reportError(Loc, "A dwo section may not contain relocations"); - return false; - } - if (To && isDwoSection(*To)) { - Ctx.reportError(Loc, "A relocation may not refer to a dwo section"); - return false; - } - return true; - } - - uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override { - uint64_t Size = ELFWriter(*this, OS, IsLittleEndian, ELFWriter::NonDwoOnly) - .writeObject(Asm, Layout); - Size += ELFWriter(*this, DwoOS, IsLittleEndian, ELFWriter::DwoOnly) - .writeObject(Asm, Layout); - return Size; - } -}; - -} // end anonymous namespace - -void ELFWriter::align(unsigned Alignment) { - uint64_t Padding = OffsetToAlignment(W.OS.tell(), Alignment); - W.OS.write_zeros(Padding); -} - -unsigned ELFWriter::addToSectionTable(const MCSectionELF *Sec) { - SectionTable.push_back(Sec); - StrTabBuilder.add(Sec->getSectionName()); - return SectionTable.size(); -} - -void SymbolTableWriter::createSymtabShndx() { - if (!ShndxIndexes.empty()) - return; - - ShndxIndexes.resize(NumWritten); -} - -template <typename T> void SymbolTableWriter::write(T Value) { - EWriter.write(Value); -} - -SymbolTableWriter::SymbolTableWriter(ELFWriter &EWriter, bool Is64Bit) - : EWriter(EWriter), Is64Bit(Is64Bit), NumWritten(0) {} - -void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value, - uint64_t size, uint8_t other, - uint32_t shndx, bool Reserved) { - bool LargeIndex = shndx >= ELF::SHN_LORESERVE && !Reserved; - - if (LargeIndex) - createSymtabShndx(); - - if (!ShndxIndexes.empty()) { - if (LargeIndex) - ShndxIndexes.push_back(shndx); - else - ShndxIndexes.push_back(0); - } - - uint16_t Index = LargeIndex ? uint16_t(ELF::SHN_XINDEX) : shndx; - - if (Is64Bit) { - write(name); // st_name - write(info); // st_info - write(other); // st_other - write(Index); // st_shndx - write(value); // st_value - write(size); // st_size - } else { - write(name); // st_name - write(uint32_t(value)); // st_value - write(uint32_t(size)); // st_size - write(info); // st_info - write(other); // st_other - write(Index); // st_shndx - } - - ++NumWritten; -} - -bool ELFWriter::is64Bit() const { - return OWriter.TargetObjectWriter->is64Bit(); -} - -bool ELFWriter::hasRelocationAddend() const { - return OWriter.hasRelocationAddend(); -} - -// Emit the ELF header. -void ELFWriter::writeHeader(const MCAssembler &Asm) { - // ELF Header - // ---------- - // - // Note - // ---- - // emitWord method behaves differently for ELF32 and ELF64, writing - // 4 bytes in the former and 8 in the latter. - - W.OS << ELF::ElfMagic; // e_ident[EI_MAG0] to e_ident[EI_MAG3] - - W.OS << char(is64Bit() ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS] - - // e_ident[EI_DATA] - W.OS << char(W.Endian == support::little ? ELF::ELFDATA2LSB - : ELF::ELFDATA2MSB); - - W.OS << char(ELF::EV_CURRENT); // e_ident[EI_VERSION] - // e_ident[EI_OSABI] - W.OS << char(OWriter.TargetObjectWriter->getOSABI()); - // e_ident[EI_ABIVERSION] - W.OS << char(OWriter.TargetObjectWriter->getABIVersion()); - - W.OS.write_zeros(ELF::EI_NIDENT - ELF::EI_PAD); - - W.write<uint16_t>(ELF::ET_REL); // e_type - - W.write<uint16_t>(OWriter.TargetObjectWriter->getEMachine()); // e_machine = target - - W.write<uint32_t>(ELF::EV_CURRENT); // e_version - WriteWord(0); // e_entry, no entry point in .o file - WriteWord(0); // e_phoff, no program header for .o - WriteWord(0); // e_shoff = sec hdr table off in bytes - - // e_flags = whatever the target wants - W.write<uint32_t>(Asm.getELFHeaderEFlags()); - - // e_ehsize = ELF header size - W.write<uint16_t>(is64Bit() ? sizeof(ELF::Elf64_Ehdr) - : sizeof(ELF::Elf32_Ehdr)); - - W.write<uint16_t>(0); // e_phentsize = prog header entry size - W.write<uint16_t>(0); // e_phnum = # prog header entries = 0 - - // e_shentsize = Section header entry size - W.write<uint16_t>(is64Bit() ? sizeof(ELF::Elf64_Shdr) - : sizeof(ELF::Elf32_Shdr)); - - // e_shnum = # of section header ents - W.write<uint16_t>(0); - - // e_shstrndx = Section # of '.shstrtab' - assert(StringTableIndex < ELF::SHN_LORESERVE); - W.write<uint16_t>(StringTableIndex); -} - -uint64_t ELFWriter::SymbolValue(const MCSymbol &Sym, - const MCAsmLayout &Layout) { - if (Sym.isCommon() && (Sym.isTargetCommon() || Sym.isExternal())) - return Sym.getCommonAlignment(); - - uint64_t Res; - if (!Layout.getSymbolOffset(Sym, Res)) - return 0; - - if (Layout.getAssembler().isThumbFunc(&Sym)) - Res |= 1; - - return Res; -} - -static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType) { - uint8_t Type = newType; - - // Propagation rules: - // IFUNC > FUNC > OBJECT > NOTYPE - // TLS_OBJECT > OBJECT > NOTYPE - // - // dont let the new type degrade the old type - switch (origType) { - default: - break; - case ELF::STT_GNU_IFUNC: - if (Type == ELF::STT_FUNC || Type == ELF::STT_OBJECT || - Type == ELF::STT_NOTYPE || Type == ELF::STT_TLS) - Type = ELF::STT_GNU_IFUNC; - break; - case ELF::STT_FUNC: - if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE || - Type == ELF::STT_TLS) - Type = ELF::STT_FUNC; - break; - case ELF::STT_OBJECT: - if (Type == ELF::STT_NOTYPE) - Type = ELF::STT_OBJECT; - break; - case ELF::STT_TLS: - if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE || - Type == ELF::STT_GNU_IFUNC || Type == ELF::STT_FUNC) - Type = ELF::STT_TLS; - break; - } - - return Type; -} - -void ELFWriter::writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex, - ELFSymbolData &MSD, const MCAsmLayout &Layout) { - const auto &Symbol = cast<MCSymbolELF>(*MSD.Symbol); - const MCSymbolELF *Base = - cast_or_null<MCSymbolELF>(Layout.getBaseSymbol(Symbol)); - - // This has to be in sync with when computeSymbolTable uses SHN_ABS or - // SHN_COMMON. - bool IsReserved = !Base || Symbol.isCommon(); - - // Binding and Type share the same byte as upper and lower nibbles - uint8_t Binding = Symbol.getBinding(); - uint8_t Type = Symbol.getType(); - if (Base) { - Type = mergeTypeForSet(Type, Base->getType()); - } - uint8_t Info = (Binding << 4) | Type; - - // Other and Visibility share the same byte with Visibility using the lower - // 2 bits - uint8_t Visibility = Symbol.getVisibility(); - uint8_t Other = Symbol.getOther() | Visibility; - - uint64_t Value = SymbolValue(*MSD.Symbol, Layout); - uint64_t Size = 0; - - const MCExpr *ESize = MSD.Symbol->getSize(); - if (!ESize && Base) - ESize = Base->getSize(); - - if (ESize) { - int64_t Res; - if (!ESize->evaluateKnownAbsolute(Res, Layout)) - report_fatal_error("Size expression must be absolute."); - Size = Res; - } - - // Write out the symbol table entry - Writer.writeSymbol(StringIndex, Info, Value, Size, Other, MSD.SectionIndex, - IsReserved); -} - -// True if the assembler knows nothing about the final value of the symbol. -// This doesn't cover the comdat issues, since in those cases the assembler -// can at least know that all symbols in the section will move together. -static bool isWeak(const MCSymbolELF &Sym) { - if (Sym.getType() == ELF::STT_GNU_IFUNC) - return true; - - switch (Sym.getBinding()) { - default: - llvm_unreachable("Unknown binding"); - case ELF::STB_LOCAL: - return false; - case ELF::STB_GLOBAL: - return false; - case ELF::STB_WEAK: - case ELF::STB_GNU_UNIQUE: - return true; - } -} - -bool ELFWriter::isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol, - bool Used, bool Renamed) { - if (Symbol.isVariable()) { - const MCExpr *Expr = Symbol.getVariableValue(); - // Target Expressions that are always inlined do not appear in the symtab - if (const auto *T = dyn_cast<MCTargetExpr>(Expr)) - if (T->inlineAssignedExpr()) - return false; - if (const MCSymbolRefExpr *Ref = dyn_cast<MCSymbolRefExpr>(Expr)) { - if (Ref->getKind() == MCSymbolRefExpr::VK_WEAKREF) - return false; - } - } - - if (Used) - return true; - - if (Renamed) - return false; - - if (Symbol.isVariable() && Symbol.isUndefined()) { - // FIXME: this is here just to diagnose the case of a var = commmon_sym. - Layout.getBaseSymbol(Symbol); - return false; - } - - if (Symbol.isUndefined() && !Symbol.isBindingSet()) - return false; - - if (Symbol.isTemporary()) - return false; - - if (Symbol.getType() == ELF::STT_SECTION) - return false; - - return true; -} - -void ELFWriter::computeSymbolTable( - MCAssembler &Asm, const MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap, const RevGroupMapTy &RevGroupMap, - SectionOffsetsTy &SectionOffsets) { - MCContext &Ctx = Asm.getContext(); - SymbolTableWriter Writer(*this, is64Bit()); - - // Symbol table - unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32; - MCSectionELF *SymtabSection = - Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, EntrySize, ""); - SymtabSection->setAlignment(is64Bit() ? 8 : 4); - SymbolTableIndex = addToSectionTable(SymtabSection); - - align(SymtabSection->getAlignment()); - uint64_t SecStart = W.OS.tell(); - - // The first entry is the undefined symbol entry. - Writer.writeSymbol(0, 0, 0, 0, 0, 0, false); - - std::vector<ELFSymbolData> LocalSymbolData; - std::vector<ELFSymbolData> ExternalSymbolData; - - // Add the data for the symbols. - bool HasLargeSectionIndex = false; - for (const MCSymbol &S : Asm.symbols()) { - const auto &Symbol = cast<MCSymbolELF>(S); - bool Used = Symbol.isUsedInReloc(); - bool WeakrefUsed = Symbol.isWeakrefUsedInReloc(); - bool isSignature = Symbol.isSignature(); - - if (!isInSymtab(Layout, Symbol, Used || WeakrefUsed || isSignature, - OWriter.Renames.count(&Symbol))) - continue; - - if (Symbol.isTemporary() && Symbol.isUndefined()) { - Ctx.reportError(SMLoc(), "Undefined temporary symbol"); - continue; - } - - ELFSymbolData MSD; - MSD.Symbol = cast<MCSymbolELF>(&Symbol); - - bool Local = Symbol.getBinding() == ELF::STB_LOCAL; - assert(Local || !Symbol.isTemporary()); - - if (Symbol.isAbsolute()) { - MSD.SectionIndex = ELF::SHN_ABS; - } else if (Symbol.isCommon()) { - if (Symbol.isTargetCommon()) { - MSD.SectionIndex = Symbol.getIndex(); - } else { - assert(!Local); - MSD.SectionIndex = ELF::SHN_COMMON; - } - } else if (Symbol.isUndefined()) { - if (isSignature && !Used) { - MSD.SectionIndex = RevGroupMap.lookup(&Symbol); - if (MSD.SectionIndex >= ELF::SHN_LORESERVE) - HasLargeSectionIndex = true; - } else { - MSD.SectionIndex = ELF::SHN_UNDEF; - } - } else { - const MCSectionELF &Section = - static_cast<const MCSectionELF &>(Symbol.getSection()); - - // We may end up with a situation when section symbol is technically - // defined, but should not be. That happens because we explicitly - // pre-create few .debug_* sections to have accessors. - // And if these sections were not really defined in the code, but were - // referenced, we simply error out. - if (!Section.isRegistered()) { - assert(static_cast<const MCSymbolELF &>(Symbol).getType() == - ELF::STT_SECTION); - Ctx.reportError(SMLoc(), - "Undefined section reference: " + Symbol.getName()); - continue; - } - - if (Mode == NonDwoOnly && isDwoSection(Section)) - continue; - MSD.SectionIndex = SectionIndexMap.lookup(&Section); - assert(MSD.SectionIndex && "Invalid section index!"); - if (MSD.SectionIndex >= ELF::SHN_LORESERVE) - HasLargeSectionIndex = true; - } - - StringRef Name = Symbol.getName(); - - // Sections have their own string table - if (Symbol.getType() != ELF::STT_SECTION) { - MSD.Name = Name; - StrTabBuilder.add(Name); - } - - if (Local) - LocalSymbolData.push_back(MSD); - else - ExternalSymbolData.push_back(MSD); - } - - // This holds the .symtab_shndx section index. - unsigned SymtabShndxSectionIndex = 0; - - if (HasLargeSectionIndex) { - MCSectionELF *SymtabShndxSection = - Ctx.getELFSection(".symtab_shndx", ELF::SHT_SYMTAB_SHNDX, 0, 4, ""); - SymtabShndxSectionIndex = addToSectionTable(SymtabShndxSection); - SymtabShndxSection->setAlignment(4); - } - - ArrayRef<std::string> FileNames = Asm.getFileNames(); - for (const std::string &Name : FileNames) - StrTabBuilder.add(Name); - - StrTabBuilder.finalize(); - - // File symbols are emitted first and handled separately from normal symbols, - // i.e. a non-STT_FILE symbol with the same name may appear. - for (const std::string &Name : FileNames) - Writer.writeSymbol(StrTabBuilder.getOffset(Name), - ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT, - ELF::SHN_ABS, true); - - // Symbols are required to be in lexicographic order. - array_pod_sort(LocalSymbolData.begin(), LocalSymbolData.end()); - array_pod_sort(ExternalSymbolData.begin(), ExternalSymbolData.end()); - - // Set the symbol indices. Local symbols must come before all other - // symbols with non-local bindings. - unsigned Index = FileNames.size() + 1; - - for (ELFSymbolData &MSD : LocalSymbolData) { - unsigned StringIndex = MSD.Symbol->getType() == ELF::STT_SECTION - ? 0 - : StrTabBuilder.getOffset(MSD.Name); - MSD.Symbol->setIndex(Index++); - writeSymbol(Writer, StringIndex, MSD, Layout); - } - - // Write the symbol table entries. - LastLocalSymbolIndex = Index; - - for (ELFSymbolData &MSD : ExternalSymbolData) { - unsigned StringIndex = StrTabBuilder.getOffset(MSD.Name); - MSD.Symbol->setIndex(Index++); - writeSymbol(Writer, StringIndex, MSD, Layout); - assert(MSD.Symbol->getBinding() != ELF::STB_LOCAL); - } - - uint64_t SecEnd = W.OS.tell(); - SectionOffsets[SymtabSection] = std::make_pair(SecStart, SecEnd); - - ArrayRef<uint32_t> ShndxIndexes = Writer.getShndxIndexes(); - if (ShndxIndexes.empty()) { - assert(SymtabShndxSectionIndex == 0); - return; - } - assert(SymtabShndxSectionIndex != 0); - - SecStart = W.OS.tell(); - const MCSectionELF *SymtabShndxSection = - SectionTable[SymtabShndxSectionIndex - 1]; - for (uint32_t Index : ShndxIndexes) - write(Index); - SecEnd = W.OS.tell(); - SectionOffsets[SymtabShndxSection] = std::make_pair(SecStart, SecEnd); -} - -void ELFWriter::writeAddrsigSection() { - for (const MCSymbol *Sym : OWriter.AddrsigSyms) - encodeULEB128(Sym->getIndex(), W.OS); -} - -MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx, - const MCSectionELF &Sec) { - if (OWriter.Relocations[&Sec].empty()) - return nullptr; - - const StringRef SectionName = Sec.getSectionName(); - std::string RelaSectionName = hasRelocationAddend() ? ".rela" : ".rel"; - RelaSectionName += SectionName; - - unsigned EntrySize; - if (hasRelocationAddend()) - EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rela) : sizeof(ELF::Elf32_Rela); - else - EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel); - - unsigned Flags = 0; - if (Sec.getFlags() & ELF::SHF_GROUP) - Flags = ELF::SHF_GROUP; - - MCSectionELF *RelaSection = Ctx.createELFRelSection( - RelaSectionName, hasRelocationAddend() ? ELF::SHT_RELA : ELF::SHT_REL, - Flags, EntrySize, Sec.getGroup(), &Sec); - RelaSection->setAlignment(is64Bit() ? 8 : 4); - return RelaSection; -} - -// Include the debug info compression header. -bool ELFWriter::maybeWriteCompression( - uint64_t Size, SmallVectorImpl<char> &CompressedContents, bool ZLibStyle, - unsigned Alignment) { - if (ZLibStyle) { - uint64_t HdrSize = - is64Bit() ? sizeof(ELF::Elf32_Chdr) : sizeof(ELF::Elf64_Chdr); - if (Size <= HdrSize + CompressedContents.size()) - return false; - // Platform specific header is followed by compressed data. - if (is64Bit()) { - // Write Elf64_Chdr header. - write(static_cast<ELF::Elf64_Word>(ELF::ELFCOMPRESS_ZLIB)); - write(static_cast<ELF::Elf64_Word>(0)); // ch_reserved field. - write(static_cast<ELF::Elf64_Xword>(Size)); - write(static_cast<ELF::Elf64_Xword>(Alignment)); - } else { - // Write Elf32_Chdr header otherwise. - write(static_cast<ELF::Elf32_Word>(ELF::ELFCOMPRESS_ZLIB)); - write(static_cast<ELF::Elf32_Word>(Size)); - write(static_cast<ELF::Elf32_Word>(Alignment)); - } - return true; - } - - // "ZLIB" followed by 8 bytes representing the uncompressed size of the section, - // useful for consumers to preallocate a buffer to decompress into. - const StringRef Magic = "ZLIB"; - if (Size <= Magic.size() + sizeof(Size) + CompressedContents.size()) - return false; - W.OS << Magic; - support::endian::write(W.OS, Size, support::big); - return true; -} - -void ELFWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec, - const MCAsmLayout &Layout) { - MCSectionELF &Section = static_cast<MCSectionELF &>(Sec); - StringRef SectionName = Section.getSectionName(); - - auto &MC = Asm.getContext(); - const auto &MAI = MC.getAsmInfo(); - - // Compressing debug_frame requires handling alignment fragments which is - // more work (possibly generalizing MCAssembler.cpp:writeFragment to allow - // for writing to arbitrary buffers) for little benefit. - bool CompressionEnabled = - MAI->compressDebugSections() != DebugCompressionType::None; - if (!CompressionEnabled || !SectionName.startswith(".debug_") || - SectionName == ".debug_frame") { - Asm.writeSectionData(W.OS, &Section, Layout); - return; - } - - assert((MAI->compressDebugSections() == DebugCompressionType::Z || - MAI->compressDebugSections() == DebugCompressionType::GNU) && - "expected zlib or zlib-gnu style compression"); - - SmallVector<char, 128> UncompressedData; - raw_svector_ostream VecOS(UncompressedData); - Asm.writeSectionData(VecOS, &Section, Layout); - - SmallVector<char, 128> CompressedContents; - if (Error E = zlib::compress( - StringRef(UncompressedData.data(), UncompressedData.size()), - CompressedContents)) { - consumeError(std::move(E)); - W.OS << UncompressedData; - return; - } - - bool ZlibStyle = MAI->compressDebugSections() == DebugCompressionType::Z; - if (!maybeWriteCompression(UncompressedData.size(), CompressedContents, - ZlibStyle, Sec.getAlignment())) { - W.OS << UncompressedData; - return; - } - - if (ZlibStyle) { - // Set the compressed flag. That is zlib style. - Section.setFlags(Section.getFlags() | ELF::SHF_COMPRESSED); - // Alignment field should reflect the requirements of - // the compressed section header. - Section.setAlignment(is64Bit() ? 8 : 4); - } else { - // Add "z" prefix to section name. This is zlib-gnu style. - MC.renameELFSection(&Section, (".z" + SectionName.drop_front(1)).str()); - } - W.OS << CompressedContents; -} - -void ELFWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, - uint64_t Address, uint64_t Offset, - uint64_t Size, uint32_t Link, uint32_t Info, - uint64_t Alignment, uint64_t EntrySize) { - W.write<uint32_t>(Name); // sh_name: index into string table - W.write<uint32_t>(Type); // sh_type - WriteWord(Flags); // sh_flags - WriteWord(Address); // sh_addr - WriteWord(Offset); // sh_offset - WriteWord(Size); // sh_size - W.write<uint32_t>(Link); // sh_link - W.write<uint32_t>(Info); // sh_info - WriteWord(Alignment); // sh_addralign - WriteWord(EntrySize); // sh_entsize -} - -void ELFWriter::writeRelocations(const MCAssembler &Asm, - const MCSectionELF &Sec) { - std::vector<ELFRelocationEntry> &Relocs = OWriter.Relocations[&Sec]; - - // We record relocations by pushing to the end of a vector. Reverse the vector - // to get the relocations in the order they were created. - // In most cases that is not important, but it can be for special sections - // (.eh_frame) or specific relocations (TLS optimizations on SystemZ). - std::reverse(Relocs.begin(), Relocs.end()); - - // Sort the relocation entries. MIPS needs this. - OWriter.TargetObjectWriter->sortRelocs(Asm, Relocs); - - for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { - const ELFRelocationEntry &Entry = Relocs[e - i - 1]; - unsigned Index = Entry.Symbol ? Entry.Symbol->getIndex() : 0; - - if (is64Bit()) { - write(Entry.Offset); - if (OWriter.TargetObjectWriter->getEMachine() == ELF::EM_MIPS) { - write(uint32_t(Index)); - - write(OWriter.TargetObjectWriter->getRSsym(Entry.Type)); - write(OWriter.TargetObjectWriter->getRType3(Entry.Type)); - write(OWriter.TargetObjectWriter->getRType2(Entry.Type)); - write(OWriter.TargetObjectWriter->getRType(Entry.Type)); - } else { - struct ELF::Elf64_Rela ERE64; - ERE64.setSymbolAndType(Index, Entry.Type); - write(ERE64.r_info); - } - if (hasRelocationAddend()) - write(Entry.Addend); - } else { - write(uint32_t(Entry.Offset)); - - struct ELF::Elf32_Rela ERE32; - ERE32.setSymbolAndType(Index, Entry.Type); - write(ERE32.r_info); - - if (hasRelocationAddend()) - write(uint32_t(Entry.Addend)); - - if (OWriter.TargetObjectWriter->getEMachine() == ELF::EM_MIPS) { - if (uint32_t RType = - OWriter.TargetObjectWriter->getRType2(Entry.Type)) { - write(uint32_t(Entry.Offset)); - - ERE32.setSymbolAndType(0, RType); - write(ERE32.r_info); - write(uint32_t(0)); - } - if (uint32_t RType = - OWriter.TargetObjectWriter->getRType3(Entry.Type)) { - write(uint32_t(Entry.Offset)); - - ERE32.setSymbolAndType(0, RType); - write(ERE32.r_info); - write(uint32_t(0)); - } - } - } - } -} - -const MCSectionELF *ELFWriter::createStringTable(MCContext &Ctx) { - const MCSectionELF *StrtabSection = SectionTable[StringTableIndex - 1]; - StrTabBuilder.write(W.OS); - return StrtabSection; -} - -void ELFWriter::writeSection(const SectionIndexMapTy &SectionIndexMap, - uint32_t GroupSymbolIndex, uint64_t Offset, - uint64_t Size, const MCSectionELF &Section) { - uint64_t sh_link = 0; - uint64_t sh_info = 0; - - switch(Section.getType()) { - default: - // Nothing to do. - break; - - case ELF::SHT_DYNAMIC: - llvm_unreachable("SHT_DYNAMIC in a relocatable object"); - - case ELF::SHT_REL: - case ELF::SHT_RELA: { - sh_link = SymbolTableIndex; - assert(sh_link && ".symtab not found"); - const MCSection *InfoSection = Section.getAssociatedSection(); - sh_info = SectionIndexMap.lookup(cast<MCSectionELF>(InfoSection)); - break; - } - - case ELF::SHT_SYMTAB: - sh_link = StringTableIndex; - sh_info = LastLocalSymbolIndex; - break; - - case ELF::SHT_SYMTAB_SHNDX: - case ELF::SHT_LLVM_CALL_GRAPH_PROFILE: - case ELF::SHT_LLVM_ADDRSIG: - sh_link = SymbolTableIndex; - break; - - case ELF::SHT_GROUP: - sh_link = SymbolTableIndex; - sh_info = GroupSymbolIndex; - break; - } - - if (Section.getFlags() & ELF::SHF_LINK_ORDER) { - const MCSymbol *Sym = Section.getAssociatedSymbol(); - const MCSectionELF *Sec = cast<MCSectionELF>(&Sym->getSection()); - sh_link = SectionIndexMap.lookup(Sec); - } - - WriteSecHdrEntry(StrTabBuilder.getOffset(Section.getSectionName()), - Section.getType(), Section.getFlags(), 0, Offset, Size, - sh_link, sh_info, Section.getAlignment(), - Section.getEntrySize()); -} - -void ELFWriter::writeSectionHeader( - const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, - const SectionOffsetsTy &SectionOffsets) { - const unsigned NumSections = SectionTable.size(); - - // Null section first. - uint64_t FirstSectionSize = - (NumSections + 1) >= ELF::SHN_LORESERVE ? NumSections + 1 : 0; - WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, 0, 0, 0, 0); - - for (const MCSectionELF *Section : SectionTable) { - uint32_t GroupSymbolIndex; - unsigned Type = Section->getType(); - if (Type != ELF::SHT_GROUP) - GroupSymbolIndex = 0; - else - GroupSymbolIndex = Section->getGroup()->getIndex(); - - const std::pair<uint64_t, uint64_t> &Offsets = - SectionOffsets.find(Section)->second; - uint64_t Size; - if (Type == ELF::SHT_NOBITS) - Size = Layout.getSectionAddressSize(Section); - else - Size = Offsets.second - Offsets.first; - - writeSection(SectionIndexMap, GroupSymbolIndex, Offsets.first, Size, - *Section); - } -} - -uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { - uint64_t StartOffset = W.OS.tell(); - - MCContext &Ctx = Asm.getContext(); - MCSectionELF *StrtabSection = - Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0); - StringTableIndex = addToSectionTable(StrtabSection); - - RevGroupMapTy RevGroupMap; - SectionIndexMapTy SectionIndexMap; - - std::map<const MCSymbol *, std::vector<const MCSectionELF *>> GroupMembers; - - // Write out the ELF header ... - writeHeader(Asm); - - // ... then the sections ... - SectionOffsetsTy SectionOffsets; - std::vector<MCSectionELF *> Groups; - std::vector<MCSectionELF *> Relocations; - for (MCSection &Sec : Asm) { - MCSectionELF &Section = static_cast<MCSectionELF &>(Sec); - if (Mode == NonDwoOnly && isDwoSection(Section)) - continue; - if (Mode == DwoOnly && !isDwoSection(Section)) - continue; - - align(Section.getAlignment()); - - // Remember the offset into the file for this section. - uint64_t SecStart = W.OS.tell(); - - const MCSymbolELF *SignatureSymbol = Section.getGroup(); - writeSectionData(Asm, Section, Layout); - - uint64_t SecEnd = W.OS.tell(); - SectionOffsets[&Section] = std::make_pair(SecStart, SecEnd); - - MCSectionELF *RelSection = createRelocationSection(Ctx, Section); - - if (SignatureSymbol) { - Asm.registerSymbol(*SignatureSymbol); - unsigned &GroupIdx = RevGroupMap[SignatureSymbol]; - if (!GroupIdx) { - MCSectionELF *Group = Ctx.createELFGroupSection(SignatureSymbol); - GroupIdx = addToSectionTable(Group); - Group->setAlignment(4); - Groups.push_back(Group); - } - std::vector<const MCSectionELF *> &Members = - GroupMembers[SignatureSymbol]; - Members.push_back(&Section); - if (RelSection) - Members.push_back(RelSection); - } - - SectionIndexMap[&Section] = addToSectionTable(&Section); - if (RelSection) { - SectionIndexMap[RelSection] = addToSectionTable(RelSection); - Relocations.push_back(RelSection); - } - - OWriter.TargetObjectWriter->addTargetSectionFlags(Ctx, Section); - } - - MCSectionELF *CGProfileSection = nullptr; - if (!Asm.CGProfile.empty()) { - CGProfileSection = Ctx.getELFSection(".llvm.call-graph-profile", - ELF::SHT_LLVM_CALL_GRAPH_PROFILE, - ELF::SHF_EXCLUDE, 16, ""); - SectionIndexMap[CGProfileSection] = addToSectionTable(CGProfileSection); - } - - for (MCSectionELF *Group : Groups) { - align(Group->getAlignment()); - - // Remember the offset into the file for this section. - uint64_t SecStart = W.OS.tell(); - - const MCSymbol *SignatureSymbol = Group->getGroup(); - assert(SignatureSymbol); - write(uint32_t(ELF::GRP_COMDAT)); - for (const MCSectionELF *Member : GroupMembers[SignatureSymbol]) { - uint32_t SecIndex = SectionIndexMap.lookup(Member); - write(SecIndex); - } - - uint64_t SecEnd = W.OS.tell(); - SectionOffsets[Group] = std::make_pair(SecStart, SecEnd); - } - - if (Mode == DwoOnly) { - // dwo files don't have symbol tables or relocations, but they do have - // string tables. - StrTabBuilder.finalize(); - } else { - MCSectionELF *AddrsigSection; - if (OWriter.EmitAddrsigSection) { - AddrsigSection = Ctx.getELFSection(".llvm_addrsig", ELF::SHT_LLVM_ADDRSIG, - ELF::SHF_EXCLUDE); - addToSectionTable(AddrsigSection); - } - - // Compute symbol table information. - computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap, - SectionOffsets); - - for (MCSectionELF *RelSection : Relocations) { - align(RelSection->getAlignment()); - - // Remember the offset into the file for this section. - uint64_t SecStart = W.OS.tell(); - - writeRelocations(Asm, - cast<MCSectionELF>(*RelSection->getAssociatedSection())); - - uint64_t SecEnd = W.OS.tell(); - SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd); - } - - if (OWriter.EmitAddrsigSection) { - uint64_t SecStart = W.OS.tell(); - writeAddrsigSection(); - uint64_t SecEnd = W.OS.tell(); - SectionOffsets[AddrsigSection] = std::make_pair(SecStart, SecEnd); - } - } - - if (CGProfileSection) { - uint64_t SecStart = W.OS.tell(); - for (const MCAssembler::CGProfileEntry &CGPE : Asm.CGProfile) { - W.write<uint32_t>(CGPE.From->getSymbol().getIndex()); - W.write<uint32_t>(CGPE.To->getSymbol().getIndex()); - W.write<uint64_t>(CGPE.Count); - } - uint64_t SecEnd = W.OS.tell(); - SectionOffsets[CGProfileSection] = std::make_pair(SecStart, SecEnd); - } - - { - uint64_t SecStart = W.OS.tell(); - const MCSectionELF *Sec = createStringTable(Ctx); - uint64_t SecEnd = W.OS.tell(); - SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd); - } - - uint64_t NaturalAlignment = is64Bit() ? 8 : 4; - align(NaturalAlignment); - - const uint64_t SectionHeaderOffset = W.OS.tell(); - - // ... then the section header table ... - writeSectionHeader(Layout, SectionIndexMap, SectionOffsets); - - uint16_t NumSections = support::endian::byte_swap<uint16_t>( - (SectionTable.size() + 1 >= ELF::SHN_LORESERVE) ? (uint16_t)ELF::SHN_UNDEF - : SectionTable.size() + 1, - W.Endian); - unsigned NumSectionsOffset; - - auto &Stream = static_cast<raw_pwrite_stream &>(W.OS); - if (is64Bit()) { - uint64_t Val = - support::endian::byte_swap<uint64_t>(SectionHeaderOffset, W.Endian); - Stream.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val), - offsetof(ELF::Elf64_Ehdr, e_shoff)); - NumSectionsOffset = offsetof(ELF::Elf64_Ehdr, e_shnum); - } else { - uint32_t Val = - support::endian::byte_swap<uint32_t>(SectionHeaderOffset, W.Endian); - Stream.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val), - offsetof(ELF::Elf32_Ehdr, e_shoff)); - NumSectionsOffset = offsetof(ELF::Elf32_Ehdr, e_shnum); - } - Stream.pwrite(reinterpret_cast<char *>(&NumSections), sizeof(NumSections), - NumSectionsOffset); - - return W.OS.tell() - StartOffset; -} - -bool ELFObjectWriter::hasRelocationAddend() const { - return TargetObjectWriter->hasRelocationAddend(); -} - -void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, - const MCAsmLayout &Layout) { - // The presence of symbol versions causes undefined symbols and - // versions declared with @@@ to be renamed. - for (const std::pair<StringRef, const MCSymbol *> &P : Asm.Symvers) { - StringRef AliasName = P.first; - const auto &Symbol = cast<MCSymbolELF>(*P.second); - size_t Pos = AliasName.find('@'); - assert(Pos != StringRef::npos); - - StringRef Prefix = AliasName.substr(0, Pos); - StringRef Rest = AliasName.substr(Pos); - StringRef Tail = Rest; - if (Rest.startswith("@@@")) - Tail = Rest.substr(Symbol.isUndefined() ? 2 : 1); - - auto *Alias = - cast<MCSymbolELF>(Asm.getContext().getOrCreateSymbol(Prefix + Tail)); - Asm.registerSymbol(*Alias); - const MCExpr *Value = MCSymbolRefExpr::create(&Symbol, Asm.getContext()); - Alias->setVariableValue(Value); - - // Aliases defined with .symvar copy the binding from the symbol they alias. - // This is the first place we are able to copy this information. - Alias->setExternal(Symbol.isExternal()); - Alias->setBinding(Symbol.getBinding()); - Alias->setOther(Symbol.getOther()); - - if (!Symbol.isUndefined() && !Rest.startswith("@@@")) - continue; - - // FIXME: Get source locations for these errors or diagnose them earlier. - if (Symbol.isUndefined() && Rest.startswith("@@") && - !Rest.startswith("@@@")) { - Asm.getContext().reportError(SMLoc(), "versioned symbol " + AliasName + - " must be defined"); - continue; - } - - if (Renames.count(&Symbol) && Renames[&Symbol] != Alias) { - Asm.getContext().reportError( - SMLoc(), llvm::Twine("multiple symbol versions defined for ") + - Symbol.getName()); - continue; - } - - Renames.insert(std::make_pair(&Symbol, Alias)); - } - - for (const MCSymbol *&Sym : AddrsigSyms) { - if (const MCSymbol *R = Renames.lookup(cast<MCSymbolELF>(Sym))) - Sym = R; - if (Sym->isInSection() && Sym->getName().startswith(".L")) - Sym = Sym->getSection().getBeginSymbol(); - Sym->setUsedInReloc(); - } -} - -// It is always valid to create a relocation with a symbol. It is preferable -// to use a relocation with a section if that is possible. Using the section -// allows us to omit some local symbols from the symbol table. -bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm, - const MCSymbolRefExpr *RefA, - const MCSymbolELF *Sym, - uint64_t C, - unsigned Type) const { - // A PCRel relocation to an absolute value has no symbol (or section). We - // represent that with a relocation to a null section. - if (!RefA) - return false; - - MCSymbolRefExpr::VariantKind Kind = RefA->getKind(); - switch (Kind) { - default: - break; - // The .odp creation emits a relocation against the symbol ".TOC." which - // create a R_PPC64_TOC relocation. However the relocation symbol name - // in final object creation should be NULL, since the symbol does not - // really exist, it is just the reference to TOC base for the current - // object file. Since the symbol is undefined, returning false results - // in a relocation with a null section which is the desired result. - case MCSymbolRefExpr::VK_PPC_TOCBASE: - return false; - - // These VariantKind cause the relocation to refer to something other than - // the symbol itself, like a linker generated table. Since the address of - // symbol is not relevant, we cannot replace the symbol with the - // section and patch the difference in the addend. - case MCSymbolRefExpr::VK_GOT: - case MCSymbolRefExpr::VK_PLT: - case MCSymbolRefExpr::VK_GOTPCREL: - case MCSymbolRefExpr::VK_PPC_GOT_LO: - case MCSymbolRefExpr::VK_PPC_GOT_HI: - case MCSymbolRefExpr::VK_PPC_GOT_HA: - return true; - } - - // An undefined symbol is not in any section, so the relocation has to point - // to the symbol itself. - assert(Sym && "Expected a symbol"); - if (Sym->isUndefined()) - return true; - - unsigned Binding = Sym->getBinding(); - switch(Binding) { - default: - llvm_unreachable("Invalid Binding"); - case ELF::STB_LOCAL: - break; - case ELF::STB_WEAK: - // If the symbol is weak, it might be overridden by a symbol in another - // file. The relocation has to point to the symbol so that the linker - // can update it. - return true; - case ELF::STB_GLOBAL: - // Global ELF symbols can be preempted by the dynamic linker. The relocation - // has to point to the symbol for a reason analogous to the STB_WEAK case. - return true; - } - - // Keep symbol type for a local ifunc because it may result in an IRELATIVE - // reloc that the dynamic loader will use to resolve the address at startup - // time. - if (Sym->getType() == ELF::STT_GNU_IFUNC) - return true; - - // If a relocation points to a mergeable section, we have to be careful. - // If the offset is zero, a relocation with the section will encode the - // same information. With a non-zero offset, the situation is different. - // For example, a relocation can point 42 bytes past the end of a string. - // If we change such a relocation to use the section, the linker would think - // that it pointed to another string and subtracting 42 at runtime will - // produce the wrong value. - if (Sym->isInSection()) { - auto &Sec = cast<MCSectionELF>(Sym->getSection()); - unsigned Flags = Sec.getFlags(); - if (Flags & ELF::SHF_MERGE) { - if (C != 0) - return true; - - // It looks like gold has a bug (http://sourceware.org/PR16794) and can - // only handle section relocations to mergeable sections if using RELA. - if (!hasRelocationAddend()) - return true; - } - - // Most TLS relocations use a got, so they need the symbol. Even those that - // are just an offset (@tpoff), require a symbol in gold versions before - // 5efeedf61e4fe720fd3e9a08e6c91c10abb66d42 (2014-09-26) which fixed - // http://sourceware.org/PR16773. - if (Flags & ELF::SHF_TLS) - return true; - } - - // If the symbol is a thumb function the final relocation must set the lowest - // bit. With a symbol that is done by just having the symbol have that bit - // set, so we would lose the bit if we relocated with the section. - // FIXME: We could use the section but add the bit to the relocation value. - if (Asm.isThumbFunc(Sym)) - return true; - - if (TargetObjectWriter->needsRelocateWithSymbol(*Sym, Type)) - return true; - return false; -} - -void ELFObjectWriter::recordRelocation(MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, MCValue Target, - uint64_t &FixedValue) { - MCAsmBackend &Backend = Asm.getBackend(); - bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags & - MCFixupKindInfo::FKF_IsPCRel; - const MCSectionELF &FixupSection = cast<MCSectionELF>(*Fragment->getParent()); - uint64_t C = Target.getConstant(); - uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); - MCContext &Ctx = Asm.getContext(); - - if (const MCSymbolRefExpr *RefB = Target.getSymB()) { - // Let A, B and C being the components of Target and R be the location of - // the fixup. If the fixup is not pcrel, we want to compute (A - B + C). - // If it is pcrel, we want to compute (A - B + C - R). - - // In general, ELF has no relocations for -B. It can only represent (A + C) - // or (A + C - R). If B = R + K and the relocation is not pcrel, we can - // replace B to implement it: (A - R - K + C) - if (IsPCRel) { - Ctx.reportError( - Fixup.getLoc(), - "No relocation available to represent this relative expression"); - return; - } - - const auto &SymB = cast<MCSymbolELF>(RefB->getSymbol()); - - if (SymB.isUndefined()) { - Ctx.reportError(Fixup.getLoc(), - Twine("symbol '") + SymB.getName() + - "' can not be undefined in a subtraction expression"); - return; - } - - assert(!SymB.isAbsolute() && "Should have been folded"); - const MCSection &SecB = SymB.getSection(); - if (&SecB != &FixupSection) { - Ctx.reportError(Fixup.getLoc(), - "Cannot represent a difference across sections"); - return; - } - - uint64_t SymBOffset = Layout.getSymbolOffset(SymB); - uint64_t K = SymBOffset - FixupOffset; - IsPCRel = true; - C -= K; - } - - // We either rejected the fixup or folded B into C at this point. - const MCSymbolRefExpr *RefA = Target.getSymA(); - const auto *SymA = RefA ? cast<MCSymbolELF>(&RefA->getSymbol()) : nullptr; - - bool ViaWeakRef = false; - if (SymA && SymA->isVariable()) { - const MCExpr *Expr = SymA->getVariableValue(); - if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr)) { - if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) { - SymA = cast<MCSymbolELF>(&Inner->getSymbol()); - ViaWeakRef = true; - } - } - } - - unsigned Type = TargetObjectWriter->getRelocType(Ctx, Target, Fixup, IsPCRel); - uint64_t OriginalC = C; - bool RelocateWithSymbol = shouldRelocateWithSymbol(Asm, RefA, SymA, C, Type); - if (!RelocateWithSymbol && SymA && !SymA->isUndefined()) - C += Layout.getSymbolOffset(*SymA); - - uint64_t Addend = 0; - if (hasRelocationAddend()) { - Addend = C; - C = 0; - } - - FixedValue = C; - - const MCSectionELF *SecA = (SymA && SymA->isInSection()) - ? cast<MCSectionELF>(&SymA->getSection()) - : nullptr; - if (!checkRelocation(Ctx, Fixup.getLoc(), &FixupSection, SecA)) - return; - - if (!RelocateWithSymbol) { - const auto *SectionSymbol = - SecA ? cast<MCSymbolELF>(SecA->getBeginSymbol()) : nullptr; - if (SectionSymbol) - SectionSymbol->setUsedInReloc(); - ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend, SymA, - OriginalC); - Relocations[&FixupSection].push_back(Rec); - return; - } - - const auto *RenamedSymA = SymA; - if (SymA) { - if (const MCSymbolELF *R = Renames.lookup(SymA)) - RenamedSymA = R; - - if (ViaWeakRef) - RenamedSymA->setIsWeakrefUsedInReloc(); - else - RenamedSymA->setUsedInReloc(); - } - ELFRelocationEntry Rec(FixupOffset, RenamedSymA, Type, Addend, SymA, - OriginalC); - Relocations[&FixupSection].push_back(Rec); -} - -bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl( - const MCAssembler &Asm, const MCSymbol &SA, const MCFragment &FB, - bool InSet, bool IsPCRel) const { - const auto &SymA = cast<MCSymbolELF>(SA); - if (IsPCRel) { - assert(!InSet); - if (isWeak(SymA)) - return false; - } - return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB, - InSet, IsPCRel); -} - -std::unique_ptr<MCObjectWriter> -llvm::createELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW, - raw_pwrite_stream &OS, bool IsLittleEndian) { - return llvm::make_unique<ELFSingleObjectWriter>(std::move(MOTW), OS, - IsLittleEndian); -} - -std::unique_ptr<MCObjectWriter> -llvm::createELFDwoObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW, - raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS, - bool IsLittleEndian) { - return llvm::make_unique<ELFDwoObjectWriter>(std::move(MOTW), OS, DwoOS, - IsLittleEndian); -} diff --git a/contrib/llvm/lib/MC/MCAsmBackend.cpp b/contrib/llvm/lib/MC/MCAsmBackend.cpp deleted file mode 100644 index b800e9caee22..000000000000 --- a/contrib/llvm/lib/MC/MCAsmBackend.cpp +++ /dev/null @@ -1,137 +0,0 @@ -//===- MCAsmBackend.cpp - Target MC Assembly Backend ----------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/MC/MCCodePadder.h" -#include "llvm/MC/MCELFObjectWriter.h" -#include "llvm/MC/MCFixupKindInfo.h" -#include "llvm/MC/MCMachObjectWriter.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCWasmObjectWriter.h" -#include "llvm/MC/MCWinCOFFObjectWriter.h" -#include "llvm/MC/MCXCOFFObjectWriter.h" -#include <cassert> -#include <cstddef> -#include <cstdint> - -using namespace llvm; - -MCAsmBackend::MCAsmBackend(support::endianness Endian) - : CodePadder(new MCCodePadder()), Endian(Endian) {} - -MCAsmBackend::~MCAsmBackend() = default; - -std::unique_ptr<MCObjectWriter> -MCAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const { - auto TW = createObjectTargetWriter(); - switch (TW->getFormat()) { - case Triple::ELF: - return createELFObjectWriter(cast<MCELFObjectTargetWriter>(std::move(TW)), OS, - Endian == support::little); - case Triple::MachO: - return createMachObjectWriter(cast<MCMachObjectTargetWriter>(std::move(TW)), - OS, Endian == support::little); - case Triple::COFF: - return createWinCOFFObjectWriter( - cast<MCWinCOFFObjectTargetWriter>(std::move(TW)), OS); - case Triple::Wasm: - return createWasmObjectWriter(cast<MCWasmObjectTargetWriter>(std::move(TW)), - OS); - case Triple::XCOFF: - return createXCOFFObjectWriter( - cast<MCXCOFFObjectTargetWriter>(std::move(TW)), OS); - default: - llvm_unreachable("unexpected object format"); - } -} - -std::unique_ptr<MCObjectWriter> -MCAsmBackend::createDwoObjectWriter(raw_pwrite_stream &OS, - raw_pwrite_stream &DwoOS) const { - auto TW = createObjectTargetWriter(); - if (TW->getFormat() != Triple::ELF) - report_fatal_error("dwo only supported with ELF"); - return createELFDwoObjectWriter(cast<MCELFObjectTargetWriter>(std::move(TW)), - OS, DwoOS, Endian == support::little); -} - -Optional<MCFixupKind> MCAsmBackend::getFixupKind(StringRef Name) const { - return None; -} - -const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { - static const MCFixupKindInfo Builtins[] = { - {"FK_NONE", 0, 0, 0}, - {"FK_Data_1", 0, 8, 0}, - {"FK_Data_2", 0, 16, 0}, - {"FK_Data_4", 0, 32, 0}, - {"FK_Data_8", 0, 64, 0}, - {"FK_Data_6b", 0, 6, 0}, - {"FK_PCRel_1", 0, 8, MCFixupKindInfo::FKF_IsPCRel}, - {"FK_PCRel_2", 0, 16, MCFixupKindInfo::FKF_IsPCRel}, - {"FK_PCRel_4", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, - {"FK_PCRel_8", 0, 64, MCFixupKindInfo::FKF_IsPCRel}, - {"FK_GPRel_1", 0, 8, 0}, - {"FK_GPRel_2", 0, 16, 0}, - {"FK_GPRel_4", 0, 32, 0}, - {"FK_GPRel_8", 0, 64, 0}, - {"FK_DTPRel_4", 0, 32, 0}, - {"FK_DTPRel_8", 0, 64, 0}, - {"FK_TPRel_4", 0, 32, 0}, - {"FK_TPRel_8", 0, 64, 0}, - {"FK_SecRel_1", 0, 8, 0}, - {"FK_SecRel_2", 0, 16, 0}, - {"FK_SecRel_4", 0, 32, 0}, - {"FK_SecRel_8", 0, 64, 0}, - {"FK_Data_Add_1", 0, 8, 0}, - {"FK_Data_Add_2", 0, 16, 0}, - {"FK_Data_Add_4", 0, 32, 0}, - {"FK_Data_Add_8", 0, 64, 0}, - {"FK_Data_Add_6b", 0, 6, 0}, - {"FK_Data_Sub_1", 0, 8, 0}, - {"FK_Data_Sub_2", 0, 16, 0}, - {"FK_Data_Sub_4", 0, 32, 0}, - {"FK_Data_Sub_8", 0, 64, 0}, - {"FK_Data_Sub_6b", 0, 6, 0}}; - - assert((size_t)Kind <= array_lengthof(Builtins) && "Unknown fixup kind"); - return Builtins[Kind]; -} - -bool MCAsmBackend::fixupNeedsRelaxationAdvanced( - const MCFixup &Fixup, bool Resolved, uint64_t Value, - const MCRelaxableFragment *DF, const MCAsmLayout &Layout, - const bool WasForced) const { - if (!Resolved) - return true; - return fixupNeedsRelaxation(Fixup, Value, DF, Layout); -} - -void MCAsmBackend::handleCodePaddingBasicBlockStart( - MCObjectStreamer *OS, const MCCodePaddingContext &Context) { - CodePadder->handleBasicBlockStart(OS, Context); -} - -void MCAsmBackend::handleCodePaddingBasicBlockEnd( - const MCCodePaddingContext &Context) { - CodePadder->handleBasicBlockEnd(Context); -} - -void MCAsmBackend::handleCodePaddingInstructionBegin(const MCInst &Inst) { - CodePadder->handleInstructionBegin(Inst); -} - -void MCAsmBackend::handleCodePaddingInstructionEnd(const MCInst &Inst) { - CodePadder->handleInstructionEnd(Inst); -} - -bool MCAsmBackend::relaxFragment(MCPaddingFragment *PF, MCAsmLayout &Layout) { - return CodePadder->relaxFragment(PF, Layout); -} diff --git a/contrib/llvm/lib/MC/MCAsmInfo.cpp b/contrib/llvm/lib/MC/MCAsmInfo.cpp deleted file mode 100644 index 71e51e320f8b..000000000000 --- a/contrib/llvm/lib/MC/MCAsmInfo.cpp +++ /dev/null @@ -1,126 +0,0 @@ -//===- MCAsmInfo.cpp - Asm Info -------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines target asm properties related what form asm statements -// should take. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/Support/CommandLine.h" - -using namespace llvm; - -enum DefaultOnOff { Default, Enable, Disable }; -static cl::opt<DefaultOnOff> DwarfExtendedLoc( - "dwarf-extended-loc", cl::Hidden, - cl::desc("Disable emission of the extended flags in .loc directives."), - cl::values(clEnumVal(Default, "Default for platform"), - clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")), - cl::init(Default)); - -MCAsmInfo::MCAsmInfo() { - SeparatorString = ";"; - CommentString = "#"; - LabelSuffix = ":"; - PrivateGlobalPrefix = "L"; - PrivateLabelPrefix = PrivateGlobalPrefix; - LinkerPrivateGlobalPrefix = ""; - InlineAsmStart = "APP"; - InlineAsmEnd = "NO_APP"; - Code16Directive = ".code16"; - Code32Directive = ".code32"; - Code64Directive = ".code64"; - ZeroDirective = "\t.zero\t"; - AsciiDirective = "\t.ascii\t"; - AscizDirective = "\t.asciz\t"; - Data8bitsDirective = "\t.byte\t"; - Data16bitsDirective = "\t.short\t"; - Data32bitsDirective = "\t.long\t"; - Data64bitsDirective = "\t.quad\t"; - GlobalDirective = "\t.globl\t"; - WeakDirective = "\t.weak\t"; - if (DwarfExtendedLoc != Default) - SupportsExtendedDwarfLocDirective = DwarfExtendedLoc == Enable; - - // FIXME: Clang's logic should be synced with the logic used to initialize - // this member and the two implementations should be merged. - // For reference: - // - Solaris always enables the integrated assembler by default - // - SparcELFMCAsmInfo and X86ELFMCAsmInfo are handling this case - // - Windows always enables the integrated assembler by default - // - MCAsmInfoCOFF is handling this case, should it be MCAsmInfoMicrosoft? - // - MachO targets always enables the integrated assembler by default - // - MCAsmInfoDarwin is handling this case - // - Generic_GCC toolchains enable the integrated assembler on a per - // architecture basis. - // - The target subclasses for AArch64, ARM, and X86 handle these cases - UseIntegratedAssembler = false; - PreserveAsmComments = true; -} - -MCAsmInfo::~MCAsmInfo() = default; - -void MCAsmInfo::addInitialFrameState(const MCCFIInstruction &Inst) { - InitialFrameState.push_back(Inst); -} - -bool MCAsmInfo::isSectionAtomizableBySymbols(const MCSection &Section) const { - return false; -} - -const MCExpr * -MCAsmInfo::getExprForPersonalitySymbol(const MCSymbol *Sym, - unsigned Encoding, - MCStreamer &Streamer) const { - return getExprForFDESymbol(Sym, Encoding, Streamer); -} - -const MCExpr * -MCAsmInfo::getExprForFDESymbol(const MCSymbol *Sym, - unsigned Encoding, - MCStreamer &Streamer) const { - if (!(Encoding & dwarf::DW_EH_PE_pcrel)) - return MCSymbolRefExpr::create(Sym, Streamer.getContext()); - - MCContext &Context = Streamer.getContext(); - const MCExpr *Res = MCSymbolRefExpr::create(Sym, Context); - MCSymbol *PCSym = Context.createTempSymbol(); - Streamer.EmitLabel(PCSym); - const MCExpr *PC = MCSymbolRefExpr::create(PCSym, Context); - return MCBinaryExpr::createSub(Res, PC, Context); -} - -static bool isAcceptableChar(char C) { - return (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z') || - (C >= '0' && C <= '9') || C == '_' || C == '$' || C == '.' || C == '@'; -} - -bool MCAsmInfo::isValidUnquotedName(StringRef Name) const { - if (Name.empty()) - return false; - - // If any of the characters in the string is an unacceptable character, force - // quotes. - for (char C : Name) { - if (!isAcceptableChar(C)) - return false; - } - - return true; -} - -bool MCAsmInfo::shouldOmitSectionDirective(StringRef SectionName) const { - // FIXME: Does .section .bss/.data/.text work everywhere?? - return SectionName == ".text" || SectionName == ".data" || - (SectionName == ".bss" && !usesELFSectionDirectiveForBSS()); -} diff --git a/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp b/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp deleted file mode 100644 index 9f19d163f57b..000000000000 --- a/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp +++ /dev/null @@ -1,68 +0,0 @@ -//===- MCAsmInfoCOFF.cpp - COFF asm properties ----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines target asm properties related what form asm statements -// should take in general on COFF-based targets -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCAsmInfoCOFF.h" -#include "llvm/MC/MCDirectives.h" - -using namespace llvm; - -void MCAsmInfoCOFF::anchor() {} - -MCAsmInfoCOFF::MCAsmInfoCOFF() { - // MingW 4.5 and later support .comm with log2 alignment, but .lcomm uses byte - // alignment. - COMMDirectiveAlignmentIsInBytes = false; - LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment; - HasDotTypeDotSizeDirective = false; - HasSingleParameterDotFile = true; - WeakRefDirective = "\t.weak\t"; - HasLinkOnceDirective = true; - - // Doesn't support visibility: - HiddenVisibilityAttr = HiddenDeclarationVisibilityAttr = MCSA_Invalid; - ProtectedVisibilityAttr = MCSA_Invalid; - - // Set up DWARF directives - SupportsDebugInformation = true; - NeedsDwarfSectionOffsetDirective = true; - - UseIntegratedAssembler = true; - - // At least MSVC inline-asm does AShr. - UseLogicalShr = false; - - // If this is a COFF target, assume that it supports associative comdats. It's - // part of the spec. - HasCOFFAssociativeComdats = true; - - // We can generate constants in comdat sections that can be shared, - // but in order not to create null typed symbols, we actually need to - // make them global symbols as well. - HasCOFFComdatConstants = true; -} - -void MCAsmInfoMicrosoft::anchor() {} - -MCAsmInfoMicrosoft::MCAsmInfoMicrosoft() = default; - -void MCAsmInfoGNUCOFF::anchor() {} - -MCAsmInfoGNUCOFF::MCAsmInfoGNUCOFF() { - // If this is a GNU environment (mingw or cygwin), don't use associative - // comdats for jump tables, unwind information, and other data associated with - // a function. - HasCOFFAssociativeComdats = false; - - // We don't create constants in comdat sections for MinGW. - HasCOFFComdatConstants = false; -} diff --git a/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp b/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp deleted file mode 100644 index 62bc5b8c9418..000000000000 --- a/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp +++ /dev/null @@ -1,97 +0,0 @@ -//===- MCAsmInfoDarwin.cpp - Darwin asm properties ------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines target asm properties related what form asm statements -// should take in general on Darwin-based targets -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCAsmInfoDarwin.h" -#include "llvm/BinaryFormat/MachO.h" -#include "llvm/MC/MCDirectives.h" -#include "llvm/MC/MCSectionMachO.h" - -using namespace llvm; - -bool MCAsmInfoDarwin::isSectionAtomizableBySymbols( - const MCSection &Section) const { - const MCSectionMachO &SMO = static_cast<const MCSectionMachO &>(Section); - - // Sections holding 1 byte strings are atomized based on the data they - // contain. - // Sections holding 2 byte strings require symbols in order to be atomized. - // There is no dedicated section for 4 byte strings. - if (SMO.getType() == MachO::S_CSTRING_LITERALS) - return false; - - if (SMO.getSegmentName() == "__DATA" && SMO.getSectionName() == "__cfstring") - return false; - - if (SMO.getSegmentName() == "__DATA" && - SMO.getSectionName() == "__objc_classrefs") - return false; - - switch (SMO.getType()) { - default: - return true; - - // These sections are atomized at the element boundaries without using - // symbols. - case MachO::S_4BYTE_LITERALS: - case MachO::S_8BYTE_LITERALS: - case MachO::S_16BYTE_LITERALS: - case MachO::S_LITERAL_POINTERS: - case MachO::S_NON_LAZY_SYMBOL_POINTERS: - case MachO::S_LAZY_SYMBOL_POINTERS: - case MachO::S_THREAD_LOCAL_VARIABLE_POINTERS: - case MachO::S_MOD_INIT_FUNC_POINTERS: - case MachO::S_MOD_TERM_FUNC_POINTERS: - case MachO::S_INTERPOSING: - return false; - } -} - -MCAsmInfoDarwin::MCAsmInfoDarwin() { - // Common settings for all Darwin targets. - // Syntax: - LinkerPrivateGlobalPrefix = "l"; - HasSingleParameterDotFile = false; - HasSubsectionsViaSymbols = true; - - AlignmentIsInBytes = false; - COMMDirectiveAlignmentIsInBytes = false; - LCOMMDirectiveAlignmentType = LCOMM::Log2Alignment; - InlineAsmStart = " InlineAsm Start"; - InlineAsmEnd = " InlineAsm End"; - - // Directives: - HasWeakDefDirective = true; - HasWeakDefCanBeHiddenDirective = true; - WeakRefDirective = "\t.weak_reference "; - ZeroDirective = "\t.space\t"; // ".space N" emits N zeros. - HasMachoZeroFillDirective = true; // Uses .zerofill - HasMachoTBSSDirective = true; // Uses .tbss - - // FIXME: Change this once MC is the system assembler. - HasAggressiveSymbolFolding = false; - - HiddenVisibilityAttr = MCSA_PrivateExtern; - HiddenDeclarationVisibilityAttr = MCSA_Invalid; - - // Doesn't support protected visibility. - ProtectedVisibilityAttr = MCSA_Invalid; - - HasDotTypeDotSizeDirective = false; - HasNoDeadStrip = true; - HasAltEntry = true; - - DwarfUsesRelocationsAcrossSections = false; - - UseIntegratedAssembler = true; - SetDirectiveSuppressesReloc = true; -} diff --git a/contrib/llvm/lib/MC/MCAsmInfoELF.cpp b/contrib/llvm/lib/MC/MCAsmInfoELF.cpp deleted file mode 100644 index a5e8aff7f129..000000000000 --- a/contrib/llvm/lib/MC/MCAsmInfoELF.cpp +++ /dev/null @@ -1,34 +0,0 @@ -//===- MCAsmInfoELF.cpp - ELF asm properties ------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines target asm properties related what form asm statements -// should take in general on ELF-based targets -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCAsmInfoELF.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCSectionELF.h" - -using namespace llvm; - -void MCAsmInfoELF::anchor() {} - -MCSection *MCAsmInfoELF::getNonexecutableStackSection(MCContext &Ctx) const { - if (!UsesNonexecutableStackSection) - return nullptr; - return Ctx.getELFSection(".note.GNU-stack", ELF::SHT_PROGBITS, 0); -} - -MCAsmInfoELF::MCAsmInfoELF() { - HasIdentDirective = true; - WeakRefDirective = "\t.weak\t"; - PrivateGlobalPrefix = ".L"; - PrivateLabelPrefix = ".L"; -} diff --git a/contrib/llvm/lib/MC/MCAsmInfoWasm.cpp b/contrib/llvm/lib/MC/MCAsmInfoWasm.cpp deleted file mode 100644 index ce6ec7ef211e..000000000000 --- a/contrib/llvm/lib/MC/MCAsmInfoWasm.cpp +++ /dev/null @@ -1,25 +0,0 @@ -//===-- MCAsmInfoWasm.cpp - Wasm asm properties -----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines target asm properties related what form asm statements -// should take in general on Wasm-based targets -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCAsmInfoWasm.h" -using namespace llvm; - -void MCAsmInfoWasm::anchor() {} - -MCAsmInfoWasm::MCAsmInfoWasm() { - HasIdentDirective = true; - HasNoDeadStrip = true; - WeakRefDirective = "\t.weak\t"; - PrivateGlobalPrefix = ".L"; - PrivateLabelPrefix = ".L"; -} diff --git a/contrib/llvm/lib/MC/MCAsmInfoXCOFF.cpp b/contrib/llvm/lib/MC/MCAsmInfoXCOFF.cpp deleted file mode 100644 index 74c21f0c9e6d..000000000000 --- a/contrib/llvm/lib/MC/MCAsmInfoXCOFF.cpp +++ /dev/null @@ -1,18 +0,0 @@ -//===- MC/MCAsmInfoXCOFF.cpp - XCOFF asm properties ------------ *- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCAsmInfoXCOFF.h" - -using namespace llvm; - -void MCAsmInfoXCOFF::anchor() {} - -MCAsmInfoXCOFF::MCAsmInfoXCOFF() { - IsLittleEndian = false; - HasDotTypeDotSizeDirective = false; -} diff --git a/contrib/llvm/lib/MC/MCAsmMacro.cpp b/contrib/llvm/lib/MC/MCAsmMacro.cpp deleted file mode 100644 index ba4fb7d4f387..000000000000 --- a/contrib/llvm/lib/MC/MCAsmMacro.cpp +++ /dev/null @@ -1,41 +0,0 @@ -//===- MCAsmMacro.h - Assembly Macros ---------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCAsmMacro.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -void MCAsmMacroParameter::dump(raw_ostream &OS) const { - OS << "\"" << Name << "\""; - if (Required) - OS << ":req"; - if (Vararg) - OS << ":vararg"; - if (!Value.empty()) { - OS << " = "; - bool first = true; - for (const AsmToken &T : Value) { - if (!first) - OS << ", "; - first = false; - OS << T.getString(); - } - } - OS << "\n"; -} - -void MCAsmMacro::dump(raw_ostream &OS) const { - OS << "Macro " << Name << ":\n"; - OS << " Parameters:\n"; - for (const MCAsmMacroParameter &P : Parameters) { - OS << " "; - P.dump(); - } - OS << " (BEGIN BODY)" << Body << "(END BODY)\n"; -} diff --git a/contrib/llvm/lib/MC/MCAsmStreamer.cpp b/contrib/llvm/lib/MC/MCAsmStreamer.cpp deleted file mode 100644 index 7a2b0b8a1220..000000000000 --- a/contrib/llvm/lib/MC/MCAsmStreamer.cpp +++ /dev/null @@ -1,1941 +0,0 @@ -//===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output ----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/Twine.h" -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCCodeEmitter.h" -#include "llvm/MC/MCCodeView.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFixupKindInfo.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCInstPrinter.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSectionMachO.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/LEB128.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/TargetRegistry.h" -#include <cctype> - -using namespace llvm; - -namespace { - -class MCAsmStreamer final : public MCStreamer { - std::unique_ptr<formatted_raw_ostream> OSOwner; - formatted_raw_ostream &OS; - const MCAsmInfo *MAI; - std::unique_ptr<MCInstPrinter> InstPrinter; - std::unique_ptr<MCAssembler> Assembler; - - SmallString<128> ExplicitCommentToEmit; - SmallString<128> CommentToEmit; - raw_svector_ostream CommentStream; - raw_null_ostream NullStream; - - unsigned IsVerboseAsm : 1; - unsigned ShowInst : 1; - unsigned UseDwarfDirectory : 1; - - void EmitRegisterName(int64_t Register); - void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; - void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; - -public: - MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os, - bool isVerboseAsm, bool useDwarfDirectory, - MCInstPrinter *printer, std::unique_ptr<MCCodeEmitter> emitter, - std::unique_ptr<MCAsmBackend> asmbackend, bool showInst) - : MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner), - MAI(Context.getAsmInfo()), InstPrinter(printer), - Assembler(llvm::make_unique<MCAssembler>( - Context, std::move(asmbackend), std::move(emitter), - (asmbackend) ? asmbackend->createObjectWriter(NullStream) - : nullptr)), - CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm), - ShowInst(showInst), UseDwarfDirectory(useDwarfDirectory) { - assert(InstPrinter); - if (IsVerboseAsm) - InstPrinter->setCommentStream(CommentStream); - } - - MCAssembler &getAssembler() { return *Assembler; } - MCAssembler *getAssemblerPtr() override { return nullptr; } - - inline void EmitEOL() { - // Dump Explicit Comments here. - emitExplicitComments(); - // If we don't have any comments, just emit a \n. - if (!IsVerboseAsm) { - OS << '\n'; - return; - } - EmitCommentsAndEOL(); - } - - void EmitSyntaxDirective() override; - - void EmitCommentsAndEOL(); - - /// Return true if this streamer supports verbose assembly at all. - bool isVerboseAsm() const override { return IsVerboseAsm; } - - /// Do we support EmitRawText? - bool hasRawTextSupport() const override { return true; } - - /// Add a comment that can be emitted to the generated .s file to make the - /// output of the compiler more readable. This only affects the MCAsmStreamer - /// and only when verbose assembly output is enabled. - void AddComment(const Twine &T, bool EOL = true) override; - - /// Add a comment showing the encoding of an instruction. - void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &); - - /// Return a raw_ostream that comments can be written to. - /// Unlike AddComment, you are required to terminate comments with \n if you - /// use this method. - raw_ostream &GetCommentOS() override { - if (!IsVerboseAsm) - return nulls(); // Discard comments unless in verbose asm mode. - return CommentStream; - } - - void emitRawComment(const Twine &T, bool TabPrefix = true) override; - - void addExplicitComment(const Twine &T) override; - void emitExplicitComments() override; - - /// Emit a blank line to a .s file to pretty it up. - void AddBlankLine() override { - EmitEOL(); - } - - /// @name MCStreamer Interface - /// @{ - - void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; - - void emitELFSymverDirective(StringRef AliasName, - const MCSymbol *Aliasee) override; - - void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override; - void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; - - void EmitAssemblerFlag(MCAssemblerFlag Flag) override; - void EmitLinkerOptions(ArrayRef<std::string> Options) override; - void EmitDataRegion(MCDataRegionType Kind) override; - void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor, - unsigned Update, VersionTuple SDKVersion) override; - void EmitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor, - unsigned Update, VersionTuple SDKVersion) override; - void EmitThumbFunc(MCSymbol *Func) override; - - void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; - void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; - bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; - - void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; - void BeginCOFFSymbolDef(const MCSymbol *Symbol) override; - void EmitCOFFSymbolStorageClass(int StorageClass) override; - void EmitCOFFSymbolType(int Type) override; - void EndCOFFSymbolDef() override; - void EmitCOFFSafeSEH(MCSymbol const *Symbol) override; - void EmitCOFFSymbolIndex(MCSymbol const *Symbol) override; - void EmitCOFFSectionIndex(MCSymbol const *Symbol) override; - void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override; - void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override; - void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; - void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) override; - - /// Emit a local common (.lcomm) symbol. - /// - /// @param Symbol - The common symbol to emit. - /// @param Size - The size of the common symbol. - /// @param ByteAlignment - The alignment of the common symbol in bytes. - void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) override; - - void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, - uint64_t Size = 0, unsigned ByteAlignment = 0, - SMLoc Loc = SMLoc()) override; - - void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment = 0) override; - - void EmitBinaryData(StringRef Data) override; - - void EmitBytes(StringRef Data) override; - - void EmitValueImpl(const MCExpr *Value, unsigned Size, - SMLoc Loc = SMLoc()) override; - void EmitIntValue(uint64_t Value, unsigned Size) override; - void EmitIntValueInHex(uint64_t Value, unsigned Size) override; - - void EmitULEB128Value(const MCExpr *Value) override; - - void EmitSLEB128Value(const MCExpr *Value) override; - - void EmitDTPRel32Value(const MCExpr *Value) override; - void EmitDTPRel64Value(const MCExpr *Value) override; - void EmitTPRel32Value(const MCExpr *Value) override; - void EmitTPRel64Value(const MCExpr *Value) override; - - void EmitGPRel64Value(const MCExpr *Value) override; - - void EmitGPRel32Value(const MCExpr *Value) override; - - void emitFill(const MCExpr &NumBytes, uint64_t FillValue, - SMLoc Loc = SMLoc()) override; - - void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr, - SMLoc Loc = SMLoc()) override; - - void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, - unsigned ValueSize = 1, - unsigned MaxBytesToEmit = 0) override; - - void EmitCodeAlignment(unsigned ByteAlignment, - unsigned MaxBytesToEmit = 0) override; - - void emitValueToOffset(const MCExpr *Offset, - unsigned char Value, - SMLoc Loc) override; - - void EmitFileDirective(StringRef Filename) override; - Expected<unsigned> tryEmitDwarfFileDirective(unsigned FileNo, - StringRef Directory, - StringRef Filename, - Optional<MD5::MD5Result> Checksum = None, - Optional<StringRef> Source = None, - unsigned CUID = 0) override; - void emitDwarfFile0Directive(StringRef Directory, StringRef Filename, - Optional<MD5::MD5Result> Checksum, - Optional<StringRef> Source, - unsigned CUID = 0) override; - void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, - unsigned Column, unsigned Flags, - unsigned Isa, unsigned Discriminator, - StringRef FileName) override; - MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override; - - bool EmitCVFileDirective(unsigned FileNo, StringRef Filename, - ArrayRef<uint8_t> Checksum, - unsigned ChecksumKind) override; - bool EmitCVFuncIdDirective(unsigned FuncId) override; - bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc, - unsigned IAFile, unsigned IALine, - unsigned IACol, SMLoc Loc) override; - void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line, - unsigned Column, bool PrologueEnd, bool IsStmt, - StringRef FileName, SMLoc Loc) override; - void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart, - const MCSymbol *FnEnd) override; - void EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId, - unsigned SourceFileId, - unsigned SourceLineNum, - const MCSymbol *FnStartSym, - const MCSymbol *FnEndSym) override; - void EmitCVDefRangeDirective( - ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, - StringRef FixedSizePortion) override; - void EmitCVStringTableDirective() override; - void EmitCVFileChecksumsDirective() override; - void EmitCVFileChecksumOffsetDirective(unsigned FileNo) override; - void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override; - - void EmitIdent(StringRef IdentString) override; - void EmitCFIBKeyFrame() override; - void EmitCFISections(bool EH, bool Debug) override; - void EmitCFIDefCfa(int64_t Register, int64_t Offset) override; - void EmitCFIDefCfaOffset(int64_t Offset) override; - void EmitCFIDefCfaRegister(int64_t Register) override; - void EmitCFIOffset(int64_t Register, int64_t Offset) override; - void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override; - void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) override; - void EmitCFIRememberState() override; - void EmitCFIRestoreState() override; - void EmitCFIRestore(int64_t Register) override; - void EmitCFISameValue(int64_t Register) override; - void EmitCFIRelOffset(int64_t Register, int64_t Offset) override; - void EmitCFIAdjustCfaOffset(int64_t Adjustment) override; - void EmitCFIEscape(StringRef Values) override; - void EmitCFIGnuArgsSize(int64_t Size) override; - void EmitCFISignalFrame() override; - void EmitCFIUndefined(int64_t Register) override; - void EmitCFIRegister(int64_t Register1, int64_t Register2) override; - void EmitCFIWindowSave() override; - void EmitCFINegateRAState() override; - void EmitCFIReturnColumn(int64_t Register) override; - - void EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override; - void EmitWinCFIEndProc(SMLoc Loc) override; - void EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) override; - void EmitWinCFIStartChained(SMLoc Loc) override; - void EmitWinCFIEndChained(SMLoc Loc) override; - void EmitWinCFIPushReg(unsigned Register, SMLoc Loc) override; - void EmitWinCFISetFrame(unsigned Register, unsigned Offset, - SMLoc Loc) override; - void EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) override; - void EmitWinCFISaveReg(unsigned Register, unsigned Offset, - SMLoc Loc) override; - void EmitWinCFISaveXMM(unsigned Register, unsigned Offset, - SMLoc Loc) override; - void EmitWinCFIPushFrame(bool Code, SMLoc Loc) override; - void EmitWinCFIEndProlog(SMLoc Loc) override; - - void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except, - SMLoc Loc) override; - void EmitWinEHHandlerData(SMLoc Loc) override; - - void emitCGProfileEntry(const MCSymbolRefExpr *From, - const MCSymbolRefExpr *To, uint64_t Count) override; - - void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; - - void EmitBundleAlignMode(unsigned AlignPow2) override; - void EmitBundleLock(bool AlignToEnd) override; - void EmitBundleUnlock() override; - - bool EmitRelocDirective(const MCExpr &Offset, StringRef Name, - const MCExpr *Expr, SMLoc Loc, - const MCSubtargetInfo &STI) override; - - void EmitAddrsig() override; - void EmitAddrsigSym(const MCSymbol *Sym) override; - - /// If this file is backed by an assembly streamer, this dumps the specified - /// string in the output .s file. This capability is indicated by the - /// hasRawTextSupport() predicate. - void EmitRawTextImpl(StringRef String) override; - - void FinishImpl() override; -}; - -} // end anonymous namespace. - -void MCAsmStreamer::AddComment(const Twine &T, bool EOL) { - if (!IsVerboseAsm) return; - - T.toVector(CommentToEmit); - - if (EOL) - CommentToEmit.push_back('\n'); // Place comment in a new line. -} - -void MCAsmStreamer::EmitCommentsAndEOL() { - if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) { - OS << '\n'; - return; - } - - StringRef Comments = CommentToEmit; - - assert(Comments.back() == '\n' && - "Comment array not newline terminated"); - do { - // Emit a line of comments. - OS.PadToColumn(MAI->getCommentColumn()); - size_t Position = Comments.find('\n'); - OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n'; - - Comments = Comments.substr(Position+1); - } while (!Comments.empty()); - - CommentToEmit.clear(); -} - -static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { - assert(Bytes > 0 && Bytes <= 8 && "Invalid size!"); - return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); -} - -void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) { - if (TabPrefix) - OS << '\t'; - OS << MAI->getCommentString() << T; - EmitEOL(); -} - -void MCAsmStreamer::addExplicitComment(const Twine &T) { - StringRef c = T.getSingleStringRef(); - if (c.equals(StringRef(MAI->getSeparatorString()))) - return; - if (c.startswith(StringRef("//"))) { - ExplicitCommentToEmit.append("\t"); - ExplicitCommentToEmit.append(MAI->getCommentString()); - // drop // - ExplicitCommentToEmit.append(c.slice(2, c.size()).str()); - } else if (c.startswith(StringRef("/*"))) { - size_t p = 2, len = c.size() - 2; - // emit each line in comment as separate newline. - do { - size_t newp = std::min(len, c.find_first_of("\r\n", p)); - ExplicitCommentToEmit.append("\t"); - ExplicitCommentToEmit.append(MAI->getCommentString()); - ExplicitCommentToEmit.append(c.slice(p, newp).str()); - // If we have another line in this comment add line - if (newp < len) - ExplicitCommentToEmit.append("\n"); - p = newp + 1; - } while (p < len); - } else if (c.startswith(StringRef(MAI->getCommentString()))) { - ExplicitCommentToEmit.append("\t"); - ExplicitCommentToEmit.append(c.str()); - } else if (c.front() == '#') { - - ExplicitCommentToEmit.append("\t"); - ExplicitCommentToEmit.append(MAI->getCommentString()); - ExplicitCommentToEmit.append(c.slice(1, c.size()).str()); - } else - assert(false && "Unexpected Assembly Comment"); - // full line comments immediately output - if (c.back() == '\n') - emitExplicitComments(); -} - -void MCAsmStreamer::emitExplicitComments() { - StringRef Comments = ExplicitCommentToEmit; - if (!Comments.empty()) - OS << Comments; - ExplicitCommentToEmit.clear(); -} - -void MCAsmStreamer::ChangeSection(MCSection *Section, - const MCExpr *Subsection) { - assert(Section && "Cannot switch to a null section!"); - if (MCTargetStreamer *TS = getTargetStreamer()) { - TS->changeSection(getCurrentSectionOnly(), Section, Subsection, OS); - } else { - Section->PrintSwitchToSection( - *MAI, getContext().getObjectFileInfo()->getTargetTriple(), OS, - Subsection); - } -} - -void MCAsmStreamer::emitELFSymverDirective(StringRef AliasName, - const MCSymbol *Aliasee) { - OS << ".symver "; - Aliasee->print(OS, MAI); - OS << ", " << AliasName; - EmitEOL(); -} - -void MCAsmStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) { - MCStreamer::EmitLabel(Symbol, Loc); - - Symbol->print(OS, MAI); - OS << MAI->getLabelSuffix(); - - EmitEOL(); -} - -void MCAsmStreamer::EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) { - StringRef str = MCLOHIdToName(Kind); - -#ifndef NDEBUG - int NbArgs = MCLOHIdToNbArgs(Kind); - assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!"); - assert(str != "" && "Invalid LOH name"); -#endif - - OS << "\t" << MCLOHDirectiveName() << " " << str << "\t"; - bool IsFirst = true; - for (const MCSymbol *Arg : Args) { - if (!IsFirst) - OS << ", "; - IsFirst = false; - Arg->print(OS, MAI); - } - EmitEOL(); -} - -void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { - switch (Flag) { - case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break; - case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break; - case MCAF_Code16: OS << '\t'<< MAI->getCode16Directive();break; - case MCAF_Code32: OS << '\t'<< MAI->getCode32Directive();break; - case MCAF_Code64: OS << '\t'<< MAI->getCode64Directive();break; - } - EmitEOL(); -} - -void MCAsmStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) { - assert(!Options.empty() && "At least one option is required!"); - OS << "\t.linker_option \"" << Options[0] << '"'; - for (ArrayRef<std::string>::iterator it = Options.begin() + 1, - ie = Options.end(); it != ie; ++it) { - OS << ", " << '"' << *it << '"'; - } - EmitEOL(); -} - -void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) { - if (!MAI->doesSupportDataRegionDirectives()) - return; - switch (Kind) { - case MCDR_DataRegion: OS << "\t.data_region"; break; - case MCDR_DataRegionJT8: OS << "\t.data_region jt8"; break; - case MCDR_DataRegionJT16: OS << "\t.data_region jt16"; break; - case MCDR_DataRegionJT32: OS << "\t.data_region jt32"; break; - case MCDR_DataRegionEnd: OS << "\t.end_data_region"; break; - } - EmitEOL(); -} - -static const char *getVersionMinDirective(MCVersionMinType Type) { - switch (Type) { - case MCVM_WatchOSVersionMin: return ".watchos_version_min"; - case MCVM_TvOSVersionMin: return ".tvos_version_min"; - case MCVM_IOSVersionMin: return ".ios_version_min"; - case MCVM_OSXVersionMin: return ".macosx_version_min"; - } - llvm_unreachable("Invalid MC version min type"); -} - -static void EmitSDKVersionSuffix(raw_ostream &OS, - const VersionTuple &SDKVersion) { - if (SDKVersion.empty()) - return; - OS << '\t' << "sdk_version " << SDKVersion.getMajor(); - if (auto Minor = SDKVersion.getMinor()) { - OS << ", " << *Minor; - if (auto Subminor = SDKVersion.getSubminor()) { - OS << ", " << *Subminor; - } - } -} - -void MCAsmStreamer::EmitVersionMin(MCVersionMinType Type, unsigned Major, - unsigned Minor, unsigned Update, - VersionTuple SDKVersion) { - OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor; - if (Update) - OS << ", " << Update; - EmitSDKVersionSuffix(OS, SDKVersion); - EmitEOL(); -} - -static const char *getPlatformName(MachO::PlatformType Type) { - switch (Type) { - case MachO::PLATFORM_MACOS: return "macos"; - case MachO::PLATFORM_IOS: return "ios"; - case MachO::PLATFORM_TVOS: return "tvos"; - case MachO::PLATFORM_WATCHOS: return "watchos"; - case MachO::PLATFORM_BRIDGEOS: return "bridgeos"; - case MachO::PLATFORM_MACCATALYST: return "macCatalyst"; - case MachO::PLATFORM_IOSSIMULATOR: return "iossimulator"; - case MachO::PLATFORM_TVOSSIMULATOR: return "tvossimulator"; - case MachO::PLATFORM_WATCHOSSIMULATOR: return "watchossimulator"; - } - llvm_unreachable("Invalid Mach-O platform type"); -} - -void MCAsmStreamer::EmitBuildVersion(unsigned Platform, unsigned Major, - unsigned Minor, unsigned Update, - VersionTuple SDKVersion) { - const char *PlatformName = getPlatformName((MachO::PlatformType)Platform); - OS << "\t.build_version " << PlatformName << ", " << Major << ", " << Minor; - if (Update) - OS << ", " << Update; - EmitSDKVersionSuffix(OS, SDKVersion); - EmitEOL(); -} - -void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) { - // This needs to emit to a temporary string to get properly quoted - // MCSymbols when they have spaces in them. - OS << "\t.thumb_func"; - // Only Mach-O hasSubsectionsViaSymbols() - if (MAI->hasSubsectionsViaSymbols()) { - OS << '\t'; - Func->print(OS, MAI); - } - EmitEOL(); -} - -void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { - // Do not emit a .set on inlined target assignments. - bool EmitSet = true; - if (auto *E = dyn_cast<MCTargetExpr>(Value)) - if (E->inlineAssignedExpr()) - EmitSet = false; - if (EmitSet) { - OS << ".set "; - Symbol->print(OS, MAI); - OS << ", "; - Value->print(OS, MAI); - - EmitEOL(); - } - - MCStreamer::EmitAssignment(Symbol, Value); -} - -void MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { - OS << ".weakref "; - Alias->print(OS, MAI); - OS << ", "; - Symbol->print(OS, MAI); - EmitEOL(); -} - -bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, - MCSymbolAttr Attribute) { - switch (Attribute) { - case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute"); - case MCSA_ELF_TypeFunction: /// .type _foo, STT_FUNC # aka @function - case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC - case MCSA_ELF_TypeObject: /// .type _foo, STT_OBJECT # aka @object - case MCSA_ELF_TypeTLS: /// .type _foo, STT_TLS # aka @tls_object - case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common - case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype - case MCSA_ELF_TypeGnuUniqueObject: /// .type _foo, @gnu_unique_object - if (!MAI->hasDotTypeDotSizeDirective()) - return false; // Symbol attribute not supported - OS << "\t.type\t"; - Symbol->print(OS, MAI); - OS << ',' << ((MAI->getCommentString()[0] != '@') ? '@' : '%'); - switch (Attribute) { - default: return false; - case MCSA_ELF_TypeFunction: OS << "function"; break; - case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break; - case MCSA_ELF_TypeObject: OS << "object"; break; - case MCSA_ELF_TypeTLS: OS << "tls_object"; break; - case MCSA_ELF_TypeCommon: OS << "common"; break; - case MCSA_ELF_TypeNoType: OS << "notype"; break; - case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break; - } - EmitEOL(); - return true; - case MCSA_Global: // .globl/.global - OS << MAI->getGlobalDirective(); - break; - case MCSA_Hidden: OS << "\t.hidden\t"; break; - case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break; - case MCSA_Internal: OS << "\t.internal\t"; break; - case MCSA_LazyReference: OS << "\t.lazy_reference\t"; break; - case MCSA_Local: OS << "\t.local\t"; break; - case MCSA_NoDeadStrip: - if (!MAI->hasNoDeadStrip()) - return false; - OS << "\t.no_dead_strip\t"; - break; - case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break; - case MCSA_AltEntry: OS << "\t.alt_entry\t"; break; - case MCSA_PrivateExtern: - OS << "\t.private_extern\t"; - break; - case MCSA_Protected: OS << "\t.protected\t"; break; - case MCSA_Reference: OS << "\t.reference\t"; break; - case MCSA_Weak: OS << MAI->getWeakDirective(); break; - case MCSA_WeakDefinition: - OS << "\t.weak_definition\t"; - break; - // .weak_reference - case MCSA_WeakReference: OS << MAI->getWeakRefDirective(); break; - case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break; - case MCSA_Cold: - // Assemblers currently do not support a .cold directive. - return false; - } - - Symbol->print(OS, MAI); - EmitEOL(); - - return true; -} - -void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { - OS << ".desc" << ' '; - Symbol->print(OS, MAI); - OS << ',' << DescValue; - EmitEOL(); -} - -void MCAsmStreamer::EmitSyntaxDirective() { - if (MAI->getAssemblerDialect() == 1) { - OS << "\t.intel_syntax noprefix"; - EmitEOL(); - } - // FIXME: Currently emit unprefix'ed registers. - // The intel_syntax directive has one optional argument - // with may have a value of prefix or noprefix. -} - -void MCAsmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) { - OS << "\t.def\t "; - Symbol->print(OS, MAI); - OS << ';'; - EmitEOL(); -} - -void MCAsmStreamer::EmitCOFFSymbolStorageClass (int StorageClass) { - OS << "\t.scl\t" << StorageClass << ';'; - EmitEOL(); -} - -void MCAsmStreamer::EmitCOFFSymbolType (int Type) { - OS << "\t.type\t" << Type << ';'; - EmitEOL(); -} - -void MCAsmStreamer::EndCOFFSymbolDef() { - OS << "\t.endef"; - EmitEOL(); -} - -void MCAsmStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) { - OS << "\t.safeseh\t"; - Symbol->print(OS, MAI); - EmitEOL(); -} - -void MCAsmStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) { - OS << "\t.symidx\t"; - Symbol->print(OS, MAI); - EmitEOL(); -} - -void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { - OS << "\t.secidx\t"; - Symbol->print(OS, MAI); - EmitEOL(); -} - -void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) { - OS << "\t.secrel32\t"; - Symbol->print(OS, MAI); - if (Offset != 0) - OS << '+' << Offset; - EmitEOL(); -} - -void MCAsmStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) { - OS << "\t.rva\t"; - Symbol->print(OS, MAI); - if (Offset > 0) - OS << '+' << Offset; - else if (Offset < 0) - OS << '-' << -Offset; - EmitEOL(); -} - -void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) { - assert(MAI->hasDotTypeDotSizeDirective()); - OS << "\t.size\t"; - Symbol->print(OS, MAI); - OS << ", "; - Value->print(OS, MAI); - EmitEOL(); -} - -void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) { - OS << "\t.comm\t"; - Symbol->print(OS, MAI); - OS << ',' << Size; - - if (ByteAlignment != 0) { - if (MAI->getCOMMDirectiveAlignmentIsInBytes()) - OS << ',' << ByteAlignment; - else - OS << ',' << Log2_32(ByteAlignment); - } - EmitEOL(); -} - -void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlign) { - OS << "\t.lcomm\t"; - Symbol->print(OS, MAI); - OS << ',' << Size; - - if (ByteAlign > 1) { - switch (MAI->getLCOMMDirectiveAlignmentType()) { - case LCOMM::NoAlignment: - llvm_unreachable("alignment not supported on .lcomm!"); - case LCOMM::ByteAlignment: - OS << ',' << ByteAlign; - break; - case LCOMM::Log2Alignment: - assert(isPowerOf2_32(ByteAlign) && "alignment must be a power of 2"); - OS << ',' << Log2_32(ByteAlign); - break; - } - } - EmitEOL(); -} - -void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment, - SMLoc Loc) { - if (Symbol) - AssignFragment(Symbol, &Section->getDummyFragment()); - - // Note: a .zerofill directive does not switch sections. - OS << ".zerofill "; - - assert(Section->getVariant() == MCSection::SV_MachO && - ".zerofill is a Mach-O specific directive"); - // This is a mach-o specific directive. - - const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section); - OS << MOSection->getSegmentName() << "," << MOSection->getSectionName(); - - if (Symbol) { - OS << ','; - Symbol->print(OS, MAI); - OS << ',' << Size; - if (ByteAlignment != 0) - OS << ',' << Log2_32(ByteAlignment); - } - EmitEOL(); -} - -// .tbss sym, size, align -// This depends that the symbol has already been mangled from the original, -// e.g. _a. -void MCAsmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment) { - AssignFragment(Symbol, &Section->getDummyFragment()); - - assert(Symbol && "Symbol shouldn't be NULL!"); - // Instead of using the Section we'll just use the shortcut. - - assert(Section->getVariant() == MCSection::SV_MachO && - ".zerofill is a Mach-O specific directive"); - // This is a mach-o specific directive and section. - - OS << ".tbss "; - Symbol->print(OS, MAI); - OS << ", " << Size; - - // Output align if we have it. We default to 1 so don't bother printing - // that. - if (ByteAlignment > 1) OS << ", " << Log2_32(ByteAlignment); - - EmitEOL(); -} - -static inline char toOctal(int X) { return (X&7)+'0'; } - -static void PrintQuotedString(StringRef Data, raw_ostream &OS) { - OS << '"'; - - for (unsigned i = 0, e = Data.size(); i != e; ++i) { - unsigned char C = Data[i]; - if (C == '"' || C == '\\') { - OS << '\\' << (char)C; - continue; - } - - if (isPrint((unsigned char)C)) { - OS << (char)C; - continue; - } - - switch (C) { - case '\b': OS << "\\b"; break; - case '\f': OS << "\\f"; break; - case '\n': OS << "\\n"; break; - case '\r': OS << "\\r"; break; - case '\t': OS << "\\t"; break; - default: - OS << '\\'; - OS << toOctal(C >> 6); - OS << toOctal(C >> 3); - OS << toOctal(C >> 0); - break; - } - } - - OS << '"'; -} - -void MCAsmStreamer::EmitBytes(StringRef Data) { - assert(getCurrentSectionOnly() && - "Cannot emit contents before setting section!"); - if (Data.empty()) return; - - // If only single byte is provided or no ascii or asciz directives is - // supported, emit as vector of 8bits data. - if (Data.size() == 1 || - !(MAI->getAscizDirective() || MAI->getAsciiDirective())) { - if (MCTargetStreamer *TS = getTargetStreamer()) { - TS->emitRawBytes(Data); - } else { - const char *Directive = MAI->getData8bitsDirective(); - for (const unsigned char C : Data.bytes()) { - OS << Directive << (unsigned)C; - EmitEOL(); - } - } - return; - } - - // If the data ends with 0 and the target supports .asciz, use it, otherwise - // use .ascii - if (MAI->getAscizDirective() && Data.back() == 0) { - OS << MAI->getAscizDirective(); - Data = Data.substr(0, Data.size()-1); - } else { - OS << MAI->getAsciiDirective(); - } - - PrintQuotedString(Data, OS); - EmitEOL(); -} - -void MCAsmStreamer::EmitBinaryData(StringRef Data) { - // This is binary data. Print it in a grid of hex bytes for readability. - const size_t Cols = 4; - for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) { - size_t J = I, EJ = std::min(I + Cols, Data.size()); - assert(EJ > 0); - OS << MAI->getData8bitsDirective(); - for (; J < EJ - 1; ++J) - OS << format("0x%02x", uint8_t(Data[J])) << ", "; - OS << format("0x%02x", uint8_t(Data[J])); - EmitEOL(); - } -} - -void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size) { - EmitValue(MCConstantExpr::create(Value, getContext()), Size); -} - -void MCAsmStreamer::EmitIntValueInHex(uint64_t Value, unsigned Size) { - EmitValue(MCConstantExpr::create(Value, getContext(), true), Size); -} - -void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, - SMLoc Loc) { - assert(Size <= 8 && "Invalid size"); - assert(getCurrentSectionOnly() && - "Cannot emit contents before setting section!"); - const char *Directive = nullptr; - switch (Size) { - default: break; - case 1: Directive = MAI->getData8bitsDirective(); break; - case 2: Directive = MAI->getData16bitsDirective(); break; - case 4: Directive = MAI->getData32bitsDirective(); break; - case 8: Directive = MAI->getData64bitsDirective(); break; - } - - if (!Directive) { - int64_t IntValue; - if (!Value->evaluateAsAbsolute(IntValue)) - report_fatal_error("Don't know how to emit this value."); - - // We couldn't handle the requested integer size so we fallback by breaking - // the request down into several, smaller, integers. - // Since sizes greater or equal to "Size" are invalid, we use the greatest - // power of 2 that is less than "Size" as our largest piece of granularity. - bool IsLittleEndian = MAI->isLittleEndian(); - for (unsigned Emitted = 0; Emitted != Size;) { - unsigned Remaining = Size - Emitted; - // The size of our partial emission must be a power of two less than - // Size. - unsigned EmissionSize = PowerOf2Floor(std::min(Remaining, Size - 1)); - // Calculate the byte offset of our partial emission taking into account - // the endianness of the target. - unsigned ByteOffset = - IsLittleEndian ? Emitted : (Remaining - EmissionSize); - uint64_t ValueToEmit = IntValue >> (ByteOffset * 8); - // We truncate our partial emission to fit within the bounds of the - // emission domain. This produces nicer output and silences potential - // truncation warnings when round tripping through another assembler. - uint64_t Shift = 64 - EmissionSize * 8; - assert(Shift < static_cast<uint64_t>( - std::numeric_limits<unsigned long long>::digits) && - "undefined behavior"); - ValueToEmit &= ~0ULL >> Shift; - EmitIntValue(ValueToEmit, EmissionSize); - Emitted += EmissionSize; - } - return; - } - - assert(Directive && "Invalid size for machine code value!"); - OS << Directive; - if (MCTargetStreamer *TS = getTargetStreamer()) { - TS->emitValue(Value); - } else { - Value->print(OS, MAI); - EmitEOL(); - } -} - -void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) { - int64_t IntValue; - if (Value->evaluateAsAbsolute(IntValue)) { - EmitULEB128IntValue(IntValue); - return; - } - OS << "\t.uleb128 "; - Value->print(OS, MAI); - EmitEOL(); -} - -void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) { - int64_t IntValue; - if (Value->evaluateAsAbsolute(IntValue)) { - EmitSLEB128IntValue(IntValue); - return; - } - OS << "\t.sleb128 "; - Value->print(OS, MAI); - EmitEOL(); -} - -void MCAsmStreamer::EmitDTPRel64Value(const MCExpr *Value) { - assert(MAI->getDTPRel64Directive() != nullptr); - OS << MAI->getDTPRel64Directive(); - Value->print(OS, MAI); - EmitEOL(); -} - -void MCAsmStreamer::EmitDTPRel32Value(const MCExpr *Value) { - assert(MAI->getDTPRel32Directive() != nullptr); - OS << MAI->getDTPRel32Directive(); - Value->print(OS, MAI); - EmitEOL(); -} - -void MCAsmStreamer::EmitTPRel64Value(const MCExpr *Value) { - assert(MAI->getTPRel64Directive() != nullptr); - OS << MAI->getTPRel64Directive(); - Value->print(OS, MAI); - EmitEOL(); -} - -void MCAsmStreamer::EmitTPRel32Value(const MCExpr *Value) { - assert(MAI->getTPRel32Directive() != nullptr); - OS << MAI->getTPRel32Directive(); - Value->print(OS, MAI); - EmitEOL(); -} - -void MCAsmStreamer::EmitGPRel64Value(const MCExpr *Value) { - assert(MAI->getGPRel64Directive() != nullptr); - OS << MAI->getGPRel64Directive(); - Value->print(OS, MAI); - EmitEOL(); -} - -void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) { - assert(MAI->getGPRel32Directive() != nullptr); - OS << MAI->getGPRel32Directive(); - Value->print(OS, MAI); - EmitEOL(); -} - -void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue, - SMLoc Loc) { - int64_t IntNumBytes; - if (NumBytes.evaluateAsAbsolute(IntNumBytes) && IntNumBytes == 0) - return; - - if (const char *ZeroDirective = MAI->getZeroDirective()) { - // FIXME: Emit location directives - OS << ZeroDirective; - NumBytes.print(OS, MAI); - if (FillValue != 0) - OS << ',' << (int)FillValue; - EmitEOL(); - return; - } - - MCStreamer::emitFill(NumBytes, FillValue); -} - -void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size, - int64_t Expr, SMLoc Loc) { - // FIXME: Emit location directives - OS << "\t.fill\t"; - NumValues.print(OS, MAI); - OS << ", " << Size << ", 0x"; - OS.write_hex(truncateToSize(Expr, 4)); - EmitEOL(); -} - -void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, - unsigned ValueSize, - unsigned MaxBytesToEmit) { - // Some assemblers don't support non-power of two alignments, so we always - // emit alignments as a power of two if possible. - if (isPowerOf2_32(ByteAlignment)) { - switch (ValueSize) { - default: - llvm_unreachable("Invalid size for machine code value!"); - case 1: - OS << "\t.p2align\t"; - break; - case 2: - OS << ".p2alignw "; - break; - case 4: - OS << ".p2alignl "; - break; - case 8: - llvm_unreachable("Unsupported alignment size!"); - } - - OS << Log2_32(ByteAlignment); - - if (Value || MaxBytesToEmit) { - OS << ", 0x"; - OS.write_hex(truncateToSize(Value, ValueSize)); - - if (MaxBytesToEmit) - OS << ", " << MaxBytesToEmit; - } - EmitEOL(); - return; - } - - // Non-power of two alignment. This is not widely supported by assemblers. - // FIXME: Parameterize this based on MAI. - switch (ValueSize) { - default: llvm_unreachable("Invalid size for machine code value!"); - case 1: OS << ".balign"; break; - case 2: OS << ".balignw"; break; - case 4: OS << ".balignl"; break; - case 8: llvm_unreachable("Unsupported alignment size!"); - } - - OS << ' ' << ByteAlignment; - OS << ", " << truncateToSize(Value, ValueSize); - if (MaxBytesToEmit) - OS << ", " << MaxBytesToEmit; - EmitEOL(); -} - -void MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment, - unsigned MaxBytesToEmit) { - // Emit with a text fill value. - EmitValueToAlignment(ByteAlignment, MAI->getTextAlignFillValue(), - 1, MaxBytesToEmit); -} - -void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset, - unsigned char Value, - SMLoc Loc) { - // FIXME: Verify that Offset is associated with the current section. - OS << ".org "; - Offset->print(OS, MAI); - OS << ", " << (unsigned)Value; - EmitEOL(); -} - -void MCAsmStreamer::EmitFileDirective(StringRef Filename) { - assert(MAI->hasSingleParameterDotFile()); - OS << "\t.file\t"; - PrintQuotedString(Filename, OS); - EmitEOL(); -} - -static void printDwarfFileDirective(unsigned FileNo, StringRef Directory, - StringRef Filename, - Optional<MD5::MD5Result> Checksum, - Optional<StringRef> Source, - bool UseDwarfDirectory, - raw_svector_ostream &OS) { - SmallString<128> FullPathName; - - if (!UseDwarfDirectory && !Directory.empty()) { - if (sys::path::is_absolute(Filename)) - Directory = ""; - else { - FullPathName = Directory; - sys::path::append(FullPathName, Filename); - Directory = ""; - Filename = FullPathName; - } - } - - OS << "\t.file\t" << FileNo << ' '; - if (!Directory.empty()) { - PrintQuotedString(Directory, OS); - OS << ' '; - } - PrintQuotedString(Filename, OS); - if (Checksum) - OS << " md5 0x" << Checksum->digest(); - if (Source) { - OS << " source "; - PrintQuotedString(*Source, OS); - } -} - -Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective( - unsigned FileNo, StringRef Directory, StringRef Filename, - Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source, unsigned CUID) { - assert(CUID == 0 && "multiple CUs not supported by MCAsmStreamer"); - - MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID); - unsigned NumFiles = Table.getMCDwarfFiles().size(); - Expected<unsigned> FileNoOrErr = - Table.tryGetFile(Directory, Filename, Checksum, Source, - getContext().getDwarfVersion(), FileNo); - if (!FileNoOrErr) - return FileNoOrErr.takeError(); - FileNo = FileNoOrErr.get(); - if (NumFiles == Table.getMCDwarfFiles().size()) - return FileNo; - - SmallString<128> Str; - raw_svector_ostream OS1(Str); - printDwarfFileDirective(FileNo, Directory, Filename, Checksum, Source, - UseDwarfDirectory, OS1); - - if (MCTargetStreamer *TS = getTargetStreamer()) - TS->emitDwarfFileDirective(OS1.str()); - else - EmitRawText(OS1.str()); - - return FileNo; -} - -void MCAsmStreamer::emitDwarfFile0Directive(StringRef Directory, - StringRef Filename, - Optional<MD5::MD5Result> Checksum, - Optional<StringRef> Source, - unsigned CUID) { - assert(CUID == 0); - // .file 0 is new for DWARF v5. - if (getContext().getDwarfVersion() < 5) - return; - // Inform MCDwarf about the root file. - getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum, - Source); - - SmallString<128> Str; - raw_svector_ostream OS1(Str); - printDwarfFileDirective(0, Directory, Filename, Checksum, Source, - UseDwarfDirectory, OS1); - - if (MCTargetStreamer *TS = getTargetStreamer()) - TS->emitDwarfFileDirective(OS1.str()); - else - EmitRawText(OS1.str()); -} - -void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, - unsigned Column, unsigned Flags, - unsigned Isa, - unsigned Discriminator, - StringRef FileName) { - OS << "\t.loc\t" << FileNo << " " << Line << " " << Column; - if (MAI->supportsExtendedDwarfLocDirective()) { - if (Flags & DWARF2_FLAG_BASIC_BLOCK) - OS << " basic_block"; - if (Flags & DWARF2_FLAG_PROLOGUE_END) - OS << " prologue_end"; - if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN) - OS << " epilogue_begin"; - - unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags(); - if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) { - OS << " is_stmt "; - - if (Flags & DWARF2_FLAG_IS_STMT) - OS << "1"; - else - OS << "0"; - } - - if (Isa) - OS << " isa " << Isa; - if (Discriminator) - OS << " discriminator " << Discriminator; - } - - if (IsVerboseAsm) { - OS.PadToColumn(MAI->getCommentColumn()); - OS << MAI->getCommentString() << ' ' << FileName << ':' - << Line << ':' << Column; - } - EmitEOL(); - this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, - Isa, Discriminator, FileName); -} - -MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) { - // Always use the zeroth line table, since asm syntax only supports one line - // table for now. - return MCStreamer::getDwarfLineTableSymbol(0); -} - -bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename, - ArrayRef<uint8_t> Checksum, - unsigned ChecksumKind) { - if (!getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum, - ChecksumKind)) - return false; - - OS << "\t.cv_file\t" << FileNo << ' '; - PrintQuotedString(Filename, OS); - - if (!ChecksumKind) { - EmitEOL(); - return true; - } - - OS << ' '; - PrintQuotedString(toHex(Checksum), OS); - OS << ' ' << ChecksumKind; - - EmitEOL(); - return true; -} - -bool MCAsmStreamer::EmitCVFuncIdDirective(unsigned FuncId) { - OS << "\t.cv_func_id " << FuncId << '\n'; - return MCStreamer::EmitCVFuncIdDirective(FuncId); -} - -bool MCAsmStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId, - unsigned IAFunc, - unsigned IAFile, - unsigned IALine, unsigned IACol, - SMLoc Loc) { - OS << "\t.cv_inline_site_id " << FunctionId << " within " << IAFunc - << " inlined_at " << IAFile << ' ' << IALine << ' ' << IACol << '\n'; - return MCStreamer::EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile, - IALine, IACol, Loc); -} - -void MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, - unsigned Line, unsigned Column, - bool PrologueEnd, bool IsStmt, - StringRef FileName, SMLoc Loc) { - // Validate the directive. - if (!checkCVLocSection(FunctionId, FileNo, Loc)) - return; - - OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " " - << Column; - if (PrologueEnd) - OS << " prologue_end"; - - if (IsStmt) - OS << " is_stmt 1"; - - if (IsVerboseAsm) { - OS.PadToColumn(MAI->getCommentColumn()); - OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':' - << Column; - } - EmitEOL(); -} - -void MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId, - const MCSymbol *FnStart, - const MCSymbol *FnEnd) { - OS << "\t.cv_linetable\t" << FunctionId << ", "; - FnStart->print(OS, MAI); - OS << ", "; - FnEnd->print(OS, MAI); - EmitEOL(); - this->MCStreamer::EmitCVLinetableDirective(FunctionId, FnStart, FnEnd); -} - -void MCAsmStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId, - unsigned SourceFileId, - unsigned SourceLineNum, - const MCSymbol *FnStartSym, - const MCSymbol *FnEndSym) { - OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId - << ' ' << SourceLineNum << ' '; - FnStartSym->print(OS, MAI); - OS << ' '; - FnEndSym->print(OS, MAI); - EmitEOL(); - this->MCStreamer::EmitCVInlineLinetableDirective( - PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym); -} - -void MCAsmStreamer::EmitCVDefRangeDirective( - ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, - StringRef FixedSizePortion) { - OS << "\t.cv_def_range\t"; - for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) { - OS << ' '; - Range.first->print(OS, MAI); - OS << ' '; - Range.second->print(OS, MAI); - } - OS << ", "; - PrintQuotedString(FixedSizePortion, OS); - EmitEOL(); - this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion); -} - -void MCAsmStreamer::EmitCVStringTableDirective() { - OS << "\t.cv_stringtable"; - EmitEOL(); -} - -void MCAsmStreamer::EmitCVFileChecksumsDirective() { - OS << "\t.cv_filechecksums"; - EmitEOL(); -} - -void MCAsmStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) { - OS << "\t.cv_filechecksumoffset\t" << FileNo; - EmitEOL(); -} - -void MCAsmStreamer::EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) { - OS << "\t.cv_fpo_data\t"; - ProcSym->print(OS, MAI); - EmitEOL(); -} - -void MCAsmStreamer::EmitIdent(StringRef IdentString) { - assert(MAI->hasIdentDirective() && ".ident directive not supported"); - OS << "\t.ident\t"; - PrintQuotedString(IdentString, OS); - EmitEOL(); -} - -void MCAsmStreamer::EmitCFISections(bool EH, bool Debug) { - MCStreamer::EmitCFISections(EH, Debug); - OS << "\t.cfi_sections "; - if (EH) { - OS << ".eh_frame"; - if (Debug) - OS << ", .debug_frame"; - } else if (Debug) { - OS << ".debug_frame"; - } - - EmitEOL(); -} - -void MCAsmStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { - OS << "\t.cfi_startproc"; - if (Frame.IsSimple) - OS << " simple"; - EmitEOL(); -} - -void MCAsmStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { - MCStreamer::EmitCFIEndProcImpl(Frame); - OS << "\t.cfi_endproc"; - EmitEOL(); -} - -void MCAsmStreamer::EmitRegisterName(int64_t Register) { - if (!MAI->useDwarfRegNumForCFI()) { - // User .cfi_* directives can use arbitrary DWARF register numbers, not - // just ones that map to LLVM register numbers and have known names. - // Fall back to using the original number directly if no name is known. - const MCRegisterInfo *MRI = getContext().getRegisterInfo(); - int LLVMRegister = MRI->getLLVMRegNumFromEH(Register); - if (LLVMRegister != -1) { - InstPrinter->printRegName(OS, LLVMRegister); - return; - } - } - OS << Register; -} - -void MCAsmStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { - MCStreamer::EmitCFIDefCfa(Register, Offset); - OS << "\t.cfi_def_cfa "; - EmitRegisterName(Register); - OS << ", " << Offset; - EmitEOL(); -} - -void MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) { - MCStreamer::EmitCFIDefCfaOffset(Offset); - OS << "\t.cfi_def_cfa_offset " << Offset; - EmitEOL(); -} - -static void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) { - OS << "\t.cfi_escape "; - if (!Values.empty()) { - size_t e = Values.size() - 1; - for (size_t i = 0; i < e; ++i) - OS << format("0x%02x", uint8_t(Values[i])) << ", "; - OS << format("0x%02x", uint8_t(Values[e])); - } -} - -void MCAsmStreamer::EmitCFIEscape(StringRef Values) { - MCStreamer::EmitCFIEscape(Values); - PrintCFIEscape(OS, Values); - EmitEOL(); -} - -void MCAsmStreamer::EmitCFIGnuArgsSize(int64_t Size) { - MCStreamer::EmitCFIGnuArgsSize(Size); - - uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size }; - unsigned Len = encodeULEB128(Size, Buffer + 1) + 1; - - PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len)); - EmitEOL(); -} - -void MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) { - MCStreamer::EmitCFIDefCfaRegister(Register); - OS << "\t.cfi_def_cfa_register "; - EmitRegisterName(Register); - EmitEOL(); -} - -void MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { - this->MCStreamer::EmitCFIOffset(Register, Offset); - OS << "\t.cfi_offset "; - EmitRegisterName(Register); - OS << ", " << Offset; - EmitEOL(); -} - -void MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym, - unsigned Encoding) { - MCStreamer::EmitCFIPersonality(Sym, Encoding); - OS << "\t.cfi_personality " << Encoding << ", "; - Sym->print(OS, MAI); - EmitEOL(); -} - -void MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { - MCStreamer::EmitCFILsda(Sym, Encoding); - OS << "\t.cfi_lsda " << Encoding << ", "; - Sym->print(OS, MAI); - EmitEOL(); -} - -void MCAsmStreamer::EmitCFIRememberState() { - MCStreamer::EmitCFIRememberState(); - OS << "\t.cfi_remember_state"; - EmitEOL(); -} - -void MCAsmStreamer::EmitCFIRestoreState() { - MCStreamer::EmitCFIRestoreState(); - OS << "\t.cfi_restore_state"; - EmitEOL(); -} - -void MCAsmStreamer::EmitCFIRestore(int64_t Register) { - MCStreamer::EmitCFIRestore(Register); - OS << "\t.cfi_restore "; - EmitRegisterName(Register); - EmitEOL(); -} - -void MCAsmStreamer::EmitCFISameValue(int64_t Register) { - MCStreamer::EmitCFISameValue(Register); - OS << "\t.cfi_same_value "; - EmitRegisterName(Register); - EmitEOL(); -} - -void MCAsmStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) { - MCStreamer::EmitCFIRelOffset(Register, Offset); - OS << "\t.cfi_rel_offset "; - EmitRegisterName(Register); - OS << ", " << Offset; - EmitEOL(); -} - -void MCAsmStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) { - MCStreamer::EmitCFIAdjustCfaOffset(Adjustment); - OS << "\t.cfi_adjust_cfa_offset " << Adjustment; - EmitEOL(); -} - -void MCAsmStreamer::EmitCFISignalFrame() { - MCStreamer::EmitCFISignalFrame(); - OS << "\t.cfi_signal_frame"; - EmitEOL(); -} - -void MCAsmStreamer::EmitCFIUndefined(int64_t Register) { - MCStreamer::EmitCFIUndefined(Register); - OS << "\t.cfi_undefined " << Register; - EmitEOL(); -} - -void MCAsmStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) { - MCStreamer::EmitCFIRegister(Register1, Register2); - OS << "\t.cfi_register " << Register1 << ", " << Register2; - EmitEOL(); -} - -void MCAsmStreamer::EmitCFIWindowSave() { - MCStreamer::EmitCFIWindowSave(); - OS << "\t.cfi_window_save"; - EmitEOL(); -} - -void MCAsmStreamer::EmitCFINegateRAState() { - MCStreamer::EmitCFINegateRAState(); - OS << "\t.cfi_negate_ra_state"; - EmitEOL(); -} - -void MCAsmStreamer::EmitCFIReturnColumn(int64_t Register) { - MCStreamer::EmitCFIReturnColumn(Register); - OS << "\t.cfi_return_column " << Register; - EmitEOL(); -} - -void MCAsmStreamer::EmitCFIBKeyFrame() { - MCStreamer::EmitCFIBKeyFrame(); - OS << "\t.cfi_b_key_frame"; - EmitEOL(); -} - -void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) { - MCStreamer::EmitWinCFIStartProc(Symbol, Loc); - - OS << ".seh_proc "; - Symbol->print(OS, MAI); - EmitEOL(); -} - -void MCAsmStreamer::EmitWinCFIEndProc(SMLoc Loc) { - MCStreamer::EmitWinCFIEndProc(Loc); - - OS << "\t.seh_endproc"; - EmitEOL(); -} - -// TODO: Implement -void MCAsmStreamer::EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) { -} - -void MCAsmStreamer::EmitWinCFIStartChained(SMLoc Loc) { - MCStreamer::EmitWinCFIStartChained(Loc); - - OS << "\t.seh_startchained"; - EmitEOL(); -} - -void MCAsmStreamer::EmitWinCFIEndChained(SMLoc Loc) { - MCStreamer::EmitWinCFIEndChained(Loc); - - OS << "\t.seh_endchained"; - EmitEOL(); -} - -void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, - bool Except, SMLoc Loc) { - MCStreamer::EmitWinEHHandler(Sym, Unwind, Except, Loc); - - OS << "\t.seh_handler "; - Sym->print(OS, MAI); - if (Unwind) - OS << ", @unwind"; - if (Except) - OS << ", @except"; - EmitEOL(); -} - -void MCAsmStreamer::EmitWinEHHandlerData(SMLoc Loc) { - MCStreamer::EmitWinEHHandlerData(Loc); - - // Switch sections. Don't call SwitchSection directly, because that will - // cause the section switch to be visible in the emitted assembly. - // We only do this so the section switch that terminates the handler - // data block is visible. - WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo(); - MCSection *TextSec = &CurFrame->Function->getSection(); - MCSection *XData = getAssociatedXDataSection(TextSec); - SwitchSectionNoChange(XData); - - OS << "\t.seh_handlerdata"; - EmitEOL(); -} - -void MCAsmStreamer::EmitWinCFIPushReg(unsigned Register, SMLoc Loc) { - MCStreamer::EmitWinCFIPushReg(Register, Loc); - - OS << "\t.seh_pushreg " << Register; - EmitEOL(); -} - -void MCAsmStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset, - SMLoc Loc) { - MCStreamer::EmitWinCFISetFrame(Register, Offset, Loc); - - OS << "\t.seh_setframe " << Register << ", " << Offset; - EmitEOL(); -} - -void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) { - MCStreamer::EmitWinCFIAllocStack(Size, Loc); - - OS << "\t.seh_stackalloc " << Size; - EmitEOL(); -} - -void MCAsmStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset, - SMLoc Loc) { - MCStreamer::EmitWinCFISaveReg(Register, Offset, Loc); - - OS << "\t.seh_savereg " << Register << ", " << Offset; - EmitEOL(); -} - -void MCAsmStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset, - SMLoc Loc) { - MCStreamer::EmitWinCFISaveXMM(Register, Offset, Loc); - - OS << "\t.seh_savexmm " << Register << ", " << Offset; - EmitEOL(); -} - -void MCAsmStreamer::EmitWinCFIPushFrame(bool Code, SMLoc Loc) { - MCStreamer::EmitWinCFIPushFrame(Code, Loc); - - OS << "\t.seh_pushframe"; - if (Code) - OS << " @code"; - EmitEOL(); -} - -void MCAsmStreamer::EmitWinCFIEndProlog(SMLoc Loc) { - MCStreamer::EmitWinCFIEndProlog(Loc); - - OS << "\t.seh_endprologue"; - EmitEOL(); -} - -void MCAsmStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From, - const MCSymbolRefExpr *To, - uint64_t Count) { - OS << "\t.cg_profile "; - From->getSymbol().print(OS, MAI); - OS << ", "; - To->getSymbol().print(OS, MAI); - OS << ", " << Count; - EmitEOL(); -} - -void MCAsmStreamer::AddEncodingComment(const MCInst &Inst, - const MCSubtargetInfo &STI) { - raw_ostream &OS = GetCommentOS(); - SmallString<256> Code; - SmallVector<MCFixup, 4> Fixups; - raw_svector_ostream VecOS(Code); - - // If we have no code emitter, don't emit code. - if (!getAssembler().getEmitterPtr()) - return; - - getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); - - // If we are showing fixups, create symbolic markers in the encoded - // representation. We do this by making a per-bit map to the fixup item index, - // then trying to display it as nicely as possible. - SmallVector<uint8_t, 64> FixupMap; - FixupMap.resize(Code.size() * 8); - for (unsigned i = 0, e = Code.size() * 8; i != e; ++i) - FixupMap[i] = 0; - - for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { - MCFixup &F = Fixups[i]; - const MCFixupKindInfo &Info = - getAssembler().getBackend().getFixupKindInfo(F.getKind()); - for (unsigned j = 0; j != Info.TargetSize; ++j) { - unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j; - assert(Index < Code.size() * 8 && "Invalid offset in fixup!"); - FixupMap[Index] = 1 + i; - } - } - - // FIXME: Note the fixup comments for Thumb2 are completely bogus since the - // high order halfword of a 32-bit Thumb2 instruction is emitted first. - OS << "encoding: ["; - for (unsigned i = 0, e = Code.size(); i != e; ++i) { - if (i) - OS << ','; - - // See if all bits are the same map entry. - uint8_t MapEntry = FixupMap[i * 8 + 0]; - for (unsigned j = 1; j != 8; ++j) { - if (FixupMap[i * 8 + j] == MapEntry) - continue; - - MapEntry = uint8_t(~0U); - break; - } - - if (MapEntry != uint8_t(~0U)) { - if (MapEntry == 0) { - OS << format("0x%02x", uint8_t(Code[i])); - } else { - if (Code[i]) { - // FIXME: Some of the 8 bits require fix up. - OS << format("0x%02x", uint8_t(Code[i])) << '\'' - << char('A' + MapEntry - 1) << '\''; - } else - OS << char('A' + MapEntry - 1); - } - } else { - // Otherwise, write out in binary. - OS << "0b"; - for (unsigned j = 8; j--;) { - unsigned Bit = (Code[i] >> j) & 1; - - unsigned FixupBit; - if (MAI->isLittleEndian()) - FixupBit = i * 8 + j; - else - FixupBit = i * 8 + (7-j); - - if (uint8_t MapEntry = FixupMap[FixupBit]) { - assert(Bit == 0 && "Encoder wrote into fixed up bit!"); - OS << char('A' + MapEntry - 1); - } else - OS << Bit; - } - } - } - OS << "]\n"; - - for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { - MCFixup &F = Fixups[i]; - const MCFixupKindInfo &Info = - getAssembler().getBackend().getFixupKindInfo(F.getKind()); - OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset() - << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n"; - } -} - -void MCAsmStreamer::EmitInstruction(const MCInst &Inst, - const MCSubtargetInfo &STI) { - assert(getCurrentSectionOnly() && - "Cannot emit contents before setting section!"); - - // Show the encoding in a comment if we have a code emitter. - AddEncodingComment(Inst, STI); - - // Show the MCInst if enabled. - if (ShowInst) { - Inst.dump_pretty(GetCommentOS(), InstPrinter.get(), "\n "); - GetCommentOS() << "\n"; - } - - if(getTargetStreamer()) - getTargetStreamer()->prettyPrintAsm(*InstPrinter, OS, Inst, STI); - else - InstPrinter->printInst(&Inst, OS, "", STI); - - StringRef Comments = CommentToEmit; - if (Comments.size() && Comments.back() != '\n') - GetCommentOS() << "\n"; - - EmitEOL(); -} - -void MCAsmStreamer::EmitBundleAlignMode(unsigned AlignPow2) { - OS << "\t.bundle_align_mode " << AlignPow2; - EmitEOL(); -} - -void MCAsmStreamer::EmitBundleLock(bool AlignToEnd) { - OS << "\t.bundle_lock"; - if (AlignToEnd) - OS << " align_to_end"; - EmitEOL(); -} - -void MCAsmStreamer::EmitBundleUnlock() { - OS << "\t.bundle_unlock"; - EmitEOL(); -} - -bool MCAsmStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name, - const MCExpr *Expr, SMLoc, - const MCSubtargetInfo &STI) { - OS << "\t.reloc "; - Offset.print(OS, MAI); - OS << ", " << Name; - if (Expr) { - OS << ", "; - Expr->print(OS, MAI); - } - EmitEOL(); - return false; -} - -void MCAsmStreamer::EmitAddrsig() { - OS << "\t.addrsig"; - EmitEOL(); -} - -void MCAsmStreamer::EmitAddrsigSym(const MCSymbol *Sym) { - OS << "\t.addrsig_sym "; - Sym->print(OS, MAI); - EmitEOL(); -} - -/// EmitRawText - If this file is backed by an assembly streamer, this dumps -/// the specified string in the output .s file. This capability is -/// indicated by the hasRawTextSupport() predicate. -void MCAsmStreamer::EmitRawTextImpl(StringRef String) { - if (!String.empty() && String.back() == '\n') - String = String.substr(0, String.size()-1); - OS << String; - EmitEOL(); -} - -void MCAsmStreamer::FinishImpl() { - // If we are generating dwarf for assembly source files dump out the sections. - if (getContext().getGenDwarfForAssembly()) - MCGenDwarfInfo::Emit(this); - - // Emit the label for the line table, if requested - since the rest of the - // line table will be defined by .loc/.file directives, and not emitted - // directly, the label is the only work required here. - const auto &Tables = getContext().getMCDwarfLineTables(); - if (!Tables.empty()) { - assert(Tables.size() == 1 && "asm output only supports one line table"); - if (auto *Label = Tables.begin()->second.getLabel()) { - SwitchSection(getContext().getObjectFileInfo()->getDwarfLineSection()); - EmitLabel(Label); - } - } -} - -MCStreamer *llvm::createAsmStreamer(MCContext &Context, - std::unique_ptr<formatted_raw_ostream> OS, - bool isVerboseAsm, bool useDwarfDirectory, - MCInstPrinter *IP, - std::unique_ptr<MCCodeEmitter> &&CE, - std::unique_ptr<MCAsmBackend> &&MAB, - bool ShowInst) { - return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm, - useDwarfDirectory, IP, std::move(CE), std::move(MAB), - ShowInst); -} diff --git a/contrib/llvm/lib/MC/MCAssembler.cpp b/contrib/llvm/lib/MC/MCAssembler.cpp deleted file mode 100644 index 22a8e73e4af3..000000000000 --- a/contrib/llvm/lib/MC/MCAssembler.cpp +++ /dev/null @@ -1,1154 +0,0 @@ -//===- lib/MC/MCAssembler.cpp - Assembler Backend Implementation ----------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCAssembler.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCAsmLayout.h" -#include "llvm/MC/MCCodeEmitter.h" -#include "llvm/MC/MCCodeView.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDwarf.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFixup.h" -#include "llvm/MC/MCFixupKindInfo.h" -#include "llvm/MC/MCFragment.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSectionELF.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCValue.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/LEB128.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> -#include <cstdint> -#include <cstring> -#include <tuple> -#include <utility> - -using namespace llvm; - -#define DEBUG_TYPE "assembler" - -namespace { -namespace stats { - -STATISTIC(EmittedFragments, "Number of emitted assembler fragments - total"); -STATISTIC(EmittedRelaxableFragments, - "Number of emitted assembler fragments - relaxable"); -STATISTIC(EmittedDataFragments, - "Number of emitted assembler fragments - data"); -STATISTIC(EmittedCompactEncodedInstFragments, - "Number of emitted assembler fragments - compact encoded inst"); -STATISTIC(EmittedAlignFragments, - "Number of emitted assembler fragments - align"); -STATISTIC(EmittedFillFragments, - "Number of emitted assembler fragments - fill"); -STATISTIC(EmittedOrgFragments, - "Number of emitted assembler fragments - org"); -STATISTIC(evaluateFixup, "Number of evaluated fixups"); -STATISTIC(FragmentLayouts, "Number of fragment layouts"); -STATISTIC(ObjectBytes, "Number of emitted object file bytes"); -STATISTIC(RelaxationSteps, "Number of assembler layout and relaxation steps"); -STATISTIC(RelaxedInstructions, "Number of relaxed instructions"); -STATISTIC(PaddingFragmentsRelaxations, - "Number of Padding Fragments relaxations"); -STATISTIC(PaddingFragmentsBytes, - "Total size of all padding from adding Fragments"); - -} // end namespace stats -} // end anonymous namespace - -// FIXME FIXME FIXME: There are number of places in this file where we convert -// what is a 64-bit assembler value used for computation into a value in the -// object file, which may truncate it. We should detect that truncation where -// invalid and report errors back. - -/* *** */ - -MCAssembler::MCAssembler(MCContext &Context, - std::unique_ptr<MCAsmBackend> Backend, - std::unique_ptr<MCCodeEmitter> Emitter, - std::unique_ptr<MCObjectWriter> Writer) - : Context(Context), Backend(std::move(Backend)), - Emitter(std::move(Emitter)), Writer(std::move(Writer)), - BundleAlignSize(0), RelaxAll(false), SubsectionsViaSymbols(false), - IncrementalLinkerCompatible(false), ELFHeaderEFlags(0) { - VersionInfo.Major = 0; // Major version == 0 for "none specified" -} - -MCAssembler::~MCAssembler() = default; - -void MCAssembler::reset() { - Sections.clear(); - Symbols.clear(); - IndirectSymbols.clear(); - DataRegions.clear(); - LinkerOptions.clear(); - FileNames.clear(); - ThumbFuncs.clear(); - BundleAlignSize = 0; - RelaxAll = false; - SubsectionsViaSymbols = false; - IncrementalLinkerCompatible = false; - ELFHeaderEFlags = 0; - LOHContainer.reset(); - VersionInfo.Major = 0; - VersionInfo.SDKVersion = VersionTuple(); - - // reset objects owned by us - if (getBackendPtr()) - getBackendPtr()->reset(); - if (getEmitterPtr()) - getEmitterPtr()->reset(); - if (getWriterPtr()) - getWriterPtr()->reset(); - getLOHContainer().reset(); -} - -bool MCAssembler::registerSection(MCSection &Section) { - if (Section.isRegistered()) - return false; - Sections.push_back(&Section); - Section.setIsRegistered(true); - return true; -} - -bool MCAssembler::isThumbFunc(const MCSymbol *Symbol) const { - if (ThumbFuncs.count(Symbol)) - return true; - - if (!Symbol->isVariable()) - return false; - - const MCExpr *Expr = Symbol->getVariableValue(); - - MCValue V; - if (!Expr->evaluateAsRelocatable(V, nullptr, nullptr)) - return false; - - if (V.getSymB() || V.getRefKind() != MCSymbolRefExpr::VK_None) - return false; - - const MCSymbolRefExpr *Ref = V.getSymA(); - if (!Ref) - return false; - - if (Ref->getKind() != MCSymbolRefExpr::VK_None) - return false; - - const MCSymbol &Sym = Ref->getSymbol(); - if (!isThumbFunc(&Sym)) - return false; - - ThumbFuncs.insert(Symbol); // Cache it. - return true; -} - -bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const { - // Non-temporary labels should always be visible to the linker. - if (!Symbol.isTemporary()) - return true; - - // Absolute temporary labels are never visible. - if (!Symbol.isInSection()) - return false; - - if (Symbol.isUsedInReloc()) - return true; - - return false; -} - -const MCSymbol *MCAssembler::getAtom(const MCSymbol &S) const { - // Linker visible symbols define atoms. - if (isSymbolLinkerVisible(S)) - return &S; - - // Absolute and undefined symbols have no defining atom. - if (!S.isInSection()) - return nullptr; - - // Non-linker visible symbols in sections which can't be atomized have no - // defining atom. - if (!getContext().getAsmInfo()->isSectionAtomizableBySymbols( - *S.getFragment()->getParent())) - return nullptr; - - // Otherwise, return the atom for the containing fragment. - return S.getFragment()->getAtom(); -} - -bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, - const MCFixup &Fixup, const MCFragment *DF, - MCValue &Target, uint64_t &Value, - bool &WasForced) const { - ++stats::evaluateFixup; - - // FIXME: This code has some duplication with recordRelocation. We should - // probably merge the two into a single callback that tries to evaluate a - // fixup and records a relocation if one is needed. - - // On error claim to have completely evaluated the fixup, to prevent any - // further processing from being done. - const MCExpr *Expr = Fixup.getValue(); - MCContext &Ctx = getContext(); - Value = 0; - WasForced = false; - if (!Expr->evaluateAsRelocatable(Target, &Layout, &Fixup)) { - Ctx.reportError(Fixup.getLoc(), "expected relocatable expression"); - return true; - } - if (const MCSymbolRefExpr *RefB = Target.getSymB()) { - if (RefB->getKind() != MCSymbolRefExpr::VK_None) { - Ctx.reportError(Fixup.getLoc(), - "unsupported subtraction of qualified symbol"); - return true; - } - } - - assert(getBackendPtr() && "Expected assembler backend"); - bool IsPCRel = getBackendPtr()->getFixupKindInfo(Fixup.getKind()).Flags & - MCFixupKindInfo::FKF_IsPCRel; - - bool IsResolved = false; - if (IsPCRel) { - if (Target.getSymB()) { - IsResolved = false; - } else if (!Target.getSymA()) { - IsResolved = false; - } else { - const MCSymbolRefExpr *A = Target.getSymA(); - const MCSymbol &SA = A->getSymbol(); - if (A->getKind() != MCSymbolRefExpr::VK_None || SA.isUndefined()) { - IsResolved = false; - } else if (auto *Writer = getWriterPtr()) { - IsResolved = Writer->isSymbolRefDifferenceFullyResolvedImpl( - *this, SA, *DF, false, true); - } - } - } else { - IsResolved = Target.isAbsolute(); - } - - Value = Target.getConstant(); - - if (const MCSymbolRefExpr *A = Target.getSymA()) { - const MCSymbol &Sym = A->getSymbol(); - if (Sym.isDefined()) - Value += Layout.getSymbolOffset(Sym); - } - if (const MCSymbolRefExpr *B = Target.getSymB()) { - const MCSymbol &Sym = B->getSymbol(); - if (Sym.isDefined()) - Value -= Layout.getSymbolOffset(Sym); - } - - bool ShouldAlignPC = getBackend().getFixupKindInfo(Fixup.getKind()).Flags & - MCFixupKindInfo::FKF_IsAlignedDownTo32Bits; - assert((ShouldAlignPC ? IsPCRel : true) && - "FKF_IsAlignedDownTo32Bits is only allowed on PC-relative fixups!"); - - if (IsPCRel) { - uint32_t Offset = Layout.getFragmentOffset(DF) + Fixup.getOffset(); - - // A number of ARM fixups in Thumb mode require that the effective PC - // address be determined as the 32-bit aligned version of the actual offset. - if (ShouldAlignPC) Offset &= ~0x3; - Value -= Offset; - } - - // Let the backend force a relocation if needed. - if (IsResolved && getBackend().shouldForceRelocation(*this, Fixup, Target)) { - IsResolved = false; - WasForced = true; - } - - return IsResolved; -} - -uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, - const MCFragment &F) const { - assert(getBackendPtr() && "Requires assembler backend"); - switch (F.getKind()) { - case MCFragment::FT_Data: - return cast<MCDataFragment>(F).getContents().size(); - case MCFragment::FT_Relaxable: - return cast<MCRelaxableFragment>(F).getContents().size(); - case MCFragment::FT_CompactEncodedInst: - return cast<MCCompactEncodedInstFragment>(F).getContents().size(); - case MCFragment::FT_Fill: { - auto &FF = cast<MCFillFragment>(F); - int64_t NumValues = 0; - if (!FF.getNumValues().evaluateAsAbsolute(NumValues, Layout)) { - getContext().reportError(FF.getLoc(), - "expected assembly-time absolute expression"); - return 0; - } - int64_t Size = NumValues * FF.getValueSize(); - if (Size < 0) { - getContext().reportError(FF.getLoc(), "invalid number of bytes"); - return 0; - } - return Size; - } - - case MCFragment::FT_LEB: - return cast<MCLEBFragment>(F).getContents().size(); - - case MCFragment::FT_Padding: - return cast<MCPaddingFragment>(F).getSize(); - - case MCFragment::FT_SymbolId: - return 4; - - case MCFragment::FT_Align: { - const MCAlignFragment &AF = cast<MCAlignFragment>(F); - unsigned Offset = Layout.getFragmentOffset(&AF); - unsigned Size = OffsetToAlignment(Offset, AF.getAlignment()); - - // Insert extra Nops for code alignment if the target define - // shouldInsertExtraNopBytesForCodeAlign target hook. - if (AF.getParent()->UseCodeAlign() && AF.hasEmitNops() && - getBackend().shouldInsertExtraNopBytesForCodeAlign(AF, Size)) - return Size; - - // If we are padding with nops, force the padding to be larger than the - // minimum nop size. - if (Size > 0 && AF.hasEmitNops()) { - while (Size % getBackend().getMinimumNopSize()) - Size += AF.getAlignment(); - } - if (Size > AF.getMaxBytesToEmit()) - return 0; - return Size; - } - - case MCFragment::FT_Org: { - const MCOrgFragment &OF = cast<MCOrgFragment>(F); - MCValue Value; - if (!OF.getOffset().evaluateAsValue(Value, Layout)) { - getContext().reportError(OF.getLoc(), - "expected assembly-time absolute expression"); - return 0; - } - - uint64_t FragmentOffset = Layout.getFragmentOffset(&OF); - int64_t TargetLocation = Value.getConstant(); - if (const MCSymbolRefExpr *A = Value.getSymA()) { - uint64_t Val; - if (!Layout.getSymbolOffset(A->getSymbol(), Val)) { - getContext().reportError(OF.getLoc(), "expected absolute expression"); - return 0; - } - TargetLocation += Val; - } - int64_t Size = TargetLocation - FragmentOffset; - if (Size < 0 || Size >= 0x40000000) { - getContext().reportError( - OF.getLoc(), "invalid .org offset '" + Twine(TargetLocation) + - "' (at offset '" + Twine(FragmentOffset) + "')"); - return 0; - } - return Size; - } - - case MCFragment::FT_Dwarf: - return cast<MCDwarfLineAddrFragment>(F).getContents().size(); - case MCFragment::FT_DwarfFrame: - return cast<MCDwarfCallFrameFragment>(F).getContents().size(); - case MCFragment::FT_CVInlineLines: - return cast<MCCVInlineLineTableFragment>(F).getContents().size(); - case MCFragment::FT_CVDefRange: - return cast<MCCVDefRangeFragment>(F).getContents().size(); - case MCFragment::FT_Dummy: - llvm_unreachable("Should not have been added"); - } - - llvm_unreachable("invalid fragment kind"); -} - -void MCAsmLayout::layoutFragment(MCFragment *F) { - MCFragment *Prev = F->getPrevNode(); - - // We should never try to recompute something which is valid. - assert(!isFragmentValid(F) && "Attempt to recompute a valid fragment!"); - // We should never try to compute the fragment layout if its predecessor - // isn't valid. - assert((!Prev || isFragmentValid(Prev)) && - "Attempt to compute fragment before its predecessor!"); - - ++stats::FragmentLayouts; - - // Compute fragment offset and size. - if (Prev) - F->Offset = Prev->Offset + getAssembler().computeFragmentSize(*this, *Prev); - else - F->Offset = 0; - LastValidFragment[F->getParent()] = F; - - // If bundling is enabled and this fragment has instructions in it, it has to - // obey the bundling restrictions. With padding, we'll have: - // - // - // BundlePadding - // ||| - // ------------------------------------- - // Prev |##########| F | - // ------------------------------------- - // ^ - // | - // F->Offset - // - // The fragment's offset will point to after the padding, and its computed - // size won't include the padding. - // - // When the -mc-relax-all flag is used, we optimize bundling by writting the - // padding directly into fragments when the instructions are emitted inside - // the streamer. When the fragment is larger than the bundle size, we need to - // ensure that it's bundle aligned. This means that if we end up with - // multiple fragments, we must emit bundle padding between fragments. - // - // ".align N" is an example of a directive that introduces multiple - // fragments. We could add a special case to handle ".align N" by emitting - // within-fragment padding (which would produce less padding when N is less - // than the bundle size), but for now we don't. - // - if (Assembler.isBundlingEnabled() && F->hasInstructions()) { - assert(isa<MCEncodedFragment>(F) && - "Only MCEncodedFragment implementations have instructions"); - MCEncodedFragment *EF = cast<MCEncodedFragment>(F); - uint64_t FSize = Assembler.computeFragmentSize(*this, *EF); - - if (!Assembler.getRelaxAll() && FSize > Assembler.getBundleAlignSize()) - report_fatal_error("Fragment can't be larger than a bundle size"); - - uint64_t RequiredBundlePadding = - computeBundlePadding(Assembler, EF, EF->Offset, FSize); - if (RequiredBundlePadding > UINT8_MAX) - report_fatal_error("Padding cannot exceed 255 bytes"); - EF->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding)); - EF->Offset += RequiredBundlePadding; - } -} - -void MCAssembler::registerSymbol(const MCSymbol &Symbol, bool *Created) { - bool New = !Symbol.isRegistered(); - if (Created) - *Created = New; - if (New) { - Symbol.setIsRegistered(true); - Symbols.push_back(&Symbol); - } -} - -void MCAssembler::writeFragmentPadding(raw_ostream &OS, - const MCEncodedFragment &EF, - uint64_t FSize) const { - assert(getBackendPtr() && "Expected assembler backend"); - // Should NOP padding be written out before this fragment? - unsigned BundlePadding = EF.getBundlePadding(); - if (BundlePadding > 0) { - assert(isBundlingEnabled() && - "Writing bundle padding with disabled bundling"); - assert(EF.hasInstructions() && - "Writing bundle padding for a fragment without instructions"); - - unsigned TotalLength = BundlePadding + static_cast<unsigned>(FSize); - if (EF.alignToBundleEnd() && TotalLength > getBundleAlignSize()) { - // If the padding itself crosses a bundle boundary, it must be emitted - // in 2 pieces, since even nop instructions must not cross boundaries. - // v--------------v <- BundleAlignSize - // v---------v <- BundlePadding - // ---------------------------- - // | Prev |####|####| F | - // ---------------------------- - // ^-------------------^ <- TotalLength - unsigned DistanceToBoundary = TotalLength - getBundleAlignSize(); - if (!getBackend().writeNopData(OS, DistanceToBoundary)) - report_fatal_error("unable to write NOP sequence of " + - Twine(DistanceToBoundary) + " bytes"); - BundlePadding -= DistanceToBoundary; - } - if (!getBackend().writeNopData(OS, BundlePadding)) - report_fatal_error("unable to write NOP sequence of " + - Twine(BundlePadding) + " bytes"); - } -} - -/// Write the fragment \p F to the output file. -static void writeFragment(raw_ostream &OS, const MCAssembler &Asm, - const MCAsmLayout &Layout, const MCFragment &F) { - // FIXME: Embed in fragments instead? - uint64_t FragmentSize = Asm.computeFragmentSize(Layout, F); - - support::endianness Endian = Asm.getBackend().Endian; - - if (const MCEncodedFragment *EF = dyn_cast<MCEncodedFragment>(&F)) - Asm.writeFragmentPadding(OS, *EF, FragmentSize); - - // This variable (and its dummy usage) is to participate in the assert at - // the end of the function. - uint64_t Start = OS.tell(); - (void) Start; - - ++stats::EmittedFragments; - - switch (F.getKind()) { - case MCFragment::FT_Align: { - ++stats::EmittedAlignFragments; - const MCAlignFragment &AF = cast<MCAlignFragment>(F); - assert(AF.getValueSize() && "Invalid virtual align in concrete fragment!"); - - uint64_t Count = FragmentSize / AF.getValueSize(); - - // FIXME: This error shouldn't actually occur (the front end should emit - // multiple .align directives to enforce the semantics it wants), but is - // severe enough that we want to report it. How to handle this? - if (Count * AF.getValueSize() != FragmentSize) - report_fatal_error("undefined .align directive, value size '" + - Twine(AF.getValueSize()) + - "' is not a divisor of padding size '" + - Twine(FragmentSize) + "'"); - - // See if we are aligning with nops, and if so do that first to try to fill - // the Count bytes. Then if that did not fill any bytes or there are any - // bytes left to fill use the Value and ValueSize to fill the rest. - // If we are aligning with nops, ask that target to emit the right data. - if (AF.hasEmitNops()) { - if (!Asm.getBackend().writeNopData(OS, Count)) - report_fatal_error("unable to write nop sequence of " + - Twine(Count) + " bytes"); - break; - } - - // Otherwise, write out in multiples of the value size. - for (uint64_t i = 0; i != Count; ++i) { - switch (AF.getValueSize()) { - default: llvm_unreachable("Invalid size!"); - case 1: OS << char(AF.getValue()); break; - case 2: - support::endian::write<uint16_t>(OS, AF.getValue(), Endian); - break; - case 4: - support::endian::write<uint32_t>(OS, AF.getValue(), Endian); - break; - case 8: - support::endian::write<uint64_t>(OS, AF.getValue(), Endian); - break; - } - } - break; - } - - case MCFragment::FT_Data: - ++stats::EmittedDataFragments; - OS << cast<MCDataFragment>(F).getContents(); - break; - - case MCFragment::FT_Relaxable: - ++stats::EmittedRelaxableFragments; - OS << cast<MCRelaxableFragment>(F).getContents(); - break; - - case MCFragment::FT_CompactEncodedInst: - ++stats::EmittedCompactEncodedInstFragments; - OS << cast<MCCompactEncodedInstFragment>(F).getContents(); - break; - - case MCFragment::FT_Fill: { - ++stats::EmittedFillFragments; - const MCFillFragment &FF = cast<MCFillFragment>(F); - uint64_t V = FF.getValue(); - unsigned VSize = FF.getValueSize(); - const unsigned MaxChunkSize = 16; - char Data[MaxChunkSize]; - // Duplicate V into Data as byte vector to reduce number of - // writes done. As such, do endian conversion here. - for (unsigned I = 0; I != VSize; ++I) { - unsigned index = Endian == support::little ? I : (VSize - I - 1); - Data[I] = uint8_t(V >> (index * 8)); - } - for (unsigned I = VSize; I < MaxChunkSize; ++I) - Data[I] = Data[I - VSize]; - - // Set to largest multiple of VSize in Data. - const unsigned NumPerChunk = MaxChunkSize / VSize; - // Set ChunkSize to largest multiple of VSize in Data - const unsigned ChunkSize = VSize * NumPerChunk; - - // Do copies by chunk. - StringRef Ref(Data, ChunkSize); - for (uint64_t I = 0, E = FragmentSize / ChunkSize; I != E; ++I) - OS << Ref; - - // do remainder if needed. - unsigned TrailingCount = FragmentSize % ChunkSize; - if (TrailingCount) - OS.write(Data, TrailingCount); - break; - } - - case MCFragment::FT_LEB: { - const MCLEBFragment &LF = cast<MCLEBFragment>(F); - OS << LF.getContents(); - break; - } - - case MCFragment::FT_Padding: { - if (!Asm.getBackend().writeNopData(OS, FragmentSize)) - report_fatal_error("unable to write nop sequence of " + - Twine(FragmentSize) + " bytes"); - break; - } - - case MCFragment::FT_SymbolId: { - const MCSymbolIdFragment &SF = cast<MCSymbolIdFragment>(F); - support::endian::write<uint32_t>(OS, SF.getSymbol()->getIndex(), Endian); - break; - } - - case MCFragment::FT_Org: { - ++stats::EmittedOrgFragments; - const MCOrgFragment &OF = cast<MCOrgFragment>(F); - - for (uint64_t i = 0, e = FragmentSize; i != e; ++i) - OS << char(OF.getValue()); - - break; - } - - case MCFragment::FT_Dwarf: { - const MCDwarfLineAddrFragment &OF = cast<MCDwarfLineAddrFragment>(F); - OS << OF.getContents(); - break; - } - case MCFragment::FT_DwarfFrame: { - const MCDwarfCallFrameFragment &CF = cast<MCDwarfCallFrameFragment>(F); - OS << CF.getContents(); - break; - } - case MCFragment::FT_CVInlineLines: { - const auto &OF = cast<MCCVInlineLineTableFragment>(F); - OS << OF.getContents(); - break; - } - case MCFragment::FT_CVDefRange: { - const auto &DRF = cast<MCCVDefRangeFragment>(F); - OS << DRF.getContents(); - break; - } - case MCFragment::FT_Dummy: - llvm_unreachable("Should not have been added"); - } - - assert(OS.tell() - Start == FragmentSize && - "The stream should advance by fragment size"); -} - -void MCAssembler::writeSectionData(raw_ostream &OS, const MCSection *Sec, - const MCAsmLayout &Layout) const { - assert(getBackendPtr() && "Expected assembler backend"); - - // Ignore virtual sections. - if (Sec->isVirtualSection()) { - assert(Layout.getSectionFileSize(Sec) == 0 && "Invalid size for section!"); - - // Check that contents are only things legal inside a virtual section. - for (const MCFragment &F : *Sec) { - switch (F.getKind()) { - default: llvm_unreachable("Invalid fragment in virtual section!"); - case MCFragment::FT_Data: { - // Check that we aren't trying to write a non-zero contents (or fixups) - // into a virtual section. This is to support clients which use standard - // directives to fill the contents of virtual sections. - const MCDataFragment &DF = cast<MCDataFragment>(F); - if (DF.fixup_begin() != DF.fixup_end()) - report_fatal_error("cannot have fixups in virtual section!"); - for (unsigned i = 0, e = DF.getContents().size(); i != e; ++i) - if (DF.getContents()[i]) { - if (auto *ELFSec = dyn_cast<const MCSectionELF>(Sec)) - report_fatal_error("non-zero initializer found in section '" + - ELFSec->getSectionName() + "'"); - else - report_fatal_error("non-zero initializer found in virtual section"); - } - break; - } - case MCFragment::FT_Align: - // Check that we aren't trying to write a non-zero value into a virtual - // section. - assert((cast<MCAlignFragment>(F).getValueSize() == 0 || - cast<MCAlignFragment>(F).getValue() == 0) && - "Invalid align in virtual section!"); - break; - case MCFragment::FT_Fill: - assert((cast<MCFillFragment>(F).getValue() == 0) && - "Invalid fill in virtual section!"); - break; - } - } - - return; - } - - uint64_t Start = OS.tell(); - (void)Start; - - for (const MCFragment &F : *Sec) - writeFragment(OS, *this, Layout, F); - - assert(OS.tell() - Start == Layout.getSectionAddressSize(Sec)); -} - -std::tuple<MCValue, uint64_t, bool> -MCAssembler::handleFixup(const MCAsmLayout &Layout, MCFragment &F, - const MCFixup &Fixup) { - // Evaluate the fixup. - MCValue Target; - uint64_t FixedValue; - bool WasForced; - bool IsResolved = evaluateFixup(Layout, Fixup, &F, Target, FixedValue, - WasForced); - if (!IsResolved) { - // The fixup was unresolved, we need a relocation. Inform the object - // writer of the relocation, and give it an opportunity to adjust the - // fixup value if need be. - if (Target.getSymA() && Target.getSymB() && - getBackend().requiresDiffExpressionRelocations()) { - // The fixup represents the difference between two symbols, which the - // backend has indicated must be resolved at link time. Split up the fixup - // into two relocations, one for the add, and one for the sub, and emit - // both of these. The constant will be associated with the add half of the - // expression. - MCFixup FixupAdd = MCFixup::createAddFor(Fixup); - MCValue TargetAdd = - MCValue::get(Target.getSymA(), nullptr, Target.getConstant()); - getWriter().recordRelocation(*this, Layout, &F, FixupAdd, TargetAdd, - FixedValue); - MCFixup FixupSub = MCFixup::createSubFor(Fixup); - MCValue TargetSub = MCValue::get(Target.getSymB()); - getWriter().recordRelocation(*this, Layout, &F, FixupSub, TargetSub, - FixedValue); - } else { - getWriter().recordRelocation(*this, Layout, &F, Fixup, Target, - FixedValue); - } - } - return std::make_tuple(Target, FixedValue, IsResolved); -} - -void MCAssembler::layout(MCAsmLayout &Layout) { - assert(getBackendPtr() && "Expected assembler backend"); - DEBUG_WITH_TYPE("mc-dump", { - errs() << "assembler backend - pre-layout\n--\n"; - dump(); }); - - // Create dummy fragments and assign section ordinals. - unsigned SectionIndex = 0; - for (MCSection &Sec : *this) { - // Create dummy fragments to eliminate any empty sections, this simplifies - // layout. - if (Sec.getFragmentList().empty()) - new MCDataFragment(&Sec); - - Sec.setOrdinal(SectionIndex++); - } - - // Assign layout order indices to sections and fragments. - for (unsigned i = 0, e = Layout.getSectionOrder().size(); i != e; ++i) { - MCSection *Sec = Layout.getSectionOrder()[i]; - Sec->setLayoutOrder(i); - - unsigned FragmentIndex = 0; - for (MCFragment &Frag : *Sec) - Frag.setLayoutOrder(FragmentIndex++); - } - - // Layout until everything fits. - while (layoutOnce(Layout)) - if (getContext().hadError()) - return; - - DEBUG_WITH_TYPE("mc-dump", { - errs() << "assembler backend - post-relaxation\n--\n"; - dump(); }); - - // Finalize the layout, including fragment lowering. - finishLayout(Layout); - - DEBUG_WITH_TYPE("mc-dump", { - errs() << "assembler backend - final-layout\n--\n"; - dump(); }); - - // Allow the object writer a chance to perform post-layout binding (for - // example, to set the index fields in the symbol data). - getWriter().executePostLayoutBinding(*this, Layout); - - // Evaluate and apply the fixups, generating relocation entries as necessary. - for (MCSection &Sec : *this) { - for (MCFragment &Frag : Sec) { - // Data and relaxable fragments both have fixups. So only process - // those here. - // FIXME: Is there a better way to do this? MCEncodedFragmentWithFixups - // being templated makes this tricky. - if (isa<MCEncodedFragment>(&Frag) && - isa<MCCompactEncodedInstFragment>(&Frag)) - continue; - if (!isa<MCEncodedFragment>(&Frag) && !isa<MCCVDefRangeFragment>(&Frag) && - !isa<MCAlignFragment>(&Frag)) - continue; - ArrayRef<MCFixup> Fixups; - MutableArrayRef<char> Contents; - const MCSubtargetInfo *STI = nullptr; - if (auto *FragWithFixups = dyn_cast<MCDataFragment>(&Frag)) { - Fixups = FragWithFixups->getFixups(); - Contents = FragWithFixups->getContents(); - STI = FragWithFixups->getSubtargetInfo(); - assert(!FragWithFixups->hasInstructions() || STI != nullptr); - } else if (auto *FragWithFixups = dyn_cast<MCRelaxableFragment>(&Frag)) { - Fixups = FragWithFixups->getFixups(); - Contents = FragWithFixups->getContents(); - STI = FragWithFixups->getSubtargetInfo(); - assert(!FragWithFixups->hasInstructions() || STI != nullptr); - } else if (auto *FragWithFixups = dyn_cast<MCCVDefRangeFragment>(&Frag)) { - Fixups = FragWithFixups->getFixups(); - Contents = FragWithFixups->getContents(); - } else if (auto *FragWithFixups = dyn_cast<MCDwarfLineAddrFragment>(&Frag)) { - Fixups = FragWithFixups->getFixups(); - Contents = FragWithFixups->getContents(); - } else if (auto *AF = dyn_cast<MCAlignFragment>(&Frag)) { - // Insert fixup type for code alignment if the target define - // shouldInsertFixupForCodeAlign target hook. - if (Sec.UseCodeAlign() && AF->hasEmitNops()) { - getBackend().shouldInsertFixupForCodeAlign(*this, Layout, *AF); - } - continue; - } else if (auto *FragWithFixups = - dyn_cast<MCDwarfCallFrameFragment>(&Frag)) { - Fixups = FragWithFixups->getFixups(); - Contents = FragWithFixups->getContents(); - } else - llvm_unreachable("Unknown fragment with fixups!"); - for (const MCFixup &Fixup : Fixups) { - uint64_t FixedValue; - bool IsResolved; - MCValue Target; - std::tie(Target, FixedValue, IsResolved) = - handleFixup(Layout, Frag, Fixup); - getBackend().applyFixup(*this, Fixup, Target, Contents, FixedValue, - IsResolved, STI); - } - } - } -} - -void MCAssembler::Finish() { - // Create the layout object. - MCAsmLayout Layout(*this); - layout(Layout); - - // Write the object file. - stats::ObjectBytes += getWriter().writeObject(*this, Layout); -} - -bool MCAssembler::fixupNeedsRelaxation(const MCFixup &Fixup, - const MCRelaxableFragment *DF, - const MCAsmLayout &Layout) const { - assert(getBackendPtr() && "Expected assembler backend"); - MCValue Target; - uint64_t Value; - bool WasForced; - bool Resolved = evaluateFixup(Layout, Fixup, DF, Target, Value, WasForced); - if (Target.getSymA() && - Target.getSymA()->getKind() == MCSymbolRefExpr::VK_X86_ABS8 && - Fixup.getKind() == FK_Data_1) - return false; - return getBackend().fixupNeedsRelaxationAdvanced(Fixup, Resolved, Value, DF, - Layout, WasForced); -} - -bool MCAssembler::fragmentNeedsRelaxation(const MCRelaxableFragment *F, - const MCAsmLayout &Layout) const { - assert(getBackendPtr() && "Expected assembler backend"); - // If this inst doesn't ever need relaxation, ignore it. This occurs when we - // are intentionally pushing out inst fragments, or because we relaxed a - // previous instruction to one that doesn't need relaxation. - if (!getBackend().mayNeedRelaxation(F->getInst(), *F->getSubtargetInfo())) - return false; - - for (const MCFixup &Fixup : F->getFixups()) - if (fixupNeedsRelaxation(Fixup, F, Layout)) - return true; - - return false; -} - -bool MCAssembler::relaxInstruction(MCAsmLayout &Layout, - MCRelaxableFragment &F) { - assert(getEmitterPtr() && - "Expected CodeEmitter defined for relaxInstruction"); - if (!fragmentNeedsRelaxation(&F, Layout)) - return false; - - ++stats::RelaxedInstructions; - - // FIXME-PERF: We could immediately lower out instructions if we can tell - // they are fully resolved, to avoid retesting on later passes. - - // Relax the fragment. - - MCInst Relaxed; - getBackend().relaxInstruction(F.getInst(), *F.getSubtargetInfo(), Relaxed); - - // Encode the new instruction. - // - // FIXME-PERF: If it matters, we could let the target do this. It can - // probably do so more efficiently in many cases. - SmallVector<MCFixup, 4> Fixups; - SmallString<256> Code; - raw_svector_ostream VecOS(Code); - getEmitter().encodeInstruction(Relaxed, VecOS, Fixups, *F.getSubtargetInfo()); - - // Update the fragment. - F.setInst(Relaxed); - F.getContents() = Code; - F.getFixups() = Fixups; - - return true; -} - -bool MCAssembler::relaxPaddingFragment(MCAsmLayout &Layout, - MCPaddingFragment &PF) { - assert(getBackendPtr() && "Expected assembler backend"); - uint64_t OldSize = PF.getSize(); - if (!getBackend().relaxFragment(&PF, Layout)) - return false; - uint64_t NewSize = PF.getSize(); - - ++stats::PaddingFragmentsRelaxations; - stats::PaddingFragmentsBytes += NewSize; - stats::PaddingFragmentsBytes -= OldSize; - return true; -} - -bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) { - uint64_t OldSize = LF.getContents().size(); - int64_t Value; - bool Abs = LF.getValue().evaluateKnownAbsolute(Value, Layout); - if (!Abs) - report_fatal_error("sleb128 and uleb128 expressions must be absolute"); - SmallString<8> &Data = LF.getContents(); - Data.clear(); - raw_svector_ostream OSE(Data); - // The compiler can generate EH table assembly that is impossible to assemble - // without either adding padding to an LEB fragment or adding extra padding - // to a later alignment fragment. To accommodate such tables, relaxation can - // only increase an LEB fragment size here, not decrease it. See PR35809. - if (LF.isSigned()) - encodeSLEB128(Value, OSE, OldSize); - else - encodeULEB128(Value, OSE, OldSize); - return OldSize != LF.getContents().size(); -} - -bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout, - MCDwarfLineAddrFragment &DF) { - MCContext &Context = Layout.getAssembler().getContext(); - uint64_t OldSize = DF.getContents().size(); - int64_t AddrDelta; - bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout); - assert(Abs && "We created a line delta with an invalid expression"); - (void)Abs; - int64_t LineDelta; - LineDelta = DF.getLineDelta(); - SmallVectorImpl<char> &Data = DF.getContents(); - Data.clear(); - raw_svector_ostream OSE(Data); - DF.getFixups().clear(); - - if (!getBackend().requiresDiffExpressionRelocations()) { - MCDwarfLineAddr::Encode(Context, getDWARFLinetableParams(), LineDelta, - AddrDelta, OSE); - } else { - uint32_t Offset; - uint32_t Size; - bool SetDelta = MCDwarfLineAddr::FixedEncode(Context, - getDWARFLinetableParams(), - LineDelta, AddrDelta, - OSE, &Offset, &Size); - // Add Fixups for address delta or new address. - const MCExpr *FixupExpr; - if (SetDelta) { - FixupExpr = &DF.getAddrDelta(); - } else { - const MCBinaryExpr *ABE = cast<MCBinaryExpr>(&DF.getAddrDelta()); - FixupExpr = ABE->getLHS(); - } - DF.getFixups().push_back( - MCFixup::create(Offset, FixupExpr, - MCFixup::getKindForSize(Size, false /*isPCRel*/))); - } - - return OldSize != Data.size(); -} - -bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout, - MCDwarfCallFrameFragment &DF) { - MCContext &Context = Layout.getAssembler().getContext(); - uint64_t OldSize = DF.getContents().size(); - int64_t AddrDelta; - bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout); - assert(Abs && "We created call frame with an invalid expression"); - (void) Abs; - SmallVectorImpl<char> &Data = DF.getContents(); - Data.clear(); - raw_svector_ostream OSE(Data); - DF.getFixups().clear(); - - if (getBackend().requiresDiffExpressionRelocations()) { - uint32_t Offset; - uint32_t Size; - MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OSE, &Offset, - &Size); - if (Size) { - DF.getFixups().push_back(MCFixup::create( - Offset, &DF.getAddrDelta(), - MCFixup::getKindForSizeInBits(Size /*In bits.*/, false /*isPCRel*/))); - } - } else { - MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OSE); - } - - return OldSize != Data.size(); -} - -bool MCAssembler::relaxCVInlineLineTable(MCAsmLayout &Layout, - MCCVInlineLineTableFragment &F) { - unsigned OldSize = F.getContents().size(); - getContext().getCVContext().encodeInlineLineTable(Layout, F); - return OldSize != F.getContents().size(); -} - -bool MCAssembler::relaxCVDefRange(MCAsmLayout &Layout, - MCCVDefRangeFragment &F) { - unsigned OldSize = F.getContents().size(); - getContext().getCVContext().encodeDefRange(Layout, F); - return OldSize != F.getContents().size(); -} - -bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec) { - // Holds the first fragment which needed relaxing during this layout. It will - // remain NULL if none were relaxed. - // When a fragment is relaxed, all the fragments following it should get - // invalidated because their offset is going to change. - MCFragment *FirstRelaxedFragment = nullptr; - - // Attempt to relax all the fragments in the section. - for (MCSection::iterator I = Sec.begin(), IE = Sec.end(); I != IE; ++I) { - // Check if this is a fragment that needs relaxation. - bool RelaxedFrag = false; - switch(I->getKind()) { - default: - break; - case MCFragment::FT_Relaxable: - assert(!getRelaxAll() && - "Did not expect a MCRelaxableFragment in RelaxAll mode"); - RelaxedFrag = relaxInstruction(Layout, *cast<MCRelaxableFragment>(I)); - break; - case MCFragment::FT_Dwarf: - RelaxedFrag = relaxDwarfLineAddr(Layout, - *cast<MCDwarfLineAddrFragment>(I)); - break; - case MCFragment::FT_DwarfFrame: - RelaxedFrag = - relaxDwarfCallFrameFragment(Layout, - *cast<MCDwarfCallFrameFragment>(I)); - break; - case MCFragment::FT_LEB: - RelaxedFrag = relaxLEB(Layout, *cast<MCLEBFragment>(I)); - break; - case MCFragment::FT_Padding: - RelaxedFrag = relaxPaddingFragment(Layout, *cast<MCPaddingFragment>(I)); - break; - case MCFragment::FT_CVInlineLines: - RelaxedFrag = - relaxCVInlineLineTable(Layout, *cast<MCCVInlineLineTableFragment>(I)); - break; - case MCFragment::FT_CVDefRange: - RelaxedFrag = relaxCVDefRange(Layout, *cast<MCCVDefRangeFragment>(I)); - break; - } - if (RelaxedFrag && !FirstRelaxedFragment) - FirstRelaxedFragment = &*I; - } - if (FirstRelaxedFragment) { - Layout.invalidateFragmentsFrom(FirstRelaxedFragment); - return true; - } - return false; -} - -bool MCAssembler::layoutOnce(MCAsmLayout &Layout) { - ++stats::RelaxationSteps; - - bool WasRelaxed = false; - for (iterator it = begin(), ie = end(); it != ie; ++it) { - MCSection &Sec = *it; - while (layoutSectionOnce(Layout, Sec)) - WasRelaxed = true; - } - - return WasRelaxed; -} - -void MCAssembler::finishLayout(MCAsmLayout &Layout) { - assert(getBackendPtr() && "Expected assembler backend"); - // The layout is done. Mark every fragment as valid. - for (unsigned int i = 0, n = Layout.getSectionOrder().size(); i != n; ++i) { - MCSection &Section = *Layout.getSectionOrder()[i]; - Layout.getFragmentOffset(&*Section.rbegin()); - computeFragmentSize(Layout, *Section.rbegin()); - } - getBackend().finishLayout(*this, Layout); -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -LLVM_DUMP_METHOD void MCAssembler::dump() const{ - raw_ostream &OS = errs(); - - OS << "<MCAssembler\n"; - OS << " Sections:[\n "; - for (const_iterator it = begin(), ie = end(); it != ie; ++it) { - if (it != begin()) OS << ",\n "; - it->dump(); - } - OS << "],\n"; - OS << " Symbols:["; - - for (const_symbol_iterator it = symbol_begin(), ie = symbol_end(); it != ie; ++it) { - if (it != symbol_begin()) OS << ",\n "; - OS << "("; - it->dump(); - OS << ", Index:" << it->getIndex() << ", "; - OS << ")"; - } - OS << "]>\n"; -} -#endif diff --git a/contrib/llvm/lib/MC/MCCodeEmitter.cpp b/contrib/llvm/lib/MC/MCCodeEmitter.cpp deleted file mode 100644 index 0d114f12d58c..000000000000 --- a/contrib/llvm/lib/MC/MCCodeEmitter.cpp +++ /dev/null @@ -1,15 +0,0 @@ -//===- MCCodeEmitter.cpp - Instruction Encoding ---------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCCodeEmitter.h" - -using namespace llvm; - -MCCodeEmitter::MCCodeEmitter() = default; - -MCCodeEmitter::~MCCodeEmitter() = default; diff --git a/contrib/llvm/lib/MC/MCCodePadder.cpp b/contrib/llvm/lib/MC/MCCodePadder.cpp deleted file mode 100644 index 27a62f95a529..000000000000 --- a/contrib/llvm/lib/MC/MCCodePadder.cpp +++ /dev/null @@ -1,370 +0,0 @@ -//===- MCCodePadder.cpp - Target MC Code Padder ---------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCAsmLayout.h" -#include "llvm/MC/MCCodePadder.h" -#include "llvm/MC/MCObjectStreamer.h" -#include <algorithm> -#include <limits> -#include <numeric> - -using namespace llvm; - -//--------------------------------------------------------------------------- -// MCCodePadder -// - -MCCodePadder::~MCCodePadder() { - for (auto *Policy : CodePaddingPolicies) - delete Policy; -} - -bool MCCodePadder::addPolicy(MCCodePaddingPolicy *Policy) { - assert(Policy && "Policy must be valid"); - return CodePaddingPolicies.insert(Policy).second; -} - -void MCCodePadder::handleBasicBlockStart(MCObjectStreamer *OS, - const MCCodePaddingContext &Context) { - assert(OS != nullptr && "OS must be valid"); - assert(this->OS == nullptr && "Still handling another basic block"); - this->OS = OS; - - ArePoliciesActive = usePoliciesForBasicBlock(Context); - - bool InsertionPoint = basicBlockRequiresInsertionPoint(Context); - assert((!InsertionPoint || - OS->getCurrentFragment()->getKind() != MCFragment::FT_Align) && - "Cannot insert padding nops right after an alignment fragment as it " - "will ruin the alignment"); - - uint64_t PoliciesMask = MCPaddingFragment::PFK_None; - if (ArePoliciesActive) { - PoliciesMask = std::accumulate( - CodePaddingPolicies.begin(), CodePaddingPolicies.end(), - MCPaddingFragment::PFK_None, - [&Context](uint64_t Mask, - const MCCodePaddingPolicy *Policy) -> uint64_t { - return Policy->basicBlockRequiresPaddingFragment(Context) - ? (Mask | Policy->getKindMask()) - : Mask; - }); - } - - if (InsertionPoint || PoliciesMask != MCPaddingFragment::PFK_None) { - MCPaddingFragment *PaddingFragment = OS->getOrCreatePaddingFragment(); - if (InsertionPoint) - PaddingFragment->setAsInsertionPoint(); - PaddingFragment->setPaddingPoliciesMask( - PaddingFragment->getPaddingPoliciesMask() | PoliciesMask); - } -} - -void MCCodePadder::handleBasicBlockEnd(const MCCodePaddingContext &Context) { - assert(this->OS != nullptr && "Not handling a basic block"); - OS = nullptr; -} - -void MCCodePadder::handleInstructionBegin(const MCInst &Inst) { - if (!OS) - return; // instruction was emitted outside a function - - assert(CurrHandledInstFragment == nullptr && "Can't start handling an " - "instruction while still " - "handling another instruction"); - - bool InsertionPoint = instructionRequiresInsertionPoint(Inst); - assert((!InsertionPoint || - OS->getCurrentFragment()->getKind() != MCFragment::FT_Align) && - "Cannot insert padding nops right after an alignment fragment as it " - "will ruin the alignment"); - - uint64_t PoliciesMask = MCPaddingFragment::PFK_None; - if (ArePoliciesActive) { - PoliciesMask = std::accumulate( - CodePaddingPolicies.begin(), CodePaddingPolicies.end(), - MCPaddingFragment::PFK_None, - [&Inst](uint64_t Mask, const MCCodePaddingPolicy *Policy) -> uint64_t { - return Policy->instructionRequiresPaddingFragment(Inst) - ? (Mask | Policy->getKindMask()) - : Mask; - }); - } - MCFragment *CurrFragment = OS->getCurrentFragment(); - // CurrFragment can be a previously created MCPaddingFragment. If so, let's - // update it with the information we have, such as the instruction that it - // should point to. - bool needToUpdateCurrFragment = - CurrFragment != nullptr && - CurrFragment->getKind() == MCFragment::FT_Padding; - if (InsertionPoint || PoliciesMask != MCPaddingFragment::PFK_None || - needToUpdateCurrFragment) { - // temporarily holding the fragment as CurrHandledInstFragment, to be - // updated after the instruction will be written - CurrHandledInstFragment = OS->getOrCreatePaddingFragment(); - if (InsertionPoint) - CurrHandledInstFragment->setAsInsertionPoint(); - CurrHandledInstFragment->setPaddingPoliciesMask( - CurrHandledInstFragment->getPaddingPoliciesMask() | PoliciesMask); - } -} - -void MCCodePadder::handleInstructionEnd(const MCInst &Inst) { - if (!OS) - return; // instruction was emitted outside a function - if (CurrHandledInstFragment == nullptr) - return; - - MCFragment *InstFragment = OS->getCurrentFragment(); - if (MCDataFragment *InstDataFragment = - dyn_cast_or_null<MCDataFragment>(InstFragment)) - // Inst is a fixed size instruction and was encoded into a MCDataFragment. - // Let the fragment hold it and its size. Its size is the current size of - // the data fragment, as the padding fragment was inserted right before it - // and nothing was written yet except Inst - CurrHandledInstFragment->setInstAndInstSize( - Inst, InstDataFragment->getContents().size()); - else if (MCRelaxableFragment *InstRelaxableFragment = - dyn_cast_or_null<MCRelaxableFragment>(InstFragment)) - // Inst may be relaxed and its size may vary. - // Let the fragment hold the instruction and the MCRelaxableFragment - // that's holding it. - CurrHandledInstFragment->setInstAndInstFragment(Inst, - InstRelaxableFragment); - else - llvm_unreachable("After encoding an instruction current fragment must be " - "either a MCDataFragment or a MCRelaxableFragment"); - - CurrHandledInstFragment = nullptr; -} - -MCPFRange &MCCodePadder::getJurisdiction(MCPaddingFragment *Fragment, - MCAsmLayout &Layout) { - auto JurisdictionLocation = FragmentToJurisdiction.find(Fragment); - if (JurisdictionLocation != FragmentToJurisdiction.end()) - return JurisdictionLocation->second; - - MCPFRange Jurisdiction; - - // Forward scanning the fragments in this section, starting from the given - // fragments, and adding relevant MCPaddingFragments to the Jurisdiction - for (MCFragment *CurrFragment = Fragment; CurrFragment != nullptr; - CurrFragment = CurrFragment->getNextNode()) { - - MCPaddingFragment *CurrPaddingFragment = - dyn_cast<MCPaddingFragment>(CurrFragment); - if (CurrPaddingFragment == nullptr) - continue; - - if (CurrPaddingFragment != Fragment && - CurrPaddingFragment->isInsertionPoint()) - // Found next insertion point Fragment. From now on it's its jurisdiction. - break; - for (const auto *Policy : CodePaddingPolicies) { - if (CurrPaddingFragment->hasPaddingPolicy(Policy->getKindMask())) { - Jurisdiction.push_back(CurrPaddingFragment); - break; - } - } - } - - auto InsertionResult = - FragmentToJurisdiction.insert(std::make_pair(Fragment, Jurisdiction)); - assert(InsertionResult.second && - "Insertion to FragmentToJurisdiction failed"); - return InsertionResult.first->second; -} - -uint64_t MCCodePadder::getMaxWindowSize(MCPaddingFragment *Fragment, - MCAsmLayout &Layout) { - auto MaxFragmentSizeLocation = FragmentToMaxWindowSize.find(Fragment); - if (MaxFragmentSizeLocation != FragmentToMaxWindowSize.end()) - return MaxFragmentSizeLocation->second; - - MCPFRange &Jurisdiction = getJurisdiction(Fragment, Layout); - uint64_t JurisdictionMask = MCPaddingFragment::PFK_None; - for (const auto *Protege : Jurisdiction) - JurisdictionMask |= Protege->getPaddingPoliciesMask(); - - uint64_t MaxFragmentSize = UINT64_C(0); - for (const auto *Policy : CodePaddingPolicies) - if ((JurisdictionMask & Policy->getKindMask()) != - MCPaddingFragment::PFK_None) - MaxFragmentSize = std::max(MaxFragmentSize, Policy->getWindowSize()); - - auto InsertionResult = - FragmentToMaxWindowSize.insert(std::make_pair(Fragment, MaxFragmentSize)); - assert(InsertionResult.second && - "Insertion to FragmentToMaxWindowSize failed"); - return InsertionResult.first->second; -} - -bool MCCodePadder::relaxFragment(MCPaddingFragment *Fragment, - MCAsmLayout &Layout) { - if (!Fragment->isInsertionPoint()) - return false; - uint64_t OldSize = Fragment->getSize(); - - uint64_t MaxWindowSize = getMaxWindowSize(Fragment, Layout); - if (MaxWindowSize == UINT64_C(0)) - return false; - assert(isPowerOf2_64(MaxWindowSize) && - "MaxWindowSize must be an integer power of 2"); - uint64_t SectionAlignment = Fragment->getParent()->getAlignment(); - assert(isPowerOf2_64(SectionAlignment) && - "SectionAlignment must be an integer power of 2"); - - MCPFRange &Jurisdiction = getJurisdiction(Fragment, Layout); - uint64_t OptimalSize = UINT64_C(0); - double OptimalWeight = std::numeric_limits<double>::max(); - uint64_t MaxFragmentSize = MaxWindowSize - UINT16_C(1); - for (uint64_t Size = UINT64_C(0); Size <= MaxFragmentSize; ++Size) { - Fragment->setSize(Size); - Layout.invalidateFragmentsFrom(Fragment); - double SizeWeight = 0.0; - // The section is guaranteed to be aligned to SectionAlignment, but that - // doesn't guarantee the exact section offset w.r.t. the policies window - // size. - // As a concrete example, the section could be aligned to 16B, but a - // policy's window size can be 32B. That means that the section actual start - // address can either be 0mod32 or 16mod32. The said policy will act - // differently for each case, so we need to take both into consideration. - for (uint64_t Offset = UINT64_C(0); Offset < MaxWindowSize; - Offset += SectionAlignment) { - double OffsetWeight = std::accumulate( - CodePaddingPolicies.begin(), CodePaddingPolicies.end(), 0.0, - [&Jurisdiction, &Offset, &Layout]( - double Weight, const MCCodePaddingPolicy *Policy) -> double { - double PolicyWeight = - Policy->computeRangePenaltyWeight(Jurisdiction, Offset, Layout); - assert(PolicyWeight >= 0.0 && "A penalty weight must be positive"); - return Weight + PolicyWeight; - }); - SizeWeight = std::max(SizeWeight, OffsetWeight); - } - if (SizeWeight < OptimalWeight) { - OptimalWeight = SizeWeight; - OptimalSize = Size; - } - if (OptimalWeight == 0.0) - break; - } - - Fragment->setSize(OptimalSize); - Layout.invalidateFragmentsFrom(Fragment); - return OldSize != OptimalSize; -} - -//--------------------------------------------------------------------------- -// MCCodePaddingPolicy -// - -uint64_t MCCodePaddingPolicy::getNextFragmentOffset(const MCFragment *Fragment, - const MCAsmLayout &Layout) { - assert(Fragment != nullptr && "Fragment cannot be null"); - MCFragment const *NextFragment = Fragment->getNextNode(); - return NextFragment == nullptr - ? Layout.getSectionAddressSize(Fragment->getParent()) - : Layout.getFragmentOffset(NextFragment); -} - -uint64_t -MCCodePaddingPolicy::getFragmentInstByte(const MCPaddingFragment *Fragment, - MCAsmLayout &Layout) const { - uint64_t InstByte = getNextFragmentOffset(Fragment, Layout); - if (InstByteIsLastByte) - InstByte += Fragment->getInstSize() - UINT64_C(1); - return InstByte; -} - -uint64_t -MCCodePaddingPolicy::computeWindowEndAddress(const MCPaddingFragment *Fragment, - uint64_t Offset, - MCAsmLayout &Layout) const { - uint64_t InstByte = getFragmentInstByte(Fragment, Layout); - return alignTo(InstByte + UINT64_C(1) + Offset, WindowSize) - Offset; -} - -double MCCodePaddingPolicy::computeRangePenaltyWeight( - const MCPFRange &Range, uint64_t Offset, MCAsmLayout &Layout) const { - - SmallVector<MCPFRange, 8> Windows; - SmallVector<MCPFRange, 8>::iterator CurrWindowLocation = Windows.end(); - for (const MCPaddingFragment *Fragment : Range) { - if (!Fragment->hasPaddingPolicy(getKindMask())) - continue; - uint64_t FragmentWindowEndAddress = - computeWindowEndAddress(Fragment, Offset, Layout); - if (CurrWindowLocation == Windows.end() || - FragmentWindowEndAddress != - computeWindowEndAddress(*CurrWindowLocation->begin(), Offset, - Layout)) { - // next window is starting - Windows.push_back(MCPFRange()); - CurrWindowLocation = Windows.end() - 1; - } - CurrWindowLocation->push_back(Fragment); - } - - if (Windows.empty()) - return 0.0; - - double RangeWeight = 0.0; - SmallVector<MCPFRange, 8>::iterator I = Windows.begin(); - RangeWeight += computeFirstWindowPenaltyWeight(*I, Offset, Layout); - ++I; - RangeWeight += std::accumulate( - I, Windows.end(), 0.0, - [this, &Layout, &Offset](double Weight, MCPFRange &Window) -> double { - return Weight += computeWindowPenaltyWeight(Window, Offset, Layout); - }); - return RangeWeight; -} - -double MCCodePaddingPolicy::computeFirstWindowPenaltyWeight( - const MCPFRange &Window, uint64_t Offset, MCAsmLayout &Layout) const { - if (Window.empty()) - return 0.0; - uint64_t WindowEndAddress = - computeWindowEndAddress(*Window.begin(), Offset, Layout); - - MCPFRange FullWindowFirstPart; // will hold all the fragments that are in the - // same window as the fragments in the given - // window but their penalty weight should not - // be added - for (const MCFragment *Fragment = (*Window.begin())->getPrevNode(); - Fragment != nullptr; Fragment = Fragment->getPrevNode()) { - const MCPaddingFragment *PaddingNopFragment = - dyn_cast<MCPaddingFragment>(Fragment); - if (PaddingNopFragment == nullptr || - !PaddingNopFragment->hasPaddingPolicy(getKindMask())) - continue; - if (WindowEndAddress != - computeWindowEndAddress(PaddingNopFragment, Offset, Layout)) - break; - - FullWindowFirstPart.push_back(PaddingNopFragment); - } - - std::reverse(FullWindowFirstPart.begin(), FullWindowFirstPart.end()); - double FullWindowFirstPartWeight = - computeWindowPenaltyWeight(FullWindowFirstPart, Offset, Layout); - - MCPFRange FullWindow( - FullWindowFirstPart); // will hold all the fragments that are in the - // same window as the fragments in the given - // window, whether their weight should be added - // or not - FullWindow.append(Window.begin(), Window.end()); - double FullWindowWeight = - computeWindowPenaltyWeight(FullWindow, Offset, Layout); - - assert(FullWindowWeight >= FullWindowFirstPartWeight && - "More fragments necessarily means bigger weight"); - return FullWindowWeight - FullWindowFirstPartWeight; -} diff --git a/contrib/llvm/lib/MC/MCCodeView.cpp b/contrib/llvm/lib/MC/MCCodeView.cpp deleted file mode 100644 index 1a71b542bd06..000000000000 --- a/contrib/llvm/lib/MC/MCCodeView.cpp +++ /dev/null @@ -1,696 +0,0 @@ -//===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Holds state from .cv_file and .cv_loc directives for later emission. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCCodeView.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/DebugInfo/CodeView/CodeView.h" -#include "llvm/DebugInfo/CodeView/Line.h" -#include "llvm/DebugInfo/CodeView/SymbolRecord.h" -#include "llvm/MC/MCAsmLayout.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCObjectStreamer.h" -#include "llvm/MC/MCValue.h" -#include "llvm/Support/EndianStream.h" - -using namespace llvm; -using namespace llvm::codeview; - -CodeViewContext::CodeViewContext() {} - -CodeViewContext::~CodeViewContext() { - // If someone inserted strings into the string table but never actually - // emitted them somewhere, clean up the fragment. - if (!InsertedStrTabFragment) - delete StrTabFragment; -} - -/// This is a valid number for use with .cv_loc if we've already seen a .cv_file -/// for it. -bool CodeViewContext::isValidFileNumber(unsigned FileNumber) const { - unsigned Idx = FileNumber - 1; - if (Idx < Files.size()) - return Files[Idx].Assigned; - return false; -} - -bool CodeViewContext::addFile(MCStreamer &OS, unsigned FileNumber, - StringRef Filename, - ArrayRef<uint8_t> ChecksumBytes, - uint8_t ChecksumKind) { - assert(FileNumber > 0); - auto FilenameOffset = addToStringTable(Filename); - Filename = FilenameOffset.first; - unsigned Idx = FileNumber - 1; - if (Idx >= Files.size()) - Files.resize(Idx + 1); - - if (Filename.empty()) - Filename = "<stdin>"; - - if (Files[Idx].Assigned) - return false; - - FilenameOffset = addToStringTable(Filename); - Filename = FilenameOffset.first; - unsigned Offset = FilenameOffset.second; - - auto ChecksumOffsetSymbol = - OS.getContext().createTempSymbol("checksum_offset", false); - Files[Idx].StringTableOffset = Offset; - Files[Idx].ChecksumTableOffset = ChecksumOffsetSymbol; - Files[Idx].Assigned = true; - Files[Idx].Checksum = ChecksumBytes; - Files[Idx].ChecksumKind = ChecksumKind; - - return true; -} - -MCCVFunctionInfo *CodeViewContext::getCVFunctionInfo(unsigned FuncId) { - if (FuncId >= Functions.size()) - return nullptr; - if (Functions[FuncId].isUnallocatedFunctionInfo()) - return nullptr; - return &Functions[FuncId]; -} - -bool CodeViewContext::recordFunctionId(unsigned FuncId) { - if (FuncId >= Functions.size()) - Functions.resize(FuncId + 1); - - // Return false if this function info was already allocated. - if (!Functions[FuncId].isUnallocatedFunctionInfo()) - return false; - - // Mark this as an allocated normal function, and leave the rest alone. - Functions[FuncId].ParentFuncIdPlusOne = MCCVFunctionInfo::FunctionSentinel; - return true; -} - -bool CodeViewContext::recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc, - unsigned IAFile, unsigned IALine, - unsigned IACol) { - if (FuncId >= Functions.size()) - Functions.resize(FuncId + 1); - - // Return false if this function info was already allocated. - if (!Functions[FuncId].isUnallocatedFunctionInfo()) - return false; - - MCCVFunctionInfo::LineInfo InlinedAt; - InlinedAt.File = IAFile; - InlinedAt.Line = IALine; - InlinedAt.Col = IACol; - - // Mark this as an inlined call site and record call site line info. - MCCVFunctionInfo *Info = &Functions[FuncId]; - Info->ParentFuncIdPlusOne = IAFunc + 1; - Info->InlinedAt = InlinedAt; - - // Walk up the call chain adding this function id to the InlinedAtMap of all - // transitive callers until we hit a real function. - while (Info->isInlinedCallSite()) { - InlinedAt = Info->InlinedAt; - Info = getCVFunctionInfo(Info->getParentFuncId()); - Info->InlinedAtMap[FuncId] = InlinedAt; - } - - return true; -} - -void CodeViewContext::recordCVLoc(MCContext &Ctx, const MCSymbol *Label, - unsigned FunctionId, unsigned FileNo, - unsigned Line, unsigned Column, - bool PrologueEnd, bool IsStmt) { - addLineEntry(MCCVLoc{ - Label, FunctionId, FileNo, Line, Column, PrologueEnd, IsStmt}); -} - -MCDataFragment *CodeViewContext::getStringTableFragment() { - if (!StrTabFragment) { - StrTabFragment = new MCDataFragment(); - // Start a new string table out with a null byte. - StrTabFragment->getContents().push_back('\0'); - } - return StrTabFragment; -} - -std::pair<StringRef, unsigned> CodeViewContext::addToStringTable(StringRef S) { - SmallVectorImpl<char> &Contents = getStringTableFragment()->getContents(); - auto Insertion = - StringTable.insert(std::make_pair(S, unsigned(Contents.size()))); - // Return the string from the table, since it is stable. - std::pair<StringRef, unsigned> Ret = - std::make_pair(Insertion.first->first(), Insertion.first->second); - if (Insertion.second) { - // The string map key is always null terminated. - Contents.append(Ret.first.begin(), Ret.first.end() + 1); - } - return Ret; -} - -unsigned CodeViewContext::getStringTableOffset(StringRef S) { - // A string table offset of zero is always the empty string. - if (S.empty()) - return 0; - auto I = StringTable.find(S); - assert(I != StringTable.end()); - return I->second; -} - -void CodeViewContext::emitStringTable(MCObjectStreamer &OS) { - MCContext &Ctx = OS.getContext(); - MCSymbol *StringBegin = Ctx.createTempSymbol("strtab_begin", false), - *StringEnd = Ctx.createTempSymbol("strtab_end", false); - - OS.EmitIntValue(unsigned(DebugSubsectionKind::StringTable), 4); - OS.emitAbsoluteSymbolDiff(StringEnd, StringBegin, 4); - OS.EmitLabel(StringBegin); - - // Put the string table data fragment here, if we haven't already put it - // somewhere else. If somebody wants two string tables in their .s file, one - // will just be empty. - if (!InsertedStrTabFragment) { - OS.insert(getStringTableFragment()); - InsertedStrTabFragment = true; - } - - OS.EmitValueToAlignment(4, 0); - - OS.EmitLabel(StringEnd); -} - -void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) { - // Do nothing if there are no file checksums. Microsoft's linker rejects empty - // CodeView substreams. - if (Files.empty()) - return; - - MCContext &Ctx = OS.getContext(); - MCSymbol *FileBegin = Ctx.createTempSymbol("filechecksums_begin", false), - *FileEnd = Ctx.createTempSymbol("filechecksums_end", false); - - OS.EmitIntValue(unsigned(DebugSubsectionKind::FileChecksums), 4); - OS.emitAbsoluteSymbolDiff(FileEnd, FileBegin, 4); - OS.EmitLabel(FileBegin); - - unsigned CurrentOffset = 0; - - // Emit an array of FileChecksum entries. We index into this table using the - // user-provided file number. Each entry may be a variable number of bytes - // determined by the checksum kind and size. - for (auto File : Files) { - OS.EmitAssignment(File.ChecksumTableOffset, - MCConstantExpr::create(CurrentOffset, Ctx)); - CurrentOffset += 4; // String table offset. - if (!File.ChecksumKind) { - CurrentOffset += - 4; // One byte each for checksum size and kind, then align to 4 bytes. - } else { - CurrentOffset += 2; // One byte each for checksum size and kind. - CurrentOffset += File.Checksum.size(); - CurrentOffset = alignTo(CurrentOffset, 4); - } - - OS.EmitIntValue(File.StringTableOffset, 4); - - if (!File.ChecksumKind) { - // There is no checksum. Therefore zero the next two fields and align - // back to 4 bytes. - OS.EmitIntValue(0, 4); - continue; - } - OS.EmitIntValue(static_cast<uint8_t>(File.Checksum.size()), 1); - OS.EmitIntValue(File.ChecksumKind, 1); - OS.EmitBytes(toStringRef(File.Checksum)); - OS.EmitValueToAlignment(4); - } - - OS.EmitLabel(FileEnd); - - ChecksumOffsetsAssigned = true; -} - -// Output checksum table offset of the given file number. It is possible that -// not all files have been registered yet, and so the offset cannot be -// calculated. In this case a symbol representing the offset is emitted, and -// the value of this symbol will be fixed up at a later time. -void CodeViewContext::emitFileChecksumOffset(MCObjectStreamer &OS, - unsigned FileNo) { - unsigned Idx = FileNo - 1; - - if (Idx >= Files.size()) - Files.resize(Idx + 1); - - if (ChecksumOffsetsAssigned) { - OS.EmitSymbolValue(Files[Idx].ChecksumTableOffset, 4); - return; - } - - const MCSymbolRefExpr *SRE = - MCSymbolRefExpr::create(Files[Idx].ChecksumTableOffset, OS.getContext()); - - OS.EmitValueImpl(SRE, 4); -} - -void CodeViewContext::addLineEntry(const MCCVLoc &LineEntry) { - size_t Offset = MCCVLines.size(); - auto I = MCCVLineStartStop.insert( - {LineEntry.getFunctionId(), {Offset, Offset + 1}}); - if (!I.second) - I.first->second.second = Offset + 1; - MCCVLines.push_back(LineEntry); -} - -std::vector<MCCVLoc> -CodeViewContext::getFunctionLineEntries(unsigned FuncId) { - std::vector<MCCVLoc> FilteredLines; - auto I = MCCVLineStartStop.find(FuncId); - if (I != MCCVLineStartStop.end()) { - MCCVFunctionInfo *SiteInfo = getCVFunctionInfo(FuncId); - for (size_t Idx = I->second.first, End = I->second.second; Idx != End; - ++Idx) { - unsigned LocationFuncId = MCCVLines[Idx].getFunctionId(); - if (LocationFuncId == FuncId) { - // This was a .cv_loc directly for FuncId, so record it. - FilteredLines.push_back(MCCVLines[Idx]); - } else { - // Check if the current location is inlined in this function. If it is, - // synthesize a statement .cv_loc at the original inlined call site. - auto I = SiteInfo->InlinedAtMap.find(LocationFuncId); - if (I != SiteInfo->InlinedAtMap.end()) { - MCCVFunctionInfo::LineInfo &IA = I->second; - // Only add the location if it differs from the previous location. - // Large inlined calls will have many .cv_loc entries and we only need - // one line table entry in the parent function. - if (FilteredLines.empty() || - FilteredLines.back().getFileNum() != IA.File || - FilteredLines.back().getLine() != IA.Line || - FilteredLines.back().getColumn() != IA.Col) { - FilteredLines.push_back(MCCVLoc( - MCCVLines[Idx].getLabel(), - FuncId, IA.File, IA.Line, IA.Col, false, false)); - } - } - } - } - } - return FilteredLines; -} - -std::pair<size_t, size_t> CodeViewContext::getLineExtent(unsigned FuncId) { - auto I = MCCVLineStartStop.find(FuncId); - // Return an empty extent if there are no cv_locs for this function id. - if (I == MCCVLineStartStop.end()) - return {~0ULL, 0}; - return I->second; -} - -ArrayRef<MCCVLoc> CodeViewContext::getLinesForExtent(size_t L, size_t R) { - if (R <= L) - return None; - if (L >= MCCVLines.size()) - return None; - return makeArrayRef(&MCCVLines[L], R - L); -} - -void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS, - unsigned FuncId, - const MCSymbol *FuncBegin, - const MCSymbol *FuncEnd) { - MCContext &Ctx = OS.getContext(); - MCSymbol *LineBegin = Ctx.createTempSymbol("linetable_begin", false), - *LineEnd = Ctx.createTempSymbol("linetable_end", false); - - OS.EmitIntValue(unsigned(DebugSubsectionKind::Lines), 4); - OS.emitAbsoluteSymbolDiff(LineEnd, LineBegin, 4); - OS.EmitLabel(LineBegin); - OS.EmitCOFFSecRel32(FuncBegin, /*Offset=*/0); - OS.EmitCOFFSectionIndex(FuncBegin); - - // Actual line info. - std::vector<MCCVLoc> Locs = getFunctionLineEntries(FuncId); - bool HaveColumns = any_of(Locs, [](const MCCVLoc &LineEntry) { - return LineEntry.getColumn() != 0; - }); - OS.EmitIntValue(HaveColumns ? int(LF_HaveColumns) : 0, 2); - OS.emitAbsoluteSymbolDiff(FuncEnd, FuncBegin, 4); - - for (auto I = Locs.begin(), E = Locs.end(); I != E;) { - // Emit a file segment for the run of locations that share a file id. - unsigned CurFileNum = I->getFileNum(); - auto FileSegEnd = - std::find_if(I, E, [CurFileNum](const MCCVLoc &Loc) { - return Loc.getFileNum() != CurFileNum; - }); - unsigned EntryCount = FileSegEnd - I; - OS.AddComment( - "Segment for file '" + - Twine(getStringTableFragment() - ->getContents()[Files[CurFileNum - 1].StringTableOffset]) + - "' begins"); - OS.EmitCVFileChecksumOffsetDirective(CurFileNum); - OS.EmitIntValue(EntryCount, 4); - uint32_t SegmentSize = 12; - SegmentSize += 8 * EntryCount; - if (HaveColumns) - SegmentSize += 4 * EntryCount; - OS.EmitIntValue(SegmentSize, 4); - - for (auto J = I; J != FileSegEnd; ++J) { - OS.emitAbsoluteSymbolDiff(J->getLabel(), FuncBegin, 4); - unsigned LineData = J->getLine(); - if (J->isStmt()) - LineData |= LineInfo::StatementFlag; - OS.EmitIntValue(LineData, 4); - } - if (HaveColumns) { - for (auto J = I; J != FileSegEnd; ++J) { - OS.EmitIntValue(J->getColumn(), 2); - OS.EmitIntValue(0, 2); - } - } - I = FileSegEnd; - } - OS.EmitLabel(LineEnd); -} - -static bool compressAnnotation(uint32_t Data, SmallVectorImpl<char> &Buffer) { - if (isUInt<7>(Data)) { - Buffer.push_back(Data); - return true; - } - - if (isUInt<14>(Data)) { - Buffer.push_back((Data >> 8) | 0x80); - Buffer.push_back(Data & 0xff); - return true; - } - - if (isUInt<29>(Data)) { - Buffer.push_back((Data >> 24) | 0xC0); - Buffer.push_back((Data >> 16) & 0xff); - Buffer.push_back((Data >> 8) & 0xff); - Buffer.push_back(Data & 0xff); - return true; - } - - return false; -} - -static bool compressAnnotation(BinaryAnnotationsOpCode Annotation, - SmallVectorImpl<char> &Buffer) { - return compressAnnotation(static_cast<uint32_t>(Annotation), Buffer); -} - -static uint32_t encodeSignedNumber(uint32_t Data) { - if (Data >> 31) - return ((-Data) << 1) | 1; - return Data << 1; -} - -void CodeViewContext::emitInlineLineTableForFunction(MCObjectStreamer &OS, - unsigned PrimaryFunctionId, - unsigned SourceFileId, - unsigned SourceLineNum, - const MCSymbol *FnStartSym, - const MCSymbol *FnEndSym) { - // Create and insert a fragment into the current section that will be encoded - // later. - new MCCVInlineLineTableFragment(PrimaryFunctionId, SourceFileId, - SourceLineNum, FnStartSym, FnEndSym, - OS.getCurrentSectionOnly()); -} - -MCFragment *CodeViewContext::emitDefRange( - MCObjectStreamer &OS, - ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, - StringRef FixedSizePortion) { - // Create and insert a fragment into the current section that will be encoded - // later. - return new MCCVDefRangeFragment(Ranges, FixedSizePortion, - OS.getCurrentSectionOnly()); -} - -static unsigned computeLabelDiff(MCAsmLayout &Layout, const MCSymbol *Begin, - const MCSymbol *End) { - MCContext &Ctx = Layout.getAssembler().getContext(); - MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; - const MCExpr *BeginRef = MCSymbolRefExpr::create(Begin, Variant, Ctx), - *EndRef = MCSymbolRefExpr::create(End, Variant, Ctx); - const MCExpr *AddrDelta = - MCBinaryExpr::create(MCBinaryExpr::Sub, EndRef, BeginRef, Ctx); - int64_t Result; - bool Success = AddrDelta->evaluateKnownAbsolute(Result, Layout); - assert(Success && "failed to evaluate label difference as absolute"); - (void)Success; - assert(Result >= 0 && "negative label difference requested"); - assert(Result < UINT_MAX && "label difference greater than 2GB"); - return unsigned(Result); -} - -void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout, - MCCVInlineLineTableFragment &Frag) { - size_t LocBegin; - size_t LocEnd; - std::tie(LocBegin, LocEnd) = getLineExtent(Frag.SiteFuncId); - - // Include all child inline call sites in our .cv_loc extent. - MCCVFunctionInfo *SiteInfo = getCVFunctionInfo(Frag.SiteFuncId); - for (auto &KV : SiteInfo->InlinedAtMap) { - unsigned ChildId = KV.first; - auto Extent = getLineExtent(ChildId); - LocBegin = std::min(LocBegin, Extent.first); - LocEnd = std::max(LocEnd, Extent.second); - } - - if (LocBegin >= LocEnd) - return; - ArrayRef<MCCVLoc> Locs = getLinesForExtent(LocBegin, LocEnd); - if (Locs.empty()) - return; - - // Check that the locations are all in the same section. -#ifndef NDEBUG - const MCSection *FirstSec = &Locs.front().getLabel()->getSection(); - for (const MCCVLoc &Loc : Locs) { - if (&Loc.getLabel()->getSection() != FirstSec) { - errs() << ".cv_loc " << Loc.getFunctionId() << ' ' << Loc.getFileNum() - << ' ' << Loc.getLine() << ' ' << Loc.getColumn() - << " is in the wrong section\n"; - llvm_unreachable(".cv_loc crosses sections"); - } - } -#endif - - // Make an artificial start location using the function start and the inlinee - // lines start location information. All deltas start relative to this - // location. - MCCVLoc StartLoc = Locs.front(); - StartLoc.setLabel(Frag.getFnStartSym()); - StartLoc.setFileNum(Frag.StartFileId); - StartLoc.setLine(Frag.StartLineNum); - bool HaveOpenRange = false; - - const MCSymbol *LastLabel = Frag.getFnStartSym(); - MCCVFunctionInfo::LineInfo LastSourceLoc, CurSourceLoc; - LastSourceLoc.File = Frag.StartFileId; - LastSourceLoc.Line = Frag.StartLineNum; - - SmallVectorImpl<char> &Buffer = Frag.getContents(); - Buffer.clear(); // Clear old contents if we went through relaxation. - for (const MCCVLoc &Loc : Locs) { - // Exit early if our line table would produce an oversized InlineSiteSym - // record. Account for the ChangeCodeLength annotation emitted after the - // loop ends. - constexpr uint32_t InlineSiteSize = 12; - constexpr uint32_t AnnotationSize = 8; - size_t MaxBufferSize = MaxRecordLength - InlineSiteSize - AnnotationSize; - if (Buffer.size() >= MaxBufferSize) - break; - - if (Loc.getFunctionId() == Frag.SiteFuncId) { - CurSourceLoc.File = Loc.getFileNum(); - CurSourceLoc.Line = Loc.getLine(); - } else { - auto I = SiteInfo->InlinedAtMap.find(Loc.getFunctionId()); - if (I != SiteInfo->InlinedAtMap.end()) { - // This .cv_loc is from a child inline call site. Use the source - // location of the inlined call site instead of the .cv_loc directive - // source location. - CurSourceLoc = I->second; - } else { - // We've hit a cv_loc not attributed to this inline call site. Use this - // label to end the PC range. - if (HaveOpenRange) { - unsigned Length = computeLabelDiff(Layout, LastLabel, Loc.getLabel()); - compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer); - compressAnnotation(Length, Buffer); - LastLabel = Loc.getLabel(); - } - HaveOpenRange = false; - continue; - } - } - - // Skip this .cv_loc if we have an open range and this isn't a meaningful - // source location update. The current table format does not support column - // info, so we can skip updates for those. - if (HaveOpenRange && CurSourceLoc.File == LastSourceLoc.File && - CurSourceLoc.Line == LastSourceLoc.Line) - continue; - - HaveOpenRange = true; - - if (CurSourceLoc.File != LastSourceLoc.File) { - unsigned FileOffset = static_cast<const MCConstantExpr *>( - Files[CurSourceLoc.File - 1] - .ChecksumTableOffset->getVariableValue()) - ->getValue(); - compressAnnotation(BinaryAnnotationsOpCode::ChangeFile, Buffer); - compressAnnotation(FileOffset, Buffer); - } - - int LineDelta = CurSourceLoc.Line - LastSourceLoc.Line; - unsigned EncodedLineDelta = encodeSignedNumber(LineDelta); - unsigned CodeDelta = computeLabelDiff(Layout, LastLabel, Loc.getLabel()); - if (CodeDelta == 0 && LineDelta != 0) { - compressAnnotation(BinaryAnnotationsOpCode::ChangeLineOffset, Buffer); - compressAnnotation(EncodedLineDelta, Buffer); - } else if (EncodedLineDelta < 0x8 && CodeDelta <= 0xf) { - // The ChangeCodeOffsetAndLineOffset combination opcode is used when the - // encoded line delta uses 3 or fewer set bits and the code offset fits - // in one nibble. - unsigned Operand = (EncodedLineDelta << 4) | CodeDelta; - compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset, - Buffer); - compressAnnotation(Operand, Buffer); - } else { - // Otherwise use the separate line and code deltas. - if (LineDelta != 0) { - compressAnnotation(BinaryAnnotationsOpCode::ChangeLineOffset, Buffer); - compressAnnotation(EncodedLineDelta, Buffer); - } - compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeOffset, Buffer); - compressAnnotation(CodeDelta, Buffer); - } - - LastLabel = Loc.getLabel(); - LastSourceLoc = CurSourceLoc; - } - - assert(HaveOpenRange); - - unsigned EndSymLength = - computeLabelDiff(Layout, LastLabel, Frag.getFnEndSym()); - unsigned LocAfterLength = ~0U; - ArrayRef<MCCVLoc> LocAfter = getLinesForExtent(LocEnd, LocEnd + 1); - if (!LocAfter.empty()) { - // Only try to compute this difference if we're in the same section. - const MCCVLoc &Loc = LocAfter[0]; - if (&Loc.getLabel()->getSection() == &LastLabel->getSection()) - LocAfterLength = computeLabelDiff(Layout, LastLabel, Loc.getLabel()); - } - - compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer); - compressAnnotation(std::min(EndSymLength, LocAfterLength), Buffer); -} - -void CodeViewContext::encodeDefRange(MCAsmLayout &Layout, - MCCVDefRangeFragment &Frag) { - MCContext &Ctx = Layout.getAssembler().getContext(); - SmallVectorImpl<char> &Contents = Frag.getContents(); - Contents.clear(); - SmallVectorImpl<MCFixup> &Fixups = Frag.getFixups(); - Fixups.clear(); - raw_svector_ostream OS(Contents); - - // Compute all the sizes up front. - SmallVector<std::pair<unsigned, unsigned>, 4> GapAndRangeSizes; - const MCSymbol *LastLabel = nullptr; - for (std::pair<const MCSymbol *, const MCSymbol *> Range : Frag.getRanges()) { - unsigned GapSize = - LastLabel ? computeLabelDiff(Layout, LastLabel, Range.first) : 0; - unsigned RangeSize = computeLabelDiff(Layout, Range.first, Range.second); - GapAndRangeSizes.push_back({GapSize, RangeSize}); - LastLabel = Range.second; - } - - // Write down each range where the variable is defined. - for (size_t I = 0, E = Frag.getRanges().size(); I != E;) { - // If the range size of multiple consecutive ranges is under the max, - // combine the ranges and emit some gaps. - const MCSymbol *RangeBegin = Frag.getRanges()[I].first; - unsigned RangeSize = GapAndRangeSizes[I].second; - size_t J = I + 1; - for (; J != E; ++J) { - unsigned GapAndRangeSize = GapAndRangeSizes[J].first + GapAndRangeSizes[J].second; - if (RangeSize + GapAndRangeSize > MaxDefRange) - break; - RangeSize += GapAndRangeSize; - } - unsigned NumGaps = J - I - 1; - - support::endian::Writer LEWriter(OS, support::little); - - unsigned Bias = 0; - // We must split the range into chunks of MaxDefRange, this is a fundamental - // limitation of the file format. - do { - uint16_t Chunk = std::min((uint32_t)MaxDefRange, RangeSize); - - const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(RangeBegin, Ctx); - const MCBinaryExpr *BE = - MCBinaryExpr::createAdd(SRE, MCConstantExpr::create(Bias, Ctx), Ctx); - MCValue Res; - BE->evaluateAsRelocatable(Res, &Layout, /*Fixup=*/nullptr); - - // Each record begins with a 2-byte number indicating how large the record - // is. - StringRef FixedSizePortion = Frag.getFixedSizePortion(); - // Our record is a fixed sized prefix and a LocalVariableAddrRange that we - // are artificially constructing. - size_t RecordSize = FixedSizePortion.size() + - sizeof(LocalVariableAddrRange) + 4 * NumGaps; - // Write out the record size. - LEWriter.write<uint16_t>(RecordSize); - // Write out the fixed size prefix. - OS << FixedSizePortion; - // Make space for a fixup that will eventually have a section relative - // relocation pointing at the offset where the variable becomes live. - Fixups.push_back(MCFixup::create(Contents.size(), BE, FK_SecRel_4)); - LEWriter.write<uint32_t>(0); // Fixup for code start. - // Make space for a fixup that will record the section index for the code. - Fixups.push_back(MCFixup::create(Contents.size(), BE, FK_SecRel_2)); - LEWriter.write<uint16_t>(0); // Fixup for section index. - // Write down the range's extent. - LEWriter.write<uint16_t>(Chunk); - - // Move on to the next range. - Bias += Chunk; - RangeSize -= Chunk; - } while (RangeSize > 0); - - // Emit the gaps afterwards. - assert((NumGaps == 0 || Bias <= MaxDefRange) && - "large ranges should not have gaps"); - unsigned GapStartOffset = GapAndRangeSizes[I].second; - for (++I; I != J; ++I) { - unsigned GapSize, RangeSize; - assert(I < GapAndRangeSizes.size()); - std::tie(GapSize, RangeSize) = GapAndRangeSizes[I]; - LEWriter.write<uint16_t>(GapStartOffset); - LEWriter.write<uint16_t>(GapSize); - GapStartOffset += GapSize + RangeSize; - } - } -} diff --git a/contrib/llvm/lib/MC/MCContext.cpp b/contrib/llvm/lib/MC/MCContext.cpp deleted file mode 100644 index 6f9efec36361..000000000000 --- a/contrib/llvm/lib/MC/MCContext.cpp +++ /dev/null @@ -1,707 +0,0 @@ -//===- lib/MC/MCContext.cpp - Machine Code Context ------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCContext.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/BinaryFormat/COFF.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCCodeView.h" -#include "llvm/MC/MCDwarf.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFragment.h" -#include "llvm/MC/MCLabel.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCSectionCOFF.h" -#include "llvm/MC/MCSectionELF.h" -#include "llvm/MC/MCSectionMachO.h" -#include "llvm/MC/MCSectionWasm.h" -#include "llvm/MC/MCSectionXCOFF.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCSymbolCOFF.h" -#include "llvm/MC/MCSymbolELF.h" -#include "llvm/MC/MCSymbolMachO.h" -#include "llvm/MC/MCSymbolWasm.h" -#include "llvm/MC/MCSymbolXCOFF.h" -#include "llvm/MC/SectionKind.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/Signals.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> -#include <cstdlib> -#include <tuple> -#include <utility> - -using namespace llvm; - -static cl::opt<char*> -AsSecureLogFileName("as-secure-log-file-name", - cl::desc("As secure log file name (initialized from " - "AS_SECURE_LOG_FILE env variable)"), - cl::init(getenv("AS_SECURE_LOG_FILE")), cl::Hidden); - -MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri, - const MCObjectFileInfo *mofi, const SourceMgr *mgr, - bool DoAutoReset) - : SrcMgr(mgr), InlineSrcMgr(nullptr), MAI(mai), MRI(mri), MOFI(mofi), - Symbols(Allocator), UsedNames(Allocator), - InlineAsmUsedLabelNames(Allocator), - CurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0), - AutoReset(DoAutoReset) { - SecureLogFile = AsSecureLogFileName; - - if (SrcMgr && SrcMgr->getNumBuffers()) - MainFileName = - SrcMgr->getMemoryBuffer(SrcMgr->getMainFileID())->getBufferIdentifier(); -} - -MCContext::~MCContext() { - if (AutoReset) - reset(); - - // NOTE: The symbols are all allocated out of a bump pointer allocator, - // we don't need to free them here. -} - -//===----------------------------------------------------------------------===// -// Module Lifetime Management -//===----------------------------------------------------------------------===// - -void MCContext::reset() { - // Call the destructors so the fragments are freed - COFFAllocator.DestroyAll(); - ELFAllocator.DestroyAll(); - MachOAllocator.DestroyAll(); - XCOFFAllocator.DestroyAll(); - - MCSubtargetAllocator.DestroyAll(); - InlineAsmUsedLabelNames.clear(); - UsedNames.clear(); - Symbols.clear(); - Allocator.Reset(); - Instances.clear(); - CompilationDir.clear(); - MainFileName.clear(); - MCDwarfLineTablesCUMap.clear(); - SectionsForRanges.clear(); - MCGenDwarfLabelEntries.clear(); - DwarfDebugFlags = StringRef(); - DwarfCompileUnitID = 0; - CurrentDwarfLoc = MCDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0); - - CVContext.reset(); - - MachOUniquingMap.clear(); - ELFUniquingMap.clear(); - COFFUniquingMap.clear(); - WasmUniquingMap.clear(); - XCOFFUniquingMap.clear(); - - NextID.clear(); - AllowTemporaryLabels = true; - DwarfLocSeen = false; - GenDwarfForAssembly = false; - GenDwarfFileNumber = 0; - - HadError = false; -} - -//===----------------------------------------------------------------------===// -// Symbol Manipulation -//===----------------------------------------------------------------------===// - -MCSymbol *MCContext::getOrCreateSymbol(const Twine &Name) { - SmallString<128> NameSV; - StringRef NameRef = Name.toStringRef(NameSV); - - assert(!NameRef.empty() && "Normal symbols cannot be unnamed!"); - - MCSymbol *&Sym = Symbols[NameRef]; - if (!Sym) - Sym = createSymbol(NameRef, false, false); - - return Sym; -} - -MCSymbol *MCContext::getOrCreateFrameAllocSymbol(StringRef FuncName, - unsigned Idx) { - return getOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + FuncName + - "$frame_escape_" + Twine(Idx)); -} - -MCSymbol *MCContext::getOrCreateParentFrameOffsetSymbol(StringRef FuncName) { - return getOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + FuncName + - "$parent_frame_offset"); -} - -MCSymbol *MCContext::getOrCreateLSDASymbol(StringRef FuncName) { - return getOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + "__ehtable$" + - FuncName); -} - -MCSymbol *MCContext::createSymbolImpl(const StringMapEntry<bool> *Name, - bool IsTemporary) { - if (MOFI) { - switch (MOFI->getObjectFileType()) { - case MCObjectFileInfo::IsCOFF: - return new (Name, *this) MCSymbolCOFF(Name, IsTemporary); - case MCObjectFileInfo::IsELF: - return new (Name, *this) MCSymbolELF(Name, IsTemporary); - case MCObjectFileInfo::IsMachO: - return new (Name, *this) MCSymbolMachO(Name, IsTemporary); - case MCObjectFileInfo::IsWasm: - return new (Name, *this) MCSymbolWasm(Name, IsTemporary); - case MCObjectFileInfo::IsXCOFF: - return new (Name, *this) MCSymbolXCOFF(Name, IsTemporary); - } - } - return new (Name, *this) MCSymbol(MCSymbol::SymbolKindUnset, Name, - IsTemporary); -} - -MCSymbol *MCContext::createSymbol(StringRef Name, bool AlwaysAddSuffix, - bool CanBeUnnamed) { - if (CanBeUnnamed && !UseNamesOnTempLabels) - return createSymbolImpl(nullptr, true); - - // Determine whether this is a user written assembler temporary or normal - // label, if used. - bool IsTemporary = CanBeUnnamed; - if (AllowTemporaryLabels && !IsTemporary) - IsTemporary = Name.startswith(MAI->getPrivateGlobalPrefix()); - - SmallString<128> NewName = Name; - bool AddSuffix = AlwaysAddSuffix; - unsigned &NextUniqueID = NextID[Name]; - while (true) { - if (AddSuffix) { - NewName.resize(Name.size()); - raw_svector_ostream(NewName) << NextUniqueID++; - } - auto NameEntry = UsedNames.insert(std::make_pair(NewName, true)); - if (NameEntry.second || !NameEntry.first->second) { - // Ok, we found a name. - // Mark it as used for a non-section symbol. - NameEntry.first->second = true; - // Have the MCSymbol object itself refer to the copy of the string that is - // embedded in the UsedNames entry. - return createSymbolImpl(&*NameEntry.first, IsTemporary); - } - assert(IsTemporary && "Cannot rename non-temporary symbols"); - AddSuffix = true; - } - llvm_unreachable("Infinite loop"); -} - -MCSymbol *MCContext::createTempSymbol(const Twine &Name, bool AlwaysAddSuffix, - bool CanBeUnnamed) { - SmallString<128> NameSV; - raw_svector_ostream(NameSV) << MAI->getPrivateGlobalPrefix() << Name; - return createSymbol(NameSV, AlwaysAddSuffix, CanBeUnnamed); -} - -MCSymbol *MCContext::createLinkerPrivateTempSymbol() { - SmallString<128> NameSV; - raw_svector_ostream(NameSV) << MAI->getLinkerPrivateGlobalPrefix() << "tmp"; - return createSymbol(NameSV, true, false); -} - -MCSymbol *MCContext::createTempSymbol(bool CanBeUnnamed) { - return createTempSymbol("tmp", true, CanBeUnnamed); -} - -unsigned MCContext::NextInstance(unsigned LocalLabelVal) { - MCLabel *&Label = Instances[LocalLabelVal]; - if (!Label) - Label = new (*this) MCLabel(0); - return Label->incInstance(); -} - -unsigned MCContext::GetInstance(unsigned LocalLabelVal) { - MCLabel *&Label = Instances[LocalLabelVal]; - if (!Label) - Label = new (*this) MCLabel(0); - return Label->getInstance(); -} - -MCSymbol *MCContext::getOrCreateDirectionalLocalSymbol(unsigned LocalLabelVal, - unsigned Instance) { - MCSymbol *&Sym = LocalSymbols[std::make_pair(LocalLabelVal, Instance)]; - if (!Sym) - Sym = createTempSymbol(false); - return Sym; -} - -MCSymbol *MCContext::createDirectionalLocalSymbol(unsigned LocalLabelVal) { - unsigned Instance = NextInstance(LocalLabelVal); - return getOrCreateDirectionalLocalSymbol(LocalLabelVal, Instance); -} - -MCSymbol *MCContext::getDirectionalLocalSymbol(unsigned LocalLabelVal, - bool Before) { - unsigned Instance = GetInstance(LocalLabelVal); - if (!Before) - ++Instance; - return getOrCreateDirectionalLocalSymbol(LocalLabelVal, Instance); -} - -MCSymbol *MCContext::lookupSymbol(const Twine &Name) const { - SmallString<128> NameSV; - StringRef NameRef = Name.toStringRef(NameSV); - return Symbols.lookup(NameRef); -} - -void MCContext::setSymbolValue(MCStreamer &Streamer, - StringRef Sym, - uint64_t Val) { - auto Symbol = getOrCreateSymbol(Sym); - Streamer.EmitAssignment(Symbol, MCConstantExpr::create(Val, *this)); -} - -void MCContext::registerInlineAsmLabel(MCSymbol *Sym) { - InlineAsmUsedLabelNames[Sym->getName()] = Sym; -} - -//===----------------------------------------------------------------------===// -// Section Management -//===----------------------------------------------------------------------===// - -MCSectionMachO *MCContext::getMachOSection(StringRef Segment, StringRef Section, - unsigned TypeAndAttributes, - unsigned Reserved2, SectionKind Kind, - const char *BeginSymName) { - // We unique sections by their segment/section pair. The returned section - // may not have the same flags as the requested section, if so this should be - // diagnosed by the client as an error. - - // Form the name to look up. - SmallString<64> Name; - Name += Segment; - Name.push_back(','); - Name += Section; - - // Do the lookup, if we have a hit, return it. - MCSectionMachO *&Entry = MachOUniquingMap[Name]; - if (Entry) - return Entry; - - MCSymbol *Begin = nullptr; - if (BeginSymName) - Begin = createTempSymbol(BeginSymName, false); - - // Otherwise, return a new section. - return Entry = new (MachOAllocator.Allocate()) MCSectionMachO( - Segment, Section, TypeAndAttributes, Reserved2, Kind, Begin); -} - -void MCContext::renameELFSection(MCSectionELF *Section, StringRef Name) { - StringRef GroupName; - if (const MCSymbol *Group = Section->getGroup()) - GroupName = Group->getName(); - - unsigned UniqueID = Section->getUniqueID(); - ELFUniquingMap.erase( - ELFSectionKey{Section->getSectionName(), GroupName, UniqueID}); - auto I = ELFUniquingMap.insert(std::make_pair( - ELFSectionKey{Name, GroupName, UniqueID}, - Section)) - .first; - StringRef CachedName = I->first.SectionName; - const_cast<MCSectionELF *>(Section)->setSectionName(CachedName); -} - -MCSectionELF *MCContext::createELFSectionImpl(StringRef Section, unsigned Type, - unsigned Flags, SectionKind K, - unsigned EntrySize, - const MCSymbolELF *Group, - unsigned UniqueID, - const MCSymbolELF *Associated) { - MCSymbolELF *R; - MCSymbol *&Sym = Symbols[Section]; - // A section symbol can not redefine regular symbols. There may be multiple - // sections with the same name, in which case the first such section wins. - if (Sym && Sym->isDefined() && - (!Sym->isInSection() || Sym->getSection().getBeginSymbol() != Sym)) - reportError(SMLoc(), "invalid symbol redefinition"); - if (Sym && Sym->isUndefined()) { - R = cast<MCSymbolELF>(Sym); - } else { - auto NameIter = UsedNames.insert(std::make_pair(Section, false)).first; - R = new (&*NameIter, *this) MCSymbolELF(&*NameIter, /*isTemporary*/ false); - if (!Sym) - Sym = R; - } - R->setBinding(ELF::STB_LOCAL); - R->setType(ELF::STT_SECTION); - - auto *Ret = new (ELFAllocator.Allocate()) MCSectionELF( - Section, Type, Flags, K, EntrySize, Group, UniqueID, R, Associated); - - auto *F = new MCDataFragment(); - Ret->getFragmentList().insert(Ret->begin(), F); - F->setParent(Ret); - R->setFragment(F); - - return Ret; -} - -MCSectionELF *MCContext::createELFRelSection(const Twine &Name, unsigned Type, - unsigned Flags, unsigned EntrySize, - const MCSymbolELF *Group, - const MCSectionELF *RelInfoSection) { - StringMap<bool>::iterator I; - bool Inserted; - std::tie(I, Inserted) = - RelSecNames.insert(std::make_pair(Name.str(), true)); - - return createELFSectionImpl( - I->getKey(), Type, Flags, SectionKind::getReadOnly(), EntrySize, Group, - true, cast<MCSymbolELF>(RelInfoSection->getBeginSymbol())); -} - -MCSectionELF *MCContext::getELFNamedSection(const Twine &Prefix, - const Twine &Suffix, unsigned Type, - unsigned Flags, - unsigned EntrySize) { - return getELFSection(Prefix + "." + Suffix, Type, Flags, EntrySize, Suffix); -} - -MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type, - unsigned Flags, unsigned EntrySize, - const Twine &Group, unsigned UniqueID, - const MCSymbolELF *Associated) { - MCSymbolELF *GroupSym = nullptr; - if (!Group.isTriviallyEmpty() && !Group.str().empty()) - GroupSym = cast<MCSymbolELF>(getOrCreateSymbol(Group)); - - return getELFSection(Section, Type, Flags, EntrySize, GroupSym, UniqueID, - Associated); -} - -MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type, - unsigned Flags, unsigned EntrySize, - const MCSymbolELF *GroupSym, - unsigned UniqueID, - const MCSymbolELF *Associated) { - StringRef Group = ""; - if (GroupSym) - Group = GroupSym->getName(); - // Do the lookup, if we have a hit, return it. - auto IterBool = ELFUniquingMap.insert( - std::make_pair(ELFSectionKey{Section.str(), Group, UniqueID}, nullptr)); - auto &Entry = *IterBool.first; - if (!IterBool.second) - return Entry.second; - - StringRef CachedName = Entry.first.SectionName; - - SectionKind Kind; - if (Flags & ELF::SHF_ARM_PURECODE) - Kind = SectionKind::getExecuteOnly(); - else if (Flags & ELF::SHF_EXECINSTR) - Kind = SectionKind::getText(); - else - Kind = SectionKind::getReadOnly(); - - MCSectionELF *Result = createELFSectionImpl( - CachedName, Type, Flags, Kind, EntrySize, GroupSym, UniqueID, Associated); - Entry.second = Result; - return Result; -} - -MCSectionELF *MCContext::createELFGroupSection(const MCSymbolELF *Group) { - return createELFSectionImpl(".group", ELF::SHT_GROUP, 0, - SectionKind::getReadOnly(), 4, Group, ~0, - nullptr); -} - -MCSectionCOFF *MCContext::getCOFFSection(StringRef Section, - unsigned Characteristics, - SectionKind Kind, - StringRef COMDATSymName, int Selection, - unsigned UniqueID, - const char *BeginSymName) { - MCSymbol *COMDATSymbol = nullptr; - if (!COMDATSymName.empty()) { - COMDATSymbol = getOrCreateSymbol(COMDATSymName); - COMDATSymName = COMDATSymbol->getName(); - } - - - // Do the lookup, if we have a hit, return it. - COFFSectionKey T{Section, COMDATSymName, Selection, UniqueID}; - auto IterBool = COFFUniquingMap.insert(std::make_pair(T, nullptr)); - auto Iter = IterBool.first; - if (!IterBool.second) - return Iter->second; - - MCSymbol *Begin = nullptr; - if (BeginSymName) - Begin = createTempSymbol(BeginSymName, false); - - StringRef CachedName = Iter->first.SectionName; - MCSectionCOFF *Result = new (COFFAllocator.Allocate()) MCSectionCOFF( - CachedName, Characteristics, COMDATSymbol, Selection, Kind, Begin); - - Iter->second = Result; - return Result; -} - -MCSectionCOFF *MCContext::getCOFFSection(StringRef Section, - unsigned Characteristics, - SectionKind Kind, - const char *BeginSymName) { - return getCOFFSection(Section, Characteristics, Kind, "", 0, GenericSectionID, - BeginSymName); -} - -MCSectionCOFF *MCContext::getAssociativeCOFFSection(MCSectionCOFF *Sec, - const MCSymbol *KeySym, - unsigned UniqueID) { - // Return the normal section if we don't have to be associative or unique. - if (!KeySym && UniqueID == GenericSectionID) - return Sec; - - // If we have a key symbol, make an associative section with the same name and - // kind as the normal section. - unsigned Characteristics = Sec->getCharacteristics(); - if (KeySym) { - Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; - return getCOFFSection(Sec->getSectionName(), Characteristics, - Sec->getKind(), KeySym->getName(), - COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, UniqueID); - } - - return getCOFFSection(Sec->getSectionName(), Characteristics, Sec->getKind(), - "", 0, UniqueID); -} - -MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind K, - const Twine &Group, unsigned UniqueID, - const char *BeginSymName) { - MCSymbolWasm *GroupSym = nullptr; - if (!Group.isTriviallyEmpty() && !Group.str().empty()) { - GroupSym = cast<MCSymbolWasm>(getOrCreateSymbol(Group)); - GroupSym->setComdat(true); - } - - return getWasmSection(Section, K, GroupSym, UniqueID, BeginSymName); -} - -MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind Kind, - const MCSymbolWasm *GroupSym, - unsigned UniqueID, - const char *BeginSymName) { - StringRef Group = ""; - if (GroupSym) - Group = GroupSym->getName(); - // Do the lookup, if we have a hit, return it. - auto IterBool = WasmUniquingMap.insert( - std::make_pair(WasmSectionKey{Section.str(), Group, UniqueID}, nullptr)); - auto &Entry = *IterBool.first; - if (!IterBool.second) - return Entry.second; - - StringRef CachedName = Entry.first.SectionName; - - MCSymbol *Begin = createSymbol(CachedName, false, false); - cast<MCSymbolWasm>(Begin)->setType(wasm::WASM_SYMBOL_TYPE_SECTION); - - MCSectionWasm *Result = new (WasmAllocator.Allocate()) - MCSectionWasm(CachedName, Kind, GroupSym, UniqueID, Begin); - Entry.second = Result; - - auto *F = new MCDataFragment(); - Result->getFragmentList().insert(Result->begin(), F); - F->setParent(Result); - Begin->setFragment(F); - - return Result; -} - -MCSectionXCOFF *MCContext::getXCOFFSection(StringRef Section, - XCOFF::StorageMappingClass SMC, - SectionKind Kind, - const char *BeginSymName) { - // Do the lookup. If we have a hit, return it. - auto IterBool = XCOFFUniquingMap.insert( - std::make_pair(XCOFFSectionKey{Section.str(), SMC}, nullptr)); - auto &Entry = *IterBool.first; - if (!IterBool.second) - return Entry.second; - - // Otherwise, return a new section. - StringRef CachedName = Entry.first.SectionName; - - MCSymbol *Begin = nullptr; - if (BeginSymName) - Begin = createTempSymbol(BeginSymName, false); - - MCSectionXCOFF *Result = new (XCOFFAllocator.Allocate()) - MCSectionXCOFF(CachedName, SMC, Kind, Begin); - Entry.second = Result; - - auto *F = new MCDataFragment(); - Result->getFragmentList().insert(Result->begin(), F); - F->setParent(Result); - - if (Begin) - Begin->setFragment(F); - - return Result; -} - -MCSubtargetInfo &MCContext::getSubtargetCopy(const MCSubtargetInfo &STI) { - return *new (MCSubtargetAllocator.Allocate()) MCSubtargetInfo(STI); -} - -void MCContext::addDebugPrefixMapEntry(const std::string &From, - const std::string &To) { - DebugPrefixMap.insert(std::make_pair(From, To)); -} - -void MCContext::RemapDebugPaths() { - const auto &DebugPrefixMap = this->DebugPrefixMap; - const auto RemapDebugPath = [&DebugPrefixMap](std::string &Path) { - for (const auto &Entry : DebugPrefixMap) - if (StringRef(Path).startswith(Entry.first)) { - std::string RemappedPath = - (Twine(Entry.second) + Path.substr(Entry.first.size())).str(); - Path.swap(RemappedPath); - } - }; - - // Remap compilation directory. - std::string CompDir = CompilationDir.str(); - RemapDebugPath(CompDir); - CompilationDir = CompDir; - - // Remap MCDwarfDirs in all compilation units. - for (auto &CUIDTablePair : MCDwarfLineTablesCUMap) - for (auto &Dir : CUIDTablePair.second.getMCDwarfDirs()) - RemapDebugPath(Dir); -} - -//===----------------------------------------------------------------------===// -// Dwarf Management -//===----------------------------------------------------------------------===// - -void MCContext::setGenDwarfRootFile(StringRef InputFileName, StringRef Buffer) { - // MCDwarf needs the root file as well as the compilation directory. - // If we find a '.file 0' directive that will supersede these values. - Optional<MD5::MD5Result> Cksum; - if (getDwarfVersion() >= 5) { - MD5 Hash; - MD5::MD5Result Sum; - Hash.update(Buffer); - Hash.final(Sum); - Cksum = Sum; - } - // Canonicalize the root filename. It cannot be empty, and should not - // repeat the compilation dir. - // The MCContext ctor initializes MainFileName to the name associated with - // the SrcMgr's main file ID, which might be the same as InputFileName (and - // possibly include directory components). - // Or, MainFileName might have been overridden by a -main-file-name option, - // which is supposed to be just a base filename with no directory component. - // So, if the InputFileName and MainFileName are not equal, assume - // MainFileName is a substitute basename and replace the last component. - SmallString<1024> FileNameBuf = InputFileName; - if (FileNameBuf.empty() || FileNameBuf == "-") - FileNameBuf = "<stdin>"; - if (!getMainFileName().empty() && FileNameBuf != getMainFileName()) { - llvm::sys::path::remove_filename(FileNameBuf); - llvm::sys::path::append(FileNameBuf, getMainFileName()); - } - StringRef FileName = FileNameBuf; - if (FileName.consume_front(getCompilationDir())) - if (llvm::sys::path::is_separator(FileName.front())) - FileName = FileName.drop_front(); - assert(!FileName.empty()); - setMCLineTableRootFile( - /*CUID=*/0, getCompilationDir(), FileName, Cksum, None); -} - -/// getDwarfFile - takes a file name and number to place in the dwarf file and -/// directory tables. If the file number has already been allocated it is an -/// error and zero is returned and the client reports the error, else the -/// allocated file number is returned. The file numbers may be in any order. -Expected<unsigned> MCContext::getDwarfFile(StringRef Directory, - StringRef FileName, - unsigned FileNumber, - Optional<MD5::MD5Result> Checksum, - Optional<StringRef> Source, - unsigned CUID) { - MCDwarfLineTable &Table = MCDwarfLineTablesCUMap[CUID]; - return Table.tryGetFile(Directory, FileName, Checksum, Source, DwarfVersion, - FileNumber); -} - -/// isValidDwarfFileNumber - takes a dwarf file number and returns true if it -/// currently is assigned and false otherwise. -bool MCContext::isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID) { - const MCDwarfLineTable &LineTable = getMCDwarfLineTable(CUID); - if (FileNumber == 0) - return getDwarfVersion() >= 5; - if (FileNumber >= LineTable.getMCDwarfFiles().size()) - return false; - - return !LineTable.getMCDwarfFiles()[FileNumber].Name.empty(); -} - -/// Remove empty sections from SectionsForRanges, to avoid generating -/// useless debug info for them. -void MCContext::finalizeDwarfSections(MCStreamer &MCOS) { - SectionsForRanges.remove_if( - [&](MCSection *Sec) { return !MCOS.mayHaveInstructions(*Sec); }); -} - -CodeViewContext &MCContext::getCVContext() { - if (!CVContext.get()) - CVContext.reset(new CodeViewContext); - return *CVContext.get(); -} - -//===----------------------------------------------------------------------===// -// Error Reporting -//===----------------------------------------------------------------------===// - -void MCContext::reportError(SMLoc Loc, const Twine &Msg) { - HadError = true; - - // If we have a source manager use it. Otherwise, try using the inline source - // manager. - // If that fails, use the generic report_fatal_error(). - if (SrcMgr) - SrcMgr->PrintMessage(Loc, SourceMgr::DK_Error, Msg); - else if (InlineSrcMgr) - InlineSrcMgr->PrintMessage(Loc, SourceMgr::DK_Error, Msg); - else - report_fatal_error(Msg, false); -} - -void MCContext::reportFatalError(SMLoc Loc, const Twine &Msg) { - reportError(Loc, Msg); - - // If we reached here, we are failing ungracefully. Run the interrupt handlers - // to make sure any special cleanups get done, in particular that we remove - // files registered with RemoveFileOnSignal. - sys::RunInterruptHandlers(); - exit(1); -} diff --git a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp deleted file mode 100644 index 21bdc2eaea3e..000000000000 --- a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp +++ /dev/null @@ -1,343 +0,0 @@ -//===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface ---------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "Disassembler.h" -#include "llvm-c/Disassembler.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Triple.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDisassembler/MCDisassembler.h" -#include "llvm/MC/MCDisassembler/MCRelocationInfo.h" -#include "llvm/MC/MCDisassembler/MCSymbolizer.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCInstPrinter.h" -#include "llvm/MC/MCInstrDesc.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCInstrItineraries.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSchedule.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> -#include <cstddef> -#include <cstring> - -using namespace llvm; - -// LLVMCreateDisasm() creates a disassembler for the TripleName. Symbolic -// disassembly is supported by passing a block of information in the DisInfo -// parameter and specifying the TagType and callback functions as described in -// the header llvm-c/Disassembler.h . The pointer to the block and the -// functions can all be passed as NULL. If successful, this returns a -// disassembler context. If not, it returns NULL. -// -LLVMDisasmContextRef -LLVMCreateDisasmCPUFeatures(const char *TT, const char *CPU, - const char *Features, void *DisInfo, int TagType, - LLVMOpInfoCallback GetOpInfo, - LLVMSymbolLookupCallback SymbolLookUp) { - // Get the target. - std::string Error; - const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error); - if (!TheTarget) - return nullptr; - - std::unique_ptr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); - if (!MRI) - return nullptr; - - // Get the assembler info needed to setup the MCContext. - std::unique_ptr<const MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT)); - if (!MAI) - return nullptr; - - std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo()); - if (!MII) - return nullptr; - - std::unique_ptr<const MCSubtargetInfo> STI( - TheTarget->createMCSubtargetInfo(TT, CPU, Features)); - if (!STI) - return nullptr; - - // Set up the MCContext for creating symbols and MCExpr's. - std::unique_ptr<MCContext> Ctx(new MCContext(MAI.get(), MRI.get(), nullptr)); - if (!Ctx) - return nullptr; - - // Set up disassembler. - std::unique_ptr<MCDisassembler> DisAsm( - TheTarget->createMCDisassembler(*STI, *Ctx)); - if (!DisAsm) - return nullptr; - - std::unique_ptr<MCRelocationInfo> RelInfo( - TheTarget->createMCRelocationInfo(TT, *Ctx)); - if (!RelInfo) - return nullptr; - - std::unique_ptr<MCSymbolizer> Symbolizer(TheTarget->createMCSymbolizer( - TT, GetOpInfo, SymbolLookUp, DisInfo, Ctx.get(), std::move(RelInfo))); - DisAsm->setSymbolizer(std::move(Symbolizer)); - - // Set up the instruction printer. - int AsmPrinterVariant = MAI->getAssemblerDialect(); - std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( - Triple(TT), AsmPrinterVariant, *MAI, *MII, *MRI)); - if (!IP) - return nullptr; - - LLVMDisasmContext *DC = new LLVMDisasmContext( - TT, DisInfo, TagType, GetOpInfo, SymbolLookUp, TheTarget, std::move(MAI), - std::move(MRI), std::move(STI), std::move(MII), std::move(Ctx), - std::move(DisAsm), std::move(IP)); - if (!DC) - return nullptr; - - DC->setCPU(CPU); - return DC; -} - -LLVMDisasmContextRef -LLVMCreateDisasmCPU(const char *TT, const char *CPU, void *DisInfo, int TagType, - LLVMOpInfoCallback GetOpInfo, - LLVMSymbolLookupCallback SymbolLookUp) { - return LLVMCreateDisasmCPUFeatures(TT, CPU, "", DisInfo, TagType, GetOpInfo, - SymbolLookUp); -} - -LLVMDisasmContextRef LLVMCreateDisasm(const char *TT, void *DisInfo, - int TagType, LLVMOpInfoCallback GetOpInfo, - LLVMSymbolLookupCallback SymbolLookUp) { - return LLVMCreateDisasmCPUFeatures(TT, "", "", DisInfo, TagType, GetOpInfo, - SymbolLookUp); -} - -// -// LLVMDisasmDispose() disposes of the disassembler specified by the context. -// -void LLVMDisasmDispose(LLVMDisasmContextRef DCR){ - LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); - delete DC; -} - -/// Emits the comments that are stored in \p DC comment stream. -/// Each comment in the comment stream must end with a newline. -static void emitComments(LLVMDisasmContext *DC, - formatted_raw_ostream &FormattedOS) { - // Flush the stream before taking its content. - StringRef Comments = DC->CommentsToEmit.str(); - // Get the default information for printing a comment. - const MCAsmInfo *MAI = DC->getAsmInfo(); - StringRef CommentBegin = MAI->getCommentString(); - unsigned CommentColumn = MAI->getCommentColumn(); - bool IsFirst = true; - while (!Comments.empty()) { - if (!IsFirst) - FormattedOS << '\n'; - // Emit a line of comments. - FormattedOS.PadToColumn(CommentColumn); - size_t Position = Comments.find('\n'); - FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position); - // Move after the newline character. - Comments = Comments.substr(Position+1); - IsFirst = false; - } - FormattedOS.flush(); - - // Tell the comment stream that the vector changed underneath it. - DC->CommentsToEmit.clear(); -} - -/// Gets latency information for \p Inst from the itinerary -/// scheduling model, based on \p DC information. -/// \return The maximum expected latency over all the operands or -1 -/// if no information is available. -static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) { - const int NoInformationAvailable = -1; - - // Check if we have a CPU to get the itinerary information. - if (DC->getCPU().empty()) - return NoInformationAvailable; - - // Get itinerary information. - const MCSubtargetInfo *STI = DC->getSubtargetInfo(); - InstrItineraryData IID = STI->getInstrItineraryForCPU(DC->getCPU()); - // Get the scheduling class of the requested instruction. - const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode()); - unsigned SCClass = Desc.getSchedClass(); - - int Latency = 0; - for (unsigned OpIdx = 0, OpIdxEnd = Inst.getNumOperands(); OpIdx != OpIdxEnd; - ++OpIdx) - Latency = std::max(Latency, IID.getOperandCycle(SCClass, OpIdx)); - - return Latency; -} - -/// Gets latency information for \p Inst, based on \p DC information. -/// \return The maximum expected latency over all the definitions or -1 -/// if no information is available. -static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) { - // Try to compute scheduling information. - const MCSubtargetInfo *STI = DC->getSubtargetInfo(); - const MCSchedModel SCModel = STI->getSchedModel(); - const int NoInformationAvailable = -1; - - // Check if we have a scheduling model for instructions. - if (!SCModel.hasInstrSchedModel()) - // Try to fall back to the itinerary model if the scheduling model doesn't - // have a scheduling table. Note the default does not have a table. - return getItineraryLatency(DC, Inst); - - // Get the scheduling class of the requested instruction. - const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode()); - unsigned SCClass = Desc.getSchedClass(); - const MCSchedClassDesc *SCDesc = SCModel.getSchedClassDesc(SCClass); - // Resolving the variant SchedClass requires an MI to pass to - // SubTargetInfo::resolveSchedClass. - if (!SCDesc || !SCDesc->isValid() || SCDesc->isVariant()) - return NoInformationAvailable; - - // Compute output latency. - int16_t Latency = 0; - for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries; - DefIdx != DefEnd; ++DefIdx) { - // Lookup the definition's write latency in SubtargetInfo. - const MCWriteLatencyEntry *WLEntry = STI->getWriteLatencyEntry(SCDesc, - DefIdx); - Latency = std::max(Latency, WLEntry->Cycles); - } - - return Latency; -} - -/// Emits latency information in DC->CommentStream for \p Inst, based -/// on the information available in \p DC. -static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) { - int Latency = getLatency(DC, Inst); - - // Report only interesting latencies. - if (Latency < 2) - return; - - DC->CommentStream << "Latency: " << Latency << '\n'; -} - -// -// LLVMDisasmInstruction() disassembles a single instruction using the -// disassembler context specified in the parameter DC. The bytes of the -// instruction are specified in the parameter Bytes, and contains at least -// BytesSize number of bytes. The instruction is at the address specified by -// the PC parameter. If a valid instruction can be disassembled its string is -// returned indirectly in OutString which whos size is specified in the -// parameter OutStringSize. This function returns the number of bytes in the -// instruction or zero if there was no valid instruction. If this function -// returns zero the caller will have to pick how many bytes they want to step -// over by printing a .byte, .long etc. to continue. -// -size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes, - uint64_t BytesSize, uint64_t PC, char *OutString, - size_t OutStringSize){ - LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); - // Wrap the pointer to the Bytes, BytesSize and PC in a MemoryObject. - ArrayRef<uint8_t> Data(Bytes, BytesSize); - - uint64_t Size; - MCInst Inst; - const MCDisassembler *DisAsm = DC->getDisAsm(); - MCInstPrinter *IP = DC->getIP(); - MCDisassembler::DecodeStatus S; - SmallVector<char, 64> InsnStr; - raw_svector_ostream Annotations(InsnStr); - S = DisAsm->getInstruction(Inst, Size, Data, PC, - /*REMOVE*/ nulls(), Annotations); - switch (S) { - case MCDisassembler::Fail: - case MCDisassembler::SoftFail: - // FIXME: Do something different for soft failure modes? - return 0; - - case MCDisassembler::Success: { - StringRef AnnotationsStr = Annotations.str(); - - SmallVector<char, 64> InsnStr; - raw_svector_ostream OS(InsnStr); - formatted_raw_ostream FormattedOS(OS); - IP->printInst(&Inst, FormattedOS, AnnotationsStr, *DC->getSubtargetInfo()); - - if (DC->getOptions() & LLVMDisassembler_Option_PrintLatency) - emitLatency(DC, Inst); - - emitComments(DC, FormattedOS); - - assert(OutStringSize != 0 && "Output buffer cannot be zero size"); - size_t OutputSize = std::min(OutStringSize-1, InsnStr.size()); - std::memcpy(OutString, InsnStr.data(), OutputSize); - OutString[OutputSize] = '\0'; // Terminate string. - - return Size; - } - } - llvm_unreachable("Invalid DecodeStatus!"); -} - -// -// LLVMSetDisasmOptions() sets the disassembler's options. It returns 1 if it -// can set all the Options and 0 otherwise. -// -int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){ - if (Options & LLVMDisassembler_Option_UseMarkup){ - LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); - MCInstPrinter *IP = DC->getIP(); - IP->setUseMarkup(true); - DC->addOptions(LLVMDisassembler_Option_UseMarkup); - Options &= ~LLVMDisassembler_Option_UseMarkup; - } - if (Options & LLVMDisassembler_Option_PrintImmHex){ - LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); - MCInstPrinter *IP = DC->getIP(); - IP->setPrintImmHex(true); - DC->addOptions(LLVMDisassembler_Option_PrintImmHex); - Options &= ~LLVMDisassembler_Option_PrintImmHex; - } - if (Options & LLVMDisassembler_Option_AsmPrinterVariant){ - LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); - // Try to set up the new instruction printer. - const MCAsmInfo *MAI = DC->getAsmInfo(); - const MCInstrInfo *MII = DC->getInstrInfo(); - const MCRegisterInfo *MRI = DC->getRegisterInfo(); - int AsmPrinterVariant = MAI->getAssemblerDialect(); - AsmPrinterVariant = AsmPrinterVariant == 0 ? 1 : 0; - MCInstPrinter *IP = DC->getTarget()->createMCInstPrinter( - Triple(DC->getTripleName()), AsmPrinterVariant, *MAI, *MII, *MRI); - if (IP) { - DC->setIP(IP); - DC->addOptions(LLVMDisassembler_Option_AsmPrinterVariant); - Options &= ~LLVMDisassembler_Option_AsmPrinterVariant; - } - } - if (Options & LLVMDisassembler_Option_SetInstrComments) { - LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); - MCInstPrinter *IP = DC->getIP(); - IP->setCommentStream(DC->CommentStream); - DC->addOptions(LLVMDisassembler_Option_SetInstrComments); - Options &= ~LLVMDisassembler_Option_SetInstrComments; - } - if (Options & LLVMDisassembler_Option_PrintLatency) { - LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); - DC->addOptions(LLVMDisassembler_Option_PrintLatency); - Options &= ~LLVMDisassembler_Option_PrintLatency; - } - return (Options == 0); -} diff --git a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h deleted file mode 100644 index e5aab53a7613..000000000000 --- a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h +++ /dev/null @@ -1,124 +0,0 @@ -//===------------- Disassembler.h - LLVM Disassembler -----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the interface for the Disassembly library's disassembler -// context. The disassembler is responsible for producing strings for -// individual instructions according to a given architecture and disassembly -// syntax. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_MC_MCDISASSEMBLER_DISASSEMBLER_H -#define LLVM_LIB_MC_MCDISASSEMBLER_DISASSEMBLER_H - -#include "llvm-c/Disassembler.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDisassembler/MCDisassembler.h" -#include "llvm/MC/MCInstPrinter.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/Support/raw_ostream.h" -#include <string> -#include <utility> - -namespace llvm { -class Target; - -// -// This is the disassembler context returned by LLVMCreateDisasm(). -// -class LLVMDisasmContext { -private: - // - // The passed parameters when the disassembler context is created. - // - // The TripleName for this disassembler. - std::string TripleName; - // The pointer to the caller's block of symbolic information. - void *DisInfo; - // The Triple specific symbolic information type returned by GetOpInfo. - int TagType; - // The function to get the symbolic information for operands. - LLVMOpInfoCallback GetOpInfo; - // The function to look up a symbol name. - LLVMSymbolLookupCallback SymbolLookUp; - // - // The objects created and saved by LLVMCreateDisasm() then used by - // LLVMDisasmInstruction(). - // - // The LLVM target corresponding to the disassembler. - // FIXME: using std::unique_ptr<const llvm::Target> causes a malloc error - // when this LLVMDisasmContext is deleted. - const Target *TheTarget; - // The assembly information for the target architecture. - std::unique_ptr<const llvm::MCAsmInfo> MAI; - // The register information for the target architecture. - std::unique_ptr<const llvm::MCRegisterInfo> MRI; - // The subtarget information for the target architecture. - std::unique_ptr<const llvm::MCSubtargetInfo> MSI; - // The instruction information for the target architecture. - std::unique_ptr<const llvm::MCInstrInfo> MII; - // The assembly context for creating symbols and MCExprs. - std::unique_ptr<const llvm::MCContext> Ctx; - // The disassembler for the target architecture. - std::unique_ptr<const llvm::MCDisassembler> DisAsm; - // The instruction printer for the target architecture. - std::unique_ptr<llvm::MCInstPrinter> IP; - // The options used to set up the disassembler. - uint64_t Options; - // The CPU string. - std::string CPU; - -public: - // Comment stream and backing vector. - SmallString<128> CommentsToEmit; - raw_svector_ostream CommentStream; - - LLVMDisasmContext(std::string TripleName, void *DisInfo, int TagType, - LLVMOpInfoCallback GetOpInfo, - LLVMSymbolLookupCallback SymbolLookUp, - const Target *TheTarget, - std::unique_ptr<const MCAsmInfo> &&MAI, - std::unique_ptr<const MCRegisterInfo> &&MRI, - std::unique_ptr<const MCSubtargetInfo> &&MSI, - std::unique_ptr<const MCInstrInfo> &&MII, - std::unique_ptr<const llvm::MCContext> &&Ctx, - std::unique_ptr<const MCDisassembler> &&DisAsm, - std::unique_ptr<MCInstPrinter> &&IP) - : TripleName(std::move(TripleName)), DisInfo(DisInfo), TagType(TagType), - GetOpInfo(GetOpInfo), SymbolLookUp(SymbolLookUp), TheTarget(TheTarget), - MAI(std::move(MAI)), MRI(std::move(MRI)), MSI(std::move(MSI)), - MII(std::move(MII)), Ctx(std::move(Ctx)), DisAsm(std::move(DisAsm)), - IP(std::move(IP)), Options(0), CommentStream(CommentsToEmit) {} - const std::string &getTripleName() const { return TripleName; } - void *getDisInfo() const { return DisInfo; } - int getTagType() const { return TagType; } - LLVMOpInfoCallback getGetOpInfo() const { return GetOpInfo; } - LLVMSymbolLookupCallback getSymbolLookupCallback() const { - return SymbolLookUp; - } - const Target *getTarget() const { return TheTarget; } - const MCDisassembler *getDisAsm() const { return DisAsm.get(); } - const MCAsmInfo *getAsmInfo() const { return MAI.get(); } - const MCInstrInfo *getInstrInfo() const { return MII.get(); } - const MCRegisterInfo *getRegisterInfo() const { return MRI.get(); } - const MCSubtargetInfo *getSubtargetInfo() const { return MSI.get(); } - MCInstPrinter *getIP() { return IP.get(); } - void setIP(MCInstPrinter *NewIP) { IP.reset(NewIP); } - uint64_t getOptions() const { return Options; } - void addOptions(uint64_t Options) { this->Options |= Options; } - StringRef getCPU() const { return CPU; } - void setCPU(const char *CPU) { this->CPU = CPU; } -}; - -} // namespace llvm - -#endif diff --git a/contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp b/contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp deleted file mode 100644 index 063f7e706024..000000000000 --- a/contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp +++ /dev/null @@ -1,46 +0,0 @@ -//===- MCDisassembler.cpp - Disassembler interface ------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCDisassembler/MCDisassembler.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> - -using namespace llvm; - -MCDisassembler::~MCDisassembler() = default; - -MCDisassembler::DecodeStatus MCDisassembler::onSymbolStart( - StringRef Name, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address, - raw_ostream &VStream, raw_ostream &CStream) const { - Size = 0; - return MCDisassembler::Success; -} - -bool MCDisassembler::tryAddingSymbolicOperand(MCInst &Inst, int64_t Value, - uint64_t Address, bool IsBranch, - uint64_t Offset, - uint64_t InstSize) const { - raw_ostream &cStream = CommentStream ? *CommentStream : nulls(); - if (Symbolizer) - return Symbolizer->tryAddingSymbolicOperand(Inst, cStream, Value, Address, - IsBranch, Offset, InstSize); - return false; -} - -void MCDisassembler::tryAddingPcLoadReferenceComment(int64_t Value, - uint64_t Address) const { - raw_ostream &cStream = CommentStream ? *CommentStream : nulls(); - if (Symbolizer) - Symbolizer->tryAddingPcLoadReferenceComment(cStream, Value, Address); -} - -void MCDisassembler::setSymbolizer(std::unique_ptr<MCSymbolizer> Symzer) { - Symbolizer = std::move(Symzer); -} diff --git a/contrib/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp b/contrib/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp deleted file mode 100644 index 7befef86303c..000000000000 --- a/contrib/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp +++ /dev/null @@ -1,199 +0,0 @@ -//===-- MCExternalSymbolizer.cpp - External symbolizer --------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCDisassembler/MCExternalSymbolizer.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" -#include "llvm/Support/raw_ostream.h" -#include <cstring> - -using namespace llvm; - -namespace llvm { -class Triple; -} - -// This function tries to add a symbolic operand in place of the immediate -// Value in the MCInst. The immediate Value has had any PC adjustment made by -// the caller. If the instruction is a branch instruction then IsBranch is true, -// else false. If the getOpInfo() function was set as part of the -// setupForSymbolicDisassembly() call then that function is called to get any -// symbolic information at the Address for this instruction. If that returns -// non-zero then the symbolic information it returns is used to create an MCExpr -// and that is added as an operand to the MCInst. If getOpInfo() returns zero -// and IsBranch is true then a symbol look up for Value is done and if a symbol -// is found an MCExpr is created with that, else an MCExpr with Value is -// created. This function returns true if it adds an operand to the MCInst and -// false otherwise. -bool MCExternalSymbolizer::tryAddingSymbolicOperand(MCInst &MI, - raw_ostream &cStream, - int64_t Value, - uint64_t Address, - bool IsBranch, - uint64_t Offset, - uint64_t InstSize) { - struct LLVMOpInfo1 SymbolicOp; - std::memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1)); - SymbolicOp.Value = Value; - - if (!GetOpInfo || - !GetOpInfo(DisInfo, Address, Offset, InstSize, 1, &SymbolicOp)) { - // Clear SymbolicOp.Value from above and also all other fields. - std::memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1)); - - // At this point, GetOpInfo() did not find any relocation information about - // this operand and we are left to use the SymbolLookUp() call back to guess - // if the Value is the address of a symbol. In the case this is a branch - // that always makes sense to guess. But in the case of an immediate it is - // a bit more questionable if it is an address of a symbol or some other - // reference. So if the immediate Value comes from a width of 1 byte, - // InstSize, we will not guess it is an address of a symbol. Because in - // object files assembled starting at address 0 this usually leads to - // incorrect symbolication. - if (!SymbolLookUp || (InstSize == 1 && !IsBranch)) - return false; - - uint64_t ReferenceType; - if (IsBranch) - ReferenceType = LLVMDisassembler_ReferenceType_In_Branch; - else - ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; - const char *ReferenceName; - const char *Name = SymbolLookUp(DisInfo, Value, &ReferenceType, Address, - &ReferenceName); - if (Name) { - SymbolicOp.AddSymbol.Name = Name; - SymbolicOp.AddSymbol.Present = true; - // If Name is a C++ symbol name put the human readable name in a comment. - if(ReferenceType == LLVMDisassembler_ReferenceType_DeMangled_Name) - cStream << ReferenceName; - } - // For branches always create an MCExpr so it gets printed as hex address. - else if (IsBranch) { - SymbolicOp.Value = Value; - } - if(ReferenceType == LLVMDisassembler_ReferenceType_Out_SymbolStub) - cStream << "symbol stub for: " << ReferenceName; - else if(ReferenceType == LLVMDisassembler_ReferenceType_Out_Objc_Message) - cStream << "Objc message: " << ReferenceName; - if (!Name && !IsBranch) - return false; - } - - const MCExpr *Add = nullptr; - if (SymbolicOp.AddSymbol.Present) { - if (SymbolicOp.AddSymbol.Name) { - StringRef Name(SymbolicOp.AddSymbol.Name); - MCSymbol *Sym = Ctx.getOrCreateSymbol(Name); - Add = MCSymbolRefExpr::create(Sym, Ctx); - } else { - Add = MCConstantExpr::create((int)SymbolicOp.AddSymbol.Value, Ctx); - } - } - - const MCExpr *Sub = nullptr; - if (SymbolicOp.SubtractSymbol.Present) { - if (SymbolicOp.SubtractSymbol.Name) { - StringRef Name(SymbolicOp.SubtractSymbol.Name); - MCSymbol *Sym = Ctx.getOrCreateSymbol(Name); - Sub = MCSymbolRefExpr::create(Sym, Ctx); - } else { - Sub = MCConstantExpr::create((int)SymbolicOp.SubtractSymbol.Value, Ctx); - } - } - - const MCExpr *Off = nullptr; - if (SymbolicOp.Value != 0) - Off = MCConstantExpr::create(SymbolicOp.Value, Ctx); - - const MCExpr *Expr; - if (Sub) { - const MCExpr *LHS; - if (Add) - LHS = MCBinaryExpr::createSub(Add, Sub, Ctx); - else - LHS = MCUnaryExpr::createMinus(Sub, Ctx); - if (Off) - Expr = MCBinaryExpr::createAdd(LHS, Off, Ctx); - else - Expr = LHS; - } else if (Add) { - if (Off) - Expr = MCBinaryExpr::createAdd(Add, Off, Ctx); - else - Expr = Add; - } else { - if (Off) - Expr = Off; - else - Expr = MCConstantExpr::create(0, Ctx); - } - - Expr = RelInfo->createExprForCAPIVariantKind(Expr, SymbolicOp.VariantKind); - if (!Expr) - return false; - - MI.addOperand(MCOperand::createExpr(Expr)); - return true; -} - -// This function tries to add a comment as to what is being referenced by a load -// instruction with the base register that is the Pc. These can often be values -// in a literal pool near the Address of the instruction. The Address of the -// instruction and its immediate Value are used as a possible literal pool entry. -// The SymbolLookUp call back will return the name of a symbol referenced by the -// literal pool's entry if the referenced address is that of a symbol. Or it -// will return a pointer to a literal 'C' string if the referenced address of -// the literal pool's entry is an address into a section with C string literals. -// Or if the reference is to an Objective-C data structure it will return a -// specific reference type for it and a string. -void MCExternalSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream, - int64_t Value, - uint64_t Address) { - if (SymbolLookUp) { - uint64_t ReferenceType = LLVMDisassembler_ReferenceType_In_PCrel_Load; - const char *ReferenceName; - (void)SymbolLookUp(DisInfo, Value, &ReferenceType, Address, &ReferenceName); - if(ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr) - cStream << "literal pool symbol address: " << ReferenceName; - else if(ReferenceType == - LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr) { - cStream << "literal pool for: \""; - cStream.write_escaped(ReferenceName); - cStream << "\""; - } - else if(ReferenceType == - LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref) - cStream << "Objc cfstring ref: @\"" << ReferenceName << "\""; - else if(ReferenceType == - LLVMDisassembler_ReferenceType_Out_Objc_Message) - cStream << "Objc message: " << ReferenceName; - else if(ReferenceType == - LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref) - cStream << "Objc message ref: " << ReferenceName; - else if(ReferenceType == - LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref) - cStream << "Objc selector ref: " << ReferenceName; - else if(ReferenceType == - LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref) - cStream << "Objc class ref: " << ReferenceName; - } -} - -namespace llvm { -MCSymbolizer *createMCSymbolizer(const Triple &TT, LLVMOpInfoCallback GetOpInfo, - LLVMSymbolLookupCallback SymbolLookUp, - void *DisInfo, MCContext *Ctx, - std::unique_ptr<MCRelocationInfo> &&RelInfo) { - assert(Ctx && "No MCContext given for symbolic disassembly"); - - return new MCExternalSymbolizer(*Ctx, std::move(RelInfo), GetOpInfo, - SymbolLookUp, DisInfo); -} -} diff --git a/contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp b/contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp deleted file mode 100644 index 64e216e0051d..000000000000 --- a/contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp +++ /dev/null @@ -1,30 +0,0 @@ -//===-- MCRelocationInfo.cpp ----------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCDisassembler/MCRelocationInfo.h" -#include "llvm-c/Disassembler.h" -#include "llvm/Support/TargetRegistry.h" - -using namespace llvm; - -MCRelocationInfo::MCRelocationInfo(MCContext &Ctx) : Ctx(Ctx) {} - -MCRelocationInfo::~MCRelocationInfo() = default; - -const MCExpr * -MCRelocationInfo::createExprForCAPIVariantKind(const MCExpr *SubExpr, - unsigned VariantKind) { - if (VariantKind != LLVMDisassembler_VariantKind_None) - return nullptr; - return SubExpr; -} - -MCRelocationInfo *llvm::createMCRelocationInfo(const Triple &TT, - MCContext &Ctx) { - return new MCRelocationInfo(Ctx); -} diff --git a/contrib/llvm/lib/MC/MCDisassembler/MCSymbolizer.cpp b/contrib/llvm/lib/MC/MCDisassembler/MCSymbolizer.cpp deleted file mode 100644 index 8214a196afb1..000000000000 --- a/contrib/llvm/lib/MC/MCDisassembler/MCSymbolizer.cpp +++ /dev/null @@ -1,13 +0,0 @@ -//===-- llvm/MC/MCSymbolizer.cpp - MCSymbolizer class ---------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCDisassembler/MCSymbolizer.h" - -using namespace llvm; - -MCSymbolizer::~MCSymbolizer() = default; diff --git a/contrib/llvm/lib/MC/MCDwarf.cpp b/contrib/llvm/lib/MC/MCDwarf.cpp deleted file mode 100644 index 8456b3421bcd..000000000000 --- a/contrib/llvm/lib/MC/MCDwarf.cpp +++ /dev/null @@ -1,1950 +0,0 @@ -//===- lib/MC/MCDwarf.cpp - MCDwarf implementation ------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#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 (!HasSplitLineTable) - 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) { - const 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) 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() - ? MCOS->getContext().getCompilationDir() - : 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. - // MCDwarfFiles has an unused element [0] so use size() not size()+1. - // But sometimes MCDwarfFiles is empty, in which case we still emit one file. - MCOS->EmitULEB128IntValue(MCDwarfFiles.empty() ? 1 : MCDwarfFiles.size()); - // 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. - assert((!RootFile.Name.empty() || MCDwarfFiles.size() >= 1) && - "No root file and no .file directives"); - 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); - 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, - Optional<MD5::MD5Result> Checksum, - Optional<StringRef> Source, - uint16_t DwarfVersion, - unsigned FileNumber) { - return Header.tryGetFile(Directory, FileName, Checksum, Source, DwarfVersion, - FileNumber); -} - -bool isRootFile(const MCDwarfFile &RootFile, StringRef &Directory, - StringRef &FileName, Optional<MD5::MD5Result> Checksum) { - if (RootFile.Name.empty() || RootFile.Name != FileName.data()) - return false; - return RootFile.Checksum == Checksum; -} - -Expected<unsigned> -MCDwarfLineTableHeader::tryGetFile(StringRef &Directory, - StringRef &FileName, - Optional<MD5::MD5Result> Checksum, - Optional<StringRef> Source, - uint16_t DwarfVersion, - 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.hasValue()); - HasSource = (Source != None); - } - if (isRootFile(RootFile, Directory, FileName, Checksum) && DwarfVersion >= 5) - return 0; - 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 = llvm::find(MCDwarfDirs, Directory) - MCDwarfDirs.begin(); - 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.hasValue()); - 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; - OS.write_zeros(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 = context.getMCDwarfFiles(); - // MCDwarfFiles might be empty if we have an empty source file. - // If it's not empty, [0] is unused and [1] is the first actual file. - assert(MCDwarfFiles.empty() || MCDwarfFiles.size() >= 2); - const MCDwarfFile &RootFile = - MCDwarfFiles.empty() - ? context.getMCDwarfLineTable(/*CUID=*/0).getRootFile() - : MCDwarfFiles[1]; - MCOS->EmitBytes(RootFile.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) {} - - StringRef PersonalityName() const { - if (!Personality) - return StringRef(); - return Personality->getName(); - } - - bool operator<(const CIEKey &Other) const { - return std::make_tuple(PersonalityName(), PersonalityEncoding, LsdaEncoding, - IsSignalFrame, IsSimple, RAReg) < - std::make_tuple(Other.PersonalityName(), Other.PersonalityEncoding, - Other.LsdaEncoding, Other.IsSignalFrame, - Other.IsSimple, Other.RAReg); - } - - 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(); - // Sort the FDEs by their corresponding CIE before we emit them. - // This isn't technically necessary according to the DWARF standard, - // but the Android libunwindstack rejects eh_frame sections where - // an FDE refers to a CIE other than the closest previous CIE. - std::vector<MCDwarfFrameInfo> FrameArrayX(FrameArray.begin(), FrameArray.end()); - llvm::stable_sort(FrameArrayX, - [](const MCDwarfFrameInfo &X, const MCDwarfFrameInfo &Y) { - return CIEKey(X) < CIEKey(Y); - }); - for (auto I = FrameArrayX.begin(), E = FrameArrayX.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, - uint32_t *Offset, uint32_t *Size) { - // Scale the address delta by the minimum instruction length. - AddrDelta = ScaleAddrDelta(Context, AddrDelta); - - bool WithFixups = false; - if (Offset && Size) - WithFixups = true; - - support::endianness E = - Context.getAsmInfo()->isLittleEndian() ? support::little : support::big; - if (AddrDelta == 0) { - if (WithFixups) { - *Offset = 0; - *Size = 0; - } - } else if (isUIntN(6, AddrDelta)) { - uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta; - if (WithFixups) { - *Offset = OS.tell(); - *Size = 6; - OS << uint8_t(dwarf::DW_CFA_advance_loc); - } else - OS << Opcode; - } else if (isUInt<8>(AddrDelta)) { - OS << uint8_t(dwarf::DW_CFA_advance_loc1); - if (WithFixups) { - *Offset = OS.tell(); - *Size = 8; - OS.write_zeros(1); - } else - OS << uint8_t(AddrDelta); - } else if (isUInt<16>(AddrDelta)) { - OS << uint8_t(dwarf::DW_CFA_advance_loc2); - if (WithFixups) { - *Offset = OS.tell(); - *Size = 16; - OS.write_zeros(2); - } else - support::endian::write<uint16_t>(OS, AddrDelta, E); - } else { - assert(isUInt<32>(AddrDelta)); - OS << uint8_t(dwarf::DW_CFA_advance_loc4); - if (WithFixups) { - *Offset = OS.tell(); - *Size = 32; - OS.write_zeros(4); - } else - support::endian::write<uint32_t>(OS, AddrDelta, E); - } -} diff --git a/contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp b/contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp deleted file mode 100644 index a81eab9ca296..000000000000 --- a/contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp +++ /dev/null @@ -1,31 +0,0 @@ -//===-- MCELFObjectTargetWriter.cpp - ELF Target Writer Subclass ----------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCELFObjectWriter.h" - -using namespace llvm; - -MCELFObjectTargetWriter::MCELFObjectTargetWriter(bool Is64Bit_, uint8_t OSABI_, - uint16_t EMachine_, - bool HasRelocationAddend_, - uint8_t ABIVersion_) - : OSABI(OSABI_), ABIVersion(ABIVersion_), EMachine(EMachine_), - HasRelocationAddend(HasRelocationAddend_), Is64Bit(Is64Bit_) {} - -bool MCELFObjectTargetWriter::needsRelocateWithSymbol(const MCSymbol &Sym, - unsigned Type) const { - return false; -} - -void -MCELFObjectTargetWriter::sortRelocs(const MCAssembler &Asm, - std::vector<ELFRelocationEntry> &Relocs) { -} - -void MCELFObjectTargetWriter::addTargetSectionFlags(MCContext &Ctx, - MCSectionELF &Sec) {} diff --git a/contrib/llvm/lib/MC/MCELFStreamer.cpp b/contrib/llvm/lib/MC/MCELFStreamer.cpp deleted file mode 100644 index 245dd063004f..000000000000 --- a/contrib/llvm/lib/MC/MCELFStreamer.cpp +++ /dev/null @@ -1,708 +0,0 @@ -//===- lib/MC/MCELFStreamer.cpp - ELF Object Output -----------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file assembles .s files and emits ELF .o object files. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCELFStreamer.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCCodeEmitter.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFixup.h" -#include "llvm/MC/MCFragment.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSectionELF.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCSymbolELF.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> -#include <cstdint> - -using namespace llvm; - -MCELFStreamer::MCELFStreamer(MCContext &Context, - std::unique_ptr<MCAsmBackend> TAB, - std::unique_ptr<MCObjectWriter> OW, - std::unique_ptr<MCCodeEmitter> Emitter) - : MCObjectStreamer(Context, std::move(TAB), std::move(OW), - std::move(Emitter)) {} - -bool MCELFStreamer::isBundleLocked() const { - return getCurrentSectionOnly()->isBundleLocked(); -} - -void MCELFStreamer::mergeFragment(MCDataFragment *DF, - MCDataFragment *EF) { - MCAssembler &Assembler = getAssembler(); - - if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) { - uint64_t FSize = EF->getContents().size(); - - if (FSize > Assembler.getBundleAlignSize()) - report_fatal_error("Fragment can't be larger than a bundle size"); - - uint64_t RequiredBundlePadding = computeBundlePadding( - Assembler, EF, DF->getContents().size(), FSize); - - if (RequiredBundlePadding > UINT8_MAX) - report_fatal_error("Padding cannot exceed 255 bytes"); - - if (RequiredBundlePadding > 0) { - SmallString<256> Code; - raw_svector_ostream VecOS(Code); - EF->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding)); - Assembler.writeFragmentPadding(VecOS, *EF, FSize); - - DF->getContents().append(Code.begin(), Code.end()); - } - } - - flushPendingLabels(DF, DF->getContents().size()); - - for (unsigned i = 0, e = EF->getFixups().size(); i != e; ++i) { - EF->getFixups()[i].setOffset(EF->getFixups()[i].getOffset() + - DF->getContents().size()); - DF->getFixups().push_back(EF->getFixups()[i]); - } - if (DF->getSubtargetInfo() == nullptr && EF->getSubtargetInfo()) - DF->setHasInstructions(*EF->getSubtargetInfo()); - DF->getContents().append(EF->getContents().begin(), EF->getContents().end()); -} - -void MCELFStreamer::InitSections(bool NoExecStack) { - MCContext &Ctx = getContext(); - SwitchSection(Ctx.getObjectFileInfo()->getTextSection()); - EmitCodeAlignment(4); - - if (NoExecStack) - SwitchSection(Ctx.getAsmInfo()->getNonexecutableStackSection(Ctx)); -} - -void MCELFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) { - auto *Symbol = cast<MCSymbolELF>(S); - MCObjectStreamer::EmitLabel(Symbol, Loc); - - const MCSectionELF &Section = - static_cast<const MCSectionELF &>(*getCurrentSectionOnly()); - if (Section.getFlags() & ELF::SHF_TLS) - Symbol->setType(ELF::STT_TLS); -} - -void MCELFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc, MCFragment *F) { - auto *Symbol = cast<MCSymbolELF>(S); - MCObjectStreamer::EmitLabel(Symbol, Loc, F); - - const MCSectionELF &Section = - static_cast<const MCSectionELF &>(*getCurrentSectionOnly()); - if (Section.getFlags() & ELF::SHF_TLS) - Symbol->setType(ELF::STT_TLS); -} - -void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { - // Let the target do whatever target specific stuff it needs to do. - getAssembler().getBackend().handleAssemblerFlag(Flag); - // Do any generic stuff we need to do. - switch (Flag) { - case MCAF_SyntaxUnified: return; // no-op here. - case MCAF_Code16: return; // Change parsing mode; no-op here. - case MCAF_Code32: return; // Change parsing mode; no-op here. - case MCAF_Code64: return; // Change parsing mode; no-op here. - case MCAF_SubsectionsViaSymbols: - getAssembler().setSubsectionsViaSymbols(true); - return; - } - - llvm_unreachable("invalid assembler flag!"); -} - -// If bundle alignment is used and there are any instructions in the section, it -// needs to be aligned to at least the bundle size. -static void setSectionAlignmentForBundling(const MCAssembler &Assembler, - MCSection *Section) { - if (Section && Assembler.isBundlingEnabled() && Section->hasInstructions() && - Section->getAlignment() < Assembler.getBundleAlignSize()) - Section->setAlignment(Assembler.getBundleAlignSize()); -} - -void MCELFStreamer::ChangeSection(MCSection *Section, - const MCExpr *Subsection) { - MCSection *CurSection = getCurrentSectionOnly(); - if (CurSection && isBundleLocked()) - report_fatal_error("Unterminated .bundle_lock when changing a section"); - - MCAssembler &Asm = getAssembler(); - // Ensure the previous section gets aligned if necessary. - setSectionAlignmentForBundling(Asm, CurSection); - auto *SectionELF = static_cast<const MCSectionELF *>(Section); - const MCSymbol *Grp = SectionELF->getGroup(); - if (Grp) - Asm.registerSymbol(*Grp); - - changeSectionImpl(Section, Subsection); - Asm.registerSymbol(*Section->getBeginSymbol()); -} - -void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { - getAssembler().registerSymbol(*Symbol); - const MCExpr *Value = MCSymbolRefExpr::create( - Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext()); - Alias->setVariableValue(Value); -} - -// When GNU as encounters more than one .type declaration for an object it seems -// to use a mechanism similar to the one below to decide which type is actually -// used in the object file. The greater of T1 and T2 is selected based on the -// following ordering: -// STT_NOTYPE < STT_OBJECT < STT_FUNC < STT_GNU_IFUNC < STT_TLS < anything else -// If neither T1 < T2 nor T2 < T1 according to this ordering, use T2 (the user -// provided type). -static unsigned CombineSymbolTypes(unsigned T1, unsigned T2) { - for (unsigned Type : {ELF::STT_NOTYPE, ELF::STT_OBJECT, ELF::STT_FUNC, - ELF::STT_GNU_IFUNC, ELF::STT_TLS}) { - if (T1 == Type) - return T2; - if (T2 == Type) - return T1; - } - - return T2; -} - -bool MCELFStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) { - auto *Symbol = cast<MCSymbolELF>(S); - - // Adding a symbol attribute always introduces the symbol, note that an - // important side effect of calling registerSymbol here is to register - // the symbol with the assembler. - getAssembler().registerSymbol(*Symbol); - - // The implementation of symbol attributes is designed to match 'as', but it - // leaves much to desired. It doesn't really make sense to arbitrarily add and - // remove flags, but 'as' allows this (in particular, see .desc). - // - // In the future it might be worth trying to make these operations more well - // defined. - switch (Attribute) { - case MCSA_Cold: - case MCSA_LazyReference: - case MCSA_Reference: - case MCSA_SymbolResolver: - case MCSA_PrivateExtern: - case MCSA_WeakDefinition: - case MCSA_WeakDefAutoPrivate: - case MCSA_Invalid: - case MCSA_IndirectSymbol: - return false; - - case MCSA_NoDeadStrip: - // Ignore for now. - break; - - case MCSA_ELF_TypeGnuUniqueObject: - Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT)); - Symbol->setBinding(ELF::STB_GNU_UNIQUE); - Symbol->setExternal(true); - break; - - case MCSA_Global: - Symbol->setBinding(ELF::STB_GLOBAL); - Symbol->setExternal(true); - break; - - case MCSA_WeakReference: - case MCSA_Weak: - Symbol->setBinding(ELF::STB_WEAK); - Symbol->setExternal(true); - break; - - case MCSA_Local: - Symbol->setBinding(ELF::STB_LOCAL); - Symbol->setExternal(false); - break; - - case MCSA_ELF_TypeFunction: - Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_FUNC)); - break; - - case MCSA_ELF_TypeIndFunction: - Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_GNU_IFUNC)); - break; - - case MCSA_ELF_TypeObject: - Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT)); - break; - - case MCSA_ELF_TypeTLS: - Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_TLS)); - break; - - case MCSA_ELF_TypeCommon: - // TODO: Emit these as a common symbol. - Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT)); - break; - - case MCSA_ELF_TypeNoType: - Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_NOTYPE)); - break; - - case MCSA_Protected: - Symbol->setVisibility(ELF::STV_PROTECTED); - break; - - case MCSA_Hidden: - Symbol->setVisibility(ELF::STV_HIDDEN); - break; - - case MCSA_Internal: - Symbol->setVisibility(ELF::STV_INTERNAL); - break; - - case MCSA_AltEntry: - llvm_unreachable("ELF doesn't support the .alt_entry attribute"); - } - - return true; -} - -void MCELFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size, - unsigned ByteAlignment) { - auto *Symbol = cast<MCSymbolELF>(S); - getAssembler().registerSymbol(*Symbol); - - if (!Symbol->isBindingSet()) { - Symbol->setBinding(ELF::STB_GLOBAL); - Symbol->setExternal(true); - } - - Symbol->setType(ELF::STT_OBJECT); - - if (Symbol->getBinding() == ELF::STB_LOCAL) { - MCSection &Section = *getAssembler().getContext().getELFSection( - ".bss", ELF::SHT_NOBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); - MCSectionSubPair P = getCurrentSection(); - SwitchSection(&Section); - - EmitValueToAlignment(ByteAlignment, 0, 1, 0); - EmitLabel(Symbol); - EmitZeros(Size); - - // Update the maximum alignment of the section if necessary. - if (ByteAlignment > Section.getAlignment()) - Section.setAlignment(ByteAlignment); - - SwitchSection(P.first, P.second); - } else { - if(Symbol->declareCommon(Size, ByteAlignment)) - report_fatal_error("Symbol: " + Symbol->getName() + - " redeclared as different type"); - } - - cast<MCSymbolELF>(Symbol) - ->setSize(MCConstantExpr::create(Size, getContext())); -} - -void MCELFStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) { - cast<MCSymbolELF>(Symbol)->setSize(Value); -} - -void MCELFStreamer::emitELFSymverDirective(StringRef AliasName, - const MCSymbol *Aliasee) { - getAssembler().Symvers.push_back({AliasName, Aliasee}); -} - -void MCELFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size, - unsigned ByteAlignment) { - auto *Symbol = cast<MCSymbolELF>(S); - // FIXME: Should this be caught and done earlier? - getAssembler().registerSymbol(*Symbol); - Symbol->setBinding(ELF::STB_LOCAL); - Symbol->setExternal(false); - EmitCommonSymbol(Symbol, Size, ByteAlignment); -} - -void MCELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, - SMLoc Loc) { - if (isBundleLocked()) - report_fatal_error("Emitting values inside a locked bundle is forbidden"); - fixSymbolsInTLSFixups(Value); - MCObjectStreamer::EmitValueImpl(Value, Size, Loc); -} - -void MCELFStreamer::EmitValueToAlignment(unsigned ByteAlignment, - int64_t Value, - unsigned ValueSize, - unsigned MaxBytesToEmit) { - if (isBundleLocked()) - report_fatal_error("Emitting values inside a locked bundle is forbidden"); - MCObjectStreamer::EmitValueToAlignment(ByteAlignment, Value, - ValueSize, MaxBytesToEmit); -} - -void MCELFStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From, - const MCSymbolRefExpr *To, - uint64_t Count) { - getAssembler().CGProfile.push_back({From, To, Count}); -} - -void MCELFStreamer::EmitIdent(StringRef IdentString) { - MCSection *Comment = getAssembler().getContext().getELFSection( - ".comment", ELF::SHT_PROGBITS, ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, ""); - PushSection(); - SwitchSection(Comment); - if (!SeenIdent) { - EmitIntValue(0, 1); - SeenIdent = true; - } - EmitBytes(IdentString); - EmitIntValue(0, 1); - PopSection(); -} - -void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { - switch (expr->getKind()) { - case MCExpr::Target: - cast<MCTargetExpr>(expr)->fixELFSymbolsInTLSFixups(getAssembler()); - break; - case MCExpr::Constant: - break; - - case MCExpr::Binary: { - const MCBinaryExpr *be = cast<MCBinaryExpr>(expr); - fixSymbolsInTLSFixups(be->getLHS()); - fixSymbolsInTLSFixups(be->getRHS()); - break; - } - - case MCExpr::SymbolRef: { - const MCSymbolRefExpr &symRef = *cast<MCSymbolRefExpr>(expr); - switch (symRef.getKind()) { - default: - return; - case MCSymbolRefExpr::VK_GOTTPOFF: - case MCSymbolRefExpr::VK_INDNTPOFF: - case MCSymbolRefExpr::VK_NTPOFF: - case MCSymbolRefExpr::VK_GOTNTPOFF: - case MCSymbolRefExpr::VK_TLSCALL: - case MCSymbolRefExpr::VK_TLSDESC: - case MCSymbolRefExpr::VK_TLSGD: - case MCSymbolRefExpr::VK_TLSLD: - case MCSymbolRefExpr::VK_TLSLDM: - case MCSymbolRefExpr::VK_TPOFF: - case MCSymbolRefExpr::VK_TPREL: - case MCSymbolRefExpr::VK_DTPOFF: - case MCSymbolRefExpr::VK_DTPREL: - case MCSymbolRefExpr::VK_PPC_DTPMOD: - case MCSymbolRefExpr::VK_PPC_TPREL_LO: - case MCSymbolRefExpr::VK_PPC_TPREL_HI: - case MCSymbolRefExpr::VK_PPC_TPREL_HA: - case MCSymbolRefExpr::VK_PPC_TPREL_HIGH: - case MCSymbolRefExpr::VK_PPC_TPREL_HIGHA: - case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER: - case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA: - case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST: - case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA: - case MCSymbolRefExpr::VK_PPC_DTPREL_LO: - case MCSymbolRefExpr::VK_PPC_DTPREL_HI: - case MCSymbolRefExpr::VK_PPC_DTPREL_HA: - case MCSymbolRefExpr::VK_PPC_DTPREL_HIGH: - case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHA: - case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER: - case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA: - case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST: - case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA: - case MCSymbolRefExpr::VK_PPC_GOT_TPREL: - case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO: - case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI: - case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA: - case MCSymbolRefExpr::VK_PPC_GOT_DTPREL: - case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO: - case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI: - case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA: - case MCSymbolRefExpr::VK_PPC_TLS: - case MCSymbolRefExpr::VK_PPC_GOT_TLSGD: - case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO: - case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI: - case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA: - case MCSymbolRefExpr::VK_PPC_TLSGD: - case MCSymbolRefExpr::VK_PPC_GOT_TLSLD: - case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO: - case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI: - case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA: - case MCSymbolRefExpr::VK_PPC_TLSLD: - break; - } - getAssembler().registerSymbol(symRef.getSymbol()); - cast<MCSymbolELF>(symRef.getSymbol()).setType(ELF::STT_TLS); - break; - } - - case MCExpr::Unary: - fixSymbolsInTLSFixups(cast<MCUnaryExpr>(expr)->getSubExpr()); - break; - } -} - -void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE) { - const MCSymbol *S = &SRE->getSymbol(); - if (S->isTemporary()) { - if (!S->isInSection()) { - getContext().reportError( - SRE->getLoc(), Twine("Reference to undefined temporary symbol ") + - "`" + S->getName() + "`"); - return; - } - S = S->getSection().getBeginSymbol(); - S->setUsedInReloc(); - SRE = - MCSymbolRefExpr::create(S, SRE->getKind(), getContext(), SRE->getLoc()); - return; - } - // Not a temporary, referece it as a weak undefined. - bool Created; - getAssembler().registerSymbol(*S, &Created); - if (Created) { - cast<MCSymbolELF>(S)->setBinding(ELF::STB_WEAK); - cast<MCSymbolELF>(S)->setExternal(true); - } -} - -void MCELFStreamer::finalizeCGProfile() { - for (MCAssembler::CGProfileEntry &E : getAssembler().CGProfile) { - finalizeCGProfileEntry(E.From); - finalizeCGProfileEntry(E.To); - } -} - -void MCELFStreamer::EmitInstToFragment(const MCInst &Inst, - const MCSubtargetInfo &STI) { - this->MCObjectStreamer::EmitInstToFragment(Inst, STI); - MCRelaxableFragment &F = *cast<MCRelaxableFragment>(getCurrentFragment()); - - for (unsigned i = 0, e = F.getFixups().size(); i != e; ++i) - fixSymbolsInTLSFixups(F.getFixups()[i].getValue()); -} - -// A fragment can only have one Subtarget, and when bundling is enabled we -// sometimes need to use the same fragment. We give an error if there -// are conflicting Subtargets. -static void CheckBundleSubtargets(const MCSubtargetInfo *OldSTI, - const MCSubtargetInfo *NewSTI) { - if (OldSTI && NewSTI && OldSTI != NewSTI) - report_fatal_error("A Bundle can only have one Subtarget."); -} - -void MCELFStreamer::EmitInstToData(const MCInst &Inst, - const MCSubtargetInfo &STI) { - MCAssembler &Assembler = getAssembler(); - SmallVector<MCFixup, 4> Fixups; - SmallString<256> Code; - raw_svector_ostream VecOS(Code); - Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); - - for (unsigned i = 0, e = Fixups.size(); i != e; ++i) - fixSymbolsInTLSFixups(Fixups[i].getValue()); - - // There are several possibilities here: - // - // If bundling is disabled, append the encoded instruction to the current data - // fragment (or create a new such fragment if the current fragment is not a - // data fragment, or the Subtarget has changed). - // - // If bundling is enabled: - // - If we're not in a bundle-locked group, emit the instruction into a - // fragment of its own. If there are no fixups registered for the - // instruction, emit a MCCompactEncodedInstFragment. Otherwise, emit a - // MCDataFragment. - // - If we're in a bundle-locked group, append the instruction to the current - // data fragment because we want all the instructions in a group to get into - // the same fragment. Be careful not to do that for the first instruction in - // the group, though. - MCDataFragment *DF; - - if (Assembler.isBundlingEnabled()) { - MCSection &Sec = *getCurrentSectionOnly(); - if (Assembler.getRelaxAll() && isBundleLocked()) { - // If the -mc-relax-all flag is used and we are bundle-locked, we re-use - // the current bundle group. - DF = BundleGroups.back(); - CheckBundleSubtargets(DF->getSubtargetInfo(), &STI); - } - else if (Assembler.getRelaxAll() && !isBundleLocked()) - // When not in a bundle-locked group and the -mc-relax-all flag is used, - // we create a new temporary fragment which will be later merged into - // the current fragment. - DF = new MCDataFragment(); - else if (isBundleLocked() && !Sec.isBundleGroupBeforeFirstInst()) { - // If we are bundle-locked, we re-use the current fragment. - // The bundle-locking directive ensures this is a new data fragment. - DF = cast<MCDataFragment>(getCurrentFragment()); - CheckBundleSubtargets(DF->getSubtargetInfo(), &STI); - } - else if (!isBundleLocked() && Fixups.size() == 0) { - // Optimize memory usage by emitting the instruction to a - // MCCompactEncodedInstFragment when not in a bundle-locked group and - // there are no fixups registered. - MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment(); - insert(CEIF); - CEIF->getContents().append(Code.begin(), Code.end()); - CEIF->setHasInstructions(STI); - return; - } else { - DF = new MCDataFragment(); - insert(DF); - } - if (Sec.getBundleLockState() == MCSection::BundleLockedAlignToEnd) { - // If this fragment is for a group marked "align_to_end", set a flag - // in the fragment. This can happen after the fragment has already been - // created if there are nested bundle_align groups and an inner one - // is the one marked align_to_end. - DF->setAlignToBundleEnd(true); - } - - // We're now emitting an instruction in a bundle group, so this flag has - // to be turned off. - Sec.setBundleGroupBeforeFirstInst(false); - } else { - DF = getOrCreateDataFragment(&STI); - } - - // Add the fixups and data. - for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { - Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); - DF->getFixups().push_back(Fixups[i]); - } - DF->setHasInstructions(STI); - DF->getContents().append(Code.begin(), Code.end()); - - if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) { - if (!isBundleLocked()) { - mergeFragment(getOrCreateDataFragment(&STI), DF); - delete DF; - } - } -} - -void MCELFStreamer::EmitBundleAlignMode(unsigned AlignPow2) { - assert(AlignPow2 <= 30 && "Invalid bundle alignment"); - MCAssembler &Assembler = getAssembler(); - if (AlignPow2 > 0 && (Assembler.getBundleAlignSize() == 0 || - Assembler.getBundleAlignSize() == 1U << AlignPow2)) - Assembler.setBundleAlignSize(1U << AlignPow2); - else - report_fatal_error(".bundle_align_mode cannot be changed once set"); -} - -void MCELFStreamer::EmitBundleLock(bool AlignToEnd) { - MCSection &Sec = *getCurrentSectionOnly(); - - // Sanity checks - // - if (!getAssembler().isBundlingEnabled()) - report_fatal_error(".bundle_lock forbidden when bundling is disabled"); - - if (!isBundleLocked()) - Sec.setBundleGroupBeforeFirstInst(true); - - if (getAssembler().getRelaxAll() && !isBundleLocked()) { - // TODO: drop the lock state and set directly in the fragment - MCDataFragment *DF = new MCDataFragment(); - BundleGroups.push_back(DF); - } - - Sec.setBundleLockState(AlignToEnd ? MCSection::BundleLockedAlignToEnd - : MCSection::BundleLocked); -} - -void MCELFStreamer::EmitBundleUnlock() { - MCSection &Sec = *getCurrentSectionOnly(); - - // Sanity checks - if (!getAssembler().isBundlingEnabled()) - report_fatal_error(".bundle_unlock forbidden when bundling is disabled"); - else if (!isBundleLocked()) - report_fatal_error(".bundle_unlock without matching lock"); - else if (Sec.isBundleGroupBeforeFirstInst()) - report_fatal_error("Empty bundle-locked group is forbidden"); - - // When the -mc-relax-all flag is used, we emit instructions to fragments - // stored on a stack. When the bundle unlock is emitted, we pop a fragment - // from the stack a merge it to the one below. - if (getAssembler().getRelaxAll()) { - assert(!BundleGroups.empty() && "There are no bundle groups"); - MCDataFragment *DF = BundleGroups.back(); - - // FIXME: Use BundleGroups to track the lock state instead. - Sec.setBundleLockState(MCSection::NotBundleLocked); - - // FIXME: Use more separate fragments for nested groups. - if (!isBundleLocked()) { - mergeFragment(getOrCreateDataFragment(DF->getSubtargetInfo()), DF); - BundleGroups.pop_back(); - delete DF; - } - - if (Sec.getBundleLockState() != MCSection::BundleLockedAlignToEnd) - getOrCreateDataFragment()->setAlignToBundleEnd(false); - } else - Sec.setBundleLockState(MCSection::NotBundleLocked); -} - -void MCELFStreamer::FinishImpl() { - // Ensure the last section gets aligned if necessary. - MCSection *CurSection = getCurrentSectionOnly(); - setSectionAlignmentForBundling(getAssembler(), CurSection); - - finalizeCGProfile(); - EmitFrames(nullptr); - - this->MCObjectStreamer::FinishImpl(); -} - -void MCELFStreamer::EmitThumbFunc(MCSymbol *Func) { - llvm_unreachable("Generic ELF doesn't support this directive"); -} - -void MCELFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { - llvm_unreachable("ELF doesn't support this directive"); -} - -void MCELFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment, - SMLoc Loc) { - llvm_unreachable("ELF doesn't support this directive"); -} - -void MCELFStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment) { - llvm_unreachable("ELF doesn't support this directive"); -} - -MCStreamer *llvm::createELFStreamer(MCContext &Context, - std::unique_ptr<MCAsmBackend> &&MAB, - std::unique_ptr<MCObjectWriter> &&OW, - std::unique_ptr<MCCodeEmitter> &&CE, - bool RelaxAll) { - MCELFStreamer *S = - new MCELFStreamer(Context, std::move(MAB), std::move(OW), std::move(CE)); - if (RelaxAll) - S->getAssembler().setRelaxAll(true); - return S; -} diff --git a/contrib/llvm/lib/MC/MCExpr.cpp b/contrib/llvm/lib/MC/MCExpr.cpp deleted file mode 100644 index 543b0661905c..000000000000 --- a/contrib/llvm/lib/MC/MCExpr.cpp +++ /dev/null @@ -1,931 +0,0 @@ -//===- MCExpr.cpp - Assembly Level Expression Implementation --------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCExpr.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/Config/llvm-config.h" -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCAsmLayout.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCValue.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> -#include <cstdint> - -using namespace llvm; - -#define DEBUG_TYPE "mcexpr" - -namespace { -namespace stats { - -STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations"); - -} // end namespace stats -} // end anonymous namespace - -void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const { - switch (getKind()) { - case MCExpr::Target: - return cast<MCTargetExpr>(this)->printImpl(OS, MAI); - case MCExpr::Constant: { - auto Value = cast<MCConstantExpr>(*this).getValue(); - auto PrintInHex = cast<MCConstantExpr>(*this).useHexFormat(); - if (PrintInHex) - OS << "0x" << Twine::utohexstr(Value); - else - OS << Value; - return; - } - case MCExpr::SymbolRef: { - const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this); - const MCSymbol &Sym = SRE.getSymbol(); - // Parenthesize names that start with $ so that they don't look like - // absolute names. - bool UseParens = - !InParens && !Sym.getName().empty() && Sym.getName()[0] == '$'; - if (UseParens) { - OS << '('; - Sym.print(OS, MAI); - OS << ')'; - } else - Sym.print(OS, MAI); - - if (SRE.getKind() != MCSymbolRefExpr::VK_None) - SRE.printVariantKind(OS); - - return; - } - - case MCExpr::Unary: { - const MCUnaryExpr &UE = cast<MCUnaryExpr>(*this); - switch (UE.getOpcode()) { - case MCUnaryExpr::LNot: OS << '!'; break; - case MCUnaryExpr::Minus: OS << '-'; break; - case MCUnaryExpr::Not: OS << '~'; break; - case MCUnaryExpr::Plus: OS << '+'; break; - } - bool Binary = UE.getSubExpr()->getKind() == MCExpr::Binary; - if (Binary) OS << "("; - UE.getSubExpr()->print(OS, MAI); - if (Binary) OS << ")"; - return; - } - - case MCExpr::Binary: { - const MCBinaryExpr &BE = cast<MCBinaryExpr>(*this); - - // Only print parens around the LHS if it is non-trivial. - if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) { - BE.getLHS()->print(OS, MAI); - } else { - OS << '('; - BE.getLHS()->print(OS, MAI); - OS << ')'; - } - - switch (BE.getOpcode()) { - case MCBinaryExpr::Add: - // Print "X-42" instead of "X+-42". - if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(BE.getRHS())) { - if (RHSC->getValue() < 0) { - OS << RHSC->getValue(); - return; - } - } - - OS << '+'; - break; - case MCBinaryExpr::AShr: OS << ">>"; break; - case MCBinaryExpr::And: OS << '&'; break; - case MCBinaryExpr::Div: OS << '/'; break; - case MCBinaryExpr::EQ: OS << "=="; break; - case MCBinaryExpr::GT: OS << '>'; break; - case MCBinaryExpr::GTE: OS << ">="; break; - case MCBinaryExpr::LAnd: OS << "&&"; break; - case MCBinaryExpr::LOr: OS << "||"; break; - case MCBinaryExpr::LShr: OS << ">>"; break; - case MCBinaryExpr::LT: OS << '<'; break; - case MCBinaryExpr::LTE: OS << "<="; break; - case MCBinaryExpr::Mod: OS << '%'; break; - case MCBinaryExpr::Mul: OS << '*'; break; - case MCBinaryExpr::NE: OS << "!="; break; - case MCBinaryExpr::Or: OS << '|'; break; - case MCBinaryExpr::Shl: OS << "<<"; break; - case MCBinaryExpr::Sub: OS << '-'; break; - case MCBinaryExpr::Xor: OS << '^'; break; - } - - // Only print parens around the LHS if it is non-trivial. - if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) { - BE.getRHS()->print(OS, MAI); - } else { - OS << '('; - BE.getRHS()->print(OS, MAI); - OS << ')'; - } - return; - } - } - - llvm_unreachable("Invalid expression kind!"); -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -LLVM_DUMP_METHOD void MCExpr::dump() const { - dbgs() << *this; - dbgs() << '\n'; -} -#endif - -/* *** */ - -const MCBinaryExpr *MCBinaryExpr::create(Opcode Opc, const MCExpr *LHS, - const MCExpr *RHS, MCContext &Ctx, - SMLoc Loc) { - return new (Ctx) MCBinaryExpr(Opc, LHS, RHS, Loc); -} - -const MCUnaryExpr *MCUnaryExpr::create(Opcode Opc, const MCExpr *Expr, - MCContext &Ctx, SMLoc Loc) { - return new (Ctx) MCUnaryExpr(Opc, Expr, Loc); -} - -const MCConstantExpr *MCConstantExpr::create(int64_t Value, MCContext &Ctx, - bool PrintInHex) { - return new (Ctx) MCConstantExpr(Value, PrintInHex); -} - -/* *** */ - -MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, - const MCAsmInfo *MAI, SMLoc Loc) - : MCExpr(MCExpr::SymbolRef, Loc), Kind(Kind), - UseParensForSymbolVariant(MAI->useParensForSymbolVariant()), - HasSubsectionsViaSymbols(MAI->hasSubsectionsViaSymbols()), - Symbol(Symbol) { - assert(Symbol); -} - -const MCSymbolRefExpr *MCSymbolRefExpr::create(const MCSymbol *Sym, - VariantKind Kind, - MCContext &Ctx, SMLoc Loc) { - return new (Ctx) MCSymbolRefExpr(Sym, Kind, Ctx.getAsmInfo(), Loc); -} - -const MCSymbolRefExpr *MCSymbolRefExpr::create(StringRef Name, VariantKind Kind, - MCContext &Ctx) { - return create(Ctx.getOrCreateSymbol(Name), Kind, Ctx); -} - -StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { - switch (Kind) { - case VK_Invalid: return "<<invalid>>"; - case VK_None: return "<<none>>"; - - case VK_DTPOFF: return "DTPOFF"; - case VK_DTPREL: return "DTPREL"; - case VK_GOT: return "GOT"; - case VK_GOTOFF: return "GOTOFF"; - case VK_GOTREL: return "GOTREL"; - case VK_GOTPCREL: return "GOTPCREL"; - case VK_GOTTPOFF: return "GOTTPOFF"; - case VK_INDNTPOFF: return "INDNTPOFF"; - case VK_NTPOFF: return "NTPOFF"; - case VK_GOTNTPOFF: return "GOTNTPOFF"; - case VK_PLT: return "PLT"; - case VK_TLSGD: return "TLSGD"; - case VK_TLSLD: return "TLSLD"; - case VK_TLSLDM: return "TLSLDM"; - case VK_TPOFF: return "TPOFF"; - case VK_TPREL: return "TPREL"; - case VK_TLSCALL: return "tlscall"; - case VK_TLSDESC: return "tlsdesc"; - case VK_TLVP: return "TLVP"; - case VK_TLVPPAGE: return "TLVPPAGE"; - case VK_TLVPPAGEOFF: return "TLVPPAGEOFF"; - case VK_PAGE: return "PAGE"; - case VK_PAGEOFF: return "PAGEOFF"; - case VK_GOTPAGE: return "GOTPAGE"; - case VK_GOTPAGEOFF: return "GOTPAGEOFF"; - case VK_SECREL: return "SECREL32"; - case VK_SIZE: return "SIZE"; - case VK_WEAKREF: return "WEAKREF"; - case VK_X86_ABS8: return "ABS8"; - case VK_ARM_NONE: return "none"; - case VK_ARM_GOT_PREL: return "GOT_PREL"; - case VK_ARM_TARGET1: return "target1"; - case VK_ARM_TARGET2: return "target2"; - case VK_ARM_PREL31: return "prel31"; - case VK_ARM_SBREL: return "sbrel"; - case VK_ARM_TLSLDO: return "tlsldo"; - case VK_ARM_TLSDESCSEQ: return "tlsdescseq"; - case VK_AVR_NONE: return "none"; - case VK_AVR_LO8: return "lo8"; - case VK_AVR_HI8: return "hi8"; - case VK_AVR_HLO8: return "hlo8"; - case VK_AVR_DIFF8: return "diff8"; - case VK_AVR_DIFF16: return "diff16"; - case VK_AVR_DIFF32: return "diff32"; - case VK_PPC_LO: return "l"; - case VK_PPC_HI: return "h"; - case VK_PPC_HA: return "ha"; - case VK_PPC_HIGH: return "high"; - case VK_PPC_HIGHA: return "higha"; - case VK_PPC_HIGHER: return "higher"; - case VK_PPC_HIGHERA: return "highera"; - case VK_PPC_HIGHEST: return "highest"; - case VK_PPC_HIGHESTA: return "highesta"; - case VK_PPC_GOT_LO: return "got@l"; - case VK_PPC_GOT_HI: return "got@h"; - case VK_PPC_GOT_HA: return "got@ha"; - case VK_PPC_TOCBASE: return "tocbase"; - case VK_PPC_TOC: return "toc"; - case VK_PPC_TOC_LO: return "toc@l"; - case VK_PPC_TOC_HI: return "toc@h"; - case VK_PPC_TOC_HA: return "toc@ha"; - case VK_PPC_DTPMOD: return "dtpmod"; - case VK_PPC_TPREL_LO: return "tprel@l"; - case VK_PPC_TPREL_HI: return "tprel@h"; - case VK_PPC_TPREL_HA: return "tprel@ha"; - case VK_PPC_TPREL_HIGH: return "tprel@high"; - case VK_PPC_TPREL_HIGHA: return "tprel@higha"; - case VK_PPC_TPREL_HIGHER: return "tprel@higher"; - case VK_PPC_TPREL_HIGHERA: return "tprel@highera"; - case VK_PPC_TPREL_HIGHEST: return "tprel@highest"; - case VK_PPC_TPREL_HIGHESTA: return "tprel@highesta"; - case VK_PPC_DTPREL_LO: return "dtprel@l"; - case VK_PPC_DTPREL_HI: return "dtprel@h"; - case VK_PPC_DTPREL_HA: return "dtprel@ha"; - case VK_PPC_DTPREL_HIGH: return "dtprel@high"; - case VK_PPC_DTPREL_HIGHA: return "dtprel@higha"; - case VK_PPC_DTPREL_HIGHER: return "dtprel@higher"; - case VK_PPC_DTPREL_HIGHERA: return "dtprel@highera"; - case VK_PPC_DTPREL_HIGHEST: return "dtprel@highest"; - case VK_PPC_DTPREL_HIGHESTA: return "dtprel@highesta"; - case VK_PPC_GOT_TPREL: return "got@tprel"; - case VK_PPC_GOT_TPREL_LO: return "got@tprel@l"; - case VK_PPC_GOT_TPREL_HI: return "got@tprel@h"; - case VK_PPC_GOT_TPREL_HA: return "got@tprel@ha"; - case VK_PPC_GOT_DTPREL: return "got@dtprel"; - case VK_PPC_GOT_DTPREL_LO: return "got@dtprel@l"; - case VK_PPC_GOT_DTPREL_HI: return "got@dtprel@h"; - case VK_PPC_GOT_DTPREL_HA: return "got@dtprel@ha"; - case VK_PPC_TLS: return "tls"; - case VK_PPC_GOT_TLSGD: return "got@tlsgd"; - case VK_PPC_GOT_TLSGD_LO: return "got@tlsgd@l"; - case VK_PPC_GOT_TLSGD_HI: return "got@tlsgd@h"; - case VK_PPC_GOT_TLSGD_HA: return "got@tlsgd@ha"; - case VK_PPC_TLSGD: return "tlsgd"; - case VK_PPC_GOT_TLSLD: return "got@tlsld"; - case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l"; - case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h"; - case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha"; - case VK_PPC_TLSLD: return "tlsld"; - case VK_PPC_LOCAL: return "local"; - case VK_COFF_IMGREL32: return "IMGREL"; - case VK_Hexagon_PCREL: return "PCREL"; - case VK_Hexagon_LO16: return "LO16"; - case VK_Hexagon_HI16: return "HI16"; - case VK_Hexagon_GPREL: return "GPREL"; - case VK_Hexagon_GD_GOT: return "GDGOT"; - case VK_Hexagon_LD_GOT: return "LDGOT"; - case VK_Hexagon_GD_PLT: return "GDPLT"; - case VK_Hexagon_LD_PLT: return "LDPLT"; - case VK_Hexagon_IE: return "IE"; - case VK_Hexagon_IE_GOT: return "IEGOT"; - case VK_WASM_TYPEINDEX: return "TYPEINDEX"; - case VK_WASM_MBREL: return "MBREL"; - case VK_WASM_TBREL: return "TBREL"; - case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo"; - case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi"; - case VK_AMDGPU_REL32_LO: return "rel32@lo"; - case VK_AMDGPU_REL32_HI: return "rel32@hi"; - case VK_AMDGPU_REL64: return "rel64"; - case VK_AMDGPU_ABS32_LO: return "abs32@lo"; - case VK_AMDGPU_ABS32_HI: return "abs32@hi"; - } - llvm_unreachable("Invalid variant kind"); -} - -MCSymbolRefExpr::VariantKind -MCSymbolRefExpr::getVariantKindForName(StringRef Name) { - return StringSwitch<VariantKind>(Name.lower()) - .Case("dtprel", VK_DTPREL) - .Case("dtpoff", VK_DTPOFF) - .Case("got", VK_GOT) - .Case("gotoff", VK_GOTOFF) - .Case("gotrel", VK_GOTREL) - .Case("gotpcrel", VK_GOTPCREL) - .Case("gottpoff", VK_GOTTPOFF) - .Case("indntpoff", VK_INDNTPOFF) - .Case("ntpoff", VK_NTPOFF) - .Case("gotntpoff", VK_GOTNTPOFF) - .Case("plt", VK_PLT) - .Case("tlscall", VK_TLSCALL) - .Case("tlsdesc", VK_TLSDESC) - .Case("tlsgd", VK_TLSGD) - .Case("tlsld", VK_TLSLD) - .Case("tlsldm", VK_TLSLDM) - .Case("tpoff", VK_TPOFF) - .Case("tprel", VK_TPREL) - .Case("tlvp", VK_TLVP) - .Case("tlvppage", VK_TLVPPAGE) - .Case("tlvppageoff", VK_TLVPPAGEOFF) - .Case("page", VK_PAGE) - .Case("pageoff", VK_PAGEOFF) - .Case("gotpage", VK_GOTPAGE) - .Case("gotpageoff", VK_GOTPAGEOFF) - .Case("imgrel", VK_COFF_IMGREL32) - .Case("secrel32", VK_SECREL) - .Case("size", VK_SIZE) - .Case("abs8", VK_X86_ABS8) - .Case("l", VK_PPC_LO) - .Case("h", VK_PPC_HI) - .Case("ha", VK_PPC_HA) - .Case("high", VK_PPC_HIGH) - .Case("higha", VK_PPC_HIGHA) - .Case("higher", VK_PPC_HIGHER) - .Case("highera", VK_PPC_HIGHERA) - .Case("highest", VK_PPC_HIGHEST) - .Case("highesta", VK_PPC_HIGHESTA) - .Case("got@l", VK_PPC_GOT_LO) - .Case("got@h", VK_PPC_GOT_HI) - .Case("got@ha", VK_PPC_GOT_HA) - .Case("local", VK_PPC_LOCAL) - .Case("tocbase", VK_PPC_TOCBASE) - .Case("toc", VK_PPC_TOC) - .Case("toc@l", VK_PPC_TOC_LO) - .Case("toc@h", VK_PPC_TOC_HI) - .Case("toc@ha", VK_PPC_TOC_HA) - .Case("tls", VK_PPC_TLS) - .Case("dtpmod", VK_PPC_DTPMOD) - .Case("tprel@l", VK_PPC_TPREL_LO) - .Case("tprel@h", VK_PPC_TPREL_HI) - .Case("tprel@ha", VK_PPC_TPREL_HA) - .Case("tprel@high", VK_PPC_TPREL_HIGH) - .Case("tprel@higha", VK_PPC_TPREL_HIGHA) - .Case("tprel@higher", VK_PPC_TPREL_HIGHER) - .Case("tprel@highera", VK_PPC_TPREL_HIGHERA) - .Case("tprel@highest", VK_PPC_TPREL_HIGHEST) - .Case("tprel@highesta", VK_PPC_TPREL_HIGHESTA) - .Case("dtprel@l", VK_PPC_DTPREL_LO) - .Case("dtprel@h", VK_PPC_DTPREL_HI) - .Case("dtprel@ha", VK_PPC_DTPREL_HA) - .Case("dtprel@high", VK_PPC_DTPREL_HIGH) - .Case("dtprel@higha", VK_PPC_DTPREL_HIGHA) - .Case("dtprel@higher", VK_PPC_DTPREL_HIGHER) - .Case("dtprel@highera", VK_PPC_DTPREL_HIGHERA) - .Case("dtprel@highest", VK_PPC_DTPREL_HIGHEST) - .Case("dtprel@highesta", VK_PPC_DTPREL_HIGHESTA) - .Case("got@tprel", VK_PPC_GOT_TPREL) - .Case("got@tprel@l", VK_PPC_GOT_TPREL_LO) - .Case("got@tprel@h", VK_PPC_GOT_TPREL_HI) - .Case("got@tprel@ha", VK_PPC_GOT_TPREL_HA) - .Case("got@dtprel", VK_PPC_GOT_DTPREL) - .Case("got@dtprel@l", VK_PPC_GOT_DTPREL_LO) - .Case("got@dtprel@h", VK_PPC_GOT_DTPREL_HI) - .Case("got@dtprel@ha", VK_PPC_GOT_DTPREL_HA) - .Case("got@tlsgd", VK_PPC_GOT_TLSGD) - .Case("got@tlsgd@l", VK_PPC_GOT_TLSGD_LO) - .Case("got@tlsgd@h", VK_PPC_GOT_TLSGD_HI) - .Case("got@tlsgd@ha", VK_PPC_GOT_TLSGD_HA) - .Case("got@tlsld", VK_PPC_GOT_TLSLD) - .Case("got@tlsld@l", VK_PPC_GOT_TLSLD_LO) - .Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI) - .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA) - .Case("gdgot", VK_Hexagon_GD_GOT) - .Case("gdplt", VK_Hexagon_GD_PLT) - .Case("iegot", VK_Hexagon_IE_GOT) - .Case("ie", VK_Hexagon_IE) - .Case("ldgot", VK_Hexagon_LD_GOT) - .Case("ldplt", VK_Hexagon_LD_PLT) - .Case("pcrel", VK_Hexagon_PCREL) - .Case("none", VK_ARM_NONE) - .Case("got_prel", VK_ARM_GOT_PREL) - .Case("target1", VK_ARM_TARGET1) - .Case("target2", VK_ARM_TARGET2) - .Case("prel31", VK_ARM_PREL31) - .Case("sbrel", VK_ARM_SBREL) - .Case("tlsldo", VK_ARM_TLSLDO) - .Case("lo8", VK_AVR_LO8) - .Case("hi8", VK_AVR_HI8) - .Case("hlo8", VK_AVR_HLO8) - .Case("typeindex", VK_WASM_TYPEINDEX) - .Case("tbrel", VK_WASM_TBREL) - .Case("mbrel", VK_WASM_MBREL) - .Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO) - .Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI) - .Case("rel32@lo", VK_AMDGPU_REL32_LO) - .Case("rel32@hi", VK_AMDGPU_REL32_HI) - .Case("rel64", VK_AMDGPU_REL64) - .Case("abs32@lo", VK_AMDGPU_ABS32_LO) - .Case("abs32@hi", VK_AMDGPU_ABS32_HI) - .Default(VK_Invalid); -} - -void MCSymbolRefExpr::printVariantKind(raw_ostream &OS) const { - if (UseParensForSymbolVariant) - OS << '(' << MCSymbolRefExpr::getVariantKindName(getKind()) << ')'; - else - OS << '@' << MCSymbolRefExpr::getVariantKindName(getKind()); -} - -/* *** */ - -void MCTargetExpr::anchor() {} - -/* *** */ - -bool MCExpr::evaluateAsAbsolute(int64_t &Res) const { - return evaluateAsAbsolute(Res, nullptr, nullptr, nullptr); -} - -bool MCExpr::evaluateAsAbsolute(int64_t &Res, - const MCAsmLayout &Layout) const { - return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr); -} - -bool MCExpr::evaluateAsAbsolute(int64_t &Res, - const MCAsmLayout &Layout, - const SectionAddrMap &Addrs) const { - return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs); -} - -bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const { - return evaluateAsAbsolute(Res, &Asm, nullptr, nullptr); -} - -bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const { - return evaluateAsAbsolute(Res, Asm, nullptr, nullptr); -} - -bool MCExpr::evaluateKnownAbsolute(int64_t &Res, - const MCAsmLayout &Layout) const { - return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr, - true); -} - -bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, - const MCAsmLayout *Layout, - const SectionAddrMap *Addrs) const { - // FIXME: The use if InSet = Addrs is a hack. Setting InSet causes us - // absolutize differences across sections and that is what the MachO writer - // uses Addrs for. - return evaluateAsAbsolute(Res, Asm, Layout, Addrs, Addrs); -} - -bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, - const MCAsmLayout *Layout, - const SectionAddrMap *Addrs, bool InSet) const { - MCValue Value; - - // Fast path constants. - if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(this)) { - Res = CE->getValue(); - return true; - } - - bool IsRelocatable = - evaluateAsRelocatableImpl(Value, Asm, Layout, nullptr, Addrs, InSet); - - // Record the current value. - Res = Value.getConstant(); - - return IsRelocatable && Value.isAbsolute(); -} - -/// Helper method for \see EvaluateSymbolAdd(). -static void AttemptToFoldSymbolOffsetDifference( - const MCAssembler *Asm, const MCAsmLayout *Layout, - const SectionAddrMap *Addrs, bool InSet, const MCSymbolRefExpr *&A, - const MCSymbolRefExpr *&B, int64_t &Addend) { - if (!A || !B) - return; - - const MCSymbol &SA = A->getSymbol(); - const MCSymbol &SB = B->getSymbol(); - - if (SA.isUndefined() || SB.isUndefined()) - return; - - if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet)) - return; - - if (SA.getFragment() == SB.getFragment() && !SA.isVariable() && - !SA.isUnset() && !SB.isVariable() && !SB.isUnset()) { - Addend += (SA.getOffset() - SB.getOffset()); - - // Pointers to Thumb symbols need to have their low-bit set to allow - // for interworking. - if (Asm->isThumbFunc(&SA)) - Addend |= 1; - - // If symbol is labeled as micromips, we set low-bit to ensure - // correct offset in .gcc_except_table - if (Asm->getBackend().isMicroMips(&SA)) - Addend |= 1; - - // Clear the symbol expr pointers to indicate we have folded these - // operands. - A = B = nullptr; - return; - } - - if (!Layout) - return; - - const MCSection &SecA = *SA.getFragment()->getParent(); - const MCSection &SecB = *SB.getFragment()->getParent(); - - if ((&SecA != &SecB) && !Addrs) - return; - - // Eagerly evaluate. - Addend += Layout->getSymbolOffset(A->getSymbol()) - - Layout->getSymbolOffset(B->getSymbol()); - if (Addrs && (&SecA != &SecB)) - Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB)); - - // Pointers to Thumb symbols need to have their low-bit set to allow - // for interworking. - if (Asm->isThumbFunc(&SA)) - Addend |= 1; - - // If symbol is labeled as micromips, we set low-bit to ensure - // correct offset in .gcc_except_table - if (Asm->getBackend().isMicroMips(&SA)) - Addend |= 1; - - // Clear the symbol expr pointers to indicate we have folded these - // operands. - A = B = nullptr; -} - -static bool canFold(const MCAssembler *Asm, const MCSymbolRefExpr *A, - const MCSymbolRefExpr *B, bool InSet) { - if (InSet) - return true; - - if (!Asm->getBackend().requiresDiffExpressionRelocations()) - return true; - - const MCSymbol &CheckSym = A ? A->getSymbol() : B->getSymbol(); - if (!CheckSym.isInSection()) - return true; - - if (!CheckSym.getSection().hasInstructions()) - return true; - - return false; -} - -/// Evaluate the result of an add between (conceptually) two MCValues. -/// -/// This routine conceptually attempts to construct an MCValue: -/// Result = (Result_A - Result_B + Result_Cst) -/// from two MCValue's LHS and RHS where -/// Result = LHS + RHS -/// and -/// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). -/// -/// This routine attempts to aggresively fold the operands such that the result -/// is representable in an MCValue, but may not always succeed. -/// -/// \returns True on success, false if the result is not representable in an -/// MCValue. - -/// NOTE: It is really important to have both the Asm and Layout arguments. -/// They might look redundant, but this function can be used before layout -/// is done (see the object streamer for example) and having the Asm argument -/// lets us avoid relaxations early. -static bool -EvaluateSymbolicAdd(const MCAssembler *Asm, const MCAsmLayout *Layout, - const SectionAddrMap *Addrs, bool InSet, const MCValue &LHS, - const MCSymbolRefExpr *RHS_A, const MCSymbolRefExpr *RHS_B, - int64_t RHS_Cst, MCValue &Res) { - // FIXME: This routine (and other evaluation parts) are *incredibly* sloppy - // about dealing with modifiers. This will ultimately bite us, one day. - const MCSymbolRefExpr *LHS_A = LHS.getSymA(); - const MCSymbolRefExpr *LHS_B = LHS.getSymB(); - int64_t LHS_Cst = LHS.getConstant(); - - // Fold the result constant immediately. - int64_t Result_Cst = LHS_Cst + RHS_Cst; - - assert((!Layout || Asm) && - "Must have an assembler object if layout is given!"); - - // If we have a layout, we can fold resolved differences. Do not do this if - // the backend requires this to be emitted as individual relocations, unless - // the InSet flag is set to get the current difference anyway (used for - // example to calculate symbol sizes). - if (Asm && canFold(Asm, LHS_A, LHS_B, InSet)) { - // First, fold out any differences which are fully resolved. By - // reassociating terms in - // Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). - // we have the four possible differences: - // (LHS_A - LHS_B), - // (LHS_A - RHS_B), - // (RHS_A - LHS_B), - // (RHS_A - RHS_B). - // Since we are attempting to be as aggressive as possible about folding, we - // attempt to evaluate each possible alternative. - AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, LHS_B, - Result_Cst); - AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, RHS_B, - Result_Cst); - AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, LHS_B, - Result_Cst); - AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, RHS_B, - Result_Cst); - } - - // We can't represent the addition or subtraction of two symbols. - if ((LHS_A && RHS_A) || (LHS_B && RHS_B)) - return false; - - // At this point, we have at most one additive symbol and one subtractive - // symbol -- find them. - const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A; - const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B; - - Res = MCValue::get(A, B, Result_Cst); - return true; -} - -bool MCExpr::evaluateAsRelocatable(MCValue &Res, - const MCAsmLayout *Layout, - const MCFixup *Fixup) const { - MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr; - return evaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr, - false); -} - -bool MCExpr::evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const { - MCAssembler *Assembler = &Layout.getAssembler(); - return evaluateAsRelocatableImpl(Res, Assembler, &Layout, nullptr, nullptr, - true); -} - -static bool canExpand(const MCSymbol &Sym, bool InSet) { - const MCExpr *Expr = Sym.getVariableValue(); - const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr); - if (Inner) { - if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) - return false; - } - - if (InSet) - return true; - return !Sym.isInSection(); -} - -bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, - const MCAsmLayout *Layout, - const MCFixup *Fixup, - const SectionAddrMap *Addrs, - bool InSet) const { - ++stats::MCExprEvaluate; - - switch (getKind()) { - case Target: - return cast<MCTargetExpr>(this)->evaluateAsRelocatableImpl(Res, Layout, - Fixup); - - case Constant: - Res = MCValue::get(cast<MCConstantExpr>(this)->getValue()); - return true; - - case SymbolRef: { - const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); - const MCSymbol &Sym = SRE->getSymbol(); - - // Evaluate recursively if this is a variable. - if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None && - canExpand(Sym, InSet)) { - bool IsMachO = SRE->hasSubsectionsViaSymbols(); - if (Sym.getVariableValue()->evaluateAsRelocatableImpl( - Res, Asm, Layout, Fixup, Addrs, InSet || IsMachO)) { - if (!IsMachO) - return true; - - const MCSymbolRefExpr *A = Res.getSymA(); - const MCSymbolRefExpr *B = Res.getSymB(); - // FIXME: This is small hack. Given - // a = b + 4 - // .long a - // the OS X assembler will completely drop the 4. We should probably - // include it in the relocation or produce an error if that is not - // possible. - // Allow constant expressions. - if (!A && !B) - return true; - // Allows aliases with zero offset. - if (Res.getConstant() == 0 && (!A || !B)) - return true; - } - } - - Res = MCValue::get(SRE, nullptr, 0); - return true; - } - - case Unary: { - const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this); - MCValue Value; - - if (!AUE->getSubExpr()->evaluateAsRelocatableImpl(Value, Asm, Layout, Fixup, - Addrs, InSet)) - return false; - - switch (AUE->getOpcode()) { - case MCUnaryExpr::LNot: - if (!Value.isAbsolute()) - return false; - Res = MCValue::get(!Value.getConstant()); - break; - case MCUnaryExpr::Minus: - /// -(a - b + const) ==> (b - a - const) - if (Value.getSymA() && !Value.getSymB()) - return false; - - // The cast avoids undefined behavior if the constant is INT64_MIN. - Res = MCValue::get(Value.getSymB(), Value.getSymA(), - -(uint64_t)Value.getConstant()); - break; - case MCUnaryExpr::Not: - if (!Value.isAbsolute()) - return false; - Res = MCValue::get(~Value.getConstant()); - break; - case MCUnaryExpr::Plus: - Res = Value; - break; - } - - return true; - } - - case Binary: { - const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this); - MCValue LHSValue, RHSValue; - - if (!ABE->getLHS()->evaluateAsRelocatableImpl(LHSValue, Asm, Layout, Fixup, - Addrs, InSet) || - !ABE->getRHS()->evaluateAsRelocatableImpl(RHSValue, Asm, Layout, Fixup, - Addrs, InSet)) { - // Check if both are Target Expressions, see if we can compare them. - if (const MCTargetExpr *L = dyn_cast<MCTargetExpr>(ABE->getLHS())) - if (const MCTargetExpr *R = cast<MCTargetExpr>(ABE->getRHS())) { - switch (ABE->getOpcode()) { - case MCBinaryExpr::EQ: - Res = MCValue::get((L->isEqualTo(R)) ? -1 : 0); - return true; - case MCBinaryExpr::NE: - Res = MCValue::get((R->isEqualTo(R)) ? 0 : -1); - return true; - default: break; - } - } - return false; - } - - // We only support a few operations on non-constant expressions, handle - // those first. - if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) { - switch (ABE->getOpcode()) { - default: - return false; - case MCBinaryExpr::Sub: - // Negate RHS and add. - // The cast avoids undefined behavior if the constant is INT64_MIN. - return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, - RHSValue.getSymB(), RHSValue.getSymA(), - -(uint64_t)RHSValue.getConstant(), Res); - - case MCBinaryExpr::Add: - return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, - RHSValue.getSymA(), RHSValue.getSymB(), - RHSValue.getConstant(), Res); - } - } - - // FIXME: We need target hooks for the evaluation. It may be limited in - // width, and gas defines the result of comparisons differently from - // Apple as. - int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); - int64_t Result = 0; - auto Op = ABE->getOpcode(); - switch (Op) { - case MCBinaryExpr::AShr: Result = LHS >> RHS; break; - case MCBinaryExpr::Add: Result = LHS + RHS; break; - case MCBinaryExpr::And: Result = LHS & RHS; break; - case MCBinaryExpr::Div: - case MCBinaryExpr::Mod: - // Handle division by zero. gas just emits a warning and keeps going, - // we try to be stricter. - // FIXME: Currently the caller of this function has no way to understand - // we're bailing out because of 'division by zero'. Therefore, it will - // emit a 'expected relocatable expression' error. It would be nice to - // change this code to emit a better diagnostic. - if (RHS == 0) - return false; - if (ABE->getOpcode() == MCBinaryExpr::Div) - Result = LHS / RHS; - else - Result = LHS % RHS; - break; - case MCBinaryExpr::EQ: Result = LHS == RHS; break; - case MCBinaryExpr::GT: Result = LHS > RHS; break; - case MCBinaryExpr::GTE: Result = LHS >= RHS; break; - case MCBinaryExpr::LAnd: Result = LHS && RHS; break; - case MCBinaryExpr::LOr: Result = LHS || RHS; break; - case MCBinaryExpr::LShr: Result = uint64_t(LHS) >> uint64_t(RHS); break; - case MCBinaryExpr::LT: Result = LHS < RHS; break; - case MCBinaryExpr::LTE: Result = LHS <= RHS; break; - case MCBinaryExpr::Mul: Result = LHS * RHS; break; - case MCBinaryExpr::NE: Result = LHS != RHS; break; - case MCBinaryExpr::Or: Result = LHS | RHS; break; - case MCBinaryExpr::Shl: Result = uint64_t(LHS) << uint64_t(RHS); break; - case MCBinaryExpr::Sub: Result = LHS - RHS; break; - case MCBinaryExpr::Xor: Result = LHS ^ RHS; break; - } - - switch (Op) { - default: - Res = MCValue::get(Result); - break; - case MCBinaryExpr::EQ: - case MCBinaryExpr::GT: - case MCBinaryExpr::GTE: - case MCBinaryExpr::LT: - case MCBinaryExpr::LTE: - case MCBinaryExpr::NE: - // A comparison operator returns a -1 if true and 0 if false. - Res = MCValue::get(Result ? -1 : 0); - break; - } - - return true; - } - } - - llvm_unreachable("Invalid assembly expression kind!"); -} - -MCFragment *MCExpr::findAssociatedFragment() const { - switch (getKind()) { - case Target: - // We never look through target specific expressions. - return cast<MCTargetExpr>(this)->findAssociatedFragment(); - - case Constant: - return MCSymbol::AbsolutePseudoFragment; - - case SymbolRef: { - const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); - const MCSymbol &Sym = SRE->getSymbol(); - return Sym.getFragment(); - } - - case Unary: - return cast<MCUnaryExpr>(this)->getSubExpr()->findAssociatedFragment(); - - case Binary: { - const MCBinaryExpr *BE = cast<MCBinaryExpr>(this); - MCFragment *LHS_F = BE->getLHS()->findAssociatedFragment(); - MCFragment *RHS_F = BE->getRHS()->findAssociatedFragment(); - - // If either is absolute, return the other. - if (LHS_F == MCSymbol::AbsolutePseudoFragment) - return RHS_F; - if (RHS_F == MCSymbol::AbsolutePseudoFragment) - return LHS_F; - - // Not always correct, but probably the best we can do without more context. - if (BE->getOpcode() == MCBinaryExpr::Sub) - return MCSymbol::AbsolutePseudoFragment; - - // Otherwise, return the first non-null fragment. - return LHS_F ? LHS_F : RHS_F; - } - } - - llvm_unreachable("Invalid assembly expression kind!"); -} diff --git a/contrib/llvm/lib/MC/MCFragment.cpp b/contrib/llvm/lib/MC/MCFragment.cpp deleted file mode 100644 index ae5bd65507bc..000000000000 --- a/contrib/llvm/lib/MC/MCFragment.cpp +++ /dev/null @@ -1,467 +0,0 @@ -//===- lib/MC/MCFragment.cpp - Assembler Fragment Implementation ----------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCFragment.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Config/llvm-config.h" -#include "llvm/MC/MCAsmLayout.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFixup.h" -#include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCValue.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> -#include <cstdint> -#include <utility> - -using namespace llvm; - -MCAsmLayout::MCAsmLayout(MCAssembler &Asm) : Assembler(Asm) { - // Compute the section layout order. Virtual sections must go last. - for (MCSection &Sec : Asm) - if (!Sec.isVirtualSection()) - SectionOrder.push_back(&Sec); - for (MCSection &Sec : Asm) - if (Sec.isVirtualSection()) - SectionOrder.push_back(&Sec); -} - -bool MCAsmLayout::isFragmentValid(const MCFragment *F) const { - const MCSection *Sec = F->getParent(); - const MCFragment *LastValid = LastValidFragment.lookup(Sec); - if (!LastValid) - return false; - assert(LastValid->getParent() == Sec); - return F->getLayoutOrder() <= LastValid->getLayoutOrder(); -} - -void MCAsmLayout::invalidateFragmentsFrom(MCFragment *F) { - // If this fragment wasn't already valid, we don't need to do anything. - if (!isFragmentValid(F)) - return; - - // Otherwise, reset the last valid fragment to the previous fragment - // (if this is the first fragment, it will be NULL). - LastValidFragment[F->getParent()] = F->getPrevNode(); -} - -void MCAsmLayout::ensureValid(const MCFragment *F) const { - MCSection *Sec = F->getParent(); - MCSection::iterator I; - if (MCFragment *Cur = LastValidFragment[Sec]) - I = ++MCSection::iterator(Cur); - else - I = Sec->begin(); - - // Advance the layout position until the fragment is valid. - while (!isFragmentValid(F)) { - assert(I != Sec->end() && "Layout bookkeeping error"); - const_cast<MCAsmLayout *>(this)->layoutFragment(&*I); - ++I; - } -} - -uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const { - ensureValid(F); - assert(F->Offset != ~UINT64_C(0) && "Address not set!"); - return F->Offset; -} - -// Simple getSymbolOffset helper for the non-variable case. -static bool getLabelOffset(const MCAsmLayout &Layout, const MCSymbol &S, - bool ReportError, uint64_t &Val) { - if (!S.getFragment()) { - if (ReportError) - report_fatal_error("unable to evaluate offset to undefined symbol '" + - S.getName() + "'"); - return false; - } - Val = Layout.getFragmentOffset(S.getFragment()) + S.getOffset(); - return true; -} - -static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, const MCSymbol &S, - bool ReportError, uint64_t &Val) { - if (!S.isVariable()) - return getLabelOffset(Layout, S, ReportError, Val); - - // If SD is a variable, evaluate it. - MCValue Target; - if (!S.getVariableValue()->evaluateAsValue(Target, Layout)) - report_fatal_error("unable to evaluate offset for variable '" + - S.getName() + "'"); - - uint64_t Offset = Target.getConstant(); - - const MCSymbolRefExpr *A = Target.getSymA(); - if (A) { - uint64_t ValA; - if (!getLabelOffset(Layout, A->getSymbol(), ReportError, ValA)) - return false; - Offset += ValA; - } - - const MCSymbolRefExpr *B = Target.getSymB(); - if (B) { - uint64_t ValB; - if (!getLabelOffset(Layout, B->getSymbol(), ReportError, ValB)) - return false; - Offset -= ValB; - } - - Val = Offset; - return true; -} - -bool MCAsmLayout::getSymbolOffset(const MCSymbol &S, uint64_t &Val) const { - return getSymbolOffsetImpl(*this, S, false, Val); -} - -uint64_t MCAsmLayout::getSymbolOffset(const MCSymbol &S) const { - uint64_t Val; - getSymbolOffsetImpl(*this, S, true, Val); - return Val; -} - -const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const { - if (!Symbol.isVariable()) - return &Symbol; - - const MCExpr *Expr = Symbol.getVariableValue(); - MCValue Value; - if (!Expr->evaluateAsValue(Value, *this)) { - Assembler.getContext().reportError( - Expr->getLoc(), "expression could not be evaluated"); - return nullptr; - } - - const MCSymbolRefExpr *RefB = Value.getSymB(); - if (RefB) { - Assembler.getContext().reportError( - Expr->getLoc(), Twine("symbol '") + RefB->getSymbol().getName() + - "' could not be evaluated in a subtraction expression"); - return nullptr; - } - - const MCSymbolRefExpr *A = Value.getSymA(); - if (!A) - return nullptr; - - const MCSymbol &ASym = A->getSymbol(); - const MCAssembler &Asm = getAssembler(); - if (ASym.isCommon()) { - Asm.getContext().reportError(Expr->getLoc(), - "Common symbol '" + ASym.getName() + - "' cannot be used in assignment expr"); - return nullptr; - } - - return &ASym; -} - -uint64_t MCAsmLayout::getSectionAddressSize(const MCSection *Sec) const { - // The size is the last fragment's end offset. - const MCFragment &F = Sec->getFragmentList().back(); - return getFragmentOffset(&F) + getAssembler().computeFragmentSize(*this, F); -} - -uint64_t MCAsmLayout::getSectionFileSize(const MCSection *Sec) const { - // Virtual sections have no file size. - if (Sec->isVirtualSection()) - return 0; - - // Otherwise, the file size is the same as the address space size. - return getSectionAddressSize(Sec); -} - -uint64_t llvm::computeBundlePadding(const MCAssembler &Assembler, - const MCEncodedFragment *F, - uint64_t FOffset, uint64_t FSize) { - uint64_t BundleSize = Assembler.getBundleAlignSize(); - assert(BundleSize > 0 && - "computeBundlePadding should only be called if bundling is enabled"); - uint64_t BundleMask = BundleSize - 1; - uint64_t OffsetInBundle = FOffset & BundleMask; - uint64_t EndOfFragment = OffsetInBundle + FSize; - - // There are two kinds of bundling restrictions: - // - // 1) For alignToBundleEnd(), add padding to ensure that the fragment will - // *end* on a bundle boundary. - // 2) Otherwise, check if the fragment would cross a bundle boundary. If it - // would, add padding until the end of the bundle so that the fragment - // will start in a new one. - if (F->alignToBundleEnd()) { - // Three possibilities here: - // - // A) The fragment just happens to end at a bundle boundary, so we're good. - // B) The fragment ends before the current bundle boundary: pad it just - // enough to reach the boundary. - // C) The fragment ends after the current bundle boundary: pad it until it - // reaches the end of the next bundle boundary. - // - // Note: this code could be made shorter with some modulo trickery, but it's - // intentionally kept in its more explicit form for simplicity. - if (EndOfFragment == BundleSize) - return 0; - else if (EndOfFragment < BundleSize) - return BundleSize - EndOfFragment; - else { // EndOfFragment > BundleSize - return 2 * BundleSize - EndOfFragment; - } - } else if (OffsetInBundle > 0 && EndOfFragment > BundleSize) - return BundleSize - OffsetInBundle; - else - return 0; -} - -/* *** */ - -void ilist_alloc_traits<MCFragment>::deleteNode(MCFragment *V) { V->destroy(); } - -MCFragment::~MCFragment() = default; - -MCFragment::MCFragment(FragmentType Kind, bool HasInstructions, - MCSection *Parent) - : Kind(Kind), HasInstructions(HasInstructions), LayoutOrder(0), - Parent(Parent), Atom(nullptr), Offset(~UINT64_C(0)) { - if (Parent && !isDummy()) - Parent->getFragmentList().push_back(this); -} - -void MCFragment::destroy() { - // First check if we are the sentinal. - if (Kind == FragmentType(~0)) { - delete this; - return; - } - - switch (Kind) { - case FT_Align: - delete cast<MCAlignFragment>(this); - return; - case FT_Data: - delete cast<MCDataFragment>(this); - return; - case FT_CompactEncodedInst: - delete cast<MCCompactEncodedInstFragment>(this); - return; - case FT_Fill: - delete cast<MCFillFragment>(this); - return; - case FT_Relaxable: - delete cast<MCRelaxableFragment>(this); - return; - case FT_Org: - delete cast<MCOrgFragment>(this); - return; - case FT_Dwarf: - delete cast<MCDwarfLineAddrFragment>(this); - return; - case FT_DwarfFrame: - delete cast<MCDwarfCallFrameFragment>(this); - return; - case FT_LEB: - delete cast<MCLEBFragment>(this); - return; - case FT_Padding: - delete cast<MCPaddingFragment>(this); - return; - case FT_SymbolId: - delete cast<MCSymbolIdFragment>(this); - return; - case FT_CVInlineLines: - delete cast<MCCVInlineLineTableFragment>(this); - return; - case FT_CVDefRange: - delete cast<MCCVDefRangeFragment>(this); - return; - case FT_Dummy: - delete cast<MCDummyFragment>(this); - return; - } -} - -// Debugging methods - -namespace llvm { - -raw_ostream &operator<<(raw_ostream &OS, const MCFixup &AF) { - OS << "<MCFixup" << " Offset:" << AF.getOffset() - << " Value:" << *AF.getValue() - << " Kind:" << AF.getKind() << ">"; - return OS; -} - -} // end namespace llvm - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -LLVM_DUMP_METHOD void MCFragment::dump() const { - raw_ostream &OS = errs(); - - OS << "<"; - switch (getKind()) { - case MCFragment::FT_Align: OS << "MCAlignFragment"; break; - case MCFragment::FT_Data: OS << "MCDataFragment"; break; - case MCFragment::FT_CompactEncodedInst: - OS << "MCCompactEncodedInstFragment"; break; - case MCFragment::FT_Fill: OS << "MCFillFragment"; break; - case MCFragment::FT_Relaxable: OS << "MCRelaxableFragment"; break; - case MCFragment::FT_Org: OS << "MCOrgFragment"; break; - case MCFragment::FT_Dwarf: OS << "MCDwarfFragment"; break; - case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break; - case MCFragment::FT_LEB: OS << "MCLEBFragment"; break; - case MCFragment::FT_Padding: OS << "MCPaddingFragment"; break; - case MCFragment::FT_SymbolId: OS << "MCSymbolIdFragment"; break; - case MCFragment::FT_CVInlineLines: OS << "MCCVInlineLineTableFragment"; break; - case MCFragment::FT_CVDefRange: OS << "MCCVDefRangeTableFragment"; break; - case MCFragment::FT_Dummy: OS << "MCDummyFragment"; break; - } - - OS << "<MCFragment " << (const void *)this << " LayoutOrder:" << LayoutOrder - << " Offset:" << Offset << " HasInstructions:" << hasInstructions(); - if (const MCEncodedFragment *EF = dyn_cast<MCEncodedFragment>(this)) - OS << " BundlePadding:" << static_cast<unsigned>(EF->getBundlePadding()); - OS << ">"; - - switch (getKind()) { - case MCFragment::FT_Align: { - const MCAlignFragment *AF = cast<MCAlignFragment>(this); - if (AF->hasEmitNops()) - OS << " (emit nops)"; - OS << "\n "; - OS << " Alignment:" << AF->getAlignment() - << " Value:" << AF->getValue() << " ValueSize:" << AF->getValueSize() - << " MaxBytesToEmit:" << AF->getMaxBytesToEmit() << ">"; - break; - } - case MCFragment::FT_Data: { - const MCDataFragment *DF = cast<MCDataFragment>(this); - OS << "\n "; - OS << " Contents:["; - const SmallVectorImpl<char> &Contents = DF->getContents(); - for (unsigned i = 0, e = Contents.size(); i != e; ++i) { - if (i) OS << ","; - OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF); - } - OS << "] (" << Contents.size() << " bytes)"; - - if (DF->fixup_begin() != DF->fixup_end()) { - OS << ",\n "; - OS << " Fixups:["; - for (MCDataFragment::const_fixup_iterator it = DF->fixup_begin(), - ie = DF->fixup_end(); it != ie; ++it) { - if (it != DF->fixup_begin()) OS << ",\n "; - OS << *it; - } - OS << "]"; - } - break; - } - case MCFragment::FT_CompactEncodedInst: { - const MCCompactEncodedInstFragment *CEIF = - cast<MCCompactEncodedInstFragment>(this); - OS << "\n "; - OS << " Contents:["; - const SmallVectorImpl<char> &Contents = CEIF->getContents(); - for (unsigned i = 0, e = Contents.size(); i != e; ++i) { - if (i) OS << ","; - OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF); - } - OS << "] (" << Contents.size() << " bytes)"; - break; - } - case MCFragment::FT_Fill: { - const MCFillFragment *FF = cast<MCFillFragment>(this); - OS << " Value:" << static_cast<unsigned>(FF->getValue()) - << " ValueSize:" << static_cast<unsigned>(FF->getValueSize()) - << " NumValues:" << FF->getNumValues(); - break; - } - case MCFragment::FT_Relaxable: { - const MCRelaxableFragment *F = cast<MCRelaxableFragment>(this); - OS << "\n "; - OS << " Inst:"; - F->getInst().dump_pretty(OS); - break; - } - case MCFragment::FT_Org: { - const MCOrgFragment *OF = cast<MCOrgFragment>(this); - OS << "\n "; - OS << " Offset:" << OF->getOffset() - << " Value:" << static_cast<unsigned>(OF->getValue()); - break; - } - case MCFragment::FT_Dwarf: { - const MCDwarfLineAddrFragment *OF = cast<MCDwarfLineAddrFragment>(this); - OS << "\n "; - OS << " AddrDelta:" << OF->getAddrDelta() - << " LineDelta:" << OF->getLineDelta(); - break; - } - case MCFragment::FT_DwarfFrame: { - const MCDwarfCallFrameFragment *CF = cast<MCDwarfCallFrameFragment>(this); - OS << "\n "; - OS << " AddrDelta:" << CF->getAddrDelta(); - break; - } - case MCFragment::FT_LEB: { - const MCLEBFragment *LF = cast<MCLEBFragment>(this); - OS << "\n "; - OS << " Value:" << LF->getValue() << " Signed:" << LF->isSigned(); - break; - } - case MCFragment::FT_Padding: { - const MCPaddingFragment *F = cast<MCPaddingFragment>(this); - OS << "\n "; - OS << " PaddingPoliciesMask:" << F->getPaddingPoliciesMask() - << " IsInsertionPoint:" << F->isInsertionPoint() - << " Size:" << F->getSize(); - OS << "\n "; - OS << " Inst:"; - F->getInst().dump_pretty(OS); - OS << " InstSize:" << F->getInstSize(); - OS << "\n "; - break; - } - case MCFragment::FT_SymbolId: { - const MCSymbolIdFragment *F = cast<MCSymbolIdFragment>(this); - OS << "\n "; - OS << " Sym:" << F->getSymbol(); - break; - } - case MCFragment::FT_CVInlineLines: { - const auto *F = cast<MCCVInlineLineTableFragment>(this); - OS << "\n "; - OS << " Sym:" << *F->getFnStartSym(); - break; - } - case MCFragment::FT_CVDefRange: { - const auto *F = cast<MCCVDefRangeFragment>(this); - OS << "\n "; - for (std::pair<const MCSymbol *, const MCSymbol *> RangeStartEnd : - F->getRanges()) { - OS << " RangeStart:" << RangeStartEnd.first; - OS << " RangeEnd:" << RangeStartEnd.second; - } - break; - } - case MCFragment::FT_Dummy: - break; - } - OS << ">"; -} -#endif diff --git a/contrib/llvm/lib/MC/MCInst.cpp b/contrib/llvm/lib/MC/MCInst.cpp deleted file mode 100644 index f6f6edee5822..000000000000 --- a/contrib/llvm/lib/MC/MCInst.cpp +++ /dev/null @@ -1,98 +0,0 @@ -//===- lib/MC/MCInst.cpp - MCInst implementation --------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCInst.h" -#include "llvm/Config/llvm-config.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInstPrinter.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -void MCOperand::print(raw_ostream &OS) const { - OS << "<MCOperand "; - if (!isValid()) - OS << "INVALID"; - else if (isReg()) - OS << "Reg:" << getReg(); - else if (isImm()) - OS << "Imm:" << getImm(); - else if (isFPImm()) - OS << "FPImm:" << getFPImm(); - else if (isExpr()) { - OS << "Expr:(" << *getExpr() << ")"; - } else if (isInst()) { - OS << "Inst:(" << *getInst() << ")"; - } else - OS << "UNDEFINED"; - OS << ">"; -} - -bool MCOperand::evaluateAsConstantImm(int64_t &Imm) const { - if (isImm()) { - Imm = getImm(); - return true; - } - return false; -} - -bool MCOperand::isBareSymbolRef() const { - assert(isExpr() && - "isBareSymbolRef expects only expressions"); - const MCExpr *Expr = getExpr(); - MCExpr::ExprKind Kind = getExpr()->getKind(); - return Kind == MCExpr::SymbolRef && - cast<MCSymbolRefExpr>(Expr)->getKind() == MCSymbolRefExpr::VK_None; -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -LLVM_DUMP_METHOD void MCOperand::dump() const { - print(dbgs()); - dbgs() << "\n"; -} -#endif - -void MCInst::print(raw_ostream &OS) const { - OS << "<MCInst " << getOpcode(); - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { - OS << " "; - getOperand(i).print(OS); - } - OS << ">"; -} - -void MCInst::dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer, - StringRef Separator) const { - StringRef InstName = Printer ? Printer->getOpcodeName(getOpcode()) : ""; - dump_pretty(OS, InstName, Separator); -} - -void MCInst::dump_pretty(raw_ostream &OS, StringRef Name, - StringRef Separator) const { - OS << "<MCInst #" << getOpcode(); - - // Show the instruction opcode name if we have it. - if (!Name.empty()) - OS << ' ' << Name; - - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { - OS << Separator; - getOperand(i).print(OS); - } - OS << ">"; -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -LLVM_DUMP_METHOD void MCInst::dump() const { - print(dbgs()); - dbgs() << "\n"; -} -#endif diff --git a/contrib/llvm/lib/MC/MCInstPrinter.cpp b/contrib/llvm/lib/MC/MCInstPrinter.cpp deleted file mode 100644 index 159f4070fe9f..000000000000 --- a/contrib/llvm/lib/MC/MCInstPrinter.cpp +++ /dev/null @@ -1,125 +0,0 @@ -//===- MCInstPrinter.cpp - Convert an MCInst to target assembly syntax ----===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCInstPrinter.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" -#include <cinttypes> -#include <cstdint> - -using namespace llvm; - -void llvm::dumpBytes(ArrayRef<uint8_t> bytes, raw_ostream &OS) { - static const char hex_rep[] = "0123456789abcdef"; - bool First = true; - for (char i: bytes) { - if (First) - First = false; - else - OS << ' '; - OS << hex_rep[(i & 0xF0) >> 4]; - OS << hex_rep[i & 0xF]; - } -} - -MCInstPrinter::~MCInstPrinter() = default; - -/// getOpcodeName - Return the name of the specified opcode enum (e.g. -/// "MOV32ri") or empty if we can't resolve it. -StringRef MCInstPrinter::getOpcodeName(unsigned Opcode) const { - return MII.getName(Opcode); -} - -void MCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { - llvm_unreachable("Target should implement this"); -} - -void MCInstPrinter::printAnnotation(raw_ostream &OS, StringRef Annot) { - if (!Annot.empty()) { - if (CommentStream) { - (*CommentStream) << Annot; - // By definition (see MCInstPrinter.h), CommentStream must end with - // a newline after each comment. - if (Annot.back() != '\n') - (*CommentStream) << '\n'; - } else - OS << " " << MAI.getCommentString() << " " << Annot; - } -} - -/// Utility functions to make adding mark ups simpler. -StringRef MCInstPrinter::markup(StringRef s) const { - if (getUseMarkup()) - return s; - else - return ""; -} -StringRef MCInstPrinter::markup(StringRef a, StringRef b) const { - if (getUseMarkup()) - return a; - else - return b; -} - -// For asm-style hex (e.g. 0ffh) the first digit always has to be a number. -static bool needsLeadingZero(uint64_t Value) -{ - while (Value) - { - uint64_t digit = (Value >> 60) & 0xf; - if (digit != 0) - return (digit >= 0xa); - Value <<= 4; - } - return false; -} - -format_object<int64_t> MCInstPrinter::formatDec(int64_t Value) const { - return format("%" PRId64, Value); -} - -format_object<int64_t> MCInstPrinter::formatHex(int64_t Value) const { - switch(PrintHexStyle) { - case HexStyle::C: - if (Value < 0) - return format("-0x%" PRIx64, -Value); - else - return format("0x%" PRIx64, Value); - case HexStyle::Asm: - if (Value < 0) { - if (needsLeadingZero((uint64_t)(-Value))) - return format("-0%" PRIx64 "h", -Value); - else - return format("-%" PRIx64 "h", -Value); - } else { - if (needsLeadingZero((uint64_t)(Value))) - return format("0%" PRIx64 "h", Value); - else - return format("%" PRIx64 "h", Value); - } - } - llvm_unreachable("unsupported print style"); -} - -format_object<uint64_t> MCInstPrinter::formatHex(uint64_t Value) const { - switch(PrintHexStyle) { - case HexStyle::C: - return format("0x%" PRIx64, Value); - case HexStyle::Asm: - if (needsLeadingZero(Value)) - return format("0%" PRIx64 "h", Value); - else - return format("%" PRIx64 "h", Value); - } - llvm_unreachable("unsupported print style"); -} diff --git a/contrib/llvm/lib/MC/MCInstrAnalysis.cpp b/contrib/llvm/lib/MC/MCInstrAnalysis.cpp deleted file mode 100644 index eca87f940bf5..000000000000 --- a/contrib/llvm/lib/MC/MCInstrAnalysis.cpp +++ /dev/null @@ -1,35 +0,0 @@ -//===- MCInstrAnalysis.cpp - InstrDesc target hooks -----------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCInstrAnalysis.h" - -#include "llvm/ADT/APInt.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCInstrDesc.h" -#include "llvm/MC/MCInstrInfo.h" -#include <cstdint> - -using namespace llvm; - -bool MCInstrAnalysis::clearsSuperRegisters(const MCRegisterInfo &MRI, - const MCInst &Inst, - APInt &Writes) const { - Writes.clearAllBits(); - return false; -} - -bool MCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr, - uint64_t Size, uint64_t &Target) const { - if (Inst.getNumOperands() == 0 || - Info->get(Inst.getOpcode()).OpInfo[0].OperandType != MCOI::OPERAND_PCREL) - return false; - - int64_t Imm = Inst.getOperand(0).getImm(); - Target = Addr+Size+Imm; - return true; -} diff --git a/contrib/llvm/lib/MC/MCInstrDesc.cpp b/contrib/llvm/lib/MC/MCInstrDesc.cpp deleted file mode 100644 index d54aeba89edc..000000000000 --- a/contrib/llvm/lib/MC/MCInstrDesc.cpp +++ /dev/null @@ -1,65 +0,0 @@ -//===------ llvm/MC/MCInstrDesc.cpp- Instruction Descriptors --------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines methods on the MCOperandInfo and MCInstrDesc classes, which -// are used to describe target instructions and their operands. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCInstrDesc.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSubtargetInfo.h" - -using namespace llvm; - -bool MCInstrDesc::getDeprecatedInfo(MCInst &MI, const MCSubtargetInfo &STI, - std::string &Info) const { - if (ComplexDeprecationInfo) - return ComplexDeprecationInfo(MI, STI, Info); - if (DeprecatedFeature != -1 && STI.getFeatureBits()[DeprecatedFeature]) { - // FIXME: it would be nice to include the subtarget feature here. - Info = "deprecated"; - return true; - } - return false; -} -bool MCInstrDesc::mayAffectControlFlow(const MCInst &MI, - const MCRegisterInfo &RI) const { - if (isBranch() || isCall() || isReturn() || isIndirectBranch()) - return true; - unsigned PC = RI.getProgramCounter(); - if (PC == 0) - return false; - if (hasDefOfPhysReg(MI, PC, RI)) - return true; - return false; -} - -bool MCInstrDesc::hasImplicitDefOfPhysReg(unsigned Reg, - const MCRegisterInfo *MRI) const { - if (const MCPhysReg *ImpDefs = ImplicitDefs) - for (; *ImpDefs; ++ImpDefs) - if (*ImpDefs == Reg || (MRI && MRI->isSubRegister(Reg, *ImpDefs))) - return true; - return false; -} - -bool MCInstrDesc::hasDefOfPhysReg(const MCInst &MI, unsigned Reg, - const MCRegisterInfo &RI) const { - for (int i = 0, e = NumDefs; i != e; ++i) - if (MI.getOperand(i).isReg() && - RI.isSubRegisterEq(Reg, MI.getOperand(i).getReg())) - return true; - if (variadicOpsAreDefs()) - for (int i = NumOperands - 1, e = MI.getNumOperands(); i != e; ++i) - if (MI.getOperand(i).isReg() && - RI.isSubRegisterEq(Reg, MI.getOperand(i).getReg())) - return true; - return hasImplicitDefOfPhysReg(Reg, &RI); -} diff --git a/contrib/llvm/lib/MC/MCLabel.cpp b/contrib/llvm/lib/MC/MCLabel.cpp deleted file mode 100644 index 66ee73c5bbb3..000000000000 --- a/contrib/llvm/lib/MC/MCLabel.cpp +++ /dev/null @@ -1,25 +0,0 @@ -//===- lib/MC/MCLabel.cpp - MCLabel implementation ------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCLabel.h" -#include "llvm/Config/llvm-config.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -void MCLabel::print(raw_ostream &OS) const { - OS << '"' << getInstance() << '"'; -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -LLVM_DUMP_METHOD void MCLabel::dump() const { - print(dbgs()); -} -#endif diff --git a/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp b/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp deleted file mode 100644 index 9ab321872b11..000000000000 --- a/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp +++ /dev/null @@ -1,59 +0,0 @@ -//===- llvm/MC/MCLinkerOptimizationHint.cpp ----- LOH handling ------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCLinkerOptimizationHint.h" -#include "llvm/MC/MCAsmLayout.h" -#include "llvm/MC/MCMachObjectWriter.h" -#include "llvm/Support/LEB128.h" -#include "llvm/Support/raw_ostream.h" -#include <cstddef> -#include <cstdint> - -using namespace llvm; - -// Each LOH is composed by, in this order (each field is encoded using ULEB128): -// - Its kind. -// - Its number of arguments (let say N). -// - Its arg1. -// - ... -// - Its argN. -// <arg1> to <argN> are absolute addresses in the object file, i.e., -// relative addresses from the beginning of the object file. -void MCLOHDirective::emit_impl(raw_ostream &OutStream, - const MachObjectWriter &ObjWriter, - const MCAsmLayout &Layout) const { - encodeULEB128(Kind, OutStream); - encodeULEB128(Args.size(), OutStream); - for (const MCSymbol *Arg : Args) - encodeULEB128(ObjWriter.getSymbolAddress(*Arg, Layout), OutStream); -} - -void MCLOHDirective::emit(MachObjectWriter &ObjWriter, - const MCAsmLayout &Layout) const { - raw_ostream &OutStream = ObjWriter.W.OS; - emit_impl(OutStream, ObjWriter, Layout); -} - -uint64_t MCLOHDirective::getEmitSize(const MachObjectWriter &ObjWriter, - const MCAsmLayout &Layout) const { - class raw_counting_ostream : public raw_ostream { - uint64_t Count = 0; - - void write_impl(const char *, size_t size) override { Count += size; } - - uint64_t current_pos() const override { return Count; } - - public: - raw_counting_ostream() = default; - ~raw_counting_ostream() override { flush(); } - }; - - raw_counting_ostream OutStream; - emit_impl(OutStream, ObjWriter, Layout); - return OutStream.tell(); -} diff --git a/contrib/llvm/lib/MC/MCMachOStreamer.cpp b/contrib/llvm/lib/MC/MCMachOStreamer.cpp deleted file mode 100644 index 613f255a4ea4..000000000000 --- a/contrib/llvm/lib/MC/MCMachOStreamer.cpp +++ /dev/null @@ -1,519 +0,0 @@ -//===- MCMachOStreamer.cpp - MachO Streamer -------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCCodeEmitter.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDirectives.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFixup.h" -#include "llvm/MC/MCFragment.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCLinkerOptimizationHint.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCObjectStreamer.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSectionMachO.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCSymbolMachO.h" -#include "llvm/MC/MCValue.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> -#include <vector> - -using namespace llvm; - -namespace { - -class MCMachOStreamer : public MCObjectStreamer { -private: - /// LabelSections - true if each section change should emit a linker local - /// label for use in relocations for assembler local references. Obviates the - /// need for local relocations. False by default. - bool LabelSections; - - bool DWARFMustBeAtTheEnd; - bool CreatedADWARFSection; - - /// HasSectionLabel - map of which sections have already had a non-local - /// label emitted to them. Used so we don't emit extraneous linker local - /// labels in the middle of the section. - DenseMap<const MCSection*, bool> HasSectionLabel; - - void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) override; - - void EmitDataRegion(DataRegionData::KindTy Kind); - void EmitDataRegionEnd(); - -public: - MCMachOStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB, - std::unique_ptr<MCObjectWriter> OW, - std::unique_ptr<MCCodeEmitter> Emitter, - bool DWARFMustBeAtTheEnd, bool label) - : MCObjectStreamer(Context, std::move(MAB), std::move(OW), - std::move(Emitter)), - LabelSections(label), DWARFMustBeAtTheEnd(DWARFMustBeAtTheEnd), - CreatedADWARFSection(false) {} - - /// state management - void reset() override { - CreatedADWARFSection = false; - HasSectionLabel.clear(); - MCObjectStreamer::reset(); - } - - /// @name MCStreamer Interface - /// @{ - - void ChangeSection(MCSection *Sect, const MCExpr *Subsect) override; - void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; - void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; - void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) override; - void EmitAssemblerFlag(MCAssemblerFlag Flag) override; - void EmitLinkerOptions(ArrayRef<std::string> Options) override; - void EmitDataRegion(MCDataRegionType Kind) override; - void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor, - unsigned Update, VersionTuple SDKVersion) override; - void EmitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor, - unsigned Update, VersionTuple SDKVersion) override; - void EmitThumbFunc(MCSymbol *Func) override; - bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; - void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; - void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) override; - - void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) override; - void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, - uint64_t Size = 0, unsigned ByteAlignment = 0, - SMLoc Loc = SMLoc()) override; - void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment = 0) override; - - void EmitIdent(StringRef IdentString) override { - llvm_unreachable("macho doesn't support this directive"); - } - - void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override { - getAssembler().getLOHContainer().addDirective(Kind, Args); - } - - void FinishImpl() override; -}; - -} // end anonymous namespace. - -static bool canGoAfterDWARF(const MCSectionMachO &MSec) { - // These sections are created by the assembler itself after the end of - // the .s file. - StringRef SegName = MSec.getSegmentName(); - StringRef SecName = MSec.getSectionName(); - - if (SegName == "__LD" && SecName == "__compact_unwind") - return true; - - if (SegName == "__IMPORT") { - if (SecName == "__jump_table") - return true; - - if (SecName == "__pointers") - return true; - } - - if (SegName == "__TEXT" && SecName == "__eh_frame") - return true; - - if (SegName == "__DATA" && (SecName == "__nl_symbol_ptr" || - SecName == "__thread_ptr")) - return true; - - return false; -} - -void MCMachOStreamer::ChangeSection(MCSection *Section, - const MCExpr *Subsection) { - // Change the section normally. - bool Created = changeSectionImpl(Section, Subsection); - const MCSectionMachO &MSec = *cast<MCSectionMachO>(Section); - StringRef SegName = MSec.getSegmentName(); - if (SegName == "__DWARF") - CreatedADWARFSection = true; - else if (Created && DWARFMustBeAtTheEnd && !canGoAfterDWARF(MSec)) - assert(!CreatedADWARFSection && "Creating regular section after DWARF"); - - // Output a linker-local symbol so we don't need section-relative local - // relocations. The linker hates us when we do that. - if (LabelSections && !HasSectionLabel[Section] && - !Section->getBeginSymbol()) { - MCSymbol *Label = getContext().createLinkerPrivateTempSymbol(); - Section->setBeginSymbol(Label); - HasSectionLabel[Section] = true; - } -} - -void MCMachOStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, - MCSymbol *EHSymbol) { - getAssembler().registerSymbol(*Symbol); - if (Symbol->isExternal()) - EmitSymbolAttribute(EHSymbol, MCSA_Global); - if (cast<MCSymbolMachO>(Symbol)->isWeakDefinition()) - EmitSymbolAttribute(EHSymbol, MCSA_WeakDefinition); - if (Symbol->isPrivateExtern()) - EmitSymbolAttribute(EHSymbol, MCSA_PrivateExtern); -} - -void MCMachOStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) { - // We have to create a new fragment if this is an atom defining symbol, - // fragments cannot span atoms. - if (getAssembler().isSymbolLinkerVisible(*Symbol)) - insert(new MCDataFragment()); - - MCObjectStreamer::EmitLabel(Symbol, Loc); - - // This causes the reference type flag to be cleared. Darwin 'as' was "trying" - // to clear the weak reference and weak definition bits too, but the - // implementation was buggy. For now we just try to match 'as', for - // diffability. - // - // FIXME: Cleanup this code, these bits should be emitted based on semantic - // properties, not on the order of definition, etc. - cast<MCSymbolMachO>(Symbol)->clearReferenceType(); -} - -void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { - MCValue Res; - - if (Value->evaluateAsRelocatable(Res, nullptr, nullptr)) { - if (const MCSymbolRefExpr *SymAExpr = Res.getSymA()) { - const MCSymbol &SymA = SymAExpr->getSymbol(); - if (!Res.getSymB() && (SymA.getName() == "" || Res.getConstant() != 0)) - cast<MCSymbolMachO>(Symbol)->setAltEntry(); - } - } - MCObjectStreamer::EmitAssignment(Symbol, Value); -} - -void MCMachOStreamer::EmitDataRegion(DataRegionData::KindTy Kind) { - // Create a temporary label to mark the start of the data region. - MCSymbol *Start = getContext().createTempSymbol(); - EmitLabel(Start); - // Record the region for the object writer to use. - DataRegionData Data = { Kind, Start, nullptr }; - std::vector<DataRegionData> &Regions = getAssembler().getDataRegions(); - Regions.push_back(Data); -} - -void MCMachOStreamer::EmitDataRegionEnd() { - std::vector<DataRegionData> &Regions = getAssembler().getDataRegions(); - assert(!Regions.empty() && "Mismatched .end_data_region!"); - DataRegionData &Data = Regions.back(); - assert(!Data.End && "Mismatched .end_data_region!"); - // Create a temporary label to mark the end of the data region. - Data.End = getContext().createTempSymbol(); - EmitLabel(Data.End); -} - -void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { - // Let the target do whatever target specific stuff it needs to do. - getAssembler().getBackend().handleAssemblerFlag(Flag); - // Do any generic stuff we need to do. - switch (Flag) { - case MCAF_SyntaxUnified: return; // no-op here. - case MCAF_Code16: return; // Change parsing mode; no-op here. - case MCAF_Code32: return; // Change parsing mode; no-op here. - case MCAF_Code64: return; // Change parsing mode; no-op here. - case MCAF_SubsectionsViaSymbols: - getAssembler().setSubsectionsViaSymbols(true); - return; - } -} - -void MCMachOStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) { - getAssembler().getLinkerOptions().push_back(Options); -} - -void MCMachOStreamer::EmitDataRegion(MCDataRegionType Kind) { - switch (Kind) { - case MCDR_DataRegion: - EmitDataRegion(DataRegionData::Data); - return; - case MCDR_DataRegionJT8: - EmitDataRegion(DataRegionData::JumpTable8); - return; - case MCDR_DataRegionJT16: - EmitDataRegion(DataRegionData::JumpTable16); - return; - case MCDR_DataRegionJT32: - EmitDataRegion(DataRegionData::JumpTable32); - return; - case MCDR_DataRegionEnd: - EmitDataRegionEnd(); - return; - } -} - -void MCMachOStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major, - unsigned Minor, unsigned Update, - VersionTuple SDKVersion) { - getAssembler().setVersionMin(Kind, Major, Minor, Update, SDKVersion); -} - -void MCMachOStreamer::EmitBuildVersion(unsigned Platform, unsigned Major, - unsigned Minor, unsigned Update, - VersionTuple SDKVersion) { - getAssembler().setBuildVersion((MachO::PlatformType)Platform, Major, Minor, - Update, SDKVersion); -} - -void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) { - // Remember that the function is a thumb function. Fixup and relocation - // values will need adjusted. - getAssembler().setIsThumbFunc(Symbol); - cast<MCSymbolMachO>(Symbol)->setThumbFunc(); -} - -bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Sym, - MCSymbolAttr Attribute) { - MCSymbolMachO *Symbol = cast<MCSymbolMachO>(Sym); - - // Indirect symbols are handled differently, to match how 'as' handles - // them. This makes writing matching .o files easier. - if (Attribute == MCSA_IndirectSymbol) { - // Note that we intentionally cannot use the symbol data here; this is - // important for matching the string table that 'as' generates. - IndirectSymbolData ISD; - ISD.Symbol = Symbol; - ISD.Section = getCurrentSectionOnly(); - getAssembler().getIndirectSymbols().push_back(ISD); - return true; - } - - // Adding a symbol attribute always introduces the symbol, note that an - // important side effect of calling registerSymbol here is to register - // the symbol with the assembler. - getAssembler().registerSymbol(*Symbol); - - // The implementation of symbol attributes is designed to match 'as', but it - // leaves much to desired. It doesn't really make sense to arbitrarily add and - // remove flags, but 'as' allows this (in particular, see .desc). - // - // In the future it might be worth trying to make these operations more well - // defined. - switch (Attribute) { - case MCSA_Invalid: - case MCSA_ELF_TypeFunction: - case MCSA_ELF_TypeIndFunction: - case MCSA_ELF_TypeObject: - case MCSA_ELF_TypeTLS: - case MCSA_ELF_TypeCommon: - case MCSA_ELF_TypeNoType: - case MCSA_ELF_TypeGnuUniqueObject: - case MCSA_Hidden: - case MCSA_IndirectSymbol: - case MCSA_Internal: - case MCSA_Protected: - case MCSA_Weak: - case MCSA_Local: - return false; - - case MCSA_Global: - Symbol->setExternal(true); - // This effectively clears the undefined lazy bit, in Darwin 'as', although - // it isn't very consistent because it implements this as part of symbol - // lookup. - // - // FIXME: Cleanup this code, these bits should be emitted based on semantic - // properties, not on the order of definition, etc. - Symbol->setReferenceTypeUndefinedLazy(false); - break; - - case MCSA_LazyReference: - // FIXME: This requires -dynamic. - Symbol->setNoDeadStrip(); - if (Symbol->isUndefined()) - Symbol->setReferenceTypeUndefinedLazy(true); - break; - - // Since .reference sets the no dead strip bit, it is equivalent to - // .no_dead_strip in practice. - case MCSA_Reference: - case MCSA_NoDeadStrip: - Symbol->setNoDeadStrip(); - break; - - case MCSA_SymbolResolver: - Symbol->setSymbolResolver(); - break; - - case MCSA_AltEntry: - Symbol->setAltEntry(); - break; - - case MCSA_PrivateExtern: - Symbol->setExternal(true); - Symbol->setPrivateExtern(true); - break; - - case MCSA_WeakReference: - // FIXME: This requires -dynamic. - if (Symbol->isUndefined()) - Symbol->setWeakReference(); - break; - - case MCSA_WeakDefinition: - // FIXME: 'as' enforces that this is defined and global. The manual claims - // it has to be in a coalesced section, but this isn't enforced. - Symbol->setWeakDefinition(); - break; - - case MCSA_WeakDefAutoPrivate: - Symbol->setWeakDefinition(); - Symbol->setWeakReference(); - break; - - case MCSA_Cold: - Symbol->setCold(); - break; - } - - return true; -} - -void MCMachOStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { - // Encode the 'desc' value into the lowest implementation defined bits. - getAssembler().registerSymbol(*Symbol); - cast<MCSymbolMachO>(Symbol)->setDesc(DescValue); -} - -void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) { - // FIXME: Darwin 'as' does appear to allow redef of a .comm by itself. - assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - - getAssembler().registerSymbol(*Symbol); - Symbol->setExternal(true); - Symbol->setCommon(Size, ByteAlignment); -} - -void MCMachOStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) { - // '.lcomm' is equivalent to '.zerofill'. - return EmitZerofill(getContext().getObjectFileInfo()->getDataBSSSection(), - Symbol, Size, ByteAlignment); -} - -void MCMachOStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment, - SMLoc Loc) { - // On darwin all virtual sections have zerofill type. Disallow the usage of - // .zerofill in non-virtual functions. If something similar is needed, use - // .space or .zero. - if (!Section->isVirtualSection()) { - getContext().reportError( - Loc, "The usage of .zerofill is restricted to sections of " - "ZEROFILL type. Use .zero or .space instead."); - return; // Early returning here shouldn't harm. EmitZeros should work on any - // section. - } - - PushSection(); - SwitchSection(Section); - - // The symbol may not be present, which only creates the section. - if (Symbol) { - EmitValueToAlignment(ByteAlignment, 0, 1, 0); - EmitLabel(Symbol); - EmitZeros(Size); - } - PopSection(); -} - -// This should always be called with the thread local bss section. Like the -// .zerofill directive this doesn't actually switch sections on us. -void MCMachOStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment) { - EmitZerofill(Section, Symbol, Size, ByteAlignment); -} - -void MCMachOStreamer::EmitInstToData(const MCInst &Inst, - const MCSubtargetInfo &STI) { - MCDataFragment *DF = getOrCreateDataFragment(); - - SmallVector<MCFixup, 4> Fixups; - SmallString<256> Code; - raw_svector_ostream VecOS(Code); - getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); - - // Add the fixups and data. - for (MCFixup &Fixup : Fixups) { - Fixup.setOffset(Fixup.getOffset() + DF->getContents().size()); - DF->getFixups().push_back(Fixup); - } - DF->setHasInstructions(STI); - DF->getContents().append(Code.begin(), Code.end()); -} - -void MCMachOStreamer::FinishImpl() { - EmitFrames(&getAssembler().getBackend()); - - // We have to set the fragment atom associations so we can relax properly for - // Mach-O. - - // First, scan the symbol table to build a lookup table from fragments to - // defining symbols. - DenseMap<const MCFragment *, const MCSymbol *> DefiningSymbolMap; - for (const MCSymbol &Symbol : getAssembler().symbols()) { - if (getAssembler().isSymbolLinkerVisible(Symbol) && Symbol.isInSection() && - !Symbol.isVariable()) { - // An atom defining symbol should never be internal to a fragment. - assert(Symbol.getOffset() == 0 && - "Invalid offset in atom defining symbol!"); - DefiningSymbolMap[Symbol.getFragment()] = &Symbol; - } - } - - // Set the fragment atom associations by tracking the last seen atom defining - // symbol. - for (MCSection &Sec : getAssembler()) { - const MCSymbol *CurrentAtom = nullptr; - for (MCFragment &Frag : Sec) { - if (const MCSymbol *Symbol = DefiningSymbolMap.lookup(&Frag)) - CurrentAtom = Symbol; - Frag.setAtom(CurrentAtom); - } - } - - this->MCObjectStreamer::FinishImpl(); -} - -MCStreamer *llvm::createMachOStreamer(MCContext &Context, - std::unique_ptr<MCAsmBackend> &&MAB, - std::unique_ptr<MCObjectWriter> &&OW, - std::unique_ptr<MCCodeEmitter> &&CE, - bool RelaxAll, bool DWARFMustBeAtTheEnd, - bool LabelSections) { - MCMachOStreamer *S = - new MCMachOStreamer(Context, std::move(MAB), std::move(OW), std::move(CE), - DWARFMustBeAtTheEnd, LabelSections); - const Triple &Target = Context.getObjectFileInfo()->getTargetTriple(); - S->EmitVersionForTarget(Target, Context.getObjectFileInfo()->getSDKVersion()); - if (RelaxAll) - S->getAssembler().setRelaxAll(true); - return S; -} diff --git a/contrib/llvm/lib/MC/MCMachObjectTargetWriter.cpp b/contrib/llvm/lib/MC/MCMachObjectTargetWriter.cpp deleted file mode 100644 index a57b8a7ac0ff..000000000000 --- a/contrib/llvm/lib/MC/MCMachObjectTargetWriter.cpp +++ /dev/null @@ -1,18 +0,0 @@ -//===- MCMachObjectTargetWriter.cpp - Mach-O Target Writer Subclass -------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCMachObjectWriter.h" - -using namespace llvm; - -MCMachObjectTargetWriter::MCMachObjectTargetWriter(bool Is64Bit_, - uint32_t CPUType_, - uint32_t CPUSubtype_) - : Is64Bit(Is64Bit_), CPUType(CPUType_), CPUSubtype(CPUSubtype_) {} - -MCMachObjectTargetWriter::~MCMachObjectTargetWriter() = default; diff --git a/contrib/llvm/lib/MC/MCNullStreamer.cpp b/contrib/llvm/lib/MC/MCNullStreamer.cpp deleted file mode 100644 index 8452317c8c6b..000000000000 --- a/contrib/llvm/lib/MC/MCNullStreamer.cpp +++ /dev/null @@ -1,49 +0,0 @@ -//===- lib/MC/MCNullStreamer.cpp - Dummy Streamer Implementation ----------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/StringRef.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" - -using namespace llvm; - -namespace { - - class MCNullStreamer : public MCStreamer { - public: - MCNullStreamer(MCContext &Context) : MCStreamer(Context) {} - - /// @name MCStreamer Interface - /// @{ - - bool hasRawTextSupport() const override { return true; } - void EmitRawTextImpl(StringRef String) override {} - - bool EmitSymbolAttribute(MCSymbol *Symbol, - MCSymbolAttr Attribute) override { - return true; - } - - void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) override {} - void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, - uint64_t Size = 0, unsigned ByteAlignment = 0, - SMLoc Loc = SMLoc()) override {} - void EmitGPRel32Value(const MCExpr *Value) override {} - void BeginCOFFSymbolDef(const MCSymbol *Symbol) override {} - void EmitCOFFSymbolStorageClass(int StorageClass) override {} - void EmitCOFFSymbolType(int Type) override {} - void EndCOFFSymbolDef() override {} - }; - -} - -MCStreamer *llvm::createNullStreamer(MCContext &Context) { - return new MCNullStreamer(Context); -} diff --git a/contrib/llvm/lib/MC/MCObjectFileInfo.cpp b/contrib/llvm/lib/MC/MCObjectFileInfo.cpp deleted file mode 100644 index 9f555abe1404..000000000000 --- a/contrib/llvm/lib/MC/MCObjectFileInfo.cpp +++ /dev/null @@ -1,867 +0,0 @@ -//===-- MCObjectFileInfo.cpp - Object File Information --------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/Triple.h" -#include "llvm/BinaryFormat/COFF.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSectionCOFF.h" -#include "llvm/MC/MCSectionELF.h" -#include "llvm/MC/MCSectionMachO.h" -#include "llvm/MC/MCSectionWasm.h" -#include "llvm/MC/MCSectionXCOFF.h" - -using namespace llvm; - -static bool useCompactUnwind(const Triple &T) { - // Only on darwin. - if (!T.isOSDarwin()) - return false; - - // aarch64 always has it. - if (T.getArch() == Triple::aarch64) - return true; - - // armv7k always has it. - if (T.isWatchABI()) - return true; - - // Use it on newer version of OS X. - if (T.isMacOSX() && !T.isMacOSXVersionLT(10, 6)) - return true; - - // And the iOS simulator. - if (T.isiOS() && - (T.getArch() == Triple::x86_64 || T.getArch() == Triple::x86)) - return true; - - return false; -} - -void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) { - // MachO - SupportsWeakOmittedEHFrame = false; - - EHFrameSection = Ctx->getMachOSection( - "__TEXT", "__eh_frame", - MachO::S_COALESCED | MachO::S_ATTR_NO_TOC | - MachO::S_ATTR_STRIP_STATIC_SYMS | MachO::S_ATTR_LIVE_SUPPORT, - SectionKind::getReadOnly()); - - if (T.isOSDarwin() && T.getArch() == Triple::aarch64) - SupportsCompactUnwindWithoutEHFrame = true; - - if (T.isWatchABI()) - OmitDwarfIfHaveCompactUnwind = true; - - FDECFIEncoding = dwarf::DW_EH_PE_pcrel; - - // .comm doesn't support alignment before Leopard. - if (T.isMacOSX() && T.isMacOSXVersionLT(10, 5)) - CommDirectiveSupportsAlignment = false; - - TextSection // .text - = Ctx->getMachOSection("__TEXT", "__text", - MachO::S_ATTR_PURE_INSTRUCTIONS, - SectionKind::getText()); - DataSection // .data - = Ctx->getMachOSection("__DATA", "__data", 0, SectionKind::getData()); - - // BSSSection might not be expected initialized on msvc. - BSSSection = nullptr; - - TLSDataSection // .tdata - = Ctx->getMachOSection("__DATA", "__thread_data", - MachO::S_THREAD_LOCAL_REGULAR, - SectionKind::getData()); - TLSBSSSection // .tbss - = Ctx->getMachOSection("__DATA", "__thread_bss", - MachO::S_THREAD_LOCAL_ZEROFILL, - SectionKind::getThreadBSS()); - - // TODO: Verify datarel below. - TLSTLVSection // .tlv - = Ctx->getMachOSection("__DATA", "__thread_vars", - MachO::S_THREAD_LOCAL_VARIABLES, - SectionKind::getData()); - - TLSThreadInitSection = Ctx->getMachOSection( - "__DATA", "__thread_init", MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS, - SectionKind::getData()); - - CStringSection // .cstring - = Ctx->getMachOSection("__TEXT", "__cstring", - MachO::S_CSTRING_LITERALS, - SectionKind::getMergeable1ByteCString()); - UStringSection - = Ctx->getMachOSection("__TEXT","__ustring", 0, - SectionKind::getMergeable2ByteCString()); - FourByteConstantSection // .literal4 - = Ctx->getMachOSection("__TEXT", "__literal4", - MachO::S_4BYTE_LITERALS, - SectionKind::getMergeableConst4()); - EightByteConstantSection // .literal8 - = Ctx->getMachOSection("__TEXT", "__literal8", - MachO::S_8BYTE_LITERALS, - SectionKind::getMergeableConst8()); - - SixteenByteConstantSection // .literal16 - = Ctx->getMachOSection("__TEXT", "__literal16", - MachO::S_16BYTE_LITERALS, - SectionKind::getMergeableConst16()); - - ReadOnlySection // .const - = Ctx->getMachOSection("__TEXT", "__const", 0, - SectionKind::getReadOnly()); - - // If the target is not powerpc, map the coal sections to the non-coal - // sections. - // - // "__TEXT/__textcoal_nt" => section "__TEXT/__text" - // "__TEXT/__const_coal" => section "__TEXT/__const" - // "__DATA/__datacoal_nt" => section "__DATA/__data" - Triple::ArchType ArchTy = T.getArch(); - - ConstDataSection // .const_data - = Ctx->getMachOSection("__DATA", "__const", 0, - SectionKind::getReadOnlyWithRel()); - - if (ArchTy == Triple::ppc || ArchTy == Triple::ppc64) { - TextCoalSection - = Ctx->getMachOSection("__TEXT", "__textcoal_nt", - MachO::S_COALESCED | - MachO::S_ATTR_PURE_INSTRUCTIONS, - SectionKind::getText()); - ConstTextCoalSection - = Ctx->getMachOSection("__TEXT", "__const_coal", - MachO::S_COALESCED, - SectionKind::getReadOnly()); - DataCoalSection = Ctx->getMachOSection( - "__DATA", "__datacoal_nt", MachO::S_COALESCED, SectionKind::getData()); - ConstDataCoalSection = DataCoalSection; - } else { - TextCoalSection = TextSection; - ConstTextCoalSection = ReadOnlySection; - DataCoalSection = DataSection; - ConstDataCoalSection = ConstDataSection; - } - - DataCommonSection - = Ctx->getMachOSection("__DATA","__common", - MachO::S_ZEROFILL, - SectionKind::getBSS()); - DataBSSSection - = Ctx->getMachOSection("__DATA","__bss", MachO::S_ZEROFILL, - SectionKind::getBSS()); - - - LazySymbolPointerSection - = Ctx->getMachOSection("__DATA", "__la_symbol_ptr", - MachO::S_LAZY_SYMBOL_POINTERS, - SectionKind::getMetadata()); - NonLazySymbolPointerSection - = Ctx->getMachOSection("__DATA", "__nl_symbol_ptr", - MachO::S_NON_LAZY_SYMBOL_POINTERS, - SectionKind::getMetadata()); - - ThreadLocalPointerSection - = Ctx->getMachOSection("__DATA", "__thread_ptr", - MachO::S_THREAD_LOCAL_VARIABLE_POINTERS, - SectionKind::getMetadata()); - - // Exception Handling. - LSDASection = Ctx->getMachOSection("__TEXT", "__gcc_except_tab", 0, - SectionKind::getReadOnlyWithRel()); - - COFFDebugSymbolsSection = nullptr; - COFFDebugTypesSection = nullptr; - COFFGlobalTypeHashesSection = nullptr; - - if (useCompactUnwind(T)) { - CompactUnwindSection = - Ctx->getMachOSection("__LD", "__compact_unwind", MachO::S_ATTR_DEBUG, - SectionKind::getReadOnly()); - - if (T.getArch() == Triple::x86_64 || T.getArch() == Triple::x86) - CompactUnwindDwarfEHFrameOnly = 0x04000000; // UNWIND_X86_64_MODE_DWARF - else if (T.getArch() == Triple::aarch64) - CompactUnwindDwarfEHFrameOnly = 0x03000000; // UNWIND_ARM64_MODE_DWARF - else if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb) - CompactUnwindDwarfEHFrameOnly = 0x04000000; // UNWIND_ARM_MODE_DWARF - } - - // Debug Information. - DwarfDebugNamesSection = - Ctx->getMachOSection("__DWARF", "__debug_names", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata(), "debug_names_begin"); - DwarfAccelNamesSection = - Ctx->getMachOSection("__DWARF", "__apple_names", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata(), "names_begin"); - DwarfAccelObjCSection = - Ctx->getMachOSection("__DWARF", "__apple_objc", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata(), "objc_begin"); - // 16 character section limit... - DwarfAccelNamespaceSection = - Ctx->getMachOSection("__DWARF", "__apple_namespac", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata(), "namespac_begin"); - DwarfAccelTypesSection = - Ctx->getMachOSection("__DWARF", "__apple_types", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata(), "types_begin"); - - DwarfSwiftASTSection = - Ctx->getMachOSection("__DWARF", "__swift_ast", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - - DwarfAbbrevSection = - Ctx->getMachOSection("__DWARF", "__debug_abbrev", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata(), "section_abbrev"); - DwarfInfoSection = - Ctx->getMachOSection("__DWARF", "__debug_info", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata(), "section_info"); - DwarfLineSection = - Ctx->getMachOSection("__DWARF", "__debug_line", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata(), "section_line"); - DwarfLineStrSection = - Ctx->getMachOSection("__DWARF", "__debug_line_str", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata(), "section_line_str"); - DwarfFrameSection = - Ctx->getMachOSection("__DWARF", "__debug_frame", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfPubNamesSection = - Ctx->getMachOSection("__DWARF", "__debug_pubnames", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfPubTypesSection = - Ctx->getMachOSection("__DWARF", "__debug_pubtypes", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfGnuPubNamesSection = - Ctx->getMachOSection("__DWARF", "__debug_gnu_pubn", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfGnuPubTypesSection = - Ctx->getMachOSection("__DWARF", "__debug_gnu_pubt", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfStrSection = - Ctx->getMachOSection("__DWARF", "__debug_str", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata(), "info_string"); - DwarfStrOffSection = - Ctx->getMachOSection("__DWARF", "__debug_str_offs", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata(), "section_str_off"); - DwarfAddrSection = - Ctx->getMachOSection("__DWARF", "__debug_addr", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata(), "section_info"); - DwarfLocSection = - Ctx->getMachOSection("__DWARF", "__debug_loc", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata(), "section_debug_loc"); - DwarfLoclistsSection = - Ctx->getMachOSection("__DWARF", "__debug_loclists", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata(), "section_debug_loc"); - - DwarfARangesSection = - Ctx->getMachOSection("__DWARF", "__debug_aranges", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfRangesSection = - Ctx->getMachOSection("__DWARF", "__debug_ranges", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata(), "debug_range"); - DwarfRnglistsSection = - Ctx->getMachOSection("__DWARF", "__debug_rnglists", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata(), "debug_range"); - DwarfMacinfoSection = - Ctx->getMachOSection("__DWARF", "__debug_macinfo", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata(), "debug_macinfo"); - DwarfDebugInlineSection = - Ctx->getMachOSection("__DWARF", "__debug_inlined", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfCUIndexSection = - Ctx->getMachOSection("__DWARF", "__debug_cu_index", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfTUIndexSection = - Ctx->getMachOSection("__DWARF", "__debug_tu_index", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - StackMapSection = Ctx->getMachOSection("__LLVM_STACKMAPS", "__llvm_stackmaps", - 0, SectionKind::getMetadata()); - - FaultMapSection = Ctx->getMachOSection("__LLVM_FAULTMAPS", "__llvm_faultmaps", - 0, SectionKind::getMetadata()); - - RemarksSection = Ctx->getMachOSection( - "__LLVM", "__remarks", MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); - - TLSExtraDataSection = TLSTLVSection; -} - -void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) { - switch (T.getArch()) { - case Triple::mips: - case Triple::mipsel: - case Triple::mips64: - case Triple::mips64el: - FDECFIEncoding = Ctx->getAsmInfo()->getCodePointerSize() == 4 - ? dwarf::DW_EH_PE_sdata4 - : dwarf::DW_EH_PE_sdata8; - break; - case Triple::ppc64: - case Triple::ppc64le: - case Triple::x86_64: - FDECFIEncoding = dwarf::DW_EH_PE_pcrel | - (Large ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4); - break; - case Triple::bpfel: - case Triple::bpfeb: - FDECFIEncoding = dwarf::DW_EH_PE_sdata8; - break; - case Triple::hexagon: - FDECFIEncoding = - PositionIndependent ? dwarf::DW_EH_PE_pcrel : dwarf::DW_EH_PE_absptr; - break; - default: - FDECFIEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; - break; - } - - unsigned EHSectionType = T.getArch() == Triple::x86_64 - ? ELF::SHT_X86_64_UNWIND - : ELF::SHT_PROGBITS; - - // Solaris requires different flags for .eh_frame to seemingly every other - // platform. - unsigned EHSectionFlags = ELF::SHF_ALLOC; - if (T.isOSSolaris() && T.getArch() != Triple::x86_64) - EHSectionFlags |= ELF::SHF_WRITE; - - // ELF - BSSSection = Ctx->getELFSection(".bss", ELF::SHT_NOBITS, - ELF::SHF_WRITE | ELF::SHF_ALLOC); - - TextSection = Ctx->getELFSection(".text", ELF::SHT_PROGBITS, - ELF::SHF_EXECINSTR | ELF::SHF_ALLOC); - - DataSection = Ctx->getELFSection(".data", ELF::SHT_PROGBITS, - ELF::SHF_WRITE | ELF::SHF_ALLOC); - - ReadOnlySection = - Ctx->getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC); - - TLSDataSection = - Ctx->getELFSection(".tdata", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHF_TLS | ELF::SHF_WRITE); - - TLSBSSSection = Ctx->getELFSection( - ".tbss", ELF::SHT_NOBITS, ELF::SHF_ALLOC | ELF::SHF_TLS | ELF::SHF_WRITE); - - DataRelROSection = Ctx->getELFSection(".data.rel.ro", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHF_WRITE); - - MergeableConst4Section = - Ctx->getELFSection(".rodata.cst4", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHF_MERGE, 4, ""); - - MergeableConst8Section = - Ctx->getELFSection(".rodata.cst8", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHF_MERGE, 8, ""); - - MergeableConst16Section = - Ctx->getELFSection(".rodata.cst16", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHF_MERGE, 16, ""); - - MergeableConst32Section = - Ctx->getELFSection(".rodata.cst32", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHF_MERGE, 32, ""); - - // Exception Handling Sections. - - // FIXME: We're emitting LSDA info into a readonly section on ELF, even though - // it contains relocatable pointers. In PIC mode, this is probably a big - // runtime hit for C++ apps. Either the contents of the LSDA need to be - // adjusted or this should be a data section. - LSDASection = Ctx->getELFSection(".gcc_except_table", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC); - - COFFDebugSymbolsSection = nullptr; - COFFDebugTypesSection = nullptr; - - unsigned DebugSecType = ELF::SHT_PROGBITS; - - // MIPS .debug_* sections should have SHT_MIPS_DWARF section type - // to distinguish among sections contain DWARF and ECOFF debug formats. - // Sections with ECOFF debug format are obsoleted and marked by SHT_PROGBITS. - if (T.isMIPS()) - DebugSecType = ELF::SHT_MIPS_DWARF; - - // Debug Info Sections. - DwarfAbbrevSection = - Ctx->getELFSection(".debug_abbrev", DebugSecType, 0); - DwarfInfoSection = Ctx->getELFSection(".debug_info", DebugSecType, 0); - DwarfLineSection = Ctx->getELFSection(".debug_line", DebugSecType, 0); - DwarfLineStrSection = - Ctx->getELFSection(".debug_line_str", DebugSecType, - ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, ""); - DwarfFrameSection = Ctx->getELFSection(".debug_frame", DebugSecType, 0); - DwarfPubNamesSection = - Ctx->getELFSection(".debug_pubnames", DebugSecType, 0); - DwarfPubTypesSection = - Ctx->getELFSection(".debug_pubtypes", DebugSecType, 0); - DwarfGnuPubNamesSection = - Ctx->getELFSection(".debug_gnu_pubnames", DebugSecType, 0); - DwarfGnuPubTypesSection = - Ctx->getELFSection(".debug_gnu_pubtypes", DebugSecType, 0); - DwarfStrSection = - Ctx->getELFSection(".debug_str", DebugSecType, - ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, ""); - DwarfLocSection = Ctx->getELFSection(".debug_loc", DebugSecType, 0); - DwarfARangesSection = - Ctx->getELFSection(".debug_aranges", DebugSecType, 0); - DwarfRangesSection = - Ctx->getELFSection(".debug_ranges", DebugSecType, 0); - DwarfMacinfoSection = - Ctx->getELFSection(".debug_macinfo", DebugSecType, 0); - - // DWARF5 Experimental Debug Info - - // Accelerator Tables - DwarfDebugNamesSection = - Ctx->getELFSection(".debug_names", ELF::SHT_PROGBITS, 0); - DwarfAccelNamesSection = - Ctx->getELFSection(".apple_names", ELF::SHT_PROGBITS, 0); - DwarfAccelObjCSection = - Ctx->getELFSection(".apple_objc", ELF::SHT_PROGBITS, 0); - DwarfAccelNamespaceSection = - Ctx->getELFSection(".apple_namespaces", ELF::SHT_PROGBITS, 0); - DwarfAccelTypesSection = - Ctx->getELFSection(".apple_types", ELF::SHT_PROGBITS, 0); - - // String Offset and Address Sections - DwarfStrOffSection = - Ctx->getELFSection(".debug_str_offsets", DebugSecType, 0); - DwarfAddrSection = Ctx->getELFSection(".debug_addr", DebugSecType, 0); - DwarfRnglistsSection = Ctx->getELFSection(".debug_rnglists", DebugSecType, 0); - DwarfLoclistsSection = Ctx->getELFSection(".debug_loclists", DebugSecType, 0); - - // Fission Sections - DwarfInfoDWOSection = - Ctx->getELFSection(".debug_info.dwo", DebugSecType, ELF::SHF_EXCLUDE); - DwarfTypesDWOSection = - Ctx->getELFSection(".debug_types.dwo", DebugSecType, ELF::SHF_EXCLUDE); - DwarfAbbrevDWOSection = - Ctx->getELFSection(".debug_abbrev.dwo", DebugSecType, ELF::SHF_EXCLUDE); - DwarfStrDWOSection = Ctx->getELFSection( - ".debug_str.dwo", DebugSecType, - ELF::SHF_MERGE | ELF::SHF_STRINGS | ELF::SHF_EXCLUDE, 1, ""); - DwarfLineDWOSection = - Ctx->getELFSection(".debug_line.dwo", DebugSecType, ELF::SHF_EXCLUDE); - DwarfLocDWOSection = - Ctx->getELFSection(".debug_loc.dwo", DebugSecType, ELF::SHF_EXCLUDE); - DwarfStrOffDWOSection = Ctx->getELFSection(".debug_str_offsets.dwo", - DebugSecType, ELF::SHF_EXCLUDE); - DwarfRnglistsDWOSection = - Ctx->getELFSection(".debug_rnglists.dwo", DebugSecType, ELF::SHF_EXCLUDE); - - // DWP Sections - DwarfCUIndexSection = - Ctx->getELFSection(".debug_cu_index", DebugSecType, 0); - DwarfTUIndexSection = - Ctx->getELFSection(".debug_tu_index", DebugSecType, 0); - - StackMapSection = - Ctx->getELFSection(".llvm_stackmaps", ELF::SHT_PROGBITS, ELF::SHF_ALLOC); - - FaultMapSection = - Ctx->getELFSection(".llvm_faultmaps", ELF::SHT_PROGBITS, ELF::SHF_ALLOC); - - EHFrameSection = - Ctx->getELFSection(".eh_frame", EHSectionType, EHSectionFlags); - - StackSizesSection = Ctx->getELFSection(".stack_sizes", ELF::SHT_PROGBITS, 0); - - RemarksSection = - Ctx->getELFSection(".remarks", ELF::SHT_PROGBITS, ELF::SHF_EXCLUDE); -} - -void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) { - EHFrameSection = - Ctx->getCOFFSection(".eh_frame", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getData()); - - // Set the `IMAGE_SCN_MEM_16BIT` flag when compiling for thumb mode. This is - // used to indicate to the linker that the text segment contains thumb instructions - // and to set the ISA selection bit for calls accordingly. - const bool IsThumb = T.getArch() == Triple::thumb; - - CommDirectiveSupportsAlignment = true; - - // COFF - BSSSection = Ctx->getCOFFSection( - ".bss", COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE, - SectionKind::getBSS()); - TextSection = Ctx->getCOFFSection( - ".text", - (IsThumb ? COFF::IMAGE_SCN_MEM_16BIT : (COFF::SectionCharacteristics)0) | - COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getText()); - DataSection = Ctx->getCOFFSection( - ".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ | - COFF::IMAGE_SCN_MEM_WRITE, - SectionKind::getData()); - ReadOnlySection = Ctx->getCOFFSection( - ".rdata", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ, - SectionKind::getReadOnly()); - - if (T.getArch() == Triple::x86_64 || T.getArch() == Triple::aarch64) { - // On Windows 64 with SEH, the LSDA is emitted into the .xdata section - LSDASection = nullptr; - } else { - LSDASection = Ctx->getCOFFSection(".gcc_except_table", - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getReadOnly()); - } - - // Debug info. - COFFDebugSymbolsSection = - Ctx->getCOFFSection(".debug$S", (COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ), - SectionKind::getMetadata()); - COFFDebugTypesSection = - Ctx->getCOFFSection(".debug$T", (COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ), - SectionKind::getMetadata()); - COFFGlobalTypeHashesSection = Ctx->getCOFFSection( - ".debug$H", - (COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ), - SectionKind::getMetadata()); - - DwarfAbbrevSection = Ctx->getCOFFSection( - ".debug_abbrev", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "section_abbrev"); - DwarfInfoSection = Ctx->getCOFFSection( - ".debug_info", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "section_info"); - DwarfLineSection = Ctx->getCOFFSection( - ".debug_line", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "section_line"); - DwarfLineStrSection = Ctx->getCOFFSection( - ".debug_line_str", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "section_line_str"); - DwarfFrameSection = Ctx->getCOFFSection( - ".debug_frame", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfPubNamesSection = Ctx->getCOFFSection( - ".debug_pubnames", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfPubTypesSection = Ctx->getCOFFSection( - ".debug_pubtypes", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfGnuPubNamesSection = Ctx->getCOFFSection( - ".debug_gnu_pubnames", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfGnuPubTypesSection = Ctx->getCOFFSection( - ".debug_gnu_pubtypes", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfStrSection = Ctx->getCOFFSection( - ".debug_str", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "info_string"); - DwarfStrOffSection = Ctx->getCOFFSection( - ".debug_str_offsets", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "section_str_off"); - DwarfLocSection = Ctx->getCOFFSection( - ".debug_loc", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "section_debug_loc"); - DwarfARangesSection = Ctx->getCOFFSection( - ".debug_aranges", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfRangesSection = Ctx->getCOFFSection( - ".debug_ranges", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "debug_range"); - DwarfMacinfoSection = Ctx->getCOFFSection( - ".debug_macinfo", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "debug_macinfo"); - DwarfInfoDWOSection = Ctx->getCOFFSection( - ".debug_info.dwo", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "section_info_dwo"); - DwarfTypesDWOSection = Ctx->getCOFFSection( - ".debug_types.dwo", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "section_types_dwo"); - DwarfAbbrevDWOSection = Ctx->getCOFFSection( - ".debug_abbrev.dwo", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "section_abbrev_dwo"); - DwarfStrDWOSection = Ctx->getCOFFSection( - ".debug_str.dwo", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "skel_string"); - DwarfLineDWOSection = Ctx->getCOFFSection( - ".debug_line.dwo", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfLocDWOSection = Ctx->getCOFFSection( - ".debug_loc.dwo", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "skel_loc"); - DwarfStrOffDWOSection = Ctx->getCOFFSection( - ".debug_str_offsets.dwo", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "section_str_off_dwo"); - DwarfAddrSection = Ctx->getCOFFSection( - ".debug_addr", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "addr_sec"); - DwarfCUIndexSection = Ctx->getCOFFSection( - ".debug_cu_index", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfTUIndexSection = Ctx->getCOFFSection( - ".debug_tu_index", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfDebugNamesSection = Ctx->getCOFFSection( - ".debug_names", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "debug_names_begin"); - DwarfAccelNamesSection = Ctx->getCOFFSection( - ".apple_names", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "names_begin"); - DwarfAccelNamespaceSection = Ctx->getCOFFSection( - ".apple_namespaces", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "namespac_begin"); - DwarfAccelTypesSection = Ctx->getCOFFSection( - ".apple_types", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "types_begin"); - DwarfAccelObjCSection = Ctx->getCOFFSection( - ".apple_objc", - COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata(), "objc_begin"); - - DrectveSection = Ctx->getCOFFSection( - ".drectve", COFF::IMAGE_SCN_LNK_INFO | COFF::IMAGE_SCN_LNK_REMOVE, - SectionKind::getMetadata()); - - PDataSection = Ctx->getCOFFSection( - ".pdata", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ, - SectionKind::getData()); - - XDataSection = Ctx->getCOFFSection( - ".xdata", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ, - SectionKind::getData()); - - SXDataSection = Ctx->getCOFFSection(".sxdata", COFF::IMAGE_SCN_LNK_INFO, - SectionKind::getMetadata()); - - GFIDsSection = Ctx->getCOFFSection(".gfids$y", - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - - TLSDataSection = Ctx->getCOFFSection( - ".tls$", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ | - COFF::IMAGE_SCN_MEM_WRITE, - SectionKind::getData()); - - StackMapSection = Ctx->getCOFFSection(".llvm_stackmaps", - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getReadOnly()); -} - -void MCObjectFileInfo::initWasmMCObjectFileInfo(const Triple &T) { - TextSection = Ctx->getWasmSection(".text", SectionKind::getText()); - DataSection = Ctx->getWasmSection(".data", SectionKind::getData()); - - DwarfLineSection = - Ctx->getWasmSection(".debug_line", SectionKind::getMetadata()); - DwarfLineStrSection = - Ctx->getWasmSection(".debug_line_str", SectionKind::getMetadata()); - DwarfStrSection = - Ctx->getWasmSection(".debug_str", SectionKind::getMetadata()); - DwarfLocSection = - Ctx->getWasmSection(".debug_loc", SectionKind::getMetadata()); - DwarfAbbrevSection = - Ctx->getWasmSection(".debug_abbrev", SectionKind::getMetadata()); - DwarfARangesSection = Ctx->getWasmSection(".debug_aranges", SectionKind::getMetadata()); - DwarfRangesSection = - Ctx->getWasmSection(".debug_ranges", SectionKind::getMetadata()); - DwarfMacinfoSection = - Ctx->getWasmSection(".debug_macinfo", SectionKind::getMetadata()); - DwarfAddrSection = Ctx->getWasmSection(".debug_addr", SectionKind::getMetadata()); - DwarfCUIndexSection = Ctx->getWasmSection(".debug_cu_index", SectionKind::getMetadata()); - DwarfTUIndexSection = Ctx->getWasmSection(".debug_tu_index", SectionKind::getMetadata()); - DwarfInfoSection = - Ctx->getWasmSection(".debug_info", SectionKind::getMetadata()); - DwarfFrameSection = Ctx->getWasmSection(".debug_frame", SectionKind::getMetadata()); - DwarfPubNamesSection = Ctx->getWasmSection(".debug_pubnames", SectionKind::getMetadata()); - DwarfPubTypesSection = Ctx->getWasmSection(".debug_pubtypes", SectionKind::getMetadata()); - - // Wasm use data section for LSDA. - // TODO Consider putting each function's exception table in a separate - // section, as in -function-sections, to facilitate lld's --gc-section. - LSDASection = Ctx->getWasmSection(".rodata.gcc_except_table", - SectionKind::getReadOnlyWithRel()); - - // TODO: Define more sections. -} - -void MCObjectFileInfo::initXCOFFMCObjectFileInfo(const Triple &T) { - // The default csect for program code. Functions without a specified section - // get placed into this csect. The choice of csect name is not a property of - // the ABI or object file format. For example, the XL compiler uses an unnamed - // csect for program code. - TextSection = Ctx->getXCOFFSection( - ".text", XCOFF::StorageMappingClass::XMC_PR, SectionKind::getText()); -} - -void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC, - MCContext &ctx, - bool LargeCodeModel) { - PositionIndependent = PIC; - Ctx = &ctx; - - // Common. - CommDirectiveSupportsAlignment = true; - SupportsWeakOmittedEHFrame = true; - SupportsCompactUnwindWithoutEHFrame = false; - OmitDwarfIfHaveCompactUnwind = false; - - FDECFIEncoding = dwarf::DW_EH_PE_absptr; - - CompactUnwindDwarfEHFrameOnly = 0; - - EHFrameSection = nullptr; // Created on demand. - CompactUnwindSection = nullptr; // Used only by selected targets. - DwarfAccelNamesSection = nullptr; // Used only by selected targets. - DwarfAccelObjCSection = nullptr; // Used only by selected targets. - DwarfAccelNamespaceSection = nullptr; // Used only by selected targets. - DwarfAccelTypesSection = nullptr; // Used only by selected targets. - - TT = TheTriple; - - switch (TT.getObjectFormat()) { - case Triple::MachO: - Env = IsMachO; - initMachOMCObjectFileInfo(TT); - break; - case Triple::COFF: - if (!TT.isOSWindows()) - report_fatal_error( - "Cannot initialize MC for non-Windows COFF object files."); - - Env = IsCOFF; - initCOFFMCObjectFileInfo(TT); - break; - case Triple::ELF: - Env = IsELF; - initELFMCObjectFileInfo(TT, LargeCodeModel); - break; - case Triple::Wasm: - Env = IsWasm; - initWasmMCObjectFileInfo(TT); - break; - case Triple::XCOFF: - Env = IsXCOFF; - initXCOFFMCObjectFileInfo(TT); - break; - case Triple::UnknownObjectFormat: - report_fatal_error("Cannot initialize MC for unknown object file format."); - break; - } -} - -MCSection *MCObjectFileInfo::getDwarfComdatSection(const char *Name, - uint64_t Hash) const { - switch (TT.getObjectFormat()) { - case Triple::ELF: - return Ctx->getELFSection(Name, ELF::SHT_PROGBITS, ELF::SHF_GROUP, 0, - utostr(Hash)); - case Triple::MachO: - case Triple::COFF: - case Triple::Wasm: - case Triple::XCOFF: - case Triple::UnknownObjectFormat: - report_fatal_error("Cannot get DWARF comdat section for this object file " - "format: not implemented."); - break; - } - llvm_unreachable("Unknown ObjectFormatType"); -} - -MCSection * -MCObjectFileInfo::getStackSizesSection(const MCSection &TextSec) const { - if (Env != IsELF) - return StackSizesSection; - - const MCSectionELF &ElfSec = static_cast<const MCSectionELF &>(TextSec); - unsigned Flags = ELF::SHF_LINK_ORDER; - StringRef GroupName; - if (const MCSymbol *Group = ElfSec.getGroup()) { - GroupName = Group->getName(); - Flags |= ELF::SHF_GROUP; - } - - const MCSymbol *Link = TextSec.getBeginSymbol(); - auto It = StackSizesUniquing.insert({Link, StackSizesUniquing.size()}); - unsigned UniqueID = It.first->second; - - return Ctx->getELFSection(".stack_sizes", ELF::SHT_PROGBITS, Flags, 0, - GroupName, UniqueID, cast<MCSymbolELF>(Link)); -} diff --git a/contrib/llvm/lib/MC/MCObjectStreamer.cpp b/contrib/llvm/lib/MC/MCObjectStreamer.cpp deleted file mode 100644 index 1587d8498666..000000000000 --- a/contrib/llvm/lib/MC/MCObjectStreamer.cpp +++ /dev/null @@ -1,731 +0,0 @@ -//===- lib/MC/MCObjectStreamer.cpp - Object File MCStreamer Interface -----===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCObjectStreamer.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCCodeEmitter.h" -#include "llvm/MC/MCCodeView.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDwarf.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/SourceMgr.h" -using namespace llvm; - -MCObjectStreamer::MCObjectStreamer(MCContext &Context, - std::unique_ptr<MCAsmBackend> TAB, - std::unique_ptr<MCObjectWriter> OW, - std::unique_ptr<MCCodeEmitter> Emitter) - : MCStreamer(Context), - Assembler(llvm::make_unique<MCAssembler>( - Context, std::move(TAB), std::move(Emitter), std::move(OW))), - EmitEHFrame(true), EmitDebugFrame(false) {} - -MCObjectStreamer::~MCObjectStreamer() {} - -// AssemblerPtr is used for evaluation of expressions and causes -// difference between asm and object outputs. Return nullptr to in -// inline asm mode to limit divergence to assembly inputs. -MCAssembler *MCObjectStreamer::getAssemblerPtr() { - if (getUseAssemblerInfoForParsing()) - return Assembler.get(); - return nullptr; -} - -void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) { - if (PendingLabels.empty()) - return; - if (!F) { - F = new MCDataFragment(); - MCSection *CurSection = getCurrentSectionOnly(); - CurSection->getFragmentList().insert(CurInsertionPoint, F); - F->setParent(CurSection); - } - for (MCSymbol *Sym : PendingLabels) { - Sym->setFragment(F); - Sym->setOffset(FOffset); - } - PendingLabels.clear(); -} - -// When fixup's offset is a forward declared label, e.g.: -// -// .reloc 1f, R_MIPS_JALR, foo -// 1: nop -// -// postpone adding it to Fixups vector until the label is defined and its offset -// is known. -void MCObjectStreamer::resolvePendingFixups() { - for (PendingMCFixup &PendingFixup : PendingFixups) { - if (!PendingFixup.Sym || PendingFixup.Sym->isUndefined ()) { - getContext().reportError(PendingFixup.Fixup.getLoc(), - "unresolved relocation offset"); - continue; - } - flushPendingLabels(PendingFixup.DF, PendingFixup.DF->getContents().size()); - PendingFixup.Fixup.setOffset(PendingFixup.Sym->getOffset()); - PendingFixup.DF->getFixups().push_back(PendingFixup.Fixup); - } - PendingFixups.clear(); -} - -// As a compile-time optimization, avoid allocating and evaluating an MCExpr -// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment. -static Optional<uint64_t> -absoluteSymbolDiff(MCAssembler &Asm, const MCSymbol *Hi, const MCSymbol *Lo) { - assert(Hi && Lo); - if (Asm.getBackendPtr()->requiresDiffExpressionRelocations()) - return None; - - if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() || - Hi->isVariable() || Lo->isVariable()) - return None; - - return Hi->getOffset() - Lo->getOffset(); -} - -void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi, - const MCSymbol *Lo, - unsigned Size) { - if (Optional<uint64_t> Diff = absoluteSymbolDiff(getAssembler(), Hi, Lo)) { - EmitIntValue(*Diff, Size); - return; - } - MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size); -} - -void MCObjectStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi, - const MCSymbol *Lo) { - if (Optional<uint64_t> Diff = absoluteSymbolDiff(getAssembler(), Hi, Lo)) { - EmitULEB128IntValue(*Diff); - return; - } - MCStreamer::emitAbsoluteSymbolDiffAsULEB128(Hi, Lo); -} - -void MCObjectStreamer::reset() { - if (Assembler) - Assembler->reset(); - CurInsertionPoint = MCSection::iterator(); - EmitEHFrame = true; - EmitDebugFrame = false; - PendingLabels.clear(); - MCStreamer::reset(); -} - -void MCObjectStreamer::EmitFrames(MCAsmBackend *MAB) { - if (!getNumFrameInfos()) - return; - - if (EmitEHFrame) - MCDwarfFrameEmitter::Emit(*this, MAB, true); - - if (EmitDebugFrame) - MCDwarfFrameEmitter::Emit(*this, MAB, false); -} - -MCFragment *MCObjectStreamer::getCurrentFragment() const { - assert(getCurrentSectionOnly() && "No current section!"); - - if (CurInsertionPoint != getCurrentSectionOnly()->getFragmentList().begin()) - return &*std::prev(CurInsertionPoint); - - return nullptr; -} - -static bool CanReuseDataFragment(const MCDataFragment &F, - const MCAssembler &Assembler, - const MCSubtargetInfo *STI) { - if (!F.hasInstructions()) - return true; - // When bundling is enabled, we don't want to add data to a fragment that - // already has instructions (see MCELFStreamer::EmitInstToData for details) - if (Assembler.isBundlingEnabled()) - return Assembler.getRelaxAll(); - // If the subtarget is changed mid fragment we start a new fragment to record - // the new STI. - return !STI || F.getSubtargetInfo() == STI; -} - -MCDataFragment * -MCObjectStreamer::getOrCreateDataFragment(const MCSubtargetInfo *STI) { - MCDataFragment *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment()); - if (!F || !CanReuseDataFragment(*F, *Assembler, STI)) { - F = new MCDataFragment(); - insert(F); - } - return F; -} - -MCPaddingFragment *MCObjectStreamer::getOrCreatePaddingFragment() { - MCPaddingFragment *F = - dyn_cast_or_null<MCPaddingFragment>(getCurrentFragment()); - if (!F) { - F = new MCPaddingFragment(); - insert(F); - } - return F; -} - -void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) { - Assembler->registerSymbol(Sym); -} - -void MCObjectStreamer::EmitCFISections(bool EH, bool Debug) { - MCStreamer::EmitCFISections(EH, Debug); - EmitEHFrame = EH; - EmitDebugFrame = Debug; -} - -void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, - SMLoc Loc) { - MCStreamer::EmitValueImpl(Value, Size, Loc); - MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - - MCDwarfLineEntry::Make(this, getCurrentSectionOnly()); - - // Avoid fixups when possible. - int64_t AbsValue; - if (Value->evaluateAsAbsolute(AbsValue, getAssemblerPtr())) { - if (!isUIntN(8 * Size, AbsValue) && !isIntN(8 * Size, AbsValue)) { - getContext().reportError( - Loc, "value evaluated as " + Twine(AbsValue) + " is out of range."); - return; - } - EmitIntValue(AbsValue, Size); - return; - } - DF->getFixups().push_back( - MCFixup::create(DF->getContents().size(), Value, - MCFixup::getKindForSize(Size, false), Loc)); - DF->getContents().resize(DF->getContents().size() + Size, 0); -} - -MCSymbol *MCObjectStreamer::EmitCFILabel() { - MCSymbol *Label = getContext().createTempSymbol("cfi", true); - EmitLabel(Label); - return Label; -} - -void MCObjectStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { - // We need to create a local symbol to avoid relocations. - Frame.Begin = getContext().createTempSymbol(); - EmitLabel(Frame.Begin); -} - -void MCObjectStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { - Frame.End = getContext().createTempSymbol(); - EmitLabel(Frame.End); -} - -void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) { - MCStreamer::EmitLabel(Symbol, Loc); - - getAssembler().registerSymbol(*Symbol); - - // If there is a current fragment, mark the symbol as pointing into it. - // Otherwise queue the label and set its fragment pointer when we emit the - // next fragment. - auto *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment()); - if (F && !(getAssembler().isBundlingEnabled() && - getAssembler().getRelaxAll())) { - Symbol->setFragment(F); - Symbol->setOffset(F->getContents().size()); - } else { - PendingLabels.push_back(Symbol); - } -} - -void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F) { - MCStreamer::EmitLabel(Symbol, Loc); - getAssembler().registerSymbol(*Symbol); - auto *DF = dyn_cast_or_null<MCDataFragment>(F); - if (DF) - Symbol->setFragment(F); - else - PendingLabels.push_back(Symbol); -} - -void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) { - int64_t IntValue; - if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) { - EmitULEB128IntValue(IntValue); - return; - } - insert(new MCLEBFragment(*Value, false)); -} - -void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value) { - int64_t IntValue; - if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) { - EmitSLEB128IntValue(IntValue); - return; - } - insert(new MCLEBFragment(*Value, true)); -} - -void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias, - const MCSymbol *Symbol) { - report_fatal_error("This file format doesn't support weak aliases."); -} - -void MCObjectStreamer::ChangeSection(MCSection *Section, - const MCExpr *Subsection) { - changeSectionImpl(Section, Subsection); -} - -bool MCObjectStreamer::changeSectionImpl(MCSection *Section, - const MCExpr *Subsection) { - assert(Section && "Cannot switch to a null section!"); - flushPendingLabels(nullptr); - getContext().clearDwarfLocSeen(); - - bool Created = getAssembler().registerSection(*Section); - - int64_t IntSubsection = 0; - if (Subsection && - !Subsection->evaluateAsAbsolute(IntSubsection, getAssemblerPtr())) - report_fatal_error("Cannot evaluate subsection number"); - if (IntSubsection < 0 || IntSubsection > 8192) - report_fatal_error("Subsection number out of range"); - CurInsertionPoint = - Section->getSubsectionInsertionPoint(unsigned(IntSubsection)); - return Created; -} - -void MCObjectStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { - getAssembler().registerSymbol(*Symbol); - MCStreamer::EmitAssignment(Symbol, Value); -} - -bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) const { - return Sec.hasInstructions(); -} - -void MCObjectStreamer::EmitInstruction(const MCInst &Inst, - const MCSubtargetInfo &STI) { - getAssembler().getBackend().handleCodePaddingInstructionBegin(Inst); - EmitInstructionImpl(Inst, STI); - getAssembler().getBackend().handleCodePaddingInstructionEnd(Inst); -} - -void MCObjectStreamer::EmitInstructionImpl(const MCInst &Inst, - const MCSubtargetInfo &STI) { - MCStreamer::EmitInstruction(Inst, STI); - - MCSection *Sec = getCurrentSectionOnly(); - Sec->setHasInstructions(true); - - // Now that a machine instruction has been assembled into this section, make - // a line entry for any .loc directive that has been seen. - MCDwarfLineEntry::Make(this, getCurrentSectionOnly()); - - // If this instruction doesn't need relaxation, just emit it as data. - MCAssembler &Assembler = getAssembler(); - if (!Assembler.getBackend().mayNeedRelaxation(Inst, STI)) { - EmitInstToData(Inst, STI); - return; - } - - // Otherwise, relax and emit it as data if either: - // - The RelaxAll flag was passed - // - Bundling is enabled and this instruction is inside a bundle-locked - // group. We want to emit all such instructions into the same data - // fragment. - if (Assembler.getRelaxAll() || - (Assembler.isBundlingEnabled() && Sec->isBundleLocked())) { - MCInst Relaxed; - getAssembler().getBackend().relaxInstruction(Inst, STI, Relaxed); - while (getAssembler().getBackend().mayNeedRelaxation(Relaxed, STI)) - getAssembler().getBackend().relaxInstruction(Relaxed, STI, Relaxed); - EmitInstToData(Relaxed, STI); - return; - } - - // Otherwise emit to a separate fragment. - EmitInstToFragment(Inst, STI); -} - -void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst, - const MCSubtargetInfo &STI) { - if (getAssembler().getRelaxAll() && getAssembler().isBundlingEnabled()) - llvm_unreachable("All instructions should have already been relaxed"); - - // Always create a new, separate fragment here, because its size can change - // during relaxation. - MCRelaxableFragment *IF = new MCRelaxableFragment(Inst, STI); - insert(IF); - - SmallString<128> Code; - raw_svector_ostream VecOS(Code); - getAssembler().getEmitter().encodeInstruction(Inst, VecOS, IF->getFixups(), - STI); - IF->getContents().append(Code.begin(), Code.end()); -} - -#ifndef NDEBUG -static const char *const BundlingNotImplementedMsg = - "Aligned bundling is not implemented for this object format"; -#endif - -void MCObjectStreamer::EmitBundleAlignMode(unsigned AlignPow2) { - llvm_unreachable(BundlingNotImplementedMsg); -} - -void MCObjectStreamer::EmitBundleLock(bool AlignToEnd) { - llvm_unreachable(BundlingNotImplementedMsg); -} - -void MCObjectStreamer::EmitBundleUnlock() { - llvm_unreachable(BundlingNotImplementedMsg); -} - -void MCObjectStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, - unsigned Column, unsigned Flags, - unsigned Isa, - unsigned Discriminator, - StringRef FileName) { - // In case we see two .loc directives in a row, make sure the - // first one gets a line entry. - MCDwarfLineEntry::Make(this, getCurrentSectionOnly()); - - this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, - Isa, Discriminator, FileName); -} - -static const MCExpr *buildSymbolDiff(MCObjectStreamer &OS, const MCSymbol *A, - const MCSymbol *B) { - MCContext &Context = OS.getContext(); - MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; - const MCExpr *ARef = MCSymbolRefExpr::create(A, Variant, Context); - const MCExpr *BRef = MCSymbolRefExpr::create(B, Variant, Context); - const MCExpr *AddrDelta = - MCBinaryExpr::create(MCBinaryExpr::Sub, ARef, BRef, Context); - return AddrDelta; -} - -static void emitDwarfSetLineAddr(MCObjectStreamer &OS, - MCDwarfLineTableParams Params, - int64_t LineDelta, const MCSymbol *Label, - int PointerSize) { - // emit the sequence to set the address - OS.EmitIntValue(dwarf::DW_LNS_extended_op, 1); - OS.EmitULEB128IntValue(PointerSize + 1); - OS.EmitIntValue(dwarf::DW_LNE_set_address, 1); - OS.EmitSymbolValue(Label, PointerSize); - - // emit the sequence for the LineDelta (from 1) and a zero address delta. - MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0); -} - -void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta, - const MCSymbol *LastLabel, - const MCSymbol *Label, - unsigned PointerSize) { - if (!LastLabel) { - emitDwarfSetLineAddr(*this, Assembler->getDWARFLinetableParams(), LineDelta, - Label, PointerSize); - return; - } - const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel); - int64_t Res; - if (AddrDelta->evaluateAsAbsolute(Res, getAssemblerPtr())) { - MCDwarfLineAddr::Emit(this, Assembler->getDWARFLinetableParams(), LineDelta, - Res); - return; - } - insert(new MCDwarfLineAddrFragment(LineDelta, *AddrDelta)); -} - -void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, - const MCSymbol *Label) { - const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel); - int64_t Res; - if (AddrDelta->evaluateAsAbsolute(Res, getAssemblerPtr())) { - MCDwarfFrameEmitter::EmitAdvanceLoc(*this, Res); - return; - } - insert(new MCDwarfCallFrameFragment(*AddrDelta)); -} - -void MCObjectStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, - unsigned Line, unsigned Column, - bool PrologueEnd, bool IsStmt, - StringRef FileName, SMLoc Loc) { - // Validate the directive. - if (!checkCVLocSection(FunctionId, FileNo, Loc)) - return; - - // Emit a label at the current position and record it in the CodeViewContext. - MCSymbol *LineSym = getContext().createTempSymbol(); - EmitLabel(LineSym); - getContext().getCVContext().recordCVLoc(getContext(), LineSym, FunctionId, - FileNo, Line, Column, PrologueEnd, - IsStmt); -} - -void MCObjectStreamer::EmitCVLinetableDirective(unsigned FunctionId, - const MCSymbol *Begin, - const MCSymbol *End) { - getContext().getCVContext().emitLineTableForFunction(*this, FunctionId, Begin, - End); - this->MCStreamer::EmitCVLinetableDirective(FunctionId, Begin, End); -} - -void MCObjectStreamer::EmitCVInlineLinetableDirective( - unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, - const MCSymbol *FnStartSym, const MCSymbol *FnEndSym) { - getContext().getCVContext().emitInlineLineTableForFunction( - *this, PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, - FnEndSym); - this->MCStreamer::EmitCVInlineLinetableDirective( - PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym); -} - -void MCObjectStreamer::EmitCVDefRangeDirective( - ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, - StringRef FixedSizePortion) { - MCFragment *Frag = - getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion); - // Attach labels that were pending before we created the defrange fragment to - // the beginning of the new fragment. - flushPendingLabels(Frag, 0); - this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion); -} - -void MCObjectStreamer::EmitCVStringTableDirective() { - getContext().getCVContext().emitStringTable(*this); -} -void MCObjectStreamer::EmitCVFileChecksumsDirective() { - getContext().getCVContext().emitFileChecksums(*this); -} - -void MCObjectStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) { - getContext().getCVContext().emitFileChecksumOffset(*this, FileNo); -} - -void MCObjectStreamer::EmitBytes(StringRef Data) { - MCDwarfLineEntry::Make(this, getCurrentSectionOnly()); - MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - DF->getContents().append(Data.begin(), Data.end()); - - // EmitBytes might not cover all possible ways we emit data (or could be used - // to emit executable code in some cases), but is the best method we have - // right now for checking this. - MCSection *Sec = getCurrentSectionOnly(); - Sec->setHasData(true); -} - -void MCObjectStreamer::EmitValueToAlignment(unsigned ByteAlignment, - int64_t Value, - unsigned ValueSize, - unsigned MaxBytesToEmit) { - if (MaxBytesToEmit == 0) - MaxBytesToEmit = ByteAlignment; - insert(new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit)); - - // Update the maximum alignment on the current section if necessary. - MCSection *CurSec = getCurrentSectionOnly(); - if (ByteAlignment > CurSec->getAlignment()) - CurSec->setAlignment(ByteAlignment); -} - -void MCObjectStreamer::EmitCodeAlignment(unsigned ByteAlignment, - unsigned MaxBytesToEmit) { - EmitValueToAlignment(ByteAlignment, 0, 1, MaxBytesToEmit); - cast<MCAlignFragment>(getCurrentFragment())->setEmitNops(true); -} - -void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset, - unsigned char Value, - SMLoc Loc) { - insert(new MCOrgFragment(*Offset, Value, Loc)); -} - -void MCObjectStreamer::EmitCodePaddingBasicBlockStart( - const MCCodePaddingContext &Context) { - getAssembler().getBackend().handleCodePaddingBasicBlockStart(this, Context); -} - -void MCObjectStreamer::EmitCodePaddingBasicBlockEnd( - const MCCodePaddingContext &Context) { - getAssembler().getBackend().handleCodePaddingBasicBlockEnd(Context); -} - -// Associate DTPRel32 fixup with data and resize data area -void MCObjectStreamer::EmitDTPRel32Value(const MCExpr *Value) { - MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - - DF->getFixups().push_back(MCFixup::create(DF->getContents().size(), - Value, FK_DTPRel_4)); - DF->getContents().resize(DF->getContents().size() + 4, 0); -} - -// Associate DTPRel64 fixup with data and resize data area -void MCObjectStreamer::EmitDTPRel64Value(const MCExpr *Value) { - MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - - DF->getFixups().push_back(MCFixup::create(DF->getContents().size(), - Value, FK_DTPRel_8)); - DF->getContents().resize(DF->getContents().size() + 8, 0); -} - -// Associate TPRel32 fixup with data and resize data area -void MCObjectStreamer::EmitTPRel32Value(const MCExpr *Value) { - MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - - DF->getFixups().push_back(MCFixup::create(DF->getContents().size(), - Value, FK_TPRel_4)); - DF->getContents().resize(DF->getContents().size() + 4, 0); -} - -// Associate TPRel64 fixup with data and resize data area -void MCObjectStreamer::EmitTPRel64Value(const MCExpr *Value) { - MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - - DF->getFixups().push_back(MCFixup::create(DF->getContents().size(), - Value, FK_TPRel_8)); - DF->getContents().resize(DF->getContents().size() + 8, 0); -} - -// Associate GPRel32 fixup with data and resize data area -void MCObjectStreamer::EmitGPRel32Value(const MCExpr *Value) { - MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - - DF->getFixups().push_back( - MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4)); - DF->getContents().resize(DF->getContents().size() + 4, 0); -} - -// Associate GPRel64 fixup with data and resize data area -void MCObjectStreamer::EmitGPRel64Value(const MCExpr *Value) { - MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - - DF->getFixups().push_back( - MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4)); - DF->getContents().resize(DF->getContents().size() + 8, 0); -} - -bool MCObjectStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name, - const MCExpr *Expr, SMLoc Loc, - const MCSubtargetInfo &STI) { - Optional<MCFixupKind> MaybeKind = Assembler->getBackend().getFixupKind(Name); - if (!MaybeKind.hasValue()) - return true; - - MCFixupKind Kind = *MaybeKind; - - if (Expr == nullptr) - Expr = - MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext()); - - MCDataFragment *DF = getOrCreateDataFragment(&STI); - flushPendingLabels(DF, DF->getContents().size()); - - int64_t OffsetValue; - if (Offset.evaluateAsAbsolute(OffsetValue)) { - if (OffsetValue < 0) - llvm_unreachable(".reloc offset is negative"); - DF->getFixups().push_back(MCFixup::create(OffsetValue, Expr, Kind, Loc)); - return false; - } - - if (Offset.getKind() != llvm::MCExpr::SymbolRef) - llvm_unreachable(".reloc offset is not absolute nor a label"); - - const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(Offset); - if (SRE.getSymbol().isDefined()) { - DF->getFixups().push_back(MCFixup::create(SRE.getSymbol().getOffset(), - Expr, Kind, Loc)); - return false; - } - - PendingFixups.emplace_back(&SRE.getSymbol(), DF, - MCFixup::create(-1, Expr, Kind, Loc)); - return false; -} - -void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue, - SMLoc Loc) { - MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - - assert(getCurrentSectionOnly() && "need a section"); - insert(new MCFillFragment(FillValue, 1, NumBytes, Loc)); -} - -void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size, - int64_t Expr, SMLoc Loc) { - int64_t IntNumValues; - // Do additional checking now if we can resolve the value. - if (NumValues.evaluateAsAbsolute(IntNumValues, getAssemblerPtr())) { - if (IntNumValues < 0) { - getContext().getSourceManager()->PrintMessage( - Loc, SourceMgr::DK_Warning, - "'.fill' directive with negative repeat count has no effect"); - return; - } - // Emit now if we can for better errors. - int64_t NonZeroSize = Size > 4 ? 4 : Size; - Expr &= ~0ULL >> (64 - NonZeroSize * 8); - for (uint64_t i = 0, e = IntNumValues; i != e; ++i) { - EmitIntValue(Expr, NonZeroSize); - if (NonZeroSize < Size) - EmitIntValue(0, Size - NonZeroSize); - } - return; - } - - // Otherwise emit as fragment. - MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - - assert(getCurrentSectionOnly() && "need a section"); - insert(new MCFillFragment(Expr, Size, NumValues, Loc)); -} - -void MCObjectStreamer::EmitFileDirective(StringRef Filename) { - getAssembler().addFileName(Filename); -} - -void MCObjectStreamer::EmitAddrsig() { - getAssembler().getWriter().emitAddrsigSection(); -} - -void MCObjectStreamer::EmitAddrsigSym(const MCSymbol *Sym) { - getAssembler().registerSymbol(*Sym); - getAssembler().getWriter().addAddrsigSymbol(Sym); -} - -void MCObjectStreamer::FinishImpl() { - getContext().RemapDebugPaths(); - - // If we are generating dwarf for assembly source files dump out the sections. - if (getContext().getGenDwarfForAssembly()) - MCGenDwarfInfo::Emit(this); - - // Dump out the dwarf file & directory tables and line tables. - MCDwarfLineTable::Emit(this, getAssembler().getDWARFLinetableParams()); - - flushPendingLabels(); - resolvePendingFixups(); - getAssembler().Finish(); -} diff --git a/contrib/llvm/lib/MC/MCObjectWriter.cpp b/contrib/llvm/lib/MC/MCObjectWriter.cpp deleted file mode 100644 index a058bbe0ba0b..000000000000 --- a/contrib/llvm/lib/MC/MCObjectWriter.cpp +++ /dev/null @@ -1,52 +0,0 @@ -//===- lib/MC/MCObjectWriter.cpp - MCObjectWriter implementation ----------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFragment.h" -#include "llvm/MC/MCSymbol.h" - -using namespace llvm; - -MCObjectWriter::~MCObjectWriter() = default; - -bool MCObjectWriter::isSymbolRefDifferenceFullyResolved( - const MCAssembler &Asm, const MCSymbolRefExpr *A, const MCSymbolRefExpr *B, - bool InSet) const { - // Modified symbol references cannot be resolved. - if (A->getKind() != MCSymbolRefExpr::VK_None || - B->getKind() != MCSymbolRefExpr::VK_None) - return false; - - const MCSymbol &SA = A->getSymbol(); - const MCSymbol &SB = B->getSymbol(); - if (SA.isUndefined() || SB.isUndefined()) - return false; - - if (!SA.getFragment() || !SB.getFragment()) - return false; - - return isSymbolRefDifferenceFullyResolvedImpl(Asm, SA, SB, InSet); -} - -bool MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl( - const MCAssembler &Asm, const MCSymbol &A, const MCSymbol &B, - bool InSet) const { - return isSymbolRefDifferenceFullyResolvedImpl(Asm, A, *B.getFragment(), InSet, - false); -} - -bool MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl( - const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB, - bool InSet, bool IsPCRel) const { - const MCSection &SecA = SymA.getSection(); - const MCSection &SecB = *FB.getParent(); - // On ELF and COFF A - B is absolute if A and B are in the same section. - return &SecA == &SecB; -} diff --git a/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp b/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp deleted file mode 100644 index 9155ae05d29d..000000000000 --- a/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp +++ /dev/null @@ -1,755 +0,0 @@ -//===- AsmLexer.cpp - Lexer for Assembly Files ----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This class implements the lexer for assembly files. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCParser/AsmLexer.h" -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCParser/MCAsmLexer.h" -#include "llvm/Support/SMLoc.h" -#include "llvm/Support/SaveAndRestore.h" -#include <cassert> -#include <cctype> -#include <cstdio> -#include <cstring> -#include <string> -#include <tuple> -#include <utility> - -using namespace llvm; - -AsmLexer::AsmLexer(const MCAsmInfo &MAI) : MAI(MAI) { - AllowAtInIdentifier = !StringRef(MAI.getCommentString()).startswith("@"); -} - -AsmLexer::~AsmLexer() = default; - -void AsmLexer::setBuffer(StringRef Buf, const char *ptr) { - CurBuf = Buf; - - if (ptr) - CurPtr = ptr; - else - CurPtr = CurBuf.begin(); - - TokStart = nullptr; -} - -/// ReturnError - Set the error to the specified string at the specified -/// location. This is defined to always return AsmToken::Error. -AsmToken AsmLexer::ReturnError(const char *Loc, const std::string &Msg) { - SetError(SMLoc::getFromPointer(Loc), Msg); - - return AsmToken(AsmToken::Error, StringRef(Loc, CurPtr - Loc)); -} - -int AsmLexer::getNextChar() { - if (CurPtr == CurBuf.end()) - return EOF; - return (unsigned char)*CurPtr++; -} - -/// The leading integral digit sequence and dot should have already been -/// consumed, some or all of the fractional digit sequence *can* have been -/// consumed. -AsmToken AsmLexer::LexFloatLiteral() { - // Skip the fractional digit sequence. - while (isDigit(*CurPtr)) - ++CurPtr; - - if (*CurPtr == '-' || *CurPtr == '+') - return ReturnError(CurPtr, "Invalid sign in float literal"); - - // Check for exponent - if ((*CurPtr == 'e' || *CurPtr == 'E')) { - ++CurPtr; - - if (*CurPtr == '-' || *CurPtr == '+') - ++CurPtr; - - while (isDigit(*CurPtr)) - ++CurPtr; - } - - return AsmToken(AsmToken::Real, - StringRef(TokStart, CurPtr - TokStart)); -} - -/// LexHexFloatLiteral matches essentially (.[0-9a-fA-F]*)?[pP][+-]?[0-9a-fA-F]+ -/// while making sure there are enough actual digits around for the constant to -/// be valid. -/// -/// The leading "0x[0-9a-fA-F]*" (i.e. integer part) has already been consumed -/// before we get here. -AsmToken AsmLexer::LexHexFloatLiteral(bool NoIntDigits) { - assert((*CurPtr == 'p' || *CurPtr == 'P' || *CurPtr == '.') && - "unexpected parse state in floating hex"); - bool NoFracDigits = true; - - // Skip the fractional part if there is one - if (*CurPtr == '.') { - ++CurPtr; - - const char *FracStart = CurPtr; - while (isHexDigit(*CurPtr)) - ++CurPtr; - - NoFracDigits = CurPtr == FracStart; - } - - if (NoIntDigits && NoFracDigits) - return ReturnError(TokStart, "invalid hexadecimal floating-point constant: " - "expected at least one significand digit"); - - // Make sure we do have some kind of proper exponent part - if (*CurPtr != 'p' && *CurPtr != 'P') - return ReturnError(TokStart, "invalid hexadecimal floating-point constant: " - "expected exponent part 'p'"); - ++CurPtr; - - if (*CurPtr == '+' || *CurPtr == '-') - ++CurPtr; - - // N.b. exponent digits are *not* hex - const char *ExpStart = CurPtr; - while (isDigit(*CurPtr)) - ++CurPtr; - - if (CurPtr == ExpStart) - return ReturnError(TokStart, "invalid hexadecimal floating-point constant: " - "expected at least one exponent digit"); - - return AsmToken(AsmToken::Real, StringRef(TokStart, CurPtr - TokStart)); -} - -/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@?]* -static bool IsIdentifierChar(char c, bool AllowAt) { - return isAlnum(c) || c == '_' || c == '$' || c == '.' || - (c == '@' && AllowAt) || c == '?'; -} - -AsmToken AsmLexer::LexIdentifier() { - // Check for floating point literals. - if (CurPtr[-1] == '.' && isDigit(*CurPtr)) { - // Disambiguate a .1243foo identifier from a floating literal. - while (isDigit(*CurPtr)) - ++CurPtr; - - if (!IsIdentifierChar(*CurPtr, AllowAtInIdentifier) || - *CurPtr == 'e' || *CurPtr == 'E') - return LexFloatLiteral(); - } - - while (IsIdentifierChar(*CurPtr, AllowAtInIdentifier)) - ++CurPtr; - - // Handle . as a special case. - if (CurPtr == TokStart+1 && TokStart[0] == '.') - return AsmToken(AsmToken::Dot, StringRef(TokStart, 1)); - - return AsmToken(AsmToken::Identifier, StringRef(TokStart, CurPtr - TokStart)); -} - -/// LexSlash: Slash: / -/// C-Style Comment: /* ... */ -AsmToken AsmLexer::LexSlash() { - switch (*CurPtr) { - case '*': - IsAtStartOfStatement = false; - break; // C style comment. - case '/': - ++CurPtr; - return LexLineComment(); - default: - IsAtStartOfStatement = false; - return AsmToken(AsmToken::Slash, StringRef(TokStart, 1)); - } - - // C Style comment. - ++CurPtr; // skip the star. - const char *CommentTextStart = CurPtr; - while (CurPtr != CurBuf.end()) { - switch (*CurPtr++) { - case '*': - // End of the comment? - if (*CurPtr != '/') - break; - // If we have a CommentConsumer, notify it about the comment. - if (CommentConsumer) { - CommentConsumer->HandleComment( - SMLoc::getFromPointer(CommentTextStart), - StringRef(CommentTextStart, CurPtr - 1 - CommentTextStart)); - } - ++CurPtr; // End the */. - return AsmToken(AsmToken::Comment, - StringRef(TokStart, CurPtr - TokStart)); - } - } - return ReturnError(TokStart, "unterminated comment"); -} - -/// LexLineComment: Comment: #[^\n]* -/// : //[^\n]* -AsmToken AsmLexer::LexLineComment() { - // Mark This as an end of statement with a body of the - // comment. While it would be nicer to leave this two tokens, - // backwards compatability with TargetParsers makes keeping this in this form - // better. - const char *CommentTextStart = CurPtr; - int CurChar = getNextChar(); - while (CurChar != '\n' && CurChar != '\r' && CurChar != EOF) - CurChar = getNextChar(); - if (CurChar == '\r' && CurPtr != CurBuf.end() && *CurPtr == '\n') - ++CurPtr; - - // If we have a CommentConsumer, notify it about the comment. - if (CommentConsumer) { - CommentConsumer->HandleComment( - SMLoc::getFromPointer(CommentTextStart), - StringRef(CommentTextStart, CurPtr - 1 - CommentTextStart)); - } - - IsAtStartOfLine = true; - // This is a whole line comment. leave newline - if (IsAtStartOfStatement) - return AsmToken(AsmToken::EndOfStatement, - StringRef(TokStart, CurPtr - TokStart)); - IsAtStartOfStatement = true; - - return AsmToken(AsmToken::EndOfStatement, - StringRef(TokStart, CurPtr - 1 - TokStart)); -} - -static void SkipIgnoredIntegerSuffix(const char *&CurPtr) { - // Skip ULL, UL, U, L and LL suffices. - if (CurPtr[0] == 'U') - ++CurPtr; - if (CurPtr[0] == 'L') - ++CurPtr; - if (CurPtr[0] == 'L') - ++CurPtr; -} - -// Look ahead to search for first non-hex digit, if it's [hH], then we treat the -// integer as a hexadecimal, possibly with leading zeroes. -static unsigned doHexLookAhead(const char *&CurPtr, unsigned DefaultRadix, - bool LexHex) { - const char *FirstNonDec = nullptr; - const char *LookAhead = CurPtr; - while (true) { - if (isDigit(*LookAhead)) { - ++LookAhead; - } else { - if (!FirstNonDec) - FirstNonDec = LookAhead; - - // Keep going if we are looking for a 'h' suffix. - if (LexHex && isHexDigit(*LookAhead)) - ++LookAhead; - else - break; - } - } - bool isHex = LexHex && (*LookAhead == 'h' || *LookAhead == 'H'); - CurPtr = isHex || !FirstNonDec ? LookAhead : FirstNonDec; - if (isHex) - return 16; - return DefaultRadix; -} - -static AsmToken intToken(StringRef Ref, APInt &Value) -{ - if (Value.isIntN(64)) - return AsmToken(AsmToken::Integer, Ref, Value); - return AsmToken(AsmToken::BigNum, Ref, Value); -} - -/// LexDigit: First character is [0-9]. -/// Local Label: [0-9][:] -/// Forward/Backward Label: [0-9][fb] -/// Binary integer: 0b[01]+ -/// Octal integer: 0[0-7]+ -/// Hex integer: 0x[0-9a-fA-F]+ or [0x]?[0-9][0-9a-fA-F]*[hH] -/// Decimal integer: [1-9][0-9]* -AsmToken AsmLexer::LexDigit() { - // MASM-flavor binary integer: [01]+[bB] - // MASM-flavor hexadecimal integer: [0-9][0-9a-fA-F]*[hH] - if (LexMasmIntegers && isdigit(CurPtr[-1])) { - const char *FirstNonBinary = (CurPtr[-1] != '0' && CurPtr[-1] != '1') ? - CurPtr - 1 : nullptr; - const char *OldCurPtr = CurPtr; - while (isHexDigit(*CurPtr)) { - if (*CurPtr != '0' && *CurPtr != '1' && !FirstNonBinary) - FirstNonBinary = CurPtr; - ++CurPtr; - } - - unsigned Radix = 0; - if (*CurPtr == 'h' || *CurPtr == 'H') { - // hexadecimal number - ++CurPtr; - Radix = 16; - } else if (FirstNonBinary && FirstNonBinary + 1 == CurPtr && - (*FirstNonBinary == 'b' || *FirstNonBinary == 'B')) - Radix = 2; - - if (Radix == 2 || Radix == 16) { - StringRef Result(TokStart, CurPtr - TokStart); - APInt Value(128, 0, true); - - if (Result.drop_back().getAsInteger(Radix, Value)) - return ReturnError(TokStart, Radix == 2 ? "invalid binary number" : - "invalid hexdecimal number"); - - // MSVC accepts and ignores type suffices on integer literals. - SkipIgnoredIntegerSuffix(CurPtr); - - return intToken(Result, Value); - } - - // octal/decimal integers, or floating point numbers, fall through - CurPtr = OldCurPtr; - } - - // Decimal integer: [1-9][0-9]* - if (CurPtr[-1] != '0' || CurPtr[0] == '.') { - unsigned Radix = doHexLookAhead(CurPtr, 10, LexMasmIntegers); - bool isHex = Radix == 16; - // Check for floating point literals. - if (!isHex && (*CurPtr == '.' || *CurPtr == 'e' || *CurPtr == 'E')) { - if (*CurPtr == '.') - ++CurPtr; - return LexFloatLiteral(); - } - - StringRef Result(TokStart, CurPtr - TokStart); - - APInt Value(128, 0, true); - if (Result.getAsInteger(Radix, Value)) - return ReturnError(TokStart, !isHex ? "invalid decimal number" : - "invalid hexdecimal number"); - - // Consume the [hH]. - if (LexMasmIntegers && Radix == 16) - ++CurPtr; - - // The darwin/x86 (and x86-64) assembler accepts and ignores type - // suffices on integer literals. - SkipIgnoredIntegerSuffix(CurPtr); - - return intToken(Result, Value); - } - - if (!LexMasmIntegers && ((*CurPtr == 'b') || (*CurPtr == 'B'))) { - ++CurPtr; - // See if we actually have "0b" as part of something like "jmp 0b\n" - if (!isDigit(CurPtr[0])) { - --CurPtr; - StringRef Result(TokStart, CurPtr - TokStart); - return AsmToken(AsmToken::Integer, Result, 0); - } - const char *NumStart = CurPtr; - while (CurPtr[0] == '0' || CurPtr[0] == '1') - ++CurPtr; - - // Requires at least one binary digit. - if (CurPtr == NumStart) - return ReturnError(TokStart, "invalid binary number"); - - StringRef Result(TokStart, CurPtr - TokStart); - - APInt Value(128, 0, true); - if (Result.substr(2).getAsInteger(2, Value)) - return ReturnError(TokStart, "invalid binary number"); - - // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL - // suffixes on integer literals. - SkipIgnoredIntegerSuffix(CurPtr); - - return intToken(Result, Value); - } - - if ((*CurPtr == 'x') || (*CurPtr == 'X')) { - ++CurPtr; - const char *NumStart = CurPtr; - while (isHexDigit(CurPtr[0])) - ++CurPtr; - - // "0x.0p0" is valid, and "0x0p0" (but not "0xp0" for example, which will be - // diagnosed by LexHexFloatLiteral). - if (CurPtr[0] == '.' || CurPtr[0] == 'p' || CurPtr[0] == 'P') - return LexHexFloatLiteral(NumStart == CurPtr); - - // Otherwise requires at least one hex digit. - if (CurPtr == NumStart) - return ReturnError(CurPtr-2, "invalid hexadecimal number"); - - APInt Result(128, 0); - if (StringRef(TokStart, CurPtr - TokStart).getAsInteger(0, Result)) - return ReturnError(TokStart, "invalid hexadecimal number"); - - // Consume the optional [hH]. - if (LexMasmIntegers && (*CurPtr == 'h' || *CurPtr == 'H')) - ++CurPtr; - - // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL - // suffixes on integer literals. - SkipIgnoredIntegerSuffix(CurPtr); - - return intToken(StringRef(TokStart, CurPtr - TokStart), Result); - } - - // Either octal or hexadecimal. - APInt Value(128, 0, true); - unsigned Radix = doHexLookAhead(CurPtr, 8, LexMasmIntegers); - bool isHex = Radix == 16; - StringRef Result(TokStart, CurPtr - TokStart); - if (Result.getAsInteger(Radix, Value)) - return ReturnError(TokStart, !isHex ? "invalid octal number" : - "invalid hexdecimal number"); - - // Consume the [hH]. - if (Radix == 16) - ++CurPtr; - - // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL - // suffixes on integer literals. - SkipIgnoredIntegerSuffix(CurPtr); - - return intToken(Result, Value); -} - -/// LexSingleQuote: Integer: 'b' -AsmToken AsmLexer::LexSingleQuote() { - int CurChar = getNextChar(); - - if (CurChar == '\\') - CurChar = getNextChar(); - - if (CurChar == EOF) - return ReturnError(TokStart, "unterminated single quote"); - - CurChar = getNextChar(); - - if (CurChar != '\'') - return ReturnError(TokStart, "single quote way too long"); - - // The idea here being that 'c' is basically just an integral - // constant. - StringRef Res = StringRef(TokStart,CurPtr - TokStart); - long long Value; - - if (Res.startswith("\'\\")) { - char theChar = Res[2]; - switch (theChar) { - default: Value = theChar; break; - case '\'': Value = '\''; break; - case 't': Value = '\t'; break; - case 'n': Value = '\n'; break; - case 'b': Value = '\b'; break; - } - } else - Value = TokStart[1]; - - return AsmToken(AsmToken::Integer, Res, Value); -} - -/// LexQuote: String: "..." -AsmToken AsmLexer::LexQuote() { - int CurChar = getNextChar(); - // TODO: does gas allow multiline string constants? - while (CurChar != '"') { - if (CurChar == '\\') { - // Allow \", etc. - CurChar = getNextChar(); - } - - if (CurChar == EOF) - return ReturnError(TokStart, "unterminated string constant"); - - CurChar = getNextChar(); - } - - return AsmToken(AsmToken::String, StringRef(TokStart, CurPtr - TokStart)); -} - -StringRef AsmLexer::LexUntilEndOfStatement() { - TokStart = CurPtr; - - while (!isAtStartOfComment(CurPtr) && // Start of line comment. - !isAtStatementSeparator(CurPtr) && // End of statement marker. - *CurPtr != '\n' && *CurPtr != '\r' && CurPtr != CurBuf.end()) { - ++CurPtr; - } - return StringRef(TokStart, CurPtr-TokStart); -} - -StringRef AsmLexer::LexUntilEndOfLine() { - TokStart = CurPtr; - - while (*CurPtr != '\n' && *CurPtr != '\r' && CurPtr != CurBuf.end()) { - ++CurPtr; - } - return StringRef(TokStart, CurPtr-TokStart); -} - -size_t AsmLexer::peekTokens(MutableArrayRef<AsmToken> Buf, - bool ShouldSkipSpace) { - SaveAndRestore<const char *> SavedTokenStart(TokStart); - SaveAndRestore<const char *> SavedCurPtr(CurPtr); - SaveAndRestore<bool> SavedAtStartOfLine(IsAtStartOfLine); - SaveAndRestore<bool> SavedAtStartOfStatement(IsAtStartOfStatement); - SaveAndRestore<bool> SavedSkipSpace(SkipSpace, ShouldSkipSpace); - SaveAndRestore<bool> SavedIsPeeking(IsPeeking, true); - std::string SavedErr = getErr(); - SMLoc SavedErrLoc = getErrLoc(); - - size_t ReadCount; - for (ReadCount = 0; ReadCount < Buf.size(); ++ReadCount) { - AsmToken Token = LexToken(); - - Buf[ReadCount] = Token; - - if (Token.is(AsmToken::Eof)) - break; - } - - SetError(SavedErrLoc, SavedErr); - return ReadCount; -} - -bool AsmLexer::isAtStartOfComment(const char *Ptr) { - StringRef CommentString = MAI.getCommentString(); - - if (CommentString.size() == 1) - return CommentString[0] == Ptr[0]; - - // Allow # preprocessor commments also be counted as comments for "##" cases - if (CommentString[1] == '#') - return CommentString[0] == Ptr[0]; - - return strncmp(Ptr, CommentString.data(), CommentString.size()) == 0; -} - -bool AsmLexer::isAtStatementSeparator(const char *Ptr) { - return strncmp(Ptr, MAI.getSeparatorString(), - strlen(MAI.getSeparatorString())) == 0; -} - -AsmToken AsmLexer::LexToken() { - TokStart = CurPtr; - // This always consumes at least one character. - int CurChar = getNextChar(); - - if (!IsPeeking && CurChar == '#' && IsAtStartOfStatement) { - // If this starts with a '#', this may be a cpp - // hash directive and otherwise a line comment. - AsmToken TokenBuf[2]; - MutableArrayRef<AsmToken> Buf(TokenBuf, 2); - size_t num = peekTokens(Buf, true); - // There cannot be a space preceding this - if (IsAtStartOfLine && num == 2 && TokenBuf[0].is(AsmToken::Integer) && - TokenBuf[1].is(AsmToken::String)) { - CurPtr = TokStart; // reset curPtr; - StringRef s = LexUntilEndOfLine(); - UnLex(TokenBuf[1]); - UnLex(TokenBuf[0]); - return AsmToken(AsmToken::HashDirective, s); - } - return LexLineComment(); - } - - if (isAtStartOfComment(TokStart)) - return LexLineComment(); - - if (isAtStatementSeparator(TokStart)) { - CurPtr += strlen(MAI.getSeparatorString()) - 1; - IsAtStartOfLine = true; - IsAtStartOfStatement = true; - return AsmToken(AsmToken::EndOfStatement, - StringRef(TokStart, strlen(MAI.getSeparatorString()))); - } - - // If we're missing a newline at EOF, make sure we still get an - // EndOfStatement token before the Eof token. - if (CurChar == EOF && !IsAtStartOfStatement) { - IsAtStartOfLine = true; - IsAtStartOfStatement = true; - return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1)); - } - IsAtStartOfLine = false; - bool OldIsAtStartOfStatement = IsAtStartOfStatement; - IsAtStartOfStatement = false; - switch (CurChar) { - default: - // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]* - if (isalpha(CurChar) || CurChar == '_' || CurChar == '.') - return LexIdentifier(); - - // Unknown character, emit an error. - return ReturnError(TokStart, "invalid character in input"); - case EOF: - IsAtStartOfLine = true; - IsAtStartOfStatement = true; - return AsmToken(AsmToken::Eof, StringRef(TokStart, 0)); - case 0: - case ' ': - case '\t': - IsAtStartOfStatement = OldIsAtStartOfStatement; - while (*CurPtr == ' ' || *CurPtr == '\t') - CurPtr++; - if (SkipSpace) - return LexToken(); // Ignore whitespace. - else - return AsmToken(AsmToken::Space, StringRef(TokStart, CurPtr - TokStart)); - case '\r': { - IsAtStartOfLine = true; - IsAtStartOfStatement = true; - // If this is a CR followed by LF, treat that as one token. - if (CurPtr != CurBuf.end() && *CurPtr == '\n') - ++CurPtr; - return AsmToken(AsmToken::EndOfStatement, - StringRef(TokStart, CurPtr - TokStart)); - } - case '\n': - IsAtStartOfLine = true; - IsAtStartOfStatement = true; - return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1)); - case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1)); - case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1)); - case '~': return AsmToken(AsmToken::Tilde, StringRef(TokStart, 1)); - case '(': return AsmToken(AsmToken::LParen, StringRef(TokStart, 1)); - case ')': return AsmToken(AsmToken::RParen, StringRef(TokStart, 1)); - case '[': return AsmToken(AsmToken::LBrac, StringRef(TokStart, 1)); - case ']': return AsmToken(AsmToken::RBrac, StringRef(TokStart, 1)); - case '{': return AsmToken(AsmToken::LCurly, StringRef(TokStart, 1)); - case '}': return AsmToken(AsmToken::RCurly, StringRef(TokStart, 1)); - case '*': return AsmToken(AsmToken::Star, StringRef(TokStart, 1)); - case ',': return AsmToken(AsmToken::Comma, StringRef(TokStart, 1)); - case '$': return AsmToken(AsmToken::Dollar, StringRef(TokStart, 1)); - case '@': return AsmToken(AsmToken::At, StringRef(TokStart, 1)); - case '\\': return AsmToken(AsmToken::BackSlash, StringRef(TokStart, 1)); - case '=': - if (*CurPtr == '=') { - ++CurPtr; - return AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2)); - } - return AsmToken(AsmToken::Equal, StringRef(TokStart, 1)); - case '-': - if (*CurPtr == '>') { - ++CurPtr; - return AsmToken(AsmToken::MinusGreater, StringRef(TokStart, 2)); - } - return AsmToken(AsmToken::Minus, StringRef(TokStart, 1)); - case '|': - if (*CurPtr == '|') { - ++CurPtr; - return AsmToken(AsmToken::PipePipe, StringRef(TokStart, 2)); - } - return AsmToken(AsmToken::Pipe, StringRef(TokStart, 1)); - case '^': return AsmToken(AsmToken::Caret, StringRef(TokStart, 1)); - case '&': - if (*CurPtr == '&') { - ++CurPtr; - return AsmToken(AsmToken::AmpAmp, StringRef(TokStart, 2)); - } - return AsmToken(AsmToken::Amp, StringRef(TokStart, 1)); - case '!': - if (*CurPtr == '=') { - ++CurPtr; - return AsmToken(AsmToken::ExclaimEqual, StringRef(TokStart, 2)); - } - return AsmToken(AsmToken::Exclaim, StringRef(TokStart, 1)); - case '%': - if (MAI.hasMipsExpressions()) { - AsmToken::TokenKind Operator; - unsigned OperatorLength; - - std::tie(Operator, OperatorLength) = - StringSwitch<std::pair<AsmToken::TokenKind, unsigned>>( - StringRef(CurPtr)) - .StartsWith("call16", {AsmToken::PercentCall16, 7}) - .StartsWith("call_hi", {AsmToken::PercentCall_Hi, 8}) - .StartsWith("call_lo", {AsmToken::PercentCall_Lo, 8}) - .StartsWith("dtprel_hi", {AsmToken::PercentDtprel_Hi, 10}) - .StartsWith("dtprel_lo", {AsmToken::PercentDtprel_Lo, 10}) - .StartsWith("got_disp", {AsmToken::PercentGot_Disp, 9}) - .StartsWith("got_hi", {AsmToken::PercentGot_Hi, 7}) - .StartsWith("got_lo", {AsmToken::PercentGot_Lo, 7}) - .StartsWith("got_ofst", {AsmToken::PercentGot_Ofst, 9}) - .StartsWith("got_page", {AsmToken::PercentGot_Page, 9}) - .StartsWith("gottprel", {AsmToken::PercentGottprel, 9}) - .StartsWith("got", {AsmToken::PercentGot, 4}) - .StartsWith("gp_rel", {AsmToken::PercentGp_Rel, 7}) - .StartsWith("higher", {AsmToken::PercentHigher, 7}) - .StartsWith("highest", {AsmToken::PercentHighest, 8}) - .StartsWith("hi", {AsmToken::PercentHi, 3}) - .StartsWith("lo", {AsmToken::PercentLo, 3}) - .StartsWith("neg", {AsmToken::PercentNeg, 4}) - .StartsWith("pcrel_hi", {AsmToken::PercentPcrel_Hi, 9}) - .StartsWith("pcrel_lo", {AsmToken::PercentPcrel_Lo, 9}) - .StartsWith("tlsgd", {AsmToken::PercentTlsgd, 6}) - .StartsWith("tlsldm", {AsmToken::PercentTlsldm, 7}) - .StartsWith("tprel_hi", {AsmToken::PercentTprel_Hi, 9}) - .StartsWith("tprel_lo", {AsmToken::PercentTprel_Lo, 9}) - .Default({AsmToken::Percent, 1}); - - if (Operator != AsmToken::Percent) { - CurPtr += OperatorLength - 1; - return AsmToken(Operator, StringRef(TokStart, OperatorLength)); - } - } - return AsmToken(AsmToken::Percent, StringRef(TokStart, 1)); - case '/': - IsAtStartOfStatement = OldIsAtStartOfStatement; - return LexSlash(); - case '#': return AsmToken(AsmToken::Hash, StringRef(TokStart, 1)); - case '\'': return LexSingleQuote(); - case '"': return LexQuote(); - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - return LexDigit(); - case '<': - switch (*CurPtr) { - case '<': - ++CurPtr; - return AsmToken(AsmToken::LessLess, StringRef(TokStart, 2)); - case '=': - ++CurPtr; - return AsmToken(AsmToken::LessEqual, StringRef(TokStart, 2)); - case '>': - ++CurPtr; - return AsmToken(AsmToken::LessGreater, StringRef(TokStart, 2)); - default: - return AsmToken(AsmToken::Less, StringRef(TokStart, 1)); - } - case '>': - switch (*CurPtr) { - case '>': - ++CurPtr; - return AsmToken(AsmToken::GreaterGreater, StringRef(TokStart, 2)); - case '=': - ++CurPtr; - return AsmToken(AsmToken::GreaterEqual, StringRef(TokStart, 2)); - default: - return AsmToken(AsmToken::Greater, StringRef(TokStart, 1)); - } - - // TODO: Quoted identifiers (objc methods etc) - // local labels: [0-9][:] - // Forward/backward labels: [0-9][fb] - // Integers, fp constants, character constants. - } -} diff --git a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp deleted file mode 100644 index c2cbca2177be..000000000000 --- a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp +++ /dev/null @@ -1,5962 +0,0 @@ -//===- AsmParser.cpp - Parser for Assembly Files --------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This class implements the parser for assembly files. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCCodeView.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDirectives.h" -#include "llvm/MC/MCDwarf.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInstPrinter.h" -#include "llvm/MC/MCInstrDesc.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCParser/AsmCond.h" -#include "llvm/MC/MCParser/AsmLexer.h" -#include "llvm/MC/MCParser/MCAsmLexer.h" -#include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/MC/MCParser/MCAsmParserExtension.h" -#include "llvm/MC/MCParser/MCAsmParserUtils.h" -#include "llvm/MC/MCParser/MCParsedAsmOperand.h" -#include "llvm/MC/MCParser/MCTargetAsmParser.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSection.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCTargetOptions.h" -#include "llvm/MC/MCValue.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MD5.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/SMLoc.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cassert> -#include <cctype> -#include <climits> -#include <cstddef> -#include <cstdint> -#include <deque> -#include <memory> -#include <sstream> -#include <string> -#include <tuple> -#include <utility> -#include <vector> - -using namespace llvm; - -MCAsmParserSemaCallback::~MCAsmParserSemaCallback() = default; - -static cl::opt<unsigned> AsmMacroMaxNestingDepth( - "asm-macro-max-nesting-depth", cl::init(20), cl::Hidden, - cl::desc("The maximum nesting depth allowed for assembly macros.")); - -namespace { - -/// Helper types for tracking macro definitions. -typedef std::vector<AsmToken> MCAsmMacroArgument; -typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments; - -/// Helper class for storing information about an active macro -/// instantiation. -struct MacroInstantiation { - /// The location of the instantiation. - SMLoc InstantiationLoc; - - /// The buffer where parsing should resume upon instantiation completion. - int ExitBuffer; - - /// The location where parsing should resume upon instantiation completion. - SMLoc ExitLoc; - - /// The depth of TheCondStack at the start of the instantiation. - size_t CondStackDepth; - -public: - MacroInstantiation(SMLoc IL, int EB, SMLoc EL, size_t CondStackDepth); -}; - -struct ParseStatementInfo { - /// The parsed operands from the last parsed statement. - SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands; - - /// The opcode from the last parsed instruction. - unsigned Opcode = ~0U; - - /// Was there an error parsing the inline assembly? - bool ParseError = false; - - SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr; - - ParseStatementInfo() = delete; - ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites) - : AsmRewrites(rewrites) {} -}; - -/// The concrete assembly parser instance. -class AsmParser : public MCAsmParser { -private: - AsmLexer Lexer; - MCContext &Ctx; - MCStreamer &Out; - const MCAsmInfo &MAI; - SourceMgr &SrcMgr; - SourceMgr::DiagHandlerTy SavedDiagHandler; - void *SavedDiagContext; - std::unique_ptr<MCAsmParserExtension> PlatformParser; - - /// This is the current buffer index we're lexing from as managed by the - /// SourceMgr object. - unsigned CurBuffer; - - AsmCond TheCondState; - std::vector<AsmCond> TheCondStack; - - /// maps directive names to handler methods in parser - /// extensions. Extensions register themselves in this map by calling - /// addDirectiveHandler. - StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap; - - /// Stack of active macro instantiations. - std::vector<MacroInstantiation*> ActiveMacros; - - /// List of bodies of anonymous macros. - std::deque<MCAsmMacro> MacroLikeBodies; - - /// Boolean tracking whether macro substitution is enabled. - unsigned MacrosEnabledFlag : 1; - - /// Keeps track of how many .macro's have been instantiated. - unsigned NumOfMacroInstantiations; - - /// The values from the last parsed cpp hash file line comment if any. - struct CppHashInfoTy { - StringRef Filename; - int64_t LineNumber; - SMLoc Loc; - unsigned Buf; - CppHashInfoTy() : Filename(), LineNumber(0), Loc(), Buf(0) {} - }; - CppHashInfoTy CppHashInfo; - - /// The filename from the first cpp hash file line comment, if any. - StringRef FirstCppHashFilename; - - /// List of forward directional labels for diagnosis at the end. - SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels; - - /// AssemblerDialect. ~OU means unset value and use value provided by MAI. - unsigned AssemblerDialect = ~0U; - - /// is Darwin compatibility enabled? - bool IsDarwin = false; - - /// Are we parsing ms-style inline assembly? - bool ParsingInlineAsm = false; - - /// Did we already inform the user about inconsistent MD5 usage? - bool ReportedInconsistentMD5 = false; - - // Is alt macro mode enabled. - bool AltMacroMode = false; - -public: - AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, - const MCAsmInfo &MAI, unsigned CB); - AsmParser(const AsmParser &) = delete; - AsmParser &operator=(const AsmParser &) = delete; - ~AsmParser() override; - - bool Run(bool NoInitialTextSection, bool NoFinalize = false) override; - - void addDirectiveHandler(StringRef Directive, - ExtensionDirectiveHandler Handler) override { - ExtensionDirectiveMap[Directive] = Handler; - } - - void addAliasForDirective(StringRef Directive, StringRef Alias) override { - DirectiveKindMap[Directive] = DirectiveKindMap[Alias]; - } - - /// @name MCAsmParser Interface - /// { - - SourceMgr &getSourceManager() override { return SrcMgr; } - MCAsmLexer &getLexer() override { return Lexer; } - MCContext &getContext() override { return Ctx; } - MCStreamer &getStreamer() override { return Out; } - - CodeViewContext &getCVContext() { return Ctx.getCVContext(); } - - unsigned getAssemblerDialect() override { - if (AssemblerDialect == ~0U) - return MAI.getAssemblerDialect(); - else - return AssemblerDialect; - } - void setAssemblerDialect(unsigned i) override { - AssemblerDialect = i; - } - - void Note(SMLoc L, const Twine &Msg, SMRange Range = None) override; - bool Warning(SMLoc L, const Twine &Msg, SMRange Range = None) override; - bool printError(SMLoc L, const Twine &Msg, SMRange Range = None) override; - - const AsmToken &Lex() override; - - void setParsingInlineAsm(bool V) override { - ParsingInlineAsm = V; - // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and - // hex integer literals. - Lexer.setLexMasmIntegers(V); - } - bool isParsingInlineAsm() override { return ParsingInlineAsm; } - - bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, - unsigned &NumOutputs, unsigned &NumInputs, - SmallVectorImpl<std::pair<void *,bool>> &OpDecls, - SmallVectorImpl<std::string> &Constraints, - SmallVectorImpl<std::string> &Clobbers, - const MCInstrInfo *MII, const MCInstPrinter *IP, - MCAsmParserSemaCallback &SI) override; - - bool parseExpression(const MCExpr *&Res); - bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override; - bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override; - bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override; - bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res, - SMLoc &EndLoc) override; - bool parseAbsoluteExpression(int64_t &Res) override; - - /// Parse a floating point expression using the float \p Semantics - /// and set \p Res to the value. - bool parseRealValue(const fltSemantics &Semantics, APInt &Res); - - /// Parse an identifier or string (as a quoted identifier) - /// and set \p Res to the identifier contents. - bool parseIdentifier(StringRef &Res) override; - void eatToEndOfStatement() override; - - bool checkForValidSection() override; - - /// } - -private: - bool parseStatement(ParseStatementInfo &Info, - MCAsmParserSemaCallback *SI); - bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites); - bool parseCppHashLineFilenameComment(SMLoc L); - - void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body, - ArrayRef<MCAsmMacroParameter> Parameters); - bool expandMacro(raw_svector_ostream &OS, StringRef Body, - ArrayRef<MCAsmMacroParameter> Parameters, - ArrayRef<MCAsmMacroArgument> A, bool EnableAtPseudoVariable, - SMLoc L); - - /// Are macros enabled in the parser? - bool areMacrosEnabled() {return MacrosEnabledFlag;} - - /// Control a flag in the parser that enables or disables macros. - void setMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;} - - /// Are we inside a macro instantiation? - bool isInsideMacroInstantiation() {return !ActiveMacros.empty();} - - /// Handle entry to macro instantiation. - /// - /// \param M The macro. - /// \param NameLoc Instantiation location. - bool handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc); - - /// Handle exit from macro instantiation. - void handleMacroExit(); - - /// Extract AsmTokens for a macro argument. - bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg); - - /// Parse all macro arguments for a given macro. - bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A); - - void printMacroInstantiations(); - void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg, - SMRange Range = None) const { - ArrayRef<SMRange> Ranges(Range); - SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges); - } - static void DiagHandler(const SMDiagnostic &Diag, void *Context); - - /// Should we emit DWARF describing this assembler source? (Returns false if - /// the source has .file directives, which means we don't want to generate - /// info describing the assembler source itself.) - bool enabledGenDwarfForAssembly(); - - /// Enter the specified file. This returns true on failure. - bool enterIncludeFile(const std::string &Filename); - - /// Process the specified file for the .incbin directive. - /// This returns true on failure. - bool processIncbinFile(const std::string &Filename, int64_t Skip = 0, - const MCExpr *Count = nullptr, SMLoc Loc = SMLoc()); - - /// Reset the current lexer position to that given by \p Loc. The - /// current token is not set; clients should ensure Lex() is called - /// subsequently. - /// - /// \param InBuffer If not 0, should be the known buffer id that contains the - /// location. - void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0); - - /// Parse up to the end of statement and a return the contents from the - /// current token until the end of the statement; the current token on exit - /// will be either the EndOfStatement or EOF. - StringRef parseStringToEndOfStatement() override; - - /// Parse until the end of a statement or a comma is encountered, - /// return the contents from the current token up to the end or comma. - StringRef parseStringToComma(); - - bool parseAssignment(StringRef Name, bool allow_redef, - bool NoDeadStrip = false); - - unsigned getBinOpPrecedence(AsmToken::TokenKind K, - MCBinaryExpr::Opcode &Kind); - - bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc); - bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc); - bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc); - - bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc); - - bool parseCVFunctionId(int64_t &FunctionId, StringRef DirectiveName); - bool parseCVFileId(int64_t &FileId, StringRef DirectiveName); - - // Generic (target and platform independent) directive parsing. - enum DirectiveKind { - DK_NO_DIRECTIVE, // Placeholder - DK_SET, - DK_EQU, - DK_EQUIV, - DK_ASCII, - DK_ASCIZ, - DK_STRING, - DK_BYTE, - DK_SHORT, - DK_RELOC, - DK_VALUE, - DK_2BYTE, - DK_LONG, - DK_INT, - DK_4BYTE, - DK_QUAD, - DK_8BYTE, - DK_OCTA, - DK_DC, - DK_DC_A, - DK_DC_B, - DK_DC_D, - DK_DC_L, - DK_DC_S, - DK_DC_W, - DK_DC_X, - DK_DCB, - DK_DCB_B, - DK_DCB_D, - DK_DCB_L, - DK_DCB_S, - DK_DCB_W, - DK_DCB_X, - DK_DS, - DK_DS_B, - DK_DS_D, - DK_DS_L, - DK_DS_P, - DK_DS_S, - DK_DS_W, - DK_DS_X, - DK_SINGLE, - DK_FLOAT, - DK_DOUBLE, - DK_ALIGN, - DK_ALIGN32, - DK_BALIGN, - DK_BALIGNW, - DK_BALIGNL, - DK_P2ALIGN, - DK_P2ALIGNW, - DK_P2ALIGNL, - DK_ORG, - DK_FILL, - DK_ENDR, - DK_BUNDLE_ALIGN_MODE, - DK_BUNDLE_LOCK, - DK_BUNDLE_UNLOCK, - DK_ZERO, - DK_EXTERN, - DK_GLOBL, - DK_GLOBAL, - DK_LAZY_REFERENCE, - DK_NO_DEAD_STRIP, - DK_SYMBOL_RESOLVER, - DK_PRIVATE_EXTERN, - DK_REFERENCE, - DK_WEAK_DEFINITION, - DK_WEAK_REFERENCE, - DK_WEAK_DEF_CAN_BE_HIDDEN, - DK_COLD, - DK_COMM, - DK_COMMON, - DK_LCOMM, - DK_ABORT, - DK_INCLUDE, - DK_INCBIN, - DK_CODE16, - DK_CODE16GCC, - DK_REPT, - DK_IRP, - DK_IRPC, - DK_IF, - DK_IFEQ, - DK_IFGE, - DK_IFGT, - DK_IFLE, - DK_IFLT, - DK_IFNE, - DK_IFB, - DK_IFNB, - DK_IFC, - DK_IFEQS, - DK_IFNC, - DK_IFNES, - DK_IFDEF, - DK_IFNDEF, - DK_IFNOTDEF, - DK_ELSEIF, - DK_ELSE, - DK_ENDIF, - DK_SPACE, - DK_SKIP, - DK_FILE, - DK_LINE, - DK_LOC, - DK_STABS, - DK_CV_FILE, - DK_CV_FUNC_ID, - DK_CV_INLINE_SITE_ID, - DK_CV_LOC, - DK_CV_LINETABLE, - DK_CV_INLINE_LINETABLE, - DK_CV_DEF_RANGE, - DK_CV_STRINGTABLE, - DK_CV_STRING, - DK_CV_FILECHECKSUMS, - DK_CV_FILECHECKSUM_OFFSET, - DK_CV_FPO_DATA, - DK_CFI_SECTIONS, - DK_CFI_STARTPROC, - DK_CFI_ENDPROC, - DK_CFI_DEF_CFA, - DK_CFI_DEF_CFA_OFFSET, - DK_CFI_ADJUST_CFA_OFFSET, - DK_CFI_DEF_CFA_REGISTER, - DK_CFI_OFFSET, - DK_CFI_REL_OFFSET, - DK_CFI_PERSONALITY, - DK_CFI_LSDA, - DK_CFI_REMEMBER_STATE, - DK_CFI_RESTORE_STATE, - DK_CFI_SAME_VALUE, - DK_CFI_RESTORE, - DK_CFI_ESCAPE, - DK_CFI_RETURN_COLUMN, - DK_CFI_SIGNAL_FRAME, - DK_CFI_UNDEFINED, - DK_CFI_REGISTER, - DK_CFI_WINDOW_SAVE, - DK_CFI_B_KEY_FRAME, - DK_MACROS_ON, - DK_MACROS_OFF, - DK_ALTMACRO, - DK_NOALTMACRO, - DK_MACRO, - DK_EXITM, - DK_ENDM, - DK_ENDMACRO, - DK_PURGEM, - DK_SLEB128, - DK_ULEB128, - DK_ERR, - DK_ERROR, - DK_WARNING, - DK_PRINT, - DK_ADDRSIG, - DK_ADDRSIG_SYM, - DK_END - }; - - /// Maps directive name --> DirectiveKind enum, for - /// directives parsed by this class. - StringMap<DirectiveKind> DirectiveKindMap; - - // ".ascii", ".asciz", ".string" - bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated); - bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc" - bool parseDirectiveValue(StringRef IDVal, - unsigned Size); // ".byte", ".long", ... - bool parseDirectiveOctaValue(StringRef IDVal); // ".octa", ... - bool parseDirectiveRealValue(StringRef IDVal, - const fltSemantics &); // ".single", ... - bool parseDirectiveFill(); // ".fill" - bool parseDirectiveZero(); // ".zero" - // ".set", ".equ", ".equiv" - bool parseDirectiveSet(StringRef IDVal, bool allow_redef); - bool parseDirectiveOrg(); // ".org" - // ".align{,32}", ".p2align{,w,l}" - bool parseDirectiveAlign(bool IsPow2, unsigned ValueSize); - - // ".file", ".line", ".loc", ".stabs" - bool parseDirectiveFile(SMLoc DirectiveLoc); - bool parseDirectiveLine(); - bool parseDirectiveLoc(); - bool parseDirectiveStabs(); - - // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable", - // ".cv_inline_linetable", ".cv_def_range", ".cv_string" - bool parseDirectiveCVFile(); - bool parseDirectiveCVFuncId(); - bool parseDirectiveCVInlineSiteId(); - bool parseDirectiveCVLoc(); - bool parseDirectiveCVLinetable(); - bool parseDirectiveCVInlineLinetable(); - bool parseDirectiveCVDefRange(); - bool parseDirectiveCVString(); - bool parseDirectiveCVStringTable(); - bool parseDirectiveCVFileChecksums(); - bool parseDirectiveCVFileChecksumOffset(); - bool parseDirectiveCVFPOData(); - - // .cfi directives - bool parseDirectiveCFIRegister(SMLoc DirectiveLoc); - bool parseDirectiveCFIWindowSave(); - bool parseDirectiveCFISections(); - bool parseDirectiveCFIStartProc(); - bool parseDirectiveCFIEndProc(); - bool parseDirectiveCFIDefCfaOffset(); - bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc); - bool parseDirectiveCFIAdjustCfaOffset(); - bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc); - bool parseDirectiveCFIOffset(SMLoc DirectiveLoc); - bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc); - bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality); - bool parseDirectiveCFIRememberState(); - bool parseDirectiveCFIRestoreState(); - bool parseDirectiveCFISameValue(SMLoc DirectiveLoc); - bool parseDirectiveCFIRestore(SMLoc DirectiveLoc); - bool parseDirectiveCFIEscape(); - bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc); - bool parseDirectiveCFISignalFrame(); - bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc); - - // macro directives - bool parseDirectivePurgeMacro(SMLoc DirectiveLoc); - bool parseDirectiveExitMacro(StringRef Directive); - bool parseDirectiveEndMacro(StringRef Directive); - bool parseDirectiveMacro(SMLoc DirectiveLoc); - bool parseDirectiveMacrosOnOff(StringRef Directive); - // alternate macro mode directives - bool parseDirectiveAltmacro(StringRef Directive); - // ".bundle_align_mode" - bool parseDirectiveBundleAlignMode(); - // ".bundle_lock" - bool parseDirectiveBundleLock(); - // ".bundle_unlock" - bool parseDirectiveBundleUnlock(); - - // ".space", ".skip" - bool parseDirectiveSpace(StringRef IDVal); - - // ".dcb" - bool parseDirectiveDCB(StringRef IDVal, unsigned Size); - bool parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &); - // ".ds" - bool parseDirectiveDS(StringRef IDVal, unsigned Size); - - // .sleb128 (Signed=true) and .uleb128 (Signed=false) - bool parseDirectiveLEB128(bool Signed); - - /// Parse a directive like ".globl" which - /// accepts a single symbol (which should be a label or an external). - bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr); - - bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm" - - bool parseDirectiveAbort(); // ".abort" - bool parseDirectiveInclude(); // ".include" - bool parseDirectiveIncbin(); // ".incbin" - - // ".if", ".ifeq", ".ifge", ".ifgt" , ".ifle", ".iflt" or ".ifne" - bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind); - // ".ifb" or ".ifnb", depending on ExpectBlank. - bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank); - // ".ifc" or ".ifnc", depending on ExpectEqual. - bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual); - // ".ifeqs" or ".ifnes", depending on ExpectEqual. - bool parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual); - // ".ifdef" or ".ifndef", depending on expect_defined - bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined); - bool parseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif" - bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else" - bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif - bool parseEscapedString(std::string &Data) override; - - const MCExpr *applyModifierToExpr(const MCExpr *E, - MCSymbolRefExpr::VariantKind Variant); - - // Macro-like directives - MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc); - void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, - raw_svector_ostream &OS); - bool parseDirectiveRept(SMLoc DirectiveLoc, StringRef Directive); - bool parseDirectiveIrp(SMLoc DirectiveLoc); // ".irp" - bool parseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc" - bool parseDirectiveEndr(SMLoc DirectiveLoc); // ".endr" - - // "_emit" or "__emit" - bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info, - size_t Len); - - // "align" - bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info); - - // "end" - bool parseDirectiveEnd(SMLoc DirectiveLoc); - - // ".err" or ".error" - bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage); - - // ".warning" - bool parseDirectiveWarning(SMLoc DirectiveLoc); - - // .print <double-quotes-string> - bool parseDirectivePrint(SMLoc DirectiveLoc); - - // Directives to support address-significance tables. - bool parseDirectiveAddrsig(); - bool parseDirectiveAddrsigSym(); - - void initializeDirectiveKindMap(); -}; - -} // end anonymous namespace - -namespace llvm { - -extern MCAsmParserExtension *createDarwinAsmParser(); -extern MCAsmParserExtension *createELFAsmParser(); -extern MCAsmParserExtension *createCOFFAsmParser(); -extern MCAsmParserExtension *createWasmAsmParser(); - -} // end namespace llvm - -enum { DEFAULT_ADDRSPACE = 0 }; - -AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, - const MCAsmInfo &MAI, unsigned CB = 0) - : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM), - CurBuffer(CB ? CB : SM.getMainFileID()), MacrosEnabledFlag(true) { - HadError = false; - // Save the old handler. - SavedDiagHandler = SrcMgr.getDiagHandler(); - SavedDiagContext = SrcMgr.getDiagContext(); - // Set our own handler which calls the saved handler. - SrcMgr.setDiagHandler(DiagHandler, this); - Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); - - // Initialize the platform / file format parser. - switch (Ctx.getObjectFileInfo()->getObjectFileType()) { - case MCObjectFileInfo::IsCOFF: - PlatformParser.reset(createCOFFAsmParser()); - break; - case MCObjectFileInfo::IsMachO: - PlatformParser.reset(createDarwinAsmParser()); - IsDarwin = true; - break; - case MCObjectFileInfo::IsELF: - PlatformParser.reset(createELFAsmParser()); - break; - case MCObjectFileInfo::IsWasm: - PlatformParser.reset(createWasmAsmParser()); - break; - case MCObjectFileInfo::IsXCOFF: - // TODO: Need to implement createXCOFFAsmParser for XCOFF format. - break; - } - - PlatformParser->Initialize(*this); - initializeDirectiveKindMap(); - - NumOfMacroInstantiations = 0; -} - -AsmParser::~AsmParser() { - assert((HadError || ActiveMacros.empty()) && - "Unexpected active macro instantiation!"); - - // Restore the saved diagnostics handler and context for use during - // finalization. - SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext); -} - -void AsmParser::printMacroInstantiations() { - // Print the active macro instantiation stack. - for (std::vector<MacroInstantiation *>::const_reverse_iterator - it = ActiveMacros.rbegin(), - ie = ActiveMacros.rend(); - it != ie; ++it) - printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note, - "while in macro instantiation"); -} - -void AsmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) { - printPendingErrors(); - printMessage(L, SourceMgr::DK_Note, Msg, Range); - printMacroInstantiations(); -} - -bool AsmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) { - if(getTargetParser().getTargetOptions().MCNoWarn) - return false; - if (getTargetParser().getTargetOptions().MCFatalWarnings) - return Error(L, Msg, Range); - printMessage(L, SourceMgr::DK_Warning, Msg, Range); - printMacroInstantiations(); - return false; -} - -bool AsmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) { - HadError = true; - printMessage(L, SourceMgr::DK_Error, Msg, Range); - printMacroInstantiations(); - return true; -} - -bool AsmParser::enterIncludeFile(const std::string &Filename) { - std::string IncludedFile; - unsigned NewBuf = - SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); - if (!NewBuf) - return true; - - CurBuffer = NewBuf; - Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); - return false; -} - -/// Process the specified .incbin file by searching for it in the include paths -/// then just emitting the byte contents of the file to the streamer. This -/// returns true on failure. -bool AsmParser::processIncbinFile(const std::string &Filename, int64_t Skip, - const MCExpr *Count, SMLoc Loc) { - std::string IncludedFile; - unsigned NewBuf = - SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); - if (!NewBuf) - return true; - - // Pick up the bytes from the file and emit them. - StringRef Bytes = SrcMgr.getMemoryBuffer(NewBuf)->getBuffer(); - Bytes = Bytes.drop_front(Skip); - if (Count) { - int64_t Res; - if (!Count->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr())) - return Error(Loc, "expected absolute expression"); - if (Res < 0) - return Warning(Loc, "negative count has no effect"); - Bytes = Bytes.take_front(Res); - } - getStreamer().EmitBytes(Bytes); - return false; -} - -void AsmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) { - CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc); - Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), - Loc.getPointer()); -} - -const AsmToken &AsmParser::Lex() { - if (Lexer.getTok().is(AsmToken::Error)) - Error(Lexer.getErrLoc(), Lexer.getErr()); - - // if it's a end of statement with a comment in it - if (getTok().is(AsmToken::EndOfStatement)) { - // if this is a line comment output it. - if (!getTok().getString().empty() && getTok().getString().front() != '\n' && - getTok().getString().front() != '\r' && MAI.preserveAsmComments()) - Out.addExplicitComment(Twine(getTok().getString())); - } - - const AsmToken *tok = &Lexer.Lex(); - - // Parse comments here to be deferred until end of next statement. - while (tok->is(AsmToken::Comment)) { - if (MAI.preserveAsmComments()) - Out.addExplicitComment(Twine(tok->getString())); - tok = &Lexer.Lex(); - } - - if (tok->is(AsmToken::Eof)) { - // If this is the end of an included file, pop the parent file off the - // include stack. - SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); - if (ParentIncludeLoc != SMLoc()) { - jumpToLoc(ParentIncludeLoc); - return Lex(); - } - } - - return *tok; -} - -bool AsmParser::enabledGenDwarfForAssembly() { - // Check whether the user specified -g. - if (!getContext().getGenDwarfForAssembly()) - return false; - // If we haven't encountered any .file directives (which would imply that - // the assembler source was produced with debug info already) then emit one - // describing the assembler source file itself. - if (getContext().getGenDwarfFileNumber() == 0) { - // Use the first #line directive for this, if any. It's preprocessed, so - // there is no checksum, and of course no source directive. - if (!FirstCppHashFilename.empty()) - getContext().setMCLineTableRootFile(/*CUID=*/0, - getContext().getCompilationDir(), - FirstCppHashFilename, - /*Cksum=*/None, /*Source=*/None); - const MCDwarfFile &RootFile = - getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile(); - getContext().setGenDwarfFileNumber(getStreamer().EmitDwarfFileDirective( - /*CUID=*/0, getContext().getCompilationDir(), RootFile.Name, - RootFile.Checksum, RootFile.Source)); - } - return true; -} - -bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { - // Create the initial section, if requested. - if (!NoInitialTextSection) - Out.InitSections(false); - - // Prime the lexer. - Lex(); - - HadError = false; - AsmCond StartingCondState = TheCondState; - SmallVector<AsmRewrite, 4> AsmStrRewrites; - - // If we are generating dwarf for assembly source files save the initial text - // section. (Don't use enabledGenDwarfForAssembly() here, as we aren't - // emitting any actual debug info yet and haven't had a chance to parse any - // embedded .file directives.) - if (getContext().getGenDwarfForAssembly()) { - MCSection *Sec = getStreamer().getCurrentSectionOnly(); - if (!Sec->getBeginSymbol()) { - MCSymbol *SectionStartSym = getContext().createTempSymbol(); - getStreamer().EmitLabel(SectionStartSym); - Sec->setBeginSymbol(SectionStartSym); - } - bool InsertResult = getContext().addGenDwarfSection(Sec); - assert(InsertResult && ".text section should not have debug info yet"); - (void)InsertResult; - } - - // While we have input, parse each statement. - while (Lexer.isNot(AsmToken::Eof)) { - ParseStatementInfo Info(&AsmStrRewrites); - if (!parseStatement(Info, nullptr)) - continue; - - // If we have a Lexer Error we are on an Error Token. Load in Lexer Error - // for printing ErrMsg via Lex() only if no (presumably better) parser error - // exists. - if (!hasPendingError() && Lexer.getTok().is(AsmToken::Error)) { - Lex(); - } - - // parseStatement returned true so may need to emit an error. - printPendingErrors(); - - // Skipping to the next line if needed. - if (!getLexer().isAtStartOfStatement()) - eatToEndOfStatement(); - } - - getTargetParser().onEndOfFile(); - printPendingErrors(); - - // All errors should have been emitted. - assert(!hasPendingError() && "unexpected error from parseStatement"); - - getTargetParser().flushPendingInstructions(getStreamer()); - - if (TheCondState.TheCond != StartingCondState.TheCond || - TheCondState.Ignore != StartingCondState.Ignore) - printError(getTok().getLoc(), "unmatched .ifs or .elses"); - // Check to see there are no empty DwarfFile slots. - const auto &LineTables = getContext().getMCDwarfLineTables(); - if (!LineTables.empty()) { - unsigned Index = 0; - for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) { - if (File.Name.empty() && Index != 0) - printError(getTok().getLoc(), "unassigned file number: " + - Twine(Index) + - " for .file directives"); - ++Index; - } - } - - // Check to see that all assembler local symbols were actually defined. - // Targets that don't do subsections via symbols may not want this, though, - // so conservatively exclude them. Only do this if we're finalizing, though, - // as otherwise we won't necessarilly have seen everything yet. - if (!NoFinalize) { - if (MAI.hasSubsectionsViaSymbols()) { - for (const auto &TableEntry : getContext().getSymbols()) { - MCSymbol *Sym = TableEntry.getValue(); - // Variable symbols may not be marked as defined, so check those - // explicitly. If we know it's a variable, we have a definition for - // the purposes of this check. - if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined()) - // FIXME: We would really like to refer back to where the symbol was - // first referenced for a source location. We need to add something - // to track that. Currently, we just point to the end of the file. - printError(getTok().getLoc(), "assembler local symbol '" + - Sym->getName() + "' not defined"); - } - } - - // Temporary symbols like the ones for directional jumps don't go in the - // symbol table. They also need to be diagnosed in all (final) cases. - for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) { - if (std::get<2>(LocSym)->isUndefined()) { - // Reset the state of any "# line file" directives we've seen to the - // context as it was at the diagnostic site. - CppHashInfo = std::get<1>(LocSym); - printError(std::get<0>(LocSym), "directional label undefined"); - } - } - } - - // Finalize the output stream if there are no errors and if the client wants - // us to. - if (!HadError && !NoFinalize) - Out.Finish(); - - return HadError || getContext().hadError(); -} - -bool AsmParser::checkForValidSection() { - if (!ParsingInlineAsm && !getStreamer().getCurrentSectionOnly()) { - Out.InitSections(false); - return Error(getTok().getLoc(), - "expected section directive before assembly directive"); - } - return false; -} - -/// Throw away the rest of the line for testing purposes. -void AsmParser::eatToEndOfStatement() { - while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof)) - Lexer.Lex(); - - // Eat EOL. - if (Lexer.is(AsmToken::EndOfStatement)) - Lexer.Lex(); -} - -StringRef AsmParser::parseStringToEndOfStatement() { - const char *Start = getTok().getLoc().getPointer(); - - while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof)) - Lexer.Lex(); - - const char *End = getTok().getLoc().getPointer(); - return StringRef(Start, End - Start); -} - -StringRef AsmParser::parseStringToComma() { - const char *Start = getTok().getLoc().getPointer(); - - while (Lexer.isNot(AsmToken::EndOfStatement) && - Lexer.isNot(AsmToken::Comma) && Lexer.isNot(AsmToken::Eof)) - Lexer.Lex(); - - const char *End = getTok().getLoc().getPointer(); - return StringRef(Start, End - Start); -} - -/// Parse a paren expression and return it. -/// NOTE: This assumes the leading '(' has already been consumed. -/// -/// parenexpr ::= expr) -/// -bool AsmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) { - if (parseExpression(Res)) - return true; - if (Lexer.isNot(AsmToken::RParen)) - return TokError("expected ')' in parentheses expression"); - EndLoc = Lexer.getTok().getEndLoc(); - Lex(); - return false; -} - -/// Parse a bracket expression and return it. -/// NOTE: This assumes the leading '[' has already been consumed. -/// -/// bracketexpr ::= expr] -/// -bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) { - if (parseExpression(Res)) - return true; - EndLoc = getTok().getEndLoc(); - if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression")) - return true; - return false; -} - -/// Parse a primary expression and return it. -/// primaryexpr ::= (parenexpr -/// primaryexpr ::= symbol -/// primaryexpr ::= number -/// primaryexpr ::= '.' -/// primaryexpr ::= ~,+,- primaryexpr -bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { - SMLoc FirstTokenLoc = getLexer().getLoc(); - AsmToken::TokenKind FirstTokenKind = Lexer.getKind(); - switch (FirstTokenKind) { - default: - return TokError("unknown token in expression"); - // If we have an error assume that we've already handled it. - case AsmToken::Error: - return true; - case AsmToken::Exclaim: - Lex(); // Eat the operator. - if (parsePrimaryExpr(Res, EndLoc)) - return true; - Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc); - return false; - case AsmToken::Dollar: - case AsmToken::At: - case AsmToken::String: - case AsmToken::Identifier: { - StringRef Identifier; - if (parseIdentifier(Identifier)) { - // We may have failed but $ may be a valid token. - if (getTok().is(AsmToken::Dollar)) { - if (Lexer.getMAI().getDollarIsPC()) { - Lex(); - // This is a '$' reference, which references the current PC. Emit a - // temporary label to the streamer and refer to it. - MCSymbol *Sym = Ctx.createTempSymbol(); - Out.EmitLabel(Sym); - Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, - getContext()); - EndLoc = FirstTokenLoc; - return false; - } - return Error(FirstTokenLoc, "invalid token in expression"); - } - } - // Parse symbol variant - std::pair<StringRef, StringRef> Split; - if (!MAI.useParensForSymbolVariant()) { - if (FirstTokenKind == AsmToken::String) { - if (Lexer.is(AsmToken::At)) { - Lex(); // eat @ - SMLoc AtLoc = getLexer().getLoc(); - StringRef VName; - if (parseIdentifier(VName)) - return Error(AtLoc, "expected symbol variant after '@'"); - - Split = std::make_pair(Identifier, VName); - } - } else { - Split = Identifier.split('@'); - } - } else if (Lexer.is(AsmToken::LParen)) { - Lex(); // eat '('. - StringRef VName; - parseIdentifier(VName); - // eat ')'. - if (parseToken(AsmToken::RParen, - "unexpected token in variant, expected ')'")) - return true; - Split = std::make_pair(Identifier, VName); - } - - EndLoc = SMLoc::getFromPointer(Identifier.end()); - - // This is a symbol reference. - StringRef SymbolName = Identifier; - if (SymbolName.empty()) - return Error(getLexer().getLoc(), "expected a symbol reference"); - - MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; - - // Lookup the symbol variant if used. - if (!Split.second.empty()) { - Variant = MCSymbolRefExpr::getVariantKindForName(Split.second); - if (Variant != MCSymbolRefExpr::VK_Invalid) { - SymbolName = Split.first; - } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) { - Variant = MCSymbolRefExpr::VK_None; - } else { - return Error(SMLoc::getFromPointer(Split.second.begin()), - "invalid variant '" + Split.second + "'"); - } - } - - MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName); - if (!Sym) - Sym = getContext().getOrCreateSymbol(SymbolName); - - // If this is an absolute variable reference, substitute it now to preserve - // semantics in the face of reassignment. - if (Sym->isVariable()) { - auto V = Sym->getVariableValue(/*SetUsed*/ false); - bool DoInline = isa<MCConstantExpr>(V) && !Variant; - if (auto TV = dyn_cast<MCTargetExpr>(V)) - DoInline = TV->inlineAssignedExpr(); - if (DoInline) { - if (Variant) - return Error(EndLoc, "unexpected modifier on variable reference"); - Res = Sym->getVariableValue(/*SetUsed*/ false); - return false; - } - } - - // Otherwise create a symbol ref. - Res = MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc); - return false; - } - case AsmToken::BigNum: - return TokError("literal value out of range for directive"); - case AsmToken::Integer: { - SMLoc Loc = getTok().getLoc(); - int64_t IntVal = getTok().getIntVal(); - Res = MCConstantExpr::create(IntVal, getContext()); - EndLoc = Lexer.getTok().getEndLoc(); - Lex(); // Eat token. - // Look for 'b' or 'f' following an Integer as a directional label - if (Lexer.getKind() == AsmToken::Identifier) { - StringRef IDVal = getTok().getString(); - // Lookup the symbol variant if used. - std::pair<StringRef, StringRef> Split = IDVal.split('@'); - MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; - if (Split.first.size() != IDVal.size()) { - Variant = MCSymbolRefExpr::getVariantKindForName(Split.second); - if (Variant == MCSymbolRefExpr::VK_Invalid) - return TokError("invalid variant '" + Split.second + "'"); - IDVal = Split.first; - } - if (IDVal == "f" || IDVal == "b") { - MCSymbol *Sym = - Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b"); - Res = MCSymbolRefExpr::create(Sym, Variant, getContext()); - if (IDVal == "b" && Sym->isUndefined()) - return Error(Loc, "directional label undefined"); - DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym)); - EndLoc = Lexer.getTok().getEndLoc(); - Lex(); // Eat identifier. - } - } - return false; - } - case AsmToken::Real: { - APFloat RealVal(APFloat::IEEEdouble(), getTok().getString()); - uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue(); - Res = MCConstantExpr::create(IntVal, getContext()); - EndLoc = Lexer.getTok().getEndLoc(); - Lex(); // Eat token. - return false; - } - case AsmToken::Dot: { - // This is a '.' reference, which references the current PC. Emit a - // temporary label to the streamer and refer to it. - MCSymbol *Sym = Ctx.createTempSymbol(); - Out.EmitLabel(Sym); - Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); - EndLoc = Lexer.getTok().getEndLoc(); - Lex(); // Eat identifier. - return false; - } - case AsmToken::LParen: - Lex(); // Eat the '('. - return parseParenExpr(Res, EndLoc); - case AsmToken::LBrac: - if (!PlatformParser->HasBracketExpressions()) - return TokError("brackets expression not supported on this target"); - Lex(); // Eat the '['. - return parseBracketExpr(Res, EndLoc); - case AsmToken::Minus: - Lex(); // Eat the operator. - if (parsePrimaryExpr(Res, EndLoc)) - return true; - Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc); - return false; - case AsmToken::Plus: - Lex(); // Eat the operator. - if (parsePrimaryExpr(Res, EndLoc)) - return true; - Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc); - return false; - case AsmToken::Tilde: - Lex(); // Eat the operator. - if (parsePrimaryExpr(Res, EndLoc)) - return true; - Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc); - return false; - // MIPS unary expression operators. The lexer won't generate these tokens if - // MCAsmInfo::HasMipsExpressions is false for the target. - case AsmToken::PercentCall16: - case AsmToken::PercentCall_Hi: - case AsmToken::PercentCall_Lo: - case AsmToken::PercentDtprel_Hi: - case AsmToken::PercentDtprel_Lo: - case AsmToken::PercentGot: - case AsmToken::PercentGot_Disp: - case AsmToken::PercentGot_Hi: - case AsmToken::PercentGot_Lo: - case AsmToken::PercentGot_Ofst: - case AsmToken::PercentGot_Page: - case AsmToken::PercentGottprel: - case AsmToken::PercentGp_Rel: - case AsmToken::PercentHi: - case AsmToken::PercentHigher: - case AsmToken::PercentHighest: - case AsmToken::PercentLo: - case AsmToken::PercentNeg: - case AsmToken::PercentPcrel_Hi: - case AsmToken::PercentPcrel_Lo: - case AsmToken::PercentTlsgd: - case AsmToken::PercentTlsldm: - case AsmToken::PercentTprel_Hi: - case AsmToken::PercentTprel_Lo: - Lex(); // Eat the operator. - if (Lexer.isNot(AsmToken::LParen)) - return TokError("expected '(' after operator"); - Lex(); // Eat the operator. - if (parseExpression(Res, EndLoc)) - return true; - if (Lexer.isNot(AsmToken::RParen)) - return TokError("expected ')'"); - Lex(); // Eat the operator. - Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx); - return !Res; - } -} - -bool AsmParser::parseExpression(const MCExpr *&Res) { - SMLoc EndLoc; - return parseExpression(Res, EndLoc); -} - -const MCExpr * -AsmParser::applyModifierToExpr(const MCExpr *E, - MCSymbolRefExpr::VariantKind Variant) { - // Ask the target implementation about this expression first. - const MCExpr *NewE = getTargetParser().applyModifierToExpr(E, Variant, Ctx); - if (NewE) - return NewE; - // Recurse over the given expression, rebuilding it to apply the given variant - // if there is exactly one symbol. - switch (E->getKind()) { - case MCExpr::Target: - case MCExpr::Constant: - return nullptr; - - case MCExpr::SymbolRef: { - const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E); - - if (SRE->getKind() != MCSymbolRefExpr::VK_None) { - TokError("invalid variant on expression '" + getTok().getIdentifier() + - "' (already modified)"); - return E; - } - - return MCSymbolRefExpr::create(&SRE->getSymbol(), Variant, getContext()); - } - - case MCExpr::Unary: { - const MCUnaryExpr *UE = cast<MCUnaryExpr>(E); - const MCExpr *Sub = applyModifierToExpr(UE->getSubExpr(), Variant); - if (!Sub) - return nullptr; - return MCUnaryExpr::create(UE->getOpcode(), Sub, getContext()); - } - - case MCExpr::Binary: { - const MCBinaryExpr *BE = cast<MCBinaryExpr>(E); - const MCExpr *LHS = applyModifierToExpr(BE->getLHS(), Variant); - const MCExpr *RHS = applyModifierToExpr(BE->getRHS(), Variant); - - if (!LHS && !RHS) - return nullptr; - - if (!LHS) - LHS = BE->getLHS(); - if (!RHS) - RHS = BE->getRHS(); - - return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, getContext()); - } - } - - llvm_unreachable("Invalid expression kind!"); -} - -/// This function checks if the next token is <string> type or arithmetic. -/// string that begin with character '<' must end with character '>'. -/// otherwise it is arithmetics. -/// If the function returns a 'true' value, -/// the End argument will be filled with the last location pointed to the '>' -/// character. - -/// There is a gap between the AltMacro's documentation and the single quote -/// implementation. GCC does not fully support this feature and so we will not -/// support it. -/// TODO: Adding single quote as a string. -static bool isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc) { - assert((StrLoc.getPointer() != nullptr) && - "Argument to the function cannot be a NULL value"); - const char *CharPtr = StrLoc.getPointer(); - while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') && - (*CharPtr != '\0')) { - if (*CharPtr == '!') - CharPtr++; - CharPtr++; - } - if (*CharPtr == '>') { - EndLoc = StrLoc.getFromPointer(CharPtr + 1); - return true; - } - return false; -} - -/// creating a string without the escape characters '!'. -static std::string altMacroString(StringRef AltMacroStr) { - std::string Res; - for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) { - if (AltMacroStr[Pos] == '!') - Pos++; - Res += AltMacroStr[Pos]; - } - return Res; -} - -/// Parse an expression and return it. -/// -/// expr ::= expr &&,|| expr -> lowest. -/// expr ::= expr |,^,&,! expr -/// expr ::= expr ==,!=,<>,<,<=,>,>= expr -/// expr ::= expr <<,>> expr -/// expr ::= expr +,- expr -/// expr ::= expr *,/,% expr -> highest. -/// expr ::= primaryexpr -/// -bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) { - // Parse the expression. - Res = nullptr; - if (getTargetParser().parsePrimaryExpr(Res, EndLoc) || - parseBinOpRHS(1, Res, EndLoc)) - return true; - - // As a special case, we support 'a op b @ modifier' by rewriting the - // expression to include the modifier. This is inefficient, but in general we - // expect users to use 'a@modifier op b'. - if (Lexer.getKind() == AsmToken::At) { - Lex(); - - if (Lexer.isNot(AsmToken::Identifier)) - return TokError("unexpected symbol modifier following '@'"); - - MCSymbolRefExpr::VariantKind Variant = - MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier()); - if (Variant == MCSymbolRefExpr::VK_Invalid) - return TokError("invalid variant '" + getTok().getIdentifier() + "'"); - - const MCExpr *ModifiedRes = applyModifierToExpr(Res, Variant); - if (!ModifiedRes) { - return TokError("invalid modifier '" + getTok().getIdentifier() + - "' (no symbols present)"); - } - - Res = ModifiedRes; - Lex(); - } - - // Try to constant fold it up front, if possible. Do not exploit - // assembler here. - int64_t Value; - if (Res->evaluateAsAbsolute(Value)) - Res = MCConstantExpr::create(Value, getContext()); - - return false; -} - -bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) { - Res = nullptr; - return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc); -} - -bool AsmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res, - SMLoc &EndLoc) { - if (parseParenExpr(Res, EndLoc)) - return true; - - for (; ParenDepth > 0; --ParenDepth) { - if (parseBinOpRHS(1, Res, EndLoc)) - return true; - - // We don't Lex() the last RParen. - // This is the same behavior as parseParenExpression(). - if (ParenDepth - 1 > 0) { - EndLoc = getTok().getEndLoc(); - if (parseToken(AsmToken::RParen, - "expected ')' in parentheses expression")) - return true; - } - } - return false; -} - -bool AsmParser::parseAbsoluteExpression(int64_t &Res) { - const MCExpr *Expr; - - SMLoc StartLoc = Lexer.getLoc(); - if (parseExpression(Expr)) - return true; - - if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr())) - return Error(StartLoc, "expected absolute expression"); - - return false; -} - -static unsigned getDarwinBinOpPrecedence(AsmToken::TokenKind K, - MCBinaryExpr::Opcode &Kind, - bool ShouldUseLogicalShr) { - switch (K) { - default: - return 0; // not a binop. - - // Lowest Precedence: &&, || - case AsmToken::AmpAmp: - Kind = MCBinaryExpr::LAnd; - return 1; - case AsmToken::PipePipe: - Kind = MCBinaryExpr::LOr; - return 1; - - // Low Precedence: |, &, ^ - // - // FIXME: gas seems to support '!' as an infix operator? - case AsmToken::Pipe: - Kind = MCBinaryExpr::Or; - return 2; - case AsmToken::Caret: - Kind = MCBinaryExpr::Xor; - return 2; - case AsmToken::Amp: - Kind = MCBinaryExpr::And; - return 2; - - // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >= - case AsmToken::EqualEqual: - Kind = MCBinaryExpr::EQ; - return 3; - case AsmToken::ExclaimEqual: - case AsmToken::LessGreater: - Kind = MCBinaryExpr::NE; - return 3; - case AsmToken::Less: - Kind = MCBinaryExpr::LT; - return 3; - case AsmToken::LessEqual: - Kind = MCBinaryExpr::LTE; - return 3; - case AsmToken::Greater: - Kind = MCBinaryExpr::GT; - return 3; - case AsmToken::GreaterEqual: - Kind = MCBinaryExpr::GTE; - return 3; - - // Intermediate Precedence: <<, >> - case AsmToken::LessLess: - Kind = MCBinaryExpr::Shl; - return 4; - case AsmToken::GreaterGreater: - Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr; - return 4; - - // High Intermediate Precedence: +, - - case AsmToken::Plus: - Kind = MCBinaryExpr::Add; - return 5; - case AsmToken::Minus: - Kind = MCBinaryExpr::Sub; - return 5; - - // Highest Precedence: *, /, % - case AsmToken::Star: - Kind = MCBinaryExpr::Mul; - return 6; - case AsmToken::Slash: - Kind = MCBinaryExpr::Div; - return 6; - case AsmToken::Percent: - Kind = MCBinaryExpr::Mod; - return 6; - } -} - -static unsigned getGNUBinOpPrecedence(AsmToken::TokenKind K, - MCBinaryExpr::Opcode &Kind, - bool ShouldUseLogicalShr) { - switch (K) { - default: - return 0; // not a binop. - - // Lowest Precedence: &&, || - case AsmToken::AmpAmp: - Kind = MCBinaryExpr::LAnd; - return 2; - case AsmToken::PipePipe: - Kind = MCBinaryExpr::LOr; - return 1; - - // Low Precedence: ==, !=, <>, <, <=, >, >= - case AsmToken::EqualEqual: - Kind = MCBinaryExpr::EQ; - return 3; - case AsmToken::ExclaimEqual: - case AsmToken::LessGreater: - Kind = MCBinaryExpr::NE; - return 3; - case AsmToken::Less: - Kind = MCBinaryExpr::LT; - return 3; - case AsmToken::LessEqual: - Kind = MCBinaryExpr::LTE; - return 3; - case AsmToken::Greater: - Kind = MCBinaryExpr::GT; - return 3; - case AsmToken::GreaterEqual: - Kind = MCBinaryExpr::GTE; - return 3; - - // Low Intermediate Precedence: +, - - case AsmToken::Plus: - Kind = MCBinaryExpr::Add; - return 4; - case AsmToken::Minus: - Kind = MCBinaryExpr::Sub; - return 4; - - // High Intermediate Precedence: |, &, ^ - // - // FIXME: gas seems to support '!' as an infix operator? - case AsmToken::Pipe: - Kind = MCBinaryExpr::Or; - return 5; - case AsmToken::Caret: - Kind = MCBinaryExpr::Xor; - return 5; - case AsmToken::Amp: - Kind = MCBinaryExpr::And; - return 5; - - // Highest Precedence: *, /, %, <<, >> - case AsmToken::Star: - Kind = MCBinaryExpr::Mul; - return 6; - case AsmToken::Slash: - Kind = MCBinaryExpr::Div; - return 6; - case AsmToken::Percent: - Kind = MCBinaryExpr::Mod; - return 6; - case AsmToken::LessLess: - Kind = MCBinaryExpr::Shl; - return 6; - case AsmToken::GreaterGreater: - Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr; - return 6; - } -} - -unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K, - MCBinaryExpr::Opcode &Kind) { - bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr(); - return IsDarwin ? getDarwinBinOpPrecedence(K, Kind, ShouldUseLogicalShr) - : getGNUBinOpPrecedence(K, Kind, ShouldUseLogicalShr); -} - -/// Parse all binary operators with precedence >= 'Precedence'. -/// Res contains the LHS of the expression on input. -bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, - SMLoc &EndLoc) { - SMLoc StartLoc = Lexer.getLoc(); - while (true) { - MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add; - unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind); - - // If the next token is lower precedence than we are allowed to eat, return - // successfully with what we ate already. - if (TokPrec < Precedence) - return false; - - Lex(); - - // Eat the next primary expression. - const MCExpr *RHS; - if (getTargetParser().parsePrimaryExpr(RHS, EndLoc)) - return true; - - // If BinOp binds less tightly with RHS than the operator after RHS, let - // the pending operator take RHS as its LHS. - MCBinaryExpr::Opcode Dummy; - unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy); - if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc)) - return true; - - // Merge LHS and RHS according to operator. - Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc); - } -} - -/// ParseStatement: -/// ::= EndOfStatement -/// ::= Label* Directive ...Operands... EndOfStatement -/// ::= Label* Identifier OperandList* EndOfStatement -bool AsmParser::parseStatement(ParseStatementInfo &Info, - MCAsmParserSemaCallback *SI) { - assert(!hasPendingError() && "parseStatement started with pending error"); - // Eat initial spaces and comments - while (Lexer.is(AsmToken::Space)) - Lex(); - if (Lexer.is(AsmToken::EndOfStatement)) { - // if this is a line comment we can drop it safely - if (getTok().getString().empty() || getTok().getString().front() == '\r' || - getTok().getString().front() == '\n') - Out.AddBlankLine(); - Lex(); - return false; - } - // Statements always start with an identifier. - AsmToken ID = getTok(); - SMLoc IDLoc = ID.getLoc(); - StringRef IDVal; - int64_t LocalLabelVal = -1; - if (Lexer.is(AsmToken::HashDirective)) - return parseCppHashLineFilenameComment(IDLoc); - // Allow an integer followed by a ':' as a directional local label. - if (Lexer.is(AsmToken::Integer)) { - LocalLabelVal = getTok().getIntVal(); - if (LocalLabelVal < 0) { - if (!TheCondState.Ignore) { - Lex(); // always eat a token - return Error(IDLoc, "unexpected token at start of statement"); - } - IDVal = ""; - } else { - IDVal = getTok().getString(); - Lex(); // Consume the integer token to be used as an identifier token. - if (Lexer.getKind() != AsmToken::Colon) { - if (!TheCondState.Ignore) { - Lex(); // always eat a token - return Error(IDLoc, "unexpected token at start of statement"); - } - } - } - } else if (Lexer.is(AsmToken::Dot)) { - // Treat '.' as a valid identifier in this context. - Lex(); - IDVal = "."; - } else if (Lexer.is(AsmToken::LCurly)) { - // Treat '{' as a valid identifier in this context. - Lex(); - IDVal = "{"; - - } else if (Lexer.is(AsmToken::RCurly)) { - // Treat '}' as a valid identifier in this context. - Lex(); - IDVal = "}"; - } else if (Lexer.is(AsmToken::Star) && - getTargetParser().starIsStartOfStatement()) { - // Accept '*' as a valid start of statement. - Lex(); - IDVal = "*"; - } else if (parseIdentifier(IDVal)) { - if (!TheCondState.Ignore) { - Lex(); // always eat a token - return Error(IDLoc, "unexpected token at start of statement"); - } - IDVal = ""; - } - - // Handle conditional assembly here before checking for skipping. We - // have to do this so that .endif isn't skipped in a ".if 0" block for - // example. - StringMap<DirectiveKind>::const_iterator DirKindIt = - DirectiveKindMap.find(IDVal); - DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end()) - ? DK_NO_DIRECTIVE - : DirKindIt->getValue(); - switch (DirKind) { - default: - break; - case DK_IF: - case DK_IFEQ: - case DK_IFGE: - case DK_IFGT: - case DK_IFLE: - case DK_IFLT: - case DK_IFNE: - return parseDirectiveIf(IDLoc, DirKind); - case DK_IFB: - return parseDirectiveIfb(IDLoc, true); - case DK_IFNB: - return parseDirectiveIfb(IDLoc, false); - case DK_IFC: - return parseDirectiveIfc(IDLoc, true); - case DK_IFEQS: - return parseDirectiveIfeqs(IDLoc, true); - case DK_IFNC: - return parseDirectiveIfc(IDLoc, false); - case DK_IFNES: - return parseDirectiveIfeqs(IDLoc, false); - case DK_IFDEF: - return parseDirectiveIfdef(IDLoc, true); - case DK_IFNDEF: - case DK_IFNOTDEF: - return parseDirectiveIfdef(IDLoc, false); - case DK_ELSEIF: - return parseDirectiveElseIf(IDLoc); - case DK_ELSE: - return parseDirectiveElse(IDLoc); - case DK_ENDIF: - return parseDirectiveEndIf(IDLoc); - } - - // Ignore the statement if in the middle of inactive conditional - // (e.g. ".if 0"). - if (TheCondState.Ignore) { - eatToEndOfStatement(); - return false; - } - - // FIXME: Recurse on local labels? - - // See what kind of statement we have. - switch (Lexer.getKind()) { - case AsmToken::Colon: { - if (!getTargetParser().isLabel(ID)) - break; - if (checkForValidSection()) - return true; - - // identifier ':' -> Label. - Lex(); - - // Diagnose attempt to use '.' as a label. - if (IDVal == ".") - return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label"); - - // Diagnose attempt to use a variable as a label. - // - // FIXME: Diagnostics. Note the location of the definition as a label. - // FIXME: This doesn't diagnose assignment to a symbol which has been - // implicitly marked as external. - MCSymbol *Sym; - if (LocalLabelVal == -1) { - if (ParsingInlineAsm && SI) { - StringRef RewrittenLabel = - SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true); - assert(!RewrittenLabel.empty() && - "We should have an internal name here."); - Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(), - RewrittenLabel); - IDVal = RewrittenLabel; - } - Sym = getContext().getOrCreateSymbol(IDVal); - } else - Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal); - // End of Labels should be treated as end of line for lexing - // purposes but that information is not available to the Lexer who - // does not understand Labels. This may cause us to see a Hash - // here instead of a preprocessor line comment. - if (getTok().is(AsmToken::Hash)) { - StringRef CommentStr = parseStringToEndOfStatement(); - Lexer.Lex(); - Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr)); - } - - // Consume any end of statement token, if present, to avoid spurious - // AddBlankLine calls(). - if (getTok().is(AsmToken::EndOfStatement)) { - Lex(); - } - - getTargetParser().doBeforeLabelEmit(Sym); - - // Emit the label. - if (!getTargetParser().isParsingInlineAsm()) - Out.EmitLabel(Sym, IDLoc); - - // If we are generating dwarf for assembly source files then gather the - // info to make a dwarf label entry for this label if needed. - if (enabledGenDwarfForAssembly()) - MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(), - IDLoc); - - getTargetParser().onLabelParsed(Sym); - - return false; - } - - case AsmToken::Equal: - if (!getTargetParser().equalIsAsmAssignment()) - break; - // identifier '=' ... -> assignment statement - Lex(); - - return parseAssignment(IDVal, true); - - default: // Normal instruction or directive. - break; - } - - // If macros are enabled, check to see if this is a macro instantiation. - if (areMacrosEnabled()) - if (const MCAsmMacro *M = getContext().lookupMacro(IDVal)) { - return handleMacroEntry(M, IDLoc); - } - - // Otherwise, we have a normal instruction or directive. - - // Directives start with "." - if (IDVal.startswith(".") && IDVal != ".") { - // There are several entities interested in parsing directives: - // - // 1. The target-specific assembly parser. Some directives are target - // specific or may potentially behave differently on certain targets. - // 2. Asm parser extensions. For example, platform-specific parsers - // (like the ELF parser) register themselves as extensions. - // 3. The generic directive parser implemented by this class. These are - // all the directives that behave in a target and platform independent - // manner, or at least have a default behavior that's shared between - // all targets and platforms. - - getTargetParser().flushPendingInstructions(getStreamer()); - - SMLoc StartTokLoc = getTok().getLoc(); - bool TPDirectiveReturn = getTargetParser().ParseDirective(ID); - - if (hasPendingError()) - return true; - // Currently the return value should be true if we are - // uninterested but as this is at odds with the standard parsing - // convention (return true = error) we have instances of a parsed - // directive that fails returning true as an error. Catch these - // cases as best as possible errors here. - if (TPDirectiveReturn && StartTokLoc != getTok().getLoc()) - return true; - // Return if we did some parsing or believe we succeeded. - if (!TPDirectiveReturn || StartTokLoc != getTok().getLoc()) - return false; - - // Next, check the extension directive map to see if any extension has - // registered itself to parse this directive. - std::pair<MCAsmParserExtension *, DirectiveHandler> Handler = - ExtensionDirectiveMap.lookup(IDVal); - if (Handler.first) - return (*Handler.second)(Handler.first, IDVal, IDLoc); - - // Finally, if no one else is interested in this directive, it must be - // generic and familiar to this class. - switch (DirKind) { - default: - break; - case DK_SET: - case DK_EQU: - return parseDirectiveSet(IDVal, true); - case DK_EQUIV: - return parseDirectiveSet(IDVal, false); - case DK_ASCII: - return parseDirectiveAscii(IDVal, false); - case DK_ASCIZ: - case DK_STRING: - return parseDirectiveAscii(IDVal, true); - case DK_BYTE: - case DK_DC_B: - return parseDirectiveValue(IDVal, 1); - case DK_DC: - case DK_DC_W: - case DK_SHORT: - case DK_VALUE: - case DK_2BYTE: - return parseDirectiveValue(IDVal, 2); - case DK_LONG: - case DK_INT: - case DK_4BYTE: - case DK_DC_L: - return parseDirectiveValue(IDVal, 4); - case DK_QUAD: - case DK_8BYTE: - return parseDirectiveValue(IDVal, 8); - case DK_DC_A: - return parseDirectiveValue( - IDVal, getContext().getAsmInfo()->getCodePointerSize()); - case DK_OCTA: - return parseDirectiveOctaValue(IDVal); - case DK_SINGLE: - case DK_FLOAT: - case DK_DC_S: - return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle()); - case DK_DOUBLE: - case DK_DC_D: - return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble()); - case DK_ALIGN: { - bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes(); - return parseDirectiveAlign(IsPow2, /*ExprSize=*/1); - } - case DK_ALIGN32: { - bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes(); - return parseDirectiveAlign(IsPow2, /*ExprSize=*/4); - } - case DK_BALIGN: - return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1); - case DK_BALIGNW: - return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2); - case DK_BALIGNL: - return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4); - case DK_P2ALIGN: - return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1); - case DK_P2ALIGNW: - return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2); - case DK_P2ALIGNL: - return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4); - case DK_ORG: - return parseDirectiveOrg(); - case DK_FILL: - return parseDirectiveFill(); - case DK_ZERO: - return parseDirectiveZero(); - case DK_EXTERN: - eatToEndOfStatement(); // .extern is the default, ignore it. - return false; - case DK_GLOBL: - case DK_GLOBAL: - return parseDirectiveSymbolAttribute(MCSA_Global); - case DK_LAZY_REFERENCE: - return parseDirectiveSymbolAttribute(MCSA_LazyReference); - case DK_NO_DEAD_STRIP: - return parseDirectiveSymbolAttribute(MCSA_NoDeadStrip); - case DK_SYMBOL_RESOLVER: - return parseDirectiveSymbolAttribute(MCSA_SymbolResolver); - case DK_PRIVATE_EXTERN: - return parseDirectiveSymbolAttribute(MCSA_PrivateExtern); - case DK_REFERENCE: - return parseDirectiveSymbolAttribute(MCSA_Reference); - case DK_WEAK_DEFINITION: - return parseDirectiveSymbolAttribute(MCSA_WeakDefinition); - case DK_WEAK_REFERENCE: - return parseDirectiveSymbolAttribute(MCSA_WeakReference); - case DK_WEAK_DEF_CAN_BE_HIDDEN: - return parseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate); - case DK_COLD: - return parseDirectiveSymbolAttribute(MCSA_Cold); - case DK_COMM: - case DK_COMMON: - return parseDirectiveComm(/*IsLocal=*/false); - case DK_LCOMM: - return parseDirectiveComm(/*IsLocal=*/true); - case DK_ABORT: - return parseDirectiveAbort(); - case DK_INCLUDE: - return parseDirectiveInclude(); - case DK_INCBIN: - return parseDirectiveIncbin(); - case DK_CODE16: - case DK_CODE16GCC: - return TokError(Twine(IDVal) + - " not currently supported for this target"); - case DK_REPT: - return parseDirectiveRept(IDLoc, IDVal); - case DK_IRP: - return parseDirectiveIrp(IDLoc); - case DK_IRPC: - return parseDirectiveIrpc(IDLoc); - case DK_ENDR: - return parseDirectiveEndr(IDLoc); - case DK_BUNDLE_ALIGN_MODE: - return parseDirectiveBundleAlignMode(); - case DK_BUNDLE_LOCK: - return parseDirectiveBundleLock(); - case DK_BUNDLE_UNLOCK: - return parseDirectiveBundleUnlock(); - case DK_SLEB128: - return parseDirectiveLEB128(true); - case DK_ULEB128: - return parseDirectiveLEB128(false); - case DK_SPACE: - case DK_SKIP: - return parseDirectiveSpace(IDVal); - case DK_FILE: - return parseDirectiveFile(IDLoc); - case DK_LINE: - return parseDirectiveLine(); - case DK_LOC: - return parseDirectiveLoc(); - case DK_STABS: - return parseDirectiveStabs(); - case DK_CV_FILE: - return parseDirectiveCVFile(); - case DK_CV_FUNC_ID: - return parseDirectiveCVFuncId(); - case DK_CV_INLINE_SITE_ID: - return parseDirectiveCVInlineSiteId(); - case DK_CV_LOC: - return parseDirectiveCVLoc(); - case DK_CV_LINETABLE: - return parseDirectiveCVLinetable(); - case DK_CV_INLINE_LINETABLE: - return parseDirectiveCVInlineLinetable(); - case DK_CV_DEF_RANGE: - return parseDirectiveCVDefRange(); - case DK_CV_STRING: - return parseDirectiveCVString(); - case DK_CV_STRINGTABLE: - return parseDirectiveCVStringTable(); - case DK_CV_FILECHECKSUMS: - return parseDirectiveCVFileChecksums(); - case DK_CV_FILECHECKSUM_OFFSET: - return parseDirectiveCVFileChecksumOffset(); - case DK_CV_FPO_DATA: - return parseDirectiveCVFPOData(); - case DK_CFI_SECTIONS: - return parseDirectiveCFISections(); - case DK_CFI_STARTPROC: - return parseDirectiveCFIStartProc(); - case DK_CFI_ENDPROC: - return parseDirectiveCFIEndProc(); - case DK_CFI_DEF_CFA: - return parseDirectiveCFIDefCfa(IDLoc); - case DK_CFI_DEF_CFA_OFFSET: - return parseDirectiveCFIDefCfaOffset(); - case DK_CFI_ADJUST_CFA_OFFSET: - return parseDirectiveCFIAdjustCfaOffset(); - case DK_CFI_DEF_CFA_REGISTER: - return parseDirectiveCFIDefCfaRegister(IDLoc); - case DK_CFI_OFFSET: - return parseDirectiveCFIOffset(IDLoc); - case DK_CFI_REL_OFFSET: - return parseDirectiveCFIRelOffset(IDLoc); - case DK_CFI_PERSONALITY: - return parseDirectiveCFIPersonalityOrLsda(true); - case DK_CFI_LSDA: - return parseDirectiveCFIPersonalityOrLsda(false); - case DK_CFI_REMEMBER_STATE: - return parseDirectiveCFIRememberState(); - case DK_CFI_RESTORE_STATE: - return parseDirectiveCFIRestoreState(); - case DK_CFI_SAME_VALUE: - return parseDirectiveCFISameValue(IDLoc); - case DK_CFI_RESTORE: - return parseDirectiveCFIRestore(IDLoc); - case DK_CFI_ESCAPE: - return parseDirectiveCFIEscape(); - case DK_CFI_RETURN_COLUMN: - return parseDirectiveCFIReturnColumn(IDLoc); - case DK_CFI_SIGNAL_FRAME: - return parseDirectiveCFISignalFrame(); - case DK_CFI_UNDEFINED: - return parseDirectiveCFIUndefined(IDLoc); - case DK_CFI_REGISTER: - return parseDirectiveCFIRegister(IDLoc); - case DK_CFI_WINDOW_SAVE: - return parseDirectiveCFIWindowSave(); - case DK_MACROS_ON: - case DK_MACROS_OFF: - return parseDirectiveMacrosOnOff(IDVal); - case DK_MACRO: - return parseDirectiveMacro(IDLoc); - case DK_ALTMACRO: - case DK_NOALTMACRO: - return parseDirectiveAltmacro(IDVal); - case DK_EXITM: - return parseDirectiveExitMacro(IDVal); - case DK_ENDM: - case DK_ENDMACRO: - return parseDirectiveEndMacro(IDVal); - case DK_PURGEM: - return parseDirectivePurgeMacro(IDLoc); - case DK_END: - return parseDirectiveEnd(IDLoc); - case DK_ERR: - return parseDirectiveError(IDLoc, false); - case DK_ERROR: - return parseDirectiveError(IDLoc, true); - case DK_WARNING: - return parseDirectiveWarning(IDLoc); - case DK_RELOC: - return parseDirectiveReloc(IDLoc); - case DK_DCB: - case DK_DCB_W: - return parseDirectiveDCB(IDVal, 2); - case DK_DCB_B: - return parseDirectiveDCB(IDVal, 1); - case DK_DCB_D: - return parseDirectiveRealDCB(IDVal, APFloat::IEEEdouble()); - case DK_DCB_L: - return parseDirectiveDCB(IDVal, 4); - case DK_DCB_S: - return parseDirectiveRealDCB(IDVal, APFloat::IEEEsingle()); - case DK_DC_X: - case DK_DCB_X: - return TokError(Twine(IDVal) + - " not currently supported for this target"); - case DK_DS: - case DK_DS_W: - return parseDirectiveDS(IDVal, 2); - case DK_DS_B: - return parseDirectiveDS(IDVal, 1); - case DK_DS_D: - return parseDirectiveDS(IDVal, 8); - case DK_DS_L: - case DK_DS_S: - return parseDirectiveDS(IDVal, 4); - case DK_DS_P: - case DK_DS_X: - return parseDirectiveDS(IDVal, 12); - case DK_PRINT: - return parseDirectivePrint(IDLoc); - case DK_ADDRSIG: - return parseDirectiveAddrsig(); - case DK_ADDRSIG_SYM: - return parseDirectiveAddrsigSym(); - } - - return Error(IDLoc, "unknown directive"); - } - - // __asm _emit or __asm __emit - if (ParsingInlineAsm && (IDVal == "_emit" || IDVal == "__emit" || - IDVal == "_EMIT" || IDVal == "__EMIT")) - return parseDirectiveMSEmit(IDLoc, Info, IDVal.size()); - - // __asm align - if (ParsingInlineAsm && (IDVal == "align" || IDVal == "ALIGN")) - return parseDirectiveMSAlign(IDLoc, Info); - - if (ParsingInlineAsm && (IDVal == "even" || IDVal == "EVEN")) - Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4); - if (checkForValidSection()) - return true; - - // Canonicalize the opcode to lower case. - std::string OpcodeStr = IDVal.lower(); - ParseInstructionInfo IInfo(Info.AsmRewrites); - bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID, - Info.ParsedOperands); - Info.ParseError = ParseHadError; - - // Dump the parsed representation, if requested. - if (getShowParsedOperands()) { - SmallString<256> Str; - raw_svector_ostream OS(Str); - OS << "parsed instruction: ["; - for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) { - if (i != 0) - OS << ", "; - Info.ParsedOperands[i]->print(OS); - } - OS << "]"; - - printMessage(IDLoc, SourceMgr::DK_Note, OS.str()); - } - - // Fail even if ParseInstruction erroneously returns false. - if (hasPendingError() || ParseHadError) - return true; - - // If we are generating dwarf for the current section then generate a .loc - // directive for the instruction. - if (!ParseHadError && enabledGenDwarfForAssembly() && - getContext().getGenDwarfSectionSyms().count( - getStreamer().getCurrentSectionOnly())) { - unsigned Line; - if (ActiveMacros.empty()) - Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer); - else - Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc, - ActiveMacros.front()->ExitBuffer); - - // If we previously parsed a cpp hash file line comment then make sure the - // current Dwarf File is for the CppHashFilename if not then emit the - // Dwarf File table for it and adjust the line number for the .loc. - if (!CppHashInfo.Filename.empty()) { - unsigned FileNumber = getStreamer().EmitDwarfFileDirective( - 0, StringRef(), CppHashInfo.Filename); - getContext().setGenDwarfFileNumber(FileNumber); - - unsigned CppHashLocLineNo = - SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf); - Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo); - } - - getStreamer().EmitDwarfLocDirective( - getContext().getGenDwarfFileNumber(), Line, 0, - DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0, - StringRef()); - } - - // If parsing succeeded, match the instruction. - if (!ParseHadError) { - uint64_t ErrorInfo; - if (getTargetParser().MatchAndEmitInstruction( - IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo, - getTargetParser().isParsingInlineAsm())) - return true; - } - return false; -} - -// Parse and erase curly braces marking block start/end -bool -AsmParser::parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> &AsmStrRewrites) { - // Identify curly brace marking block start/end - if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly)) - return false; - - SMLoc StartLoc = Lexer.getLoc(); - Lex(); // Eat the brace - if (Lexer.is(AsmToken::EndOfStatement)) - Lex(); // Eat EndOfStatement following the brace - - // Erase the block start/end brace from the output asm string - AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() - - StartLoc.getPointer()); - return true; -} - -/// parseCppHashLineFilenameComment as this: -/// ::= # number "filename" -bool AsmParser::parseCppHashLineFilenameComment(SMLoc L) { - Lex(); // Eat the hash token. - // Lexer only ever emits HashDirective if it fully formed if it's - // done the checking already so this is an internal error. - assert(getTok().is(AsmToken::Integer) && - "Lexing Cpp line comment: Expected Integer"); - int64_t LineNumber = getTok().getIntVal(); - Lex(); - assert(getTok().is(AsmToken::String) && - "Lexing Cpp line comment: Expected String"); - StringRef Filename = getTok().getString(); - Lex(); - - // Get rid of the enclosing quotes. - Filename = Filename.substr(1, Filename.size() - 2); - - // Save the SMLoc, Filename and LineNumber for later use by diagnostics - // and possibly DWARF file info. - CppHashInfo.Loc = L; - CppHashInfo.Filename = Filename; - CppHashInfo.LineNumber = LineNumber; - CppHashInfo.Buf = CurBuffer; - if (FirstCppHashFilename.empty()) - FirstCppHashFilename = Filename; - return false; -} - -/// will use the last parsed cpp hash line filename comment -/// for the Filename and LineNo if any in the diagnostic. -void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { - const AsmParser *Parser = static_cast<const AsmParser *>(Context); - raw_ostream &OS = errs(); - - const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr(); - SMLoc DiagLoc = Diag.getLoc(); - unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); - unsigned CppHashBuf = - Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc); - - // Like SourceMgr::printMessage() we need to print the include stack if any - // before printing the message. - unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); - if (!Parser->SavedDiagHandler && DiagCurBuffer && - DiagCurBuffer != DiagSrcMgr.getMainFileID()) { - SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer); - DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS); - } - - // If we have not parsed a cpp hash line filename comment or the source - // manager changed or buffer changed (like in a nested include) then just - // print the normal diagnostic using its Filename and LineNo. - if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr || - DiagBuf != CppHashBuf) { - if (Parser->SavedDiagHandler) - Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext); - else - Diag.print(nullptr, OS); - return; - } - - // Use the CppHashFilename and calculate a line number based on the - // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc - // for the diagnostic. - const std::string &Filename = Parser->CppHashInfo.Filename; - - int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf); - int CppHashLocLineNo = - Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf); - int LineNo = - Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo); - - SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo, - Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(), - Diag.getLineContents(), Diag.getRanges()); - - if (Parser->SavedDiagHandler) - Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext); - else - NewDiag.print(nullptr, OS); -} - -// FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The -// difference being that that function accepts '@' as part of identifiers and -// we can't do that. AsmLexer.cpp should probably be changed to handle -// '@' as a special case when needed. -static bool isIdentifierChar(char c) { - return isalnum(static_cast<unsigned char>(c)) || c == '_' || c == '$' || - c == '.'; -} - -bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, - ArrayRef<MCAsmMacroParameter> Parameters, - ArrayRef<MCAsmMacroArgument> A, - bool EnableAtPseudoVariable, SMLoc L) { - unsigned NParameters = Parameters.size(); - bool HasVararg = NParameters ? Parameters.back().Vararg : false; - if ((!IsDarwin || NParameters != 0) && NParameters != A.size()) - return Error(L, "Wrong number of arguments"); - - // A macro without parameters is handled differently on Darwin: - // gas accepts no arguments and does no substitutions - while (!Body.empty()) { - // Scan for the next substitution. - std::size_t End = Body.size(), Pos = 0; - for (; Pos != End; ++Pos) { - // Check for a substitution or escape. - if (IsDarwin && !NParameters) { - // This macro has no parameters, look for $0, $1, etc. - if (Body[Pos] != '$' || Pos + 1 == End) - continue; - - char Next = Body[Pos + 1]; - if (Next == '$' || Next == 'n' || - isdigit(static_cast<unsigned char>(Next))) - break; - } else { - // This macro has parameters, look for \foo, \bar, etc. - if (Body[Pos] == '\\' && Pos + 1 != End) - break; - } - } - - // Add the prefix. - OS << Body.slice(0, Pos); - - // Check if we reached the end. - if (Pos == End) - break; - - if (IsDarwin && !NParameters) { - switch (Body[Pos + 1]) { - // $$ => $ - case '$': - OS << '$'; - break; - - // $n => number of arguments - case 'n': - OS << A.size(); - break; - - // $[0-9] => argument - default: { - // Missing arguments are ignored. - unsigned Index = Body[Pos + 1] - '0'; - if (Index >= A.size()) - break; - - // Otherwise substitute with the token values, with spaces eliminated. - for (const AsmToken &Token : A[Index]) - OS << Token.getString(); - break; - } - } - Pos += 2; - } else { - unsigned I = Pos + 1; - - // Check for the \@ pseudo-variable. - if (EnableAtPseudoVariable && Body[I] == '@' && I + 1 != End) - ++I; - else - while (isIdentifierChar(Body[I]) && I + 1 != End) - ++I; - - const char *Begin = Body.data() + Pos + 1; - StringRef Argument(Begin, I - (Pos + 1)); - unsigned Index = 0; - - if (Argument == "@") { - OS << NumOfMacroInstantiations; - Pos += 2; - } else { - for (; Index < NParameters; ++Index) - if (Parameters[Index].Name == Argument) - break; - - if (Index == NParameters) { - if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')') - Pos += 3; - else { - OS << '\\' << Argument; - Pos = I; - } - } else { - bool VarargParameter = HasVararg && Index == (NParameters - 1); - for (const AsmToken &Token : A[Index]) - // For altmacro mode, you can write '%expr'. - // The prefix '%' evaluates the expression 'expr' - // and uses the result as a string (e.g. replace %(1+2) with the - // string "3"). - // Here, we identify the integer token which is the result of the - // absolute expression evaluation and replace it with its string - // representation. - if (AltMacroMode && Token.getString().front() == '%' && - Token.is(AsmToken::Integer)) - // Emit an integer value to the buffer. - OS << Token.getIntVal(); - // Only Token that was validated as a string and begins with '<' - // is considered altMacroString!!! - else if (AltMacroMode && Token.getString().front() == '<' && - Token.is(AsmToken::String)) { - OS << altMacroString(Token.getStringContents()); - } - // We expect no quotes around the string's contents when - // parsing for varargs. - else if (Token.isNot(AsmToken::String) || VarargParameter) - OS << Token.getString(); - else - OS << Token.getStringContents(); - - Pos += 1 + Argument.size(); - } - } - } - // Update the scan point. - Body = Body.substr(Pos); - } - - return false; -} - -MacroInstantiation::MacroInstantiation(SMLoc IL, int EB, SMLoc EL, - size_t CondStackDepth) - : InstantiationLoc(IL), ExitBuffer(EB), ExitLoc(EL), - CondStackDepth(CondStackDepth) {} - -static bool isOperator(AsmToken::TokenKind kind) { - switch (kind) { - default: - return false; - case AsmToken::Plus: - case AsmToken::Minus: - case AsmToken::Tilde: - case AsmToken::Slash: - case AsmToken::Star: - case AsmToken::Dot: - case AsmToken::Equal: - case AsmToken::EqualEqual: - case AsmToken::Pipe: - case AsmToken::PipePipe: - case AsmToken::Caret: - case AsmToken::Amp: - case AsmToken::AmpAmp: - case AsmToken::Exclaim: - case AsmToken::ExclaimEqual: - case AsmToken::Less: - case AsmToken::LessEqual: - case AsmToken::LessLess: - case AsmToken::LessGreater: - case AsmToken::Greater: - case AsmToken::GreaterEqual: - case AsmToken::GreaterGreater: - return true; - } -} - -namespace { - -class AsmLexerSkipSpaceRAII { -public: - AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) { - Lexer.setSkipSpace(SkipSpace); - } - - ~AsmLexerSkipSpaceRAII() { - Lexer.setSkipSpace(true); - } - -private: - AsmLexer &Lexer; -}; - -} // end anonymous namespace - -bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) { - - if (Vararg) { - if (Lexer.isNot(AsmToken::EndOfStatement)) { - StringRef Str = parseStringToEndOfStatement(); - MA.emplace_back(AsmToken::String, Str); - } - return false; - } - - unsigned ParenLevel = 0; - - // Darwin doesn't use spaces to delmit arguments. - AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin); - - bool SpaceEaten; - - while (true) { - SpaceEaten = false; - if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal)) - return TokError("unexpected token in macro instantiation"); - - if (ParenLevel == 0) { - - if (Lexer.is(AsmToken::Comma)) - break; - - if (Lexer.is(AsmToken::Space)) { - SpaceEaten = true; - Lexer.Lex(); // Eat spaces - } - - // Spaces can delimit parameters, but could also be part an expression. - // If the token after a space is an operator, add the token and the next - // one into this argument - if (!IsDarwin) { - if (isOperator(Lexer.getKind())) { - MA.push_back(getTok()); - Lexer.Lex(); - - // Whitespace after an operator can be ignored. - if (Lexer.is(AsmToken::Space)) - Lexer.Lex(); - - continue; - } - } - if (SpaceEaten) - break; - } - - // handleMacroEntry relies on not advancing the lexer here - // to be able to fill in the remaining default parameter values - if (Lexer.is(AsmToken::EndOfStatement)) - break; - - // Adjust the current parentheses level. - if (Lexer.is(AsmToken::LParen)) - ++ParenLevel; - else if (Lexer.is(AsmToken::RParen) && ParenLevel) - --ParenLevel; - - // Append the token to the current argument list. - MA.push_back(getTok()); - Lexer.Lex(); - } - - if (ParenLevel != 0) - return TokError("unbalanced parentheses in macro argument"); - return false; -} - -// Parse the macro instantiation arguments. -bool AsmParser::parseMacroArguments(const MCAsmMacro *M, - MCAsmMacroArguments &A) { - const unsigned NParameters = M ? M->Parameters.size() : 0; - bool NamedParametersFound = false; - SmallVector<SMLoc, 4> FALocs; - - A.resize(NParameters); - FALocs.resize(NParameters); - - // Parse two kinds of macro invocations: - // - macros defined without any parameters accept an arbitrary number of them - // - macros defined with parameters accept at most that many of them - bool HasVararg = NParameters ? M->Parameters.back().Vararg : false; - for (unsigned Parameter = 0; !NParameters || Parameter < NParameters; - ++Parameter) { - SMLoc IDLoc = Lexer.getLoc(); - MCAsmMacroParameter FA; - - if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) { - if (parseIdentifier(FA.Name)) - return Error(IDLoc, "invalid argument identifier for formal argument"); - - if (Lexer.isNot(AsmToken::Equal)) - return TokError("expected '=' after formal parameter identifier"); - - Lex(); - - NamedParametersFound = true; - } - bool Vararg = HasVararg && Parameter == (NParameters - 1); - - if (NamedParametersFound && FA.Name.empty()) - return Error(IDLoc, "cannot mix positional and keyword arguments"); - - SMLoc StrLoc = Lexer.getLoc(); - SMLoc EndLoc; - if (AltMacroMode && Lexer.is(AsmToken::Percent)) { - const MCExpr *AbsoluteExp; - int64_t Value; - /// Eat '%' - Lex(); - if (parseExpression(AbsoluteExp, EndLoc)) - return false; - if (!AbsoluteExp->evaluateAsAbsolute(Value, - getStreamer().getAssemblerPtr())) - return Error(StrLoc, "expected absolute expression"); - const char *StrChar = StrLoc.getPointer(); - const char *EndChar = EndLoc.getPointer(); - AsmToken newToken(AsmToken::Integer, - StringRef(StrChar, EndChar - StrChar), Value); - FA.Value.push_back(newToken); - } else if (AltMacroMode && Lexer.is(AsmToken::Less) && - isAltmacroString(StrLoc, EndLoc)) { - const char *StrChar = StrLoc.getPointer(); - const char *EndChar = EndLoc.getPointer(); - jumpToLoc(EndLoc, CurBuffer); - /// Eat from '<' to '>' - Lex(); - AsmToken newToken(AsmToken::String, - StringRef(StrChar, EndChar - StrChar)); - FA.Value.push_back(newToken); - } else if(parseMacroArgument(FA.Value, Vararg)) - return true; - - unsigned PI = Parameter; - if (!FA.Name.empty()) { - unsigned FAI = 0; - for (FAI = 0; FAI < NParameters; ++FAI) - if (M->Parameters[FAI].Name == FA.Name) - break; - - if (FAI >= NParameters) { - assert(M && "expected macro to be defined"); - return Error(IDLoc, "parameter named '" + FA.Name + - "' does not exist for macro '" + M->Name + "'"); - } - PI = FAI; - } - - if (!FA.Value.empty()) { - if (A.size() <= PI) - A.resize(PI + 1); - A[PI] = FA.Value; - - if (FALocs.size() <= PI) - FALocs.resize(PI + 1); - - FALocs[PI] = Lexer.getLoc(); - } - - // At the end of the statement, fill in remaining arguments that have - // default values. If there aren't any, then the next argument is - // required but missing - if (Lexer.is(AsmToken::EndOfStatement)) { - bool Failure = false; - for (unsigned FAI = 0; FAI < NParameters; ++FAI) { - if (A[FAI].empty()) { - if (M->Parameters[FAI].Required) { - Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(), - "missing value for required parameter " - "'" + M->Parameters[FAI].Name + "' in macro '" + M->Name + "'"); - Failure = true; - } - - if (!M->Parameters[FAI].Value.empty()) - A[FAI] = M->Parameters[FAI].Value; - } - } - return Failure; - } - - if (Lexer.is(AsmToken::Comma)) - Lex(); - } - - return TokError("too many positional arguments"); -} - -bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) { - // Arbitrarily limit macro nesting depth (default matches 'as'). We can - // eliminate this, although we should protect against infinite loops. - unsigned MaxNestingDepth = AsmMacroMaxNestingDepth; - if (ActiveMacros.size() == MaxNestingDepth) { - std::ostringstream MaxNestingDepthError; - MaxNestingDepthError << "macros cannot be nested more than " - << MaxNestingDepth << " levels deep." - << " Use -asm-macro-max-nesting-depth to increase " - "this limit."; - return TokError(MaxNestingDepthError.str()); - } - - MCAsmMacroArguments A; - if (parseMacroArguments(M, A)) - return true; - - // Macro instantiation is lexical, unfortunately. We construct a new buffer - // to hold the macro body with substitutions. - SmallString<256> Buf; - StringRef Body = M->Body; - raw_svector_ostream OS(Buf); - - if (expandMacro(OS, Body, M->Parameters, A, true, getTok().getLoc())) - return true; - - // We include the .endmacro in the buffer as our cue to exit the macro - // instantiation. - OS << ".endmacro\n"; - - std::unique_ptr<MemoryBuffer> Instantiation = - MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>"); - - // Create the macro instantiation object and add to the current macro - // instantiation stack. - MacroInstantiation *MI = new MacroInstantiation( - NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()); - ActiveMacros.push_back(MI); - - ++NumOfMacroInstantiations; - - // Jump to the macro instantiation and prime the lexer. - CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc()); - Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); - Lex(); - - return false; -} - -void AsmParser::handleMacroExit() { - // Jump to the EndOfStatement we should return to, and consume it. - jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer); - Lex(); - - // Pop the instantiation entry. - delete ActiveMacros.back(); - ActiveMacros.pop_back(); -} - -bool AsmParser::parseAssignment(StringRef Name, bool allow_redef, - bool NoDeadStrip) { - MCSymbol *Sym; - const MCExpr *Value; - if (MCParserUtils::parseAssignmentExpression(Name, allow_redef, *this, Sym, - Value)) - return true; - - if (!Sym) { - // In the case where we parse an expression starting with a '.', we will - // not generate an error, nor will we create a symbol. In this case we - // should just return out. - return false; - } - - // Do the assignment. - Out.EmitAssignment(Sym, Value); - if (NoDeadStrip) - Out.EmitSymbolAttribute(Sym, MCSA_NoDeadStrip); - - return false; -} - -/// parseIdentifier: -/// ::= identifier -/// ::= string -bool AsmParser::parseIdentifier(StringRef &Res) { - // The assembler has relaxed rules for accepting identifiers, in particular we - // allow things like '.globl $foo' and '.def @feat.00', which would normally be - // separate tokens. At this level, we have already lexed so we cannot (currently) - // handle this as a context dependent token, instead we detect adjacent tokens - // and return the combined identifier. - if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) { - SMLoc PrefixLoc = getLexer().getLoc(); - - // Consume the prefix character, and check for a following identifier. - - AsmToken Buf[1]; - Lexer.peekTokens(Buf, false); - - if (Buf[0].isNot(AsmToken::Identifier)) - return true; - - // We have a '$' or '@' followed by an identifier, make sure they are adjacent. - if (PrefixLoc.getPointer() + 1 != Buf[0].getLoc().getPointer()) - return true; - - // eat $ or @ - Lexer.Lex(); // Lexer's Lex guarantees consecutive token. - // Construct the joined identifier and consume the token. - Res = - StringRef(PrefixLoc.getPointer(), getTok().getIdentifier().size() + 1); - Lex(); // Parser Lex to maintain invariants. - return false; - } - - if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String)) - return true; - - Res = getTok().getIdentifier(); - - Lex(); // Consume the identifier token. - - return false; -} - -/// parseDirectiveSet: -/// ::= .equ identifier ',' expression -/// ::= .equiv identifier ',' expression -/// ::= .set identifier ',' expression -bool AsmParser::parseDirectiveSet(StringRef IDVal, bool allow_redef) { - StringRef Name; - if (check(parseIdentifier(Name), "expected identifier") || - parseToken(AsmToken::Comma) || parseAssignment(Name, allow_redef, true)) - return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); - return false; -} - -bool AsmParser::parseEscapedString(std::string &Data) { - if (check(getTok().isNot(AsmToken::String), "expected string")) - return true; - - Data = ""; - StringRef Str = getTok().getStringContents(); - for (unsigned i = 0, e = Str.size(); i != e; ++i) { - if (Str[i] != '\\') { - Data += Str[i]; - continue; - } - - // Recognize escaped characters. Note that this escape semantics currently - // loosely follows Darwin 'as'. Notably, it doesn't support hex escapes. - ++i; - if (i == e) - return TokError("unexpected backslash at end of string"); - - // Recognize octal sequences. - if ((unsigned)(Str[i] - '0') <= 7) { - // Consume up to three octal characters. - unsigned Value = Str[i] - '0'; - - if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) { - ++i; - Value = Value * 8 + (Str[i] - '0'); - - if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) { - ++i; - Value = Value * 8 + (Str[i] - '0'); - } - } - - if (Value > 255) - return TokError("invalid octal escape sequence (out of range)"); - - Data += (unsigned char)Value; - continue; - } - - // Otherwise recognize individual escapes. - switch (Str[i]) { - default: - // Just reject invalid escape sequences for now. - return TokError("invalid escape sequence (unrecognized character)"); - - case 'b': Data += '\b'; break; - case 'f': Data += '\f'; break; - case 'n': Data += '\n'; break; - case 'r': Data += '\r'; break; - case 't': Data += '\t'; break; - case '"': Data += '"'; break; - case '\\': Data += '\\'; break; - } - } - - Lex(); - return false; -} - -/// parseDirectiveAscii: -/// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ] -bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) { - auto parseOp = [&]() -> bool { - std::string Data; - if (checkForValidSection() || parseEscapedString(Data)) - return true; - getStreamer().EmitBytes(Data); - if (ZeroTerminated) - getStreamer().EmitBytes(StringRef("\0", 1)); - return false; - }; - - if (parseMany(parseOp)) - return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); - return false; -} - -/// parseDirectiveReloc -/// ::= .reloc expression , identifier [ , expression ] -bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) { - const MCExpr *Offset; - const MCExpr *Expr = nullptr; - int64_t OffsetValue; - SMLoc OffsetLoc = Lexer.getTok().getLoc(); - - if (parseExpression(Offset)) - return true; - - if ((Offset->evaluateAsAbsolute(OffsetValue, - getStreamer().getAssemblerPtr()) && - check(OffsetValue < 0, OffsetLoc, "expression is negative")) || - (check(Offset->getKind() != llvm::MCExpr::Constant && - Offset->getKind() != llvm::MCExpr::SymbolRef, - OffsetLoc, "expected non-negative number or a label")) || - (parseToken(AsmToken::Comma, "expected comma") || - check(getTok().isNot(AsmToken::Identifier), "expected relocation name"))) - return true; - - SMLoc NameLoc = Lexer.getTok().getLoc(); - StringRef Name = Lexer.getTok().getIdentifier(); - Lex(); - - if (Lexer.is(AsmToken::Comma)) { - Lex(); - SMLoc ExprLoc = Lexer.getLoc(); - if (parseExpression(Expr)) - return true; - - MCValue Value; - if (!Expr->evaluateAsRelocatable(Value, nullptr, nullptr)) - return Error(ExprLoc, "expression must be relocatable"); - } - - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in .reloc directive")) - return true; - - const MCTargetAsmParser &MCT = getTargetParser(); - const MCSubtargetInfo &STI = MCT.getSTI(); - if (getStreamer().EmitRelocDirective(*Offset, Name, Expr, DirectiveLoc, STI)) - return Error(NameLoc, "unknown relocation name"); - - return false; -} - -/// parseDirectiveValue -/// ::= (.byte | .short | ... ) [ expression (, expression)* ] -bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) { - auto parseOp = [&]() -> bool { - const MCExpr *Value; - SMLoc ExprLoc = getLexer().getLoc(); - if (checkForValidSection() || parseExpression(Value)) - return true; - // Special case constant expressions to match code generator. - if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { - assert(Size <= 8 && "Invalid size"); - uint64_t IntValue = MCE->getValue(); - if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue)) - return Error(ExprLoc, "out of range literal value"); - getStreamer().EmitIntValue(IntValue, Size); - } else - getStreamer().EmitValue(Value, Size, ExprLoc); - return false; - }; - - if (parseMany(parseOp)) - return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); - return false; -} - -static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo) { - if (Asm.getTok().isNot(AsmToken::Integer) && - Asm.getTok().isNot(AsmToken::BigNum)) - return Asm.TokError("unknown token in expression"); - SMLoc ExprLoc = Asm.getTok().getLoc(); - APInt IntValue = Asm.getTok().getAPIntVal(); - Asm.Lex(); - if (!IntValue.isIntN(128)) - return Asm.Error(ExprLoc, "out of range literal value"); - if (!IntValue.isIntN(64)) { - hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue(); - lo = IntValue.getLoBits(64).getZExtValue(); - } else { - hi = 0; - lo = IntValue.getZExtValue(); - } - return false; -} - -/// ParseDirectiveOctaValue -/// ::= .octa [ hexconstant (, hexconstant)* ] - -bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) { - auto parseOp = [&]() -> bool { - if (checkForValidSection()) - return true; - uint64_t hi, lo; - if (parseHexOcta(*this, hi, lo)) - return true; - if (MAI.isLittleEndian()) { - getStreamer().EmitIntValue(lo, 8); - getStreamer().EmitIntValue(hi, 8); - } else { - getStreamer().EmitIntValue(hi, 8); - getStreamer().EmitIntValue(lo, 8); - } - return false; - }; - - if (parseMany(parseOp)) - return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); - return false; -} - -bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) { - // We don't truly support arithmetic on floating point expressions, so we - // have to manually parse unary prefixes. - bool IsNeg = false; - if (getLexer().is(AsmToken::Minus)) { - Lexer.Lex(); - IsNeg = true; - } else if (getLexer().is(AsmToken::Plus)) - Lexer.Lex(); - - if (Lexer.is(AsmToken::Error)) - return TokError(Lexer.getErr()); - if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) && - Lexer.isNot(AsmToken::Identifier)) - return TokError("unexpected token in directive"); - - // Convert to an APFloat. - APFloat Value(Semantics); - StringRef IDVal = getTok().getString(); - if (getLexer().is(AsmToken::Identifier)) { - if (!IDVal.compare_lower("infinity") || !IDVal.compare_lower("inf")) - Value = APFloat::getInf(Semantics); - else if (!IDVal.compare_lower("nan")) - Value = APFloat::getNaN(Semantics, false, ~0); - else - return TokError("invalid floating point literal"); - } else if (Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) == - APFloat::opInvalidOp) - return TokError("invalid floating point literal"); - if (IsNeg) - Value.changeSign(); - - // Consume the numeric token. - Lex(); - - Res = Value.bitcastToAPInt(); - - return false; -} - -/// parseDirectiveRealValue -/// ::= (.single | .double) [ expression (, expression)* ] -bool AsmParser::parseDirectiveRealValue(StringRef IDVal, - const fltSemantics &Semantics) { - auto parseOp = [&]() -> bool { - APInt AsInt; - if (checkForValidSection() || parseRealValue(Semantics, AsInt)) - return true; - getStreamer().EmitIntValue(AsInt.getLimitedValue(), - AsInt.getBitWidth() / 8); - return false; - }; - - if (parseMany(parseOp)) - return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); - return false; -} - -/// parseDirectiveZero -/// ::= .zero expression -bool AsmParser::parseDirectiveZero() { - SMLoc NumBytesLoc = Lexer.getLoc(); - const MCExpr *NumBytes; - if (checkForValidSection() || parseExpression(NumBytes)) - return true; - - int64_t Val = 0; - if (getLexer().is(AsmToken::Comma)) { - Lex(); - if (parseAbsoluteExpression(Val)) - return true; - } - - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.zero' directive")) - return true; - getStreamer().emitFill(*NumBytes, Val, NumBytesLoc); - - return false; -} - -/// parseDirectiveFill -/// ::= .fill expression [ , expression [ , expression ] ] -bool AsmParser::parseDirectiveFill() { - SMLoc NumValuesLoc = Lexer.getLoc(); - const MCExpr *NumValues; - if (checkForValidSection() || parseExpression(NumValues)) - return true; - - int64_t FillSize = 1; - int64_t FillExpr = 0; - - SMLoc SizeLoc, ExprLoc; - - if (parseOptionalToken(AsmToken::Comma)) { - SizeLoc = getTok().getLoc(); - if (parseAbsoluteExpression(FillSize)) - return true; - if (parseOptionalToken(AsmToken::Comma)) { - ExprLoc = getTok().getLoc(); - if (parseAbsoluteExpression(FillExpr)) - return true; - } - } - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.fill' directive")) - return true; - - if (FillSize < 0) { - Warning(SizeLoc, "'.fill' directive with negative size has no effect"); - return false; - } - if (FillSize > 8) { - Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8"); - FillSize = 8; - } - - if (!isUInt<32>(FillExpr) && FillSize > 4) - Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits"); - - getStreamer().emitFill(*NumValues, FillSize, FillExpr, NumValuesLoc); - - return false; -} - -/// parseDirectiveOrg -/// ::= .org expression [ , expression ] -bool AsmParser::parseDirectiveOrg() { - const MCExpr *Offset; - SMLoc OffsetLoc = Lexer.getLoc(); - if (checkForValidSection() || parseExpression(Offset)) - return true; - - // Parse optional fill expression. - int64_t FillExpr = 0; - if (parseOptionalToken(AsmToken::Comma)) - if (parseAbsoluteExpression(FillExpr)) - return addErrorSuffix(" in '.org' directive"); - if (parseToken(AsmToken::EndOfStatement)) - return addErrorSuffix(" in '.org' directive"); - - getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc); - return false; -} - -/// parseDirectiveAlign -/// ::= {.align, ...} expression [ , expression [ , expression ]] -bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) { - SMLoc AlignmentLoc = getLexer().getLoc(); - int64_t Alignment; - SMLoc MaxBytesLoc; - bool HasFillExpr = false; - int64_t FillExpr = 0; - int64_t MaxBytesToFill = 0; - - auto parseAlign = [&]() -> bool { - if (parseAbsoluteExpression(Alignment)) - return true; - if (parseOptionalToken(AsmToken::Comma)) { - // The fill expression can be omitted while specifying a maximum number of - // alignment bytes, e.g: - // .align 3,,4 - if (getTok().isNot(AsmToken::Comma)) { - HasFillExpr = true; - if (parseAbsoluteExpression(FillExpr)) - return true; - } - if (parseOptionalToken(AsmToken::Comma)) - if (parseTokenLoc(MaxBytesLoc) || - parseAbsoluteExpression(MaxBytesToFill)) - return true; - } - return parseToken(AsmToken::EndOfStatement); - }; - - if (checkForValidSection()) - return addErrorSuffix(" in directive"); - // Ignore empty '.p2align' directives for GNU-as compatibility - if (IsPow2 && (ValueSize == 1) && getTok().is(AsmToken::EndOfStatement)) { - Warning(AlignmentLoc, "p2align directive with no operand(s) is ignored"); - return parseToken(AsmToken::EndOfStatement); - } - if (parseAlign()) - return addErrorSuffix(" in directive"); - - // Always emit an alignment here even if we thrown an error. - bool ReturnVal = false; - - // Compute alignment in bytes. - if (IsPow2) { - // FIXME: Diagnose overflow. - if (Alignment >= 32) { - ReturnVal |= Error(AlignmentLoc, "invalid alignment value"); - Alignment = 31; - } - - Alignment = 1ULL << Alignment; - } else { - // Reject alignments that aren't either a power of two or zero, - // for gas compatibility. Alignment of zero is silently rounded - // up to one. - if (Alignment == 0) - Alignment = 1; - if (!isPowerOf2_64(Alignment)) - ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2"); - } - - // Diagnose non-sensical max bytes to align. - if (MaxBytesLoc.isValid()) { - if (MaxBytesToFill < 1) { - ReturnVal |= Error(MaxBytesLoc, - "alignment directive can never be satisfied in this " - "many bytes, ignoring maximum bytes expression"); - MaxBytesToFill = 0; - } - - if (MaxBytesToFill >= Alignment) { - Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and " - "has no effect"); - MaxBytesToFill = 0; - } - } - - // Check whether we should use optimal code alignment for this .align - // directive. - const MCSection *Section = getStreamer().getCurrentSectionOnly(); - assert(Section && "must have section to emit alignment"); - bool UseCodeAlign = Section->UseCodeAlign(); - if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) && - ValueSize == 1 && UseCodeAlign) { - getStreamer().EmitCodeAlignment(Alignment, MaxBytesToFill); - } else { - // FIXME: Target specific behavior about how the "extra" bytes are filled. - getStreamer().EmitValueToAlignment(Alignment, FillExpr, ValueSize, - MaxBytesToFill); - } - - return ReturnVal; -} - -/// parseDirectiveFile -/// ::= .file filename -/// ::= .file number [directory] filename [md5 checksum] [source source-text] -bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) { - // FIXME: I'm not sure what this is. - int64_t FileNumber = -1; - if (getLexer().is(AsmToken::Integer)) { - FileNumber = getTok().getIntVal(); - Lex(); - - if (FileNumber < 0) - return TokError("negative file number"); - } - - std::string Path; - - // Usually the directory and filename together, otherwise just the directory. - // Allow the strings to have escaped octal character sequence. - if (check(getTok().isNot(AsmToken::String), - "unexpected token in '.file' directive") || - parseEscapedString(Path)) - return true; - - StringRef Directory; - StringRef Filename; - std::string FilenameData; - if (getLexer().is(AsmToken::String)) { - if (check(FileNumber == -1, - "explicit path specified, but no file number") || - parseEscapedString(FilenameData)) - return true; - Filename = FilenameData; - Directory = Path; - } else { - Filename = Path; - } - - uint64_t MD5Hi, MD5Lo; - bool HasMD5 = false; - - Optional<StringRef> Source; - bool HasSource = false; - std::string SourceString; - - while (!parseOptionalToken(AsmToken::EndOfStatement)) { - StringRef Keyword; - if (check(getTok().isNot(AsmToken::Identifier), - "unexpected token in '.file' directive") || - parseIdentifier(Keyword)) - return true; - if (Keyword == "md5") { - HasMD5 = true; - if (check(FileNumber == -1, - "MD5 checksum specified, but no file number") || - parseHexOcta(*this, MD5Hi, MD5Lo)) - return true; - } else if (Keyword == "source") { - HasSource = true; - if (check(FileNumber == -1, - "source specified, but no file number") || - check(getTok().isNot(AsmToken::String), - "unexpected token in '.file' directive") || - parseEscapedString(SourceString)) - return true; - } else { - return TokError("unexpected token in '.file' directive"); - } - } - - if (FileNumber == -1) { - // Ignore the directive if there is no number and the target doesn't support - // numberless .file directives. This allows some portability of assembler - // between different object file formats. - if (getContext().getAsmInfo()->hasSingleParameterDotFile()) - getStreamer().EmitFileDirective(Filename); - } else { - // In case there is a -g option as well as debug info from directive .file, - // we turn off the -g option, directly use the existing debug info instead. - // Throw away any implicit file table for the assembler source. - if (Ctx.getGenDwarfForAssembly()) { - Ctx.getMCDwarfLineTable(0).resetFileTable(); - Ctx.setGenDwarfForAssembly(false); - } - - Optional<MD5::MD5Result> CKMem; - if (HasMD5) { - MD5::MD5Result Sum; - for (unsigned i = 0; i != 8; ++i) { - Sum.Bytes[i] = uint8_t(MD5Hi >> ((7 - i) * 8)); - Sum.Bytes[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8)); - } - CKMem = Sum; - } - if (HasSource) { - char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size())); - memcpy(SourceBuf, SourceString.data(), SourceString.size()); - Source = StringRef(SourceBuf, SourceString.size()); - } - if (FileNumber == 0) { - if (Ctx.getDwarfVersion() < 5) - return Warning(DirectiveLoc, "file 0 not supported prior to DWARF-5"); - getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source); - } else { - Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective( - FileNumber, Directory, Filename, CKMem, Source); - if (!FileNumOrErr) - return Error(DirectiveLoc, toString(FileNumOrErr.takeError())); - } - // Alert the user if there are some .file directives with MD5 and some not. - // But only do that once. - if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) { - ReportedInconsistentMD5 = true; - return Warning(DirectiveLoc, "inconsistent use of MD5 checksums"); - } - } - - return false; -} - -/// parseDirectiveLine -/// ::= .line [number] -bool AsmParser::parseDirectiveLine() { - int64_t LineNumber; - if (getLexer().is(AsmToken::Integer)) { - if (parseIntToken(LineNumber, "unexpected token in '.line' directive")) - return true; - (void)LineNumber; - // FIXME: Do something with the .line. - } - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.line' directive")) - return true; - - return false; -} - -/// parseDirectiveLoc -/// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end] -/// [epilogue_begin] [is_stmt VALUE] [isa VALUE] -/// The first number is a file number, must have been previously assigned with -/// a .file directive, the second number is the line number and optionally the -/// third number is a column position (zero if not specified). The remaining -/// optional items are .loc sub-directives. -bool AsmParser::parseDirectiveLoc() { - int64_t FileNumber = 0, LineNumber = 0; - SMLoc Loc = getTok().getLoc(); - if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") || - check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc, - "file number less than one in '.loc' directive") || - check(!getContext().isValidDwarfFileNumber(FileNumber), Loc, - "unassigned file number in '.loc' directive")) - return true; - - // optional - if (getLexer().is(AsmToken::Integer)) { - LineNumber = getTok().getIntVal(); - if (LineNumber < 0) - return TokError("line number less than zero in '.loc' directive"); - Lex(); - } - - int64_t ColumnPos = 0; - if (getLexer().is(AsmToken::Integer)) { - ColumnPos = getTok().getIntVal(); - if (ColumnPos < 0) - return TokError("column position less than zero in '.loc' directive"); - Lex(); - } - - unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; - unsigned Isa = 0; - int64_t Discriminator = 0; - - auto parseLocOp = [&]() -> bool { - StringRef Name; - SMLoc Loc = getTok().getLoc(); - if (parseIdentifier(Name)) - return TokError("unexpected token in '.loc' directive"); - - if (Name == "basic_block") - Flags |= DWARF2_FLAG_BASIC_BLOCK; - else if (Name == "prologue_end") - Flags |= DWARF2_FLAG_PROLOGUE_END; - else if (Name == "epilogue_begin") - Flags |= DWARF2_FLAG_EPILOGUE_BEGIN; - else if (Name == "is_stmt") { - Loc = getTok().getLoc(); - const MCExpr *Value; - if (parseExpression(Value)) - return true; - // The expression must be the constant 0 or 1. - if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { - int Value = MCE->getValue(); - if (Value == 0) - Flags &= ~DWARF2_FLAG_IS_STMT; - else if (Value == 1) - Flags |= DWARF2_FLAG_IS_STMT; - else - return Error(Loc, "is_stmt value not 0 or 1"); - } else { - return Error(Loc, "is_stmt value not the constant value of 0 or 1"); - } - } else if (Name == "isa") { - Loc = getTok().getLoc(); - const MCExpr *Value; - if (parseExpression(Value)) - return true; - // The expression must be a constant greater or equal to 0. - if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { - int Value = MCE->getValue(); - if (Value < 0) - return Error(Loc, "isa number less than zero"); - Isa = Value; - } else { - return Error(Loc, "isa number not a constant value"); - } - } else if (Name == "discriminator") { - if (parseAbsoluteExpression(Discriminator)) - return true; - } else { - return Error(Loc, "unknown sub-directive in '.loc' directive"); - } - return false; - }; - - if (parseMany(parseLocOp, false /*hasComma*/)) - return true; - - getStreamer().EmitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags, - Isa, Discriminator, StringRef()); - - return false; -} - -/// parseDirectiveStabs -/// ::= .stabs string, number, number, number -bool AsmParser::parseDirectiveStabs() { - return TokError("unsupported directive '.stabs'"); -} - -/// parseDirectiveCVFile -/// ::= .cv_file number filename [checksum] [checksumkind] -bool AsmParser::parseDirectiveCVFile() { - SMLoc FileNumberLoc = getTok().getLoc(); - int64_t FileNumber; - std::string Filename; - std::string Checksum; - int64_t ChecksumKind = 0; - - if (parseIntToken(FileNumber, - "expected file number in '.cv_file' directive") || - check(FileNumber < 1, FileNumberLoc, "file number less than one") || - check(getTok().isNot(AsmToken::String), - "unexpected token in '.cv_file' directive") || - parseEscapedString(Filename)) - return true; - if (!parseOptionalToken(AsmToken::EndOfStatement)) { - if (check(getTok().isNot(AsmToken::String), - "unexpected token in '.cv_file' directive") || - parseEscapedString(Checksum) || - parseIntToken(ChecksumKind, - "expected checksum kind in '.cv_file' directive") || - parseToken(AsmToken::EndOfStatement, - "unexpected token in '.cv_file' directive")) - return true; - } - - Checksum = fromHex(Checksum); - void *CKMem = Ctx.allocate(Checksum.size(), 1); - memcpy(CKMem, Checksum.data(), Checksum.size()); - ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem), - Checksum.size()); - - if (!getStreamer().EmitCVFileDirective(FileNumber, Filename, ChecksumAsBytes, - static_cast<uint8_t>(ChecksumKind))) - return Error(FileNumberLoc, "file number already allocated"); - - return false; -} - -bool AsmParser::parseCVFunctionId(int64_t &FunctionId, - StringRef DirectiveName) { - SMLoc Loc; - return parseTokenLoc(Loc) || - parseIntToken(FunctionId, "expected function id in '" + DirectiveName + - "' directive") || - check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc, - "expected function id within range [0, UINT_MAX)"); -} - -bool AsmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) { - SMLoc Loc; - return parseTokenLoc(Loc) || - parseIntToken(FileNumber, "expected integer in '" + DirectiveName + - "' directive") || - check(FileNumber < 1, Loc, "file number less than one in '" + - DirectiveName + "' directive") || - check(!getCVContext().isValidFileNumber(FileNumber), Loc, - "unassigned file number in '" + DirectiveName + "' directive"); -} - -/// parseDirectiveCVFuncId -/// ::= .cv_func_id FunctionId -/// -/// Introduces a function ID that can be used with .cv_loc. -bool AsmParser::parseDirectiveCVFuncId() { - SMLoc FunctionIdLoc = getTok().getLoc(); - int64_t FunctionId; - - if (parseCVFunctionId(FunctionId, ".cv_func_id") || - parseToken(AsmToken::EndOfStatement, - "unexpected token in '.cv_func_id' directive")) - return true; - - if (!getStreamer().EmitCVFuncIdDirective(FunctionId)) - return Error(FunctionIdLoc, "function id already allocated"); - - return false; -} - -/// parseDirectiveCVInlineSiteId -/// ::= .cv_inline_site_id FunctionId -/// "within" IAFunc -/// "inlined_at" IAFile IALine [IACol] -/// -/// Introduces a function ID that can be used with .cv_loc. Includes "inlined -/// at" source location information for use in the line table of the caller, -/// whether the caller is a real function or another inlined call site. -bool AsmParser::parseDirectiveCVInlineSiteId() { - SMLoc FunctionIdLoc = getTok().getLoc(); - int64_t FunctionId; - int64_t IAFunc; - int64_t IAFile; - int64_t IALine; - int64_t IACol = 0; - - // FunctionId - if (parseCVFunctionId(FunctionId, ".cv_inline_site_id")) - return true; - - // "within" - if (check((getLexer().isNot(AsmToken::Identifier) || - getTok().getIdentifier() != "within"), - "expected 'within' identifier in '.cv_inline_site_id' directive")) - return true; - Lex(); - - // IAFunc - if (parseCVFunctionId(IAFunc, ".cv_inline_site_id")) - return true; - - // "inlined_at" - if (check((getLexer().isNot(AsmToken::Identifier) || - getTok().getIdentifier() != "inlined_at"), - "expected 'inlined_at' identifier in '.cv_inline_site_id' " - "directive") ) - return true; - Lex(); - - // IAFile IALine - if (parseCVFileId(IAFile, ".cv_inline_site_id") || - parseIntToken(IALine, "expected line number after 'inlined_at'")) - return true; - - // [IACol] - if (getLexer().is(AsmToken::Integer)) { - IACol = getTok().getIntVal(); - Lex(); - } - - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.cv_inline_site_id' directive")) - return true; - - if (!getStreamer().EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile, - IALine, IACol, FunctionIdLoc)) - return Error(FunctionIdLoc, "function id already allocated"); - - return false; -} - -/// parseDirectiveCVLoc -/// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end] -/// [is_stmt VALUE] -/// The first number is a file number, must have been previously assigned with -/// a .file directive, the second number is the line number and optionally the -/// third number is a column position (zero if not specified). The remaining -/// optional items are .loc sub-directives. -bool AsmParser::parseDirectiveCVLoc() { - SMLoc DirectiveLoc = getTok().getLoc(); - int64_t FunctionId, FileNumber; - if (parseCVFunctionId(FunctionId, ".cv_loc") || - parseCVFileId(FileNumber, ".cv_loc")) - return true; - - int64_t LineNumber = 0; - if (getLexer().is(AsmToken::Integer)) { - LineNumber = getTok().getIntVal(); - if (LineNumber < 0) - return TokError("line number less than zero in '.cv_loc' directive"); - Lex(); - } - - int64_t ColumnPos = 0; - if (getLexer().is(AsmToken::Integer)) { - ColumnPos = getTok().getIntVal(); - if (ColumnPos < 0) - return TokError("column position less than zero in '.cv_loc' directive"); - Lex(); - } - - bool PrologueEnd = false; - uint64_t IsStmt = 0; - - auto parseOp = [&]() -> bool { - StringRef Name; - SMLoc Loc = getTok().getLoc(); - if (parseIdentifier(Name)) - return TokError("unexpected token in '.cv_loc' directive"); - if (Name == "prologue_end") - PrologueEnd = true; - else if (Name == "is_stmt") { - Loc = getTok().getLoc(); - const MCExpr *Value; - if (parseExpression(Value)) - return true; - // The expression must be the constant 0 or 1. - IsStmt = ~0ULL; - if (const auto *MCE = dyn_cast<MCConstantExpr>(Value)) - IsStmt = MCE->getValue(); - - if (IsStmt > 1) - return Error(Loc, "is_stmt value not 0 or 1"); - } else { - return Error(Loc, "unknown sub-directive in '.cv_loc' directive"); - } - return false; - }; - - if (parseMany(parseOp, false /*hasComma*/)) - return true; - - getStreamer().EmitCVLocDirective(FunctionId, FileNumber, LineNumber, - ColumnPos, PrologueEnd, IsStmt, StringRef(), - DirectiveLoc); - return false; -} - -/// parseDirectiveCVLinetable -/// ::= .cv_linetable FunctionId, FnStart, FnEnd -bool AsmParser::parseDirectiveCVLinetable() { - int64_t FunctionId; - StringRef FnStartName, FnEndName; - SMLoc Loc = getTok().getLoc(); - if (parseCVFunctionId(FunctionId, ".cv_linetable") || - parseToken(AsmToken::Comma, - "unexpected token in '.cv_linetable' directive") || - parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc, - "expected identifier in directive") || - parseToken(AsmToken::Comma, - "unexpected token in '.cv_linetable' directive") || - parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc, - "expected identifier in directive")) - return true; - - MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName); - MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName); - - getStreamer().EmitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym); - return false; -} - -/// parseDirectiveCVInlineLinetable -/// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd -bool AsmParser::parseDirectiveCVInlineLinetable() { - int64_t PrimaryFunctionId, SourceFileId, SourceLineNum; - StringRef FnStartName, FnEndName; - SMLoc Loc = getTok().getLoc(); - if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") || - parseTokenLoc(Loc) || - parseIntToken( - SourceFileId, - "expected SourceField in '.cv_inline_linetable' directive") || - check(SourceFileId <= 0, Loc, - "File id less than zero in '.cv_inline_linetable' directive") || - parseTokenLoc(Loc) || - parseIntToken( - SourceLineNum, - "expected SourceLineNum in '.cv_inline_linetable' directive") || - check(SourceLineNum < 0, Loc, - "Line number less than zero in '.cv_inline_linetable' directive") || - parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc, - "expected identifier in directive") || - parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc, - "expected identifier in directive")) - return true; - - if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement")) - return true; - - MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName); - MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName); - getStreamer().EmitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId, - SourceLineNum, FnStartSym, - FnEndSym); - return false; -} - -/// parseDirectiveCVDefRange -/// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes* -bool AsmParser::parseDirectiveCVDefRange() { - SMLoc Loc; - std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges; - while (getLexer().is(AsmToken::Identifier)) { - Loc = getLexer().getLoc(); - StringRef GapStartName; - if (parseIdentifier(GapStartName)) - return Error(Loc, "expected identifier in directive"); - MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName); - - Loc = getLexer().getLoc(); - StringRef GapEndName; - if (parseIdentifier(GapEndName)) - return Error(Loc, "expected identifier in directive"); - MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName); - - Ranges.push_back({GapStartSym, GapEndSym}); - } - - std::string FixedSizePortion; - if (parseToken(AsmToken::Comma, "unexpected token in directive") || - parseEscapedString(FixedSizePortion)) - return true; - - getStreamer().EmitCVDefRangeDirective(Ranges, FixedSizePortion); - return false; -} - -/// parseDirectiveCVString -/// ::= .cv_stringtable "string" -bool AsmParser::parseDirectiveCVString() { - std::string Data; - if (checkForValidSection() || parseEscapedString(Data)) - return addErrorSuffix(" in '.cv_string' directive"); - - // Put the string in the table and emit the offset. - std::pair<StringRef, unsigned> Insertion = - getCVContext().addToStringTable(Data); - getStreamer().EmitIntValue(Insertion.second, 4); - return false; -} - -/// parseDirectiveCVStringTable -/// ::= .cv_stringtable -bool AsmParser::parseDirectiveCVStringTable() { - getStreamer().EmitCVStringTableDirective(); - return false; -} - -/// parseDirectiveCVFileChecksums -/// ::= .cv_filechecksums -bool AsmParser::parseDirectiveCVFileChecksums() { - getStreamer().EmitCVFileChecksumsDirective(); - return false; -} - -/// parseDirectiveCVFileChecksumOffset -/// ::= .cv_filechecksumoffset fileno -bool AsmParser::parseDirectiveCVFileChecksumOffset() { - int64_t FileNo; - if (parseIntToken(FileNo, "expected identifier in directive")) - return true; - if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement")) - return true; - getStreamer().EmitCVFileChecksumOffsetDirective(FileNo); - return false; -} - -/// parseDirectiveCVFPOData -/// ::= .cv_fpo_data procsym -bool AsmParser::parseDirectiveCVFPOData() { - SMLoc DirLoc = getLexer().getLoc(); - StringRef ProcName; - if (parseIdentifier(ProcName)) - return TokError("expected symbol name"); - if (parseEOL("unexpected tokens")) - return addErrorSuffix(" in '.cv_fpo_data' directive"); - MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName); - getStreamer().EmitCVFPOData(ProcSym, DirLoc); - return false; -} - -/// parseDirectiveCFISections -/// ::= .cfi_sections section [, section] -bool AsmParser::parseDirectiveCFISections() { - StringRef Name; - bool EH = false; - bool Debug = false; - - if (parseIdentifier(Name)) - return TokError("Expected an identifier"); - - if (Name == ".eh_frame") - EH = true; - else if (Name == ".debug_frame") - Debug = true; - - if (getLexer().is(AsmToken::Comma)) { - Lex(); - - if (parseIdentifier(Name)) - return TokError("Expected an identifier"); - - if (Name == ".eh_frame") - EH = true; - else if (Name == ".debug_frame") - Debug = true; - } - - getStreamer().EmitCFISections(EH, Debug); - return false; -} - -/// parseDirectiveCFIStartProc -/// ::= .cfi_startproc [simple] -bool AsmParser::parseDirectiveCFIStartProc() { - StringRef Simple; - if (!parseOptionalToken(AsmToken::EndOfStatement)) { - if (check(parseIdentifier(Simple) || Simple != "simple", - "unexpected token") || - parseToken(AsmToken::EndOfStatement)) - return addErrorSuffix(" in '.cfi_startproc' directive"); - } - - // TODO(kristina): Deal with a corner case of incorrect diagnostic context - // being produced if this directive is emitted as part of preprocessor macro - // expansion which can *ONLY* happen if Clang's cc1as is the API consumer. - // Tools like llvm-mc on the other hand are not affected by it, and report - // correct context information. - getStreamer().EmitCFIStartProc(!Simple.empty(), Lexer.getLoc()); - return false; -} - -/// parseDirectiveCFIEndProc -/// ::= .cfi_endproc -bool AsmParser::parseDirectiveCFIEndProc() { - getStreamer().EmitCFIEndProc(); - return false; -} - -/// parse register name or number. -bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register, - SMLoc DirectiveLoc) { - unsigned RegNo; - - if (getLexer().isNot(AsmToken::Integer)) { - if (getTargetParser().ParseRegister(RegNo, DirectiveLoc, DirectiveLoc)) - return true; - Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true); - } else - return parseAbsoluteExpression(Register); - - return false; -} - -/// parseDirectiveCFIDefCfa -/// ::= .cfi_def_cfa register, offset -bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) { - int64_t Register = 0, Offset = 0; - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || - parseToken(AsmToken::Comma, "unexpected token in directive") || - parseAbsoluteExpression(Offset)) - return true; - - getStreamer().EmitCFIDefCfa(Register, Offset); - return false; -} - -/// parseDirectiveCFIDefCfaOffset -/// ::= .cfi_def_cfa_offset offset -bool AsmParser::parseDirectiveCFIDefCfaOffset() { - int64_t Offset = 0; - if (parseAbsoluteExpression(Offset)) - return true; - - getStreamer().EmitCFIDefCfaOffset(Offset); - return false; -} - -/// parseDirectiveCFIRegister -/// ::= .cfi_register register, register -bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) { - int64_t Register1 = 0, Register2 = 0; - if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) || - parseToken(AsmToken::Comma, "unexpected token in directive") || - parseRegisterOrRegisterNumber(Register2, DirectiveLoc)) - return true; - - getStreamer().EmitCFIRegister(Register1, Register2); - return false; -} - -/// parseDirectiveCFIWindowSave -/// ::= .cfi_window_save -bool AsmParser::parseDirectiveCFIWindowSave() { - getStreamer().EmitCFIWindowSave(); - return false; -} - -/// parseDirectiveCFIAdjustCfaOffset -/// ::= .cfi_adjust_cfa_offset adjustment -bool AsmParser::parseDirectiveCFIAdjustCfaOffset() { - int64_t Adjustment = 0; - if (parseAbsoluteExpression(Adjustment)) - return true; - - getStreamer().EmitCFIAdjustCfaOffset(Adjustment); - return false; -} - -/// parseDirectiveCFIDefCfaRegister -/// ::= .cfi_def_cfa_register register -bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) { - int64_t Register = 0; - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) - return true; - - getStreamer().EmitCFIDefCfaRegister(Register); - return false; -} - -/// parseDirectiveCFIOffset -/// ::= .cfi_offset register, offset -bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) { - int64_t Register = 0; - int64_t Offset = 0; - - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || - parseToken(AsmToken::Comma, "unexpected token in directive") || - parseAbsoluteExpression(Offset)) - return true; - - getStreamer().EmitCFIOffset(Register, Offset); - return false; -} - -/// parseDirectiveCFIRelOffset -/// ::= .cfi_rel_offset register, offset -bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) { - int64_t Register = 0, Offset = 0; - - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || - parseToken(AsmToken::Comma, "unexpected token in directive") || - parseAbsoluteExpression(Offset)) - return true; - - getStreamer().EmitCFIRelOffset(Register, Offset); - return false; -} - -static bool isValidEncoding(int64_t Encoding) { - if (Encoding & ~0xff) - return false; - - if (Encoding == dwarf::DW_EH_PE_omit) - return true; - - const unsigned Format = Encoding & 0xf; - if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 && - Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 && - Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 && - Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed) - return false; - - const unsigned Application = Encoding & 0x70; - if (Application != dwarf::DW_EH_PE_absptr && - Application != dwarf::DW_EH_PE_pcrel) - return false; - - return true; -} - -/// parseDirectiveCFIPersonalityOrLsda -/// IsPersonality true for cfi_personality, false for cfi_lsda -/// ::= .cfi_personality encoding, [symbol_name] -/// ::= .cfi_lsda encoding, [symbol_name] -bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) { - int64_t Encoding = 0; - if (parseAbsoluteExpression(Encoding)) - return true; - if (Encoding == dwarf::DW_EH_PE_omit) - return false; - - StringRef Name; - if (check(!isValidEncoding(Encoding), "unsupported encoding.") || - parseToken(AsmToken::Comma, "unexpected token in directive") || - check(parseIdentifier(Name), "expected identifier in directive")) - return true; - - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - - if (IsPersonality) - getStreamer().EmitCFIPersonality(Sym, Encoding); - else - getStreamer().EmitCFILsda(Sym, Encoding); - return false; -} - -/// parseDirectiveCFIRememberState -/// ::= .cfi_remember_state -bool AsmParser::parseDirectiveCFIRememberState() { - getStreamer().EmitCFIRememberState(); - return false; -} - -/// parseDirectiveCFIRestoreState -/// ::= .cfi_remember_state -bool AsmParser::parseDirectiveCFIRestoreState() { - getStreamer().EmitCFIRestoreState(); - return false; -} - -/// parseDirectiveCFISameValue -/// ::= .cfi_same_value register -bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) { - int64_t Register = 0; - - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) - return true; - - getStreamer().EmitCFISameValue(Register); - return false; -} - -/// parseDirectiveCFIRestore -/// ::= .cfi_restore register -bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) { - int64_t Register = 0; - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) - return true; - - getStreamer().EmitCFIRestore(Register); - return false; -} - -/// parseDirectiveCFIEscape -/// ::= .cfi_escape expression[,...] -bool AsmParser::parseDirectiveCFIEscape() { - std::string Values; - int64_t CurrValue; - if (parseAbsoluteExpression(CurrValue)) - return true; - - Values.push_back((uint8_t)CurrValue); - - while (getLexer().is(AsmToken::Comma)) { - Lex(); - - if (parseAbsoluteExpression(CurrValue)) - return true; - - Values.push_back((uint8_t)CurrValue); - } - - getStreamer().EmitCFIEscape(Values); - return false; -} - -/// parseDirectiveCFIReturnColumn -/// ::= .cfi_return_column register -bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) { - int64_t Register = 0; - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) - return true; - getStreamer().EmitCFIReturnColumn(Register); - return false; -} - -/// parseDirectiveCFISignalFrame -/// ::= .cfi_signal_frame -bool AsmParser::parseDirectiveCFISignalFrame() { - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.cfi_signal_frame'")) - return true; - - getStreamer().EmitCFISignalFrame(); - return false; -} - -/// parseDirectiveCFIUndefined -/// ::= .cfi_undefined register -bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) { - int64_t Register = 0; - - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) - return true; - - getStreamer().EmitCFIUndefined(Register); - return false; -} - -/// parseDirectiveAltmacro -/// ::= .altmacro -/// ::= .noaltmacro -bool AsmParser::parseDirectiveAltmacro(StringRef Directive) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '" + Directive + "' directive"); - AltMacroMode = (Directive == ".altmacro"); - return false; -} - -/// parseDirectiveMacrosOnOff -/// ::= .macros_on -/// ::= .macros_off -bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) { - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '" + Directive + "' directive")) - return true; - - setMacrosEnabled(Directive == ".macros_on"); - return false; -} - -/// parseDirectiveMacro -/// ::= .macro name[,] [parameters] -bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) { - StringRef Name; - if (parseIdentifier(Name)) - return TokError("expected identifier in '.macro' directive"); - - if (getLexer().is(AsmToken::Comma)) - Lex(); - - MCAsmMacroParameters Parameters; - while (getLexer().isNot(AsmToken::EndOfStatement)) { - - if (!Parameters.empty() && Parameters.back().Vararg) - return Error(Lexer.getLoc(), - "Vararg parameter '" + Parameters.back().Name + - "' should be last one in the list of parameters."); - - MCAsmMacroParameter Parameter; - if (parseIdentifier(Parameter.Name)) - return TokError("expected identifier in '.macro' directive"); - - // Emit an error if two (or more) named parameters share the same name - for (const MCAsmMacroParameter& CurrParam : Parameters) - if (CurrParam.Name.equals(Parameter.Name)) - return TokError("macro '" + Name + "' has multiple parameters" - " named '" + Parameter.Name + "'"); - - if (Lexer.is(AsmToken::Colon)) { - Lex(); // consume ':' - - SMLoc QualLoc; - StringRef Qualifier; - - QualLoc = Lexer.getLoc(); - if (parseIdentifier(Qualifier)) - return Error(QualLoc, "missing parameter qualifier for " - "'" + Parameter.Name + "' in macro '" + Name + "'"); - - if (Qualifier == "req") - Parameter.Required = true; - else if (Qualifier == "vararg") - Parameter.Vararg = true; - else - return Error(QualLoc, Qualifier + " is not a valid parameter qualifier " - "for '" + Parameter.Name + "' in macro '" + Name + "'"); - } - - if (getLexer().is(AsmToken::Equal)) { - Lex(); - - SMLoc ParamLoc; - - ParamLoc = Lexer.getLoc(); - if (parseMacroArgument(Parameter.Value, /*Vararg=*/false )) - return true; - - if (Parameter.Required) - Warning(ParamLoc, "pointless default value for required parameter " - "'" + Parameter.Name + "' in macro '" + Name + "'"); - } - - Parameters.push_back(std::move(Parameter)); - - if (getLexer().is(AsmToken::Comma)) - Lex(); - } - - // Eat just the end of statement. - Lexer.Lex(); - - // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors - AsmToken EndToken, StartToken = getTok(); - unsigned MacroDepth = 0; - // Lex the macro definition. - while (true) { - // Ignore Lexing errors in macros. - while (Lexer.is(AsmToken::Error)) { - Lexer.Lex(); - } - - // Check whether we have reached the end of the file. - if (getLexer().is(AsmToken::Eof)) - return Error(DirectiveLoc, "no matching '.endmacro' in definition"); - - // Otherwise, check whether we have reach the .endmacro. - if (getLexer().is(AsmToken::Identifier)) { - if (getTok().getIdentifier() == ".endm" || - getTok().getIdentifier() == ".endmacro") { - if (MacroDepth == 0) { // Outermost macro. - EndToken = getTok(); - Lexer.Lex(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '" + EndToken.getIdentifier() + - "' directive"); - break; - } else { - // Otherwise we just found the end of an inner macro. - --MacroDepth; - } - } else if (getTok().getIdentifier() == ".macro") { - // We allow nested macros. Those aren't instantiated until the outermost - // macro is expanded so just ignore them for now. - ++MacroDepth; - } - } - - // Otherwise, scan til the end of the statement. - eatToEndOfStatement(); - } - - if (getContext().lookupMacro(Name)) { - return Error(DirectiveLoc, "macro '" + Name + "' is already defined"); - } - - const char *BodyStart = StartToken.getLoc().getPointer(); - const char *BodyEnd = EndToken.getLoc().getPointer(); - StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart); - checkForBadMacro(DirectiveLoc, Name, Body, Parameters); - MCAsmMacro Macro(Name, Body, std::move(Parameters)); - DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n"; - Macro.dump()); - getContext().defineMacro(Name, std::move(Macro)); - return false; -} - -/// checkForBadMacro -/// -/// With the support added for named parameters there may be code out there that -/// is transitioning from positional parameters. In versions of gas that did -/// not support named parameters they would be ignored on the macro definition. -/// But to support both styles of parameters this is not possible so if a macro -/// definition has named parameters but does not use them and has what appears -/// to be positional parameters, strings like $1, $2, ... and $n, then issue a -/// warning that the positional parameter found in body which have no effect. -/// Hoping the developer will either remove the named parameters from the macro -/// definition so the positional parameters get used if that was what was -/// intended or change the macro to use the named parameters. It is possible -/// this warning will trigger when the none of the named parameters are used -/// and the strings like $1 are infact to simply to be passed trough unchanged. -void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, - StringRef Body, - ArrayRef<MCAsmMacroParameter> Parameters) { - // If this macro is not defined with named parameters the warning we are - // checking for here doesn't apply. - unsigned NParameters = Parameters.size(); - if (NParameters == 0) - return; - - bool NamedParametersFound = false; - bool PositionalParametersFound = false; - - // Look at the body of the macro for use of both the named parameters and what - // are likely to be positional parameters. This is what expandMacro() is - // doing when it finds the parameters in the body. - while (!Body.empty()) { - // Scan for the next possible parameter. - std::size_t End = Body.size(), Pos = 0; - for (; Pos != End; ++Pos) { - // Check for a substitution or escape. - // This macro is defined with parameters, look for \foo, \bar, etc. - if (Body[Pos] == '\\' && Pos + 1 != End) - break; - - // This macro should have parameters, but look for $0, $1, ..., $n too. - if (Body[Pos] != '$' || Pos + 1 == End) - continue; - char Next = Body[Pos + 1]; - if (Next == '$' || Next == 'n' || - isdigit(static_cast<unsigned char>(Next))) - break; - } - - // Check if we reached the end. - if (Pos == End) - break; - - if (Body[Pos] == '$') { - switch (Body[Pos + 1]) { - // $$ => $ - case '$': - break; - - // $n => number of arguments - case 'n': - PositionalParametersFound = true; - break; - - // $[0-9] => argument - default: { - PositionalParametersFound = true; - break; - } - } - Pos += 2; - } else { - unsigned I = Pos + 1; - while (isIdentifierChar(Body[I]) && I + 1 != End) - ++I; - - const char *Begin = Body.data() + Pos + 1; - StringRef Argument(Begin, I - (Pos + 1)); - unsigned Index = 0; - for (; Index < NParameters; ++Index) - if (Parameters[Index].Name == Argument) - break; - - if (Index == NParameters) { - if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')') - Pos += 3; - else { - Pos = I; - } - } else { - NamedParametersFound = true; - Pos += 1 + Argument.size(); - } - } - // Update the scan point. - Body = Body.substr(Pos); - } - - if (!NamedParametersFound && PositionalParametersFound) - Warning(DirectiveLoc, "macro defined with named parameters which are not " - "used in macro body, possible positional parameter " - "found in body which will have no effect"); -} - -/// parseDirectiveExitMacro -/// ::= .exitm -bool AsmParser::parseDirectiveExitMacro(StringRef Directive) { - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '" + Directive + "' directive")) - return true; - - if (!isInsideMacroInstantiation()) - return TokError("unexpected '" + Directive + "' in file, " - "no current macro definition"); - - // Exit all conditionals that are active in the current macro. - while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) { - TheCondState = TheCondStack.back(); - TheCondStack.pop_back(); - } - - handleMacroExit(); - return false; -} - -/// parseDirectiveEndMacro -/// ::= .endm -/// ::= .endmacro -bool AsmParser::parseDirectiveEndMacro(StringRef Directive) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '" + Directive + "' directive"); - - // If we are inside a macro instantiation, terminate the current - // instantiation. - if (isInsideMacroInstantiation()) { - handleMacroExit(); - return false; - } - - // Otherwise, this .endmacro is a stray entry in the file; well formed - // .endmacro directives are handled during the macro definition parsing. - return TokError("unexpected '" + Directive + "' in file, " - "no current macro definition"); -} - -/// parseDirectivePurgeMacro -/// ::= .purgem -bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) { - StringRef Name; - SMLoc Loc; - if (parseTokenLoc(Loc) || - check(parseIdentifier(Name), Loc, - "expected identifier in '.purgem' directive") || - parseToken(AsmToken::EndOfStatement, - "unexpected token in '.purgem' directive")) - return true; - - if (!getContext().lookupMacro(Name)) - return Error(DirectiveLoc, "macro '" + Name + "' is not defined"); - - getContext().undefineMacro(Name); - DEBUG_WITH_TYPE("asm-macros", dbgs() - << "Un-defining macro: " << Name << "\n"); - return false; -} - -/// parseDirectiveBundleAlignMode -/// ::= {.bundle_align_mode} expression -bool AsmParser::parseDirectiveBundleAlignMode() { - // Expect a single argument: an expression that evaluates to a constant - // in the inclusive range 0-30. - SMLoc ExprLoc = getLexer().getLoc(); - int64_t AlignSizePow2; - if (checkForValidSection() || parseAbsoluteExpression(AlignSizePow2) || - parseToken(AsmToken::EndOfStatement, "unexpected token after expression " - "in '.bundle_align_mode' " - "directive") || - check(AlignSizePow2 < 0 || AlignSizePow2 > 30, ExprLoc, - "invalid bundle alignment size (expected between 0 and 30)")) - return true; - - // Because of AlignSizePow2's verified range we can safely truncate it to - // unsigned. - getStreamer().EmitBundleAlignMode(static_cast<unsigned>(AlignSizePow2)); - return false; -} - -/// parseDirectiveBundleLock -/// ::= {.bundle_lock} [align_to_end] -bool AsmParser::parseDirectiveBundleLock() { - if (checkForValidSection()) - return true; - bool AlignToEnd = false; - - StringRef Option; - SMLoc Loc = getTok().getLoc(); - const char *kInvalidOptionError = - "invalid option for '.bundle_lock' directive"; - - if (!parseOptionalToken(AsmToken::EndOfStatement)) { - if (check(parseIdentifier(Option), Loc, kInvalidOptionError) || - check(Option != "align_to_end", Loc, kInvalidOptionError) || - parseToken(AsmToken::EndOfStatement, - "unexpected token after '.bundle_lock' directive option")) - return true; - AlignToEnd = true; - } - - getStreamer().EmitBundleLock(AlignToEnd); - return false; -} - -/// parseDirectiveBundleLock -/// ::= {.bundle_lock} -bool AsmParser::parseDirectiveBundleUnlock() { - if (checkForValidSection() || - parseToken(AsmToken::EndOfStatement, - "unexpected token in '.bundle_unlock' directive")) - return true; - - getStreamer().EmitBundleUnlock(); - return false; -} - -/// parseDirectiveSpace -/// ::= (.skip | .space) expression [ , expression ] -bool AsmParser::parseDirectiveSpace(StringRef IDVal) { - SMLoc NumBytesLoc = Lexer.getLoc(); - const MCExpr *NumBytes; - if (checkForValidSection() || parseExpression(NumBytes)) - return true; - - int64_t FillExpr = 0; - if (parseOptionalToken(AsmToken::Comma)) - if (parseAbsoluteExpression(FillExpr)) - return addErrorSuffix("in '" + Twine(IDVal) + "' directive"); - if (parseToken(AsmToken::EndOfStatement)) - return addErrorSuffix("in '" + Twine(IDVal) + "' directive"); - - // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0. - getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc); - - return false; -} - -/// parseDirectiveDCB -/// ::= .dcb.{b, l, w} expression, expression -bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) { - SMLoc NumValuesLoc = Lexer.getLoc(); - int64_t NumValues; - if (checkForValidSection() || parseAbsoluteExpression(NumValues)) - return true; - - if (NumValues < 0) { - Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect"); - return false; - } - - if (parseToken(AsmToken::Comma, - "unexpected token in '" + Twine(IDVal) + "' directive")) - return true; - - const MCExpr *Value; - SMLoc ExprLoc = getLexer().getLoc(); - if (parseExpression(Value)) - return true; - - // Special case constant expressions to match code generator. - if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { - assert(Size <= 8 && "Invalid size"); - uint64_t IntValue = MCE->getValue(); - if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue)) - return Error(ExprLoc, "literal value out of range for directive"); - for (uint64_t i = 0, e = NumValues; i != e; ++i) - getStreamer().EmitIntValue(IntValue, Size); - } else { - for (uint64_t i = 0, e = NumValues; i != e; ++i) - getStreamer().EmitValue(Value, Size, ExprLoc); - } - - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '" + Twine(IDVal) + "' directive")) - return true; - - return false; -} - -/// parseDirectiveRealDCB -/// ::= .dcb.{d, s} expression, expression -bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Semantics) { - SMLoc NumValuesLoc = Lexer.getLoc(); - int64_t NumValues; - if (checkForValidSection() || parseAbsoluteExpression(NumValues)) - return true; - - if (NumValues < 0) { - Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect"); - return false; - } - - if (parseToken(AsmToken::Comma, - "unexpected token in '" + Twine(IDVal) + "' directive")) - return true; - - APInt AsInt; - if (parseRealValue(Semantics, AsInt)) - return true; - - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '" + Twine(IDVal) + "' directive")) - return true; - - for (uint64_t i = 0, e = NumValues; i != e; ++i) - getStreamer().EmitIntValue(AsInt.getLimitedValue(), - AsInt.getBitWidth() / 8); - - return false; -} - -/// parseDirectiveDS -/// ::= .ds.{b, d, l, p, s, w, x} expression -bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) { - SMLoc NumValuesLoc = Lexer.getLoc(); - int64_t NumValues; - if (checkForValidSection() || parseAbsoluteExpression(NumValues)) - return true; - - if (NumValues < 0) { - Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect"); - return false; - } - - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '" + Twine(IDVal) + "' directive")) - return true; - - for (uint64_t i = 0, e = NumValues; i != e; ++i) - getStreamer().emitFill(Size, 0); - - return false; -} - -/// parseDirectiveLEB128 -/// ::= (.sleb128 | .uleb128) [ expression (, expression)* ] -bool AsmParser::parseDirectiveLEB128(bool Signed) { - if (checkForValidSection()) - return true; - - auto parseOp = [&]() -> bool { - const MCExpr *Value; - if (parseExpression(Value)) - return true; - if (Signed) - getStreamer().EmitSLEB128Value(Value); - else - getStreamer().EmitULEB128Value(Value); - return false; - }; - - if (parseMany(parseOp)) - return addErrorSuffix(" in directive"); - - return false; -} - -/// parseDirectiveSymbolAttribute -/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ] -bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) { - auto parseOp = [&]() -> bool { - StringRef Name; - SMLoc Loc = getTok().getLoc(); - if (parseIdentifier(Name)) - return Error(Loc, "expected identifier"); - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - - // Assembler local symbols don't make any sense here. Complain loudly. - if (Sym->isTemporary()) - return Error(Loc, "non-local symbol required"); - - if (!getStreamer().EmitSymbolAttribute(Sym, Attr)) - return Error(Loc, "unable to emit symbol attribute"); - return false; - }; - - if (parseMany(parseOp)) - return addErrorSuffix(" in directive"); - return false; -} - -/// parseDirectiveComm -/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ] -bool AsmParser::parseDirectiveComm(bool IsLocal) { - if (checkForValidSection()) - return true; - - SMLoc IDLoc = getLexer().getLoc(); - StringRef Name; - if (parseIdentifier(Name)) - return TokError("expected identifier in directive"); - - // Handle the identifier as the key symbol. - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - - int64_t Size; - SMLoc SizeLoc = getLexer().getLoc(); - if (parseAbsoluteExpression(Size)) - return true; - - int64_t Pow2Alignment = 0; - SMLoc Pow2AlignmentLoc; - if (getLexer().is(AsmToken::Comma)) { - Lex(); - Pow2AlignmentLoc = getLexer().getLoc(); - if (parseAbsoluteExpression(Pow2Alignment)) - return true; - - LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType(); - if (IsLocal && LCOMM == LCOMM::NoAlignment) - return Error(Pow2AlignmentLoc, "alignment not supported on this target"); - - // If this target takes alignments in bytes (not log) validate and convert. - if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) || - (IsLocal && LCOMM == LCOMM::ByteAlignment)) { - if (!isPowerOf2_64(Pow2Alignment)) - return Error(Pow2AlignmentLoc, "alignment must be a power of 2"); - Pow2Alignment = Log2_64(Pow2Alignment); - } - } - - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.comm' or '.lcomm' directive")) - return true; - - // NOTE: a size of zero for a .comm should create a undefined symbol - // but a size of .lcomm creates a bss symbol of size zero. - if (Size < 0) - return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't " - "be less than zero"); - - // NOTE: The alignment in the directive is a power of 2 value, the assembler - // may internally end up wanting an alignment in bytes. - // FIXME: Diagnose overflow. - if (Pow2Alignment < 0) - return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive " - "alignment, can't be less than zero"); - - Sym->redefineIfPossible(); - if (!Sym->isUndefined()) - return Error(IDLoc, "invalid symbol redefinition"); - - // Create the Symbol as a common or local common with Size and Pow2Alignment - if (IsLocal) { - getStreamer().EmitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment); - return false; - } - - getStreamer().EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment); - return false; -} - -/// parseDirectiveAbort -/// ::= .abort [... message ...] -bool AsmParser::parseDirectiveAbort() { - // FIXME: Use loc from directive. - SMLoc Loc = getLexer().getLoc(); - - StringRef Str = parseStringToEndOfStatement(); - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.abort' directive")) - return true; - - if (Str.empty()) - return Error(Loc, ".abort detected. Assembly stopping."); - else - return Error(Loc, ".abort '" + Str + "' detected. Assembly stopping."); - // FIXME: Actually abort assembly here. - - return false; -} - -/// parseDirectiveInclude -/// ::= .include "filename" -bool AsmParser::parseDirectiveInclude() { - // Allow the strings to have escaped octal character sequence. - std::string Filename; - SMLoc IncludeLoc = getTok().getLoc(); - - if (check(getTok().isNot(AsmToken::String), - "expected string in '.include' directive") || - parseEscapedString(Filename) || - check(getTok().isNot(AsmToken::EndOfStatement), - "unexpected token in '.include' directive") || - // Attempt to switch the lexer to the included file before consuming the - // end of statement to avoid losing it when we switch. - check(enterIncludeFile(Filename), IncludeLoc, - "Could not find include file '" + Filename + "'")) - return true; - - return false; -} - -/// parseDirectiveIncbin -/// ::= .incbin "filename" [ , skip [ , count ] ] -bool AsmParser::parseDirectiveIncbin() { - // Allow the strings to have escaped octal character sequence. - std::string Filename; - SMLoc IncbinLoc = getTok().getLoc(); - if (check(getTok().isNot(AsmToken::String), - "expected string in '.incbin' directive") || - parseEscapedString(Filename)) - return true; - - int64_t Skip = 0; - const MCExpr *Count = nullptr; - SMLoc SkipLoc, CountLoc; - if (parseOptionalToken(AsmToken::Comma)) { - // The skip expression can be omitted while specifying the count, e.g: - // .incbin "filename",,4 - if (getTok().isNot(AsmToken::Comma)) { - if (parseTokenLoc(SkipLoc) || parseAbsoluteExpression(Skip)) - return true; - } - if (parseOptionalToken(AsmToken::Comma)) { - CountLoc = getTok().getLoc(); - if (parseExpression(Count)) - return true; - } - } - - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.incbin' directive")) - return true; - - if (check(Skip < 0, SkipLoc, "skip is negative")) - return true; - - // Attempt to process the included file. - if (processIncbinFile(Filename, Skip, Count, CountLoc)) - return Error(IncbinLoc, "Could not find incbin file '" + Filename + "'"); - return false; -} - -/// parseDirectiveIf -/// ::= .if{,eq,ge,gt,le,lt,ne} expression -bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) { - TheCondStack.push_back(TheCondState); - TheCondState.TheCond = AsmCond::IfCond; - if (TheCondState.Ignore) { - eatToEndOfStatement(); - } else { - int64_t ExprValue; - if (parseAbsoluteExpression(ExprValue) || - parseToken(AsmToken::EndOfStatement, - "unexpected token in '.if' directive")) - return true; - - switch (DirKind) { - default: - llvm_unreachable("unsupported directive"); - case DK_IF: - case DK_IFNE: - break; - case DK_IFEQ: - ExprValue = ExprValue == 0; - break; - case DK_IFGE: - ExprValue = ExprValue >= 0; - break; - case DK_IFGT: - ExprValue = ExprValue > 0; - break; - case DK_IFLE: - ExprValue = ExprValue <= 0; - break; - case DK_IFLT: - ExprValue = ExprValue < 0; - break; - } - - TheCondState.CondMet = ExprValue; - TheCondState.Ignore = !TheCondState.CondMet; - } - - return false; -} - -/// parseDirectiveIfb -/// ::= .ifb string -bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) { - TheCondStack.push_back(TheCondState); - TheCondState.TheCond = AsmCond::IfCond; - - if (TheCondState.Ignore) { - eatToEndOfStatement(); - } else { - StringRef Str = parseStringToEndOfStatement(); - - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.ifb' directive")) - return true; - - TheCondState.CondMet = ExpectBlank == Str.empty(); - TheCondState.Ignore = !TheCondState.CondMet; - } - - return false; -} - -/// parseDirectiveIfc -/// ::= .ifc string1, string2 -/// ::= .ifnc string1, string2 -bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) { - TheCondStack.push_back(TheCondState); - TheCondState.TheCond = AsmCond::IfCond; - - if (TheCondState.Ignore) { - eatToEndOfStatement(); - } else { - StringRef Str1 = parseStringToComma(); - - if (parseToken(AsmToken::Comma, "unexpected token in '.ifc' directive")) - return true; - - StringRef Str2 = parseStringToEndOfStatement(); - - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.ifc' directive")) - return true; - - TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim()); - TheCondState.Ignore = !TheCondState.CondMet; - } - - return false; -} - -/// parseDirectiveIfeqs -/// ::= .ifeqs string1, string2 -bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) { - if (Lexer.isNot(AsmToken::String)) { - if (ExpectEqual) - return TokError("expected string parameter for '.ifeqs' directive"); - return TokError("expected string parameter for '.ifnes' directive"); - } - - StringRef String1 = getTok().getStringContents(); - Lex(); - - if (Lexer.isNot(AsmToken::Comma)) { - if (ExpectEqual) - return TokError( - "expected comma after first string for '.ifeqs' directive"); - return TokError("expected comma after first string for '.ifnes' directive"); - } - - Lex(); - - if (Lexer.isNot(AsmToken::String)) { - if (ExpectEqual) - return TokError("expected string parameter for '.ifeqs' directive"); - return TokError("expected string parameter for '.ifnes' directive"); - } - - StringRef String2 = getTok().getStringContents(); - Lex(); - - TheCondStack.push_back(TheCondState); - TheCondState.TheCond = AsmCond::IfCond; - TheCondState.CondMet = ExpectEqual == (String1 == String2); - TheCondState.Ignore = !TheCondState.CondMet; - - return false; -} - -/// parseDirectiveIfdef -/// ::= .ifdef symbol -bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { - StringRef Name; - TheCondStack.push_back(TheCondState); - TheCondState.TheCond = AsmCond::IfCond; - - if (TheCondState.Ignore) { - eatToEndOfStatement(); - } else { - if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") || - parseToken(AsmToken::EndOfStatement, "unexpected token in '.ifdef'")) - return true; - - MCSymbol *Sym = getContext().lookupSymbol(Name); - - if (expect_defined) - TheCondState.CondMet = (Sym && !Sym->isUndefined(false)); - else - TheCondState.CondMet = (!Sym || Sym->isUndefined(false)); - TheCondState.Ignore = !TheCondState.CondMet; - } - - return false; -} - -/// parseDirectiveElseIf -/// ::= .elseif expression -bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) { - if (TheCondState.TheCond != AsmCond::IfCond && - TheCondState.TheCond != AsmCond::ElseIfCond) - return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an" - " .if or an .elseif"); - TheCondState.TheCond = AsmCond::ElseIfCond; - - bool LastIgnoreState = false; - if (!TheCondStack.empty()) - LastIgnoreState = TheCondStack.back().Ignore; - if (LastIgnoreState || TheCondState.CondMet) { - TheCondState.Ignore = true; - eatToEndOfStatement(); - } else { - int64_t ExprValue; - if (parseAbsoluteExpression(ExprValue)) - return true; - - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.elseif' directive")) - return true; - - TheCondState.CondMet = ExprValue; - TheCondState.Ignore = !TheCondState.CondMet; - } - - return false; -} - -/// parseDirectiveElse -/// ::= .else -bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) { - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.else' directive")) - return true; - - if (TheCondState.TheCond != AsmCond::IfCond && - TheCondState.TheCond != AsmCond::ElseIfCond) - return Error(DirectiveLoc, "Encountered a .else that doesn't follow " - " an .if or an .elseif"); - TheCondState.TheCond = AsmCond::ElseCond; - bool LastIgnoreState = false; - if (!TheCondStack.empty()) - LastIgnoreState = TheCondStack.back().Ignore; - if (LastIgnoreState || TheCondState.CondMet) - TheCondState.Ignore = true; - else - TheCondState.Ignore = false; - - return false; -} - -/// parseDirectiveEnd -/// ::= .end -bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) { - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.end' directive")) - return true; - - while (Lexer.isNot(AsmToken::Eof)) - Lexer.Lex(); - - return false; -} - -/// parseDirectiveError -/// ::= .err -/// ::= .error [string] -bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) { - if (!TheCondStack.empty()) { - if (TheCondStack.back().Ignore) { - eatToEndOfStatement(); - return false; - } - } - - if (!WithMessage) - return Error(L, ".err encountered"); - - StringRef Message = ".error directive invoked in source file"; - if (Lexer.isNot(AsmToken::EndOfStatement)) { - if (Lexer.isNot(AsmToken::String)) - return TokError(".error argument must be a string"); - - Message = getTok().getStringContents(); - Lex(); - } - - return Error(L, Message); -} - -/// parseDirectiveWarning -/// ::= .warning [string] -bool AsmParser::parseDirectiveWarning(SMLoc L) { - if (!TheCondStack.empty()) { - if (TheCondStack.back().Ignore) { - eatToEndOfStatement(); - return false; - } - } - - StringRef Message = ".warning directive invoked in source file"; - - if (!parseOptionalToken(AsmToken::EndOfStatement)) { - if (Lexer.isNot(AsmToken::String)) - return TokError(".warning argument must be a string"); - - Message = getTok().getStringContents(); - Lex(); - if (parseToken(AsmToken::EndOfStatement, - "expected end of statement in '.warning' directive")) - return true; - } - - return Warning(L, Message); -} - -/// parseDirectiveEndIf -/// ::= .endif -bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) { - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.endif' directive")) - return true; - - if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty()) - return Error(DirectiveLoc, "Encountered a .endif that doesn't follow " - "an .if or .else"); - if (!TheCondStack.empty()) { - TheCondState = TheCondStack.back(); - TheCondStack.pop_back(); - } - - return false; -} - -void AsmParser::initializeDirectiveKindMap() { - DirectiveKindMap[".set"] = DK_SET; - DirectiveKindMap[".equ"] = DK_EQU; - DirectiveKindMap[".equiv"] = DK_EQUIV; - DirectiveKindMap[".ascii"] = DK_ASCII; - DirectiveKindMap[".asciz"] = DK_ASCIZ; - DirectiveKindMap[".string"] = DK_STRING; - DirectiveKindMap[".byte"] = DK_BYTE; - DirectiveKindMap[".short"] = DK_SHORT; - DirectiveKindMap[".value"] = DK_VALUE; - DirectiveKindMap[".2byte"] = DK_2BYTE; - DirectiveKindMap[".long"] = DK_LONG; - DirectiveKindMap[".int"] = DK_INT; - DirectiveKindMap[".4byte"] = DK_4BYTE; - DirectiveKindMap[".quad"] = DK_QUAD; - DirectiveKindMap[".8byte"] = DK_8BYTE; - DirectiveKindMap[".octa"] = DK_OCTA; - DirectiveKindMap[".single"] = DK_SINGLE; - DirectiveKindMap[".float"] = DK_FLOAT; - DirectiveKindMap[".double"] = DK_DOUBLE; - DirectiveKindMap[".align"] = DK_ALIGN; - DirectiveKindMap[".align32"] = DK_ALIGN32; - DirectiveKindMap[".balign"] = DK_BALIGN; - DirectiveKindMap[".balignw"] = DK_BALIGNW; - DirectiveKindMap[".balignl"] = DK_BALIGNL; - DirectiveKindMap[".p2align"] = DK_P2ALIGN; - DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW; - DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL; - DirectiveKindMap[".org"] = DK_ORG; - DirectiveKindMap[".fill"] = DK_FILL; - DirectiveKindMap[".zero"] = DK_ZERO; - DirectiveKindMap[".extern"] = DK_EXTERN; - DirectiveKindMap[".globl"] = DK_GLOBL; - DirectiveKindMap[".global"] = DK_GLOBAL; - DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE; - DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP; - DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER; - DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN; - DirectiveKindMap[".reference"] = DK_REFERENCE; - DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION; - DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE; - DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN; - DirectiveKindMap[".cold"] = DK_COLD; - DirectiveKindMap[".comm"] = DK_COMM; - DirectiveKindMap[".common"] = DK_COMMON; - DirectiveKindMap[".lcomm"] = DK_LCOMM; - DirectiveKindMap[".abort"] = DK_ABORT; - DirectiveKindMap[".include"] = DK_INCLUDE; - DirectiveKindMap[".incbin"] = DK_INCBIN; - DirectiveKindMap[".code16"] = DK_CODE16; - DirectiveKindMap[".code16gcc"] = DK_CODE16GCC; - DirectiveKindMap[".rept"] = DK_REPT; - DirectiveKindMap[".rep"] = DK_REPT; - DirectiveKindMap[".irp"] = DK_IRP; - DirectiveKindMap[".irpc"] = DK_IRPC; - DirectiveKindMap[".endr"] = DK_ENDR; - DirectiveKindMap[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE; - DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK; - DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK; - DirectiveKindMap[".if"] = DK_IF; - DirectiveKindMap[".ifeq"] = DK_IFEQ; - DirectiveKindMap[".ifge"] = DK_IFGE; - DirectiveKindMap[".ifgt"] = DK_IFGT; - DirectiveKindMap[".ifle"] = DK_IFLE; - DirectiveKindMap[".iflt"] = DK_IFLT; - DirectiveKindMap[".ifne"] = DK_IFNE; - DirectiveKindMap[".ifb"] = DK_IFB; - DirectiveKindMap[".ifnb"] = DK_IFNB; - DirectiveKindMap[".ifc"] = DK_IFC; - DirectiveKindMap[".ifeqs"] = DK_IFEQS; - DirectiveKindMap[".ifnc"] = DK_IFNC; - DirectiveKindMap[".ifnes"] = DK_IFNES; - DirectiveKindMap[".ifdef"] = DK_IFDEF; - DirectiveKindMap[".ifndef"] = DK_IFNDEF; - DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF; - DirectiveKindMap[".elseif"] = DK_ELSEIF; - DirectiveKindMap[".else"] = DK_ELSE; - DirectiveKindMap[".end"] = DK_END; - DirectiveKindMap[".endif"] = DK_ENDIF; - DirectiveKindMap[".skip"] = DK_SKIP; - DirectiveKindMap[".space"] = DK_SPACE; - DirectiveKindMap[".file"] = DK_FILE; - DirectiveKindMap[".line"] = DK_LINE; - DirectiveKindMap[".loc"] = DK_LOC; - DirectiveKindMap[".stabs"] = DK_STABS; - DirectiveKindMap[".cv_file"] = DK_CV_FILE; - DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID; - DirectiveKindMap[".cv_loc"] = DK_CV_LOC; - DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE; - DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE; - DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID; - DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE; - DirectiveKindMap[".cv_string"] = DK_CV_STRING; - DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE; - DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS; - DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET; - DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA; - DirectiveKindMap[".sleb128"] = DK_SLEB128; - DirectiveKindMap[".uleb128"] = DK_ULEB128; - DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS; - DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC; - DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC; - DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA; - DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET; - DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET; - DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER; - DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET; - DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET; - DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY; - DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA; - DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE; - DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE; - DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE; - DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE; - DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE; - DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN; - DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME; - DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED; - DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER; - DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE; - DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME; - DirectiveKindMap[".macros_on"] = DK_MACROS_ON; - DirectiveKindMap[".macros_off"] = DK_MACROS_OFF; - DirectiveKindMap[".macro"] = DK_MACRO; - DirectiveKindMap[".exitm"] = DK_EXITM; - DirectiveKindMap[".endm"] = DK_ENDM; - DirectiveKindMap[".endmacro"] = DK_ENDMACRO; - DirectiveKindMap[".purgem"] = DK_PURGEM; - DirectiveKindMap[".err"] = DK_ERR; - DirectiveKindMap[".error"] = DK_ERROR; - DirectiveKindMap[".warning"] = DK_WARNING; - DirectiveKindMap[".altmacro"] = DK_ALTMACRO; - DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO; - DirectiveKindMap[".reloc"] = DK_RELOC; - DirectiveKindMap[".dc"] = DK_DC; - DirectiveKindMap[".dc.a"] = DK_DC_A; - DirectiveKindMap[".dc.b"] = DK_DC_B; - DirectiveKindMap[".dc.d"] = DK_DC_D; - DirectiveKindMap[".dc.l"] = DK_DC_L; - DirectiveKindMap[".dc.s"] = DK_DC_S; - DirectiveKindMap[".dc.w"] = DK_DC_W; - DirectiveKindMap[".dc.x"] = DK_DC_X; - DirectiveKindMap[".dcb"] = DK_DCB; - DirectiveKindMap[".dcb.b"] = DK_DCB_B; - DirectiveKindMap[".dcb.d"] = DK_DCB_D; - DirectiveKindMap[".dcb.l"] = DK_DCB_L; - DirectiveKindMap[".dcb.s"] = DK_DCB_S; - DirectiveKindMap[".dcb.w"] = DK_DCB_W; - DirectiveKindMap[".dcb.x"] = DK_DCB_X; - DirectiveKindMap[".ds"] = DK_DS; - DirectiveKindMap[".ds.b"] = DK_DS_B; - DirectiveKindMap[".ds.d"] = DK_DS_D; - DirectiveKindMap[".ds.l"] = DK_DS_L; - DirectiveKindMap[".ds.p"] = DK_DS_P; - DirectiveKindMap[".ds.s"] = DK_DS_S; - DirectiveKindMap[".ds.w"] = DK_DS_W; - DirectiveKindMap[".ds.x"] = DK_DS_X; - DirectiveKindMap[".print"] = DK_PRINT; - DirectiveKindMap[".addrsig"] = DK_ADDRSIG; - DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM; -} - -MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { - AsmToken EndToken, StartToken = getTok(); - - unsigned NestLevel = 0; - while (true) { - // Check whether we have reached the end of the file. - if (getLexer().is(AsmToken::Eof)) { - printError(DirectiveLoc, "no matching '.endr' in definition"); - return nullptr; - } - - if (Lexer.is(AsmToken::Identifier) && - (getTok().getIdentifier() == ".rep" || - getTok().getIdentifier() == ".rept" || - getTok().getIdentifier() == ".irp" || - getTok().getIdentifier() == ".irpc")) { - ++NestLevel; - } - - // Otherwise, check whether we have reached the .endr. - if (Lexer.is(AsmToken::Identifier) && getTok().getIdentifier() == ".endr") { - if (NestLevel == 0) { - EndToken = getTok(); - Lex(); - if (Lexer.isNot(AsmToken::EndOfStatement)) { - printError(getTok().getLoc(), - "unexpected token in '.endr' directive"); - return nullptr; - } - break; - } - --NestLevel; - } - - // Otherwise, scan till the end of the statement. - eatToEndOfStatement(); - } - - const char *BodyStart = StartToken.getLoc().getPointer(); - const char *BodyEnd = EndToken.getLoc().getPointer(); - StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart); - - // We Are Anonymous. - MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters()); - return &MacroLikeBodies.back(); -} - -void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, - raw_svector_ostream &OS) { - OS << ".endr\n"; - - std::unique_ptr<MemoryBuffer> Instantiation = - MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>"); - - // Create the macro instantiation object and add to the current macro - // instantiation stack. - MacroInstantiation *MI = new MacroInstantiation( - DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()); - ActiveMacros.push_back(MI); - - // Jump to the macro instantiation and prime the lexer. - CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc()); - Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); - Lex(); -} - -/// parseDirectiveRept -/// ::= .rep | .rept count -bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) { - const MCExpr *CountExpr; - SMLoc CountLoc = getTok().getLoc(); - if (parseExpression(CountExpr)) - return true; - - int64_t Count; - if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) { - return Error(CountLoc, "unexpected token in '" + Dir + "' directive"); - } - - if (check(Count < 0, CountLoc, "Count is negative") || - parseToken(AsmToken::EndOfStatement, - "unexpected token in '" + Dir + "' directive")) - return true; - - // Lex the rept definition. - MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); - if (!M) - return true; - - // Macro instantiation is lexical, unfortunately. We construct a new buffer - // to hold the macro body with substitutions. - SmallString<256> Buf; - raw_svector_ostream OS(Buf); - while (Count--) { - // Note that the AtPseudoVariable is disabled for instantiations of .rep(t). - if (expandMacro(OS, M->Body, None, None, false, getTok().getLoc())) - return true; - } - instantiateMacroLikeBody(M, DirectiveLoc, OS); - - return false; -} - -/// parseDirectiveIrp -/// ::= .irp symbol,values -bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) { - MCAsmMacroParameter Parameter; - MCAsmMacroArguments A; - if (check(parseIdentifier(Parameter.Name), - "expected identifier in '.irp' directive") || - parseToken(AsmToken::Comma, "expected comma in '.irp' directive") || - parseMacroArguments(nullptr, A) || - parseToken(AsmToken::EndOfStatement, "expected End of Statement")) - return true; - - // Lex the irp definition. - MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); - if (!M) - return true; - - // Macro instantiation is lexical, unfortunately. We construct a new buffer - // to hold the macro body with substitutions. - SmallString<256> Buf; - raw_svector_ostream OS(Buf); - - for (const MCAsmMacroArgument &Arg : A) { - // Note that the AtPseudoVariable is enabled for instantiations of .irp. - // This is undocumented, but GAS seems to support it. - if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc())) - return true; - } - - instantiateMacroLikeBody(M, DirectiveLoc, OS); - - return false; -} - -/// parseDirectiveIrpc -/// ::= .irpc symbol,values -bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) { - MCAsmMacroParameter Parameter; - MCAsmMacroArguments A; - - if (check(parseIdentifier(Parameter.Name), - "expected identifier in '.irpc' directive") || - parseToken(AsmToken::Comma, "expected comma in '.irpc' directive") || - parseMacroArguments(nullptr, A)) - return true; - - if (A.size() != 1 || A.front().size() != 1) - return TokError("unexpected token in '.irpc' directive"); - - // Eat the end of statement. - if (parseToken(AsmToken::EndOfStatement, "expected end of statement")) - return true; - - // Lex the irpc definition. - MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); - if (!M) - return true; - - // Macro instantiation is lexical, unfortunately. We construct a new buffer - // to hold the macro body with substitutions. - SmallString<256> Buf; - raw_svector_ostream OS(Buf); - - StringRef Values = A.front().front().getString(); - for (std::size_t I = 0, End = Values.size(); I != End; ++I) { - MCAsmMacroArgument Arg; - Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1)); - - // Note that the AtPseudoVariable is enabled for instantiations of .irpc. - // This is undocumented, but GAS seems to support it. - if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc())) - return true; - } - - instantiateMacroLikeBody(M, DirectiveLoc, OS); - - return false; -} - -bool AsmParser::parseDirectiveEndr(SMLoc DirectiveLoc) { - if (ActiveMacros.empty()) - return TokError("unmatched '.endr' directive"); - - // The only .repl that should get here are the ones created by - // instantiateMacroLikeBody. - assert(getLexer().is(AsmToken::EndOfStatement)); - - handleMacroExit(); - return false; -} - -bool AsmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info, - size_t Len) { - const MCExpr *Value; - SMLoc ExprLoc = getLexer().getLoc(); - if (parseExpression(Value)) - return true; - const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value); - if (!MCE) - return Error(ExprLoc, "unexpected expression in _emit"); - uint64_t IntValue = MCE->getValue(); - if (!isUInt<8>(IntValue) && !isInt<8>(IntValue)) - return Error(ExprLoc, "literal value out of range for directive"); - - Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len); - return false; -} - -bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) { - const MCExpr *Value; - SMLoc ExprLoc = getLexer().getLoc(); - if (parseExpression(Value)) - return true; - const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value); - if (!MCE) - return Error(ExprLoc, "unexpected expression in align"); - uint64_t IntValue = MCE->getValue(); - if (!isPowerOf2_64(IntValue)) - return Error(ExprLoc, "literal value not a power of two greater then zero"); - - Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue)); - return false; -} - -bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) { - const AsmToken StrTok = getTok(); - Lex(); - if (StrTok.isNot(AsmToken::String) || StrTok.getString().front() != '"') - return Error(DirectiveLoc, "expected double quoted string after .print"); - if (parseToken(AsmToken::EndOfStatement, "expected end of statement")) - return true; - llvm::outs() << StrTok.getStringContents() << '\n'; - return false; -} - -bool AsmParser::parseDirectiveAddrsig() { - getStreamer().EmitAddrsig(); - return false; -} - -bool AsmParser::parseDirectiveAddrsigSym() { - StringRef Name; - if (check(parseIdentifier(Name), - "expected identifier in '.addrsig_sym' directive")) - return true; - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - getStreamer().EmitAddrsigSym(Sym); - return false; -} - -// We are comparing pointers, but the pointers are relative to a single string. -// Thus, this should always be deterministic. -static int rewritesSort(const AsmRewrite *AsmRewriteA, - const AsmRewrite *AsmRewriteB) { - if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer()) - return -1; - if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer()) - return 1; - - // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output - // rewrite to the same location. Make sure the SizeDirective rewrite is - // performed first, then the Imm/ImmPrefix and finally the Input/Output. This - // ensures the sort algorithm is stable. - if (AsmRewritePrecedence[AsmRewriteA->Kind] > - AsmRewritePrecedence[AsmRewriteB->Kind]) - return -1; - - if (AsmRewritePrecedence[AsmRewriteA->Kind] < - AsmRewritePrecedence[AsmRewriteB->Kind]) - return 1; - llvm_unreachable("Unstable rewrite sort."); -} - -bool AsmParser::parseMSInlineAsm( - void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, - unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls, - SmallVectorImpl<std::string> &Constraints, - SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII, - const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) { - SmallVector<void *, 4> InputDecls; - SmallVector<void *, 4> OutputDecls; - SmallVector<bool, 4> InputDeclsAddressOf; - SmallVector<bool, 4> OutputDeclsAddressOf; - SmallVector<std::string, 4> InputConstraints; - SmallVector<std::string, 4> OutputConstraints; - SmallVector<unsigned, 4> ClobberRegs; - - SmallVector<AsmRewrite, 4> AsmStrRewrites; - - // Prime the lexer. - Lex(); - - // While we have input, parse each statement. - unsigned InputIdx = 0; - unsigned OutputIdx = 0; - while (getLexer().isNot(AsmToken::Eof)) { - // Parse curly braces marking block start/end - if (parseCurlyBlockScope(AsmStrRewrites)) - continue; - - ParseStatementInfo Info(&AsmStrRewrites); - bool StatementErr = parseStatement(Info, &SI); - - if (StatementErr || Info.ParseError) { - // Emit pending errors if any exist. - printPendingErrors(); - return true; - } - - // No pending error should exist here. - assert(!hasPendingError() && "unexpected error from parseStatement"); - - if (Info.Opcode == ~0U) - continue; - - const MCInstrDesc &Desc = MII->get(Info.Opcode); - - // Build the list of clobbers, outputs and inputs. - for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) { - MCParsedAsmOperand &Operand = *Info.ParsedOperands[i]; - - // Immediate. - if (Operand.isImm()) - continue; - - // Register operand. - if (Operand.isReg() && !Operand.needAddressOf() && - !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) { - unsigned NumDefs = Desc.getNumDefs(); - // Clobber. - if (NumDefs && Operand.getMCOperandNum() < NumDefs) - ClobberRegs.push_back(Operand.getReg()); - continue; - } - - // Expr/Input or Output. - StringRef SymName = Operand.getSymName(); - if (SymName.empty()) - continue; - - void *OpDecl = Operand.getOpDecl(); - if (!OpDecl) - continue; - - bool isOutput = (i == 1) && Desc.mayStore(); - SMLoc Start = SMLoc::getFromPointer(SymName.data()); - if (isOutput) { - ++InputIdx; - OutputDecls.push_back(OpDecl); - OutputDeclsAddressOf.push_back(Operand.needAddressOf()); - OutputConstraints.push_back(("=" + Operand.getConstraint()).str()); - AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size()); - } else { - InputDecls.push_back(OpDecl); - InputDeclsAddressOf.push_back(Operand.needAddressOf()); - InputConstraints.push_back(Operand.getConstraint().str()); - AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size()); - } - } - - // Consider implicit defs to be clobbers. Think of cpuid and push. - ArrayRef<MCPhysReg> ImpDefs(Desc.getImplicitDefs(), - Desc.getNumImplicitDefs()); - ClobberRegs.insert(ClobberRegs.end(), ImpDefs.begin(), ImpDefs.end()); - } - - // Set the number of Outputs and Inputs. - NumOutputs = OutputDecls.size(); - NumInputs = InputDecls.size(); - - // Set the unique clobbers. - array_pod_sort(ClobberRegs.begin(), ClobberRegs.end()); - ClobberRegs.erase(std::unique(ClobberRegs.begin(), ClobberRegs.end()), - ClobberRegs.end()); - Clobbers.assign(ClobberRegs.size(), std::string()); - for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) { - raw_string_ostream OS(Clobbers[I]); - IP->printRegName(OS, ClobberRegs[I]); - } - - // Merge the various outputs and inputs. Output are expected first. - if (NumOutputs || NumInputs) { - unsigned NumExprs = NumOutputs + NumInputs; - OpDecls.resize(NumExprs); - Constraints.resize(NumExprs); - for (unsigned i = 0; i < NumOutputs; ++i) { - OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]); - Constraints[i] = OutputConstraints[i]; - } - for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) { - OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]); - Constraints[j] = InputConstraints[i]; - } - } - - // Build the IR assembly string. - std::string AsmStringIR; - raw_string_ostream OS(AsmStringIR); - StringRef ASMString = - SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer(); - const char *AsmStart = ASMString.begin(); - const char *AsmEnd = ASMString.end(); - array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort); - for (const AsmRewrite &AR : AsmStrRewrites) { - AsmRewriteKind Kind = AR.Kind; - - const char *Loc = AR.Loc.getPointer(); - assert(Loc >= AsmStart && "Expected Loc to be at or after Start!"); - - // Emit everything up to the immediate/expression. - if (unsigned Len = Loc - AsmStart) - OS << StringRef(AsmStart, Len); - - // Skip the original expression. - if (Kind == AOK_Skip) { - AsmStart = Loc + AR.Len; - continue; - } - - unsigned AdditionalSkip = 0; - // Rewrite expressions in $N notation. - switch (Kind) { - default: - break; - case AOK_IntelExpr: - assert(AR.IntelExp.isValid() && "cannot write invalid intel expression"); - if (AR.IntelExp.NeedBracs) - OS << "["; - if (AR.IntelExp.hasBaseReg()) - OS << AR.IntelExp.BaseReg; - if (AR.IntelExp.hasIndexReg()) - OS << (AR.IntelExp.hasBaseReg() ? " + " : "") - << AR.IntelExp.IndexReg; - if (AR.IntelExp.Scale > 1) - OS << " * $$" << AR.IntelExp.Scale; - if (AR.IntelExp.Imm || !AR.IntelExp.hasRegs()) - OS << (AR.IntelExp.hasRegs() ? " + $$" : "$$") << AR.IntelExp.Imm; - if (AR.IntelExp.NeedBracs) - OS << "]"; - break; - case AOK_Label: - OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label; - break; - case AOK_Input: - OS << '$' << InputIdx++; - break; - case AOK_Output: - OS << '$' << OutputIdx++; - break; - case AOK_SizeDirective: - switch (AR.Val) { - default: break; - case 8: OS << "byte ptr "; break; - case 16: OS << "word ptr "; break; - case 32: OS << "dword ptr "; break; - case 64: OS << "qword ptr "; break; - case 80: OS << "xword ptr "; break; - case 128: OS << "xmmword ptr "; break; - case 256: OS << "ymmword ptr "; break; - } - break; - case AOK_Emit: - OS << ".byte"; - break; - case AOK_Align: { - // MS alignment directives are measured in bytes. If the native assembler - // measures alignment in bytes, we can pass it straight through. - OS << ".align"; - if (getContext().getAsmInfo()->getAlignmentIsInBytes()) - break; - - // Alignment is in log2 form, so print that instead and skip the original - // immediate. - unsigned Val = AR.Val; - OS << ' ' << Val; - assert(Val < 10 && "Expected alignment less then 2^10."); - AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4; - break; - } - case AOK_EVEN: - OS << ".even"; - break; - case AOK_EndOfStatement: - OS << "\n\t"; - break; - } - - // Skip the original expression. - AsmStart = Loc + AR.Len + AdditionalSkip; - } - - // Emit the remainder of the asm string. - if (AsmStart != AsmEnd) - OS << StringRef(AsmStart, AsmEnd - AsmStart); - - AsmString = OS.str(); - return false; -} - -namespace llvm { -namespace MCParserUtils { - -/// Returns whether the given symbol is used anywhere in the given expression, -/// or subexpressions. -static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *Value) { - switch (Value->getKind()) { - case MCExpr::Binary: { - const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Value); - return isSymbolUsedInExpression(Sym, BE->getLHS()) || - isSymbolUsedInExpression(Sym, BE->getRHS()); - } - case MCExpr::Target: - case MCExpr::Constant: - return false; - case MCExpr::SymbolRef: { - const MCSymbol &S = - static_cast<const MCSymbolRefExpr *>(Value)->getSymbol(); - if (S.isVariable()) - return isSymbolUsedInExpression(Sym, S.getVariableValue()); - return &S == Sym; - } - case MCExpr::Unary: - return isSymbolUsedInExpression( - Sym, static_cast<const MCUnaryExpr *>(Value)->getSubExpr()); - } - - llvm_unreachable("Unknown expr kind!"); -} - -bool parseAssignmentExpression(StringRef Name, bool allow_redef, - MCAsmParser &Parser, MCSymbol *&Sym, - const MCExpr *&Value) { - - // FIXME: Use better location, we should use proper tokens. - SMLoc EqualLoc = Parser.getTok().getLoc(); - if (Parser.parseExpression(Value)) - return Parser.TokError("missing expression"); - - // Note: we don't count b as used in "a = b". This is to allow - // a = b - // b = c - - if (Parser.parseToken(AsmToken::EndOfStatement)) - return true; - - // Validate that the LHS is allowed to be a variable (either it has not been - // used as a symbol, or it is an absolute symbol). - Sym = Parser.getContext().lookupSymbol(Name); - if (Sym) { - // Diagnose assignment to a label. - // - // FIXME: Diagnostics. Note the location of the definition as a label. - // FIXME: Diagnose assignment to protected identifier (e.g., register name). - if (isSymbolUsedInExpression(Sym, Value)) - return Parser.Error(EqualLoc, "Recursive use of '" + Name + "'"); - else if (Sym->isUndefined(/*SetUsed*/ false) && !Sym->isUsed() && - !Sym->isVariable()) - ; // Allow redefinitions of undefined symbols only used in directives. - else if (Sym->isVariable() && !Sym->isUsed() && allow_redef) - ; // Allow redefinitions of variables that haven't yet been used. - else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef)) - return Parser.Error(EqualLoc, "redefinition of '" + Name + "'"); - else if (!Sym->isVariable()) - return Parser.Error(EqualLoc, "invalid assignment to '" + Name + "'"); - else if (!isa<MCConstantExpr>(Sym->getVariableValue())) - return Parser.Error(EqualLoc, - "invalid reassignment of non-absolute variable '" + - Name + "'"); - } else if (Name == ".") { - Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc); - return false; - } else - Sym = Parser.getContext().getOrCreateSymbol(Name); - - Sym->setRedefinable(allow_redef); - - return false; -} - -} // end namespace MCParserUtils -} // end namespace llvm - -/// Create an MCAsmParser instance. -MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C, - MCStreamer &Out, const MCAsmInfo &MAI, - unsigned CB) { - return new AsmParser(SM, C, Out, MAI, CB); -} diff --git a/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp deleted file mode 100644 index 1217ea99e465..000000000000 --- a/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp +++ /dev/null @@ -1,865 +0,0 @@ -//===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/Triple.h" -#include "llvm/ADT/Twine.h" -#include "llvm/BinaryFormat/COFF.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDirectives.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCParser/MCAsmLexer.h" -#include "llvm/MC/MCParser/MCAsmParserExtension.h" -#include "llvm/MC/MCParser/MCTargetAsmParser.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSectionCOFF.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/SectionKind.h" -#include "llvm/Support/SMLoc.h" -#include <cassert> -#include <cstdint> -#include <limits> -#include <utility> - -using namespace llvm; - -namespace { - -class COFFAsmParser : public MCAsmParserExtension { - template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)> - void addDirectiveHandler(StringRef Directive) { - MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( - this, HandleDirective<COFFAsmParser, HandlerMethod>); - getParser().addDirectiveHandler(Directive, Handler); - } - - bool ParseSectionSwitch(StringRef Section, - unsigned Characteristics, - SectionKind Kind); - - bool ParseSectionSwitch(StringRef Section, unsigned Characteristics, - SectionKind Kind, StringRef COMDATSymName, - COFF::COMDATType Type); - - bool ParseSectionName(StringRef &SectionName); - bool ParseSectionFlags(StringRef SectionName, StringRef FlagsString, - unsigned *Flags); - - void Initialize(MCAsmParser &Parser) override { - // Call the base implementation. - MCAsmParserExtension::Initialize(Parser); - - addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text"); - addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data"); - addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss"); - addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section"); - addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def"); - addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl"); - addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type"); - addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef"); - addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32"); - addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymIdx>(".symidx"); - addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh"); - addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx"); - addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce"); - addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva"); - - // Win64 EH directives. - addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>( - ".seh_proc"); - addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>( - ".seh_endproc"); - addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>( - ".seh_startchained"); - addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>( - ".seh_endchained"); - addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>( - ".seh_handler"); - addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>( - ".seh_handlerdata"); - addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>( - ".seh_pushreg"); - addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>( - ".seh_setframe"); - addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>( - ".seh_stackalloc"); - addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>( - ".seh_savereg"); - addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>( - ".seh_savexmm"); - addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>( - ".seh_pushframe"); - addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>( - ".seh_endprologue"); - addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak"); - } - - bool ParseSectionDirectiveText(StringRef, SMLoc) { - return ParseSectionSwitch(".text", - COFF::IMAGE_SCN_CNT_CODE - | COFF::IMAGE_SCN_MEM_EXECUTE - | COFF::IMAGE_SCN_MEM_READ, - SectionKind::getText()); - } - - bool ParseSectionDirectiveData(StringRef, SMLoc) { - return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ | - COFF::IMAGE_SCN_MEM_WRITE, - SectionKind::getData()); - } - - bool ParseSectionDirectiveBSS(StringRef, SMLoc) { - return ParseSectionSwitch(".bss", - COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA - | COFF::IMAGE_SCN_MEM_READ - | COFF::IMAGE_SCN_MEM_WRITE, - SectionKind::getBSS()); - } - - bool ParseDirectiveSection(StringRef, SMLoc); - bool ParseDirectiveDef(StringRef, SMLoc); - bool ParseDirectiveScl(StringRef, SMLoc); - bool ParseDirectiveType(StringRef, SMLoc); - bool ParseDirectiveEndef(StringRef, SMLoc); - bool ParseDirectiveSecRel32(StringRef, SMLoc); - bool ParseDirectiveSecIdx(StringRef, SMLoc); - bool ParseDirectiveSafeSEH(StringRef, SMLoc); - bool ParseDirectiveSymIdx(StringRef, SMLoc); - bool parseCOMDATType(COFF::COMDATType &Type); - bool ParseDirectiveLinkOnce(StringRef, SMLoc); - bool ParseDirectiveRVA(StringRef, SMLoc); - - // Win64 EH directives. - bool ParseSEHDirectiveStartProc(StringRef, SMLoc); - bool ParseSEHDirectiveEndProc(StringRef, SMLoc); - bool ParseSEHDirectiveStartChained(StringRef, SMLoc); - bool ParseSEHDirectiveEndChained(StringRef, SMLoc); - bool ParseSEHDirectiveHandler(StringRef, SMLoc); - bool ParseSEHDirectiveHandlerData(StringRef, SMLoc); - bool ParseSEHDirectivePushReg(StringRef, SMLoc); - bool ParseSEHDirectiveSetFrame(StringRef, SMLoc); - bool ParseSEHDirectiveAllocStack(StringRef, SMLoc); - bool ParseSEHDirectiveSaveReg(StringRef, SMLoc); - bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc); - bool ParseSEHDirectivePushFrame(StringRef, SMLoc); - bool ParseSEHDirectiveEndProlog(StringRef, SMLoc); - - bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except); - bool ParseSEHRegisterNumber(unsigned &RegNo); - bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc); - -public: - COFFAsmParser() = default; -}; - -} // end annonomous namespace. - -static SectionKind computeSectionKind(unsigned Flags) { - if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE) - return SectionKind::getText(); - if (Flags & COFF::IMAGE_SCN_MEM_READ && - (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0) - return SectionKind::getReadOnly(); - return SectionKind::getData(); -} - -bool COFFAsmParser::ParseSectionFlags(StringRef SectionName, - StringRef FlagsString, unsigned *Flags) { - enum { - None = 0, - Alloc = 1 << 0, - Code = 1 << 1, - Load = 1 << 2, - InitData = 1 << 3, - Shared = 1 << 4, - NoLoad = 1 << 5, - NoRead = 1 << 6, - NoWrite = 1 << 7, - Discardable = 1 << 8, - }; - - bool ReadOnlyRemoved = false; - unsigned SecFlags = None; - - for (char FlagChar : FlagsString) { - switch (FlagChar) { - case 'a': - // Ignored. - break; - - case 'b': // bss section - SecFlags |= Alloc; - if (SecFlags & InitData) - return TokError("conflicting section flags 'b' and 'd'."); - SecFlags &= ~Load; - break; - - case 'd': // data section - SecFlags |= InitData; - if (SecFlags & Alloc) - return TokError("conflicting section flags 'b' and 'd'."); - SecFlags &= ~NoWrite; - if ((SecFlags & NoLoad) == 0) - SecFlags |= Load; - break; - - case 'n': // section is not loaded - SecFlags |= NoLoad; - SecFlags &= ~Load; - break; - - case 'D': // discardable - SecFlags |= Discardable; - break; - - case 'r': // read-only - ReadOnlyRemoved = false; - SecFlags |= NoWrite; - if ((SecFlags & Code) == 0) - SecFlags |= InitData; - if ((SecFlags & NoLoad) == 0) - SecFlags |= Load; - break; - - case 's': // shared section - SecFlags |= Shared | InitData; - SecFlags &= ~NoWrite; - if ((SecFlags & NoLoad) == 0) - SecFlags |= Load; - break; - - case 'w': // writable - SecFlags &= ~NoWrite; - ReadOnlyRemoved = true; - break; - - case 'x': // executable section - SecFlags |= Code; - if ((SecFlags & NoLoad) == 0) - SecFlags |= Load; - if (!ReadOnlyRemoved) - SecFlags |= NoWrite; - break; - - case 'y': // not readable - SecFlags |= NoRead | NoWrite; - break; - - default: - return TokError("unknown flag"); - } - } - - *Flags = 0; - - if (SecFlags == None) - SecFlags = InitData; - - if (SecFlags & Code) - *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE; - if (SecFlags & InitData) - *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; - if ((SecFlags & Alloc) && (SecFlags & Load) == 0) - *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; - if (SecFlags & NoLoad) - *Flags |= COFF::IMAGE_SCN_LNK_REMOVE; - if ((SecFlags & Discardable) || - MCSectionCOFF::isImplicitlyDiscardable(SectionName)) - *Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE; - if ((SecFlags & NoRead) == 0) - *Flags |= COFF::IMAGE_SCN_MEM_READ; - if ((SecFlags & NoWrite) == 0) - *Flags |= COFF::IMAGE_SCN_MEM_WRITE; - if (SecFlags & Shared) - *Flags |= COFF::IMAGE_SCN_MEM_SHARED; - - return false; -} - -/// ParseDirectiveSymbolAttribute -/// ::= { ".weak", ... } [ identifier ( , identifier )* ] -bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { - MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive) - .Case(".weak", MCSA_Weak) - .Default(MCSA_Invalid); - assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); - if (getLexer().isNot(AsmToken::EndOfStatement)) { - while (true) { - StringRef Name; - - if (getParser().parseIdentifier(Name)) - return TokError("expected identifier in directive"); - - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - - getStreamer().EmitSymbolAttribute(Sym, Attr); - - if (getLexer().is(AsmToken::EndOfStatement)) - break; - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - } - } - - Lex(); - return false; -} - -bool COFFAsmParser::ParseSectionSwitch(StringRef Section, - unsigned Characteristics, - SectionKind Kind) { - return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0); -} - -bool COFFAsmParser::ParseSectionSwitch(StringRef Section, - unsigned Characteristics, - SectionKind Kind, - StringRef COMDATSymName, - COFF::COMDATType Type) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in section switching directive"); - Lex(); - - getStreamer().SwitchSection(getContext().getCOFFSection( - Section, Characteristics, Kind, COMDATSymName, Type)); - - return false; -} - -bool COFFAsmParser::ParseSectionName(StringRef &SectionName) { - if (!getLexer().is(AsmToken::Identifier)) - return true; - - SectionName = getTok().getIdentifier(); - Lex(); - return false; -} - -// .section name [, "flags"] [, identifier [ identifier ], identifier] -// -// Supported flags: -// a: Ignored. -// b: BSS section (uninitialized data) -// d: data section (initialized data) -// n: "noload" section (removed by linker) -// D: Discardable section -// r: Readable section -// s: Shared section -// w: Writable section -// x: Executable section -// y: Not-readable section (clears 'r') -// -// Subsections are not supported. -bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { - StringRef SectionName; - - if (ParseSectionName(SectionName)) - return TokError("expected identifier in directive"); - - unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ | - COFF::IMAGE_SCN_MEM_WRITE; - - if (getLexer().is(AsmToken::Comma)) { - Lex(); - - if (getLexer().isNot(AsmToken::String)) - return TokError("expected string in directive"); - - StringRef FlagsStr = getTok().getStringContents(); - Lex(); - - if (ParseSectionFlags(SectionName, FlagsStr, &Flags)) - return true; - } - - COFF::COMDATType Type = (COFF::COMDATType)0; - StringRef COMDATSymName; - if (getLexer().is(AsmToken::Comma)) { - Type = COFF::IMAGE_COMDAT_SELECT_ANY; - Lex(); - - Flags |= COFF::IMAGE_SCN_LNK_COMDAT; - - if (!getLexer().is(AsmToken::Identifier)) - return TokError("expected comdat type such as 'discard' or 'largest' " - "after protection bits"); - - if (parseCOMDATType(Type)) - return true; - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("expected comma in directive"); - Lex(); - - if (getParser().parseIdentifier(COMDATSymName)) - return TokError("expected identifier in directive"); - } - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - SectionKind Kind = computeSectionKind(Flags); - if (Kind.isText()) { - const Triple &T = getContext().getObjectFileInfo()->getTargetTriple(); - if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb) - Flags |= COFF::IMAGE_SCN_MEM_16BIT; - } - ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type); - return false; -} - -bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) { - StringRef SymbolName; - - if (getParser().parseIdentifier(SymbolName)) - return TokError("expected identifier in directive"); - - MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName); - - getStreamer().BeginCOFFSymbolDef(Sym); - - Lex(); - return false; -} - -bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) { - int64_t SymbolStorageClass; - if (getParser().parseAbsoluteExpression(SymbolStorageClass)) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - Lex(); - getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass); - return false; -} - -bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) { - int64_t Type; - if (getParser().parseAbsoluteExpression(Type)) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - Lex(); - getStreamer().EmitCOFFSymbolType(Type); - return false; -} - -bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) { - Lex(); - getStreamer().EndCOFFSymbolDef(); - return false; -} - -bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) { - StringRef SymbolID; - if (getParser().parseIdentifier(SymbolID)) - return TokError("expected identifier in directive"); - - int64_t Offset = 0; - SMLoc OffsetLoc; - if (getLexer().is(AsmToken::Plus)) { - OffsetLoc = getLexer().getLoc(); - if (getParser().parseAbsoluteExpression(Offset)) - return true; - } - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - if (Offset < 0 || Offset > std::numeric_limits<uint32_t>::max()) - return Error( - OffsetLoc, - "invalid '.secrel32' directive offset, can't be less " - "than zero or greater than std::numeric_limits<uint32_t>::max()"); - - MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); - - Lex(); - getStreamer().EmitCOFFSecRel32(Symbol, Offset); - return false; -} - -bool COFFAsmParser::ParseDirectiveRVA(StringRef, SMLoc) { - auto parseOp = [&]() -> bool { - StringRef SymbolID; - if (getParser().parseIdentifier(SymbolID)) - return TokError("expected identifier in directive"); - - int64_t Offset = 0; - SMLoc OffsetLoc; - if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) { - OffsetLoc = getLexer().getLoc(); - if (getParser().parseAbsoluteExpression(Offset)) - return true; - } - - if (Offset < std::numeric_limits<int32_t>::min() || - Offset > std::numeric_limits<int32_t>::max()) - return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less " - "than -2147483648 or greater than " - "2147483647"); - - MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); - - getStreamer().EmitCOFFImgRel32(Symbol, Offset); - return false; - }; - - if (getParser().parseMany(parseOp)) - return addErrorSuffix(" in directive"); - return false; -} - -bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) { - StringRef SymbolID; - if (getParser().parseIdentifier(SymbolID)) - return TokError("expected identifier in directive"); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); - - Lex(); - getStreamer().EmitCOFFSafeSEH(Symbol); - return false; -} - -bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) { - StringRef SymbolID; - if (getParser().parseIdentifier(SymbolID)) - return TokError("expected identifier in directive"); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); - - Lex(); - getStreamer().EmitCOFFSectionIndex(Symbol); - return false; -} - -bool COFFAsmParser::ParseDirectiveSymIdx(StringRef, SMLoc) { - StringRef SymbolID; - if (getParser().parseIdentifier(SymbolID)) - return TokError("expected identifier in directive"); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); - - Lex(); - getStreamer().EmitCOFFSymbolIndex(Symbol); - return false; -} - -/// ::= [ identifier ] -bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) { - StringRef TypeId = getTok().getIdentifier(); - - Type = StringSwitch<COFF::COMDATType>(TypeId) - .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) - .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY) - .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE) - .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH) - .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) - .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST) - .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST) - .Default((COFF::COMDATType)0); - - if (Type == 0) - return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'")); - - Lex(); - - return false; -} - -/// ParseDirectiveLinkOnce -/// ::= .linkonce [ identifier ] -bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) { - COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; - if (getLexer().is(AsmToken::Identifier)) - if (parseCOMDATType(Type)) - return true; - - const MCSectionCOFF *Current = - static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly()); - - if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) - return Error(Loc, "cannot make section associative with .linkonce"); - - if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) - return Error(Loc, Twine("section '") + Current->getSectionName() + - "' is already linkonce"); - - Current->setSelection(Type); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - return false; -} - -bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc Loc) { - StringRef SymbolID; - if (getParser().parseIdentifier(SymbolID)) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); - - Lex(); - getStreamer().EmitWinCFIStartProc(Symbol, Loc); - return false; -} - -bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc Loc) { - Lex(); - getStreamer().EmitWinCFIEndProc(Loc); - return false; -} - -bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc Loc) { - Lex(); - getStreamer().EmitWinCFIStartChained(Loc); - return false; -} - -bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc Loc) { - Lex(); - getStreamer().EmitWinCFIEndChained(Loc); - return false; -} - -bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc Loc) { - StringRef SymbolID; - if (getParser().parseIdentifier(SymbolID)) - return true; - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("you must specify one or both of @unwind or @except"); - Lex(); - bool unwind = false, except = false; - if (ParseAtUnwindOrAtExcept(unwind, except)) - return true; - if (getLexer().is(AsmToken::Comma)) { - Lex(); - if (ParseAtUnwindOrAtExcept(unwind, except)) - return true; - } - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID); - - Lex(); - getStreamer().EmitWinEHHandler(handler, unwind, except, Loc); - return false; -} - -bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) { - Lex(); - getStreamer().EmitWinEHHandlerData(); - return false; -} - -bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc Loc) { - unsigned Reg = 0; - if (ParseSEHRegisterNumber(Reg)) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - Lex(); - getStreamer().EmitWinCFIPushReg(Reg, Loc); - return false; -} - -bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc Loc) { - unsigned Reg = 0; - int64_t Off; - if (ParseSEHRegisterNumber(Reg)) - return true; - if (getLexer().isNot(AsmToken::Comma)) - return TokError("you must specify a stack pointer offset"); - - Lex(); - if (getParser().parseAbsoluteExpression(Off)) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - Lex(); - getStreamer().EmitWinCFISetFrame(Reg, Off, Loc); - return false; -} - -bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) { - int64_t Size; - if (getParser().parseAbsoluteExpression(Size)) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - Lex(); - getStreamer().EmitWinCFIAllocStack(Size, Loc); - return false; -} - -bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc Loc) { - unsigned Reg = 0; - int64_t Off; - if (ParseSEHRegisterNumber(Reg)) - return true; - if (getLexer().isNot(AsmToken::Comma)) - return TokError("you must specify an offset on the stack"); - - Lex(); - if (getParser().parseAbsoluteExpression(Off)) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - Lex(); - // FIXME: Err on %xmm* registers - getStreamer().EmitWinCFISaveReg(Reg, Off, Loc); - return false; -} - -// FIXME: This method is inherently x86-specific. It should really be in the -// x86 backend. -bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc Loc) { - unsigned Reg = 0; - int64_t Off; - if (ParseSEHRegisterNumber(Reg)) - return true; - if (getLexer().isNot(AsmToken::Comma)) - return TokError("you must specify an offset on the stack"); - - Lex(); - if (getParser().parseAbsoluteExpression(Off)) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - Lex(); - // FIXME: Err on non-%xmm* registers - getStreamer().EmitWinCFISaveXMM(Reg, Off, Loc); - return false; -} - -bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc Loc) { - bool Code = false; - StringRef CodeID; - if (getLexer().is(AsmToken::At)) { - SMLoc startLoc = getLexer().getLoc(); - Lex(); - if (!getParser().parseIdentifier(CodeID)) { - if (CodeID != "code") - return Error(startLoc, "expected @code"); - Code = true; - } - } - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - Lex(); - getStreamer().EmitWinCFIPushFrame(Code, Loc); - return false; -} - -bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) { - Lex(); - getStreamer().EmitWinCFIEndProlog(Loc); - return false; -} - -bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) { - StringRef identifier; - if (getLexer().isNot(AsmToken::At)) - return TokError("a handler attribute must begin with '@'"); - SMLoc startLoc = getLexer().getLoc(); - Lex(); - if (getParser().parseIdentifier(identifier)) - return Error(startLoc, "expected @unwind or @except"); - if (identifier == "unwind") - unwind = true; - else if (identifier == "except") - except = true; - else - return Error(startLoc, "expected @unwind or @except"); - return false; -} - -bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) { - SMLoc startLoc = getLexer().getLoc(); - if (getLexer().is(AsmToken::Percent)) { - const MCRegisterInfo *MRI = getContext().getRegisterInfo(); - SMLoc endLoc; - unsigned LLVMRegNo; - if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc)) - return true; - -#if 0 - // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering - // violation so this validation code is disabled. - - // Check that this is a non-volatile register. - const unsigned *NVRegs = TAI.getCalleeSavedRegs(); - unsigned i; - for (i = 0; NVRegs[i] != 0; ++i) - if (NVRegs[i] == LLVMRegNo) - break; - if (NVRegs[i] == 0) - return Error(startLoc, "expected non-volatile register"); -#endif - - int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo); - if (SEHRegNo < 0) - return Error(startLoc,"register can't be represented in SEH unwind info"); - RegNo = SEHRegNo; - } - else { - int64_t n; - if (getParser().parseAbsoluteExpression(n)) - return true; - if (n > 15) - return Error(startLoc, "register number is too high"); - RegNo = n; - } - - return false; -} - -namespace llvm { - -MCAsmParserExtension *createCOFFAsmParser() { - return new COFFAsmParser; -} - -} // end namespace llvm diff --git a/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp deleted file mode 100644 index 1160934dc62c..000000000000 --- a/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp +++ /dev/null @@ -1,1208 +0,0 @@ -//===- DarwinAsmParser.cpp - Darwin (Mach-O) Assembly Parser --------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/Triple.h" -#include "llvm/ADT/Twine.h" -#include "llvm/BinaryFormat/MachO.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDirectives.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCParser/MCAsmLexer.h" -#include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/MC/MCParser/MCAsmParserExtension.h" -#include "llvm/MC/MCSectionMachO.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/SectionKind.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/SMLoc.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cstddef> -#include <cstdint> -#include <string> -#include <system_error> -#include <utility> - -using namespace llvm; - -namespace { - -/// Implementation of directive handling which is shared across all -/// Darwin targets. -class DarwinAsmParser : public MCAsmParserExtension { - template<bool (DarwinAsmParser::*HandlerMethod)(StringRef, SMLoc)> - void addDirectiveHandler(StringRef Directive) { - MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( - this, HandleDirective<DarwinAsmParser, HandlerMethod>); - getParser().addDirectiveHandler(Directive, Handler); - } - - bool parseSectionSwitch(StringRef Segment, StringRef Section, - unsigned TAA = 0, unsigned ImplicitAlign = 0, - unsigned StubSize = 0); - - SMLoc LastVersionDirective; - -public: - DarwinAsmParser() = default; - - void Initialize(MCAsmParser &Parser) override { - // Call the base implementation. - this->MCAsmParserExtension::Initialize(Parser); - - addDirectiveHandler<&DarwinAsmParser::parseDirectiveAltEntry>(".alt_entry"); - addDirectiveHandler<&DarwinAsmParser::parseDirectiveDesc>(".desc"); - addDirectiveHandler<&DarwinAsmParser::parseDirectiveIndirectSymbol>( - ".indirect_symbol"); - addDirectiveHandler<&DarwinAsmParser::parseDirectiveLsym>(".lsym"); - addDirectiveHandler<&DarwinAsmParser::parseDirectiveSubsectionsViaSymbols>( - ".subsections_via_symbols"); - addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(".dump"); - addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(".load"); - addDirectiveHandler<&DarwinAsmParser::parseDirectiveSection>(".section"); - addDirectiveHandler<&DarwinAsmParser::parseDirectivePushSection>( - ".pushsection"); - addDirectiveHandler<&DarwinAsmParser::parseDirectivePopSection>( - ".popsection"); - addDirectiveHandler<&DarwinAsmParser::parseDirectivePrevious>(".previous"); - addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogUnique>( - ".secure_log_unique"); - addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogReset>( - ".secure_log_reset"); - addDirectiveHandler<&DarwinAsmParser::parseDirectiveTBSS>(".tbss"); - addDirectiveHandler<&DarwinAsmParser::parseDirectiveZerofill>(".zerofill"); - - addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegion>( - ".data_region"); - addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegionEnd>( - ".end_data_region"); - - // Special section directives. - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveBss>(".bss"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConst>(".const"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstData>( - ".const_data"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstructor>( - ".constructor"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveCString>( - ".cstring"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveData>(".data"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDestructor>( - ".destructor"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDyld>(".dyld"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit0>( - ".fvmlib_init0"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit1>( - ".fvmlib_init1"); - addDirectiveHandler< - &DarwinAsmParser::parseSectionDirectiveLazySymbolPointers>( - ".lazy_symbol_pointer"); - addDirectiveHandler<&DarwinAsmParser::parseDirectiveLinkerOption>( - ".linker_option"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral16>( - ".literal16"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral4>( - ".literal4"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral8>( - ".literal8"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModInitFunc>( - ".mod_init_func"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModTermFunc>( - ".mod_term_func"); - addDirectiveHandler< - &DarwinAsmParser::parseSectionDirectiveNonLazySymbolPointers>( - ".non_lazy_symbol_pointer"); - addDirectiveHandler< - &DarwinAsmParser::parseSectionDirectiveThreadLocalVariablePointers>( - ".thread_local_variable_pointer"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatClsMeth>( - ".objc_cat_cls_meth"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatInstMeth>( - ".objc_cat_inst_meth"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCategory>( - ".objc_category"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClass>( - ".objc_class"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassNames>( - ".objc_class_names"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassVars>( - ".objc_class_vars"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsMeth>( - ".objc_cls_meth"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsRefs>( - ".objc_cls_refs"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCInstMeth>( - ".objc_inst_meth"); - addDirectiveHandler< - &DarwinAsmParser::parseSectionDirectiveObjCInstanceVars>( - ".objc_instance_vars"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMessageRefs>( - ".objc_message_refs"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMetaClass>( - ".objc_meta_class"); - addDirectiveHandler< - &DarwinAsmParser::parseSectionDirectiveObjCMethVarNames>( - ".objc_meth_var_names"); - addDirectiveHandler< - &DarwinAsmParser::parseSectionDirectiveObjCMethVarTypes>( - ".objc_meth_var_types"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCModuleInfo>( - ".objc_module_info"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCProtocol>( - ".objc_protocol"); - addDirectiveHandler< - &DarwinAsmParser::parseSectionDirectiveObjCSelectorStrs>( - ".objc_selector_strs"); - addDirectiveHandler< - &DarwinAsmParser::parseSectionDirectiveObjCStringObject>( - ".objc_string_object"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCSymbols>( - ".objc_symbols"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectivePICSymbolStub>( - ".picsymbol_stub"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticConst>( - ".static_const"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticData>( - ".static_data"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveSymbolStub>( - ".symbol_stub"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTData>(".tdata"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveText>(".text"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveThreadInitFunc>( - ".thread_init_func"); - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTLV>(".tlv"); - - addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveIdent>(".ident"); - addDirectiveHandler<&DarwinAsmParser::parseWatchOSVersionMin>( - ".watchos_version_min"); - addDirectiveHandler<&DarwinAsmParser::parseTvOSVersionMin>( - ".tvos_version_min"); - addDirectiveHandler<&DarwinAsmParser::parseIOSVersionMin>( - ".ios_version_min"); - addDirectiveHandler<&DarwinAsmParser::parseMacOSXVersionMin>( - ".macosx_version_min"); - addDirectiveHandler<&DarwinAsmParser::parseBuildVersion>(".build_version"); - - LastVersionDirective = SMLoc(); - } - - bool parseDirectiveAltEntry(StringRef, SMLoc); - bool parseDirectiveDesc(StringRef, SMLoc); - bool parseDirectiveIndirectSymbol(StringRef, SMLoc); - bool parseDirectiveDumpOrLoad(StringRef, SMLoc); - bool parseDirectiveLsym(StringRef, SMLoc); - bool parseDirectiveLinkerOption(StringRef, SMLoc); - bool parseDirectiveSection(StringRef, SMLoc); - bool parseDirectivePushSection(StringRef, SMLoc); - bool parseDirectivePopSection(StringRef, SMLoc); - bool parseDirectivePrevious(StringRef, SMLoc); - bool parseDirectiveSecureLogReset(StringRef, SMLoc); - bool parseDirectiveSecureLogUnique(StringRef, SMLoc); - bool parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc); - bool parseDirectiveTBSS(StringRef, SMLoc); - bool parseDirectiveZerofill(StringRef, SMLoc); - bool parseDirectiveDataRegion(StringRef, SMLoc); - bool parseDirectiveDataRegionEnd(StringRef, SMLoc); - - // Named Section Directive - bool parseSectionDirectiveBss(StringRef, SMLoc) { - return parseSectionSwitch("__DATA", "__bss"); - } - - bool parseSectionDirectiveConst(StringRef, SMLoc) { - return parseSectionSwitch("__TEXT", "__const"); - } - - bool parseSectionDirectiveStaticConst(StringRef, SMLoc) { - return parseSectionSwitch("__TEXT", "__static_const"); - } - - bool parseSectionDirectiveCString(StringRef, SMLoc) { - return parseSectionSwitch("__TEXT","__cstring", - MachO::S_CSTRING_LITERALS); - } - - bool parseSectionDirectiveLiteral4(StringRef, SMLoc) { - return parseSectionSwitch("__TEXT", "__literal4", - MachO::S_4BYTE_LITERALS, 4); - } - - bool parseSectionDirectiveLiteral8(StringRef, SMLoc) { - return parseSectionSwitch("__TEXT", "__literal8", - MachO::S_8BYTE_LITERALS, 8); - } - - bool parseSectionDirectiveLiteral16(StringRef, SMLoc) { - return parseSectionSwitch("__TEXT","__literal16", - MachO::S_16BYTE_LITERALS, 16); - } - - bool parseSectionDirectiveConstructor(StringRef, SMLoc) { - return parseSectionSwitch("__TEXT","__constructor"); - } - - bool parseSectionDirectiveDestructor(StringRef, SMLoc) { - return parseSectionSwitch("__TEXT","__destructor"); - } - - bool parseSectionDirectiveFVMLibInit0(StringRef, SMLoc) { - return parseSectionSwitch("__TEXT","__fvmlib_init0"); - } - - bool parseSectionDirectiveFVMLibInit1(StringRef, SMLoc) { - return parseSectionSwitch("__TEXT","__fvmlib_init1"); - } - - bool parseSectionDirectiveSymbolStub(StringRef, SMLoc) { - return parseSectionSwitch("__TEXT","__symbol_stub", - MachO::S_SYMBOL_STUBS | - MachO::S_ATTR_PURE_INSTRUCTIONS, - // FIXME: Different on PPC and ARM. - 0, 16); - } - - bool parseSectionDirectivePICSymbolStub(StringRef, SMLoc) { - return parseSectionSwitch("__TEXT","__picsymbol_stub", - MachO::S_SYMBOL_STUBS | - MachO::S_ATTR_PURE_INSTRUCTIONS, 0, 26); - } - - bool parseSectionDirectiveData(StringRef, SMLoc) { - return parseSectionSwitch("__DATA", "__data"); - } - - bool parseSectionDirectiveStaticData(StringRef, SMLoc) { - return parseSectionSwitch("__DATA", "__static_data"); - } - - bool parseSectionDirectiveNonLazySymbolPointers(StringRef, SMLoc) { - return parseSectionSwitch("__DATA", "__nl_symbol_ptr", - MachO::S_NON_LAZY_SYMBOL_POINTERS, 4); - } - - bool parseSectionDirectiveLazySymbolPointers(StringRef, SMLoc) { - return parseSectionSwitch("__DATA", "__la_symbol_ptr", - MachO::S_LAZY_SYMBOL_POINTERS, 4); - } - - bool parseSectionDirectiveThreadLocalVariablePointers(StringRef, SMLoc) { - return parseSectionSwitch("__DATA", "__thread_ptr", - MachO::S_THREAD_LOCAL_VARIABLE_POINTERS, 4); - } - - bool parseSectionDirectiveDyld(StringRef, SMLoc) { - return parseSectionSwitch("__DATA", "__dyld"); - } - - bool parseSectionDirectiveModInitFunc(StringRef, SMLoc) { - return parseSectionSwitch("__DATA", "__mod_init_func", - MachO::S_MOD_INIT_FUNC_POINTERS, 4); - } - - bool parseSectionDirectiveModTermFunc(StringRef, SMLoc) { - return parseSectionSwitch("__DATA", "__mod_term_func", - MachO::S_MOD_TERM_FUNC_POINTERS, 4); - } - - bool parseSectionDirectiveConstData(StringRef, SMLoc) { - return parseSectionSwitch("__DATA", "__const"); - } - - bool parseSectionDirectiveObjCClass(StringRef, SMLoc) { - return parseSectionSwitch("__OBJC", "__class", - MachO::S_ATTR_NO_DEAD_STRIP); - } - - bool parseSectionDirectiveObjCMetaClass(StringRef, SMLoc) { - return parseSectionSwitch("__OBJC", "__meta_class", - MachO::S_ATTR_NO_DEAD_STRIP); - } - - bool parseSectionDirectiveObjCCatClsMeth(StringRef, SMLoc) { - return parseSectionSwitch("__OBJC", "__cat_cls_meth", - MachO::S_ATTR_NO_DEAD_STRIP); - } - - bool parseSectionDirectiveObjCCatInstMeth(StringRef, SMLoc) { - return parseSectionSwitch("__OBJC", "__cat_inst_meth", - MachO::S_ATTR_NO_DEAD_STRIP); - } - - bool parseSectionDirectiveObjCProtocol(StringRef, SMLoc) { - return parseSectionSwitch("__OBJC", "__protocol", - MachO::S_ATTR_NO_DEAD_STRIP); - } - - bool parseSectionDirectiveObjCStringObject(StringRef, SMLoc) { - return parseSectionSwitch("__OBJC", "__string_object", - MachO::S_ATTR_NO_DEAD_STRIP); - } - - bool parseSectionDirectiveObjCClsMeth(StringRef, SMLoc) { - return parseSectionSwitch("__OBJC", "__cls_meth", - MachO::S_ATTR_NO_DEAD_STRIP); - } - - bool parseSectionDirectiveObjCInstMeth(StringRef, SMLoc) { - return parseSectionSwitch("__OBJC", "__inst_meth", - MachO::S_ATTR_NO_DEAD_STRIP); - } - - bool parseSectionDirectiveObjCClsRefs(StringRef, SMLoc) { - return parseSectionSwitch("__OBJC", "__cls_refs", - MachO::S_ATTR_NO_DEAD_STRIP | - MachO::S_LITERAL_POINTERS, 4); - } - - bool parseSectionDirectiveObjCMessageRefs(StringRef, SMLoc) { - return parseSectionSwitch("__OBJC", "__message_refs", - MachO::S_ATTR_NO_DEAD_STRIP | - MachO::S_LITERAL_POINTERS, 4); - } - - bool parseSectionDirectiveObjCSymbols(StringRef, SMLoc) { - return parseSectionSwitch("__OBJC", "__symbols", - MachO::S_ATTR_NO_DEAD_STRIP); - } - - bool parseSectionDirectiveObjCCategory(StringRef, SMLoc) { - return parseSectionSwitch("__OBJC", "__category", - MachO::S_ATTR_NO_DEAD_STRIP); - } - - bool parseSectionDirectiveObjCClassVars(StringRef, SMLoc) { - return parseSectionSwitch("__OBJC", "__class_vars", - MachO::S_ATTR_NO_DEAD_STRIP); - } - - bool parseSectionDirectiveObjCInstanceVars(StringRef, SMLoc) { - return parseSectionSwitch("__OBJC", "__instance_vars", - MachO::S_ATTR_NO_DEAD_STRIP); - } - - bool parseSectionDirectiveObjCModuleInfo(StringRef, SMLoc) { - return parseSectionSwitch("__OBJC", "__module_info", - MachO::S_ATTR_NO_DEAD_STRIP); - } - - bool parseSectionDirectiveObjCClassNames(StringRef, SMLoc) { - return parseSectionSwitch("__TEXT", "__cstring", - MachO::S_CSTRING_LITERALS); - } - - bool parseSectionDirectiveObjCMethVarTypes(StringRef, SMLoc) { - return parseSectionSwitch("__TEXT", "__cstring", - MachO::S_CSTRING_LITERALS); - } - - bool parseSectionDirectiveObjCMethVarNames(StringRef, SMLoc) { - return parseSectionSwitch("__TEXT", "__cstring", - MachO::S_CSTRING_LITERALS); - } - - bool parseSectionDirectiveObjCSelectorStrs(StringRef, SMLoc) { - return parseSectionSwitch("__OBJC", "__selector_strs", - MachO::S_CSTRING_LITERALS); - } - - bool parseSectionDirectiveTData(StringRef, SMLoc) { - return parseSectionSwitch("__DATA", "__thread_data", - MachO::S_THREAD_LOCAL_REGULAR); - } - - bool parseSectionDirectiveText(StringRef, SMLoc) { - return parseSectionSwitch("__TEXT", "__text", - MachO::S_ATTR_PURE_INSTRUCTIONS); - } - - bool parseSectionDirectiveTLV(StringRef, SMLoc) { - return parseSectionSwitch("__DATA", "__thread_vars", - MachO::S_THREAD_LOCAL_VARIABLES); - } - - bool parseSectionDirectiveIdent(StringRef, SMLoc) { - // Darwin silently ignores the .ident directive. - getParser().eatToEndOfStatement(); - return false; - } - - bool parseSectionDirectiveThreadInitFunc(StringRef, SMLoc) { - return parseSectionSwitch("__DATA", "__thread_init", - MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS); - } - - bool parseWatchOSVersionMin(StringRef Directive, SMLoc Loc) { - return parseVersionMin(Directive, Loc, MCVM_WatchOSVersionMin); - } - bool parseTvOSVersionMin(StringRef Directive, SMLoc Loc) { - return parseVersionMin(Directive, Loc, MCVM_TvOSVersionMin); - } - bool parseIOSVersionMin(StringRef Directive, SMLoc Loc) { - return parseVersionMin(Directive, Loc, MCVM_IOSVersionMin); - } - bool parseMacOSXVersionMin(StringRef Directive, SMLoc Loc) { - return parseVersionMin(Directive, Loc, MCVM_OSXVersionMin); - } - - bool parseBuildVersion(StringRef Directive, SMLoc Loc); - bool parseVersionMin(StringRef Directive, SMLoc Loc, MCVersionMinType Type); - bool parseMajorMinorVersionComponent(unsigned *Major, unsigned *Minor, - const char *VersionName); - bool parseOptionalTrailingVersionComponent(unsigned *Component, - const char *ComponentName); - bool parseVersion(unsigned *Major, unsigned *Minor, unsigned *Update); - bool parseSDKVersion(VersionTuple &SDKVersion); - void checkVersion(StringRef Directive, StringRef Arg, SMLoc Loc, - Triple::OSType ExpectedOS); -}; - -} // end anonymous namespace - -bool DarwinAsmParser::parseSectionSwitch(StringRef Segment, StringRef Section, - unsigned TAA, unsigned Align, - unsigned StubSize) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in section switching directive"); - Lex(); - - // FIXME: Arch specific. - bool isText = TAA & MachO::S_ATTR_PURE_INSTRUCTIONS; - getStreamer().SwitchSection(getContext().getMachOSection( - Segment, Section, TAA, StubSize, - isText ? SectionKind::getText() : SectionKind::getData())); - - // Set the implicit alignment, if any. - // - // FIXME: This isn't really what 'as' does; I think it just uses the implicit - // alignment on the section (e.g., if one manually inserts bytes into the - // section, then just issuing the section switch directive will not realign - // the section. However, this is arguably more reasonable behavior, and there - // is no good reason for someone to intentionally emit incorrectly sized - // values into the implicitly aligned sections. - if (Align) - getStreamer().EmitValueToAlignment(Align); - - return false; -} - -/// parseDirectiveAltEntry -/// ::= .alt_entry identifier -bool DarwinAsmParser::parseDirectiveAltEntry(StringRef, SMLoc) { - StringRef Name; - if (getParser().parseIdentifier(Name)) - return TokError("expected identifier in directive"); - - // Look up symbol. - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - - if (Sym->isDefined()) - return TokError(".alt_entry must preceed symbol definition"); - - if (!getStreamer().EmitSymbolAttribute(Sym, MCSA_AltEntry)) - return TokError("unable to emit symbol attribute"); - - Lex(); - return false; -} - -/// parseDirectiveDesc -/// ::= .desc identifier , expression -bool DarwinAsmParser::parseDirectiveDesc(StringRef, SMLoc) { - StringRef Name; - if (getParser().parseIdentifier(Name)) - return TokError("expected identifier in directive"); - - // Handle the identifier as the key symbol. - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '.desc' directive"); - Lex(); - - int64_t DescValue; - if (getParser().parseAbsoluteExpression(DescValue)) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.desc' directive"); - - Lex(); - - // Set the n_desc field of this Symbol to this DescValue - getStreamer().EmitSymbolDesc(Sym, DescValue); - - return false; -} - -/// parseDirectiveIndirectSymbol -/// ::= .indirect_symbol identifier -bool DarwinAsmParser::parseDirectiveIndirectSymbol(StringRef, SMLoc Loc) { - const MCSectionMachO *Current = static_cast<const MCSectionMachO *>( - getStreamer().getCurrentSectionOnly()); - MachO::SectionType SectionType = Current->getType(); - if (SectionType != MachO::S_NON_LAZY_SYMBOL_POINTERS && - SectionType != MachO::S_LAZY_SYMBOL_POINTERS && - SectionType != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS && - SectionType != MachO::S_SYMBOL_STUBS) - return Error(Loc, "indirect symbol not in a symbol pointer or stub " - "section"); - - StringRef Name; - if (getParser().parseIdentifier(Name)) - return TokError("expected identifier in .indirect_symbol directive"); - - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - - // Assembler local symbols don't make any sense here. Complain loudly. - if (Sym->isTemporary()) - return TokError("non-local symbol required in directive"); - - if (!getStreamer().EmitSymbolAttribute(Sym, MCSA_IndirectSymbol)) - return TokError("unable to emit indirect symbol attribute for: " + Name); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.indirect_symbol' directive"); - - Lex(); - - return false; -} - -/// parseDirectiveDumpOrLoad -/// ::= ( .dump | .load ) "filename" -bool DarwinAsmParser::parseDirectiveDumpOrLoad(StringRef Directive, - SMLoc IDLoc) { - bool IsDump = Directive == ".dump"; - if (getLexer().isNot(AsmToken::String)) - return TokError("expected string in '.dump' or '.load' directive"); - - Lex(); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.dump' or '.load' directive"); - - Lex(); - - // FIXME: If/when .dump and .load are implemented they will be done in the - // the assembly parser and not have any need for an MCStreamer API. - if (IsDump) - return Warning(IDLoc, "ignoring directive .dump for now"); - else - return Warning(IDLoc, "ignoring directive .load for now"); -} - -/// ParseDirectiveLinkerOption -/// ::= .linker_option "string" ( , "string" )* -bool DarwinAsmParser::parseDirectiveLinkerOption(StringRef IDVal, SMLoc) { - SmallVector<std::string, 4> Args; - while (true) { - if (getLexer().isNot(AsmToken::String)) - return TokError("expected string in '" + Twine(IDVal) + "' directive"); - - std::string Data; - if (getParser().parseEscapedString(Data)) - return true; - - Args.push_back(Data); - - if (getLexer().is(AsmToken::EndOfStatement)) - break; - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '" + Twine(IDVal) + "' directive"); - Lex(); - } - - getStreamer().EmitLinkerOptions(Args); - return false; -} - -/// parseDirectiveLsym -/// ::= .lsym identifier , expression -bool DarwinAsmParser::parseDirectiveLsym(StringRef, SMLoc) { - StringRef Name; - if (getParser().parseIdentifier(Name)) - return TokError("expected identifier in directive"); - - // Handle the identifier as the key symbol. - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '.lsym' directive"); - Lex(); - - const MCExpr *Value; - if (getParser().parseExpression(Value)) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.lsym' directive"); - - Lex(); - - // We don't currently support this directive. - // - // FIXME: Diagnostic location! - (void) Sym; - return TokError("directive '.lsym' is unsupported"); -} - -/// parseDirectiveSection: -/// ::= .section identifier (',' identifier)* -bool DarwinAsmParser::parseDirectiveSection(StringRef, SMLoc) { - SMLoc Loc = getLexer().getLoc(); - - StringRef SectionName; - if (getParser().parseIdentifier(SectionName)) - return Error(Loc, "expected identifier after '.section' directive"); - - // Verify there is a following comma. - if (!getLexer().is(AsmToken::Comma)) - return TokError("unexpected token in '.section' directive"); - - std::string SectionSpec = SectionName; - SectionSpec += ","; - - // Add all the tokens until the end of the line, ParseSectionSpecifier will - // handle this. - StringRef EOL = getLexer().LexUntilEndOfStatement(); - SectionSpec.append(EOL.begin(), EOL.end()); - - Lex(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.section' directive"); - Lex(); - - StringRef Segment, Section; - unsigned StubSize; - unsigned TAA; - bool TAAParsed; - std::string ErrorStr = - MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section, - TAA, TAAParsed, StubSize); - - if (!ErrorStr.empty()) - return Error(Loc, ErrorStr); - - // Issue a warning if the target is not powerpc and Section is a *coal* section. - Triple TT = getParser().getContext().getObjectFileInfo()->getTargetTriple(); - Triple::ArchType ArchTy = TT.getArch(); - - if (ArchTy != Triple::ppc && ArchTy != Triple::ppc64) { - StringRef NonCoalSection = StringSwitch<StringRef>(Section) - .Case("__textcoal_nt", "__text") - .Case("__const_coal", "__const") - .Case("__datacoal_nt", "__data") - .Default(Section); - - if (!Section.equals(NonCoalSection)) { - StringRef SectionVal(Loc.getPointer()); - size_t B = SectionVal.find(',') + 1, E = SectionVal.find(',', B); - SMLoc BLoc = SMLoc::getFromPointer(SectionVal.data() + B); - SMLoc ELoc = SMLoc::getFromPointer(SectionVal.data() + E); - getParser().Warning(Loc, "section \"" + Section + "\" is deprecated", - SMRange(BLoc, ELoc)); - getParser().Note(Loc, "change section name to \"" + NonCoalSection + - "\"", SMRange(BLoc, ELoc)); - } - } - - // FIXME: Arch specific. - bool isText = Segment == "__TEXT"; // FIXME: Hack. - getStreamer().SwitchSection(getContext().getMachOSection( - Segment, Section, TAA, StubSize, - isText ? SectionKind::getText() : SectionKind::getData())); - return false; -} - -/// ParseDirectivePushSection: -/// ::= .pushsection identifier (',' identifier)* -bool DarwinAsmParser::parseDirectivePushSection(StringRef S, SMLoc Loc) { - getStreamer().PushSection(); - - if (parseDirectiveSection(S, Loc)) { - getStreamer().PopSection(); - return true; - } - - return false; -} - -/// ParseDirectivePopSection: -/// ::= .popsection -bool DarwinAsmParser::parseDirectivePopSection(StringRef, SMLoc) { - if (!getStreamer().PopSection()) - return TokError(".popsection without corresponding .pushsection"); - return false; -} - -/// ParseDirectivePrevious: -/// ::= .previous -bool DarwinAsmParser::parseDirectivePrevious(StringRef DirName, SMLoc) { - MCSectionSubPair PreviousSection = getStreamer().getPreviousSection(); - if (!PreviousSection.first) - return TokError(".previous without corresponding .section"); - getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second); - return false; -} - -/// ParseDirectiveSecureLogUnique -/// ::= .secure_log_unique ... message ... -bool DarwinAsmParser::parseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) { - StringRef LogMessage = getParser().parseStringToEndOfStatement(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.secure_log_unique' directive"); - - if (getContext().getSecureLogUsed()) - return Error(IDLoc, ".secure_log_unique specified multiple times"); - - // Get the secure log path. - const char *SecureLogFile = getContext().getSecureLogFile(); - if (!SecureLogFile) - return Error(IDLoc, ".secure_log_unique used but AS_SECURE_LOG_FILE " - "environment variable unset."); - - // Open the secure log file if we haven't already. - raw_fd_ostream *OS = getContext().getSecureLog(); - if (!OS) { - std::error_code EC; - auto NewOS = llvm::make_unique<raw_fd_ostream>( - StringRef(SecureLogFile), EC, sys::fs::F_Append | sys::fs::F_Text); - if (EC) - return Error(IDLoc, Twine("can't open secure log file: ") + - SecureLogFile + " (" + EC.message() + ")"); - OS = NewOS.get(); - getContext().setSecureLog(std::move(NewOS)); - } - - // Write the message. - unsigned CurBuf = getSourceManager().FindBufferContainingLoc(IDLoc); - *OS << getSourceManager().getBufferInfo(CurBuf).Buffer->getBufferIdentifier() - << ":" << getSourceManager().FindLineNumber(IDLoc, CurBuf) << ":" - << LogMessage + "\n"; - - getContext().setSecureLogUsed(true); - - return false; -} - -/// ParseDirectiveSecureLogReset -/// ::= .secure_log_reset -bool DarwinAsmParser::parseDirectiveSecureLogReset(StringRef, SMLoc IDLoc) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.secure_log_reset' directive"); - - Lex(); - - getContext().setSecureLogUsed(false); - - return false; -} - -/// parseDirectiveSubsectionsViaSymbols -/// ::= .subsections_via_symbols -bool DarwinAsmParser::parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.subsections_via_symbols' directive"); - - Lex(); - - getStreamer().EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); - - return false; -} - -/// ParseDirectiveTBSS -/// ::= .tbss identifier, size, align -bool DarwinAsmParser::parseDirectiveTBSS(StringRef, SMLoc) { - SMLoc IDLoc = getLexer().getLoc(); - StringRef Name; - if (getParser().parseIdentifier(Name)) - return TokError("expected identifier in directive"); - - // Handle the identifier as the key symbol. - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - - int64_t Size; - SMLoc SizeLoc = getLexer().getLoc(); - if (getParser().parseAbsoluteExpression(Size)) - return true; - - int64_t Pow2Alignment = 0; - SMLoc Pow2AlignmentLoc; - if (getLexer().is(AsmToken::Comma)) { - Lex(); - Pow2AlignmentLoc = getLexer().getLoc(); - if (getParser().parseAbsoluteExpression(Pow2Alignment)) - return true; - } - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.tbss' directive"); - - Lex(); - - if (Size < 0) - return Error(SizeLoc, "invalid '.tbss' directive size, can't be less than" - "zero"); - - // FIXME: Diagnose overflow. - if (Pow2Alignment < 0) - return Error(Pow2AlignmentLoc, "invalid '.tbss' alignment, can't be less" - "than zero"); - - if (!Sym->isUndefined()) - return Error(IDLoc, "invalid symbol redefinition"); - - getStreamer().EmitTBSSSymbol(getContext().getMachOSection( - "__DATA", "__thread_bss", - MachO::S_THREAD_LOCAL_ZEROFILL, - 0, SectionKind::getThreadBSS()), - Sym, Size, 1 << Pow2Alignment); - - return false; -} - -/// ParseDirectiveZerofill -/// ::= .zerofill segname , sectname [, identifier , size_expression [ -/// , align_expression ]] -bool DarwinAsmParser::parseDirectiveZerofill(StringRef, SMLoc) { - StringRef Segment; - if (getParser().parseIdentifier(Segment)) - return TokError("expected segment name after '.zerofill' directive"); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - - StringRef Section; - SMLoc SectionLoc = getLexer().getLoc(); - if (getParser().parseIdentifier(Section)) - return TokError("expected section name after comma in '.zerofill' " - "directive"); - - // If this is the end of the line all that was wanted was to create the - // the section but with no symbol. - if (getLexer().is(AsmToken::EndOfStatement)) { - // Create the zerofill section but no symbol - getStreamer().EmitZerofill( - getContext().getMachOSection(Segment, Section, MachO::S_ZEROFILL, 0, - SectionKind::getBSS()), - /*Symbol=*/nullptr, /*Size=*/0, /*ByteAlignment=*/0, SectionLoc); - return false; - } - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - - SMLoc IDLoc = getLexer().getLoc(); - StringRef IDStr; - if (getParser().parseIdentifier(IDStr)) - return TokError("expected identifier in directive"); - - // handle the identifier as the key symbol. - MCSymbol *Sym = getContext().getOrCreateSymbol(IDStr); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - - int64_t Size; - SMLoc SizeLoc = getLexer().getLoc(); - if (getParser().parseAbsoluteExpression(Size)) - return true; - - int64_t Pow2Alignment = 0; - SMLoc Pow2AlignmentLoc; - if (getLexer().is(AsmToken::Comma)) { - Lex(); - Pow2AlignmentLoc = getLexer().getLoc(); - if (getParser().parseAbsoluteExpression(Pow2Alignment)) - return true; - } - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.zerofill' directive"); - - Lex(); - - if (Size < 0) - return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less " - "than zero"); - - // NOTE: The alignment in the directive is a power of 2 value, the assembler - // may internally end up wanting an alignment in bytes. - // FIXME: Diagnose overflow. - if (Pow2Alignment < 0) - return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, " - "can't be less than zero"); - - if (!Sym->isUndefined()) - return Error(IDLoc, "invalid symbol redefinition"); - - // Create the zerofill Symbol with Size and Pow2Alignment - // - // FIXME: Arch specific. - getStreamer().EmitZerofill(getContext().getMachOSection( - Segment, Section, MachO::S_ZEROFILL, - 0, SectionKind::getBSS()), - Sym, Size, 1 << Pow2Alignment, SectionLoc); - - return false; -} - -/// ParseDirectiveDataRegion -/// ::= .data_region [ ( jt8 | jt16 | jt32 ) ] -bool DarwinAsmParser::parseDirectiveDataRegion(StringRef, SMLoc) { - if (getLexer().is(AsmToken::EndOfStatement)) { - Lex(); - getStreamer().EmitDataRegion(MCDR_DataRegion); - return false; - } - StringRef RegionType; - SMLoc Loc = getParser().getTok().getLoc(); - if (getParser().parseIdentifier(RegionType)) - return TokError("expected region type after '.data_region' directive"); - int Kind = StringSwitch<int>(RegionType) - .Case("jt8", MCDR_DataRegionJT8) - .Case("jt16", MCDR_DataRegionJT16) - .Case("jt32", MCDR_DataRegionJT32) - .Default(-1); - if (Kind == -1) - return Error(Loc, "unknown region type in '.data_region' directive"); - Lex(); - - getStreamer().EmitDataRegion((MCDataRegionType)Kind); - return false; -} - -/// ParseDirectiveDataRegionEnd -/// ::= .end_data_region -bool DarwinAsmParser::parseDirectiveDataRegionEnd(StringRef, SMLoc) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.end_data_region' directive"); - - Lex(); - getStreamer().EmitDataRegion(MCDR_DataRegionEnd); - return false; -} - -static bool isSDKVersionToken(const AsmToken &Tok) { - return Tok.is(AsmToken::Identifier) && Tok.getIdentifier() == "sdk_version"; -} - -/// parseMajorMinorVersionComponent ::= major, minor -bool DarwinAsmParser::parseMajorMinorVersionComponent(unsigned *Major, - unsigned *Minor, - const char *VersionName) { - // Get the major version number. - if (getLexer().isNot(AsmToken::Integer)) - return TokError(Twine("invalid ") + VersionName + - " major version number, integer expected"); - int64_t MajorVal = getLexer().getTok().getIntVal(); - if (MajorVal > 65535 || MajorVal <= 0) - return TokError(Twine("invalid ") + VersionName + " major version number"); - *Major = (unsigned)MajorVal; - Lex(); - if (getLexer().isNot(AsmToken::Comma)) - return TokError(Twine(VersionName) + - " minor version number required, comma expected"); - Lex(); - // Get the minor version number. - if (getLexer().isNot(AsmToken::Integer)) - return TokError(Twine("invalid ") + VersionName + - " minor version number, integer expected"); - int64_t MinorVal = getLexer().getTok().getIntVal(); - if (MinorVal > 255 || MinorVal < 0) - return TokError(Twine("invalid ") + VersionName + " minor version number"); - *Minor = MinorVal; - Lex(); - return false; -} - -/// parseOptionalTrailingVersionComponent ::= , version_number -bool DarwinAsmParser::parseOptionalTrailingVersionComponent( - unsigned *Component, const char *ComponentName) { - assert(getLexer().is(AsmToken::Comma) && "comma expected"); - Lex(); - if (getLexer().isNot(AsmToken::Integer)) - return TokError(Twine("invalid ") + ComponentName + - " version number, integer expected"); - int64_t Val = getLexer().getTok().getIntVal(); - if (Val > 255 || Val < 0) - return TokError(Twine("invalid ") + ComponentName + " version number"); - *Component = Val; - Lex(); - return false; -} - -/// parseVersion ::= parseMajorMinorVersionComponent -/// parseOptionalTrailingVersionComponent -bool DarwinAsmParser::parseVersion(unsigned *Major, unsigned *Minor, - unsigned *Update) { - if (parseMajorMinorVersionComponent(Major, Minor, "OS")) - return true; - - // Get the update level, if specified - *Update = 0; - if (getLexer().is(AsmToken::EndOfStatement) || - isSDKVersionToken(getLexer().getTok())) - return false; - if (getLexer().isNot(AsmToken::Comma)) - return TokError("invalid OS update specifier, comma expected"); - if (parseOptionalTrailingVersionComponent(Update, "OS update")) - return true; - return false; -} - -bool DarwinAsmParser::parseSDKVersion(VersionTuple &SDKVersion) { - assert(isSDKVersionToken(getLexer().getTok()) && "expected sdk_version"); - Lex(); - unsigned Major, Minor; - if (parseMajorMinorVersionComponent(&Major, &Minor, "SDK")) - return true; - SDKVersion = VersionTuple(Major, Minor); - - // Get the subminor version, if specified. - if (getLexer().is(AsmToken::Comma)) { - unsigned Subminor; - if (parseOptionalTrailingVersionComponent(&Subminor, "SDK subminor")) - return true; - SDKVersion = VersionTuple(Major, Minor, Subminor); - } - return false; -} - -void DarwinAsmParser::checkVersion(StringRef Directive, StringRef Arg, - SMLoc Loc, Triple::OSType ExpectedOS) { - const Triple &Target = getContext().getObjectFileInfo()->getTargetTriple(); - if (Target.getOS() != ExpectedOS) - Warning(Loc, Twine(Directive) + - (Arg.empty() ? Twine() : Twine(' ') + Arg) + - " used while targeting " + Target.getOSName()); - - if (LastVersionDirective.isValid()) { - Warning(Loc, "overriding previous version directive"); - Note(LastVersionDirective, "previous definition is here"); - } - LastVersionDirective = Loc; -} - -static Triple::OSType getOSTypeFromMCVM(MCVersionMinType Type) { - switch (Type) { - case MCVM_WatchOSVersionMin: return Triple::WatchOS; - case MCVM_TvOSVersionMin: return Triple::TvOS; - case MCVM_IOSVersionMin: return Triple::IOS; - case MCVM_OSXVersionMin: return Triple::MacOSX; - } - llvm_unreachable("Invalid mc version min type"); -} - -/// parseVersionMin -/// ::= .ios_version_min parseVersion parseSDKVersion -/// | .macosx_version_min parseVersion parseSDKVersion -/// | .tvos_version_min parseVersion parseSDKVersion -/// | .watchos_version_min parseVersion parseSDKVersion -bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc, - MCVersionMinType Type) { - unsigned Major; - unsigned Minor; - unsigned Update; - if (parseVersion(&Major, &Minor, &Update)) - return true; - - VersionTuple SDKVersion; - if (isSDKVersionToken(getLexer().getTok()) && parseSDKVersion(SDKVersion)) - return true; - - if (parseToken(AsmToken::EndOfStatement)) - return addErrorSuffix(Twine(" in '") + Directive + "' directive"); - - Triple::OSType ExpectedOS = getOSTypeFromMCVM(Type); - checkVersion(Directive, StringRef(), Loc, ExpectedOS); - getStreamer().EmitVersionMin(Type, Major, Minor, Update, SDKVersion); - return false; -} - -static Triple::OSType getOSTypeFromPlatform(MachO::PlatformType Type) { - switch (Type) { - case MachO::PLATFORM_MACOS: return Triple::MacOSX; - case MachO::PLATFORM_IOS: return Triple::IOS; - case MachO::PLATFORM_TVOS: return Triple::TvOS; - case MachO::PLATFORM_WATCHOS: return Triple::WatchOS; - case MachO::PLATFORM_BRIDGEOS: /* silence warning */ break; - case MachO::PLATFORM_MACCATALYST: return Triple::IOS; - case MachO::PLATFORM_IOSSIMULATOR: /* silence warning */ break; - case MachO::PLATFORM_TVOSSIMULATOR: /* silence warning */ break; - case MachO::PLATFORM_WATCHOSSIMULATOR: /* silence warning */ break; - } - llvm_unreachable("Invalid mach-o platform type"); -} - -/// parseBuildVersion -/// ::= .build_version (macos|ios|tvos|watchos), parseVersion parseSDKVersion -bool DarwinAsmParser::parseBuildVersion(StringRef Directive, SMLoc Loc) { - StringRef PlatformName; - SMLoc PlatformLoc = getTok().getLoc(); - if (getParser().parseIdentifier(PlatformName)) - return TokError("platform name expected"); - - unsigned Platform = StringSwitch<unsigned>(PlatformName) - .Case("macos", MachO::PLATFORM_MACOS) - .Case("ios", MachO::PLATFORM_IOS) - .Case("tvos", MachO::PLATFORM_TVOS) - .Case("watchos", MachO::PLATFORM_WATCHOS) - .Case("macCatalyst", MachO::PLATFORM_MACCATALYST) - .Default(0); - if (Platform == 0) - return Error(PlatformLoc, "unknown platform name"); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("version number required, comma expected"); - Lex(); - - unsigned Major; - unsigned Minor; - unsigned Update; - if (parseVersion(&Major, &Minor, &Update)) - return true; - - VersionTuple SDKVersion; - if (isSDKVersionToken(getLexer().getTok()) && parseSDKVersion(SDKVersion)) - return true; - - if (parseToken(AsmToken::EndOfStatement)) - return addErrorSuffix(" in '.build_version' directive"); - - Triple::OSType ExpectedOS - = getOSTypeFromPlatform((MachO::PlatformType)Platform); - checkVersion(Directive, PlatformName, Loc, ExpectedOS); - getStreamer().EmitBuildVersion(Platform, Major, Minor, Update, SDKVersion); - return false; -} - - -namespace llvm { - -MCAsmParserExtension *createDarwinAsmParser() { - return new DarwinAsmParser; -} - -} // end llvm namespace diff --git a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp deleted file mode 100644 index a55bdd5364cb..000000000000 --- a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp +++ /dev/null @@ -1,899 +0,0 @@ -//===- ELFAsmParser.cpp - ELF Assembly Parser -----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDirectives.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCParser/MCAsmLexer.h" -#include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/MC/MCParser/MCAsmParserExtension.h" -#include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSectionELF.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCSymbolELF.h" -#include "llvm/MC/SectionKind.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/SMLoc.h" -#include <cassert> -#include <cstdint> -#include <utility> - -using namespace llvm; - -namespace { - -class ELFAsmParser : public MCAsmParserExtension { - template<bool (ELFAsmParser::*HandlerMethod)(StringRef, SMLoc)> - void addDirectiveHandler(StringRef Directive) { - MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( - this, HandleDirective<ELFAsmParser, HandlerMethod>); - - getParser().addDirectiveHandler(Directive, Handler); - } - - bool ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags, - SectionKind Kind); - -public: - ELFAsmParser() { BracketExpressionsSupported = true; } - - void Initialize(MCAsmParser &Parser) override { - // Call the base implementation. - this->MCAsmParserExtension::Initialize(Parser); - - addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data"); - addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text"); - addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss"); - addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata"); - addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata"); - addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss"); - addDirectiveHandler< - &ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel"); - addDirectiveHandler< - &ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro"); - addDirectiveHandler< - &ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section"); - addDirectiveHandler< - &ELFAsmParser::ParseDirectivePushSection>(".pushsection"); - addDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size"); - addDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveVersion>(".version"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".weak"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".local"); - addDirectiveHandler< - &ELFAsmParser::ParseDirectiveSymbolAttribute>(".protected"); - addDirectiveHandler< - &ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal"); - addDirectiveHandler< - &ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveSubsection>(".subsection"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveCGProfile>(".cg_profile"); - } - - // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is - // the best way for us to get access to it? - bool ParseSectionDirectiveData(StringRef, SMLoc) { - return ParseSectionSwitch(".data", ELF::SHT_PROGBITS, - ELF::SHF_WRITE | ELF::SHF_ALLOC, - SectionKind::getData()); - } - bool ParseSectionDirectiveText(StringRef, SMLoc) { - return ParseSectionSwitch(".text", ELF::SHT_PROGBITS, - ELF::SHF_EXECINSTR | - ELF::SHF_ALLOC, SectionKind::getText()); - } - bool ParseSectionDirectiveBSS(StringRef, SMLoc) { - return ParseSectionSwitch(".bss", ELF::SHT_NOBITS, - ELF::SHF_WRITE | - ELF::SHF_ALLOC, SectionKind::getBSS()); - } - bool ParseSectionDirectiveRoData(StringRef, SMLoc) { - return ParseSectionSwitch(".rodata", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC, - SectionKind::getReadOnly()); - } - bool ParseSectionDirectiveTData(StringRef, SMLoc) { - return ParseSectionSwitch(".tdata", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | - ELF::SHF_TLS | ELF::SHF_WRITE, - SectionKind::getThreadData()); - } - bool ParseSectionDirectiveTBSS(StringRef, SMLoc) { - return ParseSectionSwitch(".tbss", ELF::SHT_NOBITS, - ELF::SHF_ALLOC | - ELF::SHF_TLS | ELF::SHF_WRITE, - SectionKind::getThreadBSS()); - } - bool ParseSectionDirectiveDataRel(StringRef, SMLoc) { - return ParseSectionSwitch(".data.rel", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHF_WRITE, - SectionKind::getData()); - } - bool ParseSectionDirectiveDataRelRo(StringRef, SMLoc) { - return ParseSectionSwitch(".data.rel.ro", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | - ELF::SHF_WRITE, - SectionKind::getReadOnlyWithRel()); - } - bool ParseSectionDirectiveEhFrame(StringRef, SMLoc) { - return ParseSectionSwitch(".eh_frame", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHF_WRITE, - SectionKind::getData()); - } - bool ParseDirectivePushSection(StringRef, SMLoc); - bool ParseDirectivePopSection(StringRef, SMLoc); - bool ParseDirectiveSection(StringRef, SMLoc); - bool ParseDirectiveSize(StringRef, SMLoc); - bool ParseDirectivePrevious(StringRef, SMLoc); - bool ParseDirectiveType(StringRef, SMLoc); - bool ParseDirectiveIdent(StringRef, SMLoc); - bool ParseDirectiveSymver(StringRef, SMLoc); - bool ParseDirectiveVersion(StringRef, SMLoc); - bool ParseDirectiveWeakref(StringRef, SMLoc); - bool ParseDirectiveSymbolAttribute(StringRef, SMLoc); - bool ParseDirectiveSubsection(StringRef, SMLoc); - bool ParseDirectiveCGProfile(StringRef, SMLoc); - -private: - bool ParseSectionName(StringRef &SectionName); - bool ParseSectionArguments(bool IsPush, SMLoc loc); - unsigned parseSunStyleSectionFlags(); - bool maybeParseSectionType(StringRef &TypeName); - bool parseMergeSize(int64_t &Size); - bool parseGroup(StringRef &GroupName); - bool parseMetadataSym(MCSymbolELF *&Associated); - bool maybeParseUniqueID(int64_t &UniqueID); -}; - -} // end anonymous namespace - -/// ParseDirectiveSymbolAttribute -/// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ] -bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { - MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive) - .Case(".weak", MCSA_Weak) - .Case(".local", MCSA_Local) - .Case(".hidden", MCSA_Hidden) - .Case(".internal", MCSA_Internal) - .Case(".protected", MCSA_Protected) - .Default(MCSA_Invalid); - assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); - if (getLexer().isNot(AsmToken::EndOfStatement)) { - while (true) { - StringRef Name; - - if (getParser().parseIdentifier(Name)) - return TokError("expected identifier in directive"); - - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - - getStreamer().EmitSymbolAttribute(Sym, Attr); - - if (getLexer().is(AsmToken::EndOfStatement)) - break; - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - } - } - - Lex(); - return false; -} - -bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type, - unsigned Flags, SectionKind Kind) { - const MCExpr *Subsection = nullptr; - if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (getParser().parseExpression(Subsection)) - return true; - } - Lex(); - - getStreamer().SwitchSection(getContext().getELFSection(Section, Type, Flags), - Subsection); - - return false; -} - -bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) { - StringRef Name; - if (getParser().parseIdentifier(Name)) - return TokError("expected identifier in directive"); - MCSymbolELF *Sym = cast<MCSymbolELF>(getContext().getOrCreateSymbol(Name)); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - - const MCExpr *Expr; - if (getParser().parseExpression(Expr)) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - Lex(); - - getStreamer().emitELFSize(Sym, Expr); - return false; -} - -bool ELFAsmParser::ParseSectionName(StringRef &SectionName) { - // A section name can contain -, so we cannot just use - // parseIdentifier. - SMLoc FirstLoc = getLexer().getLoc(); - unsigned Size = 0; - - if (getLexer().is(AsmToken::String)) { - SectionName = getTok().getIdentifier(); - Lex(); - return false; - } - - while (!getParser().hasPendingError()) { - SMLoc PrevLoc = getLexer().getLoc(); - if (getLexer().is(AsmToken::Comma) || - getLexer().is(AsmToken::EndOfStatement)) - break; - - unsigned CurSize; - if (getLexer().is(AsmToken::String)) { - CurSize = getTok().getIdentifier().size() + 2; - Lex(); - } else if (getLexer().is(AsmToken::Identifier)) { - CurSize = getTok().getIdentifier().size(); - Lex(); - } else { - CurSize = getTok().getString().size(); - Lex(); - } - Size += CurSize; - SectionName = StringRef(FirstLoc.getPointer(), Size); - - // Make sure the following token is adjacent. - if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer()) - break; - } - if (Size == 0) - return true; - - return false; -} - -static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) { - unsigned flags = 0; - - // If a valid numerical value is set for the section flag, use it verbatim - if (!flagsStr.getAsInteger(0, flags)) - return flags; - - for (char i : flagsStr) { - switch (i) { - case 'a': - flags |= ELF::SHF_ALLOC; - break; - case 'e': - flags |= ELF::SHF_EXCLUDE; - break; - case 'x': - flags |= ELF::SHF_EXECINSTR; - break; - case 'w': - flags |= ELF::SHF_WRITE; - break; - case 'o': - flags |= ELF::SHF_LINK_ORDER; - break; - case 'M': - flags |= ELF::SHF_MERGE; - break; - case 'S': - flags |= ELF::SHF_STRINGS; - break; - case 'T': - flags |= ELF::SHF_TLS; - break; - case 'c': - flags |= ELF::XCORE_SHF_CP_SECTION; - break; - case 'd': - flags |= ELF::XCORE_SHF_DP_SECTION; - break; - case 'y': - flags |= ELF::SHF_ARM_PURECODE; - break; - case 's': - flags |= ELF::SHF_HEX_GPREL; - break; - case 'G': - flags |= ELF::SHF_GROUP; - break; - case '?': - *UseLastGroup = true; - break; - default: - return -1U; - } - } - - return flags; -} - -unsigned ELFAsmParser::parseSunStyleSectionFlags() { - unsigned flags = 0; - while (getLexer().is(AsmToken::Hash)) { - Lex(); // Eat the #. - - if (!getLexer().is(AsmToken::Identifier)) - return -1U; - - StringRef flagId = getTok().getIdentifier(); - if (flagId == "alloc") - flags |= ELF::SHF_ALLOC; - else if (flagId == "execinstr") - flags |= ELF::SHF_EXECINSTR; - else if (flagId == "write") - flags |= ELF::SHF_WRITE; - else if (flagId == "tls") - flags |= ELF::SHF_TLS; - else - return -1U; - - Lex(); // Eat the flag. - - if (!getLexer().is(AsmToken::Comma)) - break; - Lex(); // Eat the comma. - } - return flags; -} - - -bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) { - getStreamer().PushSection(); - - if (ParseSectionArguments(/*IsPush=*/true, loc)) { - getStreamer().PopSection(); - return true; - } - - return false; -} - -bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) { - if (!getStreamer().PopSection()) - return TokError(".popsection without corresponding .pushsection"); - return false; -} - -bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) { - return ParseSectionArguments(/*IsPush=*/false, loc); -} - -bool ELFAsmParser::maybeParseSectionType(StringRef &TypeName) { - MCAsmLexer &L = getLexer(); - if (L.isNot(AsmToken::Comma)) - return false; - Lex(); - if (L.isNot(AsmToken::At) && L.isNot(AsmToken::Percent) && - L.isNot(AsmToken::String)) { - if (L.getAllowAtInIdentifier()) - return TokError("expected '@<type>', '%<type>' or \"<type>\""); - else - return TokError("expected '%<type>' or \"<type>\""); - } - if (!L.is(AsmToken::String)) - Lex(); - if (L.is(AsmToken::Integer)) { - TypeName = getTok().getString(); - Lex(); - } else if (getParser().parseIdentifier(TypeName)) - return TokError("expected identifier in directive"); - return false; -} - -bool ELFAsmParser::parseMergeSize(int64_t &Size) { - if (getLexer().isNot(AsmToken::Comma)) - return TokError("expected the entry size"); - Lex(); - if (getParser().parseAbsoluteExpression(Size)) - return true; - if (Size <= 0) - return TokError("entry size must be positive"); - return false; -} - -bool ELFAsmParser::parseGroup(StringRef &GroupName) { - MCAsmLexer &L = getLexer(); - if (L.isNot(AsmToken::Comma)) - return TokError("expected group name"); - Lex(); - if (L.is(AsmToken::Integer)) { - GroupName = getTok().getString(); - Lex(); - } else if (getParser().parseIdentifier(GroupName)) { - return TokError("invalid group name"); - } - if (L.is(AsmToken::Comma)) { - Lex(); - StringRef Linkage; - if (getParser().parseIdentifier(Linkage)) - return TokError("invalid linkage"); - if (Linkage != "comdat") - return TokError("Linkage must be 'comdat'"); - } - return false; -} - -bool ELFAsmParser::parseMetadataSym(MCSymbolELF *&Associated) { - MCAsmLexer &L = getLexer(); - if (L.isNot(AsmToken::Comma)) - return TokError("expected metadata symbol"); - Lex(); - StringRef Name; - if (getParser().parseIdentifier(Name)) - return TokError("invalid metadata symbol"); - Associated = dyn_cast_or_null<MCSymbolELF>(getContext().lookupSymbol(Name)); - if (!Associated || !Associated->isInSection()) - return TokError("symbol is not in a section: " + Name); - return false; -} - -bool ELFAsmParser::maybeParseUniqueID(int64_t &UniqueID) { - MCAsmLexer &L = getLexer(); - if (L.isNot(AsmToken::Comma)) - return false; - Lex(); - StringRef UniqueStr; - if (getParser().parseIdentifier(UniqueStr)) - return TokError("expected identifier in directive"); - if (UniqueStr != "unique") - return TokError("expected 'unique'"); - if (L.isNot(AsmToken::Comma)) - return TokError("expected commma"); - Lex(); - if (getParser().parseAbsoluteExpression(UniqueID)) - return true; - if (UniqueID < 0) - return TokError("unique id must be positive"); - if (!isUInt<32>(UniqueID) || UniqueID == ~0U) - return TokError("unique id is too large"); - return false; -} - -static bool hasPrefix(StringRef SectionName, StringRef Prefix) { - return SectionName.startswith(Prefix) || SectionName == Prefix.drop_back(); -} - -bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) { - StringRef SectionName; - - if (ParseSectionName(SectionName)) - return TokError("expected identifier in directive"); - - StringRef TypeName; - int64_t Size = 0; - StringRef GroupName; - unsigned Flags = 0; - const MCExpr *Subsection = nullptr; - bool UseLastGroup = false; - MCSymbolELF *Associated = nullptr; - int64_t UniqueID = ~0; - - // Set the defaults first. - if (hasPrefix(SectionName, ".rodata.") || SectionName == ".rodata1") - Flags |= ELF::SHF_ALLOC; - else if (SectionName == ".fini" || SectionName == ".init" || - hasPrefix(SectionName, ".text.")) - Flags |= ELF::SHF_ALLOC | ELF::SHF_EXECINSTR; - else if (hasPrefix(SectionName, ".data.") || SectionName == ".data1" || - hasPrefix(SectionName, ".bss.") || - hasPrefix(SectionName, ".init_array.") || - hasPrefix(SectionName, ".fini_array.") || - hasPrefix(SectionName, ".preinit_array.")) - Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE; - else if (hasPrefix(SectionName, ".tdata.") || - hasPrefix(SectionName, ".tbss.")) - Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_TLS; - - if (getLexer().is(AsmToken::Comma)) { - Lex(); - - if (IsPush && getLexer().isNot(AsmToken::String)) { - if (getParser().parseExpression(Subsection)) - return true; - if (getLexer().isNot(AsmToken::Comma)) - goto EndStmt; - Lex(); - } - - unsigned extraFlags; - - if (getLexer().isNot(AsmToken::String)) { - if (!getContext().getAsmInfo()->usesSunStyleELFSectionSwitchSyntax() - || getLexer().isNot(AsmToken::Hash)) - return TokError("expected string in directive"); - extraFlags = parseSunStyleSectionFlags(); - } else { - StringRef FlagsStr = getTok().getStringContents(); - Lex(); - extraFlags = parseSectionFlags(FlagsStr, &UseLastGroup); - } - - if (extraFlags == -1U) - return TokError("unknown flag"); - Flags |= extraFlags; - - bool Mergeable = Flags & ELF::SHF_MERGE; - bool Group = Flags & ELF::SHF_GROUP; - if (Group && UseLastGroup) - return TokError("Section cannot specifiy a group name while also acting " - "as a member of the last group"); - - if (maybeParseSectionType(TypeName)) - return true; - - MCAsmLexer &L = getLexer(); - if (TypeName.empty()) { - if (Mergeable) - return TokError("Mergeable section must specify the type"); - if (Group) - return TokError("Group section must specify the type"); - if (L.isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - } - - if (Mergeable) - if (parseMergeSize(Size)) - return true; - if (Group) - if (parseGroup(GroupName)) - return true; - if (Flags & ELF::SHF_LINK_ORDER) - if (parseMetadataSym(Associated)) - return true; - if (maybeParseUniqueID(UniqueID)) - return true; - } - -EndStmt: - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - Lex(); - - unsigned Type = ELF::SHT_PROGBITS; - - if (TypeName.empty()) { - if (SectionName.startswith(".note")) - Type = ELF::SHT_NOTE; - else if (hasPrefix(SectionName, ".init_array.")) - Type = ELF::SHT_INIT_ARRAY; - else if (hasPrefix(SectionName, ".bss.")) - Type = ELF::SHT_NOBITS; - else if (hasPrefix(SectionName, ".tbss.")) - Type = ELF::SHT_NOBITS; - else if (hasPrefix(SectionName, ".fini_array.")) - Type = ELF::SHT_FINI_ARRAY; - else if (hasPrefix(SectionName, ".preinit_array.")) - Type = ELF::SHT_PREINIT_ARRAY; - } else { - if (TypeName == "init_array") - Type = ELF::SHT_INIT_ARRAY; - else if (TypeName == "fini_array") - Type = ELF::SHT_FINI_ARRAY; - else if (TypeName == "preinit_array") - Type = ELF::SHT_PREINIT_ARRAY; - else if (TypeName == "nobits") - Type = ELF::SHT_NOBITS; - else if (TypeName == "progbits") - Type = ELF::SHT_PROGBITS; - else if (TypeName == "note") - Type = ELF::SHT_NOTE; - else if (TypeName == "unwind") - Type = ELF::SHT_X86_64_UNWIND; - else if (TypeName == "llvm_odrtab") - Type = ELF::SHT_LLVM_ODRTAB; - else if (TypeName == "llvm_linker_options") - Type = ELF::SHT_LLVM_LINKER_OPTIONS; - else if (TypeName == "llvm_call_graph_profile") - Type = ELF::SHT_LLVM_CALL_GRAPH_PROFILE; - else if (TypeName == "llvm_dependent_libraries") - Type = ELF::SHT_LLVM_DEPENDENT_LIBRARIES; - else if (TypeName == "llvm_sympart") - Type = ELF::SHT_LLVM_SYMPART; - else if (TypeName.getAsInteger(0, Type)) - return TokError("unknown section type"); - } - - if (UseLastGroup) { - MCSectionSubPair CurrentSection = getStreamer().getCurrentSection(); - if (const MCSectionELF *Section = - cast_or_null<MCSectionELF>(CurrentSection.first)) - if (const MCSymbol *Group = Section->getGroup()) { - GroupName = Group->getName(); - Flags |= ELF::SHF_GROUP; - } - } - - MCSection *ELFSection = - getContext().getELFSection(SectionName, Type, Flags, Size, GroupName, - UniqueID, Associated); - getStreamer().SwitchSection(ELFSection, Subsection); - - if (getContext().getGenDwarfForAssembly()) { - bool InsertResult = getContext().addGenDwarfSection(ELFSection); - if (InsertResult) { - if (getContext().getDwarfVersion() <= 2) - Warning(loc, "DWARF2 only supports one section per compilation unit"); - - if (!ELFSection->getBeginSymbol()) { - MCSymbol *SectionStartSymbol = getContext().createTempSymbol(); - getStreamer().EmitLabel(SectionStartSymbol); - ELFSection->setBeginSymbol(SectionStartSymbol); - } - } - } - - return false; -} - -bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { - MCSectionSubPair PreviousSection = getStreamer().getPreviousSection(); - if (PreviousSection.first == nullptr) - return TokError(".previous without corresponding .section"); - getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second); - - return false; -} - -static MCSymbolAttr MCAttrForString(StringRef Type) { - return StringSwitch<MCSymbolAttr>(Type) - .Cases("STT_FUNC", "function", MCSA_ELF_TypeFunction) - .Cases("STT_OBJECT", "object", MCSA_ELF_TypeObject) - .Cases("STT_TLS", "tls_object", MCSA_ELF_TypeTLS) - .Cases("STT_COMMON", "common", MCSA_ELF_TypeCommon) - .Cases("STT_NOTYPE", "notype", MCSA_ELF_TypeNoType) - .Cases("STT_GNU_IFUNC", "gnu_indirect_function", - MCSA_ELF_TypeIndFunction) - .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject) - .Default(MCSA_Invalid); -} - -/// ParseDirectiveELFType -/// ::= .type identifier , STT_<TYPE_IN_UPPER_CASE> -/// ::= .type identifier , #attribute -/// ::= .type identifier , @attribute -/// ::= .type identifier , %attribute -/// ::= .type identifier , "attribute" -bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) { - StringRef Name; - if (getParser().parseIdentifier(Name)) - return TokError("expected identifier in directive"); - - // Handle the identifier as the key symbol. - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - - // NOTE the comma is optional in all cases. It is only documented as being - // optional in the first case, however, GAS will silently treat the comma as - // optional in all cases. Furthermore, although the documentation states that - // the first form only accepts STT_<TYPE_IN_UPPER_CASE>, in reality, GAS - // accepts both the upper case name as well as the lower case aliases. - if (getLexer().is(AsmToken::Comma)) - Lex(); - - if (getLexer().isNot(AsmToken::Identifier) && - getLexer().isNot(AsmToken::Hash) && - getLexer().isNot(AsmToken::Percent) && - getLexer().isNot(AsmToken::String)) { - if (!getLexer().getAllowAtInIdentifier()) - return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', " - "'%<type>' or \"<type>\""); - else if (getLexer().isNot(AsmToken::At)) - return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', " - "'%<type>' or \"<type>\""); - } - - if (getLexer().isNot(AsmToken::String) && - getLexer().isNot(AsmToken::Identifier)) - Lex(); - - SMLoc TypeLoc = getLexer().getLoc(); - - StringRef Type; - if (getParser().parseIdentifier(Type)) - return TokError("expected symbol type in directive"); - - MCSymbolAttr Attr = MCAttrForString(Type); - if (Attr == MCSA_Invalid) - return Error(TypeLoc, "unsupported attribute in '.type' directive"); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.type' directive"); - Lex(); - - getStreamer().EmitSymbolAttribute(Sym, Attr); - - return false; -} - -/// ParseDirectiveIdent -/// ::= .ident string -bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) { - if (getLexer().isNot(AsmToken::String)) - return TokError("unexpected token in '.ident' directive"); - - StringRef Data = getTok().getIdentifier(); - - Lex(); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.ident' directive"); - Lex(); - - getStreamer().EmitIdent(Data); - return false; -} - -/// ParseDirectiveSymver -/// ::= .symver foo, bar2@zed -bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) { - StringRef Name; - if (getParser().parseIdentifier(Name)) - return TokError("expected identifier in directive"); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("expected a comma"); - - // ARM assembly uses @ for a comment... - // except when parsing the second parameter of the .symver directive. - // Force the next symbol to allow @ in the identifier, which is - // required for this directive and then reset it to its initial state. - const bool AllowAtInIdentifier = getLexer().getAllowAtInIdentifier(); - getLexer().setAllowAtInIdentifier(true); - Lex(); - getLexer().setAllowAtInIdentifier(AllowAtInIdentifier); - - StringRef AliasName; - if (getParser().parseIdentifier(AliasName)) - return TokError("expected identifier in directive"); - - if (AliasName.find('@') == StringRef::npos) - return TokError("expected a '@' in the name"); - - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - getStreamer().emitELFSymverDirective(AliasName, Sym); - return false; -} - -/// ParseDirectiveVersion -/// ::= .version string -bool ELFAsmParser::ParseDirectiveVersion(StringRef, SMLoc) { - if (getLexer().isNot(AsmToken::String)) - return TokError("unexpected token in '.version' directive"); - - StringRef Data = getTok().getIdentifier(); - - Lex(); - - MCSection *Note = getContext().getELFSection(".note", ELF::SHT_NOTE, 0); - - getStreamer().PushSection(); - getStreamer().SwitchSection(Note); - getStreamer().EmitIntValue(Data.size()+1, 4); // namesz. - getStreamer().EmitIntValue(0, 4); // descsz = 0 (no description). - getStreamer().EmitIntValue(1, 4); // type = NT_VERSION. - getStreamer().EmitBytes(Data); // name. - getStreamer().EmitIntValue(0, 1); // terminate the string. - getStreamer().EmitValueToAlignment(4); // ensure 4 byte alignment. - getStreamer().PopSection(); - return false; -} - -/// ParseDirectiveWeakref -/// ::= .weakref foo, bar -bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) { - // FIXME: Share code with the other alias building directives. - - StringRef AliasName; - if (getParser().parseIdentifier(AliasName)) - return TokError("expected identifier in directive"); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("expected a comma"); - - Lex(); - - StringRef Name; - if (getParser().parseIdentifier(Name)) - return TokError("expected identifier in directive"); - - MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName); - - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - - getStreamer().EmitWeakReference(Alias, Sym); - return false; -} - -bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) { - const MCExpr *Subsection = nullptr; - if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (getParser().parseExpression(Subsection)) - return true; - } - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - Lex(); - - getStreamer().SubSection(Subsection); - return false; -} - -/// ParseDirectiveCGProfile -/// ::= .cg_profile identifier, identifier, <number> -bool ELFAsmParser::ParseDirectiveCGProfile(StringRef, SMLoc) { - StringRef From; - SMLoc FromLoc = getLexer().getLoc(); - if (getParser().parseIdentifier(From)) - return TokError("expected identifier in directive"); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("expected a comma"); - Lex(); - - StringRef To; - SMLoc ToLoc = getLexer().getLoc(); - if (getParser().parseIdentifier(To)) - return TokError("expected identifier in directive"); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("expected a comma"); - Lex(); - - int64_t Count; - if (getParser().parseIntToken( - Count, "expected integer count in '.cg_profile' directive")) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - MCSymbol *FromSym = getContext().getOrCreateSymbol(From); - MCSymbol *ToSym = getContext().getOrCreateSymbol(To); - - getStreamer().emitCGProfileEntry( - MCSymbolRefExpr::create(FromSym, MCSymbolRefExpr::VK_None, getContext(), - FromLoc), - MCSymbolRefExpr::create(ToSym, MCSymbolRefExpr::VK_None, getContext(), - ToLoc), - Count); - return false; -} - -namespace llvm { - -MCAsmParserExtension *createELFAsmParser() { - return new ELFAsmParser; -} - -} // end namespace llvm diff --git a/contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp b/contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp deleted file mode 100644 index 497055bc1760..000000000000 --- a/contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp +++ /dev/null @@ -1,129 +0,0 @@ -//===- MCAsmLexer.cpp - Abstract Asm Lexer Interface ----------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCParser/MCAsmLexer.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/SMLoc.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -MCAsmLexer::MCAsmLexer() { - CurTok.emplace_back(AsmToken::Space, StringRef()); -} - -MCAsmLexer::~MCAsmLexer() = default; - -SMLoc MCAsmLexer::getLoc() const { - return SMLoc::getFromPointer(TokStart); -} - -SMLoc AsmToken::getLoc() const { - return SMLoc::getFromPointer(Str.data()); -} - -SMLoc AsmToken::getEndLoc() const { - return SMLoc::getFromPointer(Str.data() + Str.size()); -} - -SMRange AsmToken::getLocRange() const { - return SMRange(getLoc(), getEndLoc()); -} - -void AsmToken::dump(raw_ostream &OS) const { - switch (Kind) { - case AsmToken::Error: - OS << "error"; - break; - case AsmToken::Identifier: - OS << "identifier: " << getString(); - break; - case AsmToken::Integer: - OS << "int: " << getString(); - break; - case AsmToken::Real: - OS << "real: " << getString(); - break; - case AsmToken::String: - OS << "string: " << getString(); - break; - - case AsmToken::Amp: OS << "Amp"; break; - case AsmToken::AmpAmp: OS << "AmpAmp"; break; - case AsmToken::At: OS << "At"; break; - case AsmToken::BackSlash: OS << "BackSlash"; break; - case AsmToken::BigNum: OS << "BigNum"; break; - case AsmToken::Caret: OS << "Caret"; break; - case AsmToken::Colon: OS << "Colon"; break; - case AsmToken::Comma: OS << "Comma"; break; - case AsmToken::Comment: OS << "Comment"; break; - case AsmToken::Dollar: OS << "Dollar"; break; - case AsmToken::Dot: OS << "Dot"; break; - case AsmToken::EndOfStatement: OS << "EndOfStatement"; break; - case AsmToken::Eof: OS << "Eof"; break; - case AsmToken::Equal: OS << "Equal"; break; - case AsmToken::EqualEqual: OS << "EqualEqual"; break; - case AsmToken::Exclaim: OS << "Exclaim"; break; - case AsmToken::ExclaimEqual: OS << "ExclaimEqual"; break; - case AsmToken::Greater: OS << "Greater"; break; - case AsmToken::GreaterEqual: OS << "GreaterEqual"; break; - case AsmToken::GreaterGreater: OS << "GreaterGreater"; break; - case AsmToken::Hash: OS << "Hash"; break; - case AsmToken::HashDirective: OS << "HashDirective"; break; - case AsmToken::LBrac: OS << "LBrac"; break; - case AsmToken::LCurly: OS << "LCurly"; break; - case AsmToken::LParen: OS << "LParen"; break; - case AsmToken::Less: OS << "Less"; break; - case AsmToken::LessEqual: OS << "LessEqual"; break; - case AsmToken::LessGreater: OS << "LessGreater"; break; - case AsmToken::LessLess: OS << "LessLess"; break; - case AsmToken::Minus: OS << "Minus"; break; - case AsmToken::MinusGreater: OS << "MinusGreater"; break; - case AsmToken::Percent: OS << "Percent"; break; - case AsmToken::Pipe: OS << "Pipe"; break; - case AsmToken::PipePipe: OS << "PipePipe"; break; - case AsmToken::Plus: OS << "Plus"; break; - case AsmToken::RBrac: OS << "RBrac"; break; - case AsmToken::RCurly: OS << "RCurly"; break; - case AsmToken::RParen: OS << "RParen"; break; - case AsmToken::Slash: OS << "Slash"; break; - case AsmToken::Space: OS << "Space"; break; - case AsmToken::Star: OS << "Star"; break; - case AsmToken::Tilde: OS << "Tilde"; break; - case AsmToken::PercentCall16: OS << "PercentCall16"; break; - case AsmToken::PercentCall_Hi: OS << "PercentCall_Hi"; break; - case AsmToken::PercentCall_Lo: OS << "PercentCall_Lo"; break; - case AsmToken::PercentDtprel_Hi: OS << "PercentDtprel_Hi"; break; - case AsmToken::PercentDtprel_Lo: OS << "PercentDtprel_Lo"; break; - case AsmToken::PercentGot: OS << "PercentGot"; break; - case AsmToken::PercentGot_Disp: OS << "PercentGot_Disp"; break; - case AsmToken::PercentGot_Hi: OS << "PercentGot_Hi"; break; - case AsmToken::PercentGot_Lo: OS << "PercentGot_Lo"; break; - case AsmToken::PercentGot_Ofst: OS << "PercentGot_Ofst"; break; - case AsmToken::PercentGot_Page: OS << "PercentGot_Page"; break; - case AsmToken::PercentGottprel: OS << "PercentGottprel"; break; - case AsmToken::PercentGp_Rel: OS << "PercentGp_Rel"; break; - case AsmToken::PercentHi: OS << "PercentHi"; break; - case AsmToken::PercentHigher: OS << "PercentHigher"; break; - case AsmToken::PercentHighest: OS << "PercentHighest"; break; - case AsmToken::PercentLo: OS << "PercentLo"; break; - case AsmToken::PercentNeg: OS << "PercentNeg"; break; - case AsmToken::PercentPcrel_Hi: OS << "PercentPcrel_Hi"; break; - case AsmToken::PercentPcrel_Lo: OS << "PercentPcrel_Lo"; break; - case AsmToken::PercentTlsgd: OS << "PercentTlsgd"; break; - case AsmToken::PercentTlsldm: OS << "PercentTlsldm"; break; - case AsmToken::PercentTprel_Hi: OS << "PercentTprel_Hi"; break; - case AsmToken::PercentTprel_Lo: OS << "PercentTprel_Lo"; break; - } - - // Print the token string. - OS << " (\""; - OS.write_escaped(getString()); - OS << "\")"; -} diff --git a/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp deleted file mode 100644 index 41a1ee555d6f..000000000000 --- a/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp +++ /dev/null @@ -1,136 +0,0 @@ -//===-- MCAsmParser.cpp - Abstract Asm Parser Interface -------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Config/llvm-config.h" -#include "llvm/MC/MCParser/MCAsmLexer.h" -#include "llvm/MC/MCParser/MCParsedAsmOperand.h" -#include "llvm/MC/MCParser/MCTargetAsmParser.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/SMLoc.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> - -using namespace llvm; - -MCAsmParser::MCAsmParser() {} - -MCAsmParser::~MCAsmParser() = default; - -void MCAsmParser::setTargetParser(MCTargetAsmParser &P) { - assert(!TargetParser && "Target parser is already initialized!"); - TargetParser = &P; - TargetParser->Initialize(*this); -} - -const AsmToken &MCAsmParser::getTok() const { - return getLexer().getTok(); -} - -bool MCAsmParser::parseTokenLoc(SMLoc &Loc) { - Loc = getTok().getLoc(); - return false; -} - -bool MCAsmParser::parseEOL(const Twine &Msg) { - if (getTok().getKind() != AsmToken::EndOfStatement) - return Error(getTok().getLoc(), Msg); - Lex(); - return false; -} - -bool MCAsmParser::parseToken(AsmToken::TokenKind T, const Twine &Msg) { - if (T == AsmToken::EndOfStatement) - return parseEOL(Msg); - if (getTok().getKind() != T) - return Error(getTok().getLoc(), Msg); - Lex(); - return false; -} - -bool MCAsmParser::parseIntToken(int64_t &V, const Twine &Msg) { - if (getTok().getKind() != AsmToken::Integer) - return TokError(Msg); - V = getTok().getIntVal(); - Lex(); - return false; -} - -bool MCAsmParser::parseOptionalToken(AsmToken::TokenKind T) { - bool Present = (getTok().getKind() == T); - if (Present) - parseToken(T); - return Present; -} - -bool MCAsmParser::check(bool P, const Twine &Msg) { - return check(P, getTok().getLoc(), Msg); -} - -bool MCAsmParser::check(bool P, SMLoc Loc, const Twine &Msg) { - if (P) - return Error(Loc, Msg); - return false; -} - -bool MCAsmParser::TokError(const Twine &Msg, SMRange Range) { - return Error(getLexer().getLoc(), Msg, Range); -} - -bool MCAsmParser::Error(SMLoc L, const Twine &Msg, SMRange Range) { - - MCPendingError PErr; - PErr.Loc = L; - Msg.toVector(PErr.Msg); - PErr.Range = Range; - PendingErrors.push_back(PErr); - - // If we threw this parsing error after a lexing error, this should - // supercede the lexing error and so we remove it from the Lexer - // before it can propagate - if (getTok().is(AsmToken::Error)) - getLexer().Lex(); - return true; -} - -bool MCAsmParser::addErrorSuffix(const Twine &Suffix) { - // Make sure lexing errors have propagated to the parser. - if (getTok().is(AsmToken::Error)) - Lex(); - for (auto &PErr : PendingErrors) - Suffix.toVector(PErr.Msg); - return true; -} - -bool MCAsmParser::parseMany(function_ref<bool()> parseOne, bool hasComma) { - if (parseOptionalToken(AsmToken::EndOfStatement)) - return false; - while (true) { - if (parseOne()) - return true; - if (parseOptionalToken(AsmToken::EndOfStatement)) - return false; - if (hasComma && parseToken(AsmToken::Comma)) - return true; - } - return false; -} - -bool MCAsmParser::parseExpression(const MCExpr *&Res) { - SMLoc L; - return parseExpression(Res, L); -} - -void MCParsedAsmOperand::dump() const { - // Cannot completely remove virtual function even in release mode. -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - dbgs() << " " << *this; -#endif -} diff --git a/contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp b/contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp deleted file mode 100644 index 18d18f0cf6ed..000000000000 --- a/contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp +++ /dev/null @@ -1,19 +0,0 @@ -//===- MCAsmParserExtension.cpp - Asm Parser Hooks ------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCParser/MCAsmParserExtension.h" - -using namespace llvm; - -MCAsmParserExtension::MCAsmParserExtension() = default; - -MCAsmParserExtension::~MCAsmParserExtension() = default; - -void MCAsmParserExtension::Initialize(MCAsmParser &Parser) { - this->Parser = &Parser; -} diff --git a/contrib/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp deleted file mode 100644 index 940f26d4750b..000000000000 --- a/contrib/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp +++ /dev/null @@ -1,29 +0,0 @@ -//===-- MCTargetAsmParser.cpp - Target Assembly Parser --------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCParser/MCTargetAsmParser.h" -#include "llvm/MC/MCContext.h" - -using namespace llvm; - -MCTargetAsmParser::MCTargetAsmParser(MCTargetOptions const &MCOptions, - const MCSubtargetInfo &STI, - const MCInstrInfo &MII) - : MCOptions(MCOptions), STI(&STI), MII(MII) {} - -MCTargetAsmParser::~MCTargetAsmParser() = default; - -MCSubtargetInfo &MCTargetAsmParser::copySTI() { - MCSubtargetInfo &STICopy = getContext().getSubtargetCopy(getSTI()); - STI = &STICopy; - return STICopy; -} - -const MCSubtargetInfo &MCTargetAsmParser::getSTI() const { - return *STI; -} diff --git a/contrib/llvm/lib/MC/MCParser/WasmAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/WasmAsmParser.cpp deleted file mode 100644 index 28d4459fecd4..000000000000 --- a/contrib/llvm/lib/MC/MCParser/WasmAsmParser.cpp +++ /dev/null @@ -1,255 +0,0 @@ -//===- WasmAsmParser.cpp - Wasm Assembly Parser -----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// -- -// -// Note, this is for wasm, the binary format (analogous to ELF), not wasm, -// the instruction set (analogous to x86), for which parsing code lives in -// WebAssemblyAsmParser. -// -// This file contains processing for generic directives implemented using -// MCTargetStreamer, the ones that depend on WebAssemblyTargetStreamer are in -// WebAssemblyAsmParser. -// -//===----------------------------------------------------------------------===// - -#include "llvm/BinaryFormat/Wasm.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCParser/MCAsmLexer.h" -#include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/MC/MCParser/MCAsmParserExtension.h" -#include "llvm/MC/MCSectionWasm.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCSymbolWasm.h" -#include "llvm/Support/MachineValueType.h" - -using namespace llvm; - -namespace { - -class WasmAsmParser : public MCAsmParserExtension { - MCAsmParser *Parser = nullptr; - MCAsmLexer *Lexer = nullptr; - - template<bool (WasmAsmParser::*HandlerMethod)(StringRef, SMLoc)> - void addDirectiveHandler(StringRef Directive) { - MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( - this, HandleDirective<WasmAsmParser, HandlerMethod>); - - getParser().addDirectiveHandler(Directive, Handler); - } - -public: - WasmAsmParser() { BracketExpressionsSupported = true; } - - void Initialize(MCAsmParser &P) override { - Parser = &P; - Lexer = &Parser->getLexer(); - // Call the base implementation. - this->MCAsmParserExtension::Initialize(*Parser); - - addDirectiveHandler<&WasmAsmParser::parseSectionDirectiveText>(".text"); - addDirectiveHandler<&WasmAsmParser::parseSectionDirective>(".section"); - addDirectiveHandler<&WasmAsmParser::parseDirectiveSize>(".size"); - addDirectiveHandler<&WasmAsmParser::parseDirectiveType>(".type"); - addDirectiveHandler<&WasmAsmParser::ParseDirectiveIdent>(".ident"); - addDirectiveHandler< - &WasmAsmParser::ParseDirectiveSymbolAttribute>(".weak"); - addDirectiveHandler< - &WasmAsmParser::ParseDirectiveSymbolAttribute>(".local"); - addDirectiveHandler< - &WasmAsmParser::ParseDirectiveSymbolAttribute>(".internal"); - addDirectiveHandler< - &WasmAsmParser::ParseDirectiveSymbolAttribute>(".hidden"); - } - - bool error(const StringRef &Msg, const AsmToken &Tok) { - return Parser->Error(Tok.getLoc(), Msg + Tok.getString()); - } - - bool isNext(AsmToken::TokenKind Kind) { - auto Ok = Lexer->is(Kind); - if (Ok) - Lex(); - return Ok; - } - - bool expect(AsmToken::TokenKind Kind, const char *KindName) { - if (!isNext(Kind)) - return error(std::string("Expected ") + KindName + ", instead got: ", - Lexer->getTok()); - return false; - } - - bool parseSectionDirectiveText(StringRef, SMLoc) { - // FIXME: .text currently no-op. - return false; - } - - bool parseSectionFlags(StringRef FlagStr, bool &Passive) { - SmallVector<StringRef, 2> Flags; - // If there are no flags, keep Flags empty - FlagStr.split(Flags, ",", -1, false); - for (auto &Flag : Flags) { - if (Flag == "passive") - Passive = true; - else - return error("Expected section flags, instead got: ", Lexer->getTok()); - } - return false; - } - - bool parseSectionDirective(StringRef, SMLoc) { - StringRef Name; - if (Parser->parseIdentifier(Name)) - return TokError("expected identifier in directive"); - - if (expect(AsmToken::Comma, ",")) - return true; - - if (Lexer->isNot(AsmToken::String)) - return error("expected string in directive, instead got: ", Lexer->getTok()); - - auto Kind = StringSwitch<Optional<SectionKind>>(Name) - .StartsWith(".data", SectionKind::getData()) - .StartsWith(".rodata", SectionKind::getReadOnly()) - .StartsWith(".text", SectionKind::getText()) - .StartsWith(".custom_section", SectionKind::getMetadata()) - .StartsWith(".bss", SectionKind::getBSS()) - // See use of .init_array in WasmObjectWriter and - // TargetLoweringObjectFileWasm - .StartsWith(".init_array", SectionKind::getData()) - .Default(Optional<SectionKind>()); - if (!Kind.hasValue()) - return Parser->Error(Lexer->getLoc(), "unknown section kind: " + Name); - - MCSectionWasm *Section = getContext().getWasmSection(Name, Kind.getValue()); - - // Update section flags if present in this .section directive - bool Passive = false; - if (parseSectionFlags(getTok().getStringContents(), Passive)) - return true; - - if (Passive) { - if (!Section->isWasmData()) - return Parser->Error(getTok().getLoc(), - "Only data sections can be passive"); - Section->setPassive(); - } - - Lex(); - - if (expect(AsmToken::Comma, ",") || expect(AsmToken::At, "@") || - expect(AsmToken::EndOfStatement, "eol")) - return true; - - auto WS = getContext().getWasmSection(Name, Kind.getValue()); - getStreamer().SwitchSection(WS); - return false; - } - - // TODO: This function is almost the same as ELFAsmParser::ParseDirectiveSize - // so maybe could be shared somehow. - bool parseDirectiveSize(StringRef, SMLoc) { - StringRef Name; - if (Parser->parseIdentifier(Name)) - return TokError("expected identifier in directive"); - auto Sym = getContext().getOrCreateSymbol(Name); - if (expect(AsmToken::Comma, ",")) - return true; - const MCExpr *Expr; - if (Parser->parseExpression(Expr)) - return true; - if (expect(AsmToken::EndOfStatement, "eol")) - return true; - // This is done automatically by the assembler for functions currently, - // so this is only currently needed for data sections: - getStreamer().emitELFSize(Sym, Expr); - return false; - } - - bool parseDirectiveType(StringRef, SMLoc) { - // This could be the start of a function, check if followed by - // "label,@function" - if (!Lexer->is(AsmToken::Identifier)) - return error("Expected label after .type directive, got: ", - Lexer->getTok()); - auto WasmSym = cast<MCSymbolWasm>( - getStreamer().getContext().getOrCreateSymbol( - Lexer->getTok().getString())); - Lex(); - if (!(isNext(AsmToken::Comma) && isNext(AsmToken::At) && - Lexer->is(AsmToken::Identifier))) - return error("Expected label,@type declaration, got: ", Lexer->getTok()); - auto TypeName = Lexer->getTok().getString(); - if (TypeName == "function") - WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); - else if (TypeName == "global") - WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL); - else if (TypeName == "object") - WasmSym->setType(wasm::WASM_SYMBOL_TYPE_DATA); - else - return error("Unknown WASM symbol type: ", Lexer->getTok()); - Lex(); - return expect(AsmToken::EndOfStatement, "EOL"); - } - - // FIXME: Shared with ELF. - /// ParseDirectiveIdent - /// ::= .ident string - bool ParseDirectiveIdent(StringRef, SMLoc) { - if (getLexer().isNot(AsmToken::String)) - return TokError("unexpected token in '.ident' directive"); - StringRef Data = getTok().getIdentifier(); - Lex(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.ident' directive"); - Lex(); - getStreamer().EmitIdent(Data); - return false; - } - - // FIXME: Shared with ELF. - /// ParseDirectiveSymbolAttribute - /// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ] - bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { - MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive) - .Case(".weak", MCSA_Weak) - .Case(".local", MCSA_Local) - .Case(".hidden", MCSA_Hidden) - .Case(".internal", MCSA_Internal) - .Case(".protected", MCSA_Protected) - .Default(MCSA_Invalid); - assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); - if (getLexer().isNot(AsmToken::EndOfStatement)) { - while (true) { - StringRef Name; - if (getParser().parseIdentifier(Name)) - return TokError("expected identifier in directive"); - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - getStreamer().EmitSymbolAttribute(Sym, Attr); - if (getLexer().is(AsmToken::EndOfStatement)) - break; - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - } - } - Lex(); - return false; - } -}; - -} // end anonymous namespace - -namespace llvm { - -MCAsmParserExtension *createWasmAsmParser() { - return new WasmAsmParser; -} - -} // end namespace llvm diff --git a/contrib/llvm/lib/MC/MCRegisterInfo.cpp b/contrib/llvm/lib/MC/MCRegisterInfo.cpp deleted file mode 100644 index 4273b876b7bb..000000000000 --- a/contrib/llvm/lib/MC/MCRegisterInfo.cpp +++ /dev/null @@ -1,134 +0,0 @@ -//===- MC/MCRegisterInfo.cpp - Target Register Description ----------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements MCRegisterInfo functions. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/ErrorHandling.h" -#include <algorithm> -#include <cassert> -#include <cstdint> - -using namespace llvm; - -unsigned MCRegisterInfo::getMatchingSuperReg(unsigned Reg, unsigned SubIdx, - const MCRegisterClass *RC) const { - for (MCSuperRegIterator Supers(Reg, this); Supers.isValid(); ++Supers) - if (RC->contains(*Supers) && Reg == getSubReg(*Supers, SubIdx)) - return *Supers; - return 0; -} - -unsigned MCRegisterInfo::getSubReg(unsigned Reg, unsigned Idx) const { - assert(Idx && Idx < getNumSubRegIndices() && - "This is not a subregister index"); - // Get a pointer to the corresponding SubRegIndices list. This list has the - // name of each sub-register in the same order as MCSubRegIterator. - const uint16_t *SRI = SubRegIndices + get(Reg).SubRegIndices; - for (MCSubRegIterator Subs(Reg, this); Subs.isValid(); ++Subs, ++SRI) - if (*SRI == Idx) - return *Subs; - return 0; -} - -unsigned MCRegisterInfo::getSubRegIndex(unsigned Reg, unsigned SubReg) const { - assert(SubReg && SubReg < getNumRegs() && "This is not a register"); - // Get a pointer to the corresponding SubRegIndices list. This list has the - // name of each sub-register in the same order as MCSubRegIterator. - const uint16_t *SRI = SubRegIndices + get(Reg).SubRegIndices; - for (MCSubRegIterator Subs(Reg, this); Subs.isValid(); ++Subs, ++SRI) - if (*Subs == SubReg) - return *SRI; - return 0; -} - -unsigned MCRegisterInfo::getSubRegIdxSize(unsigned Idx) const { - assert(Idx && Idx < getNumSubRegIndices() && - "This is not a subregister index"); - return SubRegIdxRanges[Idx].Size; -} - -unsigned MCRegisterInfo::getSubRegIdxOffset(unsigned Idx) const { - assert(Idx && Idx < getNumSubRegIndices() && - "This is not a subregister index"); - return SubRegIdxRanges[Idx].Offset; -} - -int MCRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const { - const DwarfLLVMRegPair *M = isEH ? EHL2DwarfRegs : L2DwarfRegs; - unsigned Size = isEH ? EHL2DwarfRegsSize : L2DwarfRegsSize; - - if (!M) - return -1; - DwarfLLVMRegPair Key = { RegNum, 0 }; - const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, Key); - if (I == M+Size || I->FromReg != RegNum) - return -1; - return I->ToReg; -} - -int MCRegisterInfo::getLLVMRegNum(unsigned RegNum, bool isEH) const { - const DwarfLLVMRegPair *M = isEH ? EHDwarf2LRegs : Dwarf2LRegs; - unsigned Size = isEH ? EHDwarf2LRegsSize : Dwarf2LRegsSize; - - if (!M) - return -1; - DwarfLLVMRegPair Key = { RegNum, 0 }; - const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, Key); - assert(I != M+Size && I->FromReg == RegNum && "Invalid RegNum"); - return I->ToReg; -} - -int MCRegisterInfo::getLLVMRegNumFromEH(unsigned RegNum) const { - const DwarfLLVMRegPair *M = EHDwarf2LRegs; - unsigned Size = EHDwarf2LRegsSize; - - if (!M) - return -1; - DwarfLLVMRegPair Key = { RegNum, 0 }; - const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, Key); - if (I == M+Size || I->FromReg != RegNum) - return -1; - return I->ToReg; -} - -int MCRegisterInfo::getDwarfRegNumFromDwarfEHRegNum(unsigned RegNum) const { - // On ELF platforms, DWARF EH register numbers are the same as DWARF - // other register numbers. On Darwin x86, they differ and so need to be - // mapped. The .cfi_* directives accept integer literals as well as - // register names and should generate exactly what the assembly code - // asked for, so there might be DWARF/EH register numbers that don't have - // a corresponding LLVM register number at all. So if we can't map the - // EH register number to an LLVM register number, assume it's just a - // valid DWARF register number as is. - int LRegNum = getLLVMRegNumFromEH(RegNum); - if (LRegNum != -1) - return getDwarfRegNum(LRegNum, false); - return RegNum; -} - -int MCRegisterInfo::getSEHRegNum(unsigned RegNum) const { - const DenseMap<unsigned, int>::const_iterator I = L2SEHRegs.find(RegNum); - if (I == L2SEHRegs.end()) return (int)RegNum; - return I->second; -} - -int MCRegisterInfo::getCodeViewRegNum(unsigned RegNum) const { - if (L2CVRegs.empty()) - report_fatal_error("target does not implement codeview register mapping"); - const DenseMap<unsigned, int>::const_iterator I = L2CVRegs.find(RegNum); - if (I == L2CVRegs.end()) - report_fatal_error("unknown codeview register " + (RegNum < getNumRegs() - ? getName(RegNum) - : Twine(RegNum))); - return I->second; -} diff --git a/contrib/llvm/lib/MC/MCSchedule.cpp b/contrib/llvm/lib/MC/MCSchedule.cpp deleted file mode 100644 index 1fc5ec5e975f..000000000000 --- a/contrib/llvm/lib/MC/MCSchedule.cpp +++ /dev/null @@ -1,167 +0,0 @@ -//===- MCSchedule.cpp - Scheduling ------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the default scheduling model. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCSchedule.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCInstrDesc.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include <type_traits> - -using namespace llvm; - -static_assert(std::is_pod<MCSchedModel>::value, - "We shouldn't have a static constructor here"); -const MCSchedModel MCSchedModel::Default = {DefaultIssueWidth, - DefaultMicroOpBufferSize, - DefaultLoopMicroOpBufferSize, - DefaultLoadLatency, - DefaultHighLatency, - DefaultMispredictPenalty, - false, - true, - 0, - nullptr, - nullptr, - 0, - 0, - nullptr, - nullptr}; - -int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI, - const MCSchedClassDesc &SCDesc) { - int Latency = 0; - for (unsigned DefIdx = 0, DefEnd = SCDesc.NumWriteLatencyEntries; - DefIdx != DefEnd; ++DefIdx) { - // Lookup the definition's write latency in SubtargetInfo. - const MCWriteLatencyEntry *WLEntry = - STI.getWriteLatencyEntry(&SCDesc, DefIdx); - // Early exit if we found an invalid latency. - if (WLEntry->Cycles < 0) - return WLEntry->Cycles; - Latency = std::max(Latency, static_cast<int>(WLEntry->Cycles)); - } - return Latency; -} - -int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI, - unsigned SchedClass) const { - const MCSchedClassDesc &SCDesc = *getSchedClassDesc(SchedClass); - if (!SCDesc.isValid()) - return 0; - if (!SCDesc.isVariant()) - return MCSchedModel::computeInstrLatency(STI, SCDesc); - - llvm_unreachable("unsupported variant scheduling class"); -} - -int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI, - const MCInstrInfo &MCII, - const MCInst &Inst) const { - unsigned SchedClass = MCII.get(Inst.getOpcode()).getSchedClass(); - const MCSchedClassDesc *SCDesc = getSchedClassDesc(SchedClass); - if (!SCDesc->isValid()) - return 0; - - unsigned CPUID = getProcessorID(); - while (SCDesc->isVariant()) { - SchedClass = STI.resolveVariantSchedClass(SchedClass, &Inst, CPUID); - SCDesc = getSchedClassDesc(SchedClass); - } - - if (SchedClass) - return MCSchedModel::computeInstrLatency(STI, *SCDesc); - - llvm_unreachable("unsupported variant scheduling class"); -} - -double -MCSchedModel::getReciprocalThroughput(const MCSubtargetInfo &STI, - const MCSchedClassDesc &SCDesc) { - Optional<double> Throughput; - const MCSchedModel &SM = STI.getSchedModel(); - const MCWriteProcResEntry *I = STI.getWriteProcResBegin(&SCDesc); - const MCWriteProcResEntry *E = STI.getWriteProcResEnd(&SCDesc); - for (; I != E; ++I) { - if (!I->Cycles) - continue; - unsigned NumUnits = SM.getProcResource(I->ProcResourceIdx)->NumUnits; - double Temp = NumUnits * 1.0 / I->Cycles; - Throughput = Throughput ? std::min(Throughput.getValue(), Temp) : Temp; - } - if (Throughput.hasValue()) - return 1.0 / Throughput.getValue(); - - // If no throughput value was calculated, assume that we can execute at the - // maximum issue width scaled by number of micro-ops for the schedule class. - return ((double)SCDesc.NumMicroOps) / SM.IssueWidth; -} - -double -MCSchedModel::getReciprocalThroughput(const MCSubtargetInfo &STI, - const MCInstrInfo &MCII, - const MCInst &Inst) const { - unsigned SchedClass = MCII.get(Inst.getOpcode()).getSchedClass(); - const MCSchedClassDesc *SCDesc = getSchedClassDesc(SchedClass); - - // If there's no valid class, assume that the instruction executes/completes - // at the maximum issue width. - if (!SCDesc->isValid()) - return 1.0 / IssueWidth; - - unsigned CPUID = getProcessorID(); - while (SCDesc->isVariant()) { - SchedClass = STI.resolveVariantSchedClass(SchedClass, &Inst, CPUID); - SCDesc = getSchedClassDesc(SchedClass); - } - - if (SchedClass) - return MCSchedModel::getReciprocalThroughput(STI, *SCDesc); - - llvm_unreachable("unsupported variant scheduling class"); -} - -double -MCSchedModel::getReciprocalThroughput(unsigned SchedClass, - const InstrItineraryData &IID) { - Optional<double> Throughput; - const InstrStage *I = IID.beginStage(SchedClass); - const InstrStage *E = IID.endStage(SchedClass); - for (; I != E; ++I) { - if (!I->getCycles()) - continue; - double Temp = countPopulation(I->getUnits()) * 1.0 / I->getCycles(); - Throughput = Throughput ? std::min(Throughput.getValue(), Temp) : Temp; - } - if (Throughput.hasValue()) - return 1.0 / Throughput.getValue(); - - // If there are no execution resources specified for this class, then assume - // that it can execute at the maximum default issue width. - return 1.0 / DefaultIssueWidth; -} - -unsigned -MCSchedModel::getForwardingDelayCycles(ArrayRef<MCReadAdvanceEntry> Entries, - unsigned WriteResourceID) { - if (Entries.empty()) - return 0; - - int DelayCycles = 0; - for (const MCReadAdvanceEntry &E : Entries) { - if (E.WriteResourceID != WriteResourceID) - continue; - DelayCycles = std::min(DelayCycles, E.Cycles); - } - - return std::abs(DelayCycles); -} diff --git a/contrib/llvm/lib/MC/MCSection.cpp b/contrib/llvm/lib/MC/MCSection.cpp deleted file mode 100644 index 2c892ab81608..000000000000 --- a/contrib/llvm/lib/MC/MCSection.cpp +++ /dev/null @@ -1,102 +0,0 @@ -//===- lib/MC/MCSection.cpp - Machine Code Section Representation ---------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCSection.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Config/llvm-config.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCFragment.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <utility> - -using namespace llvm; - -MCSection::MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin) - : Begin(Begin), BundleGroupBeforeFirstInst(false), HasInstructions(false), - HasData(false), IsRegistered(false), DummyFragment(this), Variant(V), - Kind(K) {} - -MCSymbol *MCSection::getEndSymbol(MCContext &Ctx) { - if (!End) - End = Ctx.createTempSymbol("sec_end", true); - return End; -} - -bool MCSection::hasEnded() const { return End && End->isInSection(); } - -MCSection::~MCSection() = default; - -void MCSection::setBundleLockState(BundleLockStateType NewState) { - if (NewState == NotBundleLocked) { - if (BundleLockNestingDepth == 0) { - report_fatal_error("Mismatched bundle_lock/unlock directives"); - } - if (--BundleLockNestingDepth == 0) { - BundleLockState = NotBundleLocked; - } - return; - } - - // If any of the directives is an align_to_end directive, the whole nested - // group is align_to_end. So don't downgrade from align_to_end to just locked. - if (BundleLockState != BundleLockedAlignToEnd) { - BundleLockState = NewState; - } - ++BundleLockNestingDepth; -} - -MCSection::iterator -MCSection::getSubsectionInsertionPoint(unsigned Subsection) { - if (Subsection == 0 && SubsectionFragmentMap.empty()) - return end(); - - SmallVectorImpl<std::pair<unsigned, MCFragment *>>::iterator MI = - std::lower_bound(SubsectionFragmentMap.begin(), - SubsectionFragmentMap.end(), - std::make_pair(Subsection, (MCFragment *)nullptr)); - bool ExactMatch = false; - if (MI != SubsectionFragmentMap.end()) { - ExactMatch = MI->first == Subsection; - if (ExactMatch) - ++MI; - } - iterator IP; - if (MI == SubsectionFragmentMap.end()) - IP = end(); - else - IP = MI->second->getIterator(); - if (!ExactMatch && Subsection != 0) { - // The GNU as documentation claims that subsections have an alignment of 4, - // although this appears not to be the case. - MCFragment *F = new MCDataFragment(); - SubsectionFragmentMap.insert(MI, std::make_pair(Subsection, F)); - getFragmentList().insert(IP, F); - F->setParent(this); - } - - return IP; -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -LLVM_DUMP_METHOD void MCSection::dump() const { - raw_ostream &OS = errs(); - - OS << "<MCSection"; - OS << " Fragments:[\n "; - for (auto it = begin(), ie = end(); it != ie; ++it) { - if (it != begin()) - OS << ",\n "; - it->dump(); - } - OS << "]>"; -} -#endif diff --git a/contrib/llvm/lib/MC/MCSectionCOFF.cpp b/contrib/llvm/lib/MC/MCSectionCOFF.cpp deleted file mode 100644 index f0c06f70bd73..000000000000 --- a/contrib/llvm/lib/MC/MCSectionCOFF.cpp +++ /dev/null @@ -1,113 +0,0 @@ -//===- lib/MC/MCSectionCOFF.cpp - COFF Code Section Representation --------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCSectionCOFF.h" -#include "llvm/BinaryFormat/COFF.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> - -using namespace llvm; - -// ShouldOmitSectionDirective - Decides whether a '.section' directive -// should be printed before the section name -bool MCSectionCOFF::ShouldOmitSectionDirective(StringRef Name, - const MCAsmInfo &MAI) const { - if (COMDATSymbol) - return false; - - // FIXME: Does .section .bss/.data/.text work everywhere?? - if (Name == ".text" || Name == ".data" || Name == ".bss") - return true; - - return false; -} - -void MCSectionCOFF::setSelection(int Selection) const { - assert(Selection != 0 && "invalid COMDAT selection type"); - this->Selection = Selection; - Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; -} - -void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, - raw_ostream &OS, - const MCExpr *Subsection) const { - // standard sections don't require the '.section' - if (ShouldOmitSectionDirective(SectionName, MAI)) { - OS << '\t' << getSectionName() << '\n'; - return; - } - - OS << "\t.section\t" << getSectionName() << ",\""; - if (getCharacteristics() & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) - OS << 'd'; - if (getCharacteristics() & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) - OS << 'b'; - if (getCharacteristics() & COFF::IMAGE_SCN_MEM_EXECUTE) - OS << 'x'; - if (getCharacteristics() & COFF::IMAGE_SCN_MEM_WRITE) - OS << 'w'; - else if (getCharacteristics() & COFF::IMAGE_SCN_MEM_READ) - OS << 'r'; - else - OS << 'y'; - if (getCharacteristics() & COFF::IMAGE_SCN_LNK_REMOVE) - OS << 'n'; - if (getCharacteristics() & COFF::IMAGE_SCN_MEM_SHARED) - OS << 's'; - if ((getCharacteristics() & COFF::IMAGE_SCN_MEM_DISCARDABLE) && - !isImplicitlyDiscardable(SectionName)) - OS << 'D'; - OS << '"'; - - if (getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) { - if (COMDATSymbol) - OS << ","; - else - OS << "\n\t.linkonce\t"; - switch (Selection) { - case COFF::IMAGE_COMDAT_SELECT_NODUPLICATES: - OS << "one_only"; - break; - case COFF::IMAGE_COMDAT_SELECT_ANY: - OS << "discard"; - break; - case COFF::IMAGE_COMDAT_SELECT_SAME_SIZE: - OS << "same_size"; - break; - case COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH: - OS << "same_contents"; - break; - case COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE: - OS << "associative"; - break; - case COFF::IMAGE_COMDAT_SELECT_LARGEST: - OS << "largest"; - break; - case COFF::IMAGE_COMDAT_SELECT_NEWEST: - OS << "newest"; - break; - default: - assert(false && "unsupported COFF selection type"); - break; - } - if (COMDATSymbol) { - OS << ","; - COMDATSymbol->print(OS, &MAI); - } - } - OS << '\n'; -} - -bool MCSectionCOFF::UseCodeAlign() const { - return getKind().isText(); -} - -bool MCSectionCOFF::isVirtualSection() const { - return getCharacteristics() & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; -} diff --git a/contrib/llvm/lib/MC/MCSectionELF.cpp b/contrib/llvm/lib/MC/MCSectionELF.cpp deleted file mode 100644 index efe504b2024c..000000000000 --- a/contrib/llvm/lib/MC/MCSectionELF.cpp +++ /dev/null @@ -1,198 +0,0 @@ -//===- lib/MC/MCSectionELF.cpp - ELF Code Section Representation ----------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCSectionELF.h" -#include "llvm/ADT/Triple.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> - -using namespace llvm; - -// Decides whether a '.section' directive -// should be printed before the section name. -bool MCSectionELF::ShouldOmitSectionDirective(StringRef Name, - const MCAsmInfo &MAI) const { - if (isUnique()) - return false; - - return MAI.shouldOmitSectionDirective(Name); -} - -static void printName(raw_ostream &OS, StringRef Name) { - if (Name.find_first_not_of("0123456789_." - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == Name.npos) { - OS << Name; - return; - } - OS << '"'; - for (const char *B = Name.begin(), *E = Name.end(); B < E; ++B) { - if (*B == '"') // Unquoted " - OS << "\\\""; - else if (*B != '\\') // Neither " or backslash - OS << *B; - else if (B + 1 == E) // Trailing backslash - OS << "\\\\"; - else { - OS << B[0] << B[1]; // Quoted character - ++B; - } - } - OS << '"'; -} - -void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, - raw_ostream &OS, - const MCExpr *Subsection) const { - if (ShouldOmitSectionDirective(SectionName, MAI)) { - OS << '\t' << getSectionName(); - if (Subsection) { - OS << '\t'; - Subsection->print(OS, &MAI); - } - OS << '\n'; - return; - } - - OS << "\t.section\t"; - printName(OS, getSectionName()); - - // Handle the weird solaris syntax if desired. - if (MAI.usesSunStyleELFSectionSwitchSyntax() && - !(Flags & ELF::SHF_MERGE)) { - if (Flags & ELF::SHF_ALLOC) - OS << ",#alloc"; - if (Flags & ELF::SHF_EXECINSTR) - OS << ",#execinstr"; - if (Flags & ELF::SHF_WRITE) - OS << ",#write"; - if (Flags & ELF::SHF_EXCLUDE) - OS << ",#exclude"; - if (Flags & ELF::SHF_TLS) - OS << ",#tls"; - OS << '\n'; - return; - } - - OS << ",\""; - if (Flags & ELF::SHF_ALLOC) - OS << 'a'; - if (Flags & ELF::SHF_EXCLUDE) - OS << 'e'; - if (Flags & ELF::SHF_EXECINSTR) - OS << 'x'; - if (Flags & ELF::SHF_GROUP) - OS << 'G'; - if (Flags & ELF::SHF_WRITE) - OS << 'w'; - if (Flags & ELF::SHF_MERGE) - OS << 'M'; - if (Flags & ELF::SHF_STRINGS) - OS << 'S'; - if (Flags & ELF::SHF_TLS) - OS << 'T'; - if (Flags & ELF::SHF_LINK_ORDER) - OS << 'o'; - - // If there are target-specific flags, print them. - Triple::ArchType Arch = T.getArch(); - if (Arch == Triple::xcore) { - if (Flags & ELF::XCORE_SHF_CP_SECTION) - OS << 'c'; - if (Flags & ELF::XCORE_SHF_DP_SECTION) - OS << 'd'; - } else if (T.isARM() || T.isThumb()) { - if (Flags & ELF::SHF_ARM_PURECODE) - OS << 'y'; - } else if (Arch == Triple::hexagon) { - if (Flags & ELF::SHF_HEX_GPREL) - OS << 's'; - } - - OS << '"'; - - OS << ','; - - // If comment string is '@', e.g. as on ARM - use '%' instead - if (MAI.getCommentString()[0] == '@') - OS << '%'; - else - OS << '@'; - - if (Type == ELF::SHT_INIT_ARRAY) - OS << "init_array"; - else if (Type == ELF::SHT_FINI_ARRAY) - OS << "fini_array"; - else if (Type == ELF::SHT_PREINIT_ARRAY) - OS << "preinit_array"; - else if (Type == ELF::SHT_NOBITS) - OS << "nobits"; - else if (Type == ELF::SHT_NOTE) - OS << "note"; - else if (Type == ELF::SHT_PROGBITS) - OS << "progbits"; - else if (Type == ELF::SHT_X86_64_UNWIND) - OS << "unwind"; - else if (Type == ELF::SHT_MIPS_DWARF) - // Print hex value of the flag while we do not have - // any standard symbolic representation of the flag. - OS << "0x7000001e"; - else if (Type == ELF::SHT_LLVM_ODRTAB) - OS << "llvm_odrtab"; - else if (Type == ELF::SHT_LLVM_LINKER_OPTIONS) - OS << "llvm_linker_options"; - else if (Type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE) - OS << "llvm_call_graph_profile"; - else if (Type == ELF::SHT_LLVM_DEPENDENT_LIBRARIES) - OS << "llvm_dependent_libraries"; - else if (Type == ELF::SHT_LLVM_SYMPART) - OS << "llvm_sympart"; - else - report_fatal_error("unsupported type 0x" + Twine::utohexstr(Type) + - " for section " + getSectionName()); - - if (EntrySize) { - assert(Flags & ELF::SHF_MERGE); - OS << "," << EntrySize; - } - - if (Flags & ELF::SHF_GROUP) { - OS << ","; - printName(OS, Group->getName()); - OS << ",comdat"; - } - - if (Flags & ELF::SHF_LINK_ORDER) { - assert(AssociatedSymbol); - OS << ","; - printName(OS, AssociatedSymbol->getName()); - } - - if (isUnique()) - OS << ",unique," << UniqueID; - - OS << '\n'; - - if (Subsection) { - OS << "\t.subsection\t"; - Subsection->print(OS, &MAI); - OS << '\n'; - } -} - -bool MCSectionELF::UseCodeAlign() const { - return getFlags() & ELF::SHF_EXECINSTR; -} - -bool MCSectionELF::isVirtualSection() const { - return getType() == ELF::SHT_NOBITS; -} diff --git a/contrib/llvm/lib/MC/MCSectionMachO.cpp b/contrib/llvm/lib/MC/MCSectionMachO.cpp deleted file mode 100644 index 0fd89dcbe5fa..000000000000 --- a/contrib/llvm/lib/MC/MCSectionMachO.cpp +++ /dev/null @@ -1,281 +0,0 @@ -//===- lib/MC/MCSectionMachO.cpp - MachO Code Section Representation ------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCSectionMachO.h" -#include "llvm/MC/MCContext.h" -#include "llvm/Support/raw_ostream.h" -#include <cctype> -using namespace llvm; - -/// SectionTypeDescriptors - These are strings that describe the various section -/// types. This *must* be kept in order with and stay synchronized with the -/// section type list. -static constexpr struct { - StringLiteral AssemblerName, EnumName; -} SectionTypeDescriptors[MachO::LAST_KNOWN_SECTION_TYPE + 1] = { - {StringLiteral("regular"), StringLiteral("S_REGULAR")}, // 0x00 - {StringLiteral(""), StringLiteral("S_ZEROFILL")}, // 0x01 - {StringLiteral("cstring_literals"), - StringLiteral("S_CSTRING_LITERALS")}, // 0x02 - {StringLiteral("4byte_literals"), - StringLiteral("S_4BYTE_LITERALS")}, // 0x03 - {StringLiteral("8byte_literals"), - StringLiteral("S_8BYTE_LITERALS")}, // 0x04 - {StringLiteral("literal_pointers"), - StringLiteral("S_LITERAL_POINTERS")}, // 0x05 - {StringLiteral("non_lazy_symbol_pointers"), - StringLiteral("S_NON_LAZY_SYMBOL_POINTERS")}, // 0x06 - {StringLiteral("lazy_symbol_pointers"), - StringLiteral("S_LAZY_SYMBOL_POINTERS")}, // 0x07 - {StringLiteral("symbol_stubs"), StringLiteral("S_SYMBOL_STUBS")}, // 0x08 - {StringLiteral("mod_init_funcs"), - StringLiteral("S_MOD_INIT_FUNC_POINTERS")}, // 0x09 - {StringLiteral("mod_term_funcs"), - StringLiteral("S_MOD_TERM_FUNC_POINTERS")}, // 0x0A - {StringLiteral("coalesced"), StringLiteral("S_COALESCED")}, // 0x0B - {StringLiteral("") /*FIXME??*/, StringLiteral("S_GB_ZEROFILL")}, // 0x0C - {StringLiteral("interposing"), StringLiteral("S_INTERPOSING")}, // 0x0D - {StringLiteral("16byte_literals"), - StringLiteral("S_16BYTE_LITERALS")}, // 0x0E - {StringLiteral("") /*FIXME??*/, StringLiteral("S_DTRACE_DOF")}, // 0x0F - {StringLiteral("") /*FIXME??*/, - StringLiteral("S_LAZY_DYLIB_SYMBOL_POINTERS")}, // 0x10 - {StringLiteral("thread_local_regular"), - StringLiteral("S_THREAD_LOCAL_REGULAR")}, // 0x11 - {StringLiteral("thread_local_zerofill"), - StringLiteral("S_THREAD_LOCAL_ZEROFILL")}, // 0x12 - {StringLiteral("thread_local_variables"), - StringLiteral("S_THREAD_LOCAL_VARIABLES")}, // 0x13 - {StringLiteral("thread_local_variable_pointers"), - StringLiteral("S_THREAD_LOCAL_VARIABLE_POINTERS")}, // 0x14 - {StringLiteral("thread_local_init_function_pointers"), - StringLiteral("S_THREAD_LOCAL_INIT_FUNCTION_POINTERS")}, // 0x15 -}; - -/// SectionAttrDescriptors - This is an array of descriptors for section -/// attributes. Unlike the SectionTypeDescriptors, this is not directly indexed -/// by attribute, instead it is searched. -static constexpr struct { - unsigned AttrFlag; - StringLiteral AssemblerName, EnumName; -} SectionAttrDescriptors[] = { -#define ENTRY(ASMNAME, ENUM) \ - { MachO::ENUM, StringLiteral(ASMNAME), StringLiteral(#ENUM) }, -ENTRY("pure_instructions", S_ATTR_PURE_INSTRUCTIONS) -ENTRY("no_toc", S_ATTR_NO_TOC) -ENTRY("strip_static_syms", S_ATTR_STRIP_STATIC_SYMS) -ENTRY("no_dead_strip", S_ATTR_NO_DEAD_STRIP) -ENTRY("live_support", S_ATTR_LIVE_SUPPORT) -ENTRY("self_modifying_code", S_ATTR_SELF_MODIFYING_CODE) -ENTRY("debug", S_ATTR_DEBUG) -ENTRY("" /*FIXME*/, S_ATTR_SOME_INSTRUCTIONS) -ENTRY("" /*FIXME*/, S_ATTR_EXT_RELOC) -ENTRY("" /*FIXME*/, S_ATTR_LOC_RELOC) -#undef ENTRY - { 0, StringLiteral("none"), StringLiteral("") }, // used if section has no attributes but has a stub size -}; - -MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section, - unsigned TAA, unsigned reserved2, SectionKind K, - MCSymbol *Begin) - : MCSection(SV_MachO, K, Begin), TypeAndAttributes(TAA), - Reserved2(reserved2) { - assert(Segment.size() <= 16 && Section.size() <= 16 && - "Segment or section string too long"); - for (unsigned i = 0; i != 16; ++i) { - if (i < Segment.size()) - SegmentName[i] = Segment[i]; - else - SegmentName[i] = 0; - - if (i < Section.size()) - SectionName[i] = Section[i]; - else - SectionName[i] = 0; - } -} - -void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, - raw_ostream &OS, - const MCExpr *Subsection) const { - OS << "\t.section\t" << getSegmentName() << ',' << getSectionName(); - - // Get the section type and attributes. - unsigned TAA = getTypeAndAttributes(); - if (TAA == 0) { - OS << '\n'; - return; - } - - MachO::SectionType SectionType = getType(); - assert(SectionType <= MachO::LAST_KNOWN_SECTION_TYPE && - "Invalid SectionType specified!"); - - if (!SectionTypeDescriptors[SectionType].AssemblerName.empty()) { - OS << ','; - OS << SectionTypeDescriptors[SectionType].AssemblerName; - } else { - // If we have no name for the attribute, stop here. - OS << '\n'; - return; - } - - // If we don't have any attributes, we're done. - unsigned SectionAttrs = TAA & MachO::SECTION_ATTRIBUTES; - if (SectionAttrs == 0) { - // If we have a S_SYMBOL_STUBS size specified, print it along with 'none' as - // the attribute specifier. - if (Reserved2 != 0) - OS << ",none," << Reserved2; - OS << '\n'; - return; - } - - // Check each attribute to see if we have it. - char Separator = ','; - for (unsigned i = 0; - SectionAttrs != 0 && SectionAttrDescriptors[i].AttrFlag; - ++i) { - // Check to see if we have this attribute. - if ((SectionAttrDescriptors[i].AttrFlag & SectionAttrs) == 0) - continue; - - // Yep, clear it and print it. - SectionAttrs &= ~SectionAttrDescriptors[i].AttrFlag; - - OS << Separator; - if (!SectionAttrDescriptors[i].AssemblerName.empty()) - OS << SectionAttrDescriptors[i].AssemblerName; - else - OS << "<<" << SectionAttrDescriptors[i].EnumName << ">>"; - Separator = '+'; - } - - assert(SectionAttrs == 0 && "Unknown section attributes!"); - - // If we have a S_SYMBOL_STUBS size specified, print it. - if (Reserved2 != 0) - OS << ',' << Reserved2; - OS << '\n'; -} - -bool MCSectionMachO::UseCodeAlign() const { - return hasAttribute(MachO::S_ATTR_PURE_INSTRUCTIONS); -} - -bool MCSectionMachO::isVirtualSection() const { - return (getType() == MachO::S_ZEROFILL || - getType() == MachO::S_GB_ZEROFILL || - getType() == MachO::S_THREAD_LOCAL_ZEROFILL); -} - -/// ParseSectionSpecifier - Parse the section specifier indicated by "Spec". -/// This is a string that can appear after a .section directive in a mach-o -/// flavored .s file. If successful, this fills in the specified Out -/// parameters and returns an empty string. When an invalid section -/// specifier is present, this returns a string indicating the problem. -std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In. - StringRef &Segment, // Out. - StringRef &Section, // Out. - unsigned &TAA, // Out. - bool &TAAParsed, // Out. - unsigned &StubSize) { // Out. - TAAParsed = false; - - SmallVector<StringRef, 5> SplitSpec; - Spec.split(SplitSpec, ','); - // Remove leading and trailing whitespace. - auto GetEmptyOrTrim = [&SplitSpec](size_t Idx) -> StringRef { - return SplitSpec.size() > Idx ? SplitSpec[Idx].trim() : StringRef(); - }; - Segment = GetEmptyOrTrim(0); - Section = GetEmptyOrTrim(1); - StringRef SectionType = GetEmptyOrTrim(2); - StringRef Attrs = GetEmptyOrTrim(3); - StringRef StubSizeStr = GetEmptyOrTrim(4); - - // Verify that the segment is present and not too long. - if (Segment.empty() || Segment.size() > 16) - return "mach-o section specifier requires a segment whose length is " - "between 1 and 16 characters"; - - // Verify that the section is present and not too long. - if (Section.empty()) - return "mach-o section specifier requires a segment and section " - "separated by a comma"; - - if (Section.size() > 16) - return "mach-o section specifier requires a section whose length is " - "between 1 and 16 characters"; - - // If there is no comma after the section, we're done. - TAA = 0; - StubSize = 0; - if (SectionType.empty()) - return ""; - - // Figure out which section type it is. - auto TypeDescriptor = std::find_if( - std::begin(SectionTypeDescriptors), std::end(SectionTypeDescriptors), - [&](decltype(*SectionTypeDescriptors) &Descriptor) { - return SectionType == Descriptor.AssemblerName; - }); - - // If we didn't find the section type, reject it. - if (TypeDescriptor == std::end(SectionTypeDescriptors)) - return "mach-o section specifier uses an unknown section type"; - - // Remember the TypeID. - TAA = TypeDescriptor - std::begin(SectionTypeDescriptors); - TAAParsed = true; - - // If we have no comma after the section type, there are no attributes. - if (Attrs.empty()) { - // S_SYMBOL_STUBS always require a symbol stub size specifier. - if (TAA == MachO::S_SYMBOL_STUBS) - return "mach-o section specifier of type 'symbol_stubs' requires a size " - "specifier"; - return ""; - } - - // The attribute list is a '+' separated list of attributes. - SmallVector<StringRef, 1> SectionAttrs; - Attrs.split(SectionAttrs, '+', /*MaxSplit=*/-1, /*KeepEmpty=*/false); - - for (StringRef &SectionAttr : SectionAttrs) { - auto AttrDescriptorI = std::find_if( - std::begin(SectionAttrDescriptors), std::end(SectionAttrDescriptors), - [&](decltype(*SectionAttrDescriptors) &Descriptor) { - return SectionAttr.trim() == Descriptor.AssemblerName; - }); - if (AttrDescriptorI == std::end(SectionAttrDescriptors)) - return "mach-o section specifier has invalid attribute"; - - TAA |= AttrDescriptorI->AttrFlag; - } - - // Okay, we've parsed the section attributes, see if we have a stub size spec. - if (StubSizeStr.empty()) { - // S_SYMBOL_STUBS always require a symbol stub size specifier. - if (TAA == MachO::S_SYMBOL_STUBS) - return "mach-o section specifier of type 'symbol_stubs' requires a size " - "specifier"; - return ""; - } - - // If we have a stub size spec, we must have a sectiontype of S_SYMBOL_STUBS. - if ((TAA & MachO::SECTION_TYPE) != MachO::S_SYMBOL_STUBS) - return "mach-o section specifier cannot have a stub size specified because " - "it does not have type 'symbol_stubs'"; - - // Convert the stub size from a string to an integer. - if (StubSizeStr.getAsInteger(0, StubSize)) - return "mach-o section specifier has a malformed stub size"; - - return ""; -} diff --git a/contrib/llvm/lib/MC/MCSectionWasm.cpp b/contrib/llvm/lib/MC/MCSectionWasm.cpp deleted file mode 100644 index 8633c10a73fd..000000000000 --- a/contrib/llvm/lib/MC/MCSectionWasm.cpp +++ /dev/null @@ -1,94 +0,0 @@ -//===- lib/MC/MCSectionWasm.cpp - Wasm Code Section Representation --------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCSectionWasm.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -// Decides whether a '.section' directive -// should be printed before the section name. -bool MCSectionWasm::shouldOmitSectionDirective(StringRef Name, - const MCAsmInfo &MAI) const { - return MAI.shouldOmitSectionDirective(Name); -} - -static void printName(raw_ostream &OS, StringRef Name) { - if (Name.find_first_not_of("0123456789_." - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == Name.npos) { - OS << Name; - return; - } - OS << '"'; - for (const char *B = Name.begin(), *E = Name.end(); B < E; ++B) { - if (*B == '"') // Unquoted " - OS << "\\\""; - else if (*B != '\\') // Neither " or backslash - OS << *B; - else if (B + 1 == E) // Trailing backslash - OS << "\\\\"; - else { - OS << B[0] << B[1]; // Quoted character - ++B; - } - } - OS << '"'; -} - -void MCSectionWasm::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, - raw_ostream &OS, - const MCExpr *Subsection) const { - - if (shouldOmitSectionDirective(SectionName, MAI)) { - OS << '\t' << getSectionName(); - if (Subsection) { - OS << '\t'; - Subsection->print(OS, &MAI); - } - OS << '\n'; - return; - } - - OS << "\t.section\t"; - printName(OS, getSectionName()); - OS << ",\""; - - if (IsPassive) - OS << "passive"; - - OS << '"'; - - OS << ','; - - // If comment string is '@', e.g. as on ARM - use '%' instead - if (MAI.getCommentString()[0] == '@') - OS << '%'; - else - OS << '@'; - - // TODO: Print section type. - - if (isUnique()) - OS << ",unique," << UniqueID; - - OS << '\n'; - - if (Subsection) { - OS << "\t.subsection\t"; - Subsection->print(OS, &MAI); - OS << '\n'; - } -} - -bool MCSectionWasm::UseCodeAlign() const { return false; } - -bool MCSectionWasm::isVirtualSection() const { return false; } diff --git a/contrib/llvm/lib/MC/MCSectionXCOFF.cpp b/contrib/llvm/lib/MC/MCSectionXCOFF.cpp deleted file mode 100644 index d1a637345024..000000000000 --- a/contrib/llvm/lib/MC/MCSectionXCOFF.cpp +++ /dev/null @@ -1,33 +0,0 @@ -//===- lib/MC/MCSectionXCOFF.cpp - XCOFF Code Section Representation ------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCSectionXCOFF.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -MCSectionXCOFF::~MCSectionXCOFF() = default; - -void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, - raw_ostream &OS, - const MCExpr *Subsection) const { - if (getKind().isText()) { - OS << "\t.csect " << getSectionName() << "[" - << "PR" - << "]" << '\n'; - return; - } - - report_fatal_error("Printing for this SectionKind is unimplemented."); -} - -bool MCSectionXCOFF::UseCodeAlign() const { return getKind().isText(); } - -bool MCSectionXCOFF::isVirtualSection() const { return !getKind().isCommon(); } diff --git a/contrib/llvm/lib/MC/MCStreamer.cpp b/contrib/llvm/lib/MC/MCStreamer.cpp deleted file mode 100644 index decbb96817e3..000000000000 --- a/contrib/llvm/lib/MC/MCStreamer.cpp +++ /dev/null @@ -1,1106 +0,0 @@ -//===- lib/MC/MCStreamer.cpp - Streaming Machine Code Output --------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCStreamer.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/BinaryFormat/COFF.h" -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCCodeView.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDwarf.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCInstPrinter.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSectionCOFF.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCWin64EH.h" -#include "llvm/MC/MCWinEH.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/LEB128.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> -#include <cstdint> -#include <cstdlib> -#include <utility> - -using namespace llvm; - -MCTargetStreamer::MCTargetStreamer(MCStreamer &S) : Streamer(S) { - S.setTargetStreamer(this); -} - -// Pin the vtables to this file. -MCTargetStreamer::~MCTargetStreamer() = default; - -void MCTargetStreamer::emitLabel(MCSymbol *Symbol) {} - -void MCTargetStreamer::finish() {} - -void MCTargetStreamer::changeSection(const MCSection *CurSection, - MCSection *Section, - const MCExpr *Subsection, - raw_ostream &OS) { - Section->PrintSwitchToSection( - *Streamer.getContext().getAsmInfo(), - Streamer.getContext().getObjectFileInfo()->getTargetTriple(), OS, - Subsection); -} - -void MCTargetStreamer::emitDwarfFileDirective(StringRef Directive) { - Streamer.EmitRawText(Directive); -} - -void MCTargetStreamer::emitValue(const MCExpr *Value) { - SmallString<128> Str; - raw_svector_ostream OS(Str); - - Value->print(OS, Streamer.getContext().getAsmInfo()); - Streamer.EmitRawText(OS.str()); -} - -void MCTargetStreamer::emitRawBytes(StringRef Data) { - const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo(); - const char *Directive = MAI->getData8bitsDirective(); - for (const unsigned char C : Data.bytes()) { - SmallString<128> Str; - raw_svector_ostream OS(Str); - - OS << Directive << (unsigned)C; - Streamer.EmitRawText(OS.str()); - } -} - -void MCTargetStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {} - -MCStreamer::MCStreamer(MCContext &Ctx) - : Context(Ctx), CurrentWinFrameInfo(nullptr), - UseAssemblerInfoForParsing(false) { - SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>()); -} - -MCStreamer::~MCStreamer() {} - -void MCStreamer::reset() { - DwarfFrameInfos.clear(); - CurrentWinFrameInfo = nullptr; - WinFrameInfos.clear(); - SymbolOrdering.clear(); - SectionStack.clear(); - SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>()); -} - -raw_ostream &MCStreamer::GetCommentOS() { - // By default, discard comments. - return nulls(); -} - -unsigned MCStreamer::getNumFrameInfos() { return DwarfFrameInfos.size(); } -ArrayRef<MCDwarfFrameInfo> MCStreamer::getDwarfFrameInfos() const { - return DwarfFrameInfos; -} - -void MCStreamer::emitRawComment(const Twine &T, bool TabPrefix) {} - -void MCStreamer::addExplicitComment(const Twine &T) {} -void MCStreamer::emitExplicitComments() {} - -void MCStreamer::generateCompactUnwindEncodings(MCAsmBackend *MAB) { - for (auto &FI : DwarfFrameInfos) - FI.CompactUnwindEncoding = - (MAB ? MAB->generateCompactUnwindEncoding(FI.Instructions) : 0); -} - -/// EmitIntValue - Special case of EmitValue that avoids the client having to -/// pass in a MCExpr for constant integers. -void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size) { - assert(1 <= Size && Size <= 8 && "Invalid size"); - assert((isUIntN(8 * Size, Value) || isIntN(8 * Size, Value)) && - "Invalid size"); - char buf[8]; - const bool isLittleEndian = Context.getAsmInfo()->isLittleEndian(); - for (unsigned i = 0; i != Size; ++i) { - unsigned index = isLittleEndian ? i : (Size - i - 1); - buf[i] = uint8_t(Value >> (index * 8)); - } - EmitBytes(StringRef(buf, Size)); -} - -/// EmitULEB128IntValue - Special case of EmitULEB128Value that avoids the -/// client having to pass in a MCExpr for constant integers. -void MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned PadTo) { - SmallString<128> Tmp; - raw_svector_ostream OSE(Tmp); - encodeULEB128(Value, OSE, PadTo); - EmitBytes(OSE.str()); -} - -/// EmitSLEB128IntValue - Special case of EmitSLEB128Value that avoids the -/// client having to pass in a MCExpr for constant integers. -void MCStreamer::EmitSLEB128IntValue(int64_t Value) { - SmallString<128> Tmp; - raw_svector_ostream OSE(Tmp); - encodeSLEB128(Value, OSE); - EmitBytes(OSE.str()); -} - -void MCStreamer::EmitValue(const MCExpr *Value, unsigned Size, SMLoc Loc) { - EmitValueImpl(Value, Size, Loc); -} - -void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size, - bool IsSectionRelative) { - assert((!IsSectionRelative || Size == 4) && - "SectionRelative value requires 4-bytes"); - - if (!IsSectionRelative) - EmitValueImpl(MCSymbolRefExpr::create(Sym, getContext()), Size); - else - EmitCOFFSecRel32(Sym, /*Offset=*/0); -} - -void MCStreamer::EmitDTPRel64Value(const MCExpr *Value) { - report_fatal_error("unsupported directive in streamer"); -} - -void MCStreamer::EmitDTPRel32Value(const MCExpr *Value) { - report_fatal_error("unsupported directive in streamer"); -} - -void MCStreamer::EmitTPRel64Value(const MCExpr *Value) { - report_fatal_error("unsupported directive in streamer"); -} - -void MCStreamer::EmitTPRel32Value(const MCExpr *Value) { - report_fatal_error("unsupported directive in streamer"); -} - -void MCStreamer::EmitGPRel64Value(const MCExpr *Value) { - report_fatal_error("unsupported directive in streamer"); -} - -void MCStreamer::EmitGPRel32Value(const MCExpr *Value) { - report_fatal_error("unsupported directive in streamer"); -} - -/// Emit NumBytes bytes worth of the value specified by FillValue. -/// This implements directives such as '.space'. -void MCStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) { - emitFill(*MCConstantExpr::create(NumBytes, getContext()), FillValue); -} - -/// The implementation in this class just redirects to emitFill. -void MCStreamer::EmitZeros(uint64_t NumBytes) { - emitFill(NumBytes, 0); -} - -Expected<unsigned> -MCStreamer::tryEmitDwarfFileDirective(unsigned FileNo, StringRef Directory, - StringRef Filename, - Optional<MD5::MD5Result> Checksum, - Optional<StringRef> Source, - unsigned CUID) { - return getContext().getDwarfFile(Directory, Filename, FileNo, Checksum, - Source, CUID); -} - -void MCStreamer::emitDwarfFile0Directive(StringRef Directory, - StringRef Filename, - Optional<MD5::MD5Result> Checksum, - Optional<StringRef> Source, - unsigned CUID) { - getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum, - Source); -} - -void MCStreamer::EmitCFIBKeyFrame() { - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->IsBKeyFrame = true; -} - -void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, - unsigned Column, unsigned Flags, - unsigned Isa, - unsigned Discriminator, - StringRef FileName) { - getContext().setCurrentDwarfLoc(FileNo, Line, Column, Flags, Isa, - Discriminator); -} - -MCSymbol *MCStreamer::getDwarfLineTableSymbol(unsigned CUID) { - MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID); - if (!Table.getLabel()) { - StringRef Prefix = Context.getAsmInfo()->getPrivateGlobalPrefix(); - Table.setLabel( - Context.getOrCreateSymbol(Prefix + "line_table_start" + Twine(CUID))); - } - return Table.getLabel(); -} - -bool MCStreamer::hasUnfinishedDwarfFrameInfo() { - return !DwarfFrameInfos.empty() && !DwarfFrameInfos.back().End; -} - -MCDwarfFrameInfo *MCStreamer::getCurrentDwarfFrameInfo() { - if (!hasUnfinishedDwarfFrameInfo()) { - getContext().reportError(SMLoc(), "this directive must appear between " - ".cfi_startproc and .cfi_endproc " - "directives"); - return nullptr; - } - return &DwarfFrameInfos.back(); -} - -bool MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename, - ArrayRef<uint8_t> Checksum, - unsigned ChecksumKind) { - return getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum, - ChecksumKind); -} - -bool MCStreamer::EmitCVFuncIdDirective(unsigned FunctionId) { - return getContext().getCVContext().recordFunctionId(FunctionId); -} - -bool MCStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId, - unsigned IAFunc, unsigned IAFile, - unsigned IALine, unsigned IACol, - SMLoc Loc) { - if (getContext().getCVContext().getCVFunctionInfo(IAFunc) == nullptr) { - getContext().reportError(Loc, "parent function id not introduced by " - ".cv_func_id or .cv_inline_site_id"); - return true; - } - - return getContext().getCVContext().recordInlinedCallSiteId( - FunctionId, IAFunc, IAFile, IALine, IACol); -} - -void MCStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, - unsigned Line, unsigned Column, - bool PrologueEnd, bool IsStmt, - StringRef FileName, SMLoc Loc) {} - -bool MCStreamer::checkCVLocSection(unsigned FuncId, unsigned FileNo, - SMLoc Loc) { - CodeViewContext &CVC = getContext().getCVContext(); - MCCVFunctionInfo *FI = CVC.getCVFunctionInfo(FuncId); - if (!FI) { - getContext().reportError( - Loc, "function id not introduced by .cv_func_id or .cv_inline_site_id"); - return false; - } - - // Track the section - if (FI->Section == nullptr) - FI->Section = getCurrentSectionOnly(); - else if (FI->Section != getCurrentSectionOnly()) { - getContext().reportError( - Loc, - "all .cv_loc directives for a function must be in the same section"); - return false; - } - return true; -} - -void MCStreamer::EmitCVLinetableDirective(unsigned FunctionId, - const MCSymbol *Begin, - const MCSymbol *End) {} - -void MCStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId, - unsigned SourceFileId, - unsigned SourceLineNum, - const MCSymbol *FnStartSym, - const MCSymbol *FnEndSym) {} - -void MCStreamer::EmitCVDefRangeDirective( - ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, - StringRef FixedSizePortion) {} - -void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, - MCSymbol *EHSymbol) { -} - -void MCStreamer::InitSections(bool NoExecStack) { - SwitchSection(getContext().getObjectFileInfo()->getTextSection()); -} - -void MCStreamer::AssignFragment(MCSymbol *Symbol, MCFragment *Fragment) { - assert(Fragment); - Symbol->setFragment(Fragment); - - // As we emit symbols into a section, track the order so that they can - // be sorted upon later. Zero is reserved to mean 'unemitted'. - SymbolOrdering[Symbol] = 1 + SymbolOrdering.size(); -} - -void MCStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) { - Symbol->redefineIfPossible(); - - if (!Symbol->isUndefined() || Symbol->isVariable()) - return getContext().reportError(Loc, "invalid symbol redefinition"); - - assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); - assert(getCurrentSectionOnly() && "Cannot emit before setting section!"); - assert(!Symbol->getFragment() && "Unexpected fragment on symbol data!"); - assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - - Symbol->setFragment(&getCurrentSectionOnly()->getDummyFragment()); - - MCTargetStreamer *TS = getTargetStreamer(); - if (TS) - TS->emitLabel(Symbol); -} - -void MCStreamer::EmitCFISections(bool EH, bool Debug) { - assert(EH || Debug); -} - -void MCStreamer::EmitCFIStartProc(bool IsSimple, SMLoc Loc) { - if (hasUnfinishedDwarfFrameInfo()) - return getContext().reportError( - Loc, "starting new .cfi frame before finishing the previous one"); - - MCDwarfFrameInfo Frame; - Frame.IsSimple = IsSimple; - EmitCFIStartProcImpl(Frame); - - const MCAsmInfo* MAI = Context.getAsmInfo(); - if (MAI) { - for (const MCCFIInstruction& Inst : MAI->getInitialFrameState()) { - if (Inst.getOperation() == MCCFIInstruction::OpDefCfa || - Inst.getOperation() == MCCFIInstruction::OpDefCfaRegister) { - Frame.CurrentCfaRegister = Inst.getRegister(); - } - } - } - - DwarfFrameInfos.push_back(Frame); -} - -void MCStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { -} - -void MCStreamer::EmitCFIEndProc() { - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - EmitCFIEndProcImpl(*CurFrame); -} - -void MCStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { - // Put a dummy non-null value in Frame.End to mark that this frame has been - // closed. - Frame.End = (MCSymbol *)1; -} - -MCSymbol *MCStreamer::EmitCFILabel() { - // Return a dummy non-null value so that label fields appear filled in when - // generating textual assembly. - return (MCSymbol *)1; -} - -void MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { - MCSymbol *Label = EmitCFILabel(); - MCCFIInstruction Instruction = - MCCFIInstruction::createDefCfa(Label, Register, Offset); - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->Instructions.push_back(Instruction); - CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register); -} - -void MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) { - MCSymbol *Label = EmitCFILabel(); - MCCFIInstruction Instruction = - MCCFIInstruction::createDefCfaOffset(Label, Offset); - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->Instructions.push_back(Instruction); -} - -void MCStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) { - MCSymbol *Label = EmitCFILabel(); - MCCFIInstruction Instruction = - MCCFIInstruction::createAdjustCfaOffset(Label, Adjustment); - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->Instructions.push_back(Instruction); -} - -void MCStreamer::EmitCFIDefCfaRegister(int64_t Register) { - MCSymbol *Label = EmitCFILabel(); - MCCFIInstruction Instruction = - MCCFIInstruction::createDefCfaRegister(Label, Register); - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->Instructions.push_back(Instruction); - CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register); -} - -void MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { - MCSymbol *Label = EmitCFILabel(); - MCCFIInstruction Instruction = - MCCFIInstruction::createOffset(Label, Register, Offset); - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->Instructions.push_back(Instruction); -} - -void MCStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) { - MCSymbol *Label = EmitCFILabel(); - MCCFIInstruction Instruction = - MCCFIInstruction::createRelOffset(Label, Register, Offset); - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->Instructions.push_back(Instruction); -} - -void MCStreamer::EmitCFIPersonality(const MCSymbol *Sym, - unsigned Encoding) { - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->Personality = Sym; - CurFrame->PersonalityEncoding = Encoding; -} - -void MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->Lsda = Sym; - CurFrame->LsdaEncoding = Encoding; -} - -void MCStreamer::EmitCFIRememberState() { - MCSymbol *Label = EmitCFILabel(); - MCCFIInstruction Instruction = MCCFIInstruction::createRememberState(Label); - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->Instructions.push_back(Instruction); -} - -void MCStreamer::EmitCFIRestoreState() { - // FIXME: Error if there is no matching cfi_remember_state. - MCSymbol *Label = EmitCFILabel(); - MCCFIInstruction Instruction = MCCFIInstruction::createRestoreState(Label); - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->Instructions.push_back(Instruction); -} - -void MCStreamer::EmitCFISameValue(int64_t Register) { - MCSymbol *Label = EmitCFILabel(); - MCCFIInstruction Instruction = - MCCFIInstruction::createSameValue(Label, Register); - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->Instructions.push_back(Instruction); -} - -void MCStreamer::EmitCFIRestore(int64_t Register) { - MCSymbol *Label = EmitCFILabel(); - MCCFIInstruction Instruction = - MCCFIInstruction::createRestore(Label, Register); - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->Instructions.push_back(Instruction); -} - -void MCStreamer::EmitCFIEscape(StringRef Values) { - MCSymbol *Label = EmitCFILabel(); - MCCFIInstruction Instruction = MCCFIInstruction::createEscape(Label, Values); - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->Instructions.push_back(Instruction); -} - -void MCStreamer::EmitCFIGnuArgsSize(int64_t Size) { - MCSymbol *Label = EmitCFILabel(); - MCCFIInstruction Instruction = - MCCFIInstruction::createGnuArgsSize(Label, Size); - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->Instructions.push_back(Instruction); -} - -void MCStreamer::EmitCFISignalFrame() { - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->IsSignalFrame = true; -} - -void MCStreamer::EmitCFIUndefined(int64_t Register) { - MCSymbol *Label = EmitCFILabel(); - MCCFIInstruction Instruction = - MCCFIInstruction::createUndefined(Label, Register); - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->Instructions.push_back(Instruction); -} - -void MCStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) { - MCSymbol *Label = EmitCFILabel(); - MCCFIInstruction Instruction = - MCCFIInstruction::createRegister(Label, Register1, Register2); - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->Instructions.push_back(Instruction); -} - -void MCStreamer::EmitCFIWindowSave() { - MCSymbol *Label = EmitCFILabel(); - MCCFIInstruction Instruction = - MCCFIInstruction::createWindowSave(Label); - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->Instructions.push_back(Instruction); -} - -void MCStreamer::EmitCFINegateRAState() { - MCSymbol *Label = EmitCFILabel(); - MCCFIInstruction Instruction = MCCFIInstruction::createNegateRAState(Label); - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->Instructions.push_back(Instruction); -} - -void MCStreamer::EmitCFIReturnColumn(int64_t Register) { - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (!CurFrame) - return; - CurFrame->RAReg = Register; -} - -WinEH::FrameInfo *MCStreamer::EnsureValidWinFrameInfo(SMLoc Loc) { - const MCAsmInfo *MAI = Context.getAsmInfo(); - if (!MAI->usesWindowsCFI()) { - getContext().reportError( - Loc, ".seh_* directives are not supported on this target"); - return nullptr; - } - if (!CurrentWinFrameInfo || CurrentWinFrameInfo->End) { - getContext().reportError( - Loc, ".seh_ directive must appear within an active frame"); - return nullptr; - } - return CurrentWinFrameInfo; -} - -void MCStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) { - const MCAsmInfo *MAI = Context.getAsmInfo(); - if (!MAI->usesWindowsCFI()) - return getContext().reportError( - Loc, ".seh_* directives are not supported on this target"); - if (CurrentWinFrameInfo && !CurrentWinFrameInfo->End) - getContext().reportError( - Loc, "Starting a function before ending the previous one!"); - - MCSymbol *StartProc = EmitCFILabel(); - - WinFrameInfos.emplace_back( - llvm::make_unique<WinEH::FrameInfo>(Symbol, StartProc)); - CurrentWinFrameInfo = WinFrameInfos.back().get(); - CurrentWinFrameInfo->TextSection = getCurrentSectionOnly(); -} - -void MCStreamer::EmitWinCFIEndProc(SMLoc Loc) { - WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); - if (!CurFrame) - return; - if (CurFrame->ChainedParent) - getContext().reportError(Loc, "Not all chained regions terminated!"); - - MCSymbol *Label = EmitCFILabel(); - CurFrame->End = Label; -} - -void MCStreamer::EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) { - WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); - if (!CurFrame) - return; - if (CurFrame->ChainedParent) - getContext().reportError(Loc, "Not all chained regions terminated!"); - - MCSymbol *Label = EmitCFILabel(); - CurFrame->FuncletOrFuncEnd = Label; -} - -void MCStreamer::EmitWinCFIStartChained(SMLoc Loc) { - WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); - if (!CurFrame) - return; - - MCSymbol *StartProc = EmitCFILabel(); - - WinFrameInfos.emplace_back(llvm::make_unique<WinEH::FrameInfo>( - CurFrame->Function, StartProc, CurFrame)); - CurrentWinFrameInfo = WinFrameInfos.back().get(); - CurrentWinFrameInfo->TextSection = getCurrentSectionOnly(); -} - -void MCStreamer::EmitWinCFIEndChained(SMLoc Loc) { - WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); - if (!CurFrame) - return; - if (!CurFrame->ChainedParent) - return getContext().reportError( - Loc, "End of a chained region outside a chained region!"); - - MCSymbol *Label = EmitCFILabel(); - - CurFrame->End = Label; - CurrentWinFrameInfo = const_cast<WinEH::FrameInfo *>(CurFrame->ChainedParent); -} - -void MCStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except, - SMLoc Loc) { - WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); - if (!CurFrame) - return; - if (CurFrame->ChainedParent) - return getContext().reportError( - Loc, "Chained unwind areas can't have handlers!"); - CurFrame->ExceptionHandler = Sym; - if (!Except && !Unwind) - getContext().reportError(Loc, "Don't know what kind of handler this is!"); - if (Unwind) - CurFrame->HandlesUnwind = true; - if (Except) - CurFrame->HandlesExceptions = true; -} - -void MCStreamer::EmitWinEHHandlerData(SMLoc Loc) { - WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); - if (!CurFrame) - return; - if (CurFrame->ChainedParent) - getContext().reportError(Loc, "Chained unwind areas can't have handlers!"); -} - -void MCStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From, - const MCSymbolRefExpr *To, uint64_t Count) { -} - -static MCSection *getWinCFISection(MCContext &Context, unsigned *NextWinCFIID, - MCSection *MainCFISec, - const MCSection *TextSec) { - // If this is the main .text section, use the main unwind info section. - if (TextSec == Context.getObjectFileInfo()->getTextSection()) - return MainCFISec; - - const auto *TextSecCOFF = cast<MCSectionCOFF>(TextSec); - auto *MainCFISecCOFF = cast<MCSectionCOFF>(MainCFISec); - unsigned UniqueID = TextSecCOFF->getOrAssignWinCFISectionID(NextWinCFIID); - - // If this section is COMDAT, this unwind section should be COMDAT associative - // with its group. - const MCSymbol *KeySym = nullptr; - if (TextSecCOFF->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) { - KeySym = TextSecCOFF->getCOMDATSymbol(); - - // In a GNU environment, we can't use associative comdats. Instead, do what - // GCC does, which is to make plain comdat selectany section named like - // ".[px]data$_Z3foov". - if (!Context.getAsmInfo()->hasCOFFAssociativeComdats()) { - std::string SectionName = - (MainCFISecCOFF->getSectionName() + "$" + - TextSecCOFF->getSectionName().split('$').second) - .str(); - return Context.getCOFFSection( - SectionName, - MainCFISecCOFF->getCharacteristics() | COFF::IMAGE_SCN_LNK_COMDAT, - MainCFISecCOFF->getKind(), "", COFF::IMAGE_COMDAT_SELECT_ANY); - } - } - - return Context.getAssociativeCOFFSection(MainCFISecCOFF, KeySym, UniqueID); -} - -MCSection *MCStreamer::getAssociatedPDataSection(const MCSection *TextSec) { - return getWinCFISection(getContext(), &NextWinCFIID, - getContext().getObjectFileInfo()->getPDataSection(), - TextSec); -} - -MCSection *MCStreamer::getAssociatedXDataSection(const MCSection *TextSec) { - return getWinCFISection(getContext(), &NextWinCFIID, - getContext().getObjectFileInfo()->getXDataSection(), - TextSec); -} - -void MCStreamer::EmitSyntaxDirective() {} - -void MCStreamer::EmitWinCFIPushReg(unsigned Register, SMLoc Loc) { - WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); - if (!CurFrame) - return; - - MCSymbol *Label = EmitCFILabel(); - - WinEH::Instruction Inst = Win64EH::Instruction::PushNonVol(Label, Register); - CurFrame->Instructions.push_back(Inst); -} - -void MCStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset, - SMLoc Loc) { - WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); - if (!CurFrame) - return; - if (CurFrame->LastFrameInst >= 0) - return getContext().reportError( - Loc, "frame register and offset can be set at most once"); - if (Offset & 0x0F) - return getContext().reportError(Loc, "offset is not a multiple of 16"); - if (Offset > 240) - return getContext().reportError( - Loc, "frame offset must be less than or equal to 240"); - - MCSymbol *Label = EmitCFILabel(); - - WinEH::Instruction Inst = - Win64EH::Instruction::SetFPReg(Label, Register, Offset); - CurFrame->LastFrameInst = CurFrame->Instructions.size(); - CurFrame->Instructions.push_back(Inst); -} - -void MCStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) { - WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); - if (!CurFrame) - return; - if (Size == 0) - return getContext().reportError(Loc, - "stack allocation size must be non-zero"); - if (Size & 7) - return getContext().reportError( - Loc, "stack allocation size is not a multiple of 8"); - - MCSymbol *Label = EmitCFILabel(); - - WinEH::Instruction Inst = Win64EH::Instruction::Alloc(Label, Size); - CurFrame->Instructions.push_back(Inst); -} - -void MCStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset, - SMLoc Loc) { - WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); - if (!CurFrame) - return; - - if (Offset & 7) - return getContext().reportError( - Loc, "register save offset is not 8 byte aligned"); - - MCSymbol *Label = EmitCFILabel(); - - WinEH::Instruction Inst = - Win64EH::Instruction::SaveNonVol(Label, Register, Offset); - CurFrame->Instructions.push_back(Inst); -} - -void MCStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset, - SMLoc Loc) { - WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); - if (!CurFrame) - return; - if (Offset & 0x0F) - return getContext().reportError(Loc, "offset is not a multiple of 16"); - - MCSymbol *Label = EmitCFILabel(); - - WinEH::Instruction Inst = - Win64EH::Instruction::SaveXMM(Label, Register, Offset); - CurFrame->Instructions.push_back(Inst); -} - -void MCStreamer::EmitWinCFIPushFrame(bool Code, SMLoc Loc) { - WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); - if (!CurFrame) - return; - if (!CurFrame->Instructions.empty()) - return getContext().reportError( - Loc, "If present, PushMachFrame must be the first UOP"); - - MCSymbol *Label = EmitCFILabel(); - - WinEH::Instruction Inst = Win64EH::Instruction::PushMachFrame(Label, Code); - CurFrame->Instructions.push_back(Inst); -} - -void MCStreamer::EmitWinCFIEndProlog(SMLoc Loc) { - WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); - if (!CurFrame) - return; - - MCSymbol *Label = EmitCFILabel(); - - CurFrame->PrologEnd = Label; -} - -void MCStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {} - -void MCStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {} - -void MCStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {} - -void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {} - -void MCStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {} - -/// EmitRawText - If this file is backed by an assembly streamer, this dumps -/// the specified string in the output .s file. This capability is -/// indicated by the hasRawTextSupport() predicate. -void MCStreamer::EmitRawTextImpl(StringRef String) { - // This is not llvm_unreachable for the sake of out of tree backend - // developers who may not have assembly streamers and should serve as a - // reminder to not accidentally call EmitRawText in the absence of such. - report_fatal_error("EmitRawText called on an MCStreamer that doesn't support " - "it (target backend is likely missing an AsmStreamer " - "implementation)"); -} - -void MCStreamer::EmitRawText(const Twine &T) { - SmallString<128> Str; - EmitRawTextImpl(T.toStringRef(Str)); -} - -void MCStreamer::EmitWindowsUnwindTables() { -} - -void MCStreamer::Finish() { - if ((!DwarfFrameInfos.empty() && !DwarfFrameInfos.back().End) || - (!WinFrameInfos.empty() && !WinFrameInfos.back()->End)) { - getContext().reportError(SMLoc(), "Unfinished frame!"); - return; - } - - MCTargetStreamer *TS = getTargetStreamer(); - if (TS) - TS->finish(); - - FinishImpl(); -} - -void MCStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { - visitUsedExpr(*Value); - Symbol->setVariableValue(Value); - - MCTargetStreamer *TS = getTargetStreamer(); - if (TS) - TS->emitAssignment(Symbol, Value); -} - -void MCTargetStreamer::prettyPrintAsm(MCInstPrinter &InstPrinter, - raw_ostream &OS, const MCInst &Inst, - const MCSubtargetInfo &STI) { - InstPrinter.printInst(&Inst, OS, "", STI); -} - -void MCStreamer::visitUsedSymbol(const MCSymbol &Sym) { -} - -void MCStreamer::visitUsedExpr(const MCExpr &Expr) { - switch (Expr.getKind()) { - case MCExpr::Target: - cast<MCTargetExpr>(Expr).visitUsedExpr(*this); - break; - - case MCExpr::Constant: - break; - - case MCExpr::Binary: { - const MCBinaryExpr &BE = cast<MCBinaryExpr>(Expr); - visitUsedExpr(*BE.getLHS()); - visitUsedExpr(*BE.getRHS()); - break; - } - - case MCExpr::SymbolRef: - visitUsedSymbol(cast<MCSymbolRefExpr>(Expr).getSymbol()); - break; - - case MCExpr::Unary: - visitUsedExpr(*cast<MCUnaryExpr>(Expr).getSubExpr()); - break; - } -} - -void MCStreamer::EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &) { - // Scan for values. - for (unsigned i = Inst.getNumOperands(); i--;) - if (Inst.getOperand(i).isExpr()) - visitUsedExpr(*Inst.getOperand(i).getExpr()); -} - -void MCStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, - unsigned Size) { - // Get the Hi-Lo expression. - const MCExpr *Diff = - MCBinaryExpr::createSub(MCSymbolRefExpr::create(Hi, Context), - MCSymbolRefExpr::create(Lo, Context), Context); - - const MCAsmInfo *MAI = Context.getAsmInfo(); - if (!MAI->doesSetDirectiveSuppressReloc()) { - EmitValue(Diff, Size); - return; - } - - // Otherwise, emit with .set (aka assignment). - MCSymbol *SetLabel = Context.createTempSymbol("set", true); - EmitAssignment(SetLabel, Diff); - EmitSymbolValue(SetLabel, Size); -} - -void MCStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi, - const MCSymbol *Lo) { - // Get the Hi-Lo expression. - const MCExpr *Diff = - MCBinaryExpr::createSub(MCSymbolRefExpr::create(Hi, Context), - MCSymbolRefExpr::create(Lo, Context), Context); - - EmitULEB128Value(Diff); -} - -void MCStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {} -void MCStreamer::EmitThumbFunc(MCSymbol *Func) {} -void MCStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {} -void MCStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) { - llvm_unreachable("this directive only supported on COFF targets"); -} -void MCStreamer::EndCOFFSymbolDef() { - llvm_unreachable("this directive only supported on COFF targets"); -} -void MCStreamer::EmitFileDirective(StringRef Filename) {} -void MCStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { - llvm_unreachable("this directive only supported on COFF targets"); -} -void MCStreamer::EmitCOFFSymbolType(int Type) { - llvm_unreachable("this directive only supported on COFF targets"); -} -void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {} -void MCStreamer::emitELFSymverDirective(StringRef AliasName, - const MCSymbol *Aliasee) {} -void MCStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) {} -void MCStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment) {} -void MCStreamer::ChangeSection(MCSection *, const MCExpr *) {} -void MCStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {} -void MCStreamer::EmitBytes(StringRef Data) {} -void MCStreamer::EmitBinaryData(StringRef Data) { EmitBytes(Data); } -void MCStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) { - visitUsedExpr(*Value); -} -void MCStreamer::EmitULEB128Value(const MCExpr *Value) {} -void MCStreamer::EmitSLEB128Value(const MCExpr *Value) {} -void MCStreamer::emitFill(const MCExpr &NumBytes, uint64_t Value, SMLoc Loc) {} -void MCStreamer::emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr, - SMLoc Loc) {} -void MCStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, - unsigned ValueSize, - unsigned MaxBytesToEmit) {} -void MCStreamer::EmitCodeAlignment(unsigned ByteAlignment, - unsigned MaxBytesToEmit) {} -void MCStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value, - SMLoc Loc) {} -void MCStreamer::EmitBundleAlignMode(unsigned AlignPow2) {} -void MCStreamer::EmitBundleLock(bool AlignToEnd) {} -void MCStreamer::FinishImpl() {} -void MCStreamer::EmitBundleUnlock() {} - -void MCStreamer::SwitchSection(MCSection *Section, const MCExpr *Subsection) { - assert(Section && "Cannot switch to a null section!"); - MCSectionSubPair curSection = SectionStack.back().first; - SectionStack.back().second = curSection; - if (MCSectionSubPair(Section, Subsection) != curSection) { - ChangeSection(Section, Subsection); - SectionStack.back().first = MCSectionSubPair(Section, Subsection); - assert(!Section->hasEnded() && "Section already ended"); - MCSymbol *Sym = Section->getBeginSymbol(); - if (Sym && !Sym->isInSection()) - EmitLabel(Sym); - } -} - -MCSymbol *MCStreamer::endSection(MCSection *Section) { - // TODO: keep track of the last subsection so that this symbol appears in the - // correct place. - MCSymbol *Sym = Section->getEndSymbol(Context); - if (Sym->isInSection()) - return Sym; - - SwitchSection(Section); - EmitLabel(Sym); - return Sym; -} - -void MCStreamer::EmitVersionForTarget(const Triple &Target, - const VersionTuple &SDKVersion) { - if (!Target.isOSBinFormatMachO() || !Target.isOSDarwin()) - return; - // Do we even know the version? - if (Target.getOSMajorVersion() == 0) - return; - - unsigned Major; - unsigned Minor; - unsigned Update; - if (Target.isMacCatalystEnvironment()) { - // Mac Catalyst always uses the build version load command. - Target.getiOSVersion(Major, Minor, Update); - assert(Major && "A non-zero major version is expected"); - EmitBuildVersion(MachO::PLATFORM_MACCATALYST, Major, Minor, Update, - SDKVersion); - return; - } - - MCVersionMinType VersionType; - if (Target.isWatchOS()) { - VersionType = MCVM_WatchOSVersionMin; - Target.getWatchOSVersion(Major, Minor, Update); - } else if (Target.isTvOS()) { - VersionType = MCVM_TvOSVersionMin; - Target.getiOSVersion(Major, Minor, Update); - } else if (Target.isMacOSX()) { - VersionType = MCVM_OSXVersionMin; - if (!Target.getMacOSXVersion(Major, Minor, Update)) - Major = 0; - } else { - VersionType = MCVM_IOSVersionMin; - Target.getiOSVersion(Major, Minor, Update); - } - if (Major != 0) - EmitVersionMin(VersionType, Major, Minor, Update, SDKVersion); -} diff --git a/contrib/llvm/lib/MC/MCSubtargetInfo.cpp b/contrib/llvm/lib/MC/MCSubtargetInfo.cpp deleted file mode 100644 index 5fd48d9e1010..000000000000 --- a/contrib/llvm/lib/MC/MCSubtargetInfo.cpp +++ /dev/null @@ -1,317 +0,0 @@ -//===- MCSubtargetInfo.cpp - Subtarget Information ------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/MC/MCInstrItineraries.h" -#include "llvm/MC/MCSchedule.h" -#include "llvm/MC/SubtargetFeature.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cassert> -#include <cstring> - -using namespace llvm; - -/// Find KV in array using binary search. -template <typename T> -static const T *Find(StringRef S, ArrayRef<T> A) { - // Binary search the array - auto F = llvm::lower_bound(A, S); - // If not found then return NULL - if (F == A.end() || StringRef(F->Key) != S) return nullptr; - // Return the found array item - return F; -} - -/// For each feature that is (transitively) implied by this feature, set it. -static -void SetImpliedBits(FeatureBitset &Bits, const FeatureBitset &Implies, - ArrayRef<SubtargetFeatureKV> FeatureTable) { - // OR the Implies bits in outside the loop. This allows the Implies for CPUs - // which might imply features not in FeatureTable to use this. - Bits |= Implies; - for (const SubtargetFeatureKV &FE : FeatureTable) - if (Implies.test(FE.Value)) - SetImpliedBits(Bits, FE.Implies.getAsBitset(), FeatureTable); -} - -/// For each feature that (transitively) implies this feature, clear it. -static -void ClearImpliedBits(FeatureBitset &Bits, unsigned Value, - ArrayRef<SubtargetFeatureKV> FeatureTable) { - for (const SubtargetFeatureKV &FE : FeatureTable) { - if (FE.Implies.getAsBitset().test(Value)) { - Bits.reset(FE.Value); - ClearImpliedBits(Bits, FE.Value, FeatureTable); - } - } -} - -static void ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature, - ArrayRef<SubtargetFeatureKV> FeatureTable) { - assert(SubtargetFeatures::hasFlag(Feature) && - "Feature flags should start with '+' or '-'"); - - // Find feature in table. - const SubtargetFeatureKV *FeatureEntry = - Find(SubtargetFeatures::StripFlag(Feature), FeatureTable); - // If there is a match - if (FeatureEntry) { - // Enable/disable feature in bits - if (SubtargetFeatures::isEnabled(Feature)) { - Bits.set(FeatureEntry->Value); - - // For each feature that this implies, set it. - SetImpliedBits(Bits, FeatureEntry->Implies.getAsBitset(), FeatureTable); - } else { - Bits.reset(FeatureEntry->Value); - - // For each feature that implies this, clear it. - ClearImpliedBits(Bits, FeatureEntry->Value, FeatureTable); - } - } else { - errs() << "'" << Feature << "' is not a recognized feature for this target" - << " (ignoring feature)\n"; - } -} - -/// Return the length of the longest entry in the table. -template <typename T> -static size_t getLongestEntryLength(ArrayRef<T> Table) { - size_t MaxLen = 0; - for (auto &I : Table) - MaxLen = std::max(MaxLen, std::strlen(I.Key)); - return MaxLen; -} - -/// Display help for feature and mcpu choices. -static void Help(ArrayRef<SubtargetSubTypeKV> CPUTable, - ArrayRef<SubtargetFeatureKV> FeatTable) { - // the static variable ensures that the help information only gets - // printed once even though a target machine creates multiple subtargets - static bool PrintOnce = false; - if (PrintOnce) { - return; - } - - // Determine the length of the longest CPU and Feature entries. - unsigned MaxCPULen = getLongestEntryLength(CPUTable); - unsigned MaxFeatLen = getLongestEntryLength(FeatTable); - - // Print the CPU table. - errs() << "Available CPUs for this target:\n\n"; - for (auto &CPU : CPUTable) - errs() << format(" %-*s - Select the %s processor.\n", MaxCPULen, CPU.Key, - CPU.Key); - errs() << '\n'; - - // Print the Feature table. - errs() << "Available features for this target:\n\n"; - for (auto &Feature : FeatTable) - errs() << format(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc); - errs() << '\n'; - - errs() << "Use +feature to enable a feature, or -feature to disable it.\n" - "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n"; - - PrintOnce = true; -} - -/// Display help for mcpu choices only -static void cpuHelp(ArrayRef<SubtargetSubTypeKV> CPUTable) { - // the static variable ensures that the help information only gets - // printed once even though a target machine creates multiple subtargets - static bool PrintOnce = false; - if (PrintOnce) { - return; - } - - // Print the CPU table. - errs() << "Available CPUs for this target:\n\n"; - for (auto &CPU : CPUTable) - errs() << "\t" << CPU.Key << "\n"; - errs() << '\n'; - - errs() << "Use -mcpu or -mtune to specify the target's processor.\n" - "For example, clang --target=aarch64-unknown-linux-gui " - "-mcpu=cortex-a35\n"; - - PrintOnce = true; -} - -static FeatureBitset getFeatures(StringRef CPU, StringRef FS, - ArrayRef<SubtargetSubTypeKV> ProcDesc, - ArrayRef<SubtargetFeatureKV> ProcFeatures) { - SubtargetFeatures Features(FS); - - if (ProcDesc.empty() || ProcFeatures.empty()) - return FeatureBitset(); - - assert(std::is_sorted(std::begin(ProcDesc), std::end(ProcDesc)) && - "CPU table is not sorted"); - assert(std::is_sorted(std::begin(ProcFeatures), std::end(ProcFeatures)) && - "CPU features table is not sorted"); - // Resulting bits - FeatureBitset Bits; - - // Check if help is needed - if (CPU == "help") - Help(ProcDesc, ProcFeatures); - - // Find CPU entry if CPU name is specified. - else if (!CPU.empty()) { - const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc); - - // If there is a match - if (CPUEntry) { - // Set the features implied by this CPU feature, if any. - SetImpliedBits(Bits, CPUEntry->Implies.getAsBitset(), ProcFeatures); - } else { - errs() << "'" << CPU << "' is not a recognized processor for this target" - << " (ignoring processor)\n"; - } - } - - // Iterate through each feature - for (const std::string &Feature : Features.getFeatures()) { - // Check for help - if (Feature == "+help") - Help(ProcDesc, ProcFeatures); - else if (Feature == "+cpuHelp") - cpuHelp(ProcDesc); - else - ApplyFeatureFlag(Bits, Feature, ProcFeatures); - } - - return Bits; -} - -void MCSubtargetInfo::InitMCProcessorInfo(StringRef CPU, StringRef FS) { - FeatureBits = getFeatures(CPU, FS, ProcDesc, ProcFeatures); - if (!CPU.empty()) - CPUSchedModel = &getSchedModelForCPU(CPU); - else - CPUSchedModel = &MCSchedModel::GetDefaultSchedModel(); -} - -void MCSubtargetInfo::setDefaultFeatures(StringRef CPU, StringRef FS) { - FeatureBits = getFeatures(CPU, FS, ProcDesc, ProcFeatures); -} - -MCSubtargetInfo::MCSubtargetInfo( - const Triple &TT, StringRef C, StringRef FS, - ArrayRef<SubtargetFeatureKV> PF, ArrayRef<SubtargetSubTypeKV> PD, - const MCWriteProcResEntry *WPR, - const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA, - const InstrStage *IS, const unsigned *OC, const unsigned *FP) - : TargetTriple(TT), CPU(C), ProcFeatures(PF), ProcDesc(PD), - WriteProcResTable(WPR), WriteLatencyTable(WL), - ReadAdvanceTable(RA), Stages(IS), OperandCycles(OC), ForwardingPaths(FP) { - InitMCProcessorInfo(CPU, FS); -} - -FeatureBitset MCSubtargetInfo::ToggleFeature(uint64_t FB) { - FeatureBits.flip(FB); - return FeatureBits; -} - -FeatureBitset MCSubtargetInfo::ToggleFeature(const FeatureBitset &FB) { - FeatureBits ^= FB; - return FeatureBits; -} - -FeatureBitset MCSubtargetInfo::SetFeatureBitsTransitively( - const FeatureBitset &FB) { - SetImpliedBits(FeatureBits, FB, ProcFeatures); - return FeatureBits; -} - -FeatureBitset MCSubtargetInfo::ClearFeatureBitsTransitively( - const FeatureBitset &FB) { - for (unsigned I = 0, E = FB.size(); I < E; I++) { - if (FB[I]) { - FeatureBits.reset(I); - ClearImpliedBits(FeatureBits, I, ProcFeatures); - } - } - return FeatureBits; -} - -FeatureBitset MCSubtargetInfo::ToggleFeature(StringRef Feature) { - // Find feature in table. - const SubtargetFeatureKV *FeatureEntry = - Find(SubtargetFeatures::StripFlag(Feature), ProcFeatures); - // If there is a match - if (FeatureEntry) { - if (FeatureBits.test(FeatureEntry->Value)) { - FeatureBits.reset(FeatureEntry->Value); - // For each feature that implies this, clear it. - ClearImpliedBits(FeatureBits, FeatureEntry->Value, ProcFeatures); - } else { - FeatureBits.set(FeatureEntry->Value); - - // For each feature that this implies, set it. - SetImpliedBits(FeatureBits, FeatureEntry->Implies.getAsBitset(), - ProcFeatures); - } - } else { - errs() << "'" << Feature << "' is not a recognized feature for this target" - << " (ignoring feature)\n"; - } - - return FeatureBits; -} - -FeatureBitset MCSubtargetInfo::ApplyFeatureFlag(StringRef FS) { - ::ApplyFeatureFlag(FeatureBits, FS, ProcFeatures); - return FeatureBits; -} - -bool MCSubtargetInfo::checkFeatures(StringRef FS) const { - SubtargetFeatures T(FS); - FeatureBitset Set, All; - for (std::string F : T.getFeatures()) { - ::ApplyFeatureFlag(Set, F, ProcFeatures); - if (F[0] == '-') - F[0] = '+'; - ::ApplyFeatureFlag(All, F, ProcFeatures); - } - return (FeatureBits & All) == Set; -} - -const MCSchedModel &MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const { - assert(std::is_sorted(ProcDesc.begin(), ProcDesc.end()) && - "Processor machine model table is not sorted"); - - // Find entry - const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc); - - if (!CPUEntry) { - if (CPU != "help") // Don't error if the user asked for help. - errs() << "'" << CPU - << "' is not a recognized processor for this target" - << " (ignoring processor)\n"; - return MCSchedModel::GetDefaultSchedModel(); - } - assert(CPUEntry->SchedModel && "Missing processor SchedModel value"); - return *CPUEntry->SchedModel; -} - -InstrItineraryData -MCSubtargetInfo::getInstrItineraryForCPU(StringRef CPU) const { - const MCSchedModel &SchedModel = getSchedModelForCPU(CPU); - return InstrItineraryData(SchedModel, Stages, OperandCycles, ForwardingPaths); -} - -void MCSubtargetInfo::initInstrItins(InstrItineraryData &InstrItins) const { - InstrItins = InstrItineraryData(getSchedModel(), Stages, OperandCycles, - ForwardingPaths); -} diff --git a/contrib/llvm/lib/MC/MCSymbol.cpp b/contrib/llvm/lib/MC/MCSymbol.cpp deleted file mode 100644 index 67cab9a92722..000000000000 --- a/contrib/llvm/lib/MC/MCSymbol.cpp +++ /dev/null @@ -1,88 +0,0 @@ -//===- lib/MC/MCSymbol.cpp - MCSymbol implementation ----------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCSymbol.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Config/llvm-config.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFragment.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> -#include <cstddef> - -using namespace llvm; - -// Only the address of this fragment is ever actually used. -static MCDummyFragment SentinelFragment(nullptr); - -// Sentinel value for the absolute pseudo fragment. -MCFragment *MCSymbol::AbsolutePseudoFragment = &SentinelFragment; - -void *MCSymbol::operator new(size_t s, const StringMapEntry<bool> *Name, - MCContext &Ctx) { - // We may need more space for a Name to account for alignment. So allocate - // space for the storage type and not the name pointer. - size_t Size = s + (Name ? sizeof(NameEntryStorageTy) : 0); - - // For safety, ensure that the alignment of a pointer is enough for an - // MCSymbol. This also ensures we don't need padding between the name and - // symbol. - static_assert((unsigned)alignof(MCSymbol) <= alignof(NameEntryStorageTy), - "Bad alignment of MCSymbol"); - void *Storage = Ctx.allocate(Size, alignof(NameEntryStorageTy)); - NameEntryStorageTy *Start = static_cast<NameEntryStorageTy*>(Storage); - NameEntryStorageTy *End = Start + (Name ? 1 : 0); - return End; -} - -void MCSymbol::setVariableValue(const MCExpr *Value) { - assert(!IsUsed && "Cannot set a variable that has already been used."); - assert(Value && "Invalid variable value!"); - assert((SymbolContents == SymContentsUnset || - SymbolContents == SymContentsVariable) && - "Cannot give common/offset symbol a variable value"); - this->Value = Value; - SymbolContents = SymContentsVariable; - setUndefined(); -} - -void MCSymbol::print(raw_ostream &OS, const MCAsmInfo *MAI) const { - // The name for this MCSymbol is required to be a valid target name. However, - // some targets support quoting names with funny characters. If the name - // contains a funny character, then print it quoted. - StringRef Name = getName(); - if (!MAI || MAI->isValidUnquotedName(Name)) { - OS << Name; - return; - } - - if (MAI && !MAI->supportsNameQuoting()) - report_fatal_error("Symbol name with unsupported characters"); - - OS << '"'; - for (char C : Name) { - if (C == '\n') - OS << "\\n"; - else if (C == '"') - OS << "\\\""; - else - OS << C; - } - OS << '"'; -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -LLVM_DUMP_METHOD void MCSymbol::dump() const { - dbgs() << *this; -} -#endif diff --git a/contrib/llvm/lib/MC/MCSymbolELF.cpp b/contrib/llvm/lib/MC/MCSymbolELF.cpp deleted file mode 100644 index a07c56c64f84..000000000000 --- a/contrib/llvm/lib/MC/MCSymbolELF.cpp +++ /dev/null @@ -1,201 +0,0 @@ -//===- lib/MC/MCSymbolELF.cpp ---------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCSymbolELF.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/MC/MCFixupKindInfo.h" - -namespace llvm { - -namespace { -enum { - // Shift value for STT_* flags. 7 possible values. 3 bits. - ELF_STT_Shift = 0, - - // Shift value for STB_* flags. 4 possible values, 2 bits. - ELF_STB_Shift = 3, - - // Shift value for STV_* flags. 4 possible values, 2 bits. - ELF_STV_Shift = 5, - - // Shift value for STO_* flags. 3 bits. All the values are between 0x20 and - // 0xe0, so we shift right by 5 before storing. - ELF_STO_Shift = 7, - - // One bit. - ELF_IsSignature_Shift = 10, - - // One bit. - ELF_WeakrefUsedInReloc_Shift = 11, - - // One bit. - ELF_BindingSet_Shift = 12 -}; -} - -void MCSymbolELF::setBinding(unsigned Binding) const { - setIsBindingSet(); - if (getType() == ELF::STT_SECTION && Binding != ELF::STB_LOCAL) - setType(ELF::STT_NOTYPE); - unsigned Val; - switch (Binding) { - default: - llvm_unreachable("Unsupported Binding"); - case ELF::STB_LOCAL: - Val = 0; - break; - case ELF::STB_GLOBAL: - Val = 1; - break; - case ELF::STB_WEAK: - Val = 2; - break; - case ELF::STB_GNU_UNIQUE: - Val = 3; - break; - } - uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STB_Shift); - setFlags(OtherFlags | (Val << ELF_STB_Shift)); -} - -unsigned MCSymbolELF::getBinding() const { - if (isBindingSet()) { - uint32_t Val = (Flags >> ELF_STB_Shift) & 3; - switch (Val) { - default: - llvm_unreachable("Invalid value"); - case 0: - return ELF::STB_LOCAL; - case 1: - return ELF::STB_GLOBAL; - case 2: - return ELF::STB_WEAK; - case 3: - return ELF::STB_GNU_UNIQUE; - } - } - - if (isDefined()) - return ELF::STB_LOCAL; - if (isUsedInReloc()) - return ELF::STB_GLOBAL; - if (isWeakrefUsedInReloc()) - return ELF::STB_WEAK; - if (isSignature()) - return ELF::STB_LOCAL; - return ELF::STB_GLOBAL; -} - -void MCSymbolELF::setType(unsigned Type) const { - unsigned Val; - if (Type == ELF::STT_SECTION && getBinding() != ELF::STB_LOCAL) - return; - switch (Type) { - default: - llvm_unreachable("Unsupported Binding"); - case ELF::STT_NOTYPE: - Val = 0; - break; - case ELF::STT_OBJECT: - Val = 1; - break; - case ELF::STT_FUNC: - Val = 2; - break; - case ELF::STT_SECTION: - Val = 3; - break; - case ELF::STT_COMMON: - Val = 4; - break; - case ELF::STT_TLS: - Val = 5; - break; - case ELF::STT_GNU_IFUNC: - Val = 6; - break; - } - uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STT_Shift); - setFlags(OtherFlags | (Val << ELF_STT_Shift)); -} - -unsigned MCSymbolELF::getType() const { - uint32_t Val = (Flags >> ELF_STT_Shift) & 7; - switch (Val) { - default: - llvm_unreachable("Invalid value"); - case 0: - return ELF::STT_NOTYPE; - case 1: - return ELF::STT_OBJECT; - case 2: - return ELF::STT_FUNC; - case 3: - return ELF::STT_SECTION; - case 4: - return ELF::STT_COMMON; - case 5: - return ELF::STT_TLS; - case 6: - return ELF::STT_GNU_IFUNC; - } -} - -void MCSymbolELF::setVisibility(unsigned Visibility) { - assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL || - Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED); - - uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STV_Shift); - setFlags(OtherFlags | (Visibility << ELF_STV_Shift)); -} - -unsigned MCSymbolELF::getVisibility() const { - unsigned Visibility = (Flags >> ELF_STV_Shift) & 3; - return Visibility; -} - -void MCSymbolELF::setOther(unsigned Other) { - assert((Other & 0x1f) == 0); - Other >>= 5; - assert(Other <= 0x7); - uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STO_Shift); - setFlags(OtherFlags | (Other << ELF_STO_Shift)); -} - -unsigned MCSymbolELF::getOther() const { - unsigned Other = (Flags >> ELF_STO_Shift) & 7; - return Other << 5; -} - -void MCSymbolELF::setIsWeakrefUsedInReloc() const { - uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_WeakrefUsedInReloc_Shift); - setFlags(OtherFlags | (1 << ELF_WeakrefUsedInReloc_Shift)); -} - -bool MCSymbolELF::isWeakrefUsedInReloc() const { - return getFlags() & (0x1 << ELF_WeakrefUsedInReloc_Shift); -} - -void MCSymbolELF::setIsSignature() const { - uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_IsSignature_Shift); - setFlags(OtherFlags | (1 << ELF_IsSignature_Shift)); -} - -bool MCSymbolELF::isSignature() const { - return getFlags() & (0x1 << ELF_IsSignature_Shift); -} - -void MCSymbolELF::setIsBindingSet() const { - uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_BindingSet_Shift); - setFlags(OtherFlags | (1 << ELF_BindingSet_Shift)); -} - -bool MCSymbolELF::isBindingSet() const { - return getFlags() & (0x1 << ELF_BindingSet_Shift); -} -} diff --git a/contrib/llvm/lib/MC/MCTargetOptions.cpp b/contrib/llvm/lib/MC/MCTargetOptions.cpp deleted file mode 100644 index 96bb094134fe..000000000000 --- a/contrib/llvm/lib/MC/MCTargetOptions.cpp +++ /dev/null @@ -1,23 +0,0 @@ -//===- lib/MC/MCTargetOptions.cpp - MC Target Options ---------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCTargetOptions.h" -#include "llvm/ADT/StringRef.h" - -using namespace llvm; - -MCTargetOptions::MCTargetOptions() - : MCRelaxAll(false), MCNoExecStack(false), MCFatalWarnings(false), - MCNoWarn(false), MCNoDeprecatedWarn(false), MCSaveTempLabels(false), - MCUseDwarfDirectory(false), MCIncrementalLinkerCompatible(false), - MCPIECopyRelocations(false), ShowMCEncoding(false), ShowMCInst(false), - AsmVerbose(false), PreserveAsmComments(true) {} - -StringRef MCTargetOptions::getABIName() const { - return ABIName; -} diff --git a/contrib/llvm/lib/MC/MCValue.cpp b/contrib/llvm/lib/MC/MCValue.cpp deleted file mode 100644 index 81da47b2eced..000000000000 --- a/contrib/llvm/lib/MC/MCValue.cpp +++ /dev/null @@ -1,61 +0,0 @@ -//===- lib/MC/MCValue.cpp - MCValue implementation ------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCValue.h" -#include "llvm/Config/llvm-config.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -void MCValue::print(raw_ostream &OS) const { - if (isAbsolute()) { - OS << getConstant(); - return; - } - - // FIXME: prints as a number, which isn't ideal. But the meaning will be - // target-specific anyway. - if (getRefKind()) - OS << ':' << getRefKind() << ':'; - - OS << *getSymA(); - - if (getSymB()) { - OS << " - "; - OS << *getSymB(); - } - - if (getConstant()) - OS << " + " << getConstant(); -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -LLVM_DUMP_METHOD void MCValue::dump() const { - print(dbgs()); -} -#endif - -MCSymbolRefExpr::VariantKind MCValue::getAccessVariant() const { - const MCSymbolRefExpr *B = getSymB(); - if (B) { - if (B->getKind() != MCSymbolRefExpr::VK_None) - llvm_unreachable("unsupported"); - } - - const MCSymbolRefExpr *A = getSymA(); - if (!A) - return MCSymbolRefExpr::VK_None; - - MCSymbolRefExpr::VariantKind Kind = A->getKind(); - if (Kind == MCSymbolRefExpr::VK_WEAKREF) - return MCSymbolRefExpr::VK_None; - return Kind; -} diff --git a/contrib/llvm/lib/MC/MCWasmObjectTargetWriter.cpp b/contrib/llvm/lib/MC/MCWasmObjectTargetWriter.cpp deleted file mode 100644 index e46257823e34..000000000000 --- a/contrib/llvm/lib/MC/MCWasmObjectTargetWriter.cpp +++ /dev/null @@ -1,17 +0,0 @@ -//===-- MCWasmObjectTargetWriter.cpp - Wasm Target Writer Subclass --------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCWasmObjectWriter.h" - -using namespace llvm; - -MCWasmObjectTargetWriter::MCWasmObjectTargetWriter(bool Is64Bit) - : Is64Bit(Is64Bit) {} - -// Pin the vtable to this object file -MCWasmObjectTargetWriter::~MCWasmObjectTargetWriter() = default; diff --git a/contrib/llvm/lib/MC/MCWasmStreamer.cpp b/contrib/llvm/lib/MC/MCWasmStreamer.cpp deleted file mode 100644 index 86fa72197855..000000000000 --- a/contrib/llvm/lib/MC/MCWasmStreamer.cpp +++ /dev/null @@ -1,229 +0,0 @@ -//===- lib/MC/MCWasmStreamer.cpp - Wasm Object Output ---------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file assembles .s files and emits Wasm .o object files. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCWasmStreamer.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCAsmLayout.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCCodeEmitter.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCObjectStreamer.h" -#include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSectionWasm.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCSymbolWasm.h" -#include "llvm/MC/MCValue.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -MCWasmStreamer::~MCWasmStreamer() = default; // anchor. - -void MCWasmStreamer::mergeFragment(MCDataFragment *DF, MCDataFragment *EF) { - flushPendingLabels(DF, DF->getContents().size()); - - for (unsigned I = 0, E = EF->getFixups().size(); I != E; ++I) { - EF->getFixups()[I].setOffset(EF->getFixups()[I].getOffset() + - DF->getContents().size()); - DF->getFixups().push_back(EF->getFixups()[I]); - } - if (DF->getSubtargetInfo() == nullptr && EF->getSubtargetInfo()) - DF->setHasInstructions(*EF->getSubtargetInfo()); - DF->getContents().append(EF->getContents().begin(), EF->getContents().end()); -} - -void MCWasmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { - // Let the target do whatever target specific stuff it needs to do. - getAssembler().getBackend().handleAssemblerFlag(Flag); - - // Do any generic stuff we need to do. - llvm_unreachable("invalid assembler flag!"); -} - -void MCWasmStreamer::ChangeSection(MCSection *Section, - const MCExpr *Subsection) { - MCAssembler &Asm = getAssembler(); - auto *SectionWasm = cast<MCSectionWasm>(Section); - const MCSymbol *Grp = SectionWasm->getGroup(); - if (Grp) - Asm.registerSymbol(*Grp); - - this->MCObjectStreamer::ChangeSection(Section, Subsection); - Asm.registerSymbol(*Section->getBeginSymbol()); -} - -void MCWasmStreamer::EmitWeakReference(MCSymbol *Alias, - const MCSymbol *Symbol) { - getAssembler().registerSymbol(*Symbol); - const MCExpr *Value = MCSymbolRefExpr::create( - Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext()); - Alias->setVariableValue(Value); -} - -bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) { - assert(Attribute != MCSA_IndirectSymbol && "indirect symbols not supported"); - - auto *Symbol = cast<MCSymbolWasm>(S); - - // Adding a symbol attribute always introduces the symbol; note that an - // important side effect of calling registerSymbol here is to register the - // symbol with the assembler. - getAssembler().registerSymbol(*Symbol); - - switch (Attribute) { - case MCSA_LazyReference: - case MCSA_Reference: - case MCSA_SymbolResolver: - case MCSA_PrivateExtern: - case MCSA_WeakDefinition: - case MCSA_WeakDefAutoPrivate: - case MCSA_Invalid: - case MCSA_IndirectSymbol: - case MCSA_Protected: - return false; - - case MCSA_Hidden: - Symbol->setHidden(true); - break; - - case MCSA_Weak: - case MCSA_WeakReference: - Symbol->setWeak(true); - Symbol->setExternal(true); - break; - - case MCSA_Global: - Symbol->setExternal(true); - break; - - case MCSA_ELF_TypeFunction: - Symbol->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); - break; - - case MCSA_ELF_TypeObject: - case MCSA_Cold: - break; - - case MCSA_NoDeadStrip: - Symbol->setExported(); - break; - - default: - // unrecognized directive - llvm_unreachable("unexpected MCSymbolAttr"); - return false; - } - - return true; -} - -void MCWasmStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size, - unsigned ByteAlignment) { - llvm_unreachable("Common symbols are not yet implemented for Wasm"); -} - -void MCWasmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) { - cast<MCSymbolWasm>(Symbol)->setSize(Value); -} - -void MCWasmStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size, - unsigned ByteAlignment) { - llvm_unreachable("Local common symbols are not yet implemented for Wasm"); -} - -void MCWasmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, - SMLoc Loc) { - MCObjectStreamer::EmitValueImpl(Value, Size, Loc); -} - -void MCWasmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, - unsigned ValueSize, - unsigned MaxBytesToEmit) { - MCObjectStreamer::EmitValueToAlignment(ByteAlignment, Value, ValueSize, - MaxBytesToEmit); -} - -void MCWasmStreamer::EmitIdent(StringRef IdentString) { - // TODO(sbc): Add the ident section once we support mergable strings - // sections in the object format -} - -void MCWasmStreamer::EmitInstToFragment(const MCInst &Inst, - const MCSubtargetInfo &STI) { - this->MCObjectStreamer::EmitInstToFragment(Inst, STI); -} - -void MCWasmStreamer::EmitInstToData(const MCInst &Inst, - const MCSubtargetInfo &STI) { - MCAssembler &Assembler = getAssembler(); - SmallVector<MCFixup, 4> Fixups; - SmallString<256> Code; - raw_svector_ostream VecOS(Code); - Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); - - // Append the encoded instruction to the current data fragment (or create a - // new such fragment if the current fragment is not a data fragment). - MCDataFragment *DF = getOrCreateDataFragment(); - - // Add the fixups and data. - for (unsigned I = 0, E = Fixups.size(); I != E; ++I) { - Fixups[I].setOffset(Fixups[I].getOffset() + DF->getContents().size()); - DF->getFixups().push_back(Fixups[I]); - } - DF->setHasInstructions(STI); - DF->getContents().append(Code.begin(), Code.end()); -} - -void MCWasmStreamer::FinishImpl() { - EmitFrames(nullptr); - - this->MCObjectStreamer::FinishImpl(); -} - -MCStreamer *llvm::createWasmStreamer(MCContext &Context, - std::unique_ptr<MCAsmBackend> &&MAB, - std::unique_ptr<MCObjectWriter> &&OW, - std::unique_ptr<MCCodeEmitter> &&CE, - bool RelaxAll) { - MCWasmStreamer *S = - new MCWasmStreamer(Context, std::move(MAB), std::move(OW), std::move(CE)); - if (RelaxAll) - S->getAssembler().setRelaxAll(true); - return S; -} - -void MCWasmStreamer::EmitThumbFunc(MCSymbol *Func) { - llvm_unreachable("Generic Wasm doesn't support this directive"); -} - -void MCWasmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { - llvm_unreachable("Wasm doesn't support this directive"); -} - -void MCWasmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment, - SMLoc Loc) { - llvm_unreachable("Wasm doesn't support this directive"); -} - -void MCWasmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment) { - llvm_unreachable("Wasm doesn't support this directive"); -} diff --git a/contrib/llvm/lib/MC/MCWin64EH.cpp b/contrib/llvm/lib/MC/MCWin64EH.cpp deleted file mode 100644 index 4e9a29667097..000000000000 --- a/contrib/llvm/lib/MC/MCWin64EH.cpp +++ /dev/null @@ -1,680 +0,0 @@ -//===- lib/MC/MCWin64EH.cpp - MCWin64EH implementation --------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCWin64EH.h" -#include "llvm/ADT/Twine.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCObjectStreamer.h" -#include "llvm/MC/MCSectionCOFF.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Support/Win64EH.h" - -using namespace llvm; - -// NOTE: All relocations generated here are 4-byte image-relative. - -static uint8_t CountOfUnwindCodes(std::vector<WinEH::Instruction> &Insns) { - uint8_t Count = 0; - for (const auto &I : Insns) { - switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) { - default: - llvm_unreachable("Unsupported unwind code"); - case Win64EH::UOP_PushNonVol: - case Win64EH::UOP_AllocSmall: - case Win64EH::UOP_SetFPReg: - case Win64EH::UOP_PushMachFrame: - Count += 1; - break; - case Win64EH::UOP_SaveNonVol: - case Win64EH::UOP_SaveXMM128: - Count += 2; - break; - case Win64EH::UOP_SaveNonVolBig: - case Win64EH::UOP_SaveXMM128Big: - Count += 3; - break; - case Win64EH::UOP_AllocLarge: - Count += (I.Offset > 512 * 1024 - 8) ? 3 : 2; - break; - } - } - return Count; -} - -static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, - const MCSymbol *RHS) { - MCContext &Context = Streamer.getContext(); - const MCExpr *Diff = - MCBinaryExpr::createSub(MCSymbolRefExpr::create(LHS, Context), - MCSymbolRefExpr::create(RHS, Context), Context); - Streamer.EmitValue(Diff, 1); -} - -static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin, - WinEH::Instruction &inst) { - uint8_t b2; - uint16_t w; - b2 = (inst.Operation & 0x0F); - switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) { - default: - llvm_unreachable("Unsupported unwind code"); - case Win64EH::UOP_PushNonVol: - EmitAbsDifference(streamer, inst.Label, begin); - b2 |= (inst.Register & 0x0F) << 4; - streamer.EmitIntValue(b2, 1); - break; - case Win64EH::UOP_AllocLarge: - EmitAbsDifference(streamer, inst.Label, begin); - if (inst.Offset > 512 * 1024 - 8) { - b2 |= 0x10; - streamer.EmitIntValue(b2, 1); - w = inst.Offset & 0xFFF8; - streamer.EmitIntValue(w, 2); - w = inst.Offset >> 16; - } else { - streamer.EmitIntValue(b2, 1); - w = inst.Offset >> 3; - } - streamer.EmitIntValue(w, 2); - break; - case Win64EH::UOP_AllocSmall: - b2 |= (((inst.Offset - 8) >> 3) & 0x0F) << 4; - EmitAbsDifference(streamer, inst.Label, begin); - streamer.EmitIntValue(b2, 1); - break; - case Win64EH::UOP_SetFPReg: - EmitAbsDifference(streamer, inst.Label, begin); - streamer.EmitIntValue(b2, 1); - break; - case Win64EH::UOP_SaveNonVol: - case Win64EH::UOP_SaveXMM128: - b2 |= (inst.Register & 0x0F) << 4; - EmitAbsDifference(streamer, inst.Label, begin); - streamer.EmitIntValue(b2, 1); - w = inst.Offset >> 3; - if (inst.Operation == Win64EH::UOP_SaveXMM128) - w >>= 1; - streamer.EmitIntValue(w, 2); - break; - case Win64EH::UOP_SaveNonVolBig: - case Win64EH::UOP_SaveXMM128Big: - b2 |= (inst.Register & 0x0F) << 4; - EmitAbsDifference(streamer, inst.Label, begin); - streamer.EmitIntValue(b2, 1); - if (inst.Operation == Win64EH::UOP_SaveXMM128Big) - w = inst.Offset & 0xFFF0; - else - w = inst.Offset & 0xFFF8; - streamer.EmitIntValue(w, 2); - w = inst.Offset >> 16; - streamer.EmitIntValue(w, 2); - break; - case Win64EH::UOP_PushMachFrame: - if (inst.Offset == 1) - b2 |= 0x10; - EmitAbsDifference(streamer, inst.Label, begin); - streamer.EmitIntValue(b2, 1); - break; - } -} - -static void EmitSymbolRefWithOfs(MCStreamer &streamer, - const MCSymbol *Base, - const MCSymbol *Other) { - MCContext &Context = streamer.getContext(); - const MCSymbolRefExpr *BaseRef = MCSymbolRefExpr::create(Base, Context); - const MCSymbolRefExpr *OtherRef = MCSymbolRefExpr::create(Other, Context); - const MCExpr *Ofs = MCBinaryExpr::createSub(OtherRef, BaseRef, Context); - const MCSymbolRefExpr *BaseRefRel = MCSymbolRefExpr::create(Base, - MCSymbolRefExpr::VK_COFF_IMGREL32, - Context); - streamer.EmitValue(MCBinaryExpr::createAdd(BaseRefRel, Ofs, Context), 4); -} - -static void EmitRuntimeFunction(MCStreamer &streamer, - const WinEH::FrameInfo *info) { - MCContext &context = streamer.getContext(); - - streamer.EmitValueToAlignment(4); - EmitSymbolRefWithOfs(streamer, info->Function, info->Begin); - EmitSymbolRefWithOfs(streamer, info->Function, info->End); - streamer.EmitValue(MCSymbolRefExpr::create(info->Symbol, - MCSymbolRefExpr::VK_COFF_IMGREL32, - context), 4); -} - -static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) { - // If this UNWIND_INFO already has a symbol, it's already been emitted. - if (info->Symbol) - return; - - MCContext &context = streamer.getContext(); - MCSymbol *Label = context.createTempSymbol(); - - streamer.EmitValueToAlignment(4); - streamer.EmitLabel(Label); - info->Symbol = Label; - - // Upper 3 bits are the version number (currently 1). - uint8_t flags = 0x01; - if (info->ChainedParent) - flags |= Win64EH::UNW_ChainInfo << 3; - else { - if (info->HandlesUnwind) - flags |= Win64EH::UNW_TerminateHandler << 3; - if (info->HandlesExceptions) - flags |= Win64EH::UNW_ExceptionHandler << 3; - } - streamer.EmitIntValue(flags, 1); - - if (info->PrologEnd) - EmitAbsDifference(streamer, info->PrologEnd, info->Begin); - else - streamer.EmitIntValue(0, 1); - - uint8_t numCodes = CountOfUnwindCodes(info->Instructions); - streamer.EmitIntValue(numCodes, 1); - - uint8_t frame = 0; - if (info->LastFrameInst >= 0) { - WinEH::Instruction &frameInst = info->Instructions[info->LastFrameInst]; - assert(frameInst.Operation == Win64EH::UOP_SetFPReg); - frame = (frameInst.Register & 0x0F) | (frameInst.Offset & 0xF0); - } - streamer.EmitIntValue(frame, 1); - - // Emit unwind instructions (in reverse order). - uint8_t numInst = info->Instructions.size(); - for (uint8_t c = 0; c < numInst; ++c) { - WinEH::Instruction inst = info->Instructions.back(); - info->Instructions.pop_back(); - EmitUnwindCode(streamer, info->Begin, inst); - } - - // For alignment purposes, the instruction array will always have an even - // number of entries, with the final entry potentially unused (in which case - // the array will be one longer than indicated by the count of unwind codes - // field). - if (numCodes & 1) { - streamer.EmitIntValue(0, 2); - } - - if (flags & (Win64EH::UNW_ChainInfo << 3)) - EmitRuntimeFunction(streamer, info->ChainedParent); - else if (flags & - ((Win64EH::UNW_TerminateHandler|Win64EH::UNW_ExceptionHandler) << 3)) - streamer.EmitValue(MCSymbolRefExpr::create(info->ExceptionHandler, - MCSymbolRefExpr::VK_COFF_IMGREL32, - context), 4); - else if (numCodes == 0) { - // The minimum size of an UNWIND_INFO struct is 8 bytes. If we're not - // a chained unwind info, if there is no handler, and if there are fewer - // than 2 slots used in the unwind code array, we have to pad to 8 bytes. - streamer.EmitIntValue(0, 4); - } -} - -void llvm::Win64EH::UnwindEmitter::Emit(MCStreamer &Streamer) const { - // Emit the unwind info structs first. - for (const auto &CFI : Streamer.getWinFrameInfos()) { - MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection); - Streamer.SwitchSection(XData); - ::EmitUnwindInfo(Streamer, CFI.get()); - } - - // Now emit RUNTIME_FUNCTION entries. - for (const auto &CFI : Streamer.getWinFrameInfos()) { - MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection); - Streamer.SwitchSection(PData); - EmitRuntimeFunction(Streamer, CFI.get()); - } -} - -void llvm::Win64EH::UnwindEmitter::EmitUnwindInfo( - MCStreamer &Streamer, WinEH::FrameInfo *info) const { - // Switch sections (the static function above is meant to be called from - // here and from Emit(). - MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection); - Streamer.SwitchSection(XData); - - ::EmitUnwindInfo(Streamer, info); -} - -static int64_t GetAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, - const MCSymbol *RHS) { - MCContext &Context = Streamer.getContext(); - const MCExpr *Diff = - MCBinaryExpr::createSub(MCSymbolRefExpr::create(LHS, Context), - MCSymbolRefExpr::create(RHS, Context), Context); - MCObjectStreamer *OS = (MCObjectStreamer *)(&Streamer); - // It should normally be possible to calculate the length of a function - // at this point, but it might not be possible in the presence of certain - // unusual constructs, like an inline asm with an alignment directive. - int64_t value; - if (!Diff->evaluateAsAbsolute(value, OS->getAssembler())) - report_fatal_error("Failed to evaluate function length in SEH unwind info"); - return value; -} - -static uint32_t -ARM64CountOfUnwindCodes(const std::vector<WinEH::Instruction> &Insns) { - uint32_t Count = 0; - for (const auto &I : Insns) { - switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) { - default: - llvm_unreachable("Unsupported ARM64 unwind code"); - case Win64EH::UOP_AllocSmall: - Count += 1; - break; - case Win64EH::UOP_AllocMedium: - Count += 2; - break; - case Win64EH::UOP_AllocLarge: - Count += 4; - break; - case Win64EH::UOP_SaveFPLRX: - Count += 1; - break; - case Win64EH::UOP_SaveFPLR: - Count += 1; - break; - case Win64EH::UOP_SaveReg: - Count += 2; - break; - case Win64EH::UOP_SaveRegP: - Count += 2; - break; - case Win64EH::UOP_SaveRegPX: - Count += 2; - break; - case Win64EH::UOP_SaveRegX: - Count += 2; - break; - case Win64EH::UOP_SaveFReg: - Count += 2; - break; - case Win64EH::UOP_SaveFRegP: - Count += 2; - break; - case Win64EH::UOP_SaveFRegX: - Count += 2; - break; - case Win64EH::UOP_SaveFRegPX: - Count += 2; - break; - case Win64EH::UOP_SetFP: - Count += 1; - break; - case Win64EH::UOP_AddFP: - Count += 2; - break; - case Win64EH::UOP_Nop: - Count += 1; - break; - case Win64EH::UOP_End: - Count += 1; - break; - } - } - return Count; -} - -// Unwind opcode encodings and restrictions are documented at -// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling -static void ARM64EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin, - WinEH::Instruction &inst) { - uint8_t b, reg; - switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) { - default: - llvm_unreachable("Unsupported ARM64 unwind code"); - case Win64EH::UOP_AllocSmall: - b = (inst.Offset >> 4) & 0x1F; - streamer.EmitIntValue(b, 1); - break; - case Win64EH::UOP_AllocMedium: { - uint16_t hw = (inst.Offset >> 4) & 0x7FF; - b = 0xC0; - b |= (hw >> 8); - streamer.EmitIntValue(b, 1); - b = hw & 0xFF; - streamer.EmitIntValue(b, 1); - break; - } - case Win64EH::UOP_AllocLarge: { - uint32_t w; - b = 0xE0; - streamer.EmitIntValue(b, 1); - w = inst.Offset >> 4; - b = (w & 0x00FF0000) >> 16; - streamer.EmitIntValue(b, 1); - b = (w & 0x0000FF00) >> 8; - streamer.EmitIntValue(b, 1); - b = w & 0x000000FF; - streamer.EmitIntValue(b, 1); - break; - } - case Win64EH::UOP_SetFP: - b = 0xE1; - streamer.EmitIntValue(b, 1); - break; - case Win64EH::UOP_AddFP: - b = 0xE2; - streamer.EmitIntValue(b, 1); - b = (inst.Offset >> 3); - streamer.EmitIntValue(b, 1); - break; - case Win64EH::UOP_Nop: - b = 0xE3; - streamer.EmitIntValue(b, 1); - break; - case Win64EH::UOP_SaveFPLRX: - b = 0x80; - b |= ((inst.Offset - 1) >> 3) & 0x3F; - streamer.EmitIntValue(b, 1); - break; - case Win64EH::UOP_SaveFPLR: - b = 0x40; - b |= (inst.Offset >> 3) & 0x3F; - streamer.EmitIntValue(b, 1); - break; - case Win64EH::UOP_SaveReg: - assert(inst.Register >= 19 && "Saved reg must be >= 19"); - reg = inst.Register - 19; - b = 0xD0 | ((reg & 0xC) >> 2); - streamer.EmitIntValue(b, 1); - b = ((reg & 0x3) << 6) | (inst.Offset >> 3); - streamer.EmitIntValue(b, 1); - break; - case Win64EH::UOP_SaveRegX: - assert(inst.Register >= 19 && "Saved reg must be >= 19"); - reg = inst.Register - 19; - b = 0xD4 | ((reg & 0x8) >> 3); - streamer.EmitIntValue(b, 1); - b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1); - streamer.EmitIntValue(b, 1); - break; - case Win64EH::UOP_SaveRegP: - assert(inst.Register >= 19 && "Saved registers must be >= 19"); - reg = inst.Register - 19; - b = 0xC8 | ((reg & 0xC) >> 2); - streamer.EmitIntValue(b, 1); - b = ((reg & 0x3) << 6) | (inst.Offset >> 3); - streamer.EmitIntValue(b, 1); - break; - case Win64EH::UOP_SaveRegPX: - assert(inst.Register >= 19 && "Saved registers must be >= 19"); - reg = inst.Register - 19; - b = 0xCC | ((reg & 0xC) >> 2); - streamer.EmitIntValue(b, 1); - b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1); - streamer.EmitIntValue(b, 1); - break; - case Win64EH::UOP_SaveFReg: - assert(inst.Register >= 8 && "Saved dreg must be >= 8"); - reg = inst.Register - 8; - b = 0xDC | ((reg & 0x4) >> 2); - streamer.EmitIntValue(b, 1); - b = ((reg & 0x3) << 6) | (inst.Offset >> 3); - streamer.EmitIntValue(b, 1); - break; - case Win64EH::UOP_SaveFRegX: - assert(inst.Register >= 8 && "Saved dreg must be >= 8"); - reg = inst.Register - 8; - b = 0xDE; - streamer.EmitIntValue(b, 1); - b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1); - streamer.EmitIntValue(b, 1); - break; - case Win64EH::UOP_SaveFRegP: - assert(inst.Register >= 8 && "Saved dregs must be >= 8"); - reg = inst.Register - 8; - b = 0xD8 | ((reg & 0x4) >> 2); - streamer.EmitIntValue(b, 1); - b = ((reg & 0x3) << 6) | (inst.Offset >> 3); - streamer.EmitIntValue(b, 1); - break; - case Win64EH::UOP_SaveFRegPX: - assert(inst.Register >= 8 && "Saved dregs must be >= 8"); - reg = inst.Register - 8; - b = 0xDA | ((reg & 0x4) >> 2); - streamer.EmitIntValue(b, 1); - b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1); - streamer.EmitIntValue(b, 1); - break; - case Win64EH::UOP_End: - b = 0xE4; - streamer.EmitIntValue(b, 1); - break; - } -} - -// Returns the epilog symbol of an epilog with the exact same unwind code -// sequence, if it exists. Otherwise, returns nulltpr. -// EpilogInstrs - Unwind codes for the current epilog. -// Epilogs - Epilogs that potentialy match the current epilog. -static MCSymbol* -FindMatchingEpilog(const std::vector<WinEH::Instruction>& EpilogInstrs, - const std::vector<MCSymbol *>& Epilogs, - const WinEH::FrameInfo *info) { - for (auto *EpilogStart : Epilogs) { - auto InstrsIter = info->EpilogMap.find(EpilogStart); - assert(InstrsIter != info->EpilogMap.end() && - "Epilog not found in EpilogMap"); - const auto &Instrs = InstrsIter->second; - - if (Instrs.size() != EpilogInstrs.size()) - continue; - - bool Match = true; - for (unsigned i = 0; i < Instrs.size(); ++i) - if (Instrs[i].Operation != EpilogInstrs[i].Operation || - Instrs[i].Offset != EpilogInstrs[i].Offset || - Instrs[i].Register != EpilogInstrs[i].Register) { - Match = false; - break; - } - - if (Match) - return EpilogStart; - } - return nullptr; -} - -// Populate the .xdata section. The format of .xdata on ARM64 is documented at -// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling -static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) { - // If this UNWIND_INFO already has a symbol, it's already been emitted. - if (info->Symbol) - return; - - MCContext &context = streamer.getContext(); - MCSymbol *Label = context.createTempSymbol(); - - streamer.EmitValueToAlignment(4); - streamer.EmitLabel(Label); - info->Symbol = Label; - - int64_t RawFuncLength; - if (!info->FuncletOrFuncEnd) { - // FIXME: This is very wrong; we emit SEH data which covers zero bytes - // of code. But otherwise test/MC/AArch64/seh.s crashes. - RawFuncLength = 0; - } else { - // FIXME: GetAbsDifference tries to compute the length of the function - // immediately, before the whole file is emitted, but in general - // that's impossible: the size in bytes of certain assembler directives - // like .align and .fill is not known until the whole file is parsed and - // relaxations are applied. Currently, GetAbsDifference fails with a fatal - // error in that case. (We mostly don't hit this because inline assembly - // specifying those directives is rare, and we don't normally try to - // align loops on AArch64.) - // - // There are two potential approaches to delaying the computation. One, - // we could emit something like ".word (endfunc-beginfunc)/4+0x10800000", - // as long as we have some conservative estimate we could use to prove - // that we don't need to split the unwind data. Emitting the constant - // is straightforward, but there's no existing code for estimating the - // size of the function. - // - // The other approach would be to use a dedicated, relaxable fragment, - // which could grow to accommodate splitting the unwind data if - // necessary. This is more straightforward, since it automatically works - // without any new infrastructure, and it's consistent with how we handle - // relaxation in other contexts. But it would require some refactoring - // to move parts of the pdata/xdata emission into the implementation of - // a fragment. We could probably continue to encode the unwind codes - // here, but we'd have to emit the pdata, the xdata header, and the - // epilogue scopes later, since they depend on whether the we need to - // split the unwind data. - RawFuncLength = GetAbsDifference(streamer, info->FuncletOrFuncEnd, - info->Begin); - } - if (RawFuncLength > 0xFFFFF) - report_fatal_error("SEH unwind data splitting not yet implemented"); - uint32_t FuncLength = (uint32_t)RawFuncLength / 4; - uint32_t PrologCodeBytes = ARM64CountOfUnwindCodes(info->Instructions); - uint32_t TotalCodeBytes = PrologCodeBytes; - - // Process epilogs. - MapVector<MCSymbol *, uint32_t> EpilogInfo; - // Epilogs processed so far. - std::vector<MCSymbol *> AddedEpilogs; - - for (auto &I : info->EpilogMap) { - MCSymbol *EpilogStart = I.first; - auto &EpilogInstrs = I.second; - uint32_t CodeBytes = ARM64CountOfUnwindCodes(EpilogInstrs); - - MCSymbol* MatchingEpilog = - FindMatchingEpilog(EpilogInstrs, AddedEpilogs, info); - if (MatchingEpilog) { - assert(EpilogInfo.find(MatchingEpilog) != EpilogInfo.end() && - "Duplicate epilog not found"); - EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog); - // Clear the unwind codes in the EpilogMap, so that they don't get output - // in the logic below. - EpilogInstrs.clear(); - } else { - EpilogInfo[EpilogStart] = TotalCodeBytes; - TotalCodeBytes += CodeBytes; - AddedEpilogs.push_back(EpilogStart); - } - } - - // Code Words, Epilog count, E, X, Vers, Function Length - uint32_t row1 = 0x0; - uint32_t CodeWords = TotalCodeBytes / 4; - uint32_t CodeWordsMod = TotalCodeBytes % 4; - if (CodeWordsMod) - CodeWords++; - uint32_t EpilogCount = info->EpilogMap.size(); - bool ExtensionWord = EpilogCount > 31 || TotalCodeBytes > 124; - if (!ExtensionWord) { - row1 |= (EpilogCount & 0x1F) << 22; - row1 |= (CodeWords & 0x1F) << 27; - } - // E is always 0 right now, TODO: packed epilog setup - if (info->HandlesExceptions) // X - row1 |= 1 << 20; - row1 |= FuncLength & 0x3FFFF; - streamer.EmitIntValue(row1, 4); - - // Extended Code Words, Extended Epilog Count - if (ExtensionWord) { - // FIXME: We should be able to split unwind info into multiple sections. - // FIXME: We should share epilog codes across epilogs, where possible, - // which would make this issue show up less frequently. - if (CodeWords > 0xFF || EpilogCount > 0xFFFF) - report_fatal_error("SEH unwind data splitting not yet implemented"); - uint32_t row2 = 0x0; - row2 |= (CodeWords & 0xFF) << 16; - row2 |= (EpilogCount & 0xFFFF); - streamer.EmitIntValue(row2, 4); - } - - // Epilog Start Index, Epilog Start Offset - for (auto &I : EpilogInfo) { - MCSymbol *EpilogStart = I.first; - uint32_t EpilogIndex = I.second; - uint32_t EpilogOffset = - (uint32_t)GetAbsDifference(streamer, EpilogStart, info->Begin); - if (EpilogOffset) - EpilogOffset /= 4; - uint32_t row3 = EpilogOffset; - row3 |= (EpilogIndex & 0x3FF) << 22; - streamer.EmitIntValue(row3, 4); - } - - // Emit prolog unwind instructions (in reverse order). - uint8_t numInst = info->Instructions.size(); - for (uint8_t c = 0; c < numInst; ++c) { - WinEH::Instruction inst = info->Instructions.back(); - info->Instructions.pop_back(); - ARM64EmitUnwindCode(streamer, info->Begin, inst); - } - - // Emit epilog unwind instructions - for (auto &I : info->EpilogMap) { - auto &EpilogInstrs = I.second; - for (uint32_t i = 0; i < EpilogInstrs.size(); i++) { - WinEH::Instruction inst = EpilogInstrs[i]; - ARM64EmitUnwindCode(streamer, info->Begin, inst); - } - } - - int32_t BytesMod = CodeWords * 4 - TotalCodeBytes; - assert(BytesMod >= 0); - for (int i = 0; i < BytesMod; i++) - streamer.EmitIntValue(0xE3, 1); - - if (info->HandlesExceptions) - streamer.EmitValue( - MCSymbolRefExpr::create(info->ExceptionHandler, - MCSymbolRefExpr::VK_COFF_IMGREL32, context), - 4); -} - -static void ARM64EmitRuntimeFunction(MCStreamer &streamer, - const WinEH::FrameInfo *info) { - MCContext &context = streamer.getContext(); - - streamer.EmitValueToAlignment(4); - EmitSymbolRefWithOfs(streamer, info->Function, info->Begin); - streamer.EmitValue(MCSymbolRefExpr::create(info->Symbol, - MCSymbolRefExpr::VK_COFF_IMGREL32, - context), - 4); -} - -void llvm::Win64EH::ARM64UnwindEmitter::Emit(MCStreamer &Streamer) const { - // Emit the unwind info structs first. - for (const auto &CFI : Streamer.getWinFrameInfos()) { - MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection); - Streamer.SwitchSection(XData); - ARM64EmitUnwindInfo(Streamer, CFI.get()); - } - - // Now emit RUNTIME_FUNCTION entries. - for (const auto &CFI : Streamer.getWinFrameInfos()) { - MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection); - Streamer.SwitchSection(PData); - ARM64EmitRuntimeFunction(Streamer, CFI.get()); - } -} - -void llvm::Win64EH::ARM64UnwindEmitter::EmitUnwindInfo( - MCStreamer &Streamer, WinEH::FrameInfo *info) const { - // Switch sections (the static function above is meant to be called from - // here and from Emit(). - MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection); - Streamer.SwitchSection(XData); - ARM64EmitUnwindInfo(Streamer, info); -} diff --git a/contrib/llvm/lib/MC/MCWinCOFFStreamer.cpp b/contrib/llvm/lib/MC/MCWinCOFFStreamer.cpp deleted file mode 100644 index 04d5f100a2ff..000000000000 --- a/contrib/llvm/lib/MC/MCWinCOFFStreamer.cpp +++ /dev/null @@ -1,325 +0,0 @@ -//===- llvm/MC/MCWinCOFFStreamer.cpp --------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains an implementation of a Windows COFF object file streamer. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Triple.h" -#include "llvm/ADT/Twine.h" -#include "llvm/BinaryFormat/COFF.h" -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCCodeEmitter.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFixup.h" -#include "llvm/MC/MCFragment.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCObjectStreamer.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSymbolCOFF.h" -#include "llvm/MC/MCWinCOFFStreamer.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/SMLoc.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cassert> -#include <cstdint> - -using namespace llvm; - -#define DEBUG_TYPE "WinCOFFStreamer" - -MCWinCOFFStreamer::MCWinCOFFStreamer(MCContext &Context, - std::unique_ptr<MCAsmBackend> MAB, - std::unique_ptr<MCCodeEmitter> CE, - std::unique_ptr<MCObjectWriter> OW) - : MCObjectStreamer(Context, std::move(MAB), std::move(OW), std::move(CE)), - CurSymbol(nullptr) {} - -void MCWinCOFFStreamer::EmitInstToData(const MCInst &Inst, - const MCSubtargetInfo &STI) { - MCDataFragment *DF = getOrCreateDataFragment(); - - SmallVector<MCFixup, 4> Fixups; - SmallString<256> Code; - raw_svector_ostream VecOS(Code); - getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); - - // Add the fixups and data. - for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { - Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); - DF->getFixups().push_back(Fixups[i]); - } - DF->setHasInstructions(STI); - DF->getContents().append(Code.begin(), Code.end()); -} - -void MCWinCOFFStreamer::InitSections(bool NoExecStack) { - // FIXME: this is identical to the ELF one. - // This emulates the same behavior of GNU as. This makes it easier - // to compare the output as the major sections are in the same order. - SwitchSection(getContext().getObjectFileInfo()->getTextSection()); - EmitCodeAlignment(4); - - SwitchSection(getContext().getObjectFileInfo()->getDataSection()); - EmitCodeAlignment(4); - - SwitchSection(getContext().getObjectFileInfo()->getBSSSection()); - EmitCodeAlignment(4); - - SwitchSection(getContext().getObjectFileInfo()->getTextSection()); -} - -void MCWinCOFFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) { - auto *Symbol = cast<MCSymbolCOFF>(S); - MCObjectStreamer::EmitLabel(Symbol, Loc); -} - -void MCWinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { - llvm_unreachable("not implemented"); -} - -void MCWinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) { - llvm_unreachable("not implemented"); -} - -bool MCWinCOFFStreamer::EmitSymbolAttribute(MCSymbol *S, - MCSymbolAttr Attribute) { - auto *Symbol = cast<MCSymbolCOFF>(S); - getAssembler().registerSymbol(*Symbol); - - switch (Attribute) { - default: return false; - case MCSA_WeakReference: - case MCSA_Weak: - Symbol->setIsWeakExternal(); - Symbol->setExternal(true); - break; - case MCSA_Global: - Symbol->setExternal(true); - break; - case MCSA_AltEntry: - llvm_unreachable("COFF doesn't support the .alt_entry attribute"); - } - - return true; -} - -void MCWinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { - llvm_unreachable("not implemented"); -} - -void MCWinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *S) { - auto *Symbol = cast<MCSymbolCOFF>(S); - if (CurSymbol) - Error("starting a new symbol definition without completing the " - "previous one"); - CurSymbol = Symbol; -} - -void MCWinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { - if (!CurSymbol) { - Error("storage class specified outside of symbol definition"); - return; - } - - if (StorageClass & ~COFF::SSC_Invalid) { - Error("storage class value '" + Twine(StorageClass) + - "' out of range"); - return; - } - - getAssembler().registerSymbol(*CurSymbol); - cast<MCSymbolCOFF>(CurSymbol)->setClass((uint16_t)StorageClass); -} - -void MCWinCOFFStreamer::EmitCOFFSymbolType(int Type) { - if (!CurSymbol) { - Error("symbol type specified outside of a symbol definition"); - return; - } - - if (Type & ~0xffff) { - Error("type value '" + Twine(Type) + "' out of range"); - return; - } - - getAssembler().registerSymbol(*CurSymbol); - cast<MCSymbolCOFF>(CurSymbol)->setType((uint16_t)Type); -} - -void MCWinCOFFStreamer::EndCOFFSymbolDef() { - if (!CurSymbol) - Error("ending symbol definition without starting one"); - CurSymbol = nullptr; -} - -void MCWinCOFFStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) { - // SafeSEH is a feature specific to 32-bit x86. It does not exist (and is - // unnecessary) on all platforms which use table-based exception dispatch. - if (getContext().getObjectFileInfo()->getTargetTriple().getArch() != - Triple::x86) - return; - - const MCSymbolCOFF *CSymbol = cast<MCSymbolCOFF>(Symbol); - if (CSymbol->isSafeSEH()) - return; - - MCSection *SXData = getContext().getObjectFileInfo()->getSXDataSection(); - getAssembler().registerSection(*SXData); - if (SXData->getAlignment() < 4) - SXData->setAlignment(4); - - new MCSymbolIdFragment(Symbol, SXData); - - getAssembler().registerSymbol(*Symbol); - CSymbol->setIsSafeSEH(); - - // The Microsoft linker requires that the symbol type of a handler be - // function. Go ahead and oblige it here. - CSymbol->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION - << COFF::SCT_COMPLEX_TYPE_SHIFT); -} - -void MCWinCOFFStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) { - MCSection *Sec = getCurrentSectionOnly(); - getAssembler().registerSection(*Sec); - if (Sec->getAlignment() < 4) - Sec->setAlignment(4); - - new MCSymbolIdFragment(Symbol, getCurrentSectionOnly()); - - getAssembler().registerSymbol(*Symbol); -} - -void MCWinCOFFStreamer::EmitCOFFSectionIndex(const MCSymbol *Symbol) { - visitUsedSymbol(*Symbol); - MCDataFragment *DF = getOrCreateDataFragment(); - const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext()); - MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, FK_SecRel_2); - DF->getFixups().push_back(Fixup); - DF->getContents().resize(DF->getContents().size() + 2, 0); -} - -void MCWinCOFFStreamer::EmitCOFFSecRel32(const MCSymbol *Symbol, - uint64_t Offset) { - visitUsedSymbol(*Symbol); - MCDataFragment *DF = getOrCreateDataFragment(); - // Create Symbol A for the relocation relative reference. - const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext()); - // Add the constant offset, if given. - if (Offset) - MCE = MCBinaryExpr::createAdd( - MCE, MCConstantExpr::create(Offset, getContext()), getContext()); - // Build the secrel32 relocation. - MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_SecRel_4); - // Record the relocation. - DF->getFixups().push_back(Fixup); - // Emit 4 bytes (zeros) to the object file. - DF->getContents().resize(DF->getContents().size() + 4, 0); -} - -void MCWinCOFFStreamer::EmitCOFFImgRel32(const MCSymbol *Symbol, - int64_t Offset) { - visitUsedSymbol(*Symbol); - MCDataFragment *DF = getOrCreateDataFragment(); - // Create Symbol A for the relocation relative reference. - const MCExpr *MCE = MCSymbolRefExpr::create( - Symbol, MCSymbolRefExpr::VK_COFF_IMGREL32, getContext()); - // Add the constant offset, if given. - if (Offset) - MCE = MCBinaryExpr::createAdd( - MCE, MCConstantExpr::create(Offset, getContext()), getContext()); - // Build the imgrel relocation. - MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_Data_4); - // Record the relocation. - DF->getFixups().push_back(Fixup); - // Emit 4 bytes (zeros) to the object file. - DF->getContents().resize(DF->getContents().size() + 4, 0); -} - -void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size, - unsigned ByteAlignment) { - auto *Symbol = cast<MCSymbolCOFF>(S); - - const Triple &T = getContext().getObjectFileInfo()->getTargetTriple(); - if (T.isWindowsMSVCEnvironment()) { - if (ByteAlignment > 32) - report_fatal_error("alignment is limited to 32-bytes"); - - // Round size up to alignment so that we will honor the alignment request. - Size = std::max(Size, static_cast<uint64_t>(ByteAlignment)); - } - - getAssembler().registerSymbol(*Symbol); - Symbol->setExternal(true); - Symbol->setCommon(Size, ByteAlignment); - - if (!T.isWindowsMSVCEnvironment() && ByteAlignment > 1) { - SmallString<128> Directive; - raw_svector_ostream OS(Directive); - const MCObjectFileInfo *MFI = getContext().getObjectFileInfo(); - - OS << " -aligncomm:\"" << Symbol->getName() << "\"," - << Log2_32_Ceil(ByteAlignment); - - PushSection(); - SwitchSection(MFI->getDrectveSection()); - EmitBytes(Directive); - PopSection(); - } -} - -void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size, - unsigned ByteAlignment) { - auto *Symbol = cast<MCSymbolCOFF>(S); - - MCSection *Section = getContext().getObjectFileInfo()->getBSSSection(); - PushSection(); - SwitchSection(Section); - EmitValueToAlignment(ByteAlignment, 0, 1, 0); - EmitLabel(Symbol); - Symbol->setExternal(false); - EmitZeros(Size); - PopSection(); -} - -void MCWinCOFFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment, - SMLoc Loc) { - llvm_unreachable("not implemented"); -} - -void MCWinCOFFStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment) { - llvm_unreachable("not implemented"); -} - -// TODO: Implement this if you want to emit .comment section in COFF obj files. -void MCWinCOFFStreamer::EmitIdent(StringRef IdentString) { - llvm_unreachable("not implemented"); -} - -void MCWinCOFFStreamer::EmitWinEHHandlerData(SMLoc Loc) { - llvm_unreachable("not implemented"); -} - -void MCWinCOFFStreamer::FinishImpl() { - MCObjectStreamer::FinishImpl(); -} - -void MCWinCOFFStreamer::Error(const Twine &Msg) const { - getContext().reportError(SMLoc(), Msg); -} diff --git a/contrib/llvm/lib/MC/MCWinEH.cpp b/contrib/llvm/lib/MC/MCWinEH.cpp deleted file mode 100644 index e58a0b2cf654..000000000000 --- a/contrib/llvm/lib/MC/MCWinEH.cpp +++ /dev/null @@ -1,25 +0,0 @@ -//===- lib/MC/MCWinEH.cpp - Windows EH implementation ---------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCWinEH.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/BinaryFormat/COFF.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCSectionCOFF.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" - -namespace llvm { -namespace WinEH { - -UnwindEmitter::~UnwindEmitter() {} - -} -} - diff --git a/contrib/llvm/lib/MC/MCXCOFFObjectTargetWriter.cpp b/contrib/llvm/lib/MC/MCXCOFFObjectTargetWriter.cpp deleted file mode 100644 index 504e333cb2d4..000000000000 --- a/contrib/llvm/lib/MC/MCXCOFFObjectTargetWriter.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===- MCXCOFFObjectTargetWriter.cpp - XCOFF Target Writer Subclass -------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCXCOFFObjectWriter.h" - -using namespace llvm; - -MCXCOFFObjectTargetWriter::MCXCOFFObjectTargetWriter(bool Is64Bit) - : Is64Bit(Is64Bit) {} - -MCXCOFFObjectTargetWriter::~MCXCOFFObjectTargetWriter() = default; diff --git a/contrib/llvm/lib/MC/MCXCOFFStreamer.cpp b/contrib/llvm/lib/MC/MCXCOFFStreamer.cpp deleted file mode 100644 index 071de024a3fa..000000000000 --- a/contrib/llvm/lib/MC/MCXCOFFStreamer.cpp +++ /dev/null @@ -1,59 +0,0 @@ -//===- lib/MC/MCXCOFFStreamer.cpp - XCOFF Object Output -------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file assembles .s files and emits XCOFF .o object files. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCXCOFFStreamer.h" -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCCodeEmitter.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/Support/TargetRegistry.h" - -using namespace llvm; - -MCXCOFFStreamer::MCXCOFFStreamer(MCContext &Context, - std::unique_ptr<MCAsmBackend> MAB, - std::unique_ptr<MCObjectWriter> OW, - std::unique_ptr<MCCodeEmitter> Emitter) - : MCObjectStreamer(Context, std::move(MAB), std::move(OW), - std::move(Emitter)) {} - -bool MCXCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, - MCSymbolAttr Attribute) { - report_fatal_error("Symbol attributes not implemented for XCOFF."); -} - -void MCXCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) { - report_fatal_error("Emiting common symbols not implemented for XCOFF."); -} - -void MCXCOFFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment, - SMLoc Loc) { - report_fatal_error("Zero fill not implemented for XCOFF."); -} - -void MCXCOFFStreamer::EmitInstToData(const MCInst &Inst, - const MCSubtargetInfo &) { - report_fatal_error("Instruction emission not implemented for XCOFF."); -} - -MCStreamer *llvm::createXCOFFStreamer(MCContext &Context, - std::unique_ptr<MCAsmBackend> &&MAB, - std::unique_ptr<MCObjectWriter> &&OW, - std::unique_ptr<MCCodeEmitter> &&CE, - bool RelaxAll) { - MCXCOFFStreamer *S = new MCXCOFFStreamer(Context, std::move(MAB), - std::move(OW), std::move(CE)); - if (RelaxAll) - S->getAssembler().setRelaxAll(true); - return S; -} diff --git a/contrib/llvm/lib/MC/MachObjectWriter.cpp b/contrib/llvm/lib/MC/MachObjectWriter.cpp deleted file mode 100644 index f0ceb86b25af..000000000000 --- a/contrib/llvm/lib/MC/MachObjectWriter.cpp +++ /dev/null @@ -1,1048 +0,0 @@ -//===- lib/MC/MachObjectWriter.cpp - Mach-O File Writer -------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Twine.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/BinaryFormat/MachO.h" -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCAsmLayout.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDirectives.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFixupKindInfo.h" -#include "llvm/MC/MCFragment.h" -#include "llvm/MC/MCMachObjectWriter.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSectionMachO.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCSymbolMachO.h" -#include "llvm/MC/MCValue.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cassert> -#include <cstdint> -#include <string> -#include <utility> -#include <vector> - -using namespace llvm; - -#define DEBUG_TYPE "mc" - -void MachObjectWriter::reset() { - Relocations.clear(); - IndirectSymBase.clear(); - StringTable.clear(); - LocalSymbolData.clear(); - ExternalSymbolData.clear(); - UndefinedSymbolData.clear(); - MCObjectWriter::reset(); -} - -bool MachObjectWriter::doesSymbolRequireExternRelocation(const MCSymbol &S) { - // Undefined symbols are always extern. - if (S.isUndefined()) - return true; - - // References to weak definitions require external relocation entries; the - // definition may not always be the one in the same object file. - if (cast<MCSymbolMachO>(S).isWeakDefinition()) - return true; - - // Otherwise, we can use an internal relocation. - return false; -} - -bool MachObjectWriter:: -MachSymbolData::operator<(const MachSymbolData &RHS) const { - return Symbol->getName() < RHS.Symbol->getName(); -} - -bool MachObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) { - const MCFixupKindInfo &FKI = Asm.getBackend().getFixupKindInfo( - (MCFixupKind) Kind); - - return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel; -} - -uint64_t MachObjectWriter::getFragmentAddress(const MCFragment *Fragment, - const MCAsmLayout &Layout) const { - return getSectionAddress(Fragment->getParent()) + - Layout.getFragmentOffset(Fragment); -} - -uint64_t MachObjectWriter::getSymbolAddress(const MCSymbol &S, - const MCAsmLayout &Layout) const { - // If this is a variable, then recursively evaluate now. - if (S.isVariable()) { - if (const MCConstantExpr *C = - dyn_cast<const MCConstantExpr>(S.getVariableValue())) - return C->getValue(); - - MCValue Target; - if (!S.getVariableValue()->evaluateAsRelocatable(Target, &Layout, nullptr)) - report_fatal_error("unable to evaluate offset for variable '" + - S.getName() + "'"); - - // Verify that any used symbols are defined. - if (Target.getSymA() && Target.getSymA()->getSymbol().isUndefined()) - report_fatal_error("unable to evaluate offset to undefined symbol '" + - Target.getSymA()->getSymbol().getName() + "'"); - if (Target.getSymB() && Target.getSymB()->getSymbol().isUndefined()) - report_fatal_error("unable to evaluate offset to undefined symbol '" + - Target.getSymB()->getSymbol().getName() + "'"); - - uint64_t Address = Target.getConstant(); - if (Target.getSymA()) - Address += getSymbolAddress(Target.getSymA()->getSymbol(), Layout); - if (Target.getSymB()) - Address += getSymbolAddress(Target.getSymB()->getSymbol(), Layout); - return Address; - } - - return getSectionAddress(S.getFragment()->getParent()) + - Layout.getSymbolOffset(S); -} - -uint64_t MachObjectWriter::getPaddingSize(const MCSection *Sec, - const MCAsmLayout &Layout) const { - uint64_t EndAddr = getSectionAddress(Sec) + Layout.getSectionAddressSize(Sec); - unsigned Next = Sec->getLayoutOrder() + 1; - if (Next >= Layout.getSectionOrder().size()) - return 0; - - const MCSection &NextSec = *Layout.getSectionOrder()[Next]; - if (NextSec.isVirtualSection()) - return 0; - return OffsetToAlignment(EndAddr, NextSec.getAlignment()); -} - -void MachObjectWriter::writeHeader(MachO::HeaderFileType Type, - unsigned NumLoadCommands, - unsigned LoadCommandsSize, - bool SubsectionsViaSymbols) { - uint32_t Flags = 0; - - if (SubsectionsViaSymbols) - Flags |= MachO::MH_SUBSECTIONS_VIA_SYMBOLS; - - // struct mach_header (28 bytes) or - // struct mach_header_64 (32 bytes) - - uint64_t Start = W.OS.tell(); - (void) Start; - - W.write<uint32_t>(is64Bit() ? MachO::MH_MAGIC_64 : MachO::MH_MAGIC); - - W.write<uint32_t>(TargetObjectWriter->getCPUType()); - W.write<uint32_t>(TargetObjectWriter->getCPUSubtype()); - - W.write<uint32_t>(Type); - W.write<uint32_t>(NumLoadCommands); - W.write<uint32_t>(LoadCommandsSize); - W.write<uint32_t>(Flags); - if (is64Bit()) - W.write<uint32_t>(0); // reserved - - assert(W.OS.tell() - Start == (is64Bit() ? sizeof(MachO::mach_header_64) - : sizeof(MachO::mach_header))); -} - -void MachObjectWriter::writeWithPadding(StringRef Str, uint64_t Size) { - assert(Size >= Str.size()); - W.OS << Str; - W.OS.write_zeros(Size - Str.size()); -} - -/// writeSegmentLoadCommand - Write a segment load command. -/// -/// \param NumSections The number of sections in this segment. -/// \param SectionDataSize The total size of the sections. -void MachObjectWriter::writeSegmentLoadCommand( - StringRef Name, unsigned NumSections, uint64_t VMAddr, uint64_t VMSize, - uint64_t SectionDataStartOffset, uint64_t SectionDataSize, uint32_t MaxProt, - uint32_t InitProt) { - // struct segment_command (56 bytes) or - // struct segment_command_64 (72 bytes) - - uint64_t Start = W.OS.tell(); - (void) Start; - - unsigned SegmentLoadCommandSize = - is64Bit() ? sizeof(MachO::segment_command_64): - sizeof(MachO::segment_command); - W.write<uint32_t>(is64Bit() ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT); - W.write<uint32_t>(SegmentLoadCommandSize + - NumSections * (is64Bit() ? sizeof(MachO::section_64) : - sizeof(MachO::section))); - - writeWithPadding(Name, 16); - if (is64Bit()) { - W.write<uint64_t>(VMAddr); // vmaddr - W.write<uint64_t>(VMSize); // vmsize - W.write<uint64_t>(SectionDataStartOffset); // file offset - W.write<uint64_t>(SectionDataSize); // file size - } else { - W.write<uint32_t>(VMAddr); // vmaddr - W.write<uint32_t>(VMSize); // vmsize - W.write<uint32_t>(SectionDataStartOffset); // file offset - W.write<uint32_t>(SectionDataSize); // file size - } - // maxprot - W.write<uint32_t>(MaxProt); - // initprot - W.write<uint32_t>(InitProt); - W.write<uint32_t>(NumSections); - W.write<uint32_t>(0); // flags - - assert(W.OS.tell() - Start == SegmentLoadCommandSize); -} - -void MachObjectWriter::writeSection(const MCAsmLayout &Layout, - const MCSection &Sec, uint64_t VMAddr, - uint64_t FileOffset, unsigned Flags, - uint64_t RelocationsStart, - unsigned NumRelocations) { - uint64_t SectionSize = Layout.getSectionAddressSize(&Sec); - const MCSectionMachO &Section = cast<MCSectionMachO>(Sec); - - // The offset is unused for virtual sections. - if (Section.isVirtualSection()) { - assert(Layout.getSectionFileSize(&Sec) == 0 && "Invalid file size!"); - FileOffset = 0; - } - - // struct section (68 bytes) or - // struct section_64 (80 bytes) - - uint64_t Start = W.OS.tell(); - (void) Start; - - writeWithPadding(Section.getSectionName(), 16); - writeWithPadding(Section.getSegmentName(), 16); - if (is64Bit()) { - W.write<uint64_t>(VMAddr); // address - W.write<uint64_t>(SectionSize); // size - } else { - W.write<uint32_t>(VMAddr); // address - W.write<uint32_t>(SectionSize); // size - } - W.write<uint32_t>(FileOffset); - - assert(isPowerOf2_32(Section.getAlignment()) && "Invalid alignment!"); - W.write<uint32_t>(Log2_32(Section.getAlignment())); - W.write<uint32_t>(NumRelocations ? RelocationsStart : 0); - W.write<uint32_t>(NumRelocations); - W.write<uint32_t>(Flags); - W.write<uint32_t>(IndirectSymBase.lookup(&Sec)); // reserved1 - W.write<uint32_t>(Section.getStubSize()); // reserved2 - if (is64Bit()) - W.write<uint32_t>(0); // reserved3 - - assert(W.OS.tell() - Start == - (is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section))); -} - -void MachObjectWriter::writeSymtabLoadCommand(uint32_t SymbolOffset, - uint32_t NumSymbols, - uint32_t StringTableOffset, - uint32_t StringTableSize) { - // struct symtab_command (24 bytes) - - uint64_t Start = W.OS.tell(); - (void) Start; - - W.write<uint32_t>(MachO::LC_SYMTAB); - W.write<uint32_t>(sizeof(MachO::symtab_command)); - W.write<uint32_t>(SymbolOffset); - W.write<uint32_t>(NumSymbols); - W.write<uint32_t>(StringTableOffset); - W.write<uint32_t>(StringTableSize); - - assert(W.OS.tell() - Start == sizeof(MachO::symtab_command)); -} - -void MachObjectWriter::writeDysymtabLoadCommand(uint32_t FirstLocalSymbol, - uint32_t NumLocalSymbols, - uint32_t FirstExternalSymbol, - uint32_t NumExternalSymbols, - uint32_t FirstUndefinedSymbol, - uint32_t NumUndefinedSymbols, - uint32_t IndirectSymbolOffset, - uint32_t NumIndirectSymbols) { - // struct dysymtab_command (80 bytes) - - uint64_t Start = W.OS.tell(); - (void) Start; - - W.write<uint32_t>(MachO::LC_DYSYMTAB); - W.write<uint32_t>(sizeof(MachO::dysymtab_command)); - W.write<uint32_t>(FirstLocalSymbol); - W.write<uint32_t>(NumLocalSymbols); - W.write<uint32_t>(FirstExternalSymbol); - W.write<uint32_t>(NumExternalSymbols); - W.write<uint32_t>(FirstUndefinedSymbol); - W.write<uint32_t>(NumUndefinedSymbols); - W.write<uint32_t>(0); // tocoff - W.write<uint32_t>(0); // ntoc - W.write<uint32_t>(0); // modtaboff - W.write<uint32_t>(0); // nmodtab - W.write<uint32_t>(0); // extrefsymoff - W.write<uint32_t>(0); // nextrefsyms - W.write<uint32_t>(IndirectSymbolOffset); - W.write<uint32_t>(NumIndirectSymbols); - W.write<uint32_t>(0); // extreloff - W.write<uint32_t>(0); // nextrel - W.write<uint32_t>(0); // locreloff - W.write<uint32_t>(0); // nlocrel - - assert(W.OS.tell() - Start == sizeof(MachO::dysymtab_command)); -} - -MachObjectWriter::MachSymbolData * -MachObjectWriter::findSymbolData(const MCSymbol &Sym) { - for (auto *SymbolData : - {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData}) - for (MachSymbolData &Entry : *SymbolData) - if (Entry.Symbol == &Sym) - return &Entry; - - return nullptr; -} - -const MCSymbol &MachObjectWriter::findAliasedSymbol(const MCSymbol &Sym) const { - const MCSymbol *S = &Sym; - while (S->isVariable()) { - const MCExpr *Value = S->getVariableValue(); - const auto *Ref = dyn_cast<MCSymbolRefExpr>(Value); - if (!Ref) - return *S; - S = &Ref->getSymbol(); - } - return *S; -} - -void MachObjectWriter::writeNlist(MachSymbolData &MSD, - const MCAsmLayout &Layout) { - const MCSymbol *Symbol = MSD.Symbol; - const MCSymbol &Data = *Symbol; - const MCSymbol *AliasedSymbol = &findAliasedSymbol(*Symbol); - uint8_t SectionIndex = MSD.SectionIndex; - uint8_t Type = 0; - uint64_t Address = 0; - bool IsAlias = Symbol != AliasedSymbol; - - const MCSymbol &OrigSymbol = *Symbol; - MachSymbolData *AliaseeInfo; - if (IsAlias) { - AliaseeInfo = findSymbolData(*AliasedSymbol); - if (AliaseeInfo) - SectionIndex = AliaseeInfo->SectionIndex; - Symbol = AliasedSymbol; - // FIXME: Should this update Data as well? - } - - // Set the N_TYPE bits. See <mach-o/nlist.h>. - // - // FIXME: Are the prebound or indirect fields possible here? - if (IsAlias && Symbol->isUndefined()) - Type = MachO::N_INDR; - else if (Symbol->isUndefined()) - Type = MachO::N_UNDF; - else if (Symbol->isAbsolute()) - Type = MachO::N_ABS; - else - Type = MachO::N_SECT; - - // FIXME: Set STAB bits. - - if (Data.isPrivateExtern()) - Type |= MachO::N_PEXT; - - // Set external bit. - if (Data.isExternal() || (!IsAlias && Symbol->isUndefined())) - Type |= MachO::N_EXT; - - // Compute the symbol address. - if (IsAlias && Symbol->isUndefined()) - Address = AliaseeInfo->StringIndex; - else if (Symbol->isDefined()) - Address = getSymbolAddress(OrigSymbol, Layout); - else if (Symbol->isCommon()) { - // Common symbols are encoded with the size in the address - // field, and their alignment in the flags. - Address = Symbol->getCommonSize(); - } - - // struct nlist (12 bytes) - - W.write<uint32_t>(MSD.StringIndex); - W.OS << char(Type); - W.OS << char(SectionIndex); - - // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc' - // value. - bool EncodeAsAltEntry = - IsAlias && cast<MCSymbolMachO>(OrigSymbol).isAltEntry(); - W.write<uint16_t>(cast<MCSymbolMachO>(Symbol)->getEncodedFlags(EncodeAsAltEntry)); - if (is64Bit()) - W.write<uint64_t>(Address); - else - W.write<uint32_t>(Address); -} - -void MachObjectWriter::writeLinkeditLoadCommand(uint32_t Type, - uint32_t DataOffset, - uint32_t DataSize) { - uint64_t Start = W.OS.tell(); - (void) Start; - - W.write<uint32_t>(Type); - W.write<uint32_t>(sizeof(MachO::linkedit_data_command)); - W.write<uint32_t>(DataOffset); - W.write<uint32_t>(DataSize); - - assert(W.OS.tell() - Start == sizeof(MachO::linkedit_data_command)); -} - -static unsigned ComputeLinkerOptionsLoadCommandSize( - const std::vector<std::string> &Options, bool is64Bit) -{ - unsigned Size = sizeof(MachO::linker_option_command); - for (const std::string &Option : Options) - Size += Option.size() + 1; - return alignTo(Size, is64Bit ? 8 : 4); -} - -void MachObjectWriter::writeLinkerOptionsLoadCommand( - const std::vector<std::string> &Options) -{ - unsigned Size = ComputeLinkerOptionsLoadCommandSize(Options, is64Bit()); - uint64_t Start = W.OS.tell(); - (void) Start; - - W.write<uint32_t>(MachO::LC_LINKER_OPTION); - W.write<uint32_t>(Size); - W.write<uint32_t>(Options.size()); - uint64_t BytesWritten = sizeof(MachO::linker_option_command); - for (const std::string &Option : Options) { - // Write each string, including the null byte. - W.OS << Option << '\0'; - BytesWritten += Option.size() + 1; - } - - // Pad to a multiple of the pointer size. - W.OS.write_zeros(OffsetToAlignment(BytesWritten, is64Bit() ? 8 : 4)); - - assert(W.OS.tell() - Start == Size); -} - -static bool isFixupTargetValid(const MCValue &Target) { - // Target is (LHS - RHS + cst). - // We don't support the form where LHS is null: -RHS + cst - if (!Target.getSymA() && Target.getSymB()) - return false; - return true; -} - -void MachObjectWriter::recordRelocation(MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, MCValue Target, - uint64_t &FixedValue) { - if (!isFixupTargetValid(Target)) { - Asm.getContext().reportError(Fixup.getLoc(), - "unsupported relocation expression"); - return; - } - - TargetObjectWriter->recordRelocation(this, Asm, Layout, Fragment, Fixup, - Target, FixedValue); -} - -void MachObjectWriter::bindIndirectSymbols(MCAssembler &Asm) { - // This is the point where 'as' creates actual symbols for indirect symbols - // (in the following two passes). It would be easier for us to do this sooner - // when we see the attribute, but that makes getting the order in the symbol - // table much more complicated than it is worth. - // - // FIXME: Revisit this when the dust settles. - - // Report errors for use of .indirect_symbol not in a symbol pointer section - // or stub section. - for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(), - ie = Asm.indirect_symbol_end(); it != ie; ++it) { - const MCSectionMachO &Section = cast<MCSectionMachO>(*it->Section); - - if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS && - Section.getType() != MachO::S_LAZY_SYMBOL_POINTERS && - Section.getType() != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS && - Section.getType() != MachO::S_SYMBOL_STUBS) { - MCSymbol &Symbol = *it->Symbol; - report_fatal_error("indirect symbol '" + Symbol.getName() + - "' not in a symbol pointer or stub section"); - } - } - - // Bind non-lazy symbol pointers first. - unsigned IndirectIndex = 0; - for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(), - ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) { - const MCSectionMachO &Section = cast<MCSectionMachO>(*it->Section); - - if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS && - Section.getType() != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) - continue; - - // Initialize the section indirect symbol base, if necessary. - IndirectSymBase.insert(std::make_pair(it->Section, IndirectIndex)); - - Asm.registerSymbol(*it->Symbol); - } - - // Then lazy symbol pointers and symbol stubs. - IndirectIndex = 0; - for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(), - ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) { - const MCSectionMachO &Section = cast<MCSectionMachO>(*it->Section); - - if (Section.getType() != MachO::S_LAZY_SYMBOL_POINTERS && - Section.getType() != MachO::S_SYMBOL_STUBS) - continue; - - // Initialize the section indirect symbol base, if necessary. - IndirectSymBase.insert(std::make_pair(it->Section, IndirectIndex)); - - // Set the symbol type to undefined lazy, but only on construction. - // - // FIXME: Do not hardcode. - bool Created; - Asm.registerSymbol(*it->Symbol, &Created); - if (Created) - cast<MCSymbolMachO>(it->Symbol)->setReferenceTypeUndefinedLazy(true); - } -} - -/// computeSymbolTable - Compute the symbol table data -void MachObjectWriter::computeSymbolTable( - MCAssembler &Asm, std::vector<MachSymbolData> &LocalSymbolData, - std::vector<MachSymbolData> &ExternalSymbolData, - std::vector<MachSymbolData> &UndefinedSymbolData) { - // Build section lookup table. - DenseMap<const MCSection*, uint8_t> SectionIndexMap; - unsigned Index = 1; - for (MCAssembler::iterator it = Asm.begin(), - ie = Asm.end(); it != ie; ++it, ++Index) - SectionIndexMap[&*it] = Index; - assert(Index <= 256 && "Too many sections!"); - - // Build the string table. - for (const MCSymbol &Symbol : Asm.symbols()) { - if (!Asm.isSymbolLinkerVisible(Symbol)) - continue; - - StringTable.add(Symbol.getName()); - } - StringTable.finalize(); - - // Build the symbol arrays but only for non-local symbols. - // - // The particular order that we collect and then sort the symbols is chosen to - // match 'as'. Even though it doesn't matter for correctness, this is - // important for letting us diff .o files. - for (const MCSymbol &Symbol : Asm.symbols()) { - // Ignore non-linker visible symbols. - if (!Asm.isSymbolLinkerVisible(Symbol)) - continue; - - if (!Symbol.isExternal() && !Symbol.isUndefined()) - continue; - - MachSymbolData MSD; - MSD.Symbol = &Symbol; - MSD.StringIndex = StringTable.getOffset(Symbol.getName()); - - if (Symbol.isUndefined()) { - MSD.SectionIndex = 0; - UndefinedSymbolData.push_back(MSD); - } else if (Symbol.isAbsolute()) { - MSD.SectionIndex = 0; - ExternalSymbolData.push_back(MSD); - } else { - MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection()); - assert(MSD.SectionIndex && "Invalid section index!"); - ExternalSymbolData.push_back(MSD); - } - } - - // Now add the data for local symbols. - for (const MCSymbol &Symbol : Asm.symbols()) { - // Ignore non-linker visible symbols. - if (!Asm.isSymbolLinkerVisible(Symbol)) - continue; - - if (Symbol.isExternal() || Symbol.isUndefined()) - continue; - - MachSymbolData MSD; - MSD.Symbol = &Symbol; - MSD.StringIndex = StringTable.getOffset(Symbol.getName()); - - if (Symbol.isAbsolute()) { - MSD.SectionIndex = 0; - LocalSymbolData.push_back(MSD); - } else { - MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection()); - assert(MSD.SectionIndex && "Invalid section index!"); - LocalSymbolData.push_back(MSD); - } - } - - // External and undefined symbols are required to be in lexicographic order. - llvm::sort(ExternalSymbolData); - llvm::sort(UndefinedSymbolData); - - // Set the symbol indices. - Index = 0; - for (auto *SymbolData : - {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData}) - for (MachSymbolData &Entry : *SymbolData) - Entry.Symbol->setIndex(Index++); - - for (const MCSection &Section : Asm) { - for (RelAndSymbol &Rel : Relocations[&Section]) { - if (!Rel.Sym) - continue; - - // Set the Index and the IsExtern bit. - unsigned Index = Rel.Sym->getIndex(); - assert(isInt<24>(Index)); - if (W.Endian == support::little) - Rel.MRE.r_word1 = (Rel.MRE.r_word1 & (~0U << 24)) | Index | (1 << 27); - else - Rel.MRE.r_word1 = (Rel.MRE.r_word1 & 0xff) | Index << 8 | (1 << 4); - } - } -} - -void MachObjectWriter::computeSectionAddresses(const MCAssembler &Asm, - const MCAsmLayout &Layout) { - uint64_t StartAddress = 0; - for (const MCSection *Sec : Layout.getSectionOrder()) { - StartAddress = alignTo(StartAddress, Sec->getAlignment()); - SectionAddress[Sec] = StartAddress; - StartAddress += Layout.getSectionAddressSize(Sec); - - // Explicitly pad the section to match the alignment requirements of the - // following one. This is for 'gas' compatibility, it shouldn't - /// strictly be necessary. - StartAddress += getPaddingSize(Sec, Layout); - } -} - -void MachObjectWriter::executePostLayoutBinding(MCAssembler &Asm, - const MCAsmLayout &Layout) { - computeSectionAddresses(Asm, Layout); - - // Create symbol data for any indirect symbols. - bindIndirectSymbols(Asm); -} - -bool MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl( - const MCAssembler &Asm, const MCSymbol &A, const MCSymbol &B, - bool InSet) const { - // FIXME: We don't handle things like - // foo = . - // creating atoms. - if (A.isVariable() || B.isVariable()) - return false; - return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, A, B, - InSet); -} - -bool MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl( - const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB, - bool InSet, bool IsPCRel) const { - if (InSet) - return true; - - // The effective address is - // addr(atom(A)) + offset(A) - // - addr(atom(B)) - offset(B) - // and the offsets are not relocatable, so the fixup is fully resolved when - // addr(atom(A)) - addr(atom(B)) == 0. - const MCSymbol &SA = findAliasedSymbol(SymA); - const MCSection &SecA = SA.getSection(); - const MCSection &SecB = *FB.getParent(); - - if (IsPCRel) { - // The simple (Darwin, except on x86_64) way of dealing with this was to - // assume that any reference to a temporary symbol *must* be a temporary - // symbol in the same atom, unless the sections differ. Therefore, any PCrel - // relocation to a temporary symbol (in the same section) is fully - // resolved. This also works in conjunction with absolutized .set, which - // requires the compiler to use .set to absolutize the differences between - // symbols which the compiler knows to be assembly time constants, so we - // don't need to worry about considering symbol differences fully resolved. - // - // If the file isn't using sub-sections-via-symbols, we can make the - // same assumptions about any symbol that we normally make about - // assembler locals. - - bool hasReliableSymbolDifference = isX86_64(); - if (!hasReliableSymbolDifference) { - if (!SA.isInSection() || &SecA != &SecB || - (!SA.isTemporary() && FB.getAtom() != SA.getFragment()->getAtom() && - Asm.getSubsectionsViaSymbols())) - return false; - return true; - } - // For Darwin x86_64, there is one special case when the reference IsPCRel. - // If the fragment with the reference does not have a base symbol but meets - // the simple way of dealing with this, in that it is a temporary symbol in - // the same atom then it is assumed to be fully resolved. This is needed so - // a relocation entry is not created and so the static linker does not - // mess up the reference later. - else if(!FB.getAtom() && - SA.isTemporary() && SA.isInSection() && &SecA == &SecB){ - return true; - } - } - - // If they are not in the same section, we can't compute the diff. - if (&SecA != &SecB) - return false; - - const MCFragment *FA = SA.getFragment(); - - // Bail if the symbol has no fragment. - if (!FA) - return false; - - // If the atoms are the same, they are guaranteed to have the same address. - if (FA->getAtom() == FB.getAtom()) - return true; - - // Otherwise, we can't prove this is fully resolved. - return false; -} - -static MachO::LoadCommandType getLCFromMCVM(MCVersionMinType Type) { - switch (Type) { - case MCVM_OSXVersionMin: return MachO::LC_VERSION_MIN_MACOSX; - case MCVM_IOSVersionMin: return MachO::LC_VERSION_MIN_IPHONEOS; - case MCVM_TvOSVersionMin: return MachO::LC_VERSION_MIN_TVOS; - case MCVM_WatchOSVersionMin: return MachO::LC_VERSION_MIN_WATCHOS; - } - llvm_unreachable("Invalid mc version min type"); -} - -uint64_t MachObjectWriter::writeObject(MCAssembler &Asm, - const MCAsmLayout &Layout) { - uint64_t StartOffset = W.OS.tell(); - - // Compute symbol table information and bind symbol indices. - computeSymbolTable(Asm, LocalSymbolData, ExternalSymbolData, - UndefinedSymbolData); - - unsigned NumSections = Asm.size(); - const MCAssembler::VersionInfoType &VersionInfo = - Layout.getAssembler().getVersionInfo(); - - // The section data starts after the header, the segment load command (and - // section headers) and the symbol table. - unsigned NumLoadCommands = 1; - uint64_t LoadCommandsSize = is64Bit() ? - sizeof(MachO::segment_command_64) + NumSections * sizeof(MachO::section_64): - sizeof(MachO::segment_command) + NumSections * sizeof(MachO::section); - - // Add the deployment target version info load command size, if used. - if (VersionInfo.Major != 0) { - ++NumLoadCommands; - if (VersionInfo.EmitBuildVersion) - LoadCommandsSize += sizeof(MachO::build_version_command); - else - LoadCommandsSize += sizeof(MachO::version_min_command); - } - - // Add the data-in-code load command size, if used. - unsigned NumDataRegions = Asm.getDataRegions().size(); - if (NumDataRegions) { - ++NumLoadCommands; - LoadCommandsSize += sizeof(MachO::linkedit_data_command); - } - - // Add the loh load command size, if used. - uint64_t LOHRawSize = Asm.getLOHContainer().getEmitSize(*this, Layout); - uint64_t LOHSize = alignTo(LOHRawSize, is64Bit() ? 8 : 4); - if (LOHSize) { - ++NumLoadCommands; - LoadCommandsSize += sizeof(MachO::linkedit_data_command); - } - - // Add the symbol table load command sizes, if used. - unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() + - UndefinedSymbolData.size(); - if (NumSymbols) { - NumLoadCommands += 2; - LoadCommandsSize += (sizeof(MachO::symtab_command) + - sizeof(MachO::dysymtab_command)); - } - - // Add the linker option load commands sizes. - for (const auto &Option : Asm.getLinkerOptions()) { - ++NumLoadCommands; - LoadCommandsSize += ComputeLinkerOptionsLoadCommandSize(Option, is64Bit()); - } - - // Compute the total size of the section data, as well as its file size and vm - // size. - uint64_t SectionDataStart = (is64Bit() ? sizeof(MachO::mach_header_64) : - sizeof(MachO::mach_header)) + LoadCommandsSize; - uint64_t SectionDataSize = 0; - uint64_t SectionDataFileSize = 0; - uint64_t VMSize = 0; - for (const MCSection &Sec : Asm) { - uint64_t Address = getSectionAddress(&Sec); - uint64_t Size = Layout.getSectionAddressSize(&Sec); - uint64_t FileSize = Layout.getSectionFileSize(&Sec); - FileSize += getPaddingSize(&Sec, Layout); - - VMSize = std::max(VMSize, Address + Size); - - if (Sec.isVirtualSection()) - continue; - - SectionDataSize = std::max(SectionDataSize, Address + Size); - SectionDataFileSize = std::max(SectionDataFileSize, Address + FileSize); - } - - // The section data is padded to 4 bytes. - // - // FIXME: Is this machine dependent? - unsigned SectionDataPadding = OffsetToAlignment(SectionDataFileSize, 4); - SectionDataFileSize += SectionDataPadding; - - // Write the prolog, starting with the header and load command... - writeHeader(MachO::MH_OBJECT, NumLoadCommands, LoadCommandsSize, - Asm.getSubsectionsViaSymbols()); - uint32_t Prot = - MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE; - writeSegmentLoadCommand("", NumSections, 0, VMSize, SectionDataStart, - SectionDataSize, Prot, Prot); - - // ... and then the section headers. - uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize; - for (const MCSection &Section : Asm) { - const auto &Sec = cast<MCSectionMachO>(Section); - std::vector<RelAndSymbol> &Relocs = Relocations[&Sec]; - unsigned NumRelocs = Relocs.size(); - uint64_t SectionStart = SectionDataStart + getSectionAddress(&Sec); - unsigned Flags = Sec.getTypeAndAttributes(); - if (Sec.hasInstructions()) - Flags |= MachO::S_ATTR_SOME_INSTRUCTIONS; - writeSection(Layout, Sec, getSectionAddress(&Sec), SectionStart, Flags, - RelocTableEnd, NumRelocs); - RelocTableEnd += NumRelocs * sizeof(MachO::any_relocation_info); - } - - // Write out the deployment target information, if it's available. - if (VersionInfo.Major != 0) { - auto EncodeVersion = [](VersionTuple V) -> uint32_t { - assert(!V.empty() && "empty version"); - unsigned Update = V.getSubminor() ? *V.getSubminor() : 0; - unsigned Minor = V.getMinor() ? *V.getMinor() : 0; - assert(Update < 256 && "unencodable update target version"); - assert(Minor < 256 && "unencodable minor target version"); - assert(V.getMajor() < 65536 && "unencodable major target version"); - return Update | (Minor << 8) | (V.getMajor() << 16); - }; - uint32_t EncodedVersion = EncodeVersion( - VersionTuple(VersionInfo.Major, VersionInfo.Minor, VersionInfo.Update)); - uint32_t SDKVersion = !VersionInfo.SDKVersion.empty() - ? EncodeVersion(VersionInfo.SDKVersion) - : 0; - if (VersionInfo.EmitBuildVersion) { - // FIXME: Currently empty tools. Add clang version in the future. - W.write<uint32_t>(MachO::LC_BUILD_VERSION); - W.write<uint32_t>(sizeof(MachO::build_version_command)); - W.write<uint32_t>(VersionInfo.TypeOrPlatform.Platform); - W.write<uint32_t>(EncodedVersion); - W.write<uint32_t>(SDKVersion); - W.write<uint32_t>(0); // Empty tools list. - } else { - MachO::LoadCommandType LCType - = getLCFromMCVM(VersionInfo.TypeOrPlatform.Type); - W.write<uint32_t>(LCType); - W.write<uint32_t>(sizeof(MachO::version_min_command)); - W.write<uint32_t>(EncodedVersion); - W.write<uint32_t>(SDKVersion); - } - } - - // Write the data-in-code load command, if used. - uint64_t DataInCodeTableEnd = RelocTableEnd + NumDataRegions * 8; - if (NumDataRegions) { - uint64_t DataRegionsOffset = RelocTableEnd; - uint64_t DataRegionsSize = NumDataRegions * 8; - writeLinkeditLoadCommand(MachO::LC_DATA_IN_CODE, DataRegionsOffset, - DataRegionsSize); - } - - // Write the loh load command, if used. - uint64_t LOHTableEnd = DataInCodeTableEnd + LOHSize; - if (LOHSize) - writeLinkeditLoadCommand(MachO::LC_LINKER_OPTIMIZATION_HINT, - DataInCodeTableEnd, LOHSize); - - // Write the symbol table load command, if used. - if (NumSymbols) { - unsigned FirstLocalSymbol = 0; - unsigned NumLocalSymbols = LocalSymbolData.size(); - unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols; - unsigned NumExternalSymbols = ExternalSymbolData.size(); - unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols; - unsigned NumUndefinedSymbols = UndefinedSymbolData.size(); - unsigned NumIndirectSymbols = Asm.indirect_symbol_size(); - unsigned NumSymTabSymbols = - NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols; - uint64_t IndirectSymbolSize = NumIndirectSymbols * 4; - uint64_t IndirectSymbolOffset = 0; - - // If used, the indirect symbols are written after the section data. - if (NumIndirectSymbols) - IndirectSymbolOffset = LOHTableEnd; - - // The symbol table is written after the indirect symbol data. - uint64_t SymbolTableOffset = LOHTableEnd + IndirectSymbolSize; - - // The string table is written after symbol table. - uint64_t StringTableOffset = - SymbolTableOffset + NumSymTabSymbols * (is64Bit() ? - sizeof(MachO::nlist_64) : - sizeof(MachO::nlist)); - writeSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols, - StringTableOffset, StringTable.getSize()); - - writeDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols, - FirstExternalSymbol, NumExternalSymbols, - FirstUndefinedSymbol, NumUndefinedSymbols, - IndirectSymbolOffset, NumIndirectSymbols); - } - - // Write the linker options load commands. - for (const auto &Option : Asm.getLinkerOptions()) - writeLinkerOptionsLoadCommand(Option); - - // Write the actual section data. - for (const MCSection &Sec : Asm) { - Asm.writeSectionData(W.OS, &Sec, Layout); - - uint64_t Pad = getPaddingSize(&Sec, Layout); - W.OS.write_zeros(Pad); - } - - // Write the extra padding. - W.OS.write_zeros(SectionDataPadding); - - // Write the relocation entries. - for (const MCSection &Sec : Asm) { - // Write the section relocation entries, in reverse order to match 'as' - // (approximately, the exact algorithm is more complicated than this). - std::vector<RelAndSymbol> &Relocs = Relocations[&Sec]; - for (const RelAndSymbol &Rel : make_range(Relocs.rbegin(), Relocs.rend())) { - W.write<uint32_t>(Rel.MRE.r_word0); - W.write<uint32_t>(Rel.MRE.r_word1); - } - } - - // Write out the data-in-code region payload, if there is one. - for (MCAssembler::const_data_region_iterator - it = Asm.data_region_begin(), ie = Asm.data_region_end(); - it != ie; ++it) { - const DataRegionData *Data = &(*it); - uint64_t Start = getSymbolAddress(*Data->Start, Layout); - uint64_t End; - if (Data->End) - End = getSymbolAddress(*Data->End, Layout); - else - report_fatal_error("Data region not terminated"); - - LLVM_DEBUG(dbgs() << "data in code region-- kind: " << Data->Kind - << " start: " << Start << "(" << Data->Start->getName() - << ")" - << " end: " << End << "(" << Data->End->getName() << ")" - << " size: " << End - Start << "\n"); - W.write<uint32_t>(Start); - W.write<uint16_t>(End - Start); - W.write<uint16_t>(Data->Kind); - } - - // Write out the loh commands, if there is one. - if (LOHSize) { -#ifndef NDEBUG - unsigned Start = W.OS.tell(); -#endif - Asm.getLOHContainer().emit(*this, Layout); - // Pad to a multiple of the pointer size. - W.OS.write_zeros(OffsetToAlignment(LOHRawSize, is64Bit() ? 8 : 4)); - assert(W.OS.tell() - Start == LOHSize); - } - - // Write the symbol table data, if used. - if (NumSymbols) { - // Write the indirect symbol entries. - for (MCAssembler::const_indirect_symbol_iterator - it = Asm.indirect_symbol_begin(), - ie = Asm.indirect_symbol_end(); it != ie; ++it) { - // Indirect symbols in the non-lazy symbol pointer section have some - // special handling. - const MCSectionMachO &Section = - static_cast<const MCSectionMachO &>(*it->Section); - if (Section.getType() == MachO::S_NON_LAZY_SYMBOL_POINTERS) { - // If this symbol is defined and internal, mark it as such. - if (it->Symbol->isDefined() && !it->Symbol->isExternal()) { - uint32_t Flags = MachO::INDIRECT_SYMBOL_LOCAL; - if (it->Symbol->isAbsolute()) - Flags |= MachO::INDIRECT_SYMBOL_ABS; - W.write<uint32_t>(Flags); - continue; - } - } - - W.write<uint32_t>(it->Symbol->getIndex()); - } - - // FIXME: Check that offsets match computed ones. - - // Write the symbol table entries. - for (auto *SymbolData : - {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData}) - for (MachSymbolData &Entry : *SymbolData) - writeNlist(Entry, Layout); - - // Write the string table. - StringTable.write(W.OS); - } - - return W.OS.tell() - StartOffset; -} - -std::unique_ptr<MCObjectWriter> -llvm::createMachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW, - raw_pwrite_stream &OS, bool IsLittleEndian) { - return llvm::make_unique<MachObjectWriter>(std::move(MOTW), OS, - IsLittleEndian); -} diff --git a/contrib/llvm/lib/MC/StringTableBuilder.cpp b/contrib/llvm/lib/MC/StringTableBuilder.cpp deleted file mode 100644 index cb3db8e2268c..000000000000 --- a/contrib/llvm/lib/MC/StringTableBuilder.cpp +++ /dev/null @@ -1,195 +0,0 @@ -//===- StringTableBuilder.cpp - String table building utility -------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/StringTableBuilder.h" -#include "llvm/ADT/CachedHashString.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/BinaryFormat/COFF.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> -#include <cstddef> -#include <cstdint> -#include <cstring> -#include <utility> -#include <vector> - -using namespace llvm; - -StringTableBuilder::~StringTableBuilder() = default; - -void StringTableBuilder::initSize() { - // Account for leading bytes in table so that offsets returned from add are - // correct. - switch (K) { - case RAW: - case DWARF: - Size = 0; - break; - case MachO: - case ELF: - // Start the table with a NUL byte. - Size = 1; - break; - case WinCOFF: - // Make room to write the table size later. - Size = 4; - break; - } -} - -StringTableBuilder::StringTableBuilder(Kind K, unsigned Alignment) - : K(K), Alignment(Alignment) { - initSize(); -} - -void StringTableBuilder::write(raw_ostream &OS) const { - assert(isFinalized()); - SmallString<0> Data; - Data.resize(getSize()); - write((uint8_t *)Data.data()); - OS << Data; -} - -using StringPair = std::pair<CachedHashStringRef, size_t>; - -void StringTableBuilder::write(uint8_t *Buf) const { - assert(isFinalized()); - for (const StringPair &P : StringIndexMap) { - StringRef Data = P.first.val(); - if (!Data.empty()) - memcpy(Buf + P.second, Data.data(), Data.size()); - } - if (K != WinCOFF) - return; - support::endian::write32le(Buf, Size); -} - -// Returns the character at Pos from end of a string. -static int charTailAt(StringPair *P, size_t Pos) { - StringRef S = P->first.val(); - if (Pos >= S.size()) - return -1; - return (unsigned char)S[S.size() - Pos - 1]; -} - -// Three-way radix quicksort. This is much faster than std::sort with strcmp -// because it does not compare characters that we already know the same. -static void multikeySort(MutableArrayRef<StringPair *> Vec, int Pos) { -tailcall: - if (Vec.size() <= 1) - return; - - // Partition items so that items in [0, I) are greater than the pivot, - // [I, J) are the same as the pivot, and [J, Vec.size()) are less than - // the pivot. - int Pivot = charTailAt(Vec[0], Pos); - size_t I = 0; - size_t J = Vec.size(); - for (size_t K = 1; K < J;) { - int C = charTailAt(Vec[K], Pos); - if (C > Pivot) - std::swap(Vec[I++], Vec[K++]); - else if (C < Pivot) - std::swap(Vec[--J], Vec[K]); - else - K++; - } - - multikeySort(Vec.slice(0, I), Pos); - multikeySort(Vec.slice(J), Pos); - - // multikeySort(Vec.slice(I, J - I), Pos + 1), but with - // tail call optimization. - if (Pivot != -1) { - Vec = Vec.slice(I, J - I); - ++Pos; - goto tailcall; - } -} - -void StringTableBuilder::finalize() { - assert(K != DWARF); - finalizeStringTable(/*Optimize=*/true); -} - -void StringTableBuilder::finalizeInOrder() { - finalizeStringTable(/*Optimize=*/false); -} - -void StringTableBuilder::finalizeStringTable(bool Optimize) { - Finalized = true; - - if (Optimize) { - std::vector<StringPair *> Strings; - Strings.reserve(StringIndexMap.size()); - for (StringPair &P : StringIndexMap) - Strings.push_back(&P); - - multikeySort(Strings, 0); - initSize(); - - StringRef Previous; - for (StringPair *P : Strings) { - StringRef S = P->first.val(); - if (Previous.endswith(S)) { - size_t Pos = Size - S.size() - (K != RAW); - if (!(Pos & (Alignment - 1))) { - P->second = Pos; - continue; - } - } - - Size = alignTo(Size, Alignment); - P->second = Size; - - Size += S.size(); - if (K != RAW) - ++Size; - Previous = S; - } - } - - if (K == MachO) - Size = alignTo(Size, 4); // Pad to multiple of 4. - - // The first byte in an ELF string table must be null, according to the ELF - // specification. In 'initSize()' we reserved the first byte to hold null for - // this purpose and here we actually add the string to allow 'getOffset()' to - // be called on an empty string. - if (K == ELF) - StringIndexMap[CachedHashStringRef("")] = 0; -} - -void StringTableBuilder::clear() { - Finalized = false; - StringIndexMap.clear(); -} - -size_t StringTableBuilder::getOffset(CachedHashStringRef S) const { - assert(isFinalized()); - auto I = StringIndexMap.find(S); - assert(I != StringIndexMap.end() && "String is not in table!"); - return I->second; -} - -size_t StringTableBuilder::add(CachedHashStringRef S) { - if (K == WinCOFF) - assert(S.size() > COFF::NameSize && "Short string in COFF string table!"); - - assert(!isFinalized()); - auto P = StringIndexMap.insert(std::make_pair(S, 0)); - if (P.second) { - size_t Start = alignTo(Size, Alignment); - P.first->second = Start; - Size = Start + S.size() + (K != RAW); - } - return P.first->second; -} diff --git a/contrib/llvm/lib/MC/SubtargetFeature.cpp b/contrib/llvm/lib/MC/SubtargetFeature.cpp deleted file mode 100644 index c4dd77359b24..000000000000 --- a/contrib/llvm/lib/MC/SubtargetFeature.cpp +++ /dev/null @@ -1,82 +0,0 @@ -//===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file Implements the SubtargetFeature interface. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/SubtargetFeature.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" -#include "llvm/Config/llvm-config.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cassert> -#include <cstddef> -#include <cstring> -#include <iterator> -#include <string> -#include <vector> - -using namespace llvm; - -/// Splits a string of comma separated items in to a vector of strings. -void SubtargetFeatures::Split(std::vector<std::string> &V, StringRef S) { - SmallVector<StringRef, 3> Tmp; - S.split(Tmp, ',', -1, false /* KeepEmpty */); - V.assign(Tmp.begin(), Tmp.end()); -} - -void SubtargetFeatures::AddFeature(StringRef String, bool Enable) { - // Don't add empty features. - if (!String.empty()) - // Convert to lowercase, prepend flag if we don't already have a flag. - Features.push_back(hasFlag(String) ? String.lower() - : (Enable ? "+" : "-") + String.lower()); -} - -SubtargetFeatures::SubtargetFeatures(StringRef Initial) { - // Break up string into separate features - Split(Features, Initial); -} - -std::string SubtargetFeatures::getString() const { - return join(Features.begin(), Features.end(), ","); -} - -void SubtargetFeatures::print(raw_ostream &OS) const { - for (auto &F : Features) - OS << F << " "; - OS << "\n"; -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -LLVM_DUMP_METHOD void SubtargetFeatures::dump() const { - print(dbgs()); -} -#endif - -void SubtargetFeatures::getDefaultSubtargetFeatures(const Triple& Triple) { - // FIXME: This is an inelegant way of specifying the features of a - // subtarget. It would be better if we could encode this information - // into the IR. See <rdar://5972456>. - if (Triple.getVendor() == Triple::Apple) { - if (Triple.getArch() == Triple::ppc) { - // powerpc-apple-* - AddFeature("altivec"); - } else if (Triple.getArch() == Triple::ppc64) { - // powerpc64-apple-* - AddFeature("64bit"); - AddFeature("altivec"); - } - } -} diff --git a/contrib/llvm/lib/MC/WasmObjectWriter.cpp b/contrib/llvm/lib/MC/WasmObjectWriter.cpp deleted file mode 100644 index 098343cd0107..000000000000 --- a/contrib/llvm/lib/MC/WasmObjectWriter.cpp +++ /dev/null @@ -1,1622 +0,0 @@ -//===- lib/MC/WasmObjectWriter.cpp - Wasm File Writer ---------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements Wasm object file writer information. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/BinaryFormat/Wasm.h" -#include "llvm/Config/llvm-config.h" -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCAsmLayout.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFixupKindInfo.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCSectionWasm.h" -#include "llvm/MC/MCSymbolWasm.h" -#include "llvm/MC/MCValue.h" -#include "llvm/MC/MCWasmObjectWriter.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/LEB128.h" -#include "llvm/Support/StringSaver.h" -#include <vector> - -using namespace llvm; - -#define DEBUG_TYPE "mc" - -namespace { - -// Went we ceate the indirect function table we start at 1, so that there is -// and emtpy slot at 0 and therefore calling a null function pointer will trap. -static const uint32_t InitialTableOffset = 1; - -// For patching purposes, we need to remember where each section starts, both -// for patching up the section size field, and for patching up references to -// locations within the section. -struct SectionBookkeeping { - // Where the size of the section is written. - uint64_t SizeOffset; - // Where the section header ends (without custom section name). - uint64_t PayloadOffset; - // Where the contents of the section starts. - uint64_t ContentsOffset; - uint32_t Index; -}; - -// The signature of a wasm function or event, in a struct capable of being used -// as a DenseMap key. -// TODO: Consider using wasm::WasmSignature directly instead. -struct WasmSignature { - // Support empty and tombstone instances, needed by DenseMap. - enum { Plain, Empty, Tombstone } State = Plain; - - // The return types of the function. - SmallVector<wasm::ValType, 1> Returns; - - // The parameter types of the function. - SmallVector<wasm::ValType, 4> Params; - - bool operator==(const WasmSignature &Other) const { - return State == Other.State && Returns == Other.Returns && - Params == Other.Params; - } -}; - -// Traits for using WasmSignature in a DenseMap. -struct WasmSignatureDenseMapInfo { - static WasmSignature getEmptyKey() { - WasmSignature Sig; - Sig.State = WasmSignature::Empty; - return Sig; - } - static WasmSignature getTombstoneKey() { - WasmSignature Sig; - Sig.State = WasmSignature::Tombstone; - return Sig; - } - static unsigned getHashValue(const WasmSignature &Sig) { - uintptr_t Value = Sig.State; - for (wasm::ValType Ret : Sig.Returns) - Value += DenseMapInfo<uint32_t>::getHashValue(uint32_t(Ret)); - for (wasm::ValType Param : Sig.Params) - Value += DenseMapInfo<uint32_t>::getHashValue(uint32_t(Param)); - return Value; - } - static bool isEqual(const WasmSignature &LHS, const WasmSignature &RHS) { - return LHS == RHS; - } -}; - -// A wasm data segment. A wasm binary contains only a single data section -// but that can contain many segments, each with their own virtual location -// in memory. Each MCSection data created by llvm is modeled as its own -// wasm data segment. -struct WasmDataSegment { - MCSectionWasm *Section; - StringRef Name; - uint32_t InitFlags; - uint32_t Offset; - uint32_t Alignment; - uint32_t LinkerFlags; - SmallVector<char, 4> Data; -}; - -// A wasm function to be written into the function section. -struct WasmFunction { - uint32_t SigIndex; - const MCSymbolWasm *Sym; -}; - -// A wasm global to be written into the global section. -struct WasmGlobal { - wasm::WasmGlobalType Type; - uint64_t InitialValue; -}; - -// Information about a single item which is part of a COMDAT. For each data -// segment or function which is in the COMDAT, there is a corresponding -// WasmComdatEntry. -struct WasmComdatEntry { - unsigned Kind; - uint32_t Index; -}; - -// Information about a single relocation. -struct WasmRelocationEntry { - uint64_t Offset; // Where is the relocation. - const MCSymbolWasm *Symbol; // The symbol to relocate with. - int64_t Addend; // A value to add to the symbol. - unsigned Type; // The type of the relocation. - const MCSectionWasm *FixupSection; // The section the relocation is targeting. - - WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol, - int64_t Addend, unsigned Type, - const MCSectionWasm *FixupSection) - : Offset(Offset), Symbol(Symbol), Addend(Addend), Type(Type), - FixupSection(FixupSection) {} - - bool hasAddend() const { return wasm::relocTypeHasAddend(Type); } - - void print(raw_ostream &Out) const { - Out << wasm::relocTypetoString(Type) << " Off=" << Offset - << ", Sym=" << *Symbol << ", Addend=" << Addend - << ", FixupSection=" << FixupSection->getSectionName(); - } - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - LLVM_DUMP_METHOD void dump() const { print(dbgs()); } -#endif -}; - -static const uint32_t InvalidIndex = -1; - -struct WasmCustomSection { - - StringRef Name; - MCSectionWasm *Section; - - uint32_t OutputContentsOffset; - uint32_t OutputIndex; - - WasmCustomSection(StringRef Name, MCSectionWasm *Section) - : Name(Name), Section(Section), OutputContentsOffset(0), - OutputIndex(InvalidIndex) {} -}; - -#if !defined(NDEBUG) -raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) { - Rel.print(OS); - return OS; -} -#endif - -// Write X as an (unsigned) LEB value at offset Offset in Stream, padded -// to allow patching. -static void writePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, - uint64_t Offset) { - uint8_t Buffer[5]; - unsigned SizeLen = encodeULEB128(X, Buffer, 5); - assert(SizeLen == 5); - Stream.pwrite((char *)Buffer, SizeLen, Offset); -} - -// Write X as an signed LEB value at offset Offset in Stream, padded -// to allow patching. -static void writePatchableSLEB(raw_pwrite_stream &Stream, int32_t X, - uint64_t Offset) { - uint8_t Buffer[5]; - unsigned SizeLen = encodeSLEB128(X, Buffer, 5); - assert(SizeLen == 5); - Stream.pwrite((char *)Buffer, SizeLen, Offset); -} - -// Write X as a plain integer value at offset Offset in Stream. -static void writeI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) { - uint8_t Buffer[4]; - support::endian::write32le(Buffer, X); - Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset); -} - -class WasmObjectWriter : public MCObjectWriter { - support::endian::Writer W; - - /// The target specific Wasm writer instance. - std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter; - - // Relocations for fixing up references in the code section. - std::vector<WasmRelocationEntry> CodeRelocations; - uint32_t CodeSectionIndex; - - // Relocations for fixing up references in the data section. - std::vector<WasmRelocationEntry> DataRelocations; - uint32_t DataSectionIndex; - - // Index values to use for fixing up call_indirect type indices. - // Maps function symbols to the index of the type of the function - DenseMap<const MCSymbolWasm *, uint32_t> TypeIndices; - // Maps function symbols to the table element index space. Used - // for TABLE_INDEX relocation types (i.e. address taken functions). - DenseMap<const MCSymbolWasm *, uint32_t> TableIndices; - // Maps function/global symbols to the function/global/event/section index - // space. - DenseMap<const MCSymbolWasm *, uint32_t> WasmIndices; - DenseMap<const MCSymbolWasm *, uint32_t> GOTIndices; - // Maps data symbols to the Wasm segment and offset/size with the segment. - DenseMap<const MCSymbolWasm *, wasm::WasmDataReference> DataLocations; - - // Stores output data (index, relocations, content offset) for custom - // section. - std::vector<WasmCustomSection> CustomSections; - std::unique_ptr<WasmCustomSection> ProducersSection; - std::unique_ptr<WasmCustomSection> TargetFeaturesSection; - // Relocations for fixing up references in the custom sections. - DenseMap<const MCSectionWasm *, std::vector<WasmRelocationEntry>> - CustomSectionsRelocations; - - // Map from section to defining function symbol. - DenseMap<const MCSection *, const MCSymbol *> SectionFunctions; - - DenseMap<WasmSignature, uint32_t, WasmSignatureDenseMapInfo> SignatureIndices; - SmallVector<WasmSignature, 4> Signatures; - SmallVector<WasmDataSegment, 4> DataSegments; - unsigned NumFunctionImports = 0; - unsigned NumGlobalImports = 0; - unsigned NumEventImports = 0; - uint32_t SectionCount = 0; - - // TargetObjectWriter wrappers. - bool is64Bit() const { return TargetObjectWriter->is64Bit(); } - - void startSection(SectionBookkeeping &Section, unsigned SectionId); - void startCustomSection(SectionBookkeeping &Section, StringRef Name); - void endSection(SectionBookkeeping &Section); - -public: - WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW, - raw_pwrite_stream &OS) - : W(OS, support::little), TargetObjectWriter(std::move(MOTW)) {} - -private: - void reset() override { - CodeRelocations.clear(); - DataRelocations.clear(); - TypeIndices.clear(); - WasmIndices.clear(); - GOTIndices.clear(); - TableIndices.clear(); - DataLocations.clear(); - CustomSections.clear(); - ProducersSection.reset(); - TargetFeaturesSection.reset(); - CustomSectionsRelocations.clear(); - SignatureIndices.clear(); - Signatures.clear(); - DataSegments.clear(); - SectionFunctions.clear(); - NumFunctionImports = 0; - NumGlobalImports = 0; - MCObjectWriter::reset(); - } - - void writeHeader(const MCAssembler &Asm); - - void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, - const MCFragment *Fragment, const MCFixup &Fixup, - MCValue Target, uint64_t &FixedValue) override; - - void executePostLayoutBinding(MCAssembler &Asm, - const MCAsmLayout &Layout) override; - - uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; - - void writeString(const StringRef Str) { - encodeULEB128(Str.size(), W.OS); - W.OS << Str; - } - - void writeValueType(wasm::ValType Ty) { W.OS << static_cast<char>(Ty); } - - void writeTypeSection(ArrayRef<WasmSignature> Signatures); - void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint32_t DataSize, - uint32_t NumElements); - void writeFunctionSection(ArrayRef<WasmFunction> Functions); - void writeExportSection(ArrayRef<wasm::WasmExport> Exports); - void writeElemSection(ArrayRef<uint32_t> TableElems); - void writeDataCountSection(); - void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout, - ArrayRef<WasmFunction> Functions); - void writeDataSection(); - void writeEventSection(ArrayRef<wasm::WasmEventType> Events); - void writeRelocSection(uint32_t SectionIndex, StringRef Name, - std::vector<WasmRelocationEntry> &Relocations); - void writeLinkingMetaDataSection( - ArrayRef<wasm::WasmSymbolInfo> SymbolInfos, - ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs, - const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats); - void writeCustomSection(WasmCustomSection &CustomSection, - const MCAssembler &Asm, const MCAsmLayout &Layout); - void writeCustomRelocSections(); - void - updateCustomSectionRelocations(const SmallVector<WasmFunction, 4> &Functions, - const MCAsmLayout &Layout); - - uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry); - void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations, - uint64_t ContentsOffset); - - uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry); - uint32_t getFunctionType(const MCSymbolWasm &Symbol); - uint32_t getEventType(const MCSymbolWasm &Symbol); - void registerFunctionType(const MCSymbolWasm &Symbol); - void registerEventType(const MCSymbolWasm &Symbol); -}; - -} // end anonymous namespace - -// Write out a section header and a patchable section size field. -void WasmObjectWriter::startSection(SectionBookkeeping &Section, - unsigned SectionId) { - LLVM_DEBUG(dbgs() << "startSection " << SectionId << "\n"); - W.OS << char(SectionId); - - Section.SizeOffset = W.OS.tell(); - - // The section size. We don't know the size yet, so reserve enough space - // for any 32-bit value; we'll patch it later. - encodeULEB128(0, W.OS, 5); - - // The position where the section starts, for measuring its size. - Section.ContentsOffset = W.OS.tell(); - Section.PayloadOffset = W.OS.tell(); - Section.Index = SectionCount++; -} - -void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section, - StringRef Name) { - LLVM_DEBUG(dbgs() << "startCustomSection " << Name << "\n"); - startSection(Section, wasm::WASM_SEC_CUSTOM); - - // The position where the section header ends, for measuring its size. - Section.PayloadOffset = W.OS.tell(); - - // Custom sections in wasm also have a string identifier. - writeString(Name); - - // The position where the custom section starts. - Section.ContentsOffset = W.OS.tell(); -} - -// Now that the section is complete and we know how big it is, patch up the -// section size field at the start of the section. -void WasmObjectWriter::endSection(SectionBookkeeping &Section) { - uint64_t Size = W.OS.tell(); - // /dev/null doesn't support seek/tell and can report offset of 0. - // Simply skip this patching in that case. - if (!Size) - return; - - Size -= Section.PayloadOffset; - if (uint32_t(Size) != Size) - report_fatal_error("section size does not fit in a uint32_t"); - - LLVM_DEBUG(dbgs() << "endSection size=" << Size << "\n"); - - // Write the final section size to the payload_len field, which follows - // the section id byte. - writePatchableLEB(static_cast<raw_pwrite_stream &>(W.OS), Size, - Section.SizeOffset); -} - -// Emit the Wasm header. -void WasmObjectWriter::writeHeader(const MCAssembler &Asm) { - W.OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic)); - W.write<uint32_t>(wasm::WasmVersion); -} - -void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm, - const MCAsmLayout &Layout) { - // Build a map of sections to the function that defines them, for use - // in recordRelocation. - for (const MCSymbol &S : Asm.symbols()) { - const auto &WS = static_cast<const MCSymbolWasm &>(S); - if (WS.isDefined() && WS.isFunction() && !WS.isVariable()) { - const auto &Sec = static_cast<const MCSectionWasm &>(S.getSection()); - auto Pair = SectionFunctions.insert(std::make_pair(&Sec, &S)); - if (!Pair.second) - report_fatal_error("section already has a defining function: " + - Sec.getSectionName()); - } - } -} - -void WasmObjectWriter::recordRelocation(MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, MCValue Target, - uint64_t &FixedValue) { - MCAsmBackend &Backend = Asm.getBackend(); - bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags & - MCFixupKindInfo::FKF_IsPCRel; - const auto &FixupSection = cast<MCSectionWasm>(*Fragment->getParent()); - uint64_t C = Target.getConstant(); - uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); - MCContext &Ctx = Asm.getContext(); - - // The .init_array isn't translated as data, so don't do relocations in it. - if (FixupSection.getSectionName().startswith(".init_array")) - return; - - if (const MCSymbolRefExpr *RefB = Target.getSymB()) { - assert(RefB->getKind() == MCSymbolRefExpr::VK_None && - "Should not have constructed this"); - - // Let A, B and C being the components of Target and R be the location of - // the fixup. If the fixup is not pcrel, we want to compute (A - B + C). - // If it is pcrel, we want to compute (A - B + C - R). - - // In general, Wasm has no relocations for -B. It can only represent (A + C) - // or (A + C - R). If B = R + K and the relocation is not pcrel, we can - // replace B to implement it: (A - R - K + C) - if (IsPCRel) { - Ctx.reportError( - Fixup.getLoc(), - "No relocation available to represent this relative expression"); - return; - } - - const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol()); - - if (SymB.isUndefined()) { - Ctx.reportError(Fixup.getLoc(), - Twine("symbol '") + SymB.getName() + - "' can not be undefined in a subtraction expression"); - return; - } - - assert(!SymB.isAbsolute() && "Should have been folded"); - const MCSection &SecB = SymB.getSection(); - if (&SecB != &FixupSection) { - Ctx.reportError(Fixup.getLoc(), - "Cannot represent a difference across sections"); - return; - } - - uint64_t SymBOffset = Layout.getSymbolOffset(SymB); - uint64_t K = SymBOffset - FixupOffset; - IsPCRel = true; - C -= K; - } - - // We either rejected the fixup or folded B into C at this point. - const MCSymbolRefExpr *RefA = Target.getSymA(); - const auto *SymA = RefA ? cast<MCSymbolWasm>(&RefA->getSymbol()) : nullptr; - - if (SymA && SymA->isVariable()) { - const MCExpr *Expr = SymA->getVariableValue(); - const auto *Inner = cast<MCSymbolRefExpr>(Expr); - if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) - llvm_unreachable("weakref used in reloc not yet implemented"); - } - - // Put any constant offset in an addend. Offsets can be negative, and - // LLVM expects wrapping, in contrast to wasm's immediates which can't - // be negative and don't wrap. - FixedValue = 0; - - unsigned Type = TargetObjectWriter->getRelocType(Target, Fixup); - assert(!IsPCRel); - assert(SymA); - - // Absolute offset within a section or a function. - // Currently only supported for for metadata sections. - // See: test/MC/WebAssembly/blockaddress.ll - if (Type == wasm::R_WASM_FUNCTION_OFFSET_I32 || - Type == wasm::R_WASM_SECTION_OFFSET_I32) { - if (!FixupSection.getKind().isMetadata()) - report_fatal_error("relocations for function or section offsets are " - "only supported in metadata sections"); - - const MCSymbol *SectionSymbol = nullptr; - const MCSection &SecA = SymA->getSection(); - if (SecA.getKind().isText()) - SectionSymbol = SectionFunctions.find(&SecA)->second; - else - SectionSymbol = SecA.getBeginSymbol(); - if (!SectionSymbol) - report_fatal_error("section symbol is required for relocation"); - - C += Layout.getSymbolOffset(*SymA); - SymA = cast<MCSymbolWasm>(SectionSymbol); - } - - // Relocation other than R_WASM_TYPE_INDEX_LEB are required to be - // against a named symbol. - if (Type != wasm::R_WASM_TYPE_INDEX_LEB) { - if (SymA->getName().empty()) - report_fatal_error("relocations against un-named temporaries are not yet " - "supported by wasm"); - - SymA->setUsedInReloc(); - } - - if (RefA->getKind() == MCSymbolRefExpr::VK_GOT) - SymA->setUsedInGOT(); - - WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection); - LLVM_DEBUG(dbgs() << "WasmReloc: " << Rec << "\n"); - - if (FixupSection.isWasmData()) { - DataRelocations.push_back(Rec); - } else if (FixupSection.getKind().isText()) { - CodeRelocations.push_back(Rec); - } else if (FixupSection.getKind().isMetadata()) { - CustomSectionsRelocations[&FixupSection].push_back(Rec); - } else { - llvm_unreachable("unexpected section type"); - } -} - -static const MCSymbolWasm *resolveSymbol(const MCSymbolWasm &Symbol) { - const MCSymbolWasm* Ret = &Symbol; - while (Ret->isVariable()) { - const MCExpr *Expr = Ret->getVariableValue(); - auto *Inner = cast<MCSymbolRefExpr>(Expr); - Ret = cast<MCSymbolWasm>(&Inner->getSymbol()); - } - return Ret; -} - -// Compute a value to write into the code at the location covered -// by RelEntry. This value isn't used by the static linker; it just serves -// to make the object format more readable and more likely to be directly -// useable. -uint32_t -WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) { - if (RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_LEB && !RelEntry.Symbol->isGlobal()) { - assert(GOTIndices.count(RelEntry.Symbol) > 0 && "symbol not found in GOT index space"); - return GOTIndices[RelEntry.Symbol]; - } - - switch (RelEntry.Type) { - case wasm::R_WASM_TABLE_INDEX_REL_SLEB: - case wasm::R_WASM_TABLE_INDEX_SLEB: - case wasm::R_WASM_TABLE_INDEX_I32: { - // Provisional value is table address of the resolved symbol itself - const MCSymbolWasm *Sym = resolveSymbol(*RelEntry.Symbol); - assert(Sym->isFunction()); - return TableIndices[Sym]; - } - case wasm::R_WASM_TYPE_INDEX_LEB: - // Provisional value is same as the index - return getRelocationIndexValue(RelEntry); - case wasm::R_WASM_FUNCTION_INDEX_LEB: - case wasm::R_WASM_GLOBAL_INDEX_LEB: - case wasm::R_WASM_EVENT_INDEX_LEB: - // Provisional value is function/global/event Wasm index - assert(WasmIndices.count(RelEntry.Symbol) > 0 && "symbol not found in wasm index space"); - return WasmIndices[RelEntry.Symbol]; - case wasm::R_WASM_FUNCTION_OFFSET_I32: - case wasm::R_WASM_SECTION_OFFSET_I32: { - const auto &Section = - static_cast<const MCSectionWasm &>(RelEntry.Symbol->getSection()); - return Section.getSectionOffset() + RelEntry.Addend; - } - case wasm::R_WASM_MEMORY_ADDR_LEB: - case wasm::R_WASM_MEMORY_ADDR_I32: - case wasm::R_WASM_MEMORY_ADDR_REL_SLEB: - case wasm::R_WASM_MEMORY_ADDR_SLEB: { - // Provisional value is address of the global - const MCSymbolWasm *Sym = resolveSymbol(*RelEntry.Symbol); - // For undefined symbols, use zero - if (!Sym->isDefined()) - return 0; - const wasm::WasmDataReference &Ref = DataLocations[Sym]; - const WasmDataSegment &Segment = DataSegments[Ref.Segment]; - // Ignore overflow. LLVM allows address arithmetic to silently wrap. - return Segment.Offset + Ref.Offset + RelEntry.Addend; - } - default: - llvm_unreachable("invalid relocation type"); - } -} - -static void addData(SmallVectorImpl<char> &DataBytes, - MCSectionWasm &DataSection) { - LLVM_DEBUG(errs() << "addData: " << DataSection.getSectionName() << "\n"); - - DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment())); - - for (const MCFragment &Frag : DataSection) { - if (Frag.hasInstructions()) - report_fatal_error("only data supported in data sections"); - - if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) { - if (Align->getValueSize() != 1) - report_fatal_error("only byte values supported for alignment"); - // If nops are requested, use zeros, as this is the data section. - uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue(); - uint64_t Size = - std::min<uint64_t>(alignTo(DataBytes.size(), Align->getAlignment()), - DataBytes.size() + Align->getMaxBytesToEmit()); - DataBytes.resize(Size, Value); - } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) { - int64_t NumValues; - if (!Fill->getNumValues().evaluateAsAbsolute(NumValues)) - llvm_unreachable("The fill should be an assembler constant"); - DataBytes.insert(DataBytes.end(), Fill->getValueSize() * NumValues, - Fill->getValue()); - } else if (auto *LEB = dyn_cast<MCLEBFragment>(&Frag)) { - const SmallVectorImpl<char> &Contents = LEB->getContents(); - DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end()); - } else { - const auto &DataFrag = cast<MCDataFragment>(Frag); - const SmallVectorImpl<char> &Contents = DataFrag.getContents(); - DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end()); - } - } - - LLVM_DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n"); -} - -uint32_t -WasmObjectWriter::getRelocationIndexValue(const WasmRelocationEntry &RelEntry) { - if (RelEntry.Type == wasm::R_WASM_TYPE_INDEX_LEB) { - if (!TypeIndices.count(RelEntry.Symbol)) - report_fatal_error("symbol not found in type index space: " + - RelEntry.Symbol->getName()); - return TypeIndices[RelEntry.Symbol]; - } - - return RelEntry.Symbol->getIndex(); -} - -// Apply the portions of the relocation records that we can handle ourselves -// directly. -void WasmObjectWriter::applyRelocations( - ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset) { - auto &Stream = static_cast<raw_pwrite_stream &>(W.OS); - for (const WasmRelocationEntry &RelEntry : Relocations) { - uint64_t Offset = ContentsOffset + - RelEntry.FixupSection->getSectionOffset() + - RelEntry.Offset; - - LLVM_DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n"); - uint32_t Value = getProvisionalValue(RelEntry); - - switch (RelEntry.Type) { - case wasm::R_WASM_FUNCTION_INDEX_LEB: - case wasm::R_WASM_TYPE_INDEX_LEB: - case wasm::R_WASM_GLOBAL_INDEX_LEB: - case wasm::R_WASM_MEMORY_ADDR_LEB: - case wasm::R_WASM_EVENT_INDEX_LEB: - writePatchableLEB(Stream, Value, Offset); - break; - case wasm::R_WASM_TABLE_INDEX_I32: - case wasm::R_WASM_MEMORY_ADDR_I32: - case wasm::R_WASM_FUNCTION_OFFSET_I32: - case wasm::R_WASM_SECTION_OFFSET_I32: - writeI32(Stream, Value, Offset); - break; - case wasm::R_WASM_TABLE_INDEX_SLEB: - case wasm::R_WASM_TABLE_INDEX_REL_SLEB: - case wasm::R_WASM_MEMORY_ADDR_SLEB: - case wasm::R_WASM_MEMORY_ADDR_REL_SLEB: - writePatchableSLEB(Stream, Value, Offset); - break; - default: - llvm_unreachable("invalid relocation type"); - } - } -} - -void WasmObjectWriter::writeTypeSection(ArrayRef<WasmSignature> Signatures) { - if (Signatures.empty()) - return; - - SectionBookkeeping Section; - startSection(Section, wasm::WASM_SEC_TYPE); - - encodeULEB128(Signatures.size(), W.OS); - - for (const WasmSignature &Sig : Signatures) { - W.OS << char(wasm::WASM_TYPE_FUNC); - encodeULEB128(Sig.Params.size(), W.OS); - for (wasm::ValType Ty : Sig.Params) - writeValueType(Ty); - encodeULEB128(Sig.Returns.size(), W.OS); - for (wasm::ValType Ty : Sig.Returns) - writeValueType(Ty); - } - - endSection(Section); -} - -void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports, - uint32_t DataSize, - uint32_t NumElements) { - if (Imports.empty()) - return; - - uint32_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize; - - SectionBookkeeping Section; - startSection(Section, wasm::WASM_SEC_IMPORT); - - encodeULEB128(Imports.size(), W.OS); - for (const wasm::WasmImport &Import : Imports) { - writeString(Import.Module); - writeString(Import.Field); - W.OS << char(Import.Kind); - - switch (Import.Kind) { - case wasm::WASM_EXTERNAL_FUNCTION: - encodeULEB128(Import.SigIndex, W.OS); - break; - case wasm::WASM_EXTERNAL_GLOBAL: - W.OS << char(Import.Global.Type); - W.OS << char(Import.Global.Mutable ? 1 : 0); - break; - case wasm::WASM_EXTERNAL_MEMORY: - encodeULEB128(0, W.OS); // flags - encodeULEB128(NumPages, W.OS); // initial - break; - case wasm::WASM_EXTERNAL_TABLE: - W.OS << char(Import.Table.ElemType); - encodeULEB128(0, W.OS); // flags - encodeULEB128(NumElements, W.OS); // initial - break; - case wasm::WASM_EXTERNAL_EVENT: - encodeULEB128(Import.Event.Attribute, W.OS); - encodeULEB128(Import.Event.SigIndex, W.OS); - break; - default: - llvm_unreachable("unsupported import kind"); - } - } - - endSection(Section); -} - -void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) { - if (Functions.empty()) - return; - - SectionBookkeeping Section; - startSection(Section, wasm::WASM_SEC_FUNCTION); - - encodeULEB128(Functions.size(), W.OS); - for (const WasmFunction &Func : Functions) - encodeULEB128(Func.SigIndex, W.OS); - - endSection(Section); -} - -void WasmObjectWriter::writeEventSection(ArrayRef<wasm::WasmEventType> Events) { - if (Events.empty()) - return; - - SectionBookkeeping Section; - startSection(Section, wasm::WASM_SEC_EVENT); - - encodeULEB128(Events.size(), W.OS); - for (const wasm::WasmEventType &Event : Events) { - encodeULEB128(Event.Attribute, W.OS); - encodeULEB128(Event.SigIndex, W.OS); - } - - endSection(Section); -} - -void WasmObjectWriter::writeExportSection(ArrayRef<wasm::WasmExport> Exports) { - if (Exports.empty()) - return; - - SectionBookkeeping Section; - startSection(Section, wasm::WASM_SEC_EXPORT); - - encodeULEB128(Exports.size(), W.OS); - for (const wasm::WasmExport &Export : Exports) { - writeString(Export.Name); - W.OS << char(Export.Kind); - encodeULEB128(Export.Index, W.OS); - } - - endSection(Section); -} - -void WasmObjectWriter::writeElemSection(ArrayRef<uint32_t> TableElems) { - if (TableElems.empty()) - return; - - SectionBookkeeping Section; - startSection(Section, wasm::WASM_SEC_ELEM); - - encodeULEB128(1, W.OS); // number of "segments" - encodeULEB128(0, W.OS); // the table index - - // init expr for starting offset - W.OS << char(wasm::WASM_OPCODE_I32_CONST); - encodeSLEB128(InitialTableOffset, W.OS); - W.OS << char(wasm::WASM_OPCODE_END); - - encodeULEB128(TableElems.size(), W.OS); - for (uint32_t Elem : TableElems) - encodeULEB128(Elem, W.OS); - - endSection(Section); -} - -void WasmObjectWriter::writeDataCountSection() { - if (DataSegments.empty()) - return; - - SectionBookkeeping Section; - startSection(Section, wasm::WASM_SEC_DATACOUNT); - encodeULEB128(DataSegments.size(), W.OS); - endSection(Section); -} - -void WasmObjectWriter::writeCodeSection(const MCAssembler &Asm, - const MCAsmLayout &Layout, - ArrayRef<WasmFunction> Functions) { - if (Functions.empty()) - return; - - SectionBookkeeping Section; - startSection(Section, wasm::WASM_SEC_CODE); - CodeSectionIndex = Section.Index; - - encodeULEB128(Functions.size(), W.OS); - - for (const WasmFunction &Func : Functions) { - auto &FuncSection = static_cast<MCSectionWasm &>(Func.Sym->getSection()); - - int64_t Size = 0; - if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout)) - report_fatal_error(".size expression must be evaluatable"); - - encodeULEB128(Size, W.OS); - FuncSection.setSectionOffset(W.OS.tell() - Section.ContentsOffset); - Asm.writeSectionData(W.OS, &FuncSection, Layout); - } - - // Apply fixups. - applyRelocations(CodeRelocations, Section.ContentsOffset); - - endSection(Section); -} - -void WasmObjectWriter::writeDataSection() { - if (DataSegments.empty()) - return; - - SectionBookkeeping Section; - startSection(Section, wasm::WASM_SEC_DATA); - DataSectionIndex = Section.Index; - - encodeULEB128(DataSegments.size(), W.OS); // count - - for (const WasmDataSegment &Segment : DataSegments) { - encodeULEB128(Segment.InitFlags, W.OS); // flags - if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX) - encodeULEB128(0, W.OS); // memory index - if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0) { - W.OS << char(wasm::WASM_OPCODE_I32_CONST); - encodeSLEB128(Segment.Offset, W.OS); // offset - W.OS << char(wasm::WASM_OPCODE_END); - } - encodeULEB128(Segment.Data.size(), W.OS); // size - Segment.Section->setSectionOffset(W.OS.tell() - Section.ContentsOffset); - W.OS << Segment.Data; // data - } - - // Apply fixups. - applyRelocations(DataRelocations, Section.ContentsOffset); - - endSection(Section); -} - -void WasmObjectWriter::writeRelocSection( - uint32_t SectionIndex, StringRef Name, - std::vector<WasmRelocationEntry> &Relocs) { - // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md - // for descriptions of the reloc sections. - - if (Relocs.empty()) - return; - - // First, ensure the relocations are sorted in offset order. In general they - // should already be sorted since `recordRelocation` is called in offset - // order, but for the code section we combine many MC sections into single - // wasm section, and this order is determined by the order of Asm.Symbols() - // not the sections order. - llvm::stable_sort( - Relocs, [](const WasmRelocationEntry &A, const WasmRelocationEntry &B) { - return (A.Offset + A.FixupSection->getSectionOffset()) < - (B.Offset + B.FixupSection->getSectionOffset()); - }); - - SectionBookkeeping Section; - startCustomSection(Section, std::string("reloc.") + Name.str()); - - encodeULEB128(SectionIndex, W.OS); - encodeULEB128(Relocs.size(), W.OS); - for (const WasmRelocationEntry &RelEntry : Relocs) { - uint64_t Offset = - RelEntry.Offset + RelEntry.FixupSection->getSectionOffset(); - uint32_t Index = getRelocationIndexValue(RelEntry); - - W.OS << char(RelEntry.Type); - encodeULEB128(Offset, W.OS); - encodeULEB128(Index, W.OS); - if (RelEntry.hasAddend()) - encodeSLEB128(RelEntry.Addend, W.OS); - } - - endSection(Section); -} - -void WasmObjectWriter::writeCustomRelocSections() { - for (const auto &Sec : CustomSections) { - auto &Relocations = CustomSectionsRelocations[Sec.Section]; - writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations); - } -} - -void WasmObjectWriter::writeLinkingMetaDataSection( - ArrayRef<wasm::WasmSymbolInfo> SymbolInfos, - ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs, - const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats) { - SectionBookkeeping Section; - startCustomSection(Section, "linking"); - encodeULEB128(wasm::WasmMetadataVersion, W.OS); - - SectionBookkeeping SubSection; - if (SymbolInfos.size() != 0) { - startSection(SubSection, wasm::WASM_SYMBOL_TABLE); - encodeULEB128(SymbolInfos.size(), W.OS); - for (const wasm::WasmSymbolInfo &Sym : SymbolInfos) { - encodeULEB128(Sym.Kind, W.OS); - encodeULEB128(Sym.Flags, W.OS); - switch (Sym.Kind) { - case wasm::WASM_SYMBOL_TYPE_FUNCTION: - case wasm::WASM_SYMBOL_TYPE_GLOBAL: - case wasm::WASM_SYMBOL_TYPE_EVENT: - encodeULEB128(Sym.ElementIndex, W.OS); - if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 || - (Sym.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) - writeString(Sym.Name); - break; - case wasm::WASM_SYMBOL_TYPE_DATA: - writeString(Sym.Name); - if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) { - encodeULEB128(Sym.DataRef.Segment, W.OS); - encodeULEB128(Sym.DataRef.Offset, W.OS); - encodeULEB128(Sym.DataRef.Size, W.OS); - } - break; - case wasm::WASM_SYMBOL_TYPE_SECTION: { - const uint32_t SectionIndex = - CustomSections[Sym.ElementIndex].OutputIndex; - encodeULEB128(SectionIndex, W.OS); - break; - } - default: - llvm_unreachable("unexpected kind"); - } - } - endSection(SubSection); - } - - if (DataSegments.size()) { - startSection(SubSection, wasm::WASM_SEGMENT_INFO); - encodeULEB128(DataSegments.size(), W.OS); - for (const WasmDataSegment &Segment : DataSegments) { - writeString(Segment.Name); - encodeULEB128(Segment.Alignment, W.OS); - encodeULEB128(Segment.LinkerFlags, W.OS); - } - endSection(SubSection); - } - - if (!InitFuncs.empty()) { - startSection(SubSection, wasm::WASM_INIT_FUNCS); - encodeULEB128(InitFuncs.size(), W.OS); - for (auto &StartFunc : InitFuncs) { - encodeULEB128(StartFunc.first, W.OS); // priority - encodeULEB128(StartFunc.second, W.OS); // function index - } - endSection(SubSection); - } - - if (Comdats.size()) { - startSection(SubSection, wasm::WASM_COMDAT_INFO); - encodeULEB128(Comdats.size(), W.OS); - for (const auto &C : Comdats) { - writeString(C.first); - encodeULEB128(0, W.OS); // flags for future use - encodeULEB128(C.second.size(), W.OS); - for (const WasmComdatEntry &Entry : C.second) { - encodeULEB128(Entry.Kind, W.OS); - encodeULEB128(Entry.Index, W.OS); - } - } - endSection(SubSection); - } - - endSection(Section); -} - -void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection, - const MCAssembler &Asm, - const MCAsmLayout &Layout) { - SectionBookkeeping Section; - auto *Sec = CustomSection.Section; - startCustomSection(Section, CustomSection.Name); - - Sec->setSectionOffset(W.OS.tell() - Section.ContentsOffset); - Asm.writeSectionData(W.OS, Sec, Layout); - - CustomSection.OutputContentsOffset = Section.ContentsOffset; - CustomSection.OutputIndex = Section.Index; - - endSection(Section); - - // Apply fixups. - auto &Relocations = CustomSectionsRelocations[CustomSection.Section]; - applyRelocations(Relocations, CustomSection.OutputContentsOffset); -} - -uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm &Symbol) { - assert(Symbol.isFunction()); - assert(TypeIndices.count(&Symbol)); - return TypeIndices[&Symbol]; -} - -uint32_t WasmObjectWriter::getEventType(const MCSymbolWasm &Symbol) { - assert(Symbol.isEvent()); - assert(TypeIndices.count(&Symbol)); - return TypeIndices[&Symbol]; -} - -void WasmObjectWriter::registerFunctionType(const MCSymbolWasm &Symbol) { - assert(Symbol.isFunction()); - - WasmSignature S; - const MCSymbolWasm *ResolvedSym = resolveSymbol(Symbol); - if (auto *Sig = ResolvedSym->getSignature()) { - S.Returns = Sig->Returns; - S.Params = Sig->Params; - } - - auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size())); - if (Pair.second) - Signatures.push_back(S); - TypeIndices[&Symbol] = Pair.first->second; - - LLVM_DEBUG(dbgs() << "registerFunctionType: " << Symbol - << " new:" << Pair.second << "\n"); - LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n"); -} - -void WasmObjectWriter::registerEventType(const MCSymbolWasm &Symbol) { - assert(Symbol.isEvent()); - - // TODO Currently we don't generate imported exceptions, but if we do, we - // should have a way of infering types of imported exceptions. - WasmSignature S; - if (auto *Sig = Symbol.getSignature()) { - S.Returns = Sig->Returns; - S.Params = Sig->Params; - } - - auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size())); - if (Pair.second) - Signatures.push_back(S); - TypeIndices[&Symbol] = Pair.first->second; - - LLVM_DEBUG(dbgs() << "registerEventType: " << Symbol << " new:" << Pair.second - << "\n"); - LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n"); -} - -static bool isInSymtab(const MCSymbolWasm &Sym) { - if (Sym.isUsedInReloc()) - return true; - - if (Sym.isComdat() && !Sym.isDefined()) - return false; - - if (Sym.isTemporary() && Sym.getName().empty()) - return false; - - if (Sym.isTemporary() && Sym.isData() && !Sym.getSize()) - return false; - - if (Sym.isSection()) - return false; - - return true; -} - -uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, - const MCAsmLayout &Layout) { - uint64_t StartOffset = W.OS.tell(); - - LLVM_DEBUG(dbgs() << "WasmObjectWriter::writeObject\n"); - - // Collect information from the available symbols. - SmallVector<WasmFunction, 4> Functions; - SmallVector<uint32_t, 4> TableElems; - SmallVector<wasm::WasmImport, 4> Imports; - SmallVector<wasm::WasmExport, 4> Exports; - SmallVector<wasm::WasmEventType, 1> Events; - SmallVector<wasm::WasmSymbolInfo, 4> SymbolInfos; - SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs; - std::map<StringRef, std::vector<WasmComdatEntry>> Comdats; - uint32_t DataSize = 0; - - // For now, always emit the memory import, since loads and stores are not - // valid without it. In the future, we could perhaps be more clever and omit - // it if there are no loads or stores. - wasm::WasmImport MemImport; - MemImport.Module = "env"; - MemImport.Field = "__linear_memory"; - MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY; - Imports.push_back(MemImport); - - // For now, always emit the table section, since indirect calls are not - // valid without it. In the future, we could perhaps be more clever and omit - // it if there are no indirect calls. - wasm::WasmImport TableImport; - TableImport.Module = "env"; - TableImport.Field = "__indirect_function_table"; - TableImport.Kind = wasm::WASM_EXTERNAL_TABLE; - TableImport.Table.ElemType = wasm::WASM_TYPE_FUNCREF; - Imports.push_back(TableImport); - - // Populate SignatureIndices, and Imports and WasmIndices for undefined - // symbols. This must be done before populating WasmIndices for defined - // symbols. - for (const MCSymbol &S : Asm.symbols()) { - const auto &WS = static_cast<const MCSymbolWasm &>(S); - - // Register types for all functions, including those with private linkage - // (because wasm always needs a type signature). - if (WS.isFunction()) - registerFunctionType(WS); - - if (WS.isEvent()) - registerEventType(WS); - - if (WS.isTemporary()) - continue; - - // If the symbol is not defined in this translation unit, import it. - if (!WS.isDefined() && !WS.isComdat()) { - if (WS.isFunction()) { - wasm::WasmImport Import; - Import.Module = WS.getImportModule(); - Import.Field = WS.getImportName(); - Import.Kind = wasm::WASM_EXTERNAL_FUNCTION; - Import.SigIndex = getFunctionType(WS); - Imports.push_back(Import); - assert(WasmIndices.count(&WS) == 0); - WasmIndices[&WS] = NumFunctionImports++; - } else if (WS.isGlobal()) { - if (WS.isWeak()) - report_fatal_error("undefined global symbol cannot be weak"); - - wasm::WasmImport Import; - Import.Field = WS.getImportName(); - Import.Kind = wasm::WASM_EXTERNAL_GLOBAL; - Import.Module = WS.getImportModule(); - Import.Global = WS.getGlobalType(); - Imports.push_back(Import); - assert(WasmIndices.count(&WS) == 0); - WasmIndices[&WS] = NumGlobalImports++; - } else if (WS.isEvent()) { - if (WS.isWeak()) - report_fatal_error("undefined event symbol cannot be weak"); - - wasm::WasmImport Import; - Import.Module = WS.getImportModule(); - Import.Field = WS.getImportName(); - Import.Kind = wasm::WASM_EXTERNAL_EVENT; - Import.Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION; - Import.Event.SigIndex = getEventType(WS); - Imports.push_back(Import); - assert(WasmIndices.count(&WS) == 0); - WasmIndices[&WS] = NumEventImports++; - } - } - } - - // Add imports for GOT globals - for (const MCSymbol &S : Asm.symbols()) { - const auto &WS = static_cast<const MCSymbolWasm &>(S); - if (WS.isUsedInGOT()) { - wasm::WasmImport Import; - if (WS.isFunction()) - Import.Module = "GOT.func"; - else - Import.Module = "GOT.mem"; - Import.Field = WS.getName(); - Import.Kind = wasm::WASM_EXTERNAL_GLOBAL; - Import.Global = {wasm::WASM_TYPE_I32, true}; - Imports.push_back(Import); - assert(GOTIndices.count(&WS) == 0); - GOTIndices[&WS] = NumGlobalImports++; - } - } - - // Populate DataSegments and CustomSections, which must be done before - // populating DataLocations. - for (MCSection &Sec : Asm) { - auto &Section = static_cast<MCSectionWasm &>(Sec); - StringRef SectionName = Section.getSectionName(); - - // .init_array sections are handled specially elsewhere. - if (SectionName.startswith(".init_array")) - continue; - - // Code is handled separately - if (Section.getKind().isText()) - continue; - - if (Section.isWasmData()) { - uint32_t SegmentIndex = DataSegments.size(); - DataSize = alignTo(DataSize, Section.getAlignment()); - DataSegments.emplace_back(); - WasmDataSegment &Segment = DataSegments.back(); - Segment.Name = SectionName; - Segment.InitFlags = - Section.getPassive() ? (uint32_t)wasm::WASM_SEGMENT_IS_PASSIVE : 0; - Segment.Offset = DataSize; - Segment.Section = &Section; - addData(Segment.Data, Section); - Segment.Alignment = Log2_32(Section.getAlignment()); - Segment.LinkerFlags = 0; - DataSize += Segment.Data.size(); - Section.setSegmentIndex(SegmentIndex); - - if (const MCSymbolWasm *C = Section.getGroup()) { - Comdats[C->getName()].emplace_back( - WasmComdatEntry{wasm::WASM_COMDAT_DATA, SegmentIndex}); - } - } else { - // Create custom sections - assert(Sec.getKind().isMetadata()); - - StringRef Name = SectionName; - - // For user-defined custom sections, strip the prefix - if (Name.startswith(".custom_section.")) - Name = Name.substr(strlen(".custom_section.")); - - MCSymbol *Begin = Sec.getBeginSymbol(); - if (Begin) { - WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size(); - if (SectionName != Begin->getName()) - report_fatal_error("section name and begin symbol should match: " + - Twine(SectionName)); - } - - // Separate out the producers and target features sections - if (Name == "producers") { - ProducersSection = llvm::make_unique<WasmCustomSection>(Name, &Section); - continue; - } - if (Name == "target_features") { - TargetFeaturesSection = - llvm::make_unique<WasmCustomSection>(Name, &Section); - continue; - } - - CustomSections.emplace_back(Name, &Section); - } - } - - // Populate WasmIndices and DataLocations for defined symbols. - for (const MCSymbol &S : Asm.symbols()) { - // Ignore unnamed temporary symbols, which aren't ever exported, imported, - // or used in relocations. - if (S.isTemporary() && S.getName().empty()) - continue; - - const auto &WS = static_cast<const MCSymbolWasm &>(S); - LLVM_DEBUG( - dbgs() << "MCSymbol: " << toString(WS.getType()) << " '" << S << "'" - << " isDefined=" << S.isDefined() << " isExternal=" - << S.isExternal() << " isTemporary=" << S.isTemporary() - << " isWeak=" << WS.isWeak() << " isHidden=" << WS.isHidden() - << " isVariable=" << WS.isVariable() << "\n"); - - if (WS.isVariable()) - continue; - if (WS.isComdat() && !WS.isDefined()) - continue; - - if (WS.isFunction()) { - unsigned Index; - if (WS.isDefined()) { - if (WS.getOffset() != 0) - report_fatal_error( - "function sections must contain one function each"); - - if (WS.getSize() == nullptr) - report_fatal_error( - "function symbols must have a size set with .size"); - - // A definition. Write out the function body. - Index = NumFunctionImports + Functions.size(); - WasmFunction Func; - Func.SigIndex = getFunctionType(WS); - Func.Sym = &WS; - WasmIndices[&WS] = Index; - Functions.push_back(Func); - - auto &Section = static_cast<MCSectionWasm &>(WS.getSection()); - if (const MCSymbolWasm *C = Section.getGroup()) { - Comdats[C->getName()].emplace_back( - WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, Index}); - } - } else { - // An import; the index was assigned above. - Index = WasmIndices.find(&WS)->second; - } - - LLVM_DEBUG(dbgs() << " -> function index: " << Index << "\n"); - - } else if (WS.isData()) { - if (!isInSymtab(WS)) - continue; - - if (!WS.isDefined()) { - LLVM_DEBUG(dbgs() << " -> segment index: -1" - << "\n"); - continue; - } - - if (!WS.getSize()) - report_fatal_error("data symbols must have a size set with .size: " + - WS.getName()); - - int64_t Size = 0; - if (!WS.getSize()->evaluateAsAbsolute(Size, Layout)) - report_fatal_error(".size expression must be evaluatable"); - - auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection()); - assert(DataSection.isWasmData()); - - // For each data symbol, export it in the symtab as a reference to the - // corresponding Wasm data segment. - wasm::WasmDataReference Ref = wasm::WasmDataReference{ - DataSection.getSegmentIndex(), - static_cast<uint32_t>(Layout.getSymbolOffset(WS)), - static_cast<uint32_t>(Size)}; - DataLocations[&WS] = Ref; - LLVM_DEBUG(dbgs() << " -> segment index: " << Ref.Segment << "\n"); - - } else if (WS.isGlobal()) { - // A "true" Wasm global (currently just __stack_pointer) - if (WS.isDefined()) - report_fatal_error("don't yet support defined globals"); - - // An import; the index was assigned above - LLVM_DEBUG(dbgs() << " -> global index: " - << WasmIndices.find(&WS)->second << "\n"); - - } else if (WS.isEvent()) { - // C++ exception symbol (__cpp_exception) - unsigned Index; - if (WS.isDefined()) { - Index = NumEventImports + Events.size(); - wasm::WasmEventType Event; - Event.SigIndex = getEventType(WS); - Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION; - assert(WasmIndices.count(&WS) == 0); - WasmIndices[&WS] = Index; - Events.push_back(Event); - } else { - // An import; the index was assigned above. - assert(WasmIndices.count(&WS) > 0); - } - LLVM_DEBUG(dbgs() << " -> event index: " << WasmIndices.find(&WS)->second - << "\n"); - - } else { - assert(WS.isSection()); - } - } - - // Populate WasmIndices and DataLocations for aliased symbols. We need to - // process these in a separate pass because we need to have processed the - // target of the alias before the alias itself and the symbols are not - // necessarily ordered in this way. - for (const MCSymbol &S : Asm.symbols()) { - if (!S.isVariable()) - continue; - - assert(S.isDefined()); - - // Find the target symbol of this weak alias and export that index - const auto &WS = static_cast<const MCSymbolWasm &>(S); - const MCSymbolWasm *ResolvedSym = resolveSymbol(WS); - LLVM_DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *ResolvedSym - << "'\n"); - - if (ResolvedSym->isFunction()) { - assert(WasmIndices.count(ResolvedSym) > 0); - uint32_t WasmIndex = WasmIndices.find(ResolvedSym)->second; - assert(WasmIndices.count(&WS) == 0); - WasmIndices[&WS] = WasmIndex; - LLVM_DEBUG(dbgs() << " -> index:" << WasmIndex << "\n"); - } else if (ResolvedSym->isData()) { - assert(DataLocations.count(ResolvedSym) > 0); - const wasm::WasmDataReference &Ref = - DataLocations.find(ResolvedSym)->second; - DataLocations[&WS] = Ref; - LLVM_DEBUG(dbgs() << " -> index:" << Ref.Segment << "\n"); - } else { - report_fatal_error("don't yet support global/event aliases"); - } - } - - // Finally, populate the symbol table itself, in its "natural" order. - for (const MCSymbol &S : Asm.symbols()) { - const auto &WS = static_cast<const MCSymbolWasm &>(S); - if (!isInSymtab(WS)) { - WS.setIndex(InvalidIndex); - continue; - } - LLVM_DEBUG(dbgs() << "adding to symtab: " << WS << "\n"); - - uint32_t Flags = 0; - if (WS.isWeak()) - Flags |= wasm::WASM_SYMBOL_BINDING_WEAK; - if (WS.isHidden()) - Flags |= wasm::WASM_SYMBOL_VISIBILITY_HIDDEN; - if (!WS.isExternal() && WS.isDefined()) - Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL; - if (WS.isUndefined()) - Flags |= wasm::WASM_SYMBOL_UNDEFINED; - if (WS.isExported()) - Flags |= wasm::WASM_SYMBOL_EXPORTED; - if (WS.getName() != WS.getImportName()) - Flags |= wasm::WASM_SYMBOL_EXPLICIT_NAME; - - wasm::WasmSymbolInfo Info; - Info.Name = WS.getName(); - Info.Kind = WS.getType(); - Info.Flags = Flags; - if (!WS.isData()) { - assert(WasmIndices.count(&WS) > 0); - Info.ElementIndex = WasmIndices.find(&WS)->second; - } else if (WS.isDefined()) { - assert(DataLocations.count(&WS) > 0); - Info.DataRef = DataLocations.find(&WS)->second; - } - WS.setIndex(SymbolInfos.size()); - SymbolInfos.emplace_back(Info); - } - - { - auto HandleReloc = [&](const WasmRelocationEntry &Rel) { - // Functions referenced by a relocation need to put in the table. This is - // purely to make the object file's provisional values readable, and is - // ignored by the linker, which re-calculates the relocations itself. - if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 && - Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB) - return; - assert(Rel.Symbol->isFunction()); - const MCSymbolWasm &WS = *resolveSymbol(*Rel.Symbol); - uint32_t FunctionIndex = WasmIndices.find(&WS)->second; - uint32_t TableIndex = TableElems.size() + InitialTableOffset; - if (TableIndices.try_emplace(&WS, TableIndex).second) { - LLVM_DEBUG(dbgs() << " -> adding " << WS.getName() - << " to table: " << TableIndex << "\n"); - TableElems.push_back(FunctionIndex); - registerFunctionType(WS); - } - }; - - for (const WasmRelocationEntry &RelEntry : CodeRelocations) - HandleReloc(RelEntry); - for (const WasmRelocationEntry &RelEntry : DataRelocations) - HandleReloc(RelEntry); - } - - // Translate .init_array section contents into start functions. - for (const MCSection &S : Asm) { - const auto &WS = static_cast<const MCSectionWasm &>(S); - if (WS.getSectionName().startswith(".fini_array")) - report_fatal_error(".fini_array sections are unsupported"); - if (!WS.getSectionName().startswith(".init_array")) - continue; - if (WS.getFragmentList().empty()) - continue; - - // init_array is expected to contain a single non-empty data fragment - if (WS.getFragmentList().size() != 3) - report_fatal_error("only one .init_array section fragment supported"); - - auto IT = WS.begin(); - const MCFragment &EmptyFrag = *IT; - if (EmptyFrag.getKind() != MCFragment::FT_Data) - report_fatal_error(".init_array section should be aligned"); - - IT = std::next(IT); - const MCFragment &AlignFrag = *IT; - if (AlignFrag.getKind() != MCFragment::FT_Align) - report_fatal_error(".init_array section should be aligned"); - if (cast<MCAlignFragment>(AlignFrag).getAlignment() != (is64Bit() ? 8 : 4)) - report_fatal_error(".init_array section should be aligned for pointers"); - - const MCFragment &Frag = *std::next(IT); - if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data) - report_fatal_error("only data supported in .init_array section"); - - uint16_t Priority = UINT16_MAX; - unsigned PrefixLength = strlen(".init_array"); - if (WS.getSectionName().size() > PrefixLength) { - if (WS.getSectionName()[PrefixLength] != '.') - report_fatal_error( - ".init_array section priority should start with '.'"); - if (WS.getSectionName() - .substr(PrefixLength + 1) - .getAsInteger(10, Priority)) - report_fatal_error("invalid .init_array section priority"); - } - const auto &DataFrag = cast<MCDataFragment>(Frag); - const SmallVectorImpl<char> &Contents = DataFrag.getContents(); - for (const uint8_t * - P = (const uint8_t *)Contents.data(), - *End = (const uint8_t *)Contents.data() + Contents.size(); - P != End; ++P) { - if (*P != 0) - report_fatal_error("non-symbolic data in .init_array section"); - } - for (const MCFixup &Fixup : DataFrag.getFixups()) { - assert(Fixup.getKind() == - MCFixup::getKindForSize(is64Bit() ? 8 : 4, false)); - const MCExpr *Expr = Fixup.getValue(); - auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr); - if (!SymRef) - report_fatal_error("fixups in .init_array should be symbol references"); - const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol()); - if (TargetSym.getIndex() == InvalidIndex) - report_fatal_error("symbols in .init_array should exist in symbtab"); - if (!TargetSym.isFunction()) - report_fatal_error("symbols in .init_array should be for functions"); - InitFuncs.push_back( - std::make_pair(Priority, TargetSym.getIndex())); - } - } - - // Write out the Wasm header. - writeHeader(Asm); - - writeTypeSection(Signatures); - writeImportSection(Imports, DataSize, TableElems.size()); - writeFunctionSection(Functions); - // Skip the "table" section; we import the table instead. - // Skip the "memory" section; we import the memory instead. - writeEventSection(Events); - writeExportSection(Exports); - writeElemSection(TableElems); - writeDataCountSection(); - writeCodeSection(Asm, Layout, Functions); - writeDataSection(); - for (auto &CustomSection : CustomSections) - writeCustomSection(CustomSection, Asm, Layout); - writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats); - writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations); - writeRelocSection(DataSectionIndex, "DATA", DataRelocations); - writeCustomRelocSections(); - if (ProducersSection) - writeCustomSection(*ProducersSection, Asm, Layout); - if (TargetFeaturesSection) - writeCustomSection(*TargetFeaturesSection, Asm, Layout); - - // TODO: Translate the .comment section to the output. - return W.OS.tell() - StartOffset; -} - -std::unique_ptr<MCObjectWriter> -llvm::createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW, - raw_pwrite_stream &OS) { - return llvm::make_unique<WasmObjectWriter>(std::move(MOTW), OS); -} diff --git a/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp b/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp deleted file mode 100644 index 0e6c05bc726d..000000000000 --- a/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ /dev/null @@ -1,1102 +0,0 @@ -//===- llvm/MC/WinCOFFObjectWriter.cpp ------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains an implementation of a Win32 COFF object file writer. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/DenseMap.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/COFF.h" -#include "llvm/MC/MCAsmLayout.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFixup.h" -#include "llvm/MC/MCFragment.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSectionCOFF.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCSymbolCOFF.h" -#include "llvm/MC/MCValue.h" -#include "llvm/MC/MCWinCOFFObjectWriter.h" -#include "llvm/MC/StringTableBuilder.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/JamCRC.h" -#include "llvm/Support/LEB128.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cassert> -#include <cstddef> -#include <cstdint> -#include <cstring> -#include <ctime> -#include <memory> -#include <string> -#include <vector> - -using namespace llvm; -using llvm::support::endian::write32le; - -#define DEBUG_TYPE "WinCOFFObjectWriter" - -namespace { - -using name = SmallString<COFF::NameSize>; - -enum AuxiliaryType { - ATWeakExternal, - ATFile, - ATSectionDefinition -}; - -struct AuxSymbol { - AuxiliaryType AuxType; - COFF::Auxiliary Aux; -}; - -class COFFSection; - -class COFFSymbol { -public: - COFF::symbol Data = {}; - - using AuxiliarySymbols = SmallVector<AuxSymbol, 1>; - - name Name; - int Index; - AuxiliarySymbols Aux; - COFFSymbol *Other = nullptr; - COFFSection *Section = nullptr; - int Relocations = 0; - const MCSymbol *MC = nullptr; - - COFFSymbol(StringRef Name) : Name(Name) {} - - void set_name_offset(uint32_t Offset); - - int64_t getIndex() const { return Index; } - void setIndex(int Value) { - Index = Value; - if (MC) - MC->setIndex(static_cast<uint32_t>(Value)); - } -}; - -// This class contains staging data for a COFF relocation entry. -struct COFFRelocation { - COFF::relocation Data; - COFFSymbol *Symb = nullptr; - - COFFRelocation() = default; - - static size_t size() { return COFF::RelocationSize; } -}; - -using relocations = std::vector<COFFRelocation>; - -class COFFSection { -public: - COFF::section Header = {}; - - std::string Name; - int Number; - MCSectionCOFF const *MCSection = nullptr; - COFFSymbol *Symbol = nullptr; - relocations Relocations; - - COFFSection(StringRef Name) : Name(Name) {} -}; - -class WinCOFFObjectWriter : public MCObjectWriter { -public: - support::endian::Writer W; - - using symbols = std::vector<std::unique_ptr<COFFSymbol>>; - using sections = std::vector<std::unique_ptr<COFFSection>>; - - using symbol_map = DenseMap<MCSymbol const *, COFFSymbol *>; - using section_map = DenseMap<MCSection const *, COFFSection *>; - - std::unique_ptr<MCWinCOFFObjectTargetWriter> TargetObjectWriter; - - // Root level file contents. - COFF::header Header = {}; - sections Sections; - symbols Symbols; - StringTableBuilder Strings{StringTableBuilder::WinCOFF}; - - // Maps used during object file creation. - section_map SectionMap; - symbol_map SymbolMap; - - bool UseBigObj; - - bool EmitAddrsigSection = false; - MCSectionCOFF *AddrsigSection; - std::vector<const MCSymbol *> AddrsigSyms; - - WinCOFFObjectWriter(std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, - raw_pwrite_stream &OS); - - void reset() override { - memset(&Header, 0, sizeof(Header)); - Header.Machine = TargetObjectWriter->getMachine(); - Sections.clear(); - Symbols.clear(); - Strings.clear(); - SectionMap.clear(); - SymbolMap.clear(); - MCObjectWriter::reset(); - } - - COFFSymbol *createSymbol(StringRef Name); - COFFSymbol *GetOrCreateCOFFSymbol(const MCSymbol *Symbol); - COFFSection *createSection(StringRef Name); - - void defineSection(MCSectionCOFF const &Sec); - - COFFSymbol *getLinkedSymbol(const MCSymbol &Symbol); - void DefineSymbol(const MCSymbol &Symbol, MCAssembler &Assembler, - const MCAsmLayout &Layout); - - void SetSymbolName(COFFSymbol &S); - void SetSectionName(COFFSection &S); - - bool IsPhysicalSection(COFFSection *S); - - // Entity writing methods. - - void WriteFileHeader(const COFF::header &Header); - void WriteSymbol(const COFFSymbol &S); - void WriteAuxiliarySymbols(const COFFSymbol::AuxiliarySymbols &S); - void writeSectionHeaders(); - void WriteRelocation(const COFF::relocation &R); - uint32_t writeSectionContents(MCAssembler &Asm, const MCAsmLayout &Layout, - const MCSection &MCSec); - void writeSection(MCAssembler &Asm, const MCAsmLayout &Layout, - const COFFSection &Sec, const MCSection &MCSec); - - // MCObjectWriter interface implementation. - - void executePostLayoutBinding(MCAssembler &Asm, - const MCAsmLayout &Layout) override; - - bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, - const MCSymbol &SymA, - const MCFragment &FB, bool InSet, - bool IsPCRel) const override; - - void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, - const MCFragment *Fragment, const MCFixup &Fixup, - MCValue Target, uint64_t &FixedValue) override; - - void createFileSymbols(MCAssembler &Asm); - void assignSectionNumbers(); - void assignFileOffsets(MCAssembler &Asm, const MCAsmLayout &Layout); - - void emitAddrsigSection() override { EmitAddrsigSection = true; } - void addAddrsigSymbol(const MCSymbol *Sym) override { - AddrsigSyms.push_back(Sym); - } - - uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; -}; - -} // end anonymous namespace - -//------------------------------------------------------------------------------ -// Symbol class implementation - -// In the case that the name does not fit within 8 bytes, the offset -// into the string table is stored in the last 4 bytes instead, leaving -// the first 4 bytes as 0. -void COFFSymbol::set_name_offset(uint32_t Offset) { - write32le(Data.Name + 0, 0); - write32le(Data.Name + 4, Offset); -} - -//------------------------------------------------------------------------------ -// WinCOFFObjectWriter class implementation - -WinCOFFObjectWriter::WinCOFFObjectWriter( - std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS) - : W(OS, support::little), TargetObjectWriter(std::move(MOTW)) { - Header.Machine = TargetObjectWriter->getMachine(); -} - -COFFSymbol *WinCOFFObjectWriter::createSymbol(StringRef Name) { - Symbols.push_back(make_unique<COFFSymbol>(Name)); - return Symbols.back().get(); -} - -COFFSymbol *WinCOFFObjectWriter::GetOrCreateCOFFSymbol(const MCSymbol *Symbol) { - COFFSymbol *&Ret = SymbolMap[Symbol]; - if (!Ret) - Ret = createSymbol(Symbol->getName()); - return Ret; -} - -COFFSection *WinCOFFObjectWriter::createSection(StringRef Name) { - Sections.emplace_back(make_unique<COFFSection>(Name)); - return Sections.back().get(); -} - -static uint32_t getAlignment(const MCSectionCOFF &Sec) { - switch (Sec.getAlignment()) { - case 1: - return COFF::IMAGE_SCN_ALIGN_1BYTES; - case 2: - return COFF::IMAGE_SCN_ALIGN_2BYTES; - case 4: - return COFF::IMAGE_SCN_ALIGN_4BYTES; - case 8: - return COFF::IMAGE_SCN_ALIGN_8BYTES; - case 16: - return COFF::IMAGE_SCN_ALIGN_16BYTES; - case 32: - return COFF::IMAGE_SCN_ALIGN_32BYTES; - case 64: - return COFF::IMAGE_SCN_ALIGN_64BYTES; - case 128: - return COFF::IMAGE_SCN_ALIGN_128BYTES; - case 256: - return COFF::IMAGE_SCN_ALIGN_256BYTES; - case 512: - return COFF::IMAGE_SCN_ALIGN_512BYTES; - case 1024: - return COFF::IMAGE_SCN_ALIGN_1024BYTES; - case 2048: - return COFF::IMAGE_SCN_ALIGN_2048BYTES; - case 4096: - return COFF::IMAGE_SCN_ALIGN_4096BYTES; - case 8192: - return COFF::IMAGE_SCN_ALIGN_8192BYTES; - } - llvm_unreachable("unsupported section alignment"); -} - -/// This function takes a section data object from the assembler -/// and creates the associated COFF section staging object. -void WinCOFFObjectWriter::defineSection(const MCSectionCOFF &MCSec) { - COFFSection *Section = createSection(MCSec.getSectionName()); - COFFSymbol *Symbol = createSymbol(MCSec.getSectionName()); - Section->Symbol = Symbol; - Symbol->Section = Section; - Symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_STATIC; - - // Create a COMDAT symbol if needed. - if (MCSec.getSelection() != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { - if (const MCSymbol *S = MCSec.getCOMDATSymbol()) { - COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(S); - if (COMDATSymbol->Section) - report_fatal_error("two sections have the same comdat"); - COMDATSymbol->Section = Section; - } - } - - // In this case the auxiliary symbol is a Section Definition. - Symbol->Aux.resize(1); - Symbol->Aux[0] = {}; - Symbol->Aux[0].AuxType = ATSectionDefinition; - Symbol->Aux[0].Aux.SectionDefinition.Selection = MCSec.getSelection(); - - // Set section alignment. - Section->Header.Characteristics = MCSec.getCharacteristics(); - Section->Header.Characteristics |= getAlignment(MCSec); - - // Bind internal COFF section to MC section. - Section->MCSection = &MCSec; - SectionMap[&MCSec] = Section; -} - -static uint64_t getSymbolValue(const MCSymbol &Symbol, - const MCAsmLayout &Layout) { - if (Symbol.isCommon() && Symbol.isExternal()) - return Symbol.getCommonSize(); - - uint64_t Res; - if (!Layout.getSymbolOffset(Symbol, Res)) - return 0; - - return Res; -} - -COFFSymbol *WinCOFFObjectWriter::getLinkedSymbol(const MCSymbol &Symbol) { - if (!Symbol.isVariable()) - return nullptr; - - const MCSymbolRefExpr *SymRef = - dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue()); - if (!SymRef) - return nullptr; - - const MCSymbol &Aliasee = SymRef->getSymbol(); - if (!Aliasee.isUndefined()) - return nullptr; - return GetOrCreateCOFFSymbol(&Aliasee); -} - -/// This function takes a symbol data object from the assembler -/// and creates the associated COFF symbol staging object. -void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &MCSym, - MCAssembler &Assembler, - const MCAsmLayout &Layout) { - COFFSymbol *Sym = GetOrCreateCOFFSymbol(&MCSym); - const MCSymbol *Base = Layout.getBaseSymbol(MCSym); - COFFSection *Sec = nullptr; - if (Base && Base->getFragment()) { - Sec = SectionMap[Base->getFragment()->getParent()]; - if (Sym->Section && Sym->Section != Sec) - report_fatal_error("conflicting sections for symbol"); - } - - COFFSymbol *Local = nullptr; - if (cast<MCSymbolCOFF>(MCSym).isWeakExternal()) { - Sym->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; - - COFFSymbol *WeakDefault = getLinkedSymbol(MCSym); - if (!WeakDefault) { - std::string WeakName = (".weak." + MCSym.getName() + ".default").str(); - WeakDefault = createSymbol(WeakName); - if (!Sec) - WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; - else - WeakDefault->Section = Sec; - Local = WeakDefault; - } - - Sym->Other = WeakDefault; - - // Setup the Weak External auxiliary symbol. - Sym->Aux.resize(1); - memset(&Sym->Aux[0], 0, sizeof(Sym->Aux[0])); - Sym->Aux[0].AuxType = ATWeakExternal; - Sym->Aux[0].Aux.WeakExternal.TagIndex = 0; - Sym->Aux[0].Aux.WeakExternal.Characteristics = - COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS; - } else { - if (!Base) - Sym->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; - else - Sym->Section = Sec; - Local = Sym; - } - - if (Local) { - Local->Data.Value = getSymbolValue(MCSym, Layout); - - const MCSymbolCOFF &SymbolCOFF = cast<MCSymbolCOFF>(MCSym); - Local->Data.Type = SymbolCOFF.getType(); - Local->Data.StorageClass = SymbolCOFF.getClass(); - - // If no storage class was specified in the streamer, define it here. - if (Local->Data.StorageClass == COFF::IMAGE_SYM_CLASS_NULL) { - bool IsExternal = MCSym.isExternal() || - (!MCSym.getFragment() && !MCSym.isVariable()); - - Local->Data.StorageClass = IsExternal ? COFF::IMAGE_SYM_CLASS_EXTERNAL - : COFF::IMAGE_SYM_CLASS_STATIC; - } - } - - Sym->MC = &MCSym; -} - -// Maximum offsets for different string table entry encodings. -enum : unsigned { Max7DecimalOffset = 9999999U }; -enum : uint64_t { MaxBase64Offset = 0xFFFFFFFFFULL }; // 64^6, including 0 - -// Encode a string table entry offset in base 64, padded to 6 chars, and -// prefixed with a double slash: '//AAAAAA', '//AAAAAB', ... -// Buffer must be at least 8 bytes large. No terminating null appended. -static void encodeBase64StringEntry(char *Buffer, uint64_t Value) { - assert(Value > Max7DecimalOffset && Value <= MaxBase64Offset && - "Illegal section name encoding for value"); - - static const char Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - - Buffer[0] = '/'; - Buffer[1] = '/'; - - char *Ptr = Buffer + 7; - for (unsigned i = 0; i < 6; ++i) { - unsigned Rem = Value % 64; - Value /= 64; - *(Ptr--) = Alphabet[Rem]; - } -} - -void WinCOFFObjectWriter::SetSectionName(COFFSection &S) { - if (S.Name.size() <= COFF::NameSize) { - std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size()); - return; - } - - uint64_t StringTableEntry = Strings.getOffset(S.Name); - if (StringTableEntry <= Max7DecimalOffset) { - SmallVector<char, COFF::NameSize> Buffer; - Twine('/').concat(Twine(StringTableEntry)).toVector(Buffer); - assert(Buffer.size() <= COFF::NameSize && Buffer.size() >= 2); - std::memcpy(S.Header.Name, Buffer.data(), Buffer.size()); - return; - } - if (StringTableEntry <= MaxBase64Offset) { - // Starting with 10,000,000, offsets are encoded as base64. - encodeBase64StringEntry(S.Header.Name, StringTableEntry); - return; - } - report_fatal_error("COFF string table is greater than 64 GB."); -} - -void WinCOFFObjectWriter::SetSymbolName(COFFSymbol &S) { - if (S.Name.size() > COFF::NameSize) - S.set_name_offset(Strings.getOffset(S.Name)); - else - std::memcpy(S.Data.Name, S.Name.c_str(), S.Name.size()); -} - -bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) { - return (S->Header.Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) == - 0; -} - -//------------------------------------------------------------------------------ -// entity writing methods - -void WinCOFFObjectWriter::WriteFileHeader(const COFF::header &Header) { - if (UseBigObj) { - W.write<uint16_t>(COFF::IMAGE_FILE_MACHINE_UNKNOWN); - W.write<uint16_t>(0xFFFF); - W.write<uint16_t>(COFF::BigObjHeader::MinBigObjectVersion); - W.write<uint16_t>(Header.Machine); - W.write<uint32_t>(Header.TimeDateStamp); - W.OS.write(COFF::BigObjMagic, sizeof(COFF::BigObjMagic)); - W.write<uint32_t>(0); - W.write<uint32_t>(0); - W.write<uint32_t>(0); - W.write<uint32_t>(0); - W.write<uint32_t>(Header.NumberOfSections); - W.write<uint32_t>(Header.PointerToSymbolTable); - W.write<uint32_t>(Header.NumberOfSymbols); - } else { - W.write<uint16_t>(Header.Machine); - W.write<uint16_t>(static_cast<int16_t>(Header.NumberOfSections)); - W.write<uint32_t>(Header.TimeDateStamp); - W.write<uint32_t>(Header.PointerToSymbolTable); - W.write<uint32_t>(Header.NumberOfSymbols); - W.write<uint16_t>(Header.SizeOfOptionalHeader); - W.write<uint16_t>(Header.Characteristics); - } -} - -void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol &S) { - W.OS.write(S.Data.Name, COFF::NameSize); - W.write<uint32_t>(S.Data.Value); - if (UseBigObj) - W.write<uint32_t>(S.Data.SectionNumber); - else - W.write<uint16_t>(static_cast<int16_t>(S.Data.SectionNumber)); - W.write<uint16_t>(S.Data.Type); - W.OS << char(S.Data.StorageClass); - W.OS << char(S.Data.NumberOfAuxSymbols); - WriteAuxiliarySymbols(S.Aux); -} - -void WinCOFFObjectWriter::WriteAuxiliarySymbols( - const COFFSymbol::AuxiliarySymbols &S) { - for (const AuxSymbol &i : S) { - switch (i.AuxType) { - case ATWeakExternal: - W.write<uint32_t>(i.Aux.WeakExternal.TagIndex); - W.write<uint32_t>(i.Aux.WeakExternal.Characteristics); - W.OS.write_zeros(sizeof(i.Aux.WeakExternal.unused)); - if (UseBigObj) - W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size); - break; - case ATFile: - W.OS.write(reinterpret_cast<const char *>(&i.Aux), - UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size); - break; - case ATSectionDefinition: - W.write<uint32_t>(i.Aux.SectionDefinition.Length); - W.write<uint16_t>(i.Aux.SectionDefinition.NumberOfRelocations); - W.write<uint16_t>(i.Aux.SectionDefinition.NumberOfLinenumbers); - W.write<uint32_t>(i.Aux.SectionDefinition.CheckSum); - W.write<uint16_t>(static_cast<int16_t>(i.Aux.SectionDefinition.Number)); - W.OS << char(i.Aux.SectionDefinition.Selection); - W.OS.write_zeros(sizeof(i.Aux.SectionDefinition.unused)); - W.write<uint16_t>(static_cast<int16_t>(i.Aux.SectionDefinition.Number >> 16)); - if (UseBigObj) - W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size); - break; - } - } -} - -// Write the section header. -void WinCOFFObjectWriter::writeSectionHeaders() { - // Section numbers must be monotonically increasing in the section - // header, but our Sections array is not sorted by section number, - // so make a copy of Sections and sort it. - std::vector<COFFSection *> Arr; - for (auto &Section : Sections) - Arr.push_back(Section.get()); - llvm::sort(Arr, [](const COFFSection *A, const COFFSection *B) { - return A->Number < B->Number; - }); - - for (auto &Section : Arr) { - if (Section->Number == -1) - continue; - - COFF::section &S = Section->Header; - if (Section->Relocations.size() >= 0xffff) - S.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL; - W.OS.write(S.Name, COFF::NameSize); - W.write<uint32_t>(S.VirtualSize); - W.write<uint32_t>(S.VirtualAddress); - W.write<uint32_t>(S.SizeOfRawData); - W.write<uint32_t>(S.PointerToRawData); - W.write<uint32_t>(S.PointerToRelocations); - W.write<uint32_t>(S.PointerToLineNumbers); - W.write<uint16_t>(S.NumberOfRelocations); - W.write<uint16_t>(S.NumberOfLineNumbers); - W.write<uint32_t>(S.Characteristics); - } -} - -void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) { - W.write<uint32_t>(R.VirtualAddress); - W.write<uint32_t>(R.SymbolTableIndex); - W.write<uint16_t>(R.Type); -} - -// Write MCSec's contents. What this function does is essentially -// "Asm.writeSectionData(&MCSec, Layout)", but it's a bit complicated -// because it needs to compute a CRC. -uint32_t WinCOFFObjectWriter::writeSectionContents(MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCSection &MCSec) { - // Save the contents of the section to a temporary buffer, we need this - // to CRC the data before we dump it into the object file. - SmallVector<char, 128> Buf; - raw_svector_ostream VecOS(Buf); - Asm.writeSectionData(VecOS, &MCSec, Layout); - - // Write the section contents to the object file. - W.OS << Buf; - - // Calculate our CRC with an initial value of '0', this is not how - // JamCRC is specified but it aligns with the expected output. - JamCRC JC(/*Init=*/0); - JC.update(Buf); - return JC.getCRC(); -} - -void WinCOFFObjectWriter::writeSection(MCAssembler &Asm, - const MCAsmLayout &Layout, - const COFFSection &Sec, - const MCSection &MCSec) { - if (Sec.Number == -1) - return; - - // Write the section contents. - if (Sec.Header.PointerToRawData != 0) { - assert(W.OS.tell() == Sec.Header.PointerToRawData && - "Section::PointerToRawData is insane!"); - - uint32_t CRC = writeSectionContents(Asm, Layout, MCSec); - - // Update the section definition auxiliary symbol to record the CRC. - COFFSection *Sec = SectionMap[&MCSec]; - COFFSymbol::AuxiliarySymbols &AuxSyms = Sec->Symbol->Aux; - assert(AuxSyms.size() == 1 && AuxSyms[0].AuxType == ATSectionDefinition); - AuxSymbol &SecDef = AuxSyms[0]; - SecDef.Aux.SectionDefinition.CheckSum = CRC; - } - - // Write relocations for this section. - if (Sec.Relocations.empty()) { - assert(Sec.Header.PointerToRelocations == 0 && - "Section::PointerToRelocations is insane!"); - return; - } - - assert(W.OS.tell() == Sec.Header.PointerToRelocations && - "Section::PointerToRelocations is insane!"); - - if (Sec.Relocations.size() >= 0xffff) { - // In case of overflow, write actual relocation count as first - // relocation. Including the synthetic reloc itself (+ 1). - COFF::relocation R; - R.VirtualAddress = Sec.Relocations.size() + 1; - R.SymbolTableIndex = 0; - R.Type = 0; - WriteRelocation(R); - } - - for (const auto &Relocation : Sec.Relocations) - WriteRelocation(Relocation.Data); -} - -//////////////////////////////////////////////////////////////////////////////// -// MCObjectWriter interface implementations - -void WinCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, - const MCAsmLayout &Layout) { - if (EmitAddrsigSection) { - AddrsigSection = Asm.getContext().getCOFFSection( - ".llvm_addrsig", COFF::IMAGE_SCN_LNK_REMOVE, - SectionKind::getMetadata()); - Asm.registerSection(*AddrsigSection); - } - - // "Define" each section & symbol. This creates section & symbol - // entries in the staging area. - for (const auto &Section : Asm) - defineSection(static_cast<const MCSectionCOFF &>(Section)); - - for (const MCSymbol &Symbol : Asm.symbols()) - if (!Symbol.isTemporary()) - DefineSymbol(Symbol, Asm, Layout); -} - -bool WinCOFFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl( - const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB, - bool InSet, bool IsPCRel) const { - // Don't drop relocations between functions, even if they are in the same text - // section. Multiple Visual C++ linker features depend on having the - // relocations present. The /INCREMENTAL flag will cause these relocations to - // point to thunks, and the /GUARD:CF flag assumes that it can use relocations - // to approximate the set of all address taken functions. LLD's implementation - // of /GUARD:CF also relies on the existance of these relocations. - uint16_t Type = cast<MCSymbolCOFF>(SymA).getType(); - if ((Type >> COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION) - return false; - return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB, - InSet, IsPCRel); -} - -void WinCOFFObjectWriter::recordRelocation(MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, MCValue Target, - uint64_t &FixedValue) { - assert(Target.getSymA() && "Relocation must reference a symbol!"); - - const MCSymbol &A = Target.getSymA()->getSymbol(); - if (!A.isRegistered()) { - Asm.getContext().reportError(Fixup.getLoc(), - Twine("symbol '") + A.getName() + - "' can not be undefined"); - return; - } - if (A.isTemporary() && A.isUndefined()) { - Asm.getContext().reportError(Fixup.getLoc(), - Twine("assembler label '") + A.getName() + - "' can not be undefined"); - return; - } - - MCSection *MCSec = Fragment->getParent(); - - // Mark this symbol as requiring an entry in the symbol table. - assert(SectionMap.find(MCSec) != SectionMap.end() && - "Section must already have been defined in executePostLayoutBinding!"); - - COFFSection *Sec = SectionMap[MCSec]; - const MCSymbolRefExpr *SymB = Target.getSymB(); - - if (SymB) { - const MCSymbol *B = &SymB->getSymbol(); - if (!B->getFragment()) { - Asm.getContext().reportError( - Fixup.getLoc(), - Twine("symbol '") + B->getName() + - "' can not be undefined in a subtraction expression"); - return; - } - - // Offset of the symbol in the section - int64_t OffsetOfB = Layout.getSymbolOffset(*B); - - // Offset of the relocation in the section - int64_t OffsetOfRelocation = - Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); - - FixedValue = (OffsetOfRelocation - OffsetOfB) + Target.getConstant(); - } else { - FixedValue = Target.getConstant(); - } - - COFFRelocation Reloc; - - Reloc.Data.SymbolTableIndex = 0; - Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment); - - // Turn relocations for temporary symbols into section relocations. - if (A.isTemporary()) { - MCSection *TargetSection = &A.getSection(); - assert( - SectionMap.find(TargetSection) != SectionMap.end() && - "Section must already have been defined in executePostLayoutBinding!"); - Reloc.Symb = SectionMap[TargetSection]->Symbol; - FixedValue += Layout.getSymbolOffset(A); - } else { - assert( - SymbolMap.find(&A) != SymbolMap.end() && - "Symbol must already have been defined in executePostLayoutBinding!"); - Reloc.Symb = SymbolMap[&A]; - } - - ++Reloc.Symb->Relocations; - - Reloc.Data.VirtualAddress += Fixup.getOffset(); - Reloc.Data.Type = TargetObjectWriter->getRelocType( - Asm.getContext(), Target, Fixup, SymB, Asm.getBackend()); - - // FIXME: Can anyone explain what this does other than adjust for the size - // of the offset? - if ((Header.Machine == COFF::IMAGE_FILE_MACHINE_AMD64 && - Reloc.Data.Type == COFF::IMAGE_REL_AMD64_REL32) || - (Header.Machine == COFF::IMAGE_FILE_MACHINE_I386 && - Reloc.Data.Type == COFF::IMAGE_REL_I386_REL32)) - FixedValue += 4; - - if (Header.Machine == COFF::IMAGE_FILE_MACHINE_ARMNT) { - switch (Reloc.Data.Type) { - case COFF::IMAGE_REL_ARM_ABSOLUTE: - case COFF::IMAGE_REL_ARM_ADDR32: - case COFF::IMAGE_REL_ARM_ADDR32NB: - case COFF::IMAGE_REL_ARM_TOKEN: - case COFF::IMAGE_REL_ARM_SECTION: - case COFF::IMAGE_REL_ARM_SECREL: - break; - case COFF::IMAGE_REL_ARM_BRANCH11: - case COFF::IMAGE_REL_ARM_BLX11: - // IMAGE_REL_ARM_BRANCH11 and IMAGE_REL_ARM_BLX11 are only used for - // pre-ARMv7, which implicitly rules it out of ARMNT (it would be valid - // for Windows CE). - case COFF::IMAGE_REL_ARM_BRANCH24: - case COFF::IMAGE_REL_ARM_BLX24: - case COFF::IMAGE_REL_ARM_MOV32A: - // IMAGE_REL_ARM_BRANCH24, IMAGE_REL_ARM_BLX24, IMAGE_REL_ARM_MOV32A are - // only used for ARM mode code, which is documented as being unsupported - // by Windows on ARM. Empirical proof indicates that masm is able to - // generate the relocations however the rest of the MSVC toolchain is - // unable to handle it. - llvm_unreachable("unsupported relocation"); - break; - case COFF::IMAGE_REL_ARM_MOV32T: - break; - case COFF::IMAGE_REL_ARM_BRANCH20T: - case COFF::IMAGE_REL_ARM_BRANCH24T: - case COFF::IMAGE_REL_ARM_BLX23T: - // IMAGE_REL_BRANCH20T, IMAGE_REL_ARM_BRANCH24T, IMAGE_REL_ARM_BLX23T all - // perform a 4 byte adjustment to the relocation. Relative branches are - // offset by 4 on ARM, however, because there is no RELA relocations, all - // branches are offset by 4. - FixedValue = FixedValue + 4; - break; - } - } - - // The fixed value never makes sense for section indices, ignore it. - if (Fixup.getKind() == FK_SecRel_2) - FixedValue = 0; - - if (TargetObjectWriter->recordRelocation(Fixup)) - Sec->Relocations.push_back(Reloc); -} - -static std::time_t getTime() { - std::time_t Now = time(nullptr); - if (Now < 0 || !isUInt<32>(Now)) - return UINT32_MAX; - return Now; -} - -// Create .file symbols. -void WinCOFFObjectWriter::createFileSymbols(MCAssembler &Asm) { - for (const std::string &Name : Asm.getFileNames()) { - // round up to calculate the number of auxiliary symbols required - unsigned SymbolSize = UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size; - unsigned Count = (Name.size() + SymbolSize - 1) / SymbolSize; - - COFFSymbol *File = createSymbol(".file"); - File->Data.SectionNumber = COFF::IMAGE_SYM_DEBUG; - File->Data.StorageClass = COFF::IMAGE_SYM_CLASS_FILE; - File->Aux.resize(Count); - - unsigned Offset = 0; - unsigned Length = Name.size(); - for (auto &Aux : File->Aux) { - Aux.AuxType = ATFile; - - if (Length > SymbolSize) { - memcpy(&Aux.Aux, Name.c_str() + Offset, SymbolSize); - Length = Length - SymbolSize; - } else { - memcpy(&Aux.Aux, Name.c_str() + Offset, Length); - memset((char *)&Aux.Aux + Length, 0, SymbolSize - Length); - break; - } - - Offset += SymbolSize; - } - } -} - -static bool isAssociative(const COFFSection &Section) { - return Section.Symbol->Aux[0].Aux.SectionDefinition.Selection == - COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE; -} - -void WinCOFFObjectWriter::assignSectionNumbers() { - size_t I = 1; - auto Assign = [&](COFFSection &Section) { - Section.Number = I; - Section.Symbol->Data.SectionNumber = I; - Section.Symbol->Aux[0].Aux.SectionDefinition.Number = I; - ++I; - }; - - // Although it is not explicitly requested by the Microsoft COFF spec, - // we should avoid emitting forward associative section references, - // because MSVC link.exe as of 2017 cannot handle that. - for (const std::unique_ptr<COFFSection> &Section : Sections) - if (!isAssociative(*Section)) - Assign(*Section); - for (const std::unique_ptr<COFFSection> &Section : Sections) - if (isAssociative(*Section)) - Assign(*Section); -} - -// Assign file offsets to COFF object file structures. -void WinCOFFObjectWriter::assignFileOffsets(MCAssembler &Asm, - const MCAsmLayout &Layout) { - unsigned Offset = W.OS.tell(); - - Offset += UseBigObj ? COFF::Header32Size : COFF::Header16Size; - Offset += COFF::SectionSize * Header.NumberOfSections; - - for (const auto &Section : Asm) { - COFFSection *Sec = SectionMap[&Section]; - - if (Sec->Number == -1) - continue; - - Sec->Header.SizeOfRawData = Layout.getSectionAddressSize(&Section); - - if (IsPhysicalSection(Sec)) { - Sec->Header.PointerToRawData = Offset; - Offset += Sec->Header.SizeOfRawData; - } - - if (!Sec->Relocations.empty()) { - bool RelocationsOverflow = Sec->Relocations.size() >= 0xffff; - - if (RelocationsOverflow) { - // Signal overflow by setting NumberOfRelocations to max value. Actual - // size is found in reloc #0. Microsoft tools understand this. - Sec->Header.NumberOfRelocations = 0xffff; - } else { - Sec->Header.NumberOfRelocations = Sec->Relocations.size(); - } - Sec->Header.PointerToRelocations = Offset; - - if (RelocationsOverflow) { - // Reloc #0 will contain actual count, so make room for it. - Offset += COFF::RelocationSize; - } - - Offset += COFF::RelocationSize * Sec->Relocations.size(); - - for (auto &Relocation : Sec->Relocations) { - assert(Relocation.Symb->getIndex() != -1); - Relocation.Data.SymbolTableIndex = Relocation.Symb->getIndex(); - } - } - - assert(Sec->Symbol->Aux.size() == 1 && - "Section's symbol must have one aux!"); - AuxSymbol &Aux = Sec->Symbol->Aux[0]; - assert(Aux.AuxType == ATSectionDefinition && - "Section's symbol's aux symbol must be a Section Definition!"); - Aux.Aux.SectionDefinition.Length = Sec->Header.SizeOfRawData; - Aux.Aux.SectionDefinition.NumberOfRelocations = - Sec->Header.NumberOfRelocations; - Aux.Aux.SectionDefinition.NumberOfLinenumbers = - Sec->Header.NumberOfLineNumbers; - } - - Header.PointerToSymbolTable = Offset; -} - -uint64_t WinCOFFObjectWriter::writeObject(MCAssembler &Asm, - const MCAsmLayout &Layout) { - uint64_t StartOffset = W.OS.tell(); - - if (Sections.size() > INT32_MAX) - report_fatal_error( - "PE COFF object files can't have more than 2147483647 sections"); - - UseBigObj = Sections.size() > COFF::MaxNumberOfSections16; - Header.NumberOfSections = Sections.size(); - Header.NumberOfSymbols = 0; - - assignSectionNumbers(); - createFileSymbols(Asm); - - for (auto &Symbol : Symbols) { - // Update section number & offset for symbols that have them. - if (Symbol->Section) - Symbol->Data.SectionNumber = Symbol->Section->Number; - Symbol->setIndex(Header.NumberOfSymbols++); - // Update auxiliary symbol info. - Symbol->Data.NumberOfAuxSymbols = Symbol->Aux.size(); - Header.NumberOfSymbols += Symbol->Data.NumberOfAuxSymbols; - } - - // Build string table. - for (const auto &S : Sections) - if (S->Name.size() > COFF::NameSize) - Strings.add(S->Name); - for (const auto &S : Symbols) - if (S->Name.size() > COFF::NameSize) - Strings.add(S->Name); - Strings.finalize(); - - // Set names. - for (const auto &S : Sections) - SetSectionName(*S); - for (auto &S : Symbols) - SetSymbolName(*S); - - // Fixup weak external references. - for (auto &Symbol : Symbols) { - if (Symbol->Other) { - assert(Symbol->getIndex() != -1); - assert(Symbol->Aux.size() == 1 && "Symbol must contain one aux symbol!"); - assert(Symbol->Aux[0].AuxType == ATWeakExternal && - "Symbol's aux symbol must be a Weak External!"); - Symbol->Aux[0].Aux.WeakExternal.TagIndex = Symbol->Other->getIndex(); - } - } - - // Fixup associative COMDAT sections. - for (auto &Section : Sections) { - if (Section->Symbol->Aux[0].Aux.SectionDefinition.Selection != - COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) - continue; - - const MCSectionCOFF &MCSec = *Section->MCSection; - const MCSymbol *AssocMCSym = MCSec.getCOMDATSymbol(); - assert(AssocMCSym); - - // It's an error to try to associate with an undefined symbol or a symbol - // without a section. - if (!AssocMCSym->isInSection()) { - Asm.getContext().reportError( - SMLoc(), Twine("cannot make section ") + MCSec.getSectionName() + - Twine(" associative with sectionless symbol ") + - AssocMCSym->getName()); - continue; - } - - const auto *AssocMCSec = cast<MCSectionCOFF>(&AssocMCSym->getSection()); - assert(SectionMap.count(AssocMCSec)); - COFFSection *AssocSec = SectionMap[AssocMCSec]; - - // Skip this section if the associated section is unused. - if (AssocSec->Number == -1) - continue; - - Section->Symbol->Aux[0].Aux.SectionDefinition.Number = AssocSec->Number; - } - - // Create the contents of the .llvm_addrsig section. - if (EmitAddrsigSection) { - auto Frag = new MCDataFragment(AddrsigSection); - Frag->setLayoutOrder(0); - raw_svector_ostream OS(Frag->getContents()); - for (const MCSymbol *S : AddrsigSyms) { - if (!S->isTemporary()) { - encodeULEB128(S->getIndex(), OS); - continue; - } - - MCSection *TargetSection = &S->getSection(); - assert(SectionMap.find(TargetSection) != SectionMap.end() && - "Section must already have been defined in " - "executePostLayoutBinding!"); - encodeULEB128(SectionMap[TargetSection]->Symbol->getIndex(), OS); - } - } - - assignFileOffsets(Asm, Layout); - - // MS LINK expects to be able to use this timestamp to implement their - // /INCREMENTAL feature. - if (Asm.isIncrementalLinkerCompatible()) { - Header.TimeDateStamp = getTime(); - } else { - // Have deterministic output if /INCREMENTAL isn't needed. Also matches GNU. - Header.TimeDateStamp = 0; - } - - // Write it all to disk... - WriteFileHeader(Header); - writeSectionHeaders(); - - // Write section contents. - sections::iterator I = Sections.begin(); - sections::iterator IE = Sections.end(); - MCAssembler::iterator J = Asm.begin(); - MCAssembler::iterator JE = Asm.end(); - for (; I != IE && J != JE; ++I, ++J) - writeSection(Asm, Layout, **I, *J); - - assert(W.OS.tell() == Header.PointerToSymbolTable && - "Header::PointerToSymbolTable is insane!"); - - // Write a symbol table. - for (auto &Symbol : Symbols) - if (Symbol->getIndex() != -1) - WriteSymbol(*Symbol); - - // Write a string table, which completes the entire COFF file. - Strings.write(W.OS); - - return W.OS.tell() - StartOffset; -} - -MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_) - : Machine(Machine_) {} - -// Pin the vtable to this file. -void MCWinCOFFObjectTargetWriter::anchor() {} - -//------------------------------------------------------------------------------ -// WinCOFFObjectWriter factory function - -std::unique_ptr<MCObjectWriter> llvm::createWinCOFFObjectWriter( - std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS) { - return llvm::make_unique<WinCOFFObjectWriter>(std::move(MOTW), OS); -} diff --git a/contrib/llvm/lib/MC/XCOFFObjectWriter.cpp b/contrib/llvm/lib/MC/XCOFFObjectWriter.cpp deleted file mode 100644 index 9b9a7b6c118c..000000000000 --- a/contrib/llvm/lib/MC/XCOFFObjectWriter.cpp +++ /dev/null @@ -1,94 +0,0 @@ -//===-- lib/MC/XCOFFObjectWriter.cpp - XCOFF file writer ------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements XCOFF object file writer information. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCValue.h" -#include "llvm/MC/MCXCOFFObjectWriter.h" - -using namespace llvm; - -namespace { - -class XCOFFObjectWriter : public MCObjectWriter { - support::endian::Writer W; - std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter; - - void executePostLayoutBinding(MCAssembler &, const MCAsmLayout &) override; - - void recordRelocation(MCAssembler &, const MCAsmLayout &, const MCFragment *, - const MCFixup &, MCValue, uint64_t &) override; - - uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override; - -public: - XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, - raw_pwrite_stream &OS); -}; - -XCOFFObjectWriter::XCOFFObjectWriter( - std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS) - : W(OS, support::big), TargetObjectWriter(std::move(MOTW)) {} - -void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &, - const MCAsmLayout &) { - // TODO Implement once we have sections and symbols to handle. -} - -void XCOFFObjectWriter::recordRelocation(MCAssembler &, const MCAsmLayout &, - const MCFragment *, const MCFixup &, - MCValue, uint64_t &) { - report_fatal_error("XCOFF relocations not supported."); -} - -uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &) { - // We always emit a timestamp of 0 for reproducibility, so ensure incremental - // linking is not enabled, in case, like with Windows COFF, such a timestamp - // is incompatible with incremental linking of XCOFF. - if (Asm.isIncrementalLinkerCompatible()) - report_fatal_error("Incremental linking not supported for XCOFF."); - - if (TargetObjectWriter->is64Bit()) - report_fatal_error("64-bit XCOFF object files are not supported yet."); - - uint64_t StartOffset = W.OS.tell(); - - // TODO FIXME Assign section numbers/finalize sections. - - // TODO FIXME Finalize symbols. - - // Magic. - W.write<uint16_t>(0x01df); - // Number of sections. - W.write<uint16_t>(0); - // Timestamp field. For reproducible output we write a 0, which represents no - // timestamp. - W.write<int32_t>(0); - // Byte Offset to the start of the symbol table. - W.write<uint32_t>(0); - // Number of entries in the symbol table. - W.write<int32_t>(0); - // Size of the optional header. - W.write<uint16_t>(0); - // Flags. - W.write<uint16_t>(0); - - return W.OS.tell() - StartOffset; -} - -} // end anonymous namespace - -std::unique_ptr<MCObjectWriter> -llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, - raw_pwrite_stream &OS) { - return llvm::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS); -} |