aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/MC
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/MC')
-rw-r--r--contrib/llvm/lib/MC/ConstantPools.cpp118
-rw-r--r--contrib/llvm/lib/MC/ELFObjectWriter.cpp1372
-rw-r--r--contrib/llvm/lib/MC/MCAsmBackend.cpp61
-rw-r--r--contrib/llvm/lib/MC/MCAsmInfo.cpp112
-rw-r--r--contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp52
-rw-r--r--contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp98
-rw-r--r--contrib/llvm/lib/MC/MCAsmInfoELF.cpp35
-rw-r--r--contrib/llvm/lib/MC/MCAsmInfoWasm.cpp27
-rw-r--r--contrib/llvm/lib/MC/MCAsmStreamer.cpp1700
-rw-r--r--contrib/llvm/lib/MC/MCAssembler.cpp960
-rw-r--r--contrib/llvm/lib/MC/MCCodeEmitter.cpp16
-rw-r--r--contrib/llvm/lib/MC/MCCodeView.cpp572
-rw-r--r--contrib/llvm/lib/MC/MCContext.cpp630
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp342
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/Disassembler.h127
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp38
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp200
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp31
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/MCSymbolizer.cpp14
-rw-r--r--contrib/llvm/lib/MC/MCDwarf.cpp1610
-rw-r--r--contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp32
-rw-r--r--contrib/llvm/lib/MC/MCELFStreamer.cpp648
-rw-r--r--contrib/llvm/lib/MC/MCExpr.cpp821
-rw-r--r--contrib/llvm/lib/MC/MCFragment.cpp471
-rw-r--r--contrib/llvm/lib/MC/MCInst.cpp74
-rw-r--r--contrib/llvm/lib/MC/MCInstPrinter.cpp122
-rw-r--r--contrib/llvm/lib/MC/MCInstrAnalysis.cpp27
-rw-r--r--contrib/llvm/lib/MC/MCInstrDesc.cpp70
-rw-r--r--contrib/llvm/lib/MC/MCLabel.cpp25
-rw-r--r--contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp60
-rw-r--r--contrib/llvm/lib/MC/MCMachOStreamer.cpp515
-rw-r--r--contrib/llvm/lib/MC/MCMachObjectTargetWriter.cpp19
-rw-r--r--contrib/llvm/lib/MC/MCNullStreamer.cpp47
-rw-r--r--contrib/llvm/lib/MC/MCObjectFileInfo.cpp908
-rw-r--r--contrib/llvm/lib/MC/MCObjectStreamer.cpp605
-rw-r--r--contrib/llvm/lib/MC/MCObjectWriter.cpp53
-rw-r--r--contrib/llvm/lib/MC/MCParser/AsmLexer.cpp733
-rw-r--r--contrib/llvm/lib/MC/MCParser/AsmParser.cpp5630
-rw-r--r--contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp832
-rw-r--r--contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp1051
-rw-r--r--contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp848
-rw-r--r--contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp36
-rw-r--r--contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp145
-rw-r--r--contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp20
-rw-r--r--contrib/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp29
-rw-r--r--contrib/llvm/lib/MC/MCRegisterInfo.cpp104
-rw-r--r--contrib/llvm/lib/MC/MCSchedule.cpp34
-rw-r--r--contrib/llvm/lib/MC/MCSection.cpp101
-rw-r--r--contrib/llvm/lib/MC/MCSectionCOFF.cpp111
-rw-r--r--contrib/llvm/lib/MC/MCSectionELF.cpp191
-rw-r--r--contrib/llvm/lib/MC/MCSectionMachO.cpp282
-rw-r--r--contrib/llvm/lib/MC/MCSectionWasm.cpp97
-rw-r--r--contrib/llvm/lib/MC/MCStreamer.cpp878
-rw-r--r--contrib/llvm/lib/MC/MCSubtargetInfo.cpp113
-rw-r--r--contrib/llvm/lib/MC/MCSymbol.cpp88
-rw-r--r--contrib/llvm/lib/MC/MCSymbolELF.cpp205
-rw-r--r--contrib/llvm/lib/MC/MCTargetOptions.cpp25
-rw-r--r--contrib/llvm/lib/MC/MCValue.cpp61
-rw-r--r--contrib/llvm/lib/MC/MCWasmObjectTargetWriter.cpp21
-rw-r--r--contrib/llvm/lib/MC/MCWasmStreamer.cpp228
-rw-r--r--contrib/llvm/lib/MC/MCWin64EH.cpp246
-rw-r--r--contrib/llvm/lib/MC/MCWinCOFFStreamer.cpp298
-rw-r--r--contrib/llvm/lib/MC/MCWinEH.cpp26
-rw-r--r--contrib/llvm/lib/MC/MachObjectWriter.cpp1001
-rw-r--r--contrib/llvm/lib/MC/StringTableBuilder.cpp190
-rw-r--r--contrib/llvm/lib/MC/SubtargetFeature.cpp279
-rw-r--r--contrib/llvm/lib/MC/WasmObjectWriter.cpp1294
-rw-r--r--contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp1090
68 files changed, 28899 insertions, 0 deletions
diff --git a/contrib/llvm/lib/MC/ConstantPools.cpp b/contrib/llvm/lib/MC/ConstantPools.cpp
new file mode 100644
index 000000000000..ca5440237e49
--- /dev/null
+++ b/contrib/llvm/lib/MC/ConstantPools.cpp
@@ -0,0 +1,118 @@
+//===- ConstantPools.cpp - ConstantPool class -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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
new file mode 100644
index 000000000000..30f357826805
--- /dev/null
+++ b/contrib/llvm/lib/MC/ELFObjectWriter.cpp
@@ -0,0 +1,1372 @@
+//===- lib/MC/ELFObjectWriter.cpp - ELF File Writer -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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/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/MCFragment.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/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;
+
+class SymbolTableWriter {
+ ELFObjectWriter &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(ELFObjectWriter &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; }
+};
+
+class ELFObjectWriter : public MCObjectWriter {
+ 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;
+ }
+ };
+
+ /// The target specific ELF writer instance.
+ std::unique_ptr<MCELFObjectTargetWriter> TargetObjectWriter;
+
+ DenseMap<const MCSymbolELF *, const MCSymbolELF *> Renames;
+
+ DenseMap<const MCSectionELF *, std::vector<ELFRelocationEntry>> Relocations;
+
+ /// @}
+ /// @name Symbol Table Data
+ /// @{
+
+ BumpPtrAllocator Alloc;
+ StringSaver VersionSymSaver{Alloc};
+ 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 { return TargetObjectWriter->is64Bit(); }
+ bool hasRelocationAddend() const {
+ return TargetObjectWriter->hasRelocationAddend();
+ }
+ unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
+ const MCFixup &Fixup, bool IsPCRel) const {
+ return TargetObjectWriter->getRelocType(Ctx, Target, Fixup, IsPCRel);
+ }
+
+ void align(unsigned Alignment);
+
+ bool maybeWriteCompression(uint64_t Size,
+ SmallVectorImpl<char> &CompressedContents,
+ bool ZLibStyle, unsigned Alignment);
+
+public:
+ ELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_pwrite_stream &OS,
+ bool IsLittleEndian)
+ : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {}
+
+ ~ELFObjectWriter() override = default;
+
+ void reset() override {
+ Renames.clear();
+ Relocations.clear();
+ StrTabBuilder.clear();
+ SectionTable.clear();
+ MCObjectWriter::reset();
+ }
+
+ void WriteWord(uint64_t W) {
+ if (is64Bit())
+ write64(W);
+ else
+ write32(W);
+ }
+
+ template <typename T> void write(T Val) {
+ if (IsLittleEndian)
+ support::endian::Writer<support::little>(getStream()).write(Val);
+ else
+ support::endian::Writer<support::big>(getStream()).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>>;
+
+ bool shouldRelocateWithSymbol(const MCAssembler &Asm,
+ const MCSymbolRefExpr *RefA,
+ const MCSymbol *Sym, uint64_t C,
+ unsigned Type) const;
+
+ void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
+ const MCFragment *Fragment, const MCFixup &Fixup,
+ MCValue Target, bool &IsPCRel,
+ uint64_t &FixedValue) override;
+
+ // 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);
+
+ MCSectionELF *createRelocationSection(MCContext &Ctx,
+ const MCSectionELF &Sec);
+
+ const MCSectionELF *createStringTable(MCContext &Ctx);
+
+ void executePostLayoutBinding(MCAssembler &Asm,
+ const MCAsmLayout &Layout) override;
+
+ 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);
+
+ using MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl;
+ bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
+ const MCSymbol &SymA,
+ const MCFragment &FB, bool InSet,
+ bool IsPCRel) const override;
+
+ void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
+ void writeSection(const SectionIndexMapTy &SectionIndexMap,
+ uint32_t GroupSymbolIndex, uint64_t Offset, uint64_t Size,
+ const MCSectionELF &Section);
+};
+
+} // end anonymous namespace
+
+void ELFObjectWriter::align(unsigned Alignment) {
+ uint64_t Padding = OffsetToAlignment(getStream().tell(), Alignment);
+ WriteZeros(Padding);
+}
+
+unsigned ELFObjectWriter::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(ELFObjectWriter &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;
+}
+
+// Emit the ELF header.
+void ELFObjectWriter::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.
+
+ writeBytes(ELF::ElfMagic); // e_ident[EI_MAG0] to e_ident[EI_MAG3]
+
+ write8(is64Bit() ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS]
+
+ // e_ident[EI_DATA]
+ write8(isLittleEndian() ? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB);
+
+ write8(ELF::EV_CURRENT); // e_ident[EI_VERSION]
+ // e_ident[EI_OSABI]
+ write8(TargetObjectWriter->getOSABI());
+ write8(0); // e_ident[EI_ABIVERSION]
+
+ WriteZeros(ELF::EI_NIDENT - ELF::EI_PAD);
+
+ write16(ELF::ET_REL); // e_type
+
+ write16(TargetObjectWriter->getEMachine()); // e_machine = target
+
+ write32(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
+ write32(Asm.getELFHeaderEFlags());
+
+ // e_ehsize = ELF header size
+ write16(is64Bit() ? sizeof(ELF::Elf64_Ehdr) : sizeof(ELF::Elf32_Ehdr));
+
+ write16(0); // e_phentsize = prog header entry size
+ write16(0); // e_phnum = # prog header entries = 0
+
+ // e_shentsize = Section header entry size
+ write16(is64Bit() ? sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr));
+
+ // e_shnum = # of section header ents
+ write16(0);
+
+ // e_shstrndx = Section # of '.shstrtab'
+ assert(StringTableIndex < ELF::SHN_LORESERVE);
+ write16(StringTableIndex);
+}
+
+uint64_t ELFObjectWriter::SymbolValue(const MCSymbol &Sym,
+ const MCAsmLayout &Layout) {
+ if (Sym.isCommon() && Sym.isExternal())
+ return Sym.getCommonAlignment();
+
+ uint64_t Res;
+ if (!Layout.getSymbolOffset(Sym, Res))
+ return 0;
+
+ if (Layout.getAssembler().isThumbFunc(&Sym))
+ Res |= 1;
+
+ return Res;
+}
+
+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 MCSymbol &A : Asm.symbols()) {
+ const auto &Alias = cast<MCSymbolELF>(A);
+ // Not an alias.
+ if (!Alias.isVariable())
+ continue;
+ auto *Ref = dyn_cast<MCSymbolRefExpr>(Alias.getVariableValue());
+ if (!Ref)
+ continue;
+ const auto &Symbol = cast<MCSymbolELF>(Ref->getSymbol());
+
+ StringRef AliasName = Alias.getName();
+ size_t Pos = AliasName.find('@');
+ if (Pos == StringRef::npos)
+ continue;
+
+ // 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());
+
+ StringRef Rest = AliasName.substr(Pos);
+ if (!Symbol.isUndefined() && !Rest.startswith("@@@"))
+ continue;
+
+ // FIXME: produce a better error message.
+ if (Symbol.isUndefined() && Rest.startswith("@@") &&
+ !Rest.startswith("@@@"))
+ report_fatal_error("A @@ version cannot be undefined");
+
+ Renames.insert(std::make_pair(&Symbol, &Alias));
+ }
+}
+
+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 ELFObjectWriter::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);
+}
+
+// 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 MCSymbol *S, uint64_t C,
+ unsigned Type) const {
+ const auto *Sym = cast_or_null<MCSymbolELF>(S);
+ // 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;
+ }
+
+ // 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;
+}
+
+// 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;
+ }
+}
+
+void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup, MCValue Target,
+ bool &IsPCRel, uint64_t &FixedValue) {
+ 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 = 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;
+
+ if (!RelocateWithSymbol) {
+ const MCSection *SecA =
+ (SymA && !SymA->isUndefined()) ? &SymA->getSection() : nullptr;
+ auto *ELFSec = cast_or_null<MCSectionELF>(SecA);
+ const auto *SectionSymbol =
+ ELFSec ? cast<MCSymbolELF>(ELFSec->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::isInSymtab(const MCAsmLayout &Layout,
+ const MCSymbolELF &Symbol, bool Used,
+ bool Renamed) {
+ if (Symbol.isVariable()) {
+ const MCExpr *Expr = Symbol.getVariableValue();
+ 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 ELFObjectWriter::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 = getStream().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,
+ 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()) {
+ 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());
+ MSD.SectionIndex = SectionIndexMap.lookup(&Section);
+ assert(MSD.SectionIndex && "Invalid section index!");
+ if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
+ HasLargeSectionIndex = true;
+ }
+
+ // The @@@ in symbol version is replaced with @ in undefined symbols and @@
+ // in defined ones.
+ //
+ // FIXME: All name handling should be done before we get to the writer,
+ // including dealing with GNU-style version suffixes. Fixing this isn't
+ // trivial.
+ //
+ // We thus have to be careful to not perform the symbol version replacement
+ // blindly:
+ //
+ // The ELF format is used on Windows by the MCJIT engine. Thus, on
+ // Windows, the ELFObjectWriter can encounter symbols mangled using the MS
+ // Visual Studio C++ name mangling scheme. Symbols mangled using the MSVC
+ // C++ name mangling can legally have "@@@" as a sub-string. In that case,
+ // the EFLObjectWriter should not interpret the "@@@" sub-string as
+ // specifying GNU-style symbol versioning. The ELFObjectWriter therefore
+ // checks for the MSVC C++ name mangling prefix which is either "?", "@?",
+ // "__imp_?" or "__imp_@?".
+ //
+ // It would have been interesting to perform the MS mangling prefix check
+ // only when the target triple is of the form *-pc-windows-elf. But, it
+ // seems that this information is not easily accessible from the
+ // ELFObjectWriter.
+ StringRef Name = Symbol.getName();
+ SmallString<32> Buf;
+ if (!Name.startswith("?") && !Name.startswith("@?") &&
+ !Name.startswith("__imp_?") && !Name.startswith("__imp_@?")) {
+ // This symbol isn't following the MSVC C++ name mangling convention. We
+ // can thus safely interpret the @@@ in symbol names as specifying symbol
+ // versioning.
+ size_t Pos = Name.find("@@@");
+ if (Pos != StringRef::npos) {
+ Buf += Name.substr(0, Pos);
+ unsigned Skip = MSD.SectionIndex == ELF::SHN_UNDEF ? 2 : 1;
+ Buf += Name.substr(Pos + Skip);
+ Name = VersionSymSaver.save(Buf.c_str());
+ }
+ }
+
+ // 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_shndxr", 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 = getStream().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 = getStream().tell();
+ const MCSectionELF *SymtabShndxSection =
+ SectionTable[SymtabShndxSectionIndex - 1];
+ for (uint32_t Index : ShndxIndexes)
+ write(Index);
+ SecEnd = getStream().tell();
+ SectionOffsets[SymtabShndxSection] = std::make_pair(SecStart, SecEnd);
+}
+
+MCSectionELF *
+ELFObjectWriter::createRelocationSection(MCContext &Ctx,
+ const MCSectionELF &Sec) {
+ if (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 ELFObjectWriter::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;
+ write(ArrayRef<char>(Magic.begin(), Magic.size()));
+ writeBE64(Size);
+ return true;
+}
+
+void ELFObjectWriter::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(&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);
+ raw_pwrite_stream &OldStream = getStream();
+ setStream(VecOS);
+ Asm.writeSectionData(&Section, Layout);
+ setStream(OldStream);
+
+ SmallVector<char, 128> CompressedContents;
+ if (Error E = zlib::compress(
+ StringRef(UncompressedData.data(), UncompressedData.size()),
+ CompressedContents)) {
+ consumeError(std::move(E));
+ getStream() << UncompressedData;
+ return;
+ }
+
+ bool ZlibStyle = MAI->compressDebugSections() == DebugCompressionType::Z;
+ if (!maybeWriteCompression(UncompressedData.size(), CompressedContents,
+ ZlibStyle, Sec.getAlignment())) {
+ getStream() << UncompressedData;
+ return;
+ }
+
+ if (ZlibStyle)
+ // Set the compressed flag. That is zlib style.
+ Section.setFlags(Section.getFlags() | ELF::SHF_COMPRESSED);
+ else
+ // Add "z" prefix to section name. This is zlib-gnu style.
+ MC.renameELFSection(&Section, (".z" + SectionName.drop_front(1)).str());
+ getStream() << CompressedContents;
+}
+
+void ELFObjectWriter::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) {
+ write32(Name); // sh_name: index into string table
+ write32(Type); // sh_type
+ WriteWord(Flags); // sh_flags
+ WriteWord(Address); // sh_addr
+ WriteWord(Offset); // sh_offset
+ WriteWord(Size); // sh_size
+ write32(Link); // sh_link
+ write32(Info); // sh_info
+ WriteWord(Alignment); // sh_addralign
+ WriteWord(EntrySize); // sh_entsize
+}
+
+void ELFObjectWriter::writeRelocations(const MCAssembler &Asm,
+ const MCSectionELF &Sec) {
+ std::vector<ELFRelocationEntry> &Relocs = 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.
+ 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 (TargetObjectWriter->isN64()) {
+ write(uint32_t(Index));
+
+ write(TargetObjectWriter->getRSsym(Entry.Type));
+ write(TargetObjectWriter->getRType3(Entry.Type));
+ write(TargetObjectWriter->getRType2(Entry.Type));
+ write(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));
+ }
+ }
+}
+
+const MCSectionELF *ELFObjectWriter::createStringTable(MCContext &Ctx) {
+ const MCSectionELF *StrtabSection = SectionTable[StringTableIndex - 1];
+ StrTabBuilder.write(getStream());
+ return StrtabSection;
+}
+
+void ELFObjectWriter::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:
+ case ELF::SHT_DYNSYM:
+ sh_link = StringTableIndex;
+ sh_info = LastLocalSymbolIndex;
+ break;
+
+ case ELF::SHT_SYMTAB_SHNDX:
+ 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 ELFObjectWriter::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);
+ }
+}
+
+void ELFObjectWriter::writeObject(MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
+ 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);
+
+ align(Section.getAlignment());
+
+ // Remember the offset into the file for this section.
+ uint64_t SecStart = getStream().tell();
+
+ const MCSymbolELF *SignatureSymbol = Section.getGroup();
+ writeSectionData(Asm, Section, Layout);
+
+ uint64_t SecEnd = getStream().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);
+ }
+ }
+
+ for (MCSectionELF *Group : Groups) {
+ align(Group->getAlignment());
+
+ // Remember the offset into the file for this section.
+ uint64_t SecStart = getStream().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 = getStream().tell();
+ SectionOffsets[Group] = std::make_pair(SecStart, SecEnd);
+ }
+
+ // 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 = getStream().tell();
+
+ writeRelocations(Asm,
+ cast<MCSectionELF>(*RelSection->getAssociatedSection()));
+
+ uint64_t SecEnd = getStream().tell();
+ SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd);
+ }
+
+ {
+ uint64_t SecStart = getStream().tell();
+ const MCSectionELF *Sec = createStringTable(Ctx);
+ uint64_t SecEnd = getStream().tell();
+ SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd);
+ }
+
+ uint64_t NaturalAlignment = is64Bit() ? 8 : 4;
+ align(NaturalAlignment);
+
+ const uint64_t SectionHeaderOffset = getStream().tell();
+
+ // ... then the section header table ...
+ writeSectionHeader(Layout, SectionIndexMap, SectionOffsets);
+
+ uint16_t NumSections = (SectionTable.size() + 1 >= ELF::SHN_LORESERVE)
+ ? (uint16_t)ELF::SHN_UNDEF
+ : SectionTable.size() + 1;
+ if (sys::IsLittleEndianHost != IsLittleEndian)
+ sys::swapByteOrder(NumSections);
+ unsigned NumSectionsOffset;
+
+ if (is64Bit()) {
+ uint64_t Val = SectionHeaderOffset;
+ if (sys::IsLittleEndianHost != IsLittleEndian)
+ sys::swapByteOrder(Val);
+ getStream().pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
+ offsetof(ELF::Elf64_Ehdr, e_shoff));
+ NumSectionsOffset = offsetof(ELF::Elf64_Ehdr, e_shnum);
+ } else {
+ uint32_t Val = SectionHeaderOffset;
+ if (sys::IsLittleEndianHost != IsLittleEndian)
+ sys::swapByteOrder(Val);
+ getStream().pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
+ offsetof(ELF::Elf32_Ehdr, e_shoff));
+ NumSectionsOffset = offsetof(ELF::Elf32_Ehdr, e_shnum);
+ }
+ getStream().pwrite(reinterpret_cast<char *>(&NumSections),
+ sizeof(NumSections), NumSectionsOffset);
+}
+
+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);
+}
+
+MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW,
+ raw_pwrite_stream &OS,
+ bool IsLittleEndian) {
+ return new ELFObjectWriter(MOTW, OS, IsLittleEndian);
+}
diff --git a/contrib/llvm/lib/MC/MCAsmBackend.cpp b/contrib/llvm/lib/MC/MCAsmBackend.cpp
new file mode 100644
index 000000000000..3642f37aa855
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCAsmBackend.cpp
@@ -0,0 +1,61 @@
+//===- MCAsmBackend.cpp - Target MC Assembly Backend ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/MC/MCFixupKindInfo.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+
+using namespace llvm;
+
+MCAsmBackend::MCAsmBackend() = default;
+
+MCAsmBackend::~MCAsmBackend() = default;
+
+Optional<MCFixupKind> MCAsmBackend::getFixupKind(StringRef Name) const {
+ return None;
+}
+
+const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
+ static const MCFixupKindInfo Builtins[] = {
+ {"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_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}};
+
+ 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 {
+ if (!Resolved)
+ return true;
+ return fixupNeedsRelaxation(Fixup, Value, DF, Layout);
+}
diff --git a/contrib/llvm/lib/MC/MCAsmInfo.cpp b/contrib/llvm/lib/MC/MCAsmInfo.cpp
new file mode 100644
index 000000000000..f05904048e0b
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCAsmInfo.cpp
@@ -0,0 +1,112 @@
+//===- MCAsmInfo.cpp - Asm Info -------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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"
+
+using namespace llvm;
+
+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";
+
+ // 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;
+
+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
new file mode 100644
index 000000000000..85104484fd40
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp
@@ -0,0 +1,52 @@
+//===- MCAsmInfoCOFF.cpp - COFF asm properties ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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 = false;
+ 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;
+}
+
+void MCAsmInfoMicrosoft::anchor() {}
+
+MCAsmInfoMicrosoft::MCAsmInfoMicrosoft() = default;
+
+void MCAsmInfoGNUCOFF::anchor() {}
+
+MCAsmInfoGNUCOFF::MCAsmInfoGNUCOFF() = default;
diff --git a/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp b/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp
new file mode 100644
index 000000000000..c74840982fb7
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp
@@ -0,0 +1,98 @@
+//===- MCAsmInfoDarwin.cpp - Darwin asm properties ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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
new file mode 100644
index 000000000000..b0dc43c6c868
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCAsmInfoELF.cpp
@@ -0,0 +1,35 @@
+//===- MCAsmInfoELF.cpp - ELF asm properties ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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
new file mode 100644
index 000000000000..aa26616dda36
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCAsmInfoWasm.cpp
@@ -0,0 +1,27 @@
+//===-- MCAsmInfoWasm.cpp - Wasm asm properties -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines target asm properties related what form asm statements
+// should take in general on Wasm-based targets
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAsmInfoWasm.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSectionWasm.h"
+using namespace llvm;
+
+void MCAsmInfoWasm::anchor() { }
+
+MCAsmInfoWasm::MCAsmInfoWasm() {
+ HasIdentDirective = true;
+ WeakRefDirective = "\t.weak\t";
+ PrivateGlobalPrefix = ".L";
+ PrivateLabelPrefix = ".L";
+}
diff --git a/contrib/llvm/lib/MC/MCAsmStreamer.cpp b/contrib/llvm/lib/MC/MCAsmStreamer.cpp
new file mode 100644
index 000000000000..9e5553fa8d42
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCAsmStreamer.cpp
@@ -0,0 +1,1700 @@
+//===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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/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/MCRegisterInfo.h"
+#include "llvm/MC/MCSectionCOFF.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbolELF.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/SourceMgr.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<MCCodeEmitter> Emitter;
+ std::unique_ptr<MCAsmBackend> AsmBackend;
+
+ SmallString<128> ExplicitCommentToEmit;
+ SmallString<128> CommentToEmit;
+ raw_svector_ostream CommentStream;
+
+ 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, MCCodeEmitter *emitter,
+ MCAsmBackend *asmbackend, bool showInst)
+ : MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner),
+ MAI(Context.getAsmInfo()), InstPrinter(printer), Emitter(emitter),
+ AsmBackend(asmbackend), CommentStream(CommentToEmit),
+ IsVerboseAsm(isVerboseAsm), ShowInst(showInst),
+ UseDwarfDirectory(useDwarfDirectory) {
+ assert(InstPrinter);
+ if (IsVerboseAsm)
+ InstPrinter->setCommentStream(CommentStream);
+ }
+
+ 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();
+
+ /// isVerboseAsm - Return true if this streamer supports verbose assembly at
+ /// all.
+ bool isVerboseAsm() const override { return IsVerboseAsm; }
+
+ /// hasRawTextSupport - We support EmitRawText.
+ bool hasRawTextSupport() const override { return true; }
+
+ /// AddComment - Add a comment that can be emitted to the generated .s
+ /// file if applicable as a QoI issue 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;
+
+ /// AddEncodingComment - Add a comment showing the encoding of an instruction.
+ /// If PrintSchedInfo - is true then the comment sched:[x:y] should
+ // be added to output if it's being supported by target
+ void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &,
+ bool PrintSchedInfo);
+
+ /// GetCommentOS - 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;
+
+ /// AddBlankLine - 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 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) 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 EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
+ void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
+ void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
+ void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment) override;
+
+ /// EmitLocalCommonSymbol - 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) 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 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(uint64_t NumBytes, uint8_t FillValue) override;
+
+ void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
+ SMLoc Loc = SMLoc()) override;
+
+ void emitFill(uint64_t NumValues, int64_t Size, int64_t Expr) 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;
+ unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
+ StringRef Filename,
+ 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) 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 EmitIdent(StringRef IdentString) 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 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 EmitWinCFIStartProc(const MCSymbol *Symbol) override;
+ void EmitWinCFIEndProc() override;
+ void EmitWinCFIStartChained() override;
+ void EmitWinCFIEndChained() override;
+ void EmitWinCFIPushReg(unsigned Register) override;
+ void EmitWinCFISetFrame(unsigned Register, unsigned Offset) override;
+ void EmitWinCFIAllocStack(unsigned Size) override;
+ void EmitWinCFISaveReg(unsigned Register, unsigned Offset) override;
+ void EmitWinCFISaveXMM(unsigned Register, unsigned Offset) override;
+ void EmitWinCFIPushFrame(bool Code) override;
+ void EmitWinCFIEndProlog() override;
+
+ void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except) override;
+ void EmitWinEHHandlerData() override;
+
+ void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ bool PrintSchedInfo) 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) override;
+
+ /// 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 EmitRawTextImpl(StringRef String) override;
+
+ void FinishImpl() override;
+};
+
+} // end anonymous namespace.
+
+/// AddComment - Add a comment that can be emitted to the generated .s
+/// file if applicable as a QoI issue to make the output of the compiler
+/// more readable. This only affects the MCAsmStreamer, and only when
+/// verbose assembly output is enabled.
+/// By deafult EOL is set to true so that each comment goes on its own line.
+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!");
+ Section->PrintSwitchToSection(
+ *MAI, getContext().getObjectFileInfo()->getTargetTriple(), OS,
+ Subsection);
+}
+
+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();
+}
+
+void MCAsmStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major,
+ unsigned Minor, unsigned Update) {
+ switch (Kind) {
+ case MCVM_WatchOSVersionMin: OS << "\t.watchos_version_min"; break;
+ case MCVM_TvOSVersionMin: OS << "\t.tvos_version_min"; break;
+ case MCVM_IOSVersionMin: OS << "\t.ios_version_min"; break;
+ case MCVM_OSXVersionMin: OS << "\t.macosx_version_min"; break;
+ }
+ OS << " " << Major << ", " << Minor;
+ if (Update)
+ OS << ", " << Update;
+ 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) {
+ 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 << "no_type"; 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;
+ }
+
+ 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::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::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();
+}
+
+/// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol.
+///
+/// @param Symbol - The common symbol to emit.
+/// @param Size - The size of the common symbol.
+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) {
+ if (Symbol)
+ AssignFragment(Symbol, &Section->getDummyFragment());
+
+ // Note: a .zerofill directive does not switch sections.
+ OS << ".zerofill ";
+
+ // 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.
+ // 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 (Data.size() == 1) {
+ OS << MAI->getData8bitsDirective();
+ OS << (unsigned)(unsigned char)Data[0];
+ 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::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;
+ Value->print(OS, MAI);
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) {
+ int64_t IntValue;
+ if (Value->evaluateAsAbsolute(IntValue)) {
+ EmitULEB128IntValue(IntValue);
+ return;
+ }
+ OS << ".uleb128 ";
+ Value->print(OS, MAI);
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) {
+ int64_t IntValue;
+ if (Value->evaluateAsAbsolute(IntValue)) {
+ EmitSLEB128IntValue(IntValue);
+ return;
+ }
+ OS << ".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();
+}
+
+/// emitFill - Emit NumBytes bytes worth of the value specified by
+/// FillValue. This implements directives such as '.space'.
+void MCAsmStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) {
+ if (NumBytes == 0) return;
+
+ const MCExpr *E = MCConstantExpr::create(NumBytes, getContext());
+ emitFill(*E, FillValue);
+}
+
+void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
+ SMLoc Loc) {
+ 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(uint64_t NumValues, int64_t Size, int64_t Expr) {
+ if (NumValues == 0)
+ return;
+
+ const MCExpr *E = MCConstantExpr::create(NumValues, getContext());
+ emitFill(*E, Size, Expr);
+}
+
+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();
+}
+
+unsigned MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo,
+ StringRef Directory,
+ StringRef Filename,
+ unsigned CUID) {
+ assert(CUID == 0);
+
+ MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
+ unsigned NumFiles = Table.getMCDwarfFiles().size();
+ FileNo = Table.getFile(Directory, Filename, FileNo);
+ if (FileNo == 0)
+ return 0;
+ if (NumFiles == Table.getMCDwarfFiles().size())
+ return FileNo;
+
+ 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);
+ EmitEOL();
+
+ return FileNo;
+}
+
+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 (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) {
+ if (!getContext().getCVContext().addFile(FileNo, Filename))
+ return false;
+
+ OS << "\t.cv_file\t" << FileNo << ' ';
+
+ PrintQuotedString(Filename, OS);
+ 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) {
+ OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "
+ << Column;
+ if (PrologueEnd)
+ OS << " prologue_end";
+
+ unsigned OldIsStmt = getContext().getCVContext().getCurrentCVLoc().isStmt();
+ if (IsStmt != OldIsStmt) {
+ OS << " is_stmt ";
+
+ if (IsStmt)
+ OS << "1";
+ else
+ OS << "0";
+ }
+
+ if (IsVerboseAsm) {
+ OS.PadToColumn(MAI->getCommentColumn());
+ OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':'
+ << Column;
+ }
+ EmitEOL();
+ this->MCStreamer::EmitCVLocDirective(FunctionId, FileNo, Line, Column,
+ PrologueEnd, IsStmt, FileName, Loc);
+}
+
+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::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()) {
+ const MCRegisterInfo *MRI = getContext().getRegisterInfo();
+ unsigned LLVMRegister = MRI->getLLVMRegNum(Register, true);
+ InstPrinter->printRegName(OS, LLVMRegister);
+ } else {
+ 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::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::EmitWinCFIStartProc(const MCSymbol *Symbol) {
+ MCStreamer::EmitWinCFIStartProc(Symbol);
+
+ OS << ".seh_proc ";
+ Symbol->print(OS, MAI);
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWinCFIEndProc() {
+ MCStreamer::EmitWinCFIEndProc();
+
+ OS << "\t.seh_endproc";
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWinCFIStartChained() {
+ MCStreamer::EmitWinCFIStartChained();
+
+ OS << "\t.seh_startchained";
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWinCFIEndChained() {
+ MCStreamer::EmitWinCFIEndChained();
+
+ OS << "\t.seh_endchained";
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind,
+ bool Except) {
+ MCStreamer::EmitWinEHHandler(Sym, Unwind, Except);
+
+ OS << "\t.seh_handler ";
+ Sym->print(OS, MAI);
+ if (Unwind)
+ OS << ", @unwind";
+ if (Except)
+ OS << ", @except";
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWinEHHandlerData() {
+ MCStreamer::EmitWinEHHandlerData();
+
+ // 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) {
+ MCStreamer::EmitWinCFIPushReg(Register);
+
+ OS << "\t.seh_pushreg " << Register;
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset) {
+ MCStreamer::EmitWinCFISetFrame(Register, Offset);
+
+ OS << "\t.seh_setframe " << Register << ", " << Offset;
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size) {
+ MCStreamer::EmitWinCFIAllocStack(Size);
+
+ OS << "\t.seh_stackalloc " << Size;
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset) {
+ MCStreamer::EmitWinCFISaveReg(Register, Offset);
+
+ OS << "\t.seh_savereg " << Register << ", " << Offset;
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) {
+ MCStreamer::EmitWinCFISaveXMM(Register, Offset);
+
+ OS << "\t.seh_savexmm " << Register << ", " << Offset;
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWinCFIPushFrame(bool Code) {
+ MCStreamer::EmitWinCFIPushFrame(Code);
+
+ OS << "\t.seh_pushframe";
+ if (Code)
+ OS << " @code";
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitWinCFIEndProlog() {
+ MCStreamer::EmitWinCFIEndProlog();
+
+ OS << "\t.seh_endprologue";
+ EmitEOL();
+}
+
+void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
+ const MCSubtargetInfo &STI,
+ bool PrintSchedInfo) {
+ raw_ostream &OS = GetCommentOS();
+ SmallString<256> Code;
+ SmallVector<MCFixup, 4> Fixups;
+ raw_svector_ostream VecOS(Code);
+ Emitter->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 = AsmBackend->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 << "]";
+ // If we are not going to add fixup or schedul comments after this point then
+ // we have to end the current comment line with "\n".
+ if (Fixups.size() || !PrintSchedInfo)
+ OS << "\n";
+
+ for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
+ MCFixup &F = Fixups[i];
+ const MCFixupKindInfo &Info = AsmBackend->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,
+ bool PrintSchedInfo) {
+ assert(getCurrentSectionOnly() &&
+ "Cannot emit contents before setting section!");
+
+ // Show the encoding in a comment if we have a code emitter.
+ if (Emitter)
+ AddEncodingComment(Inst, STI, PrintSchedInfo);
+
+ // Show the MCInst if enabled.
+ if (ShowInst) {
+ if (PrintSchedInfo)
+ GetCommentOS() << "\n";
+ Inst.dump_pretty(GetCommentOS(), InstPrinter.get(), "\n ");
+ GetCommentOS() << "\n";
+ }
+
+ if(getTargetStreamer())
+ getTargetStreamer()->prettyPrintAsm(*InstPrinter, OS, Inst, STI);
+ else
+ InstPrinter->printInst(&Inst, OS, "", STI);
+
+ if (PrintSchedInfo) {
+ std::string SI = STI.getSchedInfoStr(Inst);
+ if (!SI.empty())
+ GetCommentOS() << SI;
+ }
+
+ 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) {
+ OS << "\t.reloc ";
+ Offset.print(OS, MAI);
+ OS << ", " << Name;
+ if (Expr) {
+ OS << ", ";
+ Expr->print(OS, MAI);
+ }
+ EmitEOL();
+ return false;
+}
+
+/// 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.
+ 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, MCCodeEmitter *CE,
+ MCAsmBackend *MAB, bool ShowInst) {
+ return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm,
+ useDwarfDirectory, IP, CE, MAB, ShowInst);
+}
diff --git a/contrib/llvm/lib/MC/MCAssembler.cpp b/contrib/llvm/lib/MC/MCAssembler.cpp
new file mode 100644
index 000000000000..0318d916aa49
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCAssembler.cpp
@@ -0,0 +1,960 @@
+//===- lib/MC/MCAssembler.cpp - Assembler Backend Implementation ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/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");
+
+} // 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, MCAsmBackend &Backend,
+ MCCodeEmitter &Emitter, MCObjectWriter &Writer)
+ : Context(Context), Backend(Backend), Emitter(Emitter), Writer(Writer),
+ BundleAlignSize(0), RelaxAll(false), SubsectionsViaSymbols(false),
+ IncrementalLinkerCompatible(false), ELFHeaderEFlags(0) {
+ VersionMinInfo.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();
+ VersionMinInfo.Major = 0;
+
+ // reset objects owned by us
+ getBackend().reset();
+ getEmitter().reset();
+ getWriter().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) 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;
+ 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;
+ }
+ }
+
+ bool IsPCRel = Backend.getFixupKindInfo(
+ Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel;
+
+ bool IsResolved;
+ 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 {
+ IsResolved = getWriter().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 = Backend.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 && Backend.shouldForceRelocation(*this, Fixup, Target))
+ IsResolved = false;
+
+ return IsResolved;
+}
+
+uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
+ const MCFragment &F) const {
+ 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:
+ return cast<MCFillFragment>(F).getSize();
+
+ case MCFragment::FT_LEB:
+ return cast<MCLEBFragment>(F).getContents().size();
+
+ case MCFragment::FT_SafeSEH:
+ return 4;
+
+ case MCFragment::FT_Align: {
+ const MCAlignFragment &AF = cast<MCAlignFragment>(F);
+ unsigned Offset = Layout.getFragmentOffset(&AF);
+ unsigned Size = OffsetToAlignment(Offset, AF.getAlignment());
+ // 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");
+ uint64_t FSize = Assembler.computeFragmentSize(*this, *F);
+
+ if (!Assembler.getRelaxAll() && FSize > Assembler.getBundleAlignSize())
+ report_fatal_error("Fragment can't be larger than a bundle size");
+
+ uint64_t RequiredBundlePadding = computeBundlePadding(Assembler, F,
+ F->Offset, FSize);
+ if (RequiredBundlePadding > UINT8_MAX)
+ report_fatal_error("Padding cannot exceed 255 bytes");
+ F->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding));
+ F->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(const MCFragment &F, uint64_t FSize,
+ MCObjectWriter *OW) const {
+ // Should NOP padding be written out before this fragment?
+ unsigned BundlePadding = F.getBundlePadding();
+ if (BundlePadding > 0) {
+ assert(isBundlingEnabled() &&
+ "Writing bundle padding with disabled bundling");
+ assert(F.hasInstructions() &&
+ "Writing bundle padding for a fragment without instructions");
+
+ unsigned TotalLength = BundlePadding + static_cast<unsigned>(FSize);
+ if (F.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(DistanceToBoundary, OW))
+ report_fatal_error("unable to write NOP sequence of " +
+ Twine(DistanceToBoundary) + " bytes");
+ BundlePadding -= DistanceToBoundary;
+ }
+ if (!getBackend().writeNopData(BundlePadding, OW))
+ report_fatal_error("unable to write NOP sequence of " +
+ Twine(BundlePadding) + " bytes");
+ }
+}
+
+/// \brief Write the fragment \p F to the output file.
+static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
+ const MCFragment &F) {
+ MCObjectWriter *OW = &Asm.getWriter();
+
+ // FIXME: Embed in fragments instead?
+ uint64_t FragmentSize = Asm.computeFragmentSize(Layout, F);
+
+ Asm.writeFragmentPadding(F, FragmentSize, OW);
+
+ // This variable (and its dummy usage) is to participate in the assert at
+ // the end of the function.
+ uint64_t Start = OW->getStream().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(Count, OW))
+ 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: OW->write8 (uint8_t (AF.getValue())); break;
+ case 2: OW->write16(uint16_t(AF.getValue())); break;
+ case 4: OW->write32(uint32_t(AF.getValue())); break;
+ case 8: OW->write64(uint64_t(AF.getValue())); break;
+ }
+ }
+ break;
+ }
+
+ case MCFragment::FT_Data:
+ ++stats::EmittedDataFragments;
+ OW->writeBytes(cast<MCDataFragment>(F).getContents());
+ break;
+
+ case MCFragment::FT_Relaxable:
+ ++stats::EmittedRelaxableFragments;
+ OW->writeBytes(cast<MCRelaxableFragment>(F).getContents());
+ break;
+
+ case MCFragment::FT_CompactEncodedInst:
+ ++stats::EmittedCompactEncodedInstFragments;
+ OW->writeBytes(cast<MCCompactEncodedInstFragment>(F).getContents());
+ break;
+
+ case MCFragment::FT_Fill: {
+ ++stats::EmittedFillFragments;
+ const MCFillFragment &FF = cast<MCFillFragment>(F);
+ uint8_t V = FF.getValue();
+ const unsigned MaxChunkSize = 16;
+ char Data[MaxChunkSize];
+ memcpy(Data, &V, 1);
+ for (unsigned I = 1; I < MaxChunkSize; ++I)
+ Data[I] = Data[0];
+
+ uint64_t Size = FF.getSize();
+ for (unsigned ChunkSize = MaxChunkSize; ChunkSize; ChunkSize /= 2) {
+ StringRef Ref(Data, ChunkSize);
+ for (uint64_t I = 0, E = Size / ChunkSize; I != E; ++I)
+ OW->writeBytes(Ref);
+ Size = Size % ChunkSize;
+ }
+ break;
+ }
+
+ case MCFragment::FT_LEB: {
+ const MCLEBFragment &LF = cast<MCLEBFragment>(F);
+ OW->writeBytes(LF.getContents());
+ break;
+ }
+
+ case MCFragment::FT_SafeSEH: {
+ const MCSafeSEHFragment &SF = cast<MCSafeSEHFragment>(F);
+ OW->write32(SF.getSymbol()->getIndex());
+ break;
+ }
+
+ case MCFragment::FT_Org: {
+ ++stats::EmittedOrgFragments;
+ const MCOrgFragment &OF = cast<MCOrgFragment>(F);
+
+ for (uint64_t i = 0, e = FragmentSize; i != e; ++i)
+ OW->write8(uint8_t(OF.getValue()));
+
+ break;
+ }
+
+ case MCFragment::FT_Dwarf: {
+ const MCDwarfLineAddrFragment &OF = cast<MCDwarfLineAddrFragment>(F);
+ OW->writeBytes(OF.getContents());
+ break;
+ }
+ case MCFragment::FT_DwarfFrame: {
+ const MCDwarfCallFrameFragment &CF = cast<MCDwarfCallFrameFragment>(F);
+ OW->writeBytes(CF.getContents());
+ break;
+ }
+ case MCFragment::FT_CVInlineLines: {
+ const auto &OF = cast<MCCVInlineLineTableFragment>(F);
+ OW->writeBytes(OF.getContents());
+ break;
+ }
+ case MCFragment::FT_CVDefRange: {
+ const auto &DRF = cast<MCCVDefRangeFragment>(F);
+ OW->writeBytes(DRF.getContents());
+ break;
+ }
+ case MCFragment::FT_Dummy:
+ llvm_unreachable("Should not have been added");
+ }
+
+ assert(OW->getStream().tell() - Start == FragmentSize &&
+ "The stream should advance by fragment size");
+}
+
+void MCAssembler::writeSectionData(const MCSection *Sec,
+ const MCAsmLayout &Layout) const {
+ // 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 = getWriter().getStream().tell();
+ (void)Start;
+
+ for (const MCFragment &F : *Sec)
+ writeFragment(*this, Layout, F);
+
+ assert(getWriter().getStream().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 IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
+ MCFixupKindInfo::FKF_IsPCRel;
+ if (!evaluateFixup(Layout, Fixup, &F, Target, FixedValue)) {
+ // 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.
+ getWriter().recordRelocation(*this, Layout, &F, Fixup, Target, IsPCRel,
+ FixedValue);
+ }
+ return std::make_tuple(Target, FixedValue, IsPCRel);
+}
+
+void MCAssembler::layout(MCAsmLayout &Layout) {
+ 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))
+ continue;
+ ArrayRef<MCFixup> Fixups;
+ MutableArrayRef<char> Contents;
+ if (auto *FragWithFixups = dyn_cast<MCDataFragment>(&Frag)) {
+ Fixups = FragWithFixups->getFixups();
+ Contents = FragWithFixups->getContents();
+ } else if (auto *FragWithFixups = dyn_cast<MCRelaxableFragment>(&Frag)) {
+ Fixups = FragWithFixups->getFixups();
+ Contents = FragWithFixups->getContents();
+ } else if (auto *FragWithFixups = dyn_cast<MCCVDefRangeFragment>(&Frag)) {
+ Fixups = FragWithFixups->getFixups();
+ Contents = FragWithFixups->getContents();
+ } else
+ llvm_unreachable("Unknown fragment with fixups!");
+ for (const MCFixup &Fixup : Fixups) {
+ uint64_t FixedValue;
+ bool IsPCRel;
+ MCValue Target;
+ std::tie(Target, FixedValue, IsPCRel) =
+ handleFixup(Layout, Frag, Fixup);
+ getBackend().applyFixup(*this, Fixup, Target, Contents, FixedValue,
+ IsPCRel);
+ }
+ }
+ }
+}
+
+void MCAssembler::Finish() {
+ // Create the layout object.
+ MCAsmLayout Layout(*this);
+ layout(Layout);
+
+ raw_ostream &OS = getWriter().getStream();
+ uint64_t StartOffset = OS.tell();
+
+ // Write the object file.
+ getWriter().writeObject(*this, Layout);
+
+ stats::ObjectBytes += OS.tell() - StartOffset;
+}
+
+bool MCAssembler::fixupNeedsRelaxation(const MCFixup &Fixup,
+ const MCRelaxableFragment *DF,
+ const MCAsmLayout &Layout) const {
+ MCValue Target;
+ uint64_t Value;
+ bool Resolved = evaluateFixup(Layout, Fixup, DF, Target, Value);
+ 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);
+}
+
+bool MCAssembler::fragmentNeedsRelaxation(const MCRelaxableFragment *F,
+ const MCAsmLayout &Layout) const {
+ // 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()))
+ return false;
+
+ for (const MCFixup &Fixup : F->getFixups())
+ if (fixupNeedsRelaxation(Fixup, F, Layout))
+ return true;
+
+ return false;
+}
+
+bool MCAssembler::relaxInstruction(MCAsmLayout &Layout,
+ MCRelaxableFragment &F) {
+ 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::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);
+ if (LF.isSigned())
+ encodeSLEB128(Value, OSE);
+ else
+ encodeULEB128(Value, OSE);
+ 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();
+ SmallString<8> &Data = DF.getContents();
+ Data.clear();
+ raw_svector_ostream OSE(Data);
+ MCDwarfLineAddr::Encode(Context, getDWARFLinetableParams(), LineDelta,
+ AddrDelta, OSE);
+ 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;
+ SmallString<8> &Data = DF.getContents();
+ Data.clear();
+ raw_svector_ostream OSE(Data);
+ 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_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) {
+ // 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);
+}
diff --git a/contrib/llvm/lib/MC/MCCodeEmitter.cpp b/contrib/llvm/lib/MC/MCCodeEmitter.cpp
new file mode 100644
index 000000000000..ca69478ed10d
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCCodeEmitter.cpp
@@ -0,0 +1,16 @@
+//===- MCCodeEmitter.cpp - Instruction Encoding ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCCodeEmitter.h"
+
+using namespace llvm;
+
+MCCodeEmitter::MCCodeEmitter() = default;
+
+MCCodeEmitter::~MCCodeEmitter() = default;
diff --git a/contrib/llvm/lib/MC/MCCodeView.cpp b/contrib/llvm/lib/MC/MCCodeView.cpp
new file mode 100644
index 000000000000..92b1e12da552
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCCodeView.cpp
@@ -0,0 +1,572 @@
+//===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Holds state from .cv_file and .cv_loc directives for later emission.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCCodeView.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/BinaryFormat/COFF.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 < Filenames.size())
+ return !Filenames[Idx].empty();
+ return false;
+}
+
+bool CodeViewContext::addFile(unsigned FileNumber, StringRef Filename) {
+ assert(FileNumber > 0);
+ Filename = addToStringTable(Filename);
+ unsigned Idx = FileNumber - 1;
+ if (Idx >= Filenames.size())
+ Filenames.resize(Idx + 1);
+
+ if (Filename.empty())
+ Filename = "<stdin>";
+
+ if (!Filenames[Idx].empty())
+ return false;
+
+ // FIXME: We should store the string table offset of the filename, rather than
+ // the filename itself for efficiency.
+ Filename = addToStringTable(Filename);
+
+ Filenames[Idx] = Filename;
+ return true;
+}
+
+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;
+}
+
+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;
+}
+
+StringRef 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.
+ S = Insertion.first->first();
+ if (Insertion.second) {
+ // The string map key is always null terminated.
+ Contents.append(S.begin(), S.end() + 1);
+ }
+ return S;
+}
+
+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 (Filenames.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);
+
+ // Emit an array of FileChecksum entries. We index into this table using the
+ // user-provided file number. Each entry is currently 8 bytes, as we don't
+ // emit checksums.
+ for (StringRef Filename : Filenames) {
+ OS.EmitIntValue(getStringTableOffset(Filename), 4);
+ // Zero the next two fields and align back to 4 bytes. This indicates that
+ // no checksum is present.
+ OS.EmitIntValue(0, 4);
+ }
+
+ OS.EmitLabel(FileEnd);
+}
+
+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<MCCVLineEntry> Locs = getFunctionLineEntries(FuncId);
+ bool HaveColumns = any_of(Locs, [](const MCCVLineEntry &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 MCCVLineEntry &Loc) {
+ return Loc.getFileNum() != CurFileNum;
+ });
+ unsigned EntryCount = FileSegEnd - I;
+ OS.AddComment("Segment for file '" + Twine(Filenames[CurFileNum - 1]) +
+ "' begins");
+ OS.EmitIntValue(8 * (CurFileNum - 1), 4);
+ 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());
+}
+
+void 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.
+ 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<MCCVLineEntry> Locs = getLinesForExtent(LocBegin, LocEnd);
+ if (Locs.empty())
+ return;
+
+ // Make an artificial start location using the function start and the inlinee
+ // lines start location information. All deltas start relative to this
+ // location.
+ MCCVLineEntry StartLoc(Frag.getFnStartSym(), MCCVLoc(Locs.front()));
+ 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 MCCVLineEntry &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) {
+ // File ids are 1 based, and each file checksum table entry is 8 bytes
+ // long. See emitFileChecksums above.
+ unsigned FileOffset = 8 * (CurSourceLoc.File - 1);
+ 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<MCCVLineEntry> LocAfter = getLinesForExtent(LocEnd, LocEnd + 1);
+ if (!LocAfter.empty()) {
+ // Only try to compute this difference if we're in the same section.
+ const MCCVLineEntry &Loc = LocAfter[0];
+ if (&Loc.getLabel()->getSection(false) == &LastLabel->getSection(false))
+ 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<support::little> LEWriter(OS);
+
+ 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;
+ }
+ }
+}
+
+//
+// This is called when an instruction is assembled into the specified section
+// and if there is information from the last .cv_loc directive that has yet to have
+// a line entry made for it is made.
+//
+void MCCVLineEntry::Make(MCObjectStreamer *MCOS) {
+ CodeViewContext &CVC = MCOS->getContext().getCVContext();
+ if (!CVC.getCVLocSeen())
+ 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 MCCVLineEntry.
+ MCOS->EmitLabel(LineSym);
+
+ // Get the current .loc info saved in the context.
+ const MCCVLoc &CVLoc = CVC.getCurrentCVLoc();
+
+ // Create a (local) line entry with the symbol and the current .loc info.
+ MCCVLineEntry LineEntry(LineSym, CVLoc);
+
+ // clear CVLocSeen saying the current .loc info is now used.
+ CVC.clearCVLocSeen();
+
+ // Add the line entry to this section's entries.
+ CVC.addLineEntry(LineEntry);
+}
diff --git a/contrib/llvm/lib/MC/MCContext.cpp b/contrib/llvm/lib/MC/MCContext.cpp
new file mode 100644
index 000000000000..48ee84edb096
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCContext.cpp
@@ -0,0 +1,630 @@
+//===- lib/MC/MCContext.cpp - Machine Code Context ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCContext.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/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/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/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),
+ 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();
+
+ MCSubtargetAllocator.DestroyAll();
+ 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();
+
+ 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);
+ }
+ }
+ 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));
+}
+
+//===----------------------------------------------------------------------===//
+// 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::getCOFFSection(StringRef Section) {
+ COFFSectionKey T{Section, "", 0, GenericSectionID};
+ auto Iter = COFFUniquingMap.find(T);
+ if (Iter == COFFUniquingMap.end())
+ return nullptr;
+ return Iter->second;
+}
+
+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);
+}
+
+void MCContext::renameWasmSection(MCSectionWasm *Section, StringRef Name) {
+ StringRef GroupName;
+ assert(!Section->getGroup() && "not yet implemented");
+
+ unsigned UniqueID = Section->getUniqueID();
+ WasmUniquingMap.erase(
+ WasmSectionKey{Section->getSectionName(), GroupName, UniqueID});
+ auto I = WasmUniquingMap.insert(std::make_pair(
+ WasmSectionKey{Name, GroupName, UniqueID},
+ Section))
+ .first;
+ StringRef CachedName = I->first.SectionName;
+ const_cast<MCSectionWasm *>(Section)->setSectionName(CachedName);
+}
+
+MCSectionWasm *MCContext::createWasmRelSection(const Twine &Name, unsigned Type,
+ unsigned Flags,
+ const MCSymbolWasm *Group) {
+ StringMap<bool>::iterator I;
+ bool Inserted;
+ std::tie(I, Inserted) =
+ RelSecNames.insert(std::make_pair(Name.str(), true));
+
+ return new (WasmAllocator.Allocate())
+ MCSectionWasm(I->getKey(), Type, Flags, SectionKind::getReadOnly(),
+ Group, ~0, nullptr);
+}
+
+MCSectionWasm *MCContext::getWasmNamedSection(const Twine &Prefix,
+ const Twine &Suffix, unsigned Type,
+ unsigned Flags) {
+ return getWasmSection(Prefix + "." + Suffix, Type, Flags, Suffix);
+}
+
+MCSectionWasm *MCContext::getWasmSection(const Twine &Section, unsigned Type,
+ unsigned Flags,
+ const Twine &Group, unsigned UniqueID,
+ const char *BeginSymName) {
+ MCSymbolWasm *GroupSym = nullptr;
+ if (!Group.isTriviallyEmpty() && !Group.str().empty())
+ GroupSym = cast<MCSymbolWasm>(getOrCreateSymbol(Group));
+
+ return getWasmSection(Section, Type, Flags, GroupSym, UniqueID, BeginSymName);
+}
+
+MCSectionWasm *MCContext::getWasmSection(const Twine &Section, unsigned Type,
+ unsigned Flags,
+ 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;
+
+ SectionKind Kind = SectionKind::getText();
+
+ MCSymbol *Begin = nullptr;
+ if (BeginSymName)
+ Begin = createTempSymbol(BeginSymName, false);
+
+ MCSectionWasm *Result = new (WasmAllocator.Allocate())
+ MCSectionWasm(CachedName, Type, Flags, Kind, GroupSym, UniqueID, Begin);
+ Entry.second = Result;
+ return Result;
+}
+
+MCSubtargetInfo &MCContext::getSubtargetCopy(const MCSubtargetInfo &STI) {
+ return *new (MCSubtargetAllocator.Allocate()) MCSubtargetInfo(STI);
+}
+
+//===----------------------------------------------------------------------===//
+// Dwarf Management
+//===----------------------------------------------------------------------===//
+
+/// getDwarfFile - takes a file name an 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.
+unsigned MCContext::getDwarfFile(StringRef Directory, StringRef FileName,
+ unsigned FileNumber, unsigned CUID) {
+ MCDwarfLineTable &Table = MCDwarfLineTablesCUMap[CUID];
+ return Table.getFile(Directory, FileName, 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 SmallVectorImpl<MCDwarfFile> &MCDwarfFiles = getMCDwarfFiles(CUID);
+ if (FileNumber == 0 || FileNumber >= MCDwarfFiles.size())
+ return false;
+
+ return !MCDwarfFiles[FileNumber].Name.empty();
+}
+
+/// Remove empty sections from SectionStartEndSyms, 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
new file mode 100644
index 000000000000..ef1d8335e1bd
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp
@@ -0,0 +1,342 @@
+//===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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;
+
+ const MCRegisterInfo *MRI = TheTarget->createMCRegInfo(TT);
+ if (!MRI)
+ return nullptr;
+
+ // Get the assembler info needed to setup the MCContext.
+ const MCAsmInfo *MAI = TheTarget->createMCAsmInfo(*MRI, TT);
+ if (!MAI)
+ return nullptr;
+
+ const MCInstrInfo *MII = TheTarget->createMCInstrInfo();
+ if (!MII)
+ return nullptr;
+
+ const MCSubtargetInfo *STI =
+ TheTarget->createMCSubtargetInfo(TT, CPU, Features);
+ if (!STI)
+ return nullptr;
+
+ // Set up the MCContext for creating symbols and MCExpr's.
+ MCContext *Ctx = new MCContext(MAI, MRI, nullptr);
+ if (!Ctx)
+ return nullptr;
+
+ // Set up disassembler.
+ 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, std::move(RelInfo)));
+ DisAsm->setSymbolizer(std::move(Symbolizer));
+
+ // Set up the instruction printer.
+ int AsmPrinterVariant = MAI->getAssemblerDialect();
+ MCInstPrinter *IP = TheTarget->createMCInstPrinter(
+ Triple(TT), AsmPrinterVariant, *MAI, *MII, *MRI);
+ if (!IP)
+ return nullptr;
+
+ LLVMDisasmContext *DC =
+ new LLVMDisasmContext(TT, DisInfo, TagType, GetOpInfo, SymbolLookUp,
+ TheTarget, MAI, MRI, STI, MII, Ctx, DisAsm, 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;
+}
+
+/// \brief 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();
+}
+
+/// \brief 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;
+}
+
+/// \brief 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.
+ 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);
+ Latency = std::max(Latency, WLEntry->Cycles);
+ }
+
+ return Latency;
+}
+
+/// \brief 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
new file mode 100644
index 000000000000..25d17dafb576
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h
@@ -0,0 +1,127 @@
+//===------------- Disassembler.h - LLVM Disassembler -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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, const MCAsmInfo *mAI,
+ const MCRegisterInfo *mRI, const MCSubtargetInfo *mSI,
+ const MCInstrInfo *mII, llvm::MCContext *ctx,
+ const MCDisassembler *disAsm, MCInstPrinter *iP)
+ : TripleName(std::move(tripleName)), DisInfo(disInfo), TagType(tagType),
+ GetOpInfo(getOpInfo), SymbolLookUp(symbolLookUp), TheTarget(theTarget),
+ Options(0), CommentStream(CommentsToEmit) {
+ MAI.reset(mAI);
+ MRI.reset(mRI);
+ MSI.reset(mSI);
+ MII.reset(mII);
+ Ctx.reset(ctx);
+ DisAsm.reset(disAsm);
+ IP.reset(iP);
+ }
+ 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
new file mode 100644
index 000000000000..2f1275d00b86
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp
@@ -0,0 +1,38 @@
+//===- MCDisassembler.cpp - Disassembler interface ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCDisassembler/MCDisassembler.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+
+using namespace llvm;
+
+MCDisassembler::~MCDisassembler() = default;
+
+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
new file mode 100644
index 000000000000..1969c5dc66ab
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp
@@ -0,0 +1,200 @@
+//===-- MCExternalSymbolizer.cpp - External symbolizer --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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
new file mode 100644
index 000000000000..8f932a3f0d48
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp
@@ -0,0 +1,31 @@
+//===-- MCRelocationInfo.cpp ----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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
new file mode 100644
index 000000000000..78e611e3ddda
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCDisassembler/MCSymbolizer.cpp
@@ -0,0 +1,14 @@
+//===-- llvm/MC/MCSymbolizer.cpp - MCSymbolizer class ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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
new file mode 100644
index 000000000000..a2beee32f2cb
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCDwarf.cpp
@@ -0,0 +1,1610 @@
+//===- lib/MC/MCDwarf.cpp - MCDwarf implementation ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCDwarf.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/None.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/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;
+
+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 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;
+
+ // 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);
+}
+
+void MCDwarfDwoLineTable::Emit(MCStreamer &MCOS,
+ MCDwarfLineTableParams Params) const {
+ MCOS.EmitLabel(Header.Emit(&MCOS, Params, None).second);
+}
+
+std::pair<MCSymbol *, MCSymbol *>
+MCDwarfLineTableHeader::Emit(MCStreamer *MCOS,
+ MCDwarfLineTableParams Params) 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));
+}
+
+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);
+}
+
+std::pair<MCSymbol *, MCSymbol *>
+MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
+ ArrayRef<char> StandardOpcodeLengths) 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, which is Dwarf 2.
+ MCOS->EmitIntValue(2, 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. Which is the start of the
+ // section to the end of the prologue. Not including the 4 bytes for the
+ // total length, the 2 bytes for the version, and these 4 bytes for the
+ // length of the prologue.
+ emitAbsValue(
+ *MCOS,
+ MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym, (4 + 2 + 4)), 4);
+
+ // Parameters of the state machine, are next.
+ MCOS->EmitIntValue(context.getAsmInfo()->getMinInstAlignment(), 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.
+
+ // First the directory table.
+ for (unsigned i = 0; i < MCDwarfDirs.size(); i++) {
+ MCOS->EmitBytes(MCDwarfDirs[i]); // the DirectoryName
+ MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string
+ }
+ 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
+ MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string
+ // the Directory num
+ MCOS->EmitULEB128IntValue(MCDwarfFiles[i].DirIndex);
+ MCOS->EmitIntValue(0, 1); // last modification timestamp (always 0)
+ MCOS->EmitIntValue(0, 1); // filesize (always 0)
+ }
+ MCOS->EmitIntValue(0, 1); // Terminate the file list
+
+ // 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) const {
+ MCSymbol *LineEndSym = Header.Emit(MCOS, Params).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);
+}
+
+unsigned MCDwarfLineTable::getFile(StringRef &Directory, StringRef &FileName,
+ unsigned FileNumber) {
+ return Header.getFile(Directory, FileName, FileNumber);
+}
+
+unsigned MCDwarfLineTableHeader::getFile(StringRef &Directory,
+ StringRef &FileName,
+ unsigned FileNumber) {
+ if (Directory == CompilationDir)
+ Directory = "";
+ if (FileName.empty()) {
+ FileName = "<stdin>";
+ Directory = "";
+ }
+ assert(!FileName.empty());
+ 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.
+ MCDwarfFiles.resize(FileNumber + 1);
+
+ // Get the new MCDwarfFile slot for this FileNumber.
+ MCDwarfFile &File = MCDwarfFiles[FileNumber];
+
+ // It is an error to use see the same number more than once.
+ if (!File.Name.empty())
+ return 0;
+
+ if (Directory.empty()) {
+ // Separate the directory part from the basename of the FileName.
+ StringRef tFileName = sys::path::filename(FileName);
+ if (!tFileName.empty()) {
+ Directory = sys::path::parent_path(FileName);
+ if (!Directory.empty())
+ FileName = tFileName;
+ }
+ }
+
+ // Find or make an entry in the MCDwarfDirs vector for this Directory.
+ // Capture directory name.
+ unsigned DirIndex;
+ if (Directory.empty()) {
+ // For FileNames with no directories a DirIndex of 0 is used.
+ DirIndex = 0;
+ } else {
+ DirIndex = 0;
+ for (unsigned End = MCDwarfDirs.size(); DirIndex < End; DirIndex++) {
+ if (Directory == MCDwarfDirs[DirIndex])
+ break;
+ }
+ if (DirIndex >= MCDwarfDirs.size())
+ MCDwarfDirs.push_back(Directory);
+ // The DirIndex is one based, as DirIndex of 0 is used for FileNames with
+ // no directories. MCDwarfDirs[] is unlike MCDwarfFiles[] in that the
+ // directory names are stored at MCDwarfDirs[DirIndex-1] where FileNames
+ // are stored at MCDwarfFiles[FileNumber].Name .
+ DirIndex++;
+ }
+
+ File.Name = FileName;
+ File.DirIndex = DirIndex;
+
+ // 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);
+ }
+}
+
+// Utility function to write a tuple for .debug_abbrev.
+static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) {
+ MCOS->EmitULEB128IntValue(Name);
+ MCOS->EmitULEB128IntValue(Form);
+}
+
+// When generating dwarf for assembly source files this emits
+// the data for .debug_abbrev section which contains three DIEs.
+static void EmitGenDwarfAbbrev(MCStreamer *MCOS) {
+ MCContext &context = MCOS->getContext();
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
+
+ // DW_TAG_compile_unit DIE abbrev (1).
+ MCOS->EmitULEB128IntValue(1);
+ MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit);
+ MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1);
+ EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, context.getDwarfVersion() >= 4
+ ? dwarf::DW_FORM_sec_offset
+ : dwarf::DW_FORM_data4);
+ if (context.getGenDwarfSectionSyms().size() > 1 &&
+ context.getDwarfVersion() >= 3) {
+ EmitAbbrev(MCOS, dwarf::DW_AT_ranges, context.getDwarfVersion() >= 4
+ ? dwarf::DW_FORM_sec_offset
+ : dwarf::DW_FORM_data4);
+ } else {
+ EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
+ EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr);
+ }
+ EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
+ if (!context.getCompilationDir().empty())
+ EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string);
+ StringRef DwarfDebugFlags = context.getDwarfDebugFlags();
+ if (!DwarfDebugFlags.empty())
+ EmitAbbrev(MCOS, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string);
+ EmitAbbrev(MCOS, dwarf::DW_AT_producer, dwarf::DW_FORM_string);
+ EmitAbbrev(MCOS, dwarf::DW_AT_language, dwarf::DW_FORM_data2);
+ EmitAbbrev(MCOS, 0, 0);
+
+ // DW_TAG_label DIE abbrev (2).
+ MCOS->EmitULEB128IntValue(2);
+ MCOS->EmitULEB128IntValue(dwarf::DW_TAG_label);
+ MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1);
+ EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
+ EmitAbbrev(MCOS, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data4);
+ EmitAbbrev(MCOS, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data4);
+ EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
+ EmitAbbrev(MCOS, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag);
+ EmitAbbrev(MCOS, 0, 0);
+
+ // DW_TAG_unspecified_parameters DIE abbrev (3).
+ MCOS->EmitULEB128IntValue(3);
+ MCOS->EmitULEB128IntValue(dwarf::DW_TAG_unspecified_parameters);
+ MCOS->EmitIntValue(dwarf::DW_CHILDREN_no, 1);
+ EmitAbbrev(MCOS, 0, 0);
+
+ // Terminate the abbreviations for this compilation unit.
+ MCOS->EmitIntValue(0, 1);
+}
+
+// When generating dwarf for assembly source files this emits the data for
+// .debug_aranges section. This section contains a header and a table of pairs
+// of PointerSize'ed values for the address and size of section(s) with line
+// table entries.
+static void EmitGenDwarfAranges(MCStreamer *MCOS,
+ const MCSymbol *InfoSectionSymbol) {
+ MCContext &context = MCOS->getContext();
+
+ auto &Sections = context.getGenDwarfSectionSyms();
+
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
+
+ // This will be the length of the .debug_aranges section, first account for
+ // the size of each item in the header (see below where we emit these items).
+ int Length = 4 + 2 + 4 + 1 + 1;
+
+ // Figure the padding after the header before the table of address and size
+ // pairs who's values are PointerSize'ed.
+ const MCAsmInfo *asmInfo = context.getAsmInfo();
+ int AddrSize = asmInfo->getCodePointerSize();
+ int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1));
+ if (Pad == 2 * AddrSize)
+ Pad = 0;
+ Length += Pad;
+
+ // Add the size of the pair of PointerSize'ed values for the address and size
+ // of each section we have in the table.
+ Length += 2 * AddrSize * Sections.size();
+ // And the pair of terminating zeros.
+ Length += 2 * AddrSize;
+
+ // Emit the header for this section.
+ // The 4 byte length not including the 4 byte value for the length.
+ MCOS->EmitIntValue(Length - 4, 4);
+ // The 2 byte version, which is 2.
+ MCOS->EmitIntValue(2, 2);
+ // The 4 byte offset to the compile unit in the .debug_info from the start
+ // of the .debug_info.
+ if (InfoSectionSymbol)
+ MCOS->EmitSymbolValue(InfoSectionSymbol, 4,
+ asmInfo->needsDwarfSectionOffsetDirective());
+ else
+ MCOS->EmitIntValue(0, 4);
+ // The 1 byte size of an address.
+ MCOS->EmitIntValue(AddrSize, 1);
+ // The 1 byte size of a segment descriptor, we use a value of zero.
+ MCOS->EmitIntValue(0, 1);
+ // Align the header with the padding if needed, before we put out the table.
+ for(int i = 0; i < Pad; i++)
+ MCOS->EmitIntValue(0, 1);
+
+ // Now emit the table of pairs of PointerSize'ed values for the section
+ // addresses and sizes.
+ for (MCSection *Sec : Sections) {
+ const MCSymbol *StartSymbol = Sec->getBeginSymbol();
+ MCSymbol *EndSymbol = Sec->getEndSymbol(context);
+ assert(StartSymbol && "StartSymbol must not be NULL");
+ assert(EndSymbol && "EndSymbol must not be NULL");
+
+ const MCExpr *Addr = MCSymbolRefExpr::create(
+ StartSymbol, MCSymbolRefExpr::VK_None, context);
+ const MCExpr *Size = MakeStartMinusEndExpr(*MCOS,
+ *StartSymbol, *EndSymbol, 0);
+ MCOS->EmitValue(Addr, AddrSize);
+ emitAbsValue(*MCOS, Size, AddrSize);
+ }
+
+ // And finally the pair of terminating zeros.
+ MCOS->EmitIntValue(0, AddrSize);
+ MCOS->EmitIntValue(0, AddrSize);
+}
+
+// When generating dwarf for assembly source files this emits the data for
+// .debug_info section which contains three parts. The header, the compile_unit
+// DIE and a list of label DIEs.
+static void EmitGenDwarfInfo(MCStreamer *MCOS,
+ const MCSymbol *AbbrevSectionSymbol,
+ const MCSymbol *LineSectionSymbol,
+ const MCSymbol *RangesSectionSymbol) {
+ MCContext &context = MCOS->getContext();
+
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
+
+ // Create a symbol at the start and end of this section used in here for the
+ // expression to calculate the length in the header.
+ MCSymbol *InfoStart = context.createTempSymbol();
+ MCOS->EmitLabel(InfoStart);
+ MCSymbol *InfoEnd = context.createTempSymbol();
+
+ // First part: the header.
+
+ // The 4 byte total length of the information for this compilation unit, not
+ // including these 4 bytes.
+ const MCExpr *Length = MakeStartMinusEndExpr(*MCOS, *InfoStart, *InfoEnd, 4);
+ emitAbsValue(*MCOS, Length, 4);
+
+ // The 2 byte DWARF version.
+ MCOS->EmitIntValue(context.getDwarfVersion(), 2);
+
+ // The DWARF v5 header has unit type, address size, abbrev offset.
+ // Earlier versions have abbrev offset, address size.
+ const MCAsmInfo &AsmInfo = *context.getAsmInfo();
+ int AddrSize = AsmInfo.getCodePointerSize();
+ if (context.getDwarfVersion() >= 5) {
+ MCOS->EmitIntValue(dwarf::DW_UT_compile, 1);
+ MCOS->EmitIntValue(AddrSize, 1);
+ }
+ // The 4 byte offset to the debug abbrevs from the start of the .debug_abbrev,
+ // it is at the start of that section so this is zero.
+ if (AbbrevSectionSymbol == nullptr)
+ MCOS->EmitIntValue(0, 4);
+ else
+ MCOS->EmitSymbolValue(AbbrevSectionSymbol, 4,
+ AsmInfo.needsDwarfSectionOffsetDirective());
+ if (context.getDwarfVersion() <= 4)
+ MCOS->EmitIntValue(AddrSize, 1);
+
+ // Second part: the compile_unit DIE.
+
+ // The DW_TAG_compile_unit DIE abbrev (1).
+ MCOS->EmitULEB128IntValue(1);
+
+ // DW_AT_stmt_list, a 4 byte offset from the start of the .debug_line section,
+ // which is at the start of that section so this is zero.
+ if (LineSectionSymbol)
+ MCOS->EmitSymbolValue(LineSectionSymbol, 4,
+ AsmInfo.needsDwarfSectionOffsetDirective());
+ else
+ MCOS->EmitIntValue(0, 4);
+
+ if (RangesSectionSymbol) {
+ // There are multiple sections containing code, so we must use the
+ // .debug_ranges sections.
+
+ // AT_ranges, the 4 byte offset from the start of the .debug_ranges section
+ // to the address range list for this compilation unit.
+ MCOS->EmitSymbolValue(RangesSectionSymbol, 4);
+ } else {
+ // If we only have one non-empty code section, we can use the simpler
+ // AT_low_pc and AT_high_pc attributes.
+
+ // Find the first (and only) non-empty text section
+ auto &Sections = context.getGenDwarfSectionSyms();
+ const auto TextSection = Sections.begin();
+ assert(TextSection != Sections.end() && "No text section found");
+
+ MCSymbol *StartSymbol = (*TextSection)->getBeginSymbol();
+ MCSymbol *EndSymbol = (*TextSection)->getEndSymbol(context);
+ assert(StartSymbol && "StartSymbol must not be NULL");
+ assert(EndSymbol && "EndSymbol must not be NULL");
+
+ // AT_low_pc, the first address of the default .text section.
+ const MCExpr *Start = MCSymbolRefExpr::create(
+ StartSymbol, MCSymbolRefExpr::VK_None, context);
+ MCOS->EmitValue(Start, AddrSize);
+
+ // AT_high_pc, the last address of the default .text section.
+ const MCExpr *End = MCSymbolRefExpr::create(
+ EndSymbol, MCSymbolRefExpr::VK_None, context);
+ MCOS->EmitValue(End, AddrSize);
+ }
+
+ // AT_name, the name of the source file. Reconstruct from the first directory
+ // and file table entries.
+ const SmallVectorImpl<std::string> &MCDwarfDirs = context.getMCDwarfDirs();
+ if (MCDwarfDirs.size() > 0) {
+ MCOS->EmitBytes(MCDwarfDirs[0]);
+ MCOS->EmitBytes(sys::path::get_separator());
+ }
+ const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles =
+ MCOS->getContext().getMCDwarfFiles();
+ MCOS->EmitBytes(MCDwarfFiles[1].Name);
+ MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
+
+ // AT_comp_dir, the working directory the assembly was done in.
+ if (!context.getCompilationDir().empty()) {
+ MCOS->EmitBytes(context.getCompilationDir());
+ MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
+ }
+
+ // AT_APPLE_flags, the command line arguments of the assembler tool.
+ StringRef DwarfDebugFlags = context.getDwarfDebugFlags();
+ if (!DwarfDebugFlags.empty()){
+ MCOS->EmitBytes(DwarfDebugFlags);
+ MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
+ }
+
+ // AT_producer, the version of the assembler tool.
+ StringRef DwarfDebugProducer = context.getDwarfDebugProducer();
+ if (!DwarfDebugProducer.empty())
+ MCOS->EmitBytes(DwarfDebugProducer);
+ else
+ MCOS->EmitBytes(StringRef("llvm-mc (based on LLVM " PACKAGE_VERSION ")"));
+ MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
+
+ // AT_language, a 4 byte value. We use DW_LANG_Mips_Assembler as the dwarf2
+ // draft has no standard code for assembler.
+ MCOS->EmitIntValue(dwarf::DW_LANG_Mips_Assembler, 2);
+
+ // Third part: the list of label DIEs.
+
+ // Loop on saved info for dwarf labels and create the DIEs for them.
+ const std::vector<MCGenDwarfLabelEntry> &Entries =
+ MCOS->getContext().getMCGenDwarfLabelEntries();
+ for (const auto &Entry : Entries) {
+ // The DW_TAG_label DIE abbrev (2).
+ MCOS->EmitULEB128IntValue(2);
+
+ // AT_name, of the label without any leading underbar.
+ MCOS->EmitBytes(Entry.getName());
+ MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
+
+ // AT_decl_file, index into the file table.
+ MCOS->EmitIntValue(Entry.getFileNumber(), 4);
+
+ // AT_decl_line, source line number.
+ MCOS->EmitIntValue(Entry.getLineNumber(), 4);
+
+ // AT_low_pc, start address of the label.
+ const MCExpr *AT_low_pc = MCSymbolRefExpr::create(Entry.getLabel(),
+ MCSymbolRefExpr::VK_None, context);
+ MCOS->EmitValue(AT_low_pc, AddrSize);
+
+ // DW_AT_prototyped, a one byte flag value of 0 saying we have no prototype.
+ MCOS->EmitIntValue(0, 1);
+
+ // The DW_TAG_unspecified_parameters DIE abbrev (3).
+ MCOS->EmitULEB128IntValue(3);
+
+ // Add the NULL DIE terminating the DW_TAG_unspecified_parameters DIE's.
+ MCOS->EmitIntValue(0, 1);
+ }
+
+ // Add the NULL DIE terminating the Compile Unit DIE's.
+ MCOS->EmitIntValue(0, 1);
+
+ // Now set the value of the symbol at the end of the info section.
+ MCOS->EmitLabel(InfoEnd);
+}
+
+// When generating dwarf for assembly source files this emits the data for
+// .debug_ranges section. We only emit one range list, which spans all of the
+// executable sections of this file.
+static void EmitGenDwarfRanges(MCStreamer *MCOS) {
+ MCContext &context = MCOS->getContext();
+ auto &Sections = context.getGenDwarfSectionSyms();
+
+ const MCAsmInfo *AsmInfo = context.getAsmInfo();
+ int AddrSize = AsmInfo->getCodePointerSize();
+
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection());
+
+ for (MCSection *Sec : Sections) {
+ const MCSymbol *StartSymbol = Sec->getBeginSymbol();
+ MCSymbol *EndSymbol = Sec->getEndSymbol(context);
+ assert(StartSymbol && "StartSymbol must not be NULL");
+ assert(EndSymbol && "EndSymbol must not be NULL");
+
+ // Emit a base address selection entry for the start of this section
+ const MCExpr *SectionStartAddr = MCSymbolRefExpr::create(
+ StartSymbol, MCSymbolRefExpr::VK_None, context);
+ MCOS->emitFill(AddrSize, 0xFF);
+ MCOS->EmitValue(SectionStartAddr, AddrSize);
+
+ // Emit a range list entry spanning this section
+ const MCExpr *SectionSize = MakeStartMinusEndExpr(*MCOS,
+ *StartSymbol, *EndSymbol, 0);
+ MCOS->EmitIntValue(0, AddrSize);
+ emitAbsValue(*MCOS, SectionSize, AddrSize);
+ }
+
+ // Emit end of list entry
+ MCOS->EmitIntValue(0, AddrSize);
+ MCOS->EmitIntValue(0, AddrSize);
+}
+
+//
+// When generating dwarf for assembly source files this emits the Dwarf
+// sections.
+//
+void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
+ MCContext &context = MCOS->getContext();
+
+ // Create the dwarf sections in this order (.debug_line already created).
+ const MCAsmInfo *AsmInfo = context.getAsmInfo();
+ bool CreateDwarfSectionSymbols =
+ AsmInfo->doesDwarfUseRelocationsAcrossSections();
+ MCSymbol *LineSectionSymbol = nullptr;
+ if (CreateDwarfSectionSymbols)
+ LineSectionSymbol = MCOS->getDwarfLineTableSymbol(0);
+ MCSymbol *AbbrevSectionSymbol = nullptr;
+ MCSymbol *InfoSectionSymbol = nullptr;
+ MCSymbol *RangesSectionSymbol = nullptr;
+
+ // Create end symbols for each section, and remove empty sections
+ MCOS->getContext().finalizeDwarfSections(*MCOS);
+
+ // If there are no sections to generate debug info for, we don't need
+ // to do anything
+ if (MCOS->getContext().getGenDwarfSectionSyms().empty())
+ return;
+
+ // We only use the .debug_ranges section if we have multiple code sections,
+ // and we are emitting a DWARF version which supports it.
+ const bool UseRangesSection =
+ MCOS->getContext().getGenDwarfSectionSyms().size() > 1 &&
+ MCOS->getContext().getDwarfVersion() >= 3;
+ CreateDwarfSectionSymbols |= UseRangesSection;
+
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
+ if (CreateDwarfSectionSymbols) {
+ InfoSectionSymbol = context.createTempSymbol();
+ MCOS->EmitLabel(InfoSectionSymbol);
+ }
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
+ if (CreateDwarfSectionSymbols) {
+ AbbrevSectionSymbol = context.createTempSymbol();
+ MCOS->EmitLabel(AbbrevSectionSymbol);
+ }
+ if (UseRangesSection) {
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection());
+ if (CreateDwarfSectionSymbols) {
+ RangesSectionSymbol = context.createTempSymbol();
+ MCOS->EmitLabel(RangesSectionSymbol);
+ }
+ }
+
+ assert((RangesSectionSymbol != nullptr) || !UseRangesSection);
+
+ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
+
+ // Output the data for .debug_aranges section.
+ EmitGenDwarfAranges(MCOS, InfoSectionSymbol);
+
+ if (UseRangesSection)
+ EmitGenDwarfRanges(MCOS);
+
+ // Output the data for .debug_abbrev section.
+ EmitGenDwarfAbbrev(MCOS);
+
+ // Output the data for .debug_info section.
+ EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol,
+ RangesSectionSymbol);
+}
+
+//
+// When generating dwarf for assembly source files this is called when symbol
+// for a label is created. If this symbol is not a temporary and is in the
+// section that dwarf is being generated for, save the needed info to create
+// a dwarf label.
+//
+void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS,
+ SourceMgr &SrcMgr, SMLoc &Loc) {
+ // We won't create dwarf labels for temporary symbols.
+ if (Symbol->isTemporary())
+ return;
+ MCContext &context = MCOS->getContext();
+ // We won't create dwarf labels for symbols in sections that we are not
+ // generating debug info for.
+ if (!context.getGenDwarfSectionSyms().count(MCOS->getCurrentSectionOnly()))
+ return;
+
+ // The dwarf label's name does not have the symbol name's leading
+ // underbar if any.
+ StringRef Name = Symbol->getName();
+ if (Name.startswith("_"))
+ Name = Name.substr(1, Name.size()-1);
+
+ // Get the dwarf file number to be used for the dwarf label.
+ unsigned FileNumber = context.getGenDwarfFileNumber();
+
+ // Finding the line number is the expensive part which is why we just don't
+ // pass it in as for some symbols we won't create a dwarf label.
+ unsigned CurBuffer = SrcMgr.FindBufferContainingLoc(Loc);
+ unsigned LineNumber = SrcMgr.FindLineNumber(Loc, CurBuffer);
+
+ // We create a temporary symbol for use for the AT_high_pc and AT_low_pc
+ // values so that they don't have things like an ARM thumb bit from the
+ // original symbol. So when used they won't get a low bit set after
+ // relocation.
+ MCSymbol *Label = context.createTempSymbol();
+ MCOS->EmitLabel(Label);
+
+ // Create and entry for the info and add it to the other entries.
+ MCOS->getContext().addMCGenDwarfLabelEntry(
+ MCGenDwarfLabelEntry(Name, FileNumber, LineNumber, Label));
+}
+
+static int getDataAlignmentFactor(MCStreamer &streamer) {
+ MCContext &context = streamer.getContext();
+ const MCAsmInfo *asmInfo = context.getAsmInfo();
+ int size = asmInfo->getCalleeSaveStackSlotSize();
+ if (asmInfo->isStackGrowthDirectionUp())
+ return size;
+ else
+ return -size;
+}
+
+static unsigned getSizeForEncoding(MCStreamer &streamer,
+ unsigned symbolEncoding) {
+ MCContext &context = streamer.getContext();
+ unsigned format = symbolEncoding & 0x0f;
+ switch (format) {
+ default: llvm_unreachable("Unknown Encoding");
+ case dwarf::DW_EH_PE_absptr:
+ case dwarf::DW_EH_PE_signed:
+ return context.getAsmInfo()->getCodePointerSize();
+ case dwarf::DW_EH_PE_udata2:
+ case dwarf::DW_EH_PE_sdata2:
+ return 2;
+ case dwarf::DW_EH_PE_udata4:
+ case dwarf::DW_EH_PE_sdata4:
+ return 4;
+ case dwarf::DW_EH_PE_udata8:
+ case dwarf::DW_EH_PE_sdata8:
+ return 8;
+ }
+}
+
+static void emitFDESymbol(MCObjectStreamer &streamer, const MCSymbol &symbol,
+ unsigned symbolEncoding, bool isEH) {
+ MCContext &context = streamer.getContext();
+ const MCAsmInfo *asmInfo = context.getAsmInfo();
+ const MCExpr *v = asmInfo->getExprForFDESymbol(&symbol,
+ symbolEncoding,
+ streamer);
+ unsigned size = getSizeForEncoding(streamer, symbolEncoding);
+ if (asmInfo->doDwarfFDESymbolsUseAbsDiff() && isEH)
+ emitAbsValue(streamer, v, size);
+ else
+ streamer.EmitValue(v, size);
+}
+
+static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol,
+ unsigned symbolEncoding) {
+ MCContext &context = streamer.getContext();
+ const MCAsmInfo *asmInfo = context.getAsmInfo();
+ const MCExpr *v = asmInfo->getExprForPersonalitySymbol(&symbol,
+ symbolEncoding,
+ streamer);
+ unsigned size = getSizeForEncoding(streamer, symbolEncoding);
+ streamer.EmitValue(v, size);
+}
+
+namespace {
+
+class FrameEmitterImpl {
+ int CFAOffset = 0;
+ int InitialCFAOffset = 0;
+ bool IsEH;
+ MCObjectStreamer &Streamer;
+
+public:
+ FrameEmitterImpl(bool IsEH, MCObjectStreamer &Streamer)
+ : IsEH(IsEH), Streamer(Streamer) {}
+
+ /// Emit the unwind information in a compact way.
+ void EmitCompactUnwind(const MCDwarfFrameInfo &frame);
+
+ const MCSymbol &EmitCIE(const MCSymbol *personality,
+ unsigned personalityEncoding, const MCSymbol *lsda,
+ bool IsSignalFrame, unsigned lsdaEncoding,
+ bool IsSimple);
+ 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->getDwarfRegNum(MRI->getLLVMRegNum(Reg1, true), false);
+ Reg2 = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg2, true), false);
+ }
+ 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::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->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
+ 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->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
+ 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->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
+
+ 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->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
+ Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1);
+ 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 MCSymbol *personality,
+ unsigned personalityEncoding,
+ const MCSymbol *lsda,
+ bool IsSignalFrame,
+ unsigned lsdaEncoding,
+ bool IsSimple) {
+ 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);
+
+ // Augmentation String
+ SmallString<8> Augmentation;
+ if (IsEH) {
+ Augmentation += "z";
+ if (personality)
+ Augmentation += "P";
+ if (lsda)
+ Augmentation += "L";
+ Augmentation += "R";
+ if (IsSignalFrame)
+ Augmentation += "S";
+ 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
+ if (CIEVersion == 1) {
+ assert(MRI->getRARegister() <= 255 &&
+ "DWARF 2 encodes return_address_register in one byte");
+ Streamer.EmitIntValue(MRI->getDwarfRegNum(MRI->getRARegister(), IsEH), 1);
+ } else {
+ Streamer.EmitULEB128IntValue(
+ MRI->getDwarfRegNum(MRI->getRARegister(), IsEH));
+ }
+
+ // Augmentation Data Length (optional)
+
+ unsigned augmentationLength = 0;
+ if (IsEH) {
+ if (personality) {
+ // Personality Encoding
+ augmentationLength += 1;
+ // Personality
+ augmentationLength += getSizeForEncoding(Streamer, personalityEncoding);
+ }
+ if (lsda)
+ augmentationLength += 1;
+ // Encoding of the FDE pointers
+ augmentationLength += 1;
+
+ Streamer.EmitULEB128IntValue(augmentationLength);
+
+ // Augmentation Data (optional)
+ if (personality) {
+ // Personality Encoding
+ emitEncodingByte(Streamer, personalityEncoding);
+ // Personality
+ EmitPersonality(Streamer, *personality, personalityEncoding);
+ }
+
+ if (lsda)
+ emitEncodingByte(Streamer, lsdaEncoding);
+
+ // Encoding of the FDE pointers
+ emitEncodingByte(Streamer, MOFI->getFDEEncoding());
+ }
+
+ // Initial Instructions
+
+ const MCAsmInfo *MAI = context.getAsmInfo();
+ if (!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 const CIEKey getTombstoneKey() {
+ return CIEKey(nullptr, -1, 0, false, false);
+ }
+
+ CIEKey(const MCSymbol *Personality, unsigned PersonalityEncoding,
+ unsigned LsdaEncoding, bool IsSignalFrame, bool IsSimple)
+ : Personality(Personality), PersonalityEncoding(PersonalityEncoding),
+ LsdaEncoding(LsdaEncoding), IsSignalFrame(IsSignalFrame),
+ IsSimple(IsSimple) {}
+
+ const MCSymbol *Personality;
+ unsigned PersonalityEncoding;
+ unsigned LsdaEncoding;
+ bool IsSignalFrame;
+ bool IsSimple;
+};
+
+} // 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));
+ }
+
+ 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;
+ }
+};
+
+} // end namespace llvm
+
+void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB,
+ bool IsEH) {
+ Streamer.generateCompactUnwindEncodings(MAB);
+
+ MCContext &Context = Streamer.getContext();
+ const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();
+ const MCAsmInfo *AsmInfo = Context.getAsmInfo();
+ FrameEmitterImpl Emitter(IsEH, Streamer);
+ ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getDwarfFrameInfos();
+
+ // Emit the compact unwind info if available.
+ bool NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame();
+ if (IsEH && MOFI->getCompactUnwindSection()) {
+ bool SectionEmitted = false;
+ for (const MCDwarfFrameInfo &Frame : FrameArray) {
+ if (Frame.CompactUnwindEncoding == 0) continue;
+ if (!SectionEmitted) {
+ Streamer.SwitchSection(MOFI->getCompactUnwindSection());
+ Streamer.EmitValueToAlignment(AsmInfo->getCodePointerSize());
+ SectionEmitted = true;
+ }
+ NeedsEHFrameSection |=
+ Frame.CompactUnwindEncoding ==
+ MOFI->getCompactUnwindDwarfEHFrameOnly();
+ Emitter.EmitCompactUnwind(Frame);
+ }
+ }
+
+ if (!NeedsEHFrameSection) return;
+
+ MCSection &Section =
+ IsEH ? *const_cast<MCObjectFileInfo *>(MOFI)->getEHFrameSection()
+ : *MOFI->getDwarfFrameSection();
+
+ Streamer.SwitchSection(&Section);
+ MCSymbol *SectionStart = Context.createTempSymbol();
+ Streamer.EmitLabel(SectionStart);
+
+ DenseMap<CIEKey, const MCSymbol *> CIEStarts;
+
+ const MCSymbol *DummyDebugKey = nullptr;
+ bool CanOmitDwarf = MOFI->getOmitDwarfIfHaveCompactUnwind();
+ for (auto I = FrameArray.begin(), E = FrameArray.end(); I != E;) {
+ const MCDwarfFrameInfo &Frame = *I;
+ ++I;
+ if (CanOmitDwarf && Frame.CompactUnwindEncoding !=
+ MOFI->getCompactUnwindDwarfEHFrameOnly())
+ // Don't generate an EH frame if we don't need one. I.e., it's taken care
+ // of by the compact unwind encoding.
+ continue;
+
+ CIEKey Key(Frame.Personality, Frame.PersonalityEncoding,
+ Frame.LsdaEncoding, Frame.IsSignalFrame, Frame.IsSimple);
+ const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey;
+ if (!CIEStart)
+ CIEStart = &Emitter.EmitCIE(Frame.Personality, Frame.PersonalityEncoding,
+ Frame.Lsda, Frame.IsSignalFrame,
+ Frame.LsdaEncoding, Frame.IsSimple);
+
+ Emitter.EmitFDE(*CIEStart, Frame, I == E, *SectionStart);
+ }
+}
+
+void MCDwarfFrameEmitter::EmitAdvanceLoc(MCObjectStreamer &Streamer,
+ uint64_t AddrDelta) {
+ MCContext &Context = Streamer.getContext();
+ SmallString<256> Tmp;
+ raw_svector_ostream OS(Tmp);
+ MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OS);
+ Streamer.EmitBytes(OS.str());
+}
+
+void MCDwarfFrameEmitter::EncodeAdvanceLoc(MCContext &Context,
+ uint64_t AddrDelta,
+ raw_ostream &OS) {
+ // Scale the address delta by the minimum instruction length.
+ AddrDelta = ScaleAddrDelta(Context, AddrDelta);
+
+ if (AddrDelta == 0) {
+ } else if (isUIntN(6, AddrDelta)) {
+ uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta;
+ OS << Opcode;
+ } else if (isUInt<8>(AddrDelta)) {
+ OS << uint8_t(dwarf::DW_CFA_advance_loc1);
+ OS << uint8_t(AddrDelta);
+ } else if (isUInt<16>(AddrDelta)) {
+ OS << uint8_t(dwarf::DW_CFA_advance_loc2);
+ if (Context.getAsmInfo()->isLittleEndian())
+ support::endian::Writer<support::little>(OS).write<uint16_t>(AddrDelta);
+ else
+ support::endian::Writer<support::big>(OS).write<uint16_t>(AddrDelta);
+ } else {
+ assert(isUInt<32>(AddrDelta));
+ OS << uint8_t(dwarf::DW_CFA_advance_loc4);
+ if (Context.getAsmInfo()->isLittleEndian())
+ support::endian::Writer<support::little>(OS).write<uint32_t>(AddrDelta);
+ else
+ support::endian::Writer<support::big>(OS).write<uint32_t>(AddrDelta);
+ }
+}
diff --git a/contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp b/contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp
new file mode 100644
index 000000000000..68fb5e7cbb3d
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp
@@ -0,0 +1,32 @@
+//===-- MCELFObjectTargetWriter.cpp - ELF Target Writer Subclass ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCELFObjectWriter.h"
+
+using namespace llvm;
+
+MCELFObjectTargetWriter::MCELFObjectTargetWriter(bool Is64Bit_,
+ uint8_t OSABI_,
+ uint16_t EMachine_,
+ bool HasRelocationAddend_,
+ bool IsN64_)
+ : OSABI(OSABI_), EMachine(EMachine_),
+ HasRelocationAddend(HasRelocationAddend_), Is64Bit(Is64Bit_),
+ IsN64(IsN64_){
+}
+
+bool MCELFObjectTargetWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
+ unsigned Type) const {
+ return false;
+}
+
+void
+MCELFObjectTargetWriter::sortRelocs(const MCAssembler &Asm,
+ std::vector<ELFRelocationEntry> &Relocs) {
+}
diff --git a/contrib/llvm/lib/MC/MCELFStreamer.cpp b/contrib/llvm/lib/MC/MCELFStreamer.cpp
new file mode 100644
index 000000000000..50c1f6e79f8a
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCELFStreamer.cpp
@@ -0,0 +1,648 @@
+//===- lib/MC/MCELFStreamer.cpp - ELF Object Output -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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;
+
+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);
+ MCObjectWriter *OW = Assembler.getBackend().createObjectWriter(VecOS);
+
+ EF->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding));
+
+ Assembler.writeFragmentPadding(*EF, FSize, OW);
+ delete OW;
+
+ 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]);
+ }
+ DF->setHasInstructions(true);
+ 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);
+ // 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_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::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::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_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_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_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::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());
+}
+
+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).
+ //
+ // 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();
+ 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());
+ 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());
+ 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();
+ }
+
+ // 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(true);
+ DF->getContents().append(Code.begin(), Code.end());
+
+ if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) {
+ if (!isBundleLocked()) {
+ mergeFragment(getOrCreateDataFragment(), 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);
+ 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);
+
+ 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) {
+ 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, MCAsmBackend &MAB,
+ raw_pwrite_stream &OS, MCCodeEmitter *CE,
+ bool RelaxAll) {
+ MCELFStreamer *S = new MCELFStreamer(Context, MAB, OS, 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
new file mode 100644
index 000000000000..38a8af49c194
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCExpr.cpp
@@ -0,0 +1,821 @@
+//===- MCExpr.cpp - Assembly Level Expression Implementation --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCExpr.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringSwitch.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:
+ OS << cast<MCConstantExpr>(*this).getValue();
+ 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;
+ }
+ UE.getSubExpr()->print(OS, MAI);
+ 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) {
+ return new (Ctx) MCConstantExpr(Value);
+}
+
+/* *** */
+
+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_PPC_LO: return "l";
+ case VK_PPC_HI: return "h";
+ case VK_PPC_HA: return "ha";
+ 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_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_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_WebAssembly_FUNCTION: return "FUNCTION";
+ case VK_WebAssembly_TYPEINDEX: return "TYPEINDEX";
+ 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";
+ }
+ 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("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@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@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("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)
+ .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::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();
+}
+
+/// \brief 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() &&
+ !SB.isVariable()) {
+ 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;
+
+ // 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;
+
+ // Clear the symbol expr pointers to indicate we have folded these
+ // operands.
+ A = B = nullptr;
+}
+
+/// \brief 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.
+ if (Asm) {
+ // 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))
+ 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;
+ switch (ABE->getOpcode()) {
+ case MCBinaryExpr::AShr: Result = LHS >> RHS; break;
+ case MCBinaryExpr::Add: Result = LHS + RHS; break;
+ case MCBinaryExpr::And: Result = LHS & RHS; break;
+ case MCBinaryExpr::Div:
+ // 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;
+ 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::Mod: 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;
+ }
+
+ Res = MCValue::get(Result);
+ 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
new file mode 100644
index 000000000000..6e0249377a89
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCFragment.cpp
@@ -0,0 +1,471 @@
+//===- lib/MC/MCFragment.cpp - Assembler Fragment Implementation ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCFragment.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Twine.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-varibale 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 MCFragment *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,
+ uint8_t BundlePadding, MCSection *Parent)
+ : Kind(Kind), HasInstructions(HasInstructions), AlignToBundleEnd(false),
+ BundlePadding(BundlePadding), 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_SafeSEH:
+ delete cast<MCSafeSEHFragment>(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_SafeSEH: OS << "MCSafeSEHFragment"; 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()
+ << " BundlePadding:" << static_cast<unsigned>(getBundlePadding()) << ">";
+
+ 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())
+ << " Size:" << FF->getSize();
+ 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_SafeSEH: {
+ const MCSafeSEHFragment *F = cast<MCSafeSEHFragment>(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 << ">";
+}
+
+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/MCInst.cpp b/contrib/llvm/lib/MC/MCInst.cpp
new file mode 100644
index 000000000000..f6d1d3cffca0
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCInst.cpp
@@ -0,0 +1,74 @@
+//===- lib/MC/MCInst.cpp - MCInst implementation --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInstPrinter.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 << ">";
+}
+
+#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 {
+ OS << "<MCInst #" << getOpcode();
+
+ // Show the instruction opcode name if we have access to a printer.
+ if (Printer)
+ OS << ' ' << Printer->getOpcodeName(getOpcode());
+
+ 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
new file mode 100644
index 000000000000..9296fcedb72b
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCInstPrinter.cpp
@@ -0,0 +1,122 @@
+//===- MCInstPrinter.cpp - Convert an MCInst to target assembly syntax ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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";
+ for (char i: bytes) {
+ OS << hex_rep[(i & 0xF0) >> 4];
+ OS << hex_rep[i & 0xF];
+ OS << ' ';
+ }
+}
+
+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
new file mode 100644
index 000000000000..280b5cf68c98
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCInstrAnalysis.cpp
@@ -0,0 +1,27 @@
+//===- MCInstrAnalysis.cpp - InstrDesc target hooks -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCInstrAnalysis.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrDesc.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include <cstdint>
+
+using namespace llvm;
+
+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
new file mode 100644
index 000000000000..ee55f3eff3ac
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCInstrDesc.cpp
@@ -0,0 +1,70 @@
+//===------ llvm/MC/MCInstrDesc.cpp- Instruction Descriptors --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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;
+ // A variadic instruction may define PC in the variable operand list.
+ // There's currently no indication of which entries in a variable
+ // list are defs and which are uses. While that's the case, this function
+ // needs to assume they're defs in order to be conservatively correct.
+ for (int i = NumOperands, e = MI.getNumOperands(); i != e; ++i) {
+ if (MI.getOperand(i).isReg() &&
+ RI.isSubRegisterEq(PC, MI.getOperand(i).getReg()))
+ 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;
+ return hasImplicitDefOfPhysReg(Reg, &RI);
+}
diff --git a/contrib/llvm/lib/MC/MCLabel.cpp b/contrib/llvm/lib/MC/MCLabel.cpp
new file mode 100644
index 000000000000..db25a46fce18
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCLabel.cpp
@@ -0,0 +1,25 @@
+//===- lib/MC/MCLabel.cpp - MCLabel implementation ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCLabel.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
new file mode 100644
index 000000000000..97f95418e054
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp
@@ -0,0 +1,60 @@
+//===- llvm/MC/MCLinkerOptimizationHint.cpp ----- LOH handling ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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.getStream();
+ 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
new file mode 100644
index 000000000000..674c7b9bf619
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCMachOStreamer.cpp
@@ -0,0 +1,515 @@
+//===- MCMachOStreamer.cpp - MachO Streamer -------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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/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, MCAsmBackend &MAB, raw_pwrite_stream &OS,
+ MCCodeEmitter *Emitter, bool DWARFMustBeAtTheEnd, bool label)
+ : MCObjectStreamer(Context, MAB, OS, 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) 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) 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) {
+ getAssembler().setVersionMinInfo(Kind, Major, Minor, Update);
+}
+
+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;
+ }
+
+ 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) {
+ getAssembler().registerSection(*Section);
+
+ // The symbol may not be present, which only creates the section.
+ if (!Symbol)
+ return;
+
+ // On darwin all virtual sections have zerofill type.
+ assert(Section->isVirtualSection() && "Section does not have zerofill type!");
+
+ assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
+
+ getAssembler().registerSymbol(*Symbol);
+
+ // Emit an align fragment if necessary.
+ if (ByteAlignment != 1)
+ new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, Section);
+
+ MCFragment *F = new MCFillFragment(0, Size, Section);
+ Symbol->setFragment(F);
+
+ // Update the maximum alignment on the zero fill section if necessary.
+ if (ByteAlignment > Section->getAlignment())
+ Section->setAlignment(ByteAlignment);
+}
+
+// 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->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, MCAsmBackend &MAB,
+ raw_pwrite_stream &OS, MCCodeEmitter *CE,
+ bool RelaxAll, bool DWARFMustBeAtTheEnd,
+ bool LabelSections) {
+ MCMachOStreamer *S = new MCMachOStreamer(Context, MAB, OS, CE,
+ DWARFMustBeAtTheEnd, LabelSections);
+ const Triple &TT = Context.getObjectFileInfo()->getTargetTriple();
+ if (TT.isOSDarwin()) {
+ unsigned Major, Minor, Update;
+ TT.getOSVersion(Major, Minor, Update);
+ // If there is a version specified, Major will be non-zero.
+ if (Major) {
+ MCVersionMinType VersionType;
+ if (TT.isWatchOS())
+ VersionType = MCVM_WatchOSVersionMin;
+ else if (TT.isTvOS())
+ VersionType = MCVM_TvOSVersionMin;
+ else if (TT.isMacOSX())
+ VersionType = MCVM_OSXVersionMin;
+ else {
+ assert(TT.isiOS() && "Must only be iOS platform left");
+ VersionType = MCVM_IOSVersionMin;
+ }
+ S->EmitVersionMin(VersionType, Major, Minor, Update);
+ }
+ }
+ if (RelaxAll)
+ S->getAssembler().setRelaxAll(true);
+ return S;
+}
diff --git a/contrib/llvm/lib/MC/MCMachObjectTargetWriter.cpp b/contrib/llvm/lib/MC/MCMachObjectTargetWriter.cpp
new file mode 100644
index 000000000000..8809a3c320f8
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCMachObjectTargetWriter.cpp
@@ -0,0 +1,19 @@
+//===- MCMachObjectTargetWriter.cpp - Mach-O Target Writer Subclass -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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
new file mode 100644
index 000000000000..4db9a2c8d8de
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCNullStreamer.cpp
@@ -0,0 +1,47 @@
+//===- lib/MC/MCNullStreamer.cpp - Dummy Streamer Implementation ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSectionMachO.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 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) 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
new file mode 100644
index 000000000000..21c5516785ef
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -0,0 +1,908 @@
+//===-- MCObjectFileInfo.cpp - Object File Information --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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"
+
+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;
+
+ PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel
+ | dwarf::DW_EH_PE_sdata4;
+ LSDAEncoding = FDECFIEncoding = dwarf::DW_EH_PE_pcrel;
+ TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
+ dwarf::DW_EH_PE_sdata4;
+
+ // .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();
+
+ 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());
+ } else {
+ TextCoalSection = TextSection;
+ ConstTextCoalSection = ReadOnlySection;
+ DataCoalSection = DataSection;
+ }
+
+ ConstDataSection // .const_data
+ = Ctx->getMachOSection("__DATA", "__const", 0,
+ SectionKind::getReadOnlyWithRel());
+ 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;
+
+ 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.
+ 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");
+
+ 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");
+ 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");
+ DwarfLocSection =
+ Ctx->getMachOSection("__DWARF", "__debug_loc", 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");
+ 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());
+
+ TLSExtraDataSection = TLSTLVSection;
+}
+
+void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T) {
+ switch (T.getArch()) {
+ case Triple::mips:
+ case Triple::mipsel:
+ FDECFIEncoding = dwarf::DW_EH_PE_sdata4;
+ break;
+ case Triple::mips64:
+ case Triple::mips64el:
+ FDECFIEncoding = dwarf::DW_EH_PE_sdata8;
+ break;
+ case Triple::x86_64:
+ FDECFIEncoding = dwarf::DW_EH_PE_pcrel |
+ ((CMModel == CodeModel::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;
+ default:
+ FDECFIEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
+ break;
+ }
+
+ switch (T.getArch()) {
+ case Triple::arm:
+ case Triple::armeb:
+ case Triple::thumb:
+ case Triple::thumbeb:
+ if (Ctx->getAsmInfo()->getExceptionHandlingType() == ExceptionHandling::ARM)
+ break;
+ // Fallthrough if not using EHABI
+ LLVM_FALLTHROUGH;
+ case Triple::ppc:
+ case Triple::x86:
+ PersonalityEncoding = PositionIndependent
+ ? dwarf::DW_EH_PE_indirect |
+ dwarf::DW_EH_PE_pcrel |
+ dwarf::DW_EH_PE_sdata4
+ : dwarf::DW_EH_PE_absptr;
+ LSDAEncoding = PositionIndependent
+ ? dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4
+ : dwarf::DW_EH_PE_absptr;
+ TTypeEncoding = PositionIndependent
+ ? dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
+ dwarf::DW_EH_PE_sdata4
+ : dwarf::DW_EH_PE_absptr;
+ break;
+ case Triple::x86_64:
+ if (PositionIndependent) {
+ PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
+ ((CMModel == CodeModel::Small || CMModel == CodeModel::Medium)
+ ? dwarf::DW_EH_PE_sdata4 : dwarf::DW_EH_PE_sdata8);
+ LSDAEncoding = dwarf::DW_EH_PE_pcrel |
+ (CMModel == CodeModel::Small
+ ? dwarf::DW_EH_PE_sdata4 : dwarf::DW_EH_PE_sdata8);
+ TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
+ ((CMModel == CodeModel::Small || CMModel == CodeModel::Medium)
+ ? dwarf::DW_EH_PE_sdata4 : dwarf::DW_EH_PE_sdata8);
+ } else {
+ PersonalityEncoding =
+ (CMModel == CodeModel::Small || CMModel == CodeModel::Medium)
+ ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_absptr;
+ LSDAEncoding = (CMModel == CodeModel::Small)
+ ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_absptr;
+ TTypeEncoding = (CMModel == CodeModel::Small)
+ ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_absptr;
+ }
+ break;
+ case Triple::hexagon:
+ PersonalityEncoding = dwarf::DW_EH_PE_absptr;
+ LSDAEncoding = dwarf::DW_EH_PE_absptr;
+ FDECFIEncoding = dwarf::DW_EH_PE_absptr;
+ TTypeEncoding = dwarf::DW_EH_PE_absptr;
+ if (PositionIndependent) {
+ PersonalityEncoding |= dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel;
+ LSDAEncoding |= dwarf::DW_EH_PE_pcrel;
+ FDECFIEncoding |= dwarf::DW_EH_PE_pcrel;
+ TTypeEncoding |= dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel;
+ }
+ break;
+ case Triple::aarch64:
+ case Triple::aarch64_be:
+ // The small model guarantees static code/data size < 4GB, but not where it
+ // will be in memory. Most of these could end up >2GB away so even a signed
+ // pc-relative 32-bit address is insufficient, theoretically.
+ if (PositionIndependent) {
+ PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
+ dwarf::DW_EH_PE_sdata8;
+ LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8;
+ TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
+ dwarf::DW_EH_PE_sdata8;
+ } else {
+ PersonalityEncoding = dwarf::DW_EH_PE_absptr;
+ LSDAEncoding = dwarf::DW_EH_PE_absptr;
+ TTypeEncoding = dwarf::DW_EH_PE_absptr;
+ }
+ break;
+ case Triple::lanai:
+ LSDAEncoding = dwarf::DW_EH_PE_absptr;
+ PersonalityEncoding = dwarf::DW_EH_PE_absptr;
+ TTypeEncoding = dwarf::DW_EH_PE_absptr;
+ break;
+ case Triple::mips:
+ case Triple::mipsel:
+ case Triple::mips64:
+ case Triple::mips64el:
+ // MIPS uses indirect pointer to refer personality functions and types, so
+ // that the eh_frame section can be read-only. DW.ref.personality will be
+ // generated for relocation.
+ PersonalityEncoding = dwarf::DW_EH_PE_indirect;
+ // FIXME: The N64 ABI probably ought to use DW_EH_PE_sdata8 but we can't
+ // identify N64 from just a triple.
+ TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
+ dwarf::DW_EH_PE_sdata4;
+ // We don't support PC-relative LSDA references in GAS so we use the default
+ // DW_EH_PE_absptr for those.
+
+ // FreeBSD must be explicit about the data size and using pcrel since it's
+ // assembler/linker won't do the automatic conversion that the Linux tools
+ // do.
+ if (T.isOSFreeBSD()) {
+ PersonalityEncoding |= dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
+ LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
+ }
+ break;
+ case Triple::ppc64:
+ case Triple::ppc64le:
+ PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
+ dwarf::DW_EH_PE_udata8;
+ LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8;
+ TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
+ dwarf::DW_EH_PE_udata8;
+ break;
+ case Triple::sparcel:
+ case Triple::sparc:
+ if (PositionIndependent) {
+ LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
+ PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
+ dwarf::DW_EH_PE_sdata4;
+ TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
+ dwarf::DW_EH_PE_sdata4;
+ } else {
+ LSDAEncoding = dwarf::DW_EH_PE_absptr;
+ PersonalityEncoding = dwarf::DW_EH_PE_absptr;
+ TTypeEncoding = dwarf::DW_EH_PE_absptr;
+ }
+ break;
+ case Triple::sparcv9:
+ LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
+ if (PositionIndependent) {
+ PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
+ dwarf::DW_EH_PE_sdata4;
+ TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
+ dwarf::DW_EH_PE_sdata4;
+ } else {
+ PersonalityEncoding = dwarf::DW_EH_PE_absptr;
+ TTypeEncoding = dwarf::DW_EH_PE_absptr;
+ }
+ break;
+ case Triple::systemz:
+ // All currently-defined code models guarantee that 4-byte PC-relative
+ // values will be in range.
+ if (PositionIndependent) {
+ PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
+ dwarf::DW_EH_PE_sdata4;
+ LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
+ TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
+ dwarf::DW_EH_PE_sdata4;
+ } else {
+ PersonalityEncoding = dwarf::DW_EH_PE_absptr;
+ LSDAEncoding = dwarf::DW_EH_PE_absptr;
+ TTypeEncoding = dwarf::DW_EH_PE_absptr;
+ }
+ break;
+ default:
+ 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.getArch() == Triple::mips || T.getArch() == Triple::mipsel ||
+ T.getArch() == Triple::mips64 || T.getArch() == Triple::mips64el)
+ 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);
+ 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
+ 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);
+
+ // Fission Sections
+ DwarfInfoDWOSection =
+ Ctx->getELFSection(".debug_info.dwo", DebugSecType, 0);
+ DwarfTypesDWOSection =
+ Ctx->getELFSection(".debug_types.dwo", DebugSecType, 0);
+ DwarfAbbrevDWOSection =
+ Ctx->getELFSection(".debug_abbrev.dwo", DebugSecType, 0);
+ DwarfStrDWOSection =
+ Ctx->getELFSection(".debug_str.dwo", DebugSecType,
+ ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, "");
+ DwarfLineDWOSection =
+ Ctx->getELFSection(".debug_line.dwo", DebugSecType, 0);
+ DwarfLocDWOSection =
+ Ctx->getELFSection(".debug_loc.dwo", DebugSecType, 0);
+ DwarfStrOffDWOSection =
+ Ctx->getELFSection(".debug_str_offsets.dwo", DebugSecType, 0);
+
+ // 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);
+}
+
+void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
+ EHFrameSection = Ctx->getCOFFSection(
+ ".eh_frame", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE,
+ 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());
+
+ // FIXME: We're emitting LSDA info into a readonly section on COFF, 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.
+ if (T.getArch() == Triple::x86_64) {
+ // 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());
+
+ 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");
+
+ 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());
+ 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());
+
+ 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) {
+ // TODO: Set the section types and flags.
+ TextSection = Ctx->getWasmSection(".text", 0, 0);
+ DataSection = Ctx->getWasmSection(".data", 0, 0);
+
+ // TODO: Set the section types and flags.
+ DwarfLineSection = Ctx->getWasmSection(".debug_line", 0, 0);
+ DwarfStrSection = Ctx->getWasmSection(".debug_str", 0, 0);
+ DwarfLocSection = Ctx->getWasmSection(".debug_loc", 0, 0);
+ DwarfAbbrevSection = Ctx->getWasmSection(".debug_abbrev", 0, 0, "section_abbrev");
+ DwarfARangesSection = Ctx->getWasmSection(".debug_aranges", 0, 0);
+ DwarfRangesSection = Ctx->getWasmSection(".debug_ranges", 0, 0, "debug_range");
+ DwarfMacinfoSection = Ctx->getWasmSection(".debug_macinfo", 0, 0, "debug_macinfo");
+ DwarfAddrSection = Ctx->getWasmSection(".debug_addr", 0, 0);
+ DwarfCUIndexSection = Ctx->getWasmSection(".debug_cu_index", 0, 0);
+ DwarfTUIndexSection = Ctx->getWasmSection(".debug_tu_index", 0, 0);
+ DwarfInfoSection = Ctx->getWasmSection(".debug_info", 0, 0, "section_info");
+ DwarfFrameSection = Ctx->getWasmSection(".debug_frame", 0, 0);
+ DwarfPubNamesSection = Ctx->getWasmSection(".debug_pubnames", 0, 0);
+ DwarfPubTypesSection = Ctx->getWasmSection(".debug_pubtypes", 0, 0);
+
+ // TODO: Define more sections.
+}
+
+void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC,
+ CodeModel::Model cm,
+ MCContext &ctx) {
+ PositionIndependent = PIC;
+ CMModel = cm;
+ Ctx = &ctx;
+
+ // Common.
+ CommDirectiveSupportsAlignment = true;
+ SupportsWeakOmittedEHFrame = true;
+ SupportsCompactUnwindWithoutEHFrame = false;
+ OmitDwarfIfHaveCompactUnwind = false;
+
+ PersonalityEncoding = LSDAEncoding = FDECFIEncoding = TTypeEncoding =
+ 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);
+ break;
+ case Triple::Wasm:
+ Env = IsWasm;
+ initWasmMCObjectFileInfo(TT);
+ break;
+ case Triple::UnknownObjectFormat:
+ report_fatal_error("Cannot initialize MC for unknown object file format.");
+ break;
+ }
+}
+
+MCSection *MCObjectFileInfo::getDwarfTypesSection(uint64_t Hash) const {
+ return Ctx->getELFSection(".debug_types", ELF::SHT_PROGBITS, ELF::SHF_GROUP,
+ 0, utostr(Hash));
+}
diff --git a/contrib/llvm/lib/MC/MCObjectStreamer.cpp b/contrib/llvm/lib/MC/MCObjectStreamer.cpp
new file mode 100644
index 000000000000..174397e27396
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCObjectStreamer.cpp
@@ -0,0 +1,605 @@
+//===- lib/MC/MCObjectStreamer.cpp - Object File MCStreamer Interface -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/ADT/STLExtras.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/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"
+#include "llvm/Support/TargetRegistry.h"
+using namespace llvm;
+
+MCObjectStreamer::MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB,
+ raw_pwrite_stream &OS,
+ MCCodeEmitter *Emitter_)
+ : MCStreamer(Context),
+ Assembler(new MCAssembler(Context, TAB, *Emitter_,
+ *TAB.createObjectWriter(OS))),
+ EmitEHFrame(true), EmitDebugFrame(false) {}
+
+MCObjectStreamer::~MCObjectStreamer() {
+ delete &Assembler->getBackend();
+ delete &Assembler->getEmitter();
+ delete &Assembler->getWriter();
+ delete Assembler;
+}
+
+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();
+}
+
+void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,
+ const MCSymbol *Lo,
+ unsigned Size) {
+ // If not assigned to the same (valid) fragment, fallback.
+ if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() ||
+ Hi->isVariable() || Lo->isVariable()) {
+ MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size);
+ return;
+ }
+
+ EmitIntValue(Hi->getOffset() - Lo->getOffset(), Size);
+}
+
+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;
+}
+
+MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() {
+ MCDataFragment *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment());
+ // When bundling is enabled, we don't want to add data to a fragment that
+ // already has instructions (see MCELFStreamer::EmitInstToData for details)
+ if (!F || (Assembler->isBundlingEnabled() && !Assembler->getRelaxAll() &&
+ F->hasInstructions())) {
+ F = new MCDataFragment();
+ 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());
+
+ MCCVLineEntry::Make(this);
+ MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
+
+ // Avoid fixups when possible.
+ int64_t AbsValue;
+ if (Value->evaluateAsAbsolute(AbsValue, getAssembler())) {
+ 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);
+}
+
+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, getAssembler())) {
+ EmitULEB128IntValue(IntValue);
+ return;
+ }
+ insert(new MCLEBFragment(*Value, false));
+}
+
+void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value) {
+ int64_t IntValue;
+ if (Value->evaluateAsAbsolute(IntValue, getAssembler())) {
+ 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, getAssembler()))
+ 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, bool) {
+ 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.
+ MCCVLineEntry::Make(this);
+ MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
+
+ // If this instruction doesn't need relaxation, just emit it as data.
+ MCAssembler &Assembler = getAssembler();
+ if (!Assembler.getBackend().mayNeedRelaxation(Inst)) {
+ 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))
+ 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, getAssembler())) {
+ 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, getAssembler())) {
+ 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) {
+ // In case we see two .cv_loc directives in a row, make sure the
+ // first one gets a line entry.
+ MCCVLineEntry::Make(this);
+
+ this->MCStreamer::EmitCVLocDirective(FunctionId, FileNo, Line, Column,
+ PrologueEnd, IsStmt, FileName, Loc);
+}
+
+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) {
+ getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion);
+ this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion);
+}
+
+void MCObjectStreamer::EmitCVStringTableDirective() {
+ getContext().getCVContext().emitStringTable(*this);
+}
+void MCObjectStreamer::EmitCVFileChecksumsDirective() {
+ getContext().getCVContext().emitFileChecksums(*this);
+}
+
+
+void MCObjectStreamer::EmitBytes(StringRef Data) {
+ MCCVLineEntry::Make(this);
+ MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
+ MCDataFragment *DF = getOrCreateDataFragment();
+ flushPendingLabels(DF, DF->getContents().size());
+ DF->getContents().append(Data.begin(), Data.end());
+}
+
+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));
+}
+
+// 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) {
+ int64_t OffsetValue;
+ if (!Offset.evaluateAsAbsolute(OffsetValue))
+ llvm_unreachable("Offset is not absolute");
+
+ if (OffsetValue < 0)
+ llvm_unreachable("Offset is negative");
+
+ MCDataFragment *DF = getOrCreateDataFragment();
+ flushPendingLabels(DF, DF->getContents().size());
+
+ Optional<MCFixupKind> MaybeKind = Assembler->getBackend().getFixupKind(Name);
+ if (!MaybeKind.hasValue())
+ return true;
+
+ MCFixupKind Kind = *MaybeKind;
+
+ if (Expr == nullptr)
+ Expr =
+ MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext());
+ DF->getFixups().push_back(MCFixup::create(OffsetValue, Expr, Kind, Loc));
+ return false;
+}
+
+void MCObjectStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) {
+ assert(getCurrentSectionOnly() && "need a section");
+ insert(new MCFillFragment(FillValue, NumBytes));
+}
+
+void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
+ SMLoc Loc) {
+ MCDataFragment *DF = getOrCreateDataFragment();
+ flushPendingLabels(DF, DF->getContents().size());
+
+ int64_t IntNumBytes;
+ if (!NumBytes.evaluateAsAbsolute(IntNumBytes, getAssembler())) {
+ getContext().reportError(Loc, "expected absolute expression");
+ return;
+ }
+
+ if (IntNumBytes <= 0) {
+ getContext().reportError(Loc, "invalid number of bytes");
+ return;
+ }
+
+ emitFill(IntNumBytes, FillValue);
+}
+
+void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
+ int64_t Expr, SMLoc Loc) {
+ int64_t IntNumValues;
+ if (!NumValues.evaluateAsAbsolute(IntNumValues, getAssembler())) {
+ getContext().reportError(Loc, "expected absolute expression");
+ return;
+ }
+
+ if (IntNumValues < 0) {
+ getContext().getSourceManager()->PrintMessage(
+ Loc, SourceMgr::DK_Warning,
+ "'.fill' directive with negative repeat count has no effect");
+ return;
+ }
+
+ MCStreamer::emitFill(IntNumValues, Size, Expr);
+}
+
+void MCObjectStreamer::EmitFileDirective(StringRef Filename) {
+ getAssembler().addFileName(Filename);
+}
+
+void MCObjectStreamer::FinishImpl() {
+ // 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(nullptr);
+ getAssembler().Finish();
+}
diff --git a/contrib/llvm/lib/MC/MCObjectWriter.cpp b/contrib/llvm/lib/MC/MCObjectWriter.cpp
new file mode 100644
index 000000000000..98ac48a23f91
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCObjectWriter.cpp
@@ -0,0 +1,53 @@
+//===- lib/MC/MCObjectWriter.cpp - MCObjectWriter implementation ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/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
new file mode 100644
index 000000000000..2b963607b837
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp
@@ -0,0 +1,733 @@
+//===- AsmLexer.cpp - Lexer for Assembly Files ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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/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++;
+}
+
+/// LexFloatLiteral: [0-9]*[.][0-9]*([eE][+-]?[0-9]*)?
+///
+/// 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;
+
+ // Check for exponent; we intentionally accept a slighlty wider set of
+ // literals here and rely on the upstream client to reject invalid ones (e.g.,
+ // "1e+").
+ 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 (isxdigit(*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 (*CurPtr == 'e' || *CurPtr == 'E' ||
+ !IsIdentifierChar(*CurPtr, AllowAtInIdentifier))
+ 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 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 doLookAhead(const char *&CurPtr, unsigned DefaultRadix) {
+ const char *FirstHex = nullptr;
+ const char *LookAhead = CurPtr;
+ while (true) {
+ if (isdigit(*LookAhead)) {
+ ++LookAhead;
+ } else if (isxdigit(*LookAhead)) {
+ if (!FirstHex)
+ FirstHex = LookAhead;
+ ++LookAhead;
+ } else {
+ break;
+ }
+ }
+ bool isHex = *LookAhead == 'h' || *LookAhead == 'H';
+ CurPtr = isHex || !FirstHex ? LookAhead : FirstHex;
+ 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 (IsParsingMSInlineAsm && isdigit(CurPtr[-1])) {
+ const char *FirstNonBinary = (CurPtr[-1] != '0' && CurPtr[-1] != '1') ?
+ CurPtr - 1 : nullptr;
+ const char *OldCurPtr = CurPtr;
+ while (isxdigit(*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 = doLookAhead(CurPtr, 10);
+ bool isHex = Radix == 16;
+ // Check for floating point literals.
+ if (!isHex && (*CurPtr == '.' || *CurPtr == 'e')) {
+ ++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 [bB][hH].
+ if (Radix == 2 || 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 (!IsParsingMSInlineAsm && ((*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 (isxdigit(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 (!IsParsingMSInlineAsm && (*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 = doLookAhead(CurPtr, 8);
+ 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 preceeding 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 '\n':
+ case '\r':
+ 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::Minus, 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::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
new file mode 100644
index 000000000000..dad47e49e2c2
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -0,0 +1,5630 @@
+//===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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/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/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 {
+
+/// \brief Helper types for tracking macro definitions.
+typedef std::vector<AsmToken> MCAsmMacroArgument;
+typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
+
+struct MCAsmMacroParameter {
+ StringRef Name;
+ MCAsmMacroArgument Value;
+ bool Required = false;
+ bool Vararg = false;
+
+ MCAsmMacroParameter() = default;
+};
+
+typedef std::vector<MCAsmMacroParameter> MCAsmMacroParameters;
+
+struct MCAsmMacro {
+ StringRef Name;
+ StringRef Body;
+ MCAsmMacroParameters Parameters;
+
+public:
+ MCAsmMacro(StringRef N, StringRef B, MCAsmMacroParameters P)
+ : Name(N), Body(B), Parameters(std::move(P)) {}
+};
+
+/// \brief 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 {
+ /// \brief The parsed operands from the last parsed statement.
+ SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands;
+
+ /// \brief The opcode from the last parsed instruction.
+ unsigned Opcode = ~0U;
+
+ /// \brief Was there an error parsing the inline assembly?
+ bool ParseError = false;
+
+ SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
+
+ ParseStatementInfo() = delete;
+ ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
+ : AsmRewrites(rewrites) {}
+};
+
+/// \brief 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;
+
+ /// \brief maps directive names to handler methods in parser
+ /// extensions. Extensions register themselves in this map by calling
+ /// addDirectiveHandler.
+ StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
+
+ /// \brief Map of currently defined macros.
+ StringMap<MCAsmMacro> MacroMap;
+
+ /// \brief Stack of active macro instantiations.
+ std::vector<MacroInstantiation*> ActiveMacros;
+
+ /// \brief List of bodies of anonymous macros.
+ std::deque<MCAsmMacro> MacroLikeBodies;
+
+ /// Boolean tracking whether macro substitution is enabled.
+ unsigned MacrosEnabledFlag : 1;
+
+ /// \brief 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 = 0;
+ SMLoc Loc;
+ unsigned Buf = 0;
+ };
+ CppHashInfoTy CppHashInfo;
+
+ /// \brief List of forward directional labels for diagnosis at the end.
+ SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels;
+
+ /// When generating dwarf for assembly source files we need to calculate the
+ /// logical line number based on the last parsed cpp hash file line comment
+ /// and current line. Since this is slow and messes up the SourceMgr's
+ /// cache we save the last info we queried with SrcMgr.FindLineNumber().
+ SMLoc LastQueryIDLoc;
+ unsigned LastQueryBuffer;
+ unsigned LastQueryLine;
+
+ /// AssemblerDialect. ~OU means unset value and use value provided by MAI.
+ unsigned AssemblerDialect = ~0U;
+
+ /// \brief is Darwin compatibility enabled?
+ bool IsDarwin = false;
+
+ /// \brief Are we parsing ms-style inline assembly?
+ bool ParsingInlineAsm = 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;
+ Lexer.setParsingMSInlineAsm(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;
+
+ /// \brief Parse a floating point expression using the float \p Semantics
+ /// and set \p Res to the value.
+ bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
+
+ /// \brief 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 isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc);
+ void altMacroString(StringRef AltMacroStr, std::string &Res);
+ 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);
+
+ /// \brief Are macros enabled in the parser?
+ bool areMacrosEnabled() {return MacrosEnabledFlag;}
+
+ /// \brief Control a flag in the parser that enables or disables macros.
+ void setMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;}
+
+ /// \brief Lookup a previously defined macro.
+ /// \param Name Macro name.
+ /// \returns Pointer to macro. NULL if no such macro was defined.
+ const MCAsmMacro* lookupMacro(StringRef Name);
+
+ /// \brief Define a new macro with the given name and information.
+ void defineMacro(StringRef Name, MCAsmMacro Macro);
+
+ /// \brief Undefine a macro. If no such macro was defined, it's a no-op.
+ void undefineMacro(StringRef Name);
+
+ /// \brief Are we inside a macro instantiation?
+ bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
+
+ /// \brief Handle entry to macro instantiation.
+ ///
+ /// \param M The macro.
+ /// \param NameLoc Instantiation location.
+ bool handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc);
+
+ /// \brief Handle exit from macro instantiation.
+ void handleMacroExit();
+
+ /// \brief Extract AsmTokens for a macro argument.
+ bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg);
+
+ /// \brief 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);
+
+ /// \brief Enter the specified file. This returns true on failure.
+ bool enterIncludeFile(const std::string &Filename);
+
+ /// \brief 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());
+
+ /// \brief 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);
+
+ /// \brief 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;
+
+ /// \brief 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_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_FILECHECKSUMS,
+ 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_SIGNAL_FRAME, DK_CFI_UNDEFINED,
+ DK_CFI_REGISTER, DK_CFI_WINDOW_SAVE,
+ 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_END
+ };
+
+ /// \brief 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"
+ bool parseDirectiveCVFile();
+ bool parseDirectiveCVFuncId();
+ bool parseDirectiveCVInlineSiteId();
+ bool parseDirectiveCVLoc();
+ bool parseDirectiveCVLinetable();
+ bool parseDirectiveCVInlineLinetable();
+ bool parseDirectiveCVDefRange();
+ bool parseDirectiveCVStringTable();
+ bool parseDirectiveCVFileChecksums();
+
+ // .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 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);
+
+ /// \brief 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);
+
+ void initializeDirectiveKindMap();
+};
+
+} // end anonymous namespace
+
+namespace llvm {
+
+extern MCAsmParserExtension *createDarwinAsmParser();
+extern MCAsmParserExtension *createELFAsmParser();
+extern MCAsmParserExtension *createCOFFAsmParser();
+
+} // 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:
+ llvm_unreachable("Wasm parsing not supported yet");
+ 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))
+ 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::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 and generate a .file directive.
+ 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;
+ getContext().setGenDwarfFileNumber(getStreamer().EmitDwarfFileDirective(
+ 0, StringRef(), getContext().getMainFileName()));
+ }
+
+ // 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();
+ }
+
+ // 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;
+}
+
+/// \brief 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);
+}
+
+/// \brief 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;
+}
+
+/// \brief 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;
+}
+
+/// \brief 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 true;
+
+ 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().getOrCreateSymbol(SymbolName);
+
+ // If this is an absolute variable reference, substitute it now to preserve
+ // semantics in the face of reassignment.
+ if (Sym->isVariable() &&
+ isa<MCConstantExpr>(Sym->getVariableValue(/*SetUsed*/ false))) {
+ 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.
+bool AsmParser::isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc) {
+ assert((StrLoc.getPointer() != NULL) &&
+ "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;
+}
+
+/// \brief creating a string without the escape characters '!'.
+void AsmParser::altMacroString(StringRef AltMacroStr,std::string &Res) {
+ for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {
+ if (AltMacroStr[Pos] == '!')
+ Pos++;
+ Res += AltMacroStr[Pos];
+ }
+}
+
+/// \brief 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 (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.
+ 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))
+ 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);
+}
+
+/// \brief 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 (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;
+ }
+ if (Lexer.is(AsmToken::Hash)) {
+ // Seeing a hash here means that it was an end-of-line comment in
+ // an asm syntax where hash's are not comment and the previous
+ // statement parser did not check the end of statement. Relex as
+ // EndOfStatement.
+ StringRef CommentStr = parseStringToEndOfStatement();
+ Lexer.Lex();
+ Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
+ 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 (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();
+ }
+
+ // 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 (getContext().getGenDwarfForAssembly())
+ 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 = lookupMacro(IDVal)) {
+ return handleMacroEntry(M, IDLoc);
+ }
+
+ // Otherwise, we have a normal instruction or directive.
+
+ // Directives start with "."
+ if (IDVal[0] == '.' && 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_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_STRINGTABLE:
+ return parseDirectiveCVStringTable();
+ case DK_CV_FILECHECKSUMS:
+ return parseDirectiveCVFileChecksums();
+ 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_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);
+ }
+
+ 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 && getContext().getGenDwarfForAssembly() &&
+ 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);
+
+ // Since SrcMgr.FindLineNumber() is slow and messes up the SourceMgr's
+ // cache with the different Loc from the call above we save the last
+ // info we queried here with SrcMgr.FindLineNumber().
+ unsigned CppHashLocLineNo;
+ if (LastQueryIDLoc == CppHashInfo.Loc &&
+ LastQueryBuffer == CppHashInfo.Buf)
+ CppHashLocLineNo = LastQueryLine;
+ else {
+ CppHashLocLineNo =
+ SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
+ LastQueryLine = CppHashLocLineNo;
+ LastQueryIDLoc = CppHashInfo.Loc;
+ LastQueryBuffer = 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.
+ CppHashInfo.Loc = L;
+ CppHashInfo.Filename = Filename;
+ CppHashInfo.LineNumber = LineNumber;
+ CppHashInfo.Buf = CurBuffer;
+ return false;
+}
+
+/// \brief 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 ((Lexer.IsaAltMacroMode()) &&
+ (*(Token.getString().begin()) == '%') && 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 ((Lexer.IsaAltMacroMode()) &&
+ (*(Token.getString().begin()) == '<') &&
+ Token.is(AsmToken::String)) {
+ std::string Res;
+ altMacroString(Token.getStringContents(), Res);
+ OS << Res;
+ }
+ // 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 (Lexer.IsaAltMacroMode() && Lexer.is(AsmToken::Percent)) {
+ const MCExpr *AbsoluteExp;
+ int64_t Value;
+ /// Eat '%'
+ Lex();
+ if (parseExpression(AbsoluteExp, EndLoc))
+ return false;
+ if (!AbsoluteExp->evaluateAsAbsolute(Value))
+ 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 (Lexer.IsaAltMacroMode() && 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");
+}
+
+const MCAsmMacro *AsmParser::lookupMacro(StringRef Name) {
+ StringMap<MCAsmMacro>::iterator I = MacroMap.find(Name);
+ return (I == MacroMap.end()) ? nullptr : &I->getValue();
+}
+
+void AsmParser::defineMacro(StringRef Name, MCAsmMacro Macro) {
+ MacroMap.insert(std::make_pair(Name, std::move(Macro)));
+}
+
+void AsmParser::undefineMacro(StringRef Name) { MacroMap.erase(Name); }
+
+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;
+
+ SMLoc OffsetLoc = Lexer.getTok().getLoc();
+ int64_t OffsetValue;
+ // We can only deal with constant expressions at the moment.
+
+ if (parseExpression(Offset))
+ return true;
+
+ if (check(!Offset->evaluateAsAbsolute(OffsetValue), OffsetLoc,
+ "expression is not a constant value") ||
+ check(OffsetValue < 0, OffsetLoc, "expression is negative") ||
+ 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;
+
+ if (getStreamer().EmitRelocDirective(*Offset, Name, Expr, DirectiveLoc))
+ 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;
+}
+
+/// ParseDirectiveOctaValue
+/// ::= .octa [ hexconstant (, hexconstant)* ]
+
+bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) {
+ auto parseOp = [&]() -> bool {
+ if (checkForValidSection())
+ return true;
+ if (getTok().isNot(AsmToken::Integer) && getTok().isNot(AsmToken::BigNum))
+ return TokError("unknown token in expression");
+ SMLoc ExprLoc = getTok().getLoc();
+ APInt IntValue = getTok().getAPIntVal();
+ uint64_t hi, lo;
+ Lex();
+ if (!IntValue.isIntN(128))
+ return 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();
+ }
+ 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 (checkForValidSection() || 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 (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 [number] filename
+/// ::= .file number directory filename
+bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
+ // FIXME: I'm not sure what this is.
+ int64_t FileNumber = -1;
+ SMLoc FileNumberLoc = getLexer().getLoc();
+ if (getLexer().is(AsmToken::Integer)) {
+ FileNumber = getTok().getIntVal();
+ Lex();
+
+ if (FileNumber < 1)
+ return TokError("file number less than one");
+ }
+
+ std::string Path = getTok().getString();
+
+ // 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;
+ }
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.file' directive"))
+ return true;
+
+ if (FileNumber == -1)
+ getStreamer().EmitFileDirective(Filename);
+ else {
+ // If there is -g option as well as debug info from directive file,
+ // we turn off -g option, directly use the existing debug info instead.
+ if (getContext().getGenDwarfForAssembly())
+ getContext().setGenDwarfForAssembly(false);
+ else if (getStreamer().EmitDwarfFileDirective(FileNumber, Directory, Filename) ==
+ 0)
+ return Error(FileNumberLoc, "file number already allocated");
+ }
+
+ 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, 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
+bool AsmParser::parseDirectiveCVFile() {
+ SMLoc FileNumberLoc = getTok().getLoc();
+ int64_t FileNumber;
+ std::string Filename;
+
+ 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") ||
+ // Usually directory and filename are together, otherwise just
+ // directory. Allow the strings to have escaped octal character sequence.
+ parseEscapedString(Filename) ||
+ parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.cv_file' directive"))
+ return true;
+
+ if (!getStreamer().EmitCVFileDirective(FileNumber, Filename))
+ 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();
+ SMLoc Loc;
+ 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;
+}
+
+/// parseDirectiveCVStringTable
+/// ::= .cv_stringtable
+bool AsmParser::parseDirectiveCVStringTable() {
+ getStreamer().EmitCVStringTableDirective();
+ return false;
+}
+
+/// parseDirectiveCVFileChecksums
+/// ::= .cv_filechecksums
+bool AsmParser::parseDirectiveCVFileChecksums() {
+ getStreamer().EmitCVFileChecksumsDirective();
+ 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");
+ }
+
+ getStreamer().EmitCFIStartProc(!Simple.empty());
+ return false;
+}
+
+/// parseDirectiveCFIEndProc
+/// ::= .cfi_endproc
+bool AsmParser::parseDirectiveCFIEndProc() {
+ getStreamer().EmitCFIEndProc();
+ return false;
+}
+
+/// \brief 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;
+}
+
+/// 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");
+ if (Directive == ".altmacro")
+ getLexer().SetAltMacroMode(true);
+ else
+ getLexer().SetAltMacroMode(false);
+ 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 (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);
+ defineMacro(Name, MCAsmMacro(Name, Body, std::move(Parameters)));
+ 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 (!lookupMacro(Name))
+ return Error(DirectiveLoc, "macro '" + Name + "' is not defined");
+
+ undefineMacro(Name);
+ 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());
+ else
+ TheCondState.CondMet = (!Sym || Sym->isUndefined());
+ 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[".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_stringtable"] = DK_CV_STRINGTABLE;
+ DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
+ 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_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[".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;
+}
+
+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() == ".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)) {
+ 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;
+}
+
+// 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;
+ if (Kind == AOK_Delete)
+ continue;
+
+ 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_Imm:
+ OS << "$$" << AR.Val;
+ break;
+ case AOK_ImmPrefix:
+ 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_DotOperator:
+ // Insert the dot if the user omitted it.
+ OS.flush();
+ if (AsmStringIR.back() != '.')
+ OS << '.';
+ OS << AR.Val;
+ 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
+
+/// \brief 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
new file mode 100644
index 000000000000..b83d68d4fe20
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp
@@ -0,0 +1,832 @@
+//===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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::ParseDirectiveSecIdx>(".secidx");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
+
+ // 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 parseCOMDATType(COFF::COMDATType &Type);
+ bool ParseDirectiveLinkOnce(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::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;
+}
+
+/// ::= [ 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) {
+ 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);
+ return false;
+}
+
+bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
+ Lex();
+ getStreamer().EmitWinCFIEndProc();
+ return false;
+}
+
+bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
+ Lex();
+ getStreamer().EmitWinCFIStartChained();
+ return false;
+}
+
+bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
+ Lex();
+ getStreamer().EmitWinCFIEndChained();
+ return false;
+}
+
+bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
+ 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);
+ return false;
+}
+
+bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
+ Lex();
+ getStreamer().EmitWinEHHandlerData();
+ return false;
+}
+
+bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
+ unsigned Reg = 0;
+ if (ParseSEHRegisterNumber(Reg))
+ return true;
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ Lex();
+ getStreamer().EmitWinCFIPushReg(Reg);
+ return false;
+}
+
+bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
+ 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();
+ SMLoc startLoc = getLexer().getLoc();
+ if (getParser().parseAbsoluteExpression(Off))
+ return true;
+
+ if (Off & 0x0F)
+ return Error(startLoc, "offset is not a multiple of 16");
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ Lex();
+ getStreamer().EmitWinCFISetFrame(Reg, Off);
+ return false;
+}
+
+bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
+ int64_t Size;
+ SMLoc startLoc = getLexer().getLoc();
+ if (getParser().parseAbsoluteExpression(Size))
+ return true;
+
+ if (Size & 7)
+ return Error(startLoc, "size is not a multiple of 8");
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ Lex();
+ getStreamer().EmitWinCFIAllocStack(Size);
+ return false;
+}
+
+bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
+ 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();
+ SMLoc startLoc = getLexer().getLoc();
+ if (getParser().parseAbsoluteExpression(Off))
+ return true;
+
+ if (Off & 7)
+ return Error(startLoc, "size is not a multiple of 8");
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ Lex();
+ // FIXME: Err on %xmm* registers
+ getStreamer().EmitWinCFISaveReg(Reg, Off);
+ return false;
+}
+
+// FIXME: This method is inherently x86-specific. It should really be in the
+// x86 backend.
+bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
+ 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();
+ SMLoc startLoc = getLexer().getLoc();
+ if (getParser().parseAbsoluteExpression(Off))
+ return true;
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ if (Off & 0x0F)
+ return Error(startLoc, "offset is not a multiple of 16");
+
+ Lex();
+ // FIXME: Err on non-%xmm* registers
+ getStreamer().EmitWinCFISaveXMM(Reg, Off);
+ return false;
+}
+
+bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
+ 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);
+ return false;
+}
+
+bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
+ Lex();
+ getStreamer().EmitWinCFIEndProlog();
+ 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
new file mode 100644
index 000000000000..f4152a9067a0
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp
@@ -0,0 +1,1051 @@
+//===- DarwinAsmParser.cpp - Darwin (Mach-O) Assembly Parser --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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 {
+
+/// \brief 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 LastVersionMinDirective;
+
+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::parseVersionMin>(
+ ".watchos_version_min");
+ addDirectiveHandler<&DarwinAsmParser::parseVersionMin>(".tvos_version_min");
+ addDirectiveHandler<&DarwinAsmParser::parseVersionMin>(".ios_version_min");
+ addDirectiveHandler<&DarwinAsmParser::parseVersionMin>(
+ ".macosx_version_min");
+
+ LastVersionMinDirective = 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 parseVersionMin(StringRef, SMLoc);
+};
+
+} // 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;
+ 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()));
+ 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);
+
+ 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;
+}
+
+/// parseVersionMin
+/// ::= .ios_version_min major,minor[,update]
+/// ::= .macosx_version_min major,minor[,update]
+bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc) {
+ int64_t Major = 0, Minor = 0, Update = 0;
+ int Kind = StringSwitch<int>(Directive)
+ .Case(".watchos_version_min", MCVM_WatchOSVersionMin)
+ .Case(".tvos_version_min", MCVM_TvOSVersionMin)
+ .Case(".ios_version_min", MCVM_IOSVersionMin)
+ .Case(".macosx_version_min", MCVM_OSXVersionMin);
+ // Get the major version number.
+ if (getLexer().isNot(AsmToken::Integer))
+ return TokError("invalid OS major version number");
+ Major = getLexer().getTok().getIntVal();
+ if (Major > 65535 || Major <= 0)
+ return TokError("invalid OS major version number");
+ Lex();
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("minor OS version number required, comma expected");
+ Lex();
+ // Get the minor version number.
+ if (getLexer().isNot(AsmToken::Integer))
+ return TokError("invalid OS minor version number");
+ Minor = getLexer().getTok().getIntVal();
+ if (Minor > 255 || Minor < 0)
+ return TokError("invalid OS minor version number");
+ Lex();
+ // Get the update level, if specified
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("invalid update specifier, comma expected");
+ Lex();
+ if (getLexer().isNot(AsmToken::Integer))
+ return TokError("invalid OS update number");
+ Update = getLexer().getTok().getIntVal();
+ if (Update > 255 || Update < 0)
+ return TokError("invalid OS update number");
+ Lex();
+ }
+
+ const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
+ Triple::OSType ExpectedOS = Triple::UnknownOS;
+ switch ((MCVersionMinType)Kind) {
+ case MCVM_WatchOSVersionMin: ExpectedOS = Triple::WatchOS; break;
+ case MCVM_TvOSVersionMin: ExpectedOS = Triple::TvOS; break;
+ case MCVM_IOSVersionMin: ExpectedOS = Triple::IOS; break;
+ case MCVM_OSXVersionMin: ExpectedOS = Triple::MacOSX; break;
+ }
+ if (T.getOS() != ExpectedOS)
+ Warning(Loc, Directive + " should only be used for " +
+ Triple::getOSTypeName(ExpectedOS) + " targets");
+
+ if (LastVersionMinDirective.isValid()) {
+ Warning(Loc, "overriding previous version_min directive");
+ Note(LastVersionMinDirective, "previous definition is here");
+ }
+ LastVersionMinDirective = Loc;
+
+ // We've parsed a correct version specifier, so send it to the streamer.
+ getStreamer().EmitVersionMin((MCVersionMinType)Kind, Major, Minor, Update);
+
+ 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
new file mode 100644
index 000000000000..a407691b0bd1
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp
@@ -0,0 +1,848 @@
+//===- ELFAsmParser.cpp - ELF Assembly Parser -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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");
+ }
+
+ // 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);
+
+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 (true) {
+ 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 '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;
+}
+
+// FIXME: This is a work in progress.
+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 (getParser().parseIdentifier(GroupName))
+ return true;
+ if (L.is(AsmToken::Comma)) {
+ Lex();
+ StringRef Linkage;
+ if (getParser().parseIdentifier(Linkage))
+ return true;
+ 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 true;
+ 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;
+ StringRef UniqueStr;
+ MCSymbolELF *Associated = nullptr;
+ int64_t UniqueID = ~0;
+
+ // Set the defaults first.
+ if (hasPrefix(SectionName, ".rodata.") || SectionName == ".rodata1")
+ Flags |= ELF::SHF_ALLOC;
+ if (SectionName == ".fini" || SectionName == ".init" ||
+ hasPrefix(SectionName, ".text."))
+ Flags |= ELF::SHF_ALLOC | ELF::SHF_EXECINSTR;
+ 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;
+ 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.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 *Alias = getContext().getOrCreateSymbol(AliasName);
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+ const MCExpr *Value = MCSymbolRefExpr::create(Sym, getContext());
+
+ getStreamer().EmitAssignment(Alias, Value);
+ getStreamer().emitELFSymverDirective(Alias, 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;
+}
+
+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
new file mode 100644
index 000000000000..8f845ee1d76f
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp
@@ -0,0 +1,36 @@
+//===- MCAsmLexer.cpp - Abstract Asm Lexer Interface ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/SMLoc.h"
+
+using namespace llvm;
+
+MCAsmLexer::MCAsmLexer() : AltMacroMode(false) {
+ 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());
+}
diff --git a/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp
new file mode 100644
index 000000000000..ea36b3b9b3b2
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp
@@ -0,0 +1,145 @@
+//===-- MCAsmParser.cpp - Abstract Asm Parser Interface -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.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() : ShowParsedOperands(0) {}
+
+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::Hash) {
+ StringRef CommentStr = parseStringToEndOfStatement();
+ getLexer().Lex();
+ getLexer().UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
+ }
+ 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 token is EOL and current token is # this is an EOL comment.
+ if (getTok().getKind() == AsmToken::Hash && T == AsmToken::EndOfStatement)
+ Present = true;
+ 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) {
+ HadError = true;
+
+ 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
new file mode 100644
index 000000000000..031f473dc5fe
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp
@@ -0,0 +1,20 @@
+//===- MCAsmParserExtension.cpp - Asm Parser Hooks ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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
new file mode 100644
index 000000000000..64ac82a6c66f
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp
@@ -0,0 +1,29 @@
+//===-- MCTargetAsmParser.cpp - Target Assembly Parser --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCContext.h"
+
+using namespace llvm;
+
+MCTargetAsmParser::MCTargetAsmParser(MCTargetOptions const &MCOptions,
+ const MCSubtargetInfo &STI)
+ : MCOptions(MCOptions), STI(&STI) {}
+
+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/MCRegisterInfo.cpp b/contrib/llvm/lib/MC/MCRegisterInfo.cpp
new file mode 100644
index 000000000000..0f76c1838b51
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCRegisterInfo.cpp
@@ -0,0 +1,104 @@
+//===- MC/MCRegisterInfo.cpp - Target Register Description ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements MCRegisterInfo functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/ADT/DenseMap.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::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");
+ return I->second;
+}
diff --git a/contrib/llvm/lib/MC/MCSchedule.cpp b/contrib/llvm/lib/MC/MCSchedule.cpp
new file mode 100644
index 000000000000..f3919427bf05
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCSchedule.cpp
@@ -0,0 +1,34 @@
+//===- MCSchedule.cpp - Scheduling ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the default scheduling model.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCSchedule.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};
diff --git a/contrib/llvm/lib/MC/MCSection.cpp b/contrib/llvm/lib/MC/MCSection.cpp
new file mode 100644
index 000000000000..d141dd6627c4
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCSection.cpp
@@ -0,0 +1,101 @@
+//===- lib/MC/MCSection.cpp - Machine Code Section Representation ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCSection.h"
+#include "llvm/ADT/SmallVector.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),
+ 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
new file mode 100644
index 000000000000..72a7fc36a460
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCSectionCOFF.cpp
@@ -0,0 +1,111 @@
+//===- lib/MC/MCSectionCOFF.cpp - COFF Code Section Representation --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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;
+
+MCSectionCOFF::~MCSectionCOFF() = default; // anchor.
+
+// 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) {
+ OS << ",";
+ 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;
+ }
+ assert(COMDATSymbol);
+ 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
new file mode 100644
index 000000000000..2f4f61aa4d50
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCSectionELF.cpp
@@ -0,0 +1,191 @@
+//===- lib/MC/MCSectionELF.cpp - ELF Code Section Representation ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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;
+
+MCSectionELF::~MCSectionELF() = default; // anchor.
+
+// 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 (Arch == Triple::arm || Arch == Triple::armeb ||
+ Arch == Triple::thumb || Arch == Triple::thumbeb) {
+ if (Flags & ELF::SHF_ARM_PURECODE)
+ OS << 'y';
+ }
+
+ 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
+ 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
new file mode 100644
index 000000000000..f40237231a2f
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCSectionMachO.cpp
@@ -0,0 +1,282 @@
+//===- lib/MC/MCSectionMachO.cpp - MachO Code Section Representation ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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
new file mode 100644
index 000000000000..c61f28e129f5
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCSectionWasm.cpp
@@ -0,0 +1,97 @@
+//===- lib/MC/MCSectionWasm.cpp - Wasm Code Section Representation --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCSectionWasm.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+MCSectionWasm::~MCSectionWasm() {} // anchor.
+
+// 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 << ",\"";
+
+ // TODO: Print section flags.
+
+ 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/MCStreamer.cpp b/contrib/llvm/lib/MC/MCStreamer.cpp
new file mode 100644
index 000000000000..2bfb9a63eedb
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCStreamer.cpp
@@ -0,0 +1,878 @@
+//===- lib/MC/MCStreamer.cpp - Streaming Machine Code Output --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCStreamer.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::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {}
+
+MCStreamer::MCStreamer(MCContext &Ctx)
+ : Context(Ctx), CurrentWinFrameInfo(nullptr) {
+ SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>());
+}
+
+MCStreamer::~MCStreamer() {
+ for (unsigned i = 0; i < getNumWinFrameInfos(); ++i)
+ delete WinFrameInfos[i];
+}
+
+void MCStreamer::reset() {
+ DwarfFrameInfos.clear();
+ for (unsigned i = 0; i < getNumWinFrameInfos(); ++i)
+ delete WinFrameInfos[i];
+ WinFrameInfos.clear();
+ CurrentWinFrameInfo = nullptr;
+ SymbolOrdering.clear();
+ SectionStack.clear();
+ SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>());
+}
+
+raw_ostream &MCStreamer::GetCommentOS() {
+ // By default, discard comments.
+ return nulls();
+}
+
+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));
+}
+
+/// EmitULEB128Value - Special case of EmitULEB128Value that avoids the
+/// client having to pass in a MCExpr for constant integers.
+void MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned Padding) {
+ SmallString<128> Tmp;
+ raw_svector_ostream OSE(Tmp);
+ encodeULEB128(Value, OSE, Padding);
+ EmitBytes(OSE.str());
+}
+
+/// EmitSLEB128Value - 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) {
+ for (uint64_t i = 0, e = NumBytes; i != e; ++i)
+ EmitIntValue(FillValue, 1);
+}
+
+void MCStreamer::emitFill(uint64_t NumValues, int64_t Size, int64_t Expr) {
+ int64_t NonZeroSize = Size > 4 ? 4 : Size;
+ Expr &= ~0ULL >> (64 - NonZeroSize * 8);
+ for (uint64_t i = 0, e = NumValues; i != e; ++i) {
+ EmitIntValue(Expr, NonZeroSize);
+ if (NonZeroSize < Size)
+ EmitIntValue(0, Size - NonZeroSize);
+ }
+}
+
+/// The implementation in this class just redirects to emitFill.
+void MCStreamer::EmitZeros(uint64_t NumBytes) {
+ emitFill(NumBytes, 0);
+}
+
+unsigned MCStreamer::EmitDwarfFileDirective(unsigned FileNo,
+ StringRef Directory,
+ StringRef Filename, unsigned CUID) {
+ return getContext().getDwarfFile(Directory, Filename, FileNo, CUID);
+}
+
+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();
+}
+
+MCDwarfFrameInfo *MCStreamer::getCurrentDwarfFrameInfo() {
+ if (DwarfFrameInfos.empty())
+ return nullptr;
+ return &DwarfFrameInfos.back();
+}
+
+bool MCStreamer::hasUnfinishedDwarfFrameInfo() {
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ return CurFrame && !CurFrame->End;
+}
+
+void MCStreamer::EnsureValidDwarfFrame() {
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ if (!CurFrame || CurFrame->End)
+ report_fatal_error("No open frame");
+}
+
+bool MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename) {
+ return getContext().getCVContext().addFile(FileNo, Filename);
+}
+
+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) {
+ CodeViewContext &CVC = getContext().getCVContext();
+ MCCVFunctionInfo *FI = CVC.getCVFunctionInfo(FunctionId);
+ if (!FI)
+ return getContext().reportError(
+ Loc, "function id not introduced by .cv_func_id or .cv_inline_site_id");
+
+ // Track the section
+ if (FI->Section == nullptr)
+ FI->Section = getCurrentSectionOnly();
+ else if (FI->Section != getCurrentSectionOnly())
+ return getContext().reportError(
+ Loc,
+ "all .cv_loc directives for a function must be in the same section");
+
+ CVC.setCurrentCVLoc(FunctionId, FileNo, Line, Column, PrologueEnd, IsStmt);
+}
+
+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) {
+ if (hasUnfinishedDwarfFrameInfo())
+ report_fatal_error("Starting a 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() {
+ EnsureValidDwarfFrame();
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ 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() {
+ MCSymbol *Label = getContext().createTempSymbol("cfi", true);
+ EmitLabel(Label);
+ return Label;
+}
+
+MCSymbol *MCStreamer::EmitCFICommon() {
+ EnsureValidDwarfFrame();
+ return EmitCFILabel();
+}
+
+void MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) {
+ MCSymbol *Label = EmitCFICommon();
+ MCCFIInstruction Instruction =
+ MCCFIInstruction::createDefCfa(Label, Register, Offset);
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ CurFrame->Instructions.push_back(Instruction);
+ CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register);
+}
+
+void MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) {
+ MCSymbol *Label = EmitCFICommon();
+ MCCFIInstruction Instruction =
+ MCCFIInstruction::createDefCfaOffset(Label, Offset);
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ CurFrame->Instructions.push_back(Instruction);
+}
+
+void MCStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) {
+ MCSymbol *Label = EmitCFICommon();
+ MCCFIInstruction Instruction =
+ MCCFIInstruction::createAdjustCfaOffset(Label, Adjustment);
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ CurFrame->Instructions.push_back(Instruction);
+}
+
+void MCStreamer::EmitCFIDefCfaRegister(int64_t Register) {
+ MCSymbol *Label = EmitCFICommon();
+ MCCFIInstruction Instruction =
+ MCCFIInstruction::createDefCfaRegister(Label, Register);
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ CurFrame->Instructions.push_back(Instruction);
+ CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register);
+}
+
+void MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) {
+ MCSymbol *Label = EmitCFICommon();
+ MCCFIInstruction Instruction =
+ MCCFIInstruction::createOffset(Label, Register, Offset);
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ CurFrame->Instructions.push_back(Instruction);
+}
+
+void MCStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) {
+ MCSymbol *Label = EmitCFICommon();
+ MCCFIInstruction Instruction =
+ MCCFIInstruction::createRelOffset(Label, Register, Offset);
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ CurFrame->Instructions.push_back(Instruction);
+}
+
+void MCStreamer::EmitCFIPersonality(const MCSymbol *Sym,
+ unsigned Encoding) {
+ EnsureValidDwarfFrame();
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ CurFrame->Personality = Sym;
+ CurFrame->PersonalityEncoding = Encoding;
+}
+
+void MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
+ EnsureValidDwarfFrame();
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ CurFrame->Lsda = Sym;
+ CurFrame->LsdaEncoding = Encoding;
+}
+
+void MCStreamer::EmitCFIRememberState() {
+ MCSymbol *Label = EmitCFICommon();
+ MCCFIInstruction Instruction = MCCFIInstruction::createRememberState(Label);
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ CurFrame->Instructions.push_back(Instruction);
+}
+
+void MCStreamer::EmitCFIRestoreState() {
+ // FIXME: Error if there is no matching cfi_remember_state.
+ MCSymbol *Label = EmitCFICommon();
+ MCCFIInstruction Instruction = MCCFIInstruction::createRestoreState(Label);
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ CurFrame->Instructions.push_back(Instruction);
+}
+
+void MCStreamer::EmitCFISameValue(int64_t Register) {
+ MCSymbol *Label = EmitCFICommon();
+ MCCFIInstruction Instruction =
+ MCCFIInstruction::createSameValue(Label, Register);
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ CurFrame->Instructions.push_back(Instruction);
+}
+
+void MCStreamer::EmitCFIRestore(int64_t Register) {
+ MCSymbol *Label = EmitCFICommon();
+ MCCFIInstruction Instruction =
+ MCCFIInstruction::createRestore(Label, Register);
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ CurFrame->Instructions.push_back(Instruction);
+}
+
+void MCStreamer::EmitCFIEscape(StringRef Values) {
+ MCSymbol *Label = EmitCFICommon();
+ MCCFIInstruction Instruction = MCCFIInstruction::createEscape(Label, Values);
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ CurFrame->Instructions.push_back(Instruction);
+}
+
+void MCStreamer::EmitCFIGnuArgsSize(int64_t Size) {
+ MCSymbol *Label = EmitCFICommon();
+ MCCFIInstruction Instruction =
+ MCCFIInstruction::createGnuArgsSize(Label, Size);
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ CurFrame->Instructions.push_back(Instruction);
+}
+
+void MCStreamer::EmitCFISignalFrame() {
+ EnsureValidDwarfFrame();
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ CurFrame->IsSignalFrame = true;
+}
+
+void MCStreamer::EmitCFIUndefined(int64_t Register) {
+ MCSymbol *Label = EmitCFICommon();
+ MCCFIInstruction Instruction =
+ MCCFIInstruction::createUndefined(Label, Register);
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ CurFrame->Instructions.push_back(Instruction);
+}
+
+void MCStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) {
+ MCSymbol *Label = EmitCFICommon();
+ MCCFIInstruction Instruction =
+ MCCFIInstruction::createRegister(Label, Register1, Register2);
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ CurFrame->Instructions.push_back(Instruction);
+}
+
+void MCStreamer::EmitCFIWindowSave() {
+ MCSymbol *Label = EmitCFICommon();
+ MCCFIInstruction Instruction =
+ MCCFIInstruction::createWindowSave(Label);
+ MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+ CurFrame->Instructions.push_back(Instruction);
+}
+
+void MCStreamer::EnsureValidWinFrameInfo() {
+ const MCAsmInfo *MAI = Context.getAsmInfo();
+ if (!MAI->usesWindowsCFI())
+ report_fatal_error(".seh_* directives are not supported on this target");
+ if (!CurrentWinFrameInfo || CurrentWinFrameInfo->End)
+ report_fatal_error("No open Win64 EH frame function!");
+}
+
+void MCStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) {
+ const MCAsmInfo *MAI = Context.getAsmInfo();
+ if (!MAI->usesWindowsCFI())
+ report_fatal_error(".seh_* directives are not supported on this target");
+ if (CurrentWinFrameInfo && !CurrentWinFrameInfo->End)
+ report_fatal_error("Starting a function before ending the previous one!");
+
+ MCSymbol *StartProc = EmitCFILabel();
+
+ WinFrameInfos.push_back(new WinEH::FrameInfo(Symbol, StartProc));
+ CurrentWinFrameInfo = WinFrameInfos.back();
+ CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
+}
+
+void MCStreamer::EmitWinCFIEndProc() {
+ EnsureValidWinFrameInfo();
+ if (CurrentWinFrameInfo->ChainedParent)
+ report_fatal_error("Not all chained regions terminated!");
+
+ MCSymbol *Label = EmitCFILabel();
+ CurrentWinFrameInfo->End = Label;
+}
+
+void MCStreamer::EmitWinCFIStartChained() {
+ EnsureValidWinFrameInfo();
+
+ MCSymbol *StartProc = EmitCFILabel();
+
+ WinFrameInfos.push_back(new WinEH::FrameInfo(CurrentWinFrameInfo->Function,
+ StartProc, CurrentWinFrameInfo));
+ CurrentWinFrameInfo = WinFrameInfos.back();
+ CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
+}
+
+void MCStreamer::EmitWinCFIEndChained() {
+ EnsureValidWinFrameInfo();
+ if (!CurrentWinFrameInfo->ChainedParent)
+ report_fatal_error("End of a chained region outside a chained region!");
+
+ MCSymbol *Label = EmitCFILabel();
+
+ CurrentWinFrameInfo->End = Label;
+ CurrentWinFrameInfo =
+ const_cast<WinEH::FrameInfo *>(CurrentWinFrameInfo->ChainedParent);
+}
+
+void MCStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind,
+ bool Except) {
+ EnsureValidWinFrameInfo();
+ if (CurrentWinFrameInfo->ChainedParent)
+ report_fatal_error("Chained unwind areas can't have handlers!");
+ CurrentWinFrameInfo->ExceptionHandler = Sym;
+ if (!Except && !Unwind)
+ report_fatal_error("Don't know what kind of handler this is!");
+ if (Unwind)
+ CurrentWinFrameInfo->HandlesUnwind = true;
+ if (Except)
+ CurrentWinFrameInfo->HandlesExceptions = true;
+}
+
+void MCStreamer::EmitWinEHHandlerData() {
+ EnsureValidWinFrameInfo();
+ if (CurrentWinFrameInfo->ChainedParent)
+ report_fatal_error("Chained unwind areas can't have handlers!");
+}
+
+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);
+ 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();
+
+ return Context.getAssociativeCOFFSection(cast<MCSectionCOFF>(MainCFISec),
+ 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) {
+ EnsureValidWinFrameInfo();
+
+ MCSymbol *Label = EmitCFILabel();
+
+ WinEH::Instruction Inst = Win64EH::Instruction::PushNonVol(Label, Register);
+ CurrentWinFrameInfo->Instructions.push_back(Inst);
+}
+
+void MCStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset) {
+ EnsureValidWinFrameInfo();
+ if (CurrentWinFrameInfo->LastFrameInst >= 0)
+ report_fatal_error("Frame register and offset already specified!");
+ if (Offset & 0x0F)
+ report_fatal_error("Misaligned frame pointer offset!");
+ if (Offset > 240)
+ report_fatal_error("Frame offset must be less than or equal to 240!");
+
+ MCSymbol *Label = EmitCFILabel();
+
+ WinEH::Instruction Inst =
+ Win64EH::Instruction::SetFPReg(Label, Register, Offset);
+ CurrentWinFrameInfo->LastFrameInst = CurrentWinFrameInfo->Instructions.size();
+ CurrentWinFrameInfo->Instructions.push_back(Inst);
+}
+
+void MCStreamer::EmitWinCFIAllocStack(unsigned Size) {
+ EnsureValidWinFrameInfo();
+ if (Size == 0)
+ report_fatal_error("Allocation size must be non-zero!");
+ if (Size & 7)
+ report_fatal_error("Misaligned stack allocation!");
+
+ MCSymbol *Label = EmitCFILabel();
+
+ WinEH::Instruction Inst = Win64EH::Instruction::Alloc(Label, Size);
+ CurrentWinFrameInfo->Instructions.push_back(Inst);
+}
+
+void MCStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset) {
+ EnsureValidWinFrameInfo();
+ if (Offset & 7)
+ report_fatal_error("Misaligned saved register offset!");
+
+ MCSymbol *Label = EmitCFILabel();
+
+ WinEH::Instruction Inst =
+ Win64EH::Instruction::SaveNonVol(Label, Register, Offset);
+ CurrentWinFrameInfo->Instructions.push_back(Inst);
+}
+
+void MCStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) {
+ EnsureValidWinFrameInfo();
+ if (Offset & 0x0F)
+ report_fatal_error("Misaligned saved vector register offset!");
+
+ MCSymbol *Label = EmitCFILabel();
+
+ WinEH::Instruction Inst =
+ Win64EH::Instruction::SaveXMM(Label, Register, Offset);
+ CurrentWinFrameInfo->Instructions.push_back(Inst);
+}
+
+void MCStreamer::EmitWinCFIPushFrame(bool Code) {
+ EnsureValidWinFrameInfo();
+ if (!CurrentWinFrameInfo->Instructions.empty())
+ report_fatal_error("If present, PushMachFrame must be the first UOP");
+
+ MCSymbol *Label = EmitCFILabel();
+
+ WinEH::Instruction Inst = Win64EH::Instruction::PushMachFrame(Label, Code);
+ CurrentWinFrameInfo->Instructions.push_back(Inst);
+}
+
+void MCStreamer::EmitWinCFIEndProlog() {
+ EnsureValidWinFrameInfo();
+
+ MCSymbol *Label = EmitCFILabel();
+
+ CurrentWinFrameInfo->PrologEnd = Label;
+}
+
+void MCStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
+}
+
+void MCStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
+}
+
+void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_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) {
+ errs() << "EmitRawText called on an MCStreamer that doesn't support it, "
+ " something must not be fully mc'ized\n";
+ abort();
+}
+
+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)
+ report_fatal_error("Unfinished frame!");
+
+ 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 &STI,
+ bool) {
+ // 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::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(MCSymbol *Alias,
+ 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;
+}
diff --git a/contrib/llvm/lib/MC/MCSubtargetInfo.cpp b/contrib/llvm/lib/MC/MCSubtargetInfo.cpp
new file mode 100644
index 000000000000..385cdcc62320
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCSubtargetInfo.cpp
@@ -0,0 +1,113 @@
+//===- MCSubtargetInfo.cpp - Subtarget Information ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+
+using namespace llvm;
+
+static FeatureBitset getFeatures(StringRef CPU, StringRef FS,
+ ArrayRef<SubtargetFeatureKV> ProcDesc,
+ ArrayRef<SubtargetFeatureKV> ProcFeatures) {
+ SubtargetFeatures Features(FS);
+ return Features.getFeatureBits(CPU, ProcDesc, ProcFeatures);
+}
+
+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<SubtargetFeatureKV> PD,
+ const SubtargetInfoKV *ProcSched, 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),
+ ProcSchedModels(ProcSched), WriteProcResTable(WPR), WriteLatencyTable(WL),
+ ReadAdvanceTable(RA), Stages(IS), OperandCycles(OC), ForwardingPaths(FP) {
+ InitMCProcessorInfo(CPU, FS);
+}
+
+/// ToggleFeature - Toggle a feature and returns the re-computed feature
+/// bits. This version does not change the implied bits.
+FeatureBitset MCSubtargetInfo::ToggleFeature(uint64_t FB) {
+ FeatureBits.flip(FB);
+ return FeatureBits;
+}
+
+FeatureBitset MCSubtargetInfo::ToggleFeature(const FeatureBitset &FB) {
+ FeatureBits ^= FB;
+ return FeatureBits;
+}
+
+/// ToggleFeature - Toggle a feature and returns the re-computed feature
+/// bits. This version will also change all implied bits.
+FeatureBitset MCSubtargetInfo::ToggleFeature(StringRef FS) {
+ SubtargetFeatures::ToggleFeature(FeatureBits, FS, ProcFeatures);
+ return FeatureBits;
+}
+
+FeatureBitset MCSubtargetInfo::ApplyFeatureFlag(StringRef FS) {
+ SubtargetFeatures::ApplyFeatureFlag(FeatureBits, FS, ProcFeatures);
+ return FeatureBits;
+}
+
+const MCSchedModel &MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const {
+ assert(ProcSchedModels && "Processor machine model not available!");
+
+ ArrayRef<SubtargetInfoKV> SchedModels(ProcSchedModels, ProcDesc.size());
+
+ assert(std::is_sorted(SchedModels.begin(), SchedModels.end(),
+ [](const SubtargetInfoKV &LHS, const SubtargetInfoKV &RHS) {
+ return strcmp(LHS.Key, RHS.Key) < 0;
+ }) &&
+ "Processor machine model table is not sorted");
+
+ // Find entry
+ auto Found =
+ std::lower_bound(SchedModels.begin(), SchedModels.end(), CPU);
+ if (Found == SchedModels.end() || StringRef(Found->Key) != CPU) {
+ 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(Found->Value && "Missing processor SchedModel value");
+ return *(const MCSchedModel *)Found->Value;
+}
+
+InstrItineraryData
+MCSubtargetInfo::getInstrItineraryForCPU(StringRef CPU) const {
+ const MCSchedModel SchedModel = getSchedModelForCPU(CPU);
+ return InstrItineraryData(SchedModel, Stages, OperandCycles, ForwardingPaths);
+}
+
+/// Initialize an InstrItineraryData instance.
+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
new file mode 100644
index 000000000000..9abaaef2fe84
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCSymbol.cpp
@@ -0,0 +1,88 @@
+//===- lib/MC/MCSymbol.cpp - MCSymbol implementation ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/ADT/StringRef.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
new file mode 100644
index 000000000000..67449eb6dcf9
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCSymbolELF.cpp
@@ -0,0 +1,205 @@
+//===- lib/MC/MCSymbolELF.cpp ---------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCSymbolELF.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCAssembler.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 = (getFlags() & (0x3 << ELF_STB_Shift)) >> ELF_STB_Shift;
+ 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 = (getFlags() & (0x7 << ELF_STT_Shift)) >> ELF_STT_Shift;
+ 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 = (getFlags() & (0x3 << ELF_STV_Shift)) >> ELF_STV_Shift;
+ assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL ||
+ Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED);
+ 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 = (getFlags() & (0x7 << ELF_STO_Shift)) >> ELF_STO_Shift;
+ 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
new file mode 100644
index 000000000000..b85e53db5d61
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCTargetOptions.cpp
@@ -0,0 +1,25 @@
+//===- lib/MC/MCTargetOptions.cpp - MC Target Options ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/ADT/StringRef.h"
+
+using namespace llvm;
+
+MCTargetOptions::MCTargetOptions()
+ : SanitizeAddress(false), 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
new file mode 100644
index 000000000000..32a6adbf224e
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCValue.cpp
@@ -0,0 +1,61 @@
+//===- lib/MC/MCValue.cpp - MCValue implementation ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCValue.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
new file mode 100644
index 000000000000..301f30d4f6ec
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCWasmObjectTargetWriter.cpp
@@ -0,0 +1,21 @@
+//===-- MCWasmObjectTargetWriter.cpp - Wasm Target Writer Subclass --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCValue.h"
+#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
new file mode 100644
index 000000000000..02fa070f0c57
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCWasmStreamer.cpp
@@ -0,0 +1,228 @@
+//===- lib/MC/MCWasmStreamer.cpp - Wasm Object Output ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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/MCAsmInfo.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/MCObjectFileInfo.h"
+#include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/MC/MCObjectWriter.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() {}
+
+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]);
+ }
+ DF->setHasInstructions(true);
+ 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 = static_cast<const MCSectionWasm *>(Section);
+ const MCSymbol *Grp = SectionWasm->getGroup();
+ if (Grp)
+ Asm.registerSymbol(*Grp);
+
+ this->MCObjectStreamer::ChangeSection(Section, Subsection);
+}
+
+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_Hidden:
+ return false;
+
+ 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->setIsFunction(true);
+ break;
+
+ case MCSA_ELF_TypeObject:
+ Symbol->setIsFunction(false);
+ 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) {
+ MCSection *Comment = getAssembler().getContext().getWasmSection(
+ ".comment", 0, 0);
+ PushSection();
+ SwitchSection(Comment);
+ if (!SeenIdent) {
+ EmitIntValue(0, 1);
+ SeenIdent = true;
+ }
+ EmitBytes(IdentString);
+ EmitIntValue(0, 1);
+ PopSection();
+}
+
+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(true);
+ DF->getContents().append(Code.begin(), Code.end());
+}
+
+void MCWasmStreamer::FinishImpl() {
+ EmitFrames(nullptr);
+
+ this->MCObjectStreamer::FinishImpl();
+}
+
+MCStreamer *llvm::createWasmStreamer(MCContext &Context, MCAsmBackend &MAB,
+ raw_pwrite_stream &OS, MCCodeEmitter *CE,
+ bool RelaxAll) {
+ MCWasmStreamer *S = new MCWasmStreamer(Context, MAB, OS, 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) {
+ 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
new file mode 100644
index 000000000000..fdc4c10cd6ce
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCWin64EH.cpp
@@ -0,0 +1,246 @@
+//===- lib/MC/MCWin64EH.cpp - MCWin64EH implementation --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/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/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)) {
+ 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)) {
+ 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 (WinEH::FrameInfo *CFI : Streamer.getWinFrameInfos()) {
+ MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
+ Streamer.SwitchSection(XData);
+ ::EmitUnwindInfo(Streamer, CFI);
+ }
+
+ // Now emit RUNTIME_FUNCTION entries.
+ for (WinEH::FrameInfo *CFI : Streamer.getWinFrameInfos()) {
+ MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
+ Streamer.SwitchSection(PData);
+ EmitRuntimeFunction(Streamer, CFI);
+ }
+}
+
+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);
+}
+
diff --git a/contrib/llvm/lib/MC/MCWinCOFFStreamer.cpp b/contrib/llvm/lib/MC/MCWinCOFFStreamer.cpp
new file mode 100644
index 000000000000..bf341bb1f451
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCWinCOFFStreamer.cpp
@@ -0,0 +1,298 @@
+//===- llvm/MC/MCWinCOFFStreamer.cpp --------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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/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, MCAsmBackend &MAB,
+ MCCodeEmitter &CE, raw_pwrite_stream &OS)
+ : MCObjectStreamer(Context, MAB, OS, &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->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 MCSafeSEHFragment(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::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::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
+ unsigned ByteAlignment) {
+ auto *Symbol = cast<MCSymbolCOFF>(S);
+
+ const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
+ if (T.isKnownWindowsMSVCEnvironment()) {
+ 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.isKnownWindowsMSVCEnvironment() && 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();
+ getAssembler().registerSection(*Section);
+ if (Section->getAlignment() < ByteAlignment)
+ Section->setAlignment(ByteAlignment);
+
+ getAssembler().registerSymbol(*Symbol);
+ Symbol->setExternal(false);
+
+ if (ByteAlignment != 1)
+ new MCAlignFragment(ByteAlignment, /*Value=*/0, /*ValueSize=*/0,
+ ByteAlignment, Section);
+
+ MCFillFragment *Fragment = new MCFillFragment(
+ /*Value=*/0, Size, Section);
+ Symbol->setFragment(Fragment);
+}
+
+void MCWinCOFFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
+ uint64_t Size, unsigned ByteAlignment) {
+ 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() {
+ 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
new file mode 100644
index 000000000000..a5d0f5a2cb75
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCWinEH.cpp
@@ -0,0 +1,26 @@
+//===- lib/MC/MCWinEH.cpp - Windows EH implementation ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/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/MachObjectWriter.cpp b/contrib/llvm/lib/MC/MachObjectWriter.cpp
new file mode 100644
index 000000000000..c4e7cdbe095e
--- /dev/null
+++ b/contrib/llvm/lib/MC/MachObjectWriter.cpp
@@ -0,0 +1,1001 @@
+//===- lib/MC/MachObjectWriter.cpp - Mach-O File Writer -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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/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 = getStream().tell();
+ (void) Start;
+
+ write32(is64Bit() ? MachO::MH_MAGIC_64 : MachO::MH_MAGIC);
+
+ write32(TargetObjectWriter->getCPUType());
+ write32(TargetObjectWriter->getCPUSubtype());
+
+ write32(Type);
+ write32(NumLoadCommands);
+ write32(LoadCommandsSize);
+ write32(Flags);
+ if (is64Bit())
+ write32(0); // reserved
+
+ assert(
+ getStream().tell() - Start ==
+ (is64Bit() ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header)));
+}
+
+/// 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 = getStream().tell();
+ (void) Start;
+
+ unsigned SegmentLoadCommandSize =
+ is64Bit() ? sizeof(MachO::segment_command_64):
+ sizeof(MachO::segment_command);
+ write32(is64Bit() ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT);
+ write32(SegmentLoadCommandSize +
+ NumSections * (is64Bit() ? sizeof(MachO::section_64) :
+ sizeof(MachO::section)));
+
+ assert(Name.size() <= 16);
+ writeBytes(Name, 16);
+ if (is64Bit()) {
+ write64(VMAddr); // vmaddr
+ write64(VMSize); // vmsize
+ write64(SectionDataStartOffset); // file offset
+ write64(SectionDataSize); // file size
+ } else {
+ write32(VMAddr); // vmaddr
+ write32(VMSize); // vmsize
+ write32(SectionDataStartOffset); // file offset
+ write32(SectionDataSize); // file size
+ }
+ // maxprot
+ write32(MaxProt);
+ // initprot
+ write32(InitProt);
+ write32(NumSections);
+ write32(0); // flags
+
+ assert(getStream().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 = getStream().tell();
+ (void) Start;
+
+ writeBytes(Section.getSectionName(), 16);
+ writeBytes(Section.getSegmentName(), 16);
+ if (is64Bit()) {
+ write64(VMAddr); // address
+ write64(SectionSize); // size
+ } else {
+ write32(VMAddr); // address
+ write32(SectionSize); // size
+ }
+ write32(FileOffset);
+
+ assert(isPowerOf2_32(Section.getAlignment()) && "Invalid alignment!");
+ write32(Log2_32(Section.getAlignment()));
+ write32(NumRelocations ? RelocationsStart : 0);
+ write32(NumRelocations);
+ write32(Flags);
+ write32(IndirectSymBase.lookup(&Sec)); // reserved1
+ write32(Section.getStubSize()); // reserved2
+ if (is64Bit())
+ write32(0); // reserved3
+
+ assert(getStream().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 = getStream().tell();
+ (void) Start;
+
+ write32(MachO::LC_SYMTAB);
+ write32(sizeof(MachO::symtab_command));
+ write32(SymbolOffset);
+ write32(NumSymbols);
+ write32(StringTableOffset);
+ write32(StringTableSize);
+
+ assert(getStream().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 = getStream().tell();
+ (void) Start;
+
+ write32(MachO::LC_DYSYMTAB);
+ write32(sizeof(MachO::dysymtab_command));
+ write32(FirstLocalSymbol);
+ write32(NumLocalSymbols);
+ write32(FirstExternalSymbol);
+ write32(NumExternalSymbols);
+ write32(FirstUndefinedSymbol);
+ write32(NumUndefinedSymbols);
+ write32(0); // tocoff
+ write32(0); // ntoc
+ write32(0); // modtaboff
+ write32(0); // nmodtab
+ write32(0); // extrefsymoff
+ write32(0); // nextrefsyms
+ write32(IndirectSymbolOffset);
+ write32(NumIndirectSymbols);
+ write32(0); // extreloff
+ write32(0); // nextrel
+ write32(0); // locreloff
+ write32(0); // nlocrel
+
+ assert(getStream().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)
+
+ write32(MSD.StringIndex);
+ write8(Type);
+ write8(SectionIndex);
+
+ // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
+ // value.
+ bool EncodeAsAltEntry =
+ IsAlias && cast<MCSymbolMachO>(OrigSymbol).isAltEntry();
+ write16(cast<MCSymbolMachO>(Symbol)->getEncodedFlags(EncodeAsAltEntry));
+ if (is64Bit())
+ write64(Address);
+ else
+ write32(Address);
+}
+
+void MachObjectWriter::writeLinkeditLoadCommand(uint32_t Type,
+ uint32_t DataOffset,
+ uint32_t DataSize) {
+ uint64_t Start = getStream().tell();
+ (void) Start;
+
+ write32(Type);
+ write32(sizeof(MachO::linkedit_data_command));
+ write32(DataOffset);
+ write32(DataSize);
+
+ assert(getStream().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 = getStream().tell();
+ (void) Start;
+
+ write32(MachO::LC_LINKER_OPTION);
+ write32(Size);
+ write32(Options.size());
+ uint64_t BytesWritten = sizeof(MachO::linker_option_command);
+ for (const std::string &Option : Options) {
+ // Write each string, including the null byte.
+ writeBytes(Option, Option.size() + 1);
+ BytesWritten += Option.size() + 1;
+ }
+
+ // Pad to a multiple of the pointer size.
+ writeBytes("", OffsetToAlignment(BytesWritten, is64Bit() ? 8 : 4));
+
+ assert(getStream().tell() - Start == Size);
+}
+
+void MachObjectWriter::recordRelocation(MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup, MCValue Target,
+ bool &IsPCRel, uint64_t &FixedValue) {
+ 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.
+ std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
+ std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end());
+
+ // 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 (IsLittleEndian)
+ 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;
+}
+
+void MachObjectWriter::writeObject(MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
+ // Compute symbol table information and bind symbol indices.
+ computeSymbolTable(Asm, LocalSymbolData, ExternalSymbolData,
+ UndefinedSymbolData);
+
+ unsigned NumSections = Asm.size();
+ const MCAssembler::VersionMinInfoType &VersionInfo =
+ Layout.getAssembler().getVersionMinInfo();
+
+ // 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;
+ 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) {
+ assert(VersionInfo.Update < 256 && "unencodable update target version");
+ assert(VersionInfo.Minor < 256 && "unencodable minor target version");
+ assert(VersionInfo.Major < 65536 && "unencodable major target version");
+ uint32_t EncodedVersion = VersionInfo.Update | (VersionInfo.Minor << 8) |
+ (VersionInfo.Major << 16);
+ MachO::LoadCommandType LCType;
+ switch (VersionInfo.Kind) {
+ case MCVM_OSXVersionMin:
+ LCType = MachO::LC_VERSION_MIN_MACOSX;
+ break;
+ case MCVM_IOSVersionMin:
+ LCType = MachO::LC_VERSION_MIN_IPHONEOS;
+ break;
+ case MCVM_TvOSVersionMin:
+ LCType = MachO::LC_VERSION_MIN_TVOS;
+ break;
+ case MCVM_WatchOSVersionMin:
+ LCType = MachO::LC_VERSION_MIN_WATCHOS;
+ break;
+ }
+ write32(LCType);
+ write32(sizeof(MachO::version_min_command));
+ write32(EncodedVersion);
+ write32(0); // reserved.
+ }
+
+ // 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(&Sec, Layout);
+
+ uint64_t Pad = getPaddingSize(&Sec, Layout);
+ WriteZeros(Pad);
+ }
+
+ // Write the extra padding.
+ WriteZeros(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())) {
+ write32(Rel.MRE.r_word0);
+ write32(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 = getSymbolAddress(*Data->End, Layout);
+ DEBUG(dbgs() << "data in code region-- kind: " << Data->Kind
+ << " start: " << Start << "(" << Data->Start->getName() << ")"
+ << " end: " << End << "(" << Data->End->getName() << ")"
+ << " size: " << End - Start
+ << "\n");
+ write32(Start);
+ write16(End - Start);
+ write16(Data->Kind);
+ }
+
+ // Write out the loh commands, if there is one.
+ if (LOHSize) {
+#ifndef NDEBUG
+ unsigned Start = getStream().tell();
+#endif
+ Asm.getLOHContainer().emit(*this, Layout);
+ // Pad to a multiple of the pointer size.
+ writeBytes("", OffsetToAlignment(LOHRawSize, is64Bit() ? 8 : 4));
+ assert(getStream().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;
+ write32(Flags);
+ continue;
+ }
+ }
+
+ write32(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(getStream());
+ }
+}
+
+MCObjectWriter *llvm::createMachObjectWriter(MCMachObjectTargetWriter *MOTW,
+ raw_pwrite_stream &OS,
+ bool IsLittleEndian) {
+ return new MachObjectWriter(MOTW, OS, IsLittleEndian);
+}
diff --git a/contrib/llvm/lib/MC/StringTableBuilder.cpp b/contrib/llvm/lib/MC/StringTableBuilder.cpp
new file mode 100644
index 000000000000..6025a20a9c19
--- /dev/null
+++ b/contrib/llvm/lib/MC/StringTableBuilder.cpp
@@ -0,0 +1,190 @@
+//===- StringTableBuilder.cpp - String table building utility -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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:
+ 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 multikey_qsort(StringPair **Begin, StringPair **End, int Pos) {
+tailcall:
+ if (End - Begin <= 1)
+ return;
+
+ // Partition items. Items in [Begin, P) are greater than the pivot,
+ // [P, Q) are the same as the pivot, and [Q, End) are less than the pivot.
+ int Pivot = charTailAt(*Begin, Pos);
+ StringPair **P = Begin;
+ StringPair **Q = End;
+ for (StringPair **R = Begin + 1; R < Q;) {
+ int C = charTailAt(*R, Pos);
+ if (C > Pivot)
+ std::swap(*P++, *R++);
+ else if (C < Pivot)
+ std::swap(*--Q, *R);
+ else
+ R++;
+ }
+
+ multikey_qsort(Begin, P, Pos);
+ multikey_qsort(Q, End, Pos);
+ if (Pivot != -1) {
+ // qsort(P, Q, Pos + 1), but with tail call optimization.
+ Begin = P;
+ End = Q;
+ ++Pos;
+ goto tailcall;
+ }
+}
+
+void StringTableBuilder::finalize() {
+ 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);
+
+ if (!Strings.empty()) {
+ // If we're optimizing, sort by name. If not, sort by previously assigned
+ // offset.
+ multikey_qsort(&Strings[0], &Strings[0] + Strings.size(), 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.
+}
+
+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
new file mode 100644
index 000000000000..b68e88ca5725
--- /dev/null
+++ b/contrib/llvm/lib/MC/SubtargetFeature.cpp
@@ -0,0 +1,279 @@
+//===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file Implements the SubtargetFeature interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/SubtargetFeature.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <iterator>
+#include <string>
+#include <vector>
+
+using namespace llvm;
+
+/// Determine if a feature has a flag; '+' or '-'
+static inline bool hasFlag(StringRef Feature) {
+ assert(!Feature.empty() && "Empty string");
+ // Get first character
+ char Ch = Feature[0];
+ // Check if first character is '+' or '-' flag
+ return Ch == '+' || Ch =='-';
+}
+
+/// Return string stripped of flag.
+static inline std::string StripFlag(StringRef Feature) {
+ return hasFlag(Feature) ? Feature.substr(1) : Feature;
+}
+
+/// Return true if enable flag; '+'.
+static inline bool isEnabled(StringRef Feature) {
+ assert(!Feature.empty() && "Empty string");
+ // Get first character
+ char Ch = Feature[0];
+ // Check if first character is '+' for enabled
+ return Ch == '+';
+}
+
+/// Splits a string of comma separated items in to a vector of strings.
+static void 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());
+}
+
+/// Find KV in array using binary search.
+static const SubtargetFeatureKV *Find(StringRef S,
+ ArrayRef<SubtargetFeatureKV> A) {
+ // Binary search the array
+ auto F = std::lower_bound(A.begin(), A.end(), S);
+ // If not found then return NULL
+ if (F == A.end() || StringRef(F->Key) != S) return nullptr;
+ // Return the found array item
+ return F;
+}
+
+/// Return the length of the longest entry in the table.
+static size_t getLongestEntryLength(ArrayRef<SubtargetFeatureKV> Table) {
+ size_t MaxLen = 0;
+ for (auto &I : Table)
+ MaxLen = std::max(MaxLen, std::strlen(I.Key));
+ return MaxLen;
+}
+
+/// Display help for feature choices.
+static void Help(ArrayRef<SubtargetFeatureKV> CPUTable,
+ ArrayRef<SubtargetFeatureKV> FeatTable) {
+ // 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 - %s.\n", MaxCPULen, CPU.Key, CPU.Desc);
+ 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";
+}
+
+SubtargetFeatures::SubtargetFeatures(StringRef Initial) {
+ // Break up string into separate features
+ Split(Features, Initial);
+}
+
+std::string SubtargetFeatures::getString() const {
+ return join(Features.begin(), Features.end(), ",");
+}
+
+/// For each feature that is (transitively) implied by this feature, set it.
+static
+void SetImpliedBits(FeatureBitset &Bits, const SubtargetFeatureKV &FeatureEntry,
+ ArrayRef<SubtargetFeatureKV> FeatureTable) {
+ for (const SubtargetFeatureKV &FE : FeatureTable) {
+ if (FeatureEntry.Value == FE.Value) continue;
+
+ if ((FeatureEntry.Implies & FE.Value).any()) {
+ Bits |= FE.Value;
+ SetImpliedBits(Bits, FE, FeatureTable);
+ }
+ }
+}
+
+/// For each feature that (transitively) implies this feature, clear it.
+static
+void ClearImpliedBits(FeatureBitset &Bits,
+ const SubtargetFeatureKV &FeatureEntry,
+ ArrayRef<SubtargetFeatureKV> FeatureTable) {
+ for (const SubtargetFeatureKV &FE : FeatureTable) {
+ if (FeatureEntry.Value == FE.Value) continue;
+
+ if ((FE.Implies & FeatureEntry.Value).any()) {
+ Bits &= ~FE.Value;
+ ClearImpliedBits(Bits, FE, FeatureTable);
+ }
+ }
+}
+
+void
+SubtargetFeatures::ToggleFeature(FeatureBitset &Bits, StringRef Feature,
+ ArrayRef<SubtargetFeatureKV> FeatureTable) {
+ // Find feature in table.
+ const SubtargetFeatureKV *FeatureEntry =
+ Find(StripFlag(Feature), FeatureTable);
+ // If there is a match
+ if (FeatureEntry) {
+ if ((Bits & FeatureEntry->Value) == FeatureEntry->Value) {
+ Bits &= ~FeatureEntry->Value;
+ // For each feature that implies this, clear it.
+ ClearImpliedBits(Bits, *FeatureEntry, FeatureTable);
+ } else {
+ Bits |= FeatureEntry->Value;
+
+ // For each feature that this implies, set it.
+ SetImpliedBits(Bits, *FeatureEntry, FeatureTable);
+ }
+ } else {
+ errs() << "'" << Feature << "' is not a recognized feature for this target"
+ << " (ignoring feature)\n";
+ }
+}
+
+void SubtargetFeatures::ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature,
+ ArrayRef<SubtargetFeatureKV> FeatureTable) {
+ assert(hasFlag(Feature));
+
+ // Find feature in table.
+ const SubtargetFeatureKV *FeatureEntry =
+ Find(StripFlag(Feature), FeatureTable);
+ // If there is a match
+ if (FeatureEntry) {
+ // Enable/disable feature in bits
+ if (isEnabled(Feature)) {
+ Bits |= FeatureEntry->Value;
+
+ // For each feature that this implies, set it.
+ SetImpliedBits(Bits, *FeatureEntry, FeatureTable);
+ } else {
+ Bits &= ~FeatureEntry->Value;
+
+ // For each feature that implies this, clear it.
+ ClearImpliedBits(Bits, *FeatureEntry, FeatureTable);
+ }
+ } else {
+ errs() << "'" << Feature << "' is not a recognized feature for this target"
+ << " (ignoring feature)\n";
+ }
+}
+
+FeatureBitset
+SubtargetFeatures::getFeatureBits(StringRef CPU,
+ ArrayRef<SubtargetFeatureKV> CPUTable,
+ ArrayRef<SubtargetFeatureKV> FeatureTable) {
+ if (CPUTable.empty() || FeatureTable.empty())
+ return FeatureBitset();
+
+ assert(std::is_sorted(std::begin(CPUTable), std::end(CPUTable)) &&
+ "CPU table is not sorted");
+ assert(std::is_sorted(std::begin(FeatureTable), std::end(FeatureTable)) &&
+ "CPU features table is not sorted");
+ // Resulting bits
+ FeatureBitset Bits;
+
+ // Check if help is needed
+ if (CPU == "help")
+ Help(CPUTable, FeatureTable);
+
+ // Find CPU entry if CPU name is specified.
+ else if (!CPU.empty()) {
+ const SubtargetFeatureKV *CPUEntry = Find(CPU, CPUTable);
+
+ // If there is a match
+ if (CPUEntry) {
+ // Set base feature bits
+ Bits = CPUEntry->Value;
+
+ // Set the feature implied by this CPU feature, if any.
+ for (auto &FE : FeatureTable) {
+ if ((CPUEntry->Value & FE.Value).any())
+ SetImpliedBits(Bits, FE, FeatureTable);
+ }
+ } else {
+ errs() << "'" << CPU << "' is not a recognized processor for this target"
+ << " (ignoring processor)\n";
+ }
+ }
+
+ // Iterate through each feature
+ for (const std::string &Feature : Features) {
+ // Check for help
+ if (Feature == "+help")
+ Help(CPUTable, FeatureTable);
+
+ ApplyFeatureFlag(Bits, Feature, FeatureTable);
+ }
+
+ return Bits;
+}
+
+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
new file mode 100644
index 000000000000..82352cb50c70
--- /dev/null
+++ b/contrib/llvm/lib/MC/WasmObjectWriter.cpp
@@ -0,0 +1,1294 @@
+//===- lib/MC/WasmObjectWriter.cpp - Wasm File Writer ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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/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/MCExpr.h"
+#include "llvm/MC/MCFixupKindInfo.h"
+#include "llvm/MC/MCObjectFileInfo.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;
+
+#undef DEBUG_TYPE
+#define DEBUG_TYPE "reloc-info"
+
+namespace {
+
+// 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 contents of the section starts (after the header).
+ uint64_t ContentsOffset;
+};
+
+// The signature of a wasm function, in a struct capable of being used as a
+// DenseMap key.
+struct WasmFunctionType {
+ // Support empty and tombstone instances, needed by DenseMap.
+ enum { Plain, Empty, Tombstone } State;
+
+ // The return types of the function.
+ SmallVector<wasm::ValType, 1> Returns;
+
+ // The parameter types of the function.
+ SmallVector<wasm::ValType, 4> Params;
+
+ WasmFunctionType() : State(Plain) {}
+
+ bool operator==(const WasmFunctionType &Other) const {
+ return State == Other.State && Returns == Other.Returns &&
+ Params == Other.Params;
+ }
+};
+
+// Traits for using WasmFunctionType in a DenseMap.
+struct WasmFunctionTypeDenseMapInfo {
+ static WasmFunctionType getEmptyKey() {
+ WasmFunctionType FuncTy;
+ FuncTy.State = WasmFunctionType::Empty;
+ return FuncTy;
+ }
+ static WasmFunctionType getTombstoneKey() {
+ WasmFunctionType FuncTy;
+ FuncTy.State = WasmFunctionType::Tombstone;
+ return FuncTy;
+ }
+ static unsigned getHashValue(const WasmFunctionType &FuncTy) {
+ uintptr_t Value = FuncTy.State;
+ for (wasm::ValType Ret : FuncTy.Returns)
+ Value += DenseMapInfo<int32_t>::getHashValue(int32_t(Ret));
+ for (wasm::ValType Param : FuncTy.Params)
+ Value += DenseMapInfo<int32_t>::getHashValue(int32_t(Param));
+ return Value;
+ }
+ static bool isEqual(const WasmFunctionType &LHS,
+ const WasmFunctionType &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// A wasm import to be written into the import section.
+struct WasmImport {
+ StringRef ModuleName;
+ StringRef FieldName;
+ unsigned Kind;
+ int32_t Type;
+};
+
+// A wasm function to be written into the function section.
+struct WasmFunction {
+ int32_t Type;
+ const MCSymbolWasm *Sym;
+};
+
+// A wasm export to be written into the export section.
+struct WasmExport {
+ StringRef FieldName;
+ unsigned Kind;
+ uint32_t Index;
+};
+
+// A wasm global to be written into the global section.
+struct WasmGlobal {
+ wasm::ValType Type;
+ bool IsMutable;
+ bool HasImport;
+ uint64_t InitialValue;
+ uint32_t ImportIndex;
+};
+
+// 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 {
+ switch (Type) {
+ case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
+ case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
+ case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ void print(raw_ostream &Out) const {
+ Out << "Off=" << Offset << ", Sym=" << Symbol << ", Addend=" << Addend
+ << ", Type=" << Type << ", FixupSection=" << FixupSection;
+ }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
+#endif
+};
+
+#if !defined(NDEBUG)
+raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) {
+ Rel.print(OS);
+ return OS;
+}
+#endif
+
+class WasmObjectWriter : public MCObjectWriter {
+ /// Helper struct for containing some precomputed information on symbols.
+ struct WasmSymbolData {
+ const MCSymbolWasm *Symbol;
+ StringRef Name;
+
+ // Support lexicographic sorting.
+ bool operator<(const WasmSymbolData &RHS) const { return Name < RHS.Name; }
+ };
+
+ /// The target specific Wasm writer instance.
+ std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter;
+
+ // Relocations for fixing up references in the code section.
+ std::vector<WasmRelocationEntry> CodeRelocations;
+
+ // Relocations for fixing up references in the data section.
+ std::vector<WasmRelocationEntry> DataRelocations;
+
+ // 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> IndirectSymbolIndices;
+ // Maps function/global symbols to the function/global index space.
+ DenseMap<const MCSymbolWasm *, uint32_t> SymbolIndices;
+
+ DenseMap<WasmFunctionType, int32_t, WasmFunctionTypeDenseMapInfo>
+ FunctionTypeIndices;
+
+ // TargetObjectWriter wrappers.
+ bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
+ unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup) const {
+ return TargetObjectWriter->getRelocType(Target, Fixup);
+ }
+
+ void startSection(SectionBookkeeping &Section, unsigned SectionId,
+ const char *Name = nullptr);
+ void endSection(SectionBookkeeping &Section);
+
+public:
+ WasmObjectWriter(MCWasmObjectTargetWriter *MOTW, raw_pwrite_stream &OS)
+ : MCObjectWriter(OS, /*IsLittleEndian=*/true), TargetObjectWriter(MOTW) {}
+
+private:
+ ~WasmObjectWriter() override;
+
+ void reset() override {
+ CodeRelocations.clear();
+ DataRelocations.clear();
+ TypeIndices.clear();
+ SymbolIndices.clear();
+ IndirectSymbolIndices.clear();
+ FunctionTypeIndices.clear();
+ MCObjectWriter::reset();
+ }
+
+ void writeHeader(const MCAssembler &Asm);
+
+ void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
+ const MCFragment *Fragment, const MCFixup &Fixup,
+ MCValue Target, bool &IsPCRel,
+ uint64_t &FixedValue) override;
+
+ void executePostLayoutBinding(MCAssembler &Asm,
+ const MCAsmLayout &Layout) override;
+
+ void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
+
+ void writeString(const StringRef Str) {
+ encodeULEB128(Str.size(), getStream());
+ writeBytes(Str);
+ }
+
+ void writeValueType(wasm::ValType Ty) {
+ encodeSLEB128(int32_t(Ty), getStream());
+ }
+
+ void writeTypeSection(const SmallVector<WasmFunctionType, 4> &FunctionTypes);
+ void writeImportSection(const SmallVector<WasmImport, 4> &Imports);
+ void writeFunctionSection(const SmallVector<WasmFunction, 4> &Functions);
+ void writeTableSection(uint32_t NumElements);
+ void writeMemorySection(const SmallVector<char, 0> &DataBytes);
+ void writeGlobalSection(const SmallVector<WasmGlobal, 4> &Globals);
+ void writeExportSection(const SmallVector<WasmExport, 4> &Exports);
+ void writeElemSection(const SmallVector<uint32_t, 4> &TableElems);
+ void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
+ const SmallVector<WasmFunction, 4> &Functions);
+ uint64_t
+ writeDataSection(const SmallVector<char, 0> &DataBytes);
+ void writeNameSection(const SmallVector<WasmFunction, 4> &Functions,
+ const SmallVector<WasmImport, 4> &Imports,
+ uint32_t NumFuncImports);
+ void writeCodeRelocSection();
+ void writeDataRelocSection(uint64_t DataSectionHeaderSize);
+ void writeLinkingMetaDataSection(uint32_t DataSize, uint32_t DataAlignment,
+ ArrayRef<StringRef> WeakSymbols,
+ bool HasStackPointer,
+ uint32_t StackPointerGlobal);
+
+ void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
+ uint64_t ContentsOffset);
+
+ void writeRelocations(ArrayRef<WasmRelocationEntry> Relocations,
+ uint64_t HeaderSize);
+ uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry);
+};
+
+} // end anonymous namespace
+
+WasmObjectWriter::~WasmObjectWriter() {}
+
+// Return the padding size to write a 32-bit value into a 5-byte ULEB128.
+static unsigned PaddingFor5ByteULEB128(uint32_t X) {
+ return X == 0 ? 4 : (4u - (31u - countLeadingZeros(X)) / 7u);
+}
+
+// Return the padding size to write a 32-bit value into a 5-byte SLEB128.
+static unsigned PaddingFor5ByteSLEB128(int32_t X) {
+ return 5 - getSLEB128Size(X);
+}
+
+// Write out a section header and a patchable section size field.
+void WasmObjectWriter::startSection(SectionBookkeeping &Section,
+ unsigned SectionId,
+ const char *Name) {
+ assert((Name != nullptr) == (SectionId == wasm::WASM_SEC_CUSTOM) &&
+ "Only custom sections can have names");
+
+ DEBUG(dbgs() << "startSection " << SectionId << ": " << Name << "\n");
+ encodeULEB128(SectionId, getStream());
+
+ Section.SizeOffset = getStream().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(UINT32_MAX, getStream());
+
+ // The position where the section starts, for measuring its size.
+ Section.ContentsOffset = getStream().tell();
+
+ // Custom sections in wasm also have a string identifier.
+ if (SectionId == wasm::WASM_SEC_CUSTOM) {
+ assert(Name);
+ writeString(StringRef(Name));
+ }
+}
+
+// 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 = getStream().tell() - Section.ContentsOffset;
+ if (uint32_t(Size) != Size)
+ report_fatal_error("section size does not fit in a uint32_t");
+
+ DEBUG(dbgs() << "endSection size=" << Size << "\n");
+ unsigned Padding = PaddingFor5ByteULEB128(Size);
+
+ // Write the final section size to the payload_len field, which follows
+ // the section id byte.
+ uint8_t Buffer[16];
+ unsigned SizeLen = encodeULEB128(Size, Buffer, Padding);
+ assert(SizeLen == 5);
+ getStream().pwrite((char *)Buffer, SizeLen, Section.SizeOffset);
+}
+
+// Emit the Wasm header.
+void WasmObjectWriter::writeHeader(const MCAssembler &Asm) {
+ writeBytes(StringRef(wasm::WasmMagic, sizeof(wasm::WasmMagic)));
+ writeLE32(wasm::WasmVersion);
+}
+
+void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
+}
+
+void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup, MCValue Target,
+ bool &IsPCRel, uint64_t &FixedValue) {
+ const auto &FixupSection = cast<MCSectionWasm>(*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()) {
+ 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;
+
+ 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<MCSymbolWasm>(&Inner->getSymbol());
+ ViaWeakRef = true;
+ }
+ }
+ }
+
+ // 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;
+
+ if (SymA) {
+ if (ViaWeakRef)
+ llvm_unreachable("weakref used in reloc not yet implemented");
+ else
+ SymA->setUsedInReloc();
+ }
+
+ assert(!IsPCRel);
+ assert(SymA);
+
+ unsigned Type = getRelocType(Target, Fixup);
+
+ WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
+ DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
+
+ if (FixupSection.hasInstructions())
+ CodeRelocations.push_back(Rec);
+ else
+ DataRelocations.push_back(Rec);
+}
+
+// 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 Padding = PaddingFor5ByteULEB128(X);
+ unsigned SizeLen = encodeULEB128(X, Buffer, Padding);
+ 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 Padding = PaddingFor5ByteSLEB128(X);
+ unsigned SizeLen = encodeSLEB128(X, Buffer, Padding);
+ 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);
+}
+
+// Compute a value to write into the code at the location covered
+// by RelEntry. This value isn't used by the static linker, since
+// we have addends; it just serves to make the code more readable
+// and to make standalone wasm modules directly usable.
+static uint32_t ProvisionalValue(const WasmRelocationEntry &RelEntry) {
+ const MCSymbolWasm *Sym = RelEntry.Symbol;
+
+ // For undefined symbols, use a hopefully invalid value.
+ if (!Sym->isDefined(/*SetUsed=*/false))
+ return UINT32_MAX;
+
+ const auto &Section = cast<MCSectionWasm>(RelEntry.Symbol->getSection(false));
+ uint64_t Address = Section.getSectionOffset() + RelEntry.Addend;
+
+ // Ignore overflow. LLVM allows address arithmetic to silently wrap.
+ uint32_t Value = Address;
+
+ return Value;
+}
+
+uint32_t WasmObjectWriter::getRelocationIndexValue(
+ const WasmRelocationEntry &RelEntry) {
+ switch (RelEntry.Type) {
+ case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
+ case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
+ if (!IndirectSymbolIndices.count(RelEntry.Symbol))
+ report_fatal_error("symbol not found table index space:" +
+ RelEntry.Symbol->getName());
+ return IndirectSymbolIndices[RelEntry.Symbol];
+ case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
+ case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
+ case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
+ case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
+ case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
+ if (!SymbolIndices.count(RelEntry.Symbol))
+ report_fatal_error("symbol not found function/global index space:" +
+ RelEntry.Symbol->getName());
+ return SymbolIndices[RelEntry.Symbol];
+ case wasm::R_WEBASSEMBLY_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];
+ default:
+ llvm_unreachable("invalid relocation type");
+ }
+}
+
+// Apply the portions of the relocation records that we can handle ourselves
+// directly.
+void WasmObjectWriter::applyRelocations(
+ ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset) {
+ raw_pwrite_stream &Stream = getStream();
+ for (const WasmRelocationEntry &RelEntry : Relocations) {
+ uint64_t Offset = ContentsOffset +
+ RelEntry.FixupSection->getSectionOffset() +
+ RelEntry.Offset;
+
+ DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
+ switch (RelEntry.Type) {
+ case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
+ case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
+ case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
+ case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: {
+ uint32_t Index = getRelocationIndexValue(RelEntry);
+ WritePatchableSLEB(Stream, Index, Offset);
+ break;
+ }
+ case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: {
+ uint32_t Index = getRelocationIndexValue(RelEntry);
+ WriteI32(Stream, Index, Offset);
+ break;
+ }
+ case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: {
+ uint32_t Value = ProvisionalValue(RelEntry);
+ WritePatchableSLEB(Stream, Value, Offset);
+ break;
+ }
+ case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: {
+ uint32_t Value = ProvisionalValue(RelEntry);
+ WritePatchableLEB(Stream, Value, Offset);
+ break;
+ }
+ case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: {
+ uint32_t Value = ProvisionalValue(RelEntry);
+ WriteI32(Stream, Value, Offset);
+ break;
+ }
+ default:
+ llvm_unreachable("invalid relocation type");
+ }
+ }
+}
+
+// Write out the portions of the relocation records that the linker will
+// need to handle.
+void WasmObjectWriter::writeRelocations(
+ ArrayRef<WasmRelocationEntry> Relocations, uint64_t HeaderSize) {
+ raw_pwrite_stream &Stream = getStream();
+ for (const WasmRelocationEntry& RelEntry : Relocations) {
+
+ uint64_t Offset = RelEntry.Offset +
+ RelEntry.FixupSection->getSectionOffset() + HeaderSize;
+ uint32_t Index = getRelocationIndexValue(RelEntry);
+
+ encodeULEB128(RelEntry.Type, Stream);
+ encodeULEB128(Offset, Stream);
+ encodeULEB128(Index, Stream);
+ if (RelEntry.hasAddend())
+ encodeSLEB128(RelEntry.Addend, Stream);
+ }
+}
+
+void WasmObjectWriter::writeTypeSection(
+ const SmallVector<WasmFunctionType, 4> &FunctionTypes) {
+ if (FunctionTypes.empty())
+ return;
+
+ SectionBookkeeping Section;
+ startSection(Section, wasm::WASM_SEC_TYPE);
+
+ encodeULEB128(FunctionTypes.size(), getStream());
+
+ for (const WasmFunctionType &FuncTy : FunctionTypes) {
+ encodeSLEB128(wasm::WASM_TYPE_FUNC, getStream());
+ encodeULEB128(FuncTy.Params.size(), getStream());
+ for (wasm::ValType Ty : FuncTy.Params)
+ writeValueType(Ty);
+ encodeULEB128(FuncTy.Returns.size(), getStream());
+ for (wasm::ValType Ty : FuncTy.Returns)
+ writeValueType(Ty);
+ }
+
+ endSection(Section);
+}
+
+
+void WasmObjectWriter::writeImportSection(
+ const SmallVector<WasmImport, 4> &Imports) {
+ if (Imports.empty())
+ return;
+
+ SectionBookkeeping Section;
+ startSection(Section, wasm::WASM_SEC_IMPORT);
+
+ encodeULEB128(Imports.size(), getStream());
+ for (const WasmImport &Import : Imports) {
+ writeString(Import.ModuleName);
+ writeString(Import.FieldName);
+
+ encodeULEB128(Import.Kind, getStream());
+
+ switch (Import.Kind) {
+ case wasm::WASM_EXTERNAL_FUNCTION:
+ encodeULEB128(Import.Type, getStream());
+ break;
+ case wasm::WASM_EXTERNAL_GLOBAL:
+ encodeSLEB128(int32_t(Import.Type), getStream());
+ encodeULEB128(0, getStream()); // mutability
+ break;
+ default:
+ llvm_unreachable("unsupported import kind");
+ }
+ }
+
+ endSection(Section);
+}
+
+void WasmObjectWriter::writeFunctionSection(
+ const SmallVector<WasmFunction, 4> &Functions) {
+ if (Functions.empty())
+ return;
+
+ SectionBookkeeping Section;
+ startSection(Section, wasm::WASM_SEC_FUNCTION);
+
+ encodeULEB128(Functions.size(), getStream());
+ for (const WasmFunction &Func : Functions)
+ encodeULEB128(Func.Type, getStream());
+
+ endSection(Section);
+}
+
+void WasmObjectWriter::writeTableSection(uint32_t NumElements) {
+ // 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.
+
+ SectionBookkeeping Section;
+ startSection(Section, wasm::WASM_SEC_TABLE);
+
+ encodeULEB128(1, getStream()); // The number of tables.
+ // Fixed to 1 for now.
+ encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream()); // Type of table
+ encodeULEB128(0, getStream()); // flags
+ encodeULEB128(NumElements, getStream()); // initial
+
+ endSection(Section);
+}
+
+void WasmObjectWriter::writeMemorySection(
+ const SmallVector<char, 0> &DataBytes) {
+ // For now, always emit the memory section, 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.
+ SectionBookkeeping Section;
+ uint32_t NumPages =
+ (DataBytes.size() + wasm::WasmPageSize - 1) / wasm::WasmPageSize;
+
+ startSection(Section, wasm::WASM_SEC_MEMORY);
+ encodeULEB128(1, getStream()); // number of memory spaces
+
+ encodeULEB128(0, getStream()); // flags
+ encodeULEB128(NumPages, getStream()); // initial
+
+ endSection(Section);
+}
+
+void WasmObjectWriter::writeGlobalSection(
+ const SmallVector<WasmGlobal, 4> &Globals) {
+ if (Globals.empty())
+ return;
+
+ SectionBookkeeping Section;
+ startSection(Section, wasm::WASM_SEC_GLOBAL);
+
+ encodeULEB128(Globals.size(), getStream());
+ for (const WasmGlobal &Global : Globals) {
+ writeValueType(Global.Type);
+ write8(Global.IsMutable);
+
+ if (Global.HasImport) {
+ assert(Global.InitialValue == 0);
+ write8(wasm::WASM_OPCODE_GET_GLOBAL);
+ encodeULEB128(Global.ImportIndex, getStream());
+ } else {
+ assert(Global.ImportIndex == 0);
+ write8(wasm::WASM_OPCODE_I32_CONST);
+ encodeSLEB128(Global.InitialValue, getStream()); // offset
+ }
+ write8(wasm::WASM_OPCODE_END);
+ }
+
+ endSection(Section);
+}
+
+void WasmObjectWriter::writeExportSection(
+ const SmallVector<WasmExport, 4> &Exports) {
+ if (Exports.empty())
+ return;
+
+ SectionBookkeeping Section;
+ startSection(Section, wasm::WASM_SEC_EXPORT);
+
+ encodeULEB128(Exports.size(), getStream());
+ for (const WasmExport &Export : Exports) {
+ writeString(Export.FieldName);
+ encodeSLEB128(Export.Kind, getStream());
+ encodeULEB128(Export.Index, getStream());
+ }
+
+ endSection(Section);
+}
+
+void WasmObjectWriter::writeElemSection(
+ const SmallVector<uint32_t, 4> &TableElems) {
+ if (TableElems.empty())
+ return;
+
+ SectionBookkeeping Section;
+ startSection(Section, wasm::WASM_SEC_ELEM);
+
+ encodeULEB128(1, getStream()); // number of "segments"
+ encodeULEB128(0, getStream()); // the table index
+
+ // init expr for starting offset
+ write8(wasm::WASM_OPCODE_I32_CONST);
+ encodeSLEB128(0, getStream());
+ write8(wasm::WASM_OPCODE_END);
+
+ encodeULEB128(TableElems.size(), getStream());
+ for (uint32_t Elem : TableElems)
+ encodeULEB128(Elem, getStream());
+
+ endSection(Section);
+}
+
+void WasmObjectWriter::writeCodeSection(
+ const MCAssembler &Asm, const MCAsmLayout &Layout,
+ const SmallVector<WasmFunction, 4> &Functions) {
+ if (Functions.empty())
+ return;
+
+ SectionBookkeeping Section;
+ startSection(Section, wasm::WASM_SEC_CODE);
+
+ encodeULEB128(Functions.size(), getStream());
+
+ 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, getStream());
+
+ FuncSection.setSectionOffset(getStream().tell() - Section.ContentsOffset);
+
+ Asm.writeSectionData(&FuncSection, Layout);
+ }
+
+ // Apply fixups.
+ applyRelocations(CodeRelocations, Section.ContentsOffset);
+
+ endSection(Section);
+}
+
+uint64_t WasmObjectWriter::writeDataSection(
+ const SmallVector<char, 0> &DataBytes) {
+ if (DataBytes.empty())
+ return 0;
+
+ SectionBookkeeping Section;
+ startSection(Section, wasm::WASM_SEC_DATA);
+
+ encodeULEB128(1, getStream()); // count
+ encodeULEB128(0, getStream()); // memory index
+ write8(wasm::WASM_OPCODE_I32_CONST);
+ encodeSLEB128(0, getStream()); // offset
+ write8(wasm::WASM_OPCODE_END);
+ encodeULEB128(DataBytes.size(), getStream()); // size
+ uint32_t HeaderSize = getStream().tell() - Section.ContentsOffset;
+ writeBytes(DataBytes); // data
+
+ // Apply fixups.
+ applyRelocations(DataRelocations, Section.ContentsOffset + HeaderSize);
+
+ endSection(Section);
+ return HeaderSize;
+}
+
+void WasmObjectWriter::writeNameSection(
+ const SmallVector<WasmFunction, 4> &Functions,
+ const SmallVector<WasmImport, 4> &Imports,
+ unsigned NumFuncImports) {
+ uint32_t TotalFunctions = NumFuncImports + Functions.size();
+ if (TotalFunctions == 0)
+ return;
+
+ SectionBookkeeping Section;
+ startSection(Section, wasm::WASM_SEC_CUSTOM, "name");
+ SectionBookkeeping SubSection;
+ startSection(SubSection, wasm::WASM_NAMES_FUNCTION);
+
+ encodeULEB128(TotalFunctions, getStream());
+ uint32_t Index = 0;
+ for (const WasmImport &Import : Imports) {
+ if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
+ encodeULEB128(Index, getStream());
+ writeString(Import.FieldName);
+ ++Index;
+ }
+ }
+ for (const WasmFunction &Func : Functions) {
+ encodeULEB128(Index, getStream());
+ writeString(Func.Sym->getName());
+ ++Index;
+ }
+
+ endSection(SubSection);
+ endSection(Section);
+}
+
+void WasmObjectWriter::writeCodeRelocSection() {
+ // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
+ // for descriptions of the reloc sections.
+
+ if (CodeRelocations.empty())
+ return;
+
+ SectionBookkeeping Section;
+ startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.CODE");
+
+ encodeULEB128(wasm::WASM_SEC_CODE, getStream());
+ encodeULEB128(CodeRelocations.size(), getStream());
+
+ writeRelocations(CodeRelocations, 0);
+
+ endSection(Section);
+}
+
+void WasmObjectWriter::writeDataRelocSection(uint64_t DataSectionHeaderSize) {
+ // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
+ // for descriptions of the reloc sections.
+
+ if (DataRelocations.empty())
+ return;
+
+ SectionBookkeeping Section;
+ startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.DATA");
+
+ encodeULEB128(wasm::WASM_SEC_DATA, getStream());
+ encodeULEB128(DataRelocations.size(), getStream());
+
+ writeRelocations(DataRelocations, DataSectionHeaderSize);
+
+ endSection(Section);
+}
+
+void WasmObjectWriter::writeLinkingMetaDataSection(
+ uint32_t DataSize, uint32_t DataAlignment, ArrayRef<StringRef> WeakSymbols,
+ bool HasStackPointer, uint32_t StackPointerGlobal) {
+ SectionBookkeeping Section;
+ startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
+ SectionBookkeeping SubSection;
+
+ if (HasStackPointer) {
+ startSection(SubSection, wasm::WASM_STACK_POINTER);
+ encodeULEB128(StackPointerGlobal, getStream()); // id
+ endSection(SubSection);
+ }
+
+ if (WeakSymbols.size() != 0) {
+ startSection(SubSection, wasm::WASM_SYMBOL_INFO);
+ encodeULEB128(WeakSymbols.size(), getStream());
+ for (const StringRef Export: WeakSymbols) {
+ writeString(Export);
+ encodeULEB128(wasm::WASM_SYMBOL_FLAG_WEAK, getStream());
+ }
+ endSection(SubSection);
+ }
+
+ if (DataSize > 0) {
+ startSection(SubSection, wasm::WASM_DATA_SIZE);
+ encodeULEB128(DataSize, getStream());
+ endSection(SubSection);
+
+ startSection(SubSection, wasm::WASM_DATA_ALIGNMENT);
+ encodeULEB128(DataAlignment, getStream());
+ endSection(SubSection);
+ }
+
+ endSection(Section);
+}
+
+void WasmObjectWriter::writeObject(MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
+ DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
+ MCContext &Ctx = Asm.getContext();
+ wasm::ValType PtrType = is64Bit() ? wasm::ValType::I64 : wasm::ValType::I32;
+
+ // Collect information from the available symbols.
+ SmallVector<WasmFunctionType, 4> FunctionTypes;
+ SmallVector<WasmFunction, 4> Functions;
+ SmallVector<uint32_t, 4> TableElems;
+ SmallVector<WasmGlobal, 4> Globals;
+ SmallVector<WasmImport, 4> Imports;
+ SmallVector<WasmExport, 4> Exports;
+ SmallVector<StringRef, 4> WeakSymbols;
+ SmallPtrSet<const MCSymbolWasm *, 4> IsAddressTaken;
+ unsigned NumFuncImports = 0;
+ unsigned NumGlobalImports = 0;
+ SmallVector<char, 0> DataBytes;
+ uint32_t DataAlignment = 1;
+ uint32_t StackPointerGlobal = 0;
+ bool HasStackPointer = false;
+
+ // Populate the IsAddressTaken set.
+ for (const WasmRelocationEntry &RelEntry : CodeRelocations) {
+ switch (RelEntry.Type) {
+ case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
+ case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
+ IsAddressTaken.insert(RelEntry.Symbol);
+ break;
+ default:
+ break;
+ }
+ }
+ for (const WasmRelocationEntry &RelEntry : DataRelocations) {
+ switch (RelEntry.Type) {
+ case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
+ case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
+ IsAddressTaken.insert(RelEntry.Symbol);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Populate the Imports set.
+ for (const MCSymbol &S : Asm.symbols()) {
+ const auto &WS = static_cast<const MCSymbolWasm &>(S);
+ int32_t Type;
+
+ if (WS.isFunction()) {
+ // Prepare the function's type, if we haven't seen it yet.
+ WasmFunctionType F;
+ F.Returns = WS.getReturns();
+ F.Params = WS.getParams();
+ auto Pair =
+ FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size()));
+ if (Pair.second)
+ FunctionTypes.push_back(F);
+
+ Type = Pair.first->second;
+ } else {
+ Type = int32_t(PtrType);
+ }
+
+ // If the symbol is not defined in this translation unit, import it.
+ if (!WS.isTemporary() && !WS.isDefined(/*SetUsed=*/false)) {
+ WasmImport Import;
+ Import.ModuleName = WS.getModuleName();
+ Import.FieldName = WS.getName();
+
+ if (WS.isFunction()) {
+ Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
+ Import.Type = Type;
+ SymbolIndices[&WS] = NumFuncImports;
+ ++NumFuncImports;
+ } else {
+ Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
+ Import.Type = Type;
+ SymbolIndices[&WS] = NumGlobalImports;
+ ++NumGlobalImports;
+ }
+
+ Imports.push_back(Import);
+ }
+ }
+
+ // In the special .global_variables section, we've encoded global
+ // variables used by the function. Translate them into the Globals
+ // list.
+ MCSectionWasm *GlobalVars = Ctx.getWasmSection(".global_variables", 0, 0);
+ if (!GlobalVars->getFragmentList().empty()) {
+ if (GlobalVars->getFragmentList().size() != 1)
+ report_fatal_error("only one .global_variables fragment supported");
+ const MCFragment &Frag = *GlobalVars->begin();
+ if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
+ report_fatal_error("only data supported in .global_variables");
+ const auto &DataFrag = cast<MCDataFragment>(Frag);
+ if (!DataFrag.getFixups().empty())
+ report_fatal_error("fixups not supported in .global_variables");
+ 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; ) {
+ WasmGlobal G;
+ if (end - p < 3)
+ report_fatal_error("truncated global variable encoding");
+ G.Type = wasm::ValType(int8_t(*p++));
+ G.IsMutable = bool(*p++);
+ G.HasImport = bool(*p++);
+ if (G.HasImport) {
+ G.InitialValue = 0;
+
+ WasmImport Import;
+ Import.ModuleName = (const char *)p;
+ const uint8_t *nul = (const uint8_t *)memchr(p, '\0', end - p);
+ if (!nul)
+ report_fatal_error("global module name must be nul-terminated");
+ p = nul + 1;
+ nul = (const uint8_t *)memchr(p, '\0', end - p);
+ if (!nul)
+ report_fatal_error("global base name must be nul-terminated");
+ Import.FieldName = (const char *)p;
+ p = nul + 1;
+
+ Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
+ Import.Type = int32_t(G.Type);
+
+ G.ImportIndex = NumGlobalImports;
+ ++NumGlobalImports;
+
+ Imports.push_back(Import);
+ } else {
+ unsigned n;
+ G.InitialValue = decodeSLEB128(p, &n);
+ G.ImportIndex = 0;
+ if ((ptrdiff_t)n > end - p)
+ report_fatal_error("global initial value must be valid SLEB128");
+ p += n;
+ }
+ Globals.push_back(G);
+ }
+ }
+
+ // In the special .stack_pointer section, we've encoded the stack pointer
+ // index.
+ MCSectionWasm *StackPtr = Ctx.getWasmSection(".stack_pointer", 0, 0);
+ if (!StackPtr->getFragmentList().empty()) {
+ if (StackPtr->getFragmentList().size() != 1)
+ report_fatal_error("only one .stack_pointer fragment supported");
+ const MCFragment &Frag = *StackPtr->begin();
+ if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
+ report_fatal_error("only data supported in .stack_pointer");
+ const auto &DataFrag = cast<MCDataFragment>(Frag);
+ if (!DataFrag.getFixups().empty())
+ report_fatal_error("fixups not supported in .stack_pointer");
+ const SmallVectorImpl<char> &Contents = DataFrag.getContents();
+ if (Contents.size() != 4)
+ report_fatal_error("only one entry supported in .stack_pointer");
+ HasStackPointer = true;
+ StackPointerGlobal = NumGlobalImports + *(const int32_t *)Contents.data();
+ }
+
+ // Handle regular defined and undefined 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;
+
+ // Variable references (weak references) are handled in a second pass
+ if (S.isVariable())
+ continue;
+
+ const auto &WS = static_cast<const MCSymbolWasm &>(S);
+ DEBUG(dbgs() << "MCSymbol: '" << S << "'"
+ << " isDefined=" << S.isDefined() << " isExternal="
+ << S.isExternal() << " isTemporary=" << S.isTemporary()
+ << " isFunction=" << WS.isFunction()
+ << " isWeak=" << WS.isWeak()
+ << " isVariable=" << WS.isVariable() << "\n");
+
+ if (WS.isWeak())
+ WeakSymbols.push_back(WS.getName());
+
+ unsigned Index;
+
+ if (WS.isFunction()) {
+ // Prepare the function's type, if we haven't seen it yet.
+ WasmFunctionType F;
+ F.Returns = WS.getReturns();
+ F.Params = WS.getParams();
+ auto Pair =
+ FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size()));
+ if (Pair.second)
+ FunctionTypes.push_back(F);
+
+ int32_t Type = Pair.first->second;
+
+ if (WS.isDefined(/*SetUsed=*/false)) {
+ if (WS.getOffset() != 0)
+ report_fatal_error(
+ "function sections must contain one function each");
+
+ if (WS.getSize() == 0)
+ report_fatal_error(
+ "function symbols must have a size set with .size");
+
+ // A definition. Take the next available index.
+ Index = NumFuncImports + Functions.size();
+
+ // Prepare the function.
+ WasmFunction Func;
+ Func.Type = Type;
+ Func.Sym = &WS;
+ SymbolIndices[&WS] = Index;
+ Functions.push_back(Func);
+ } else {
+ // Should be no such thing as weak undefined symbol
+ assert(!WS.isVariable());
+
+ // An import; the index was assigned above.
+ Index = SymbolIndices.find(&WS)->second;
+ }
+
+ // If needed, prepare the function to be called indirectly.
+ if (IsAddressTaken.count(&WS)) {
+ IndirectSymbolIndices[&WS] = TableElems.size();
+ TableElems.push_back(Index);
+ }
+ } else {
+ if (WS.isTemporary() && !WS.getSize())
+ continue;
+
+ if (!WS.isDefined(/*SetUsed=*/false))
+ continue;
+
+ if (WS.getOffset() != 0)
+ report_fatal_error("data sections must contain one variable each: " +
+ WS.getName());
+ 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());
+
+ if (uint64_t(Size) != Layout.getSectionFileSize(&DataSection))
+ report_fatal_error("data sections must contain at most one variable");
+
+ DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
+ DataAlignment = std::max(DataAlignment, DataSection.getAlignment());
+
+ DataSection.setSectionOffset(DataBytes.size());
+
+ 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)) {
+ DataBytes.insert(DataBytes.end(), Size, Fill->getValue());
+ } else {
+ const auto &DataFrag = cast<MCDataFragment>(Frag);
+ const SmallVectorImpl<char> &Contents = DataFrag.getContents();
+
+ DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
+ }
+ }
+
+ // For each global, prepare a corresponding wasm global holding its
+ // address. For externals these will also be named exports.
+ Index = NumGlobalImports + Globals.size();
+
+ WasmGlobal Global;
+ Global.Type = PtrType;
+ Global.IsMutable = false;
+ Global.HasImport = false;
+ Global.InitialValue = DataSection.getSectionOffset();
+ Global.ImportIndex = 0;
+ SymbolIndices[&WS] = Index;
+ Globals.push_back(Global);
+ }
+
+ // If the symbol is visible outside this translation unit, export it.
+ if (WS.isExternal() && WS.isDefined(/*SetUsed=*/false)) {
+ WasmExport Export;
+ Export.FieldName = WS.getName();
+ Export.Index = Index;
+ if (WS.isFunction())
+ Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
+ else
+ Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
+ Exports.push_back(Export);
+ }
+ }
+
+ // Handle weak aliases
+ for (const MCSymbol &S : Asm.symbols()) {
+ if (!S.isVariable())
+ continue;
+ assert(S.isExternal());
+ assert(S.isDefined(/*SetUsed=*/false));
+
+ const auto &WS = static_cast<const MCSymbolWasm &>(S);
+
+ // Find the target symbol of this weak alias
+ const MCExpr *Expr = WS.getVariableValue();
+ auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr);
+ const auto *ResolvedSym = cast<MCSymbolWasm>(&Inner->getSymbol());
+ uint32_t Index = SymbolIndices.find(ResolvedSym)->second;
+ DEBUG(dbgs() << "Weak alias: '" << WS << "' -> '" << ResolvedSym << "' = " << Index << "\n");
+ SymbolIndices[&WS] = Index;
+
+ WasmExport Export;
+ Export.FieldName = WS.getName();
+ Export.Index = Index;
+ if (WS.isFunction())
+ Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
+ else
+ Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
+ WeakSymbols.push_back(Export.FieldName);
+ Exports.push_back(Export);
+ }
+
+ // Add types for indirect function calls.
+ for (const WasmRelocationEntry &Fixup : CodeRelocations) {
+ if (Fixup.Type != wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB)
+ continue;
+
+ WasmFunctionType F;
+ F.Returns = Fixup.Symbol->getReturns();
+ F.Params = Fixup.Symbol->getParams();
+ auto Pair =
+ FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size()));
+ if (Pair.second)
+ FunctionTypes.push_back(F);
+
+ TypeIndices[Fixup.Symbol] = Pair.first->second;
+ }
+
+ // Write out the Wasm header.
+ writeHeader(Asm);
+
+ writeTypeSection(FunctionTypes);
+ writeImportSection(Imports);
+ writeFunctionSection(Functions);
+ writeTableSection(TableElems.size());
+ writeMemorySection(DataBytes);
+ writeGlobalSection(Globals);
+ writeExportSection(Exports);
+ // TODO: Start Section
+ writeElemSection(TableElems);
+ writeCodeSection(Asm, Layout, Functions);
+ uint64_t DataSectionHeaderSize = writeDataSection(DataBytes);
+ writeNameSection(Functions, Imports, NumFuncImports);
+ writeCodeRelocSection();
+ writeDataRelocSection(DataSectionHeaderSize);
+ writeLinkingMetaDataSection(DataBytes.size(), DataAlignment, WeakSymbols, HasStackPointer, StackPointerGlobal);
+
+ // TODO: Translate the .comment section to the output.
+ // TODO: Translate debug sections to the output.
+}
+
+MCObjectWriter *llvm::createWasmObjectWriter(MCWasmObjectTargetWriter *MOTW,
+ raw_pwrite_stream &OS) {
+ return new WasmObjectWriter(MOTW, OS);
+}
diff --git a/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp b/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp
new file mode 100644
index 000000000000..fc5234950391
--- /dev/null
+++ b/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp
@@ -0,0 +1,1090 @@
+//===- llvm/MC/WinCOFFObjectWriter.cpp ------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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/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 {
+ ATFunctionDefinition,
+ ATbfAndefSymbol,
+ 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:
+ 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;
+
+ WinCOFFObjectWriter(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, bool &IsPCRel,
+ uint64_t &FixedValue) override;
+
+ void createFileSymbols(MCAssembler &Asm);
+ void assignSectionNumbers();
+ void assignFileOffsets(MCAssembler &Asm, const MCAsmLayout &Layout);
+
+ void 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(MCWinCOFFObjectTargetWriter *MOTW,
+ raw_pwrite_stream &OS)
+ : MCObjectWriter(OS, true), TargetObjectWriter(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_LIBRARY;
+ } 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) {
+ writeLE16(COFF::IMAGE_FILE_MACHINE_UNKNOWN);
+ writeLE16(0xFFFF);
+ writeLE16(COFF::BigObjHeader::MinBigObjectVersion);
+ writeLE16(Header.Machine);
+ writeLE32(Header.TimeDateStamp);
+ writeBytes(StringRef(COFF::BigObjMagic, sizeof(COFF::BigObjMagic)));
+ writeLE32(0);
+ writeLE32(0);
+ writeLE32(0);
+ writeLE32(0);
+ writeLE32(Header.NumberOfSections);
+ writeLE32(Header.PointerToSymbolTable);
+ writeLE32(Header.NumberOfSymbols);
+ } else {
+ writeLE16(Header.Machine);
+ writeLE16(static_cast<int16_t>(Header.NumberOfSections));
+ writeLE32(Header.TimeDateStamp);
+ writeLE32(Header.PointerToSymbolTable);
+ writeLE32(Header.NumberOfSymbols);
+ writeLE16(Header.SizeOfOptionalHeader);
+ writeLE16(Header.Characteristics);
+ }
+}
+
+void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol &S) {
+ writeBytes(StringRef(S.Data.Name, COFF::NameSize));
+ writeLE32(S.Data.Value);
+ if (UseBigObj)
+ writeLE32(S.Data.SectionNumber);
+ else
+ writeLE16(static_cast<int16_t>(S.Data.SectionNumber));
+ writeLE16(S.Data.Type);
+ write8(S.Data.StorageClass);
+ write8(S.Data.NumberOfAuxSymbols);
+ WriteAuxiliarySymbols(S.Aux);
+}
+
+void WinCOFFObjectWriter::WriteAuxiliarySymbols(
+ const COFFSymbol::AuxiliarySymbols &S) {
+ for (const AuxSymbol &i : S) {
+ switch (i.AuxType) {
+ case ATFunctionDefinition:
+ writeLE32(i.Aux.FunctionDefinition.TagIndex);
+ writeLE32(i.Aux.FunctionDefinition.TotalSize);
+ writeLE32(i.Aux.FunctionDefinition.PointerToLinenumber);
+ writeLE32(i.Aux.FunctionDefinition.PointerToNextFunction);
+ WriteZeros(sizeof(i.Aux.FunctionDefinition.unused));
+ if (UseBigObj)
+ WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
+ break;
+ case ATbfAndefSymbol:
+ WriteZeros(sizeof(i.Aux.bfAndefSymbol.unused1));
+ writeLE16(i.Aux.bfAndefSymbol.Linenumber);
+ WriteZeros(sizeof(i.Aux.bfAndefSymbol.unused2));
+ writeLE32(i.Aux.bfAndefSymbol.PointerToNextFunction);
+ WriteZeros(sizeof(i.Aux.bfAndefSymbol.unused3));
+ if (UseBigObj)
+ WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
+ break;
+ case ATWeakExternal:
+ writeLE32(i.Aux.WeakExternal.TagIndex);
+ writeLE32(i.Aux.WeakExternal.Characteristics);
+ WriteZeros(sizeof(i.Aux.WeakExternal.unused));
+ if (UseBigObj)
+ WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
+ break;
+ case ATFile:
+ writeBytes(
+ StringRef(reinterpret_cast<const char *>(&i.Aux),
+ UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size));
+ break;
+ case ATSectionDefinition:
+ writeLE32(i.Aux.SectionDefinition.Length);
+ writeLE16(i.Aux.SectionDefinition.NumberOfRelocations);
+ writeLE16(i.Aux.SectionDefinition.NumberOfLinenumbers);
+ writeLE32(i.Aux.SectionDefinition.CheckSum);
+ writeLE16(static_cast<int16_t>(i.Aux.SectionDefinition.Number));
+ write8(i.Aux.SectionDefinition.Selection);
+ WriteZeros(sizeof(i.Aux.SectionDefinition.unused));
+ writeLE16(static_cast<int16_t>(i.Aux.SectionDefinition.Number >> 16));
+ if (UseBigObj)
+ WriteZeros(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());
+ std::sort(Arr.begin(), Arr.end(),
+ [](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;
+ writeBytes(StringRef(S.Name, COFF::NameSize));
+ writeLE32(S.VirtualSize);
+ writeLE32(S.VirtualAddress);
+ writeLE32(S.SizeOfRawData);
+ writeLE32(S.PointerToRawData);
+ writeLE32(S.PointerToRelocations);
+ writeLE32(S.PointerToLineNumbers);
+ writeLE16(S.NumberOfRelocations);
+ writeLE16(S.NumberOfLineNumbers);
+ writeLE32(S.Characteristics);
+ }
+}
+
+void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) {
+ writeLE32(R.VirtualAddress);
+ writeLE32(R.SymbolTableIndex);
+ writeLE16(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);
+ raw_pwrite_stream &OldStream = getStream();
+
+ // Redirect the output stream to our buffer and fill our buffer with
+ // the section data.
+ setStream(VecOS);
+ Asm.writeSectionData(&MCSec, Layout);
+
+ // Reset the stream back to what it was before.
+ setStream(OldStream);
+
+ // Write the section contents to the object file.
+ getStream() << 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(getStream().tell() <= Sec.Header.PointerToRawData &&
+ "Section::PointerToRawData is insane!");
+
+ unsigned PaddingSize = Sec.Header.PointerToRawData - getStream().tell();
+ assert(PaddingSize < 4 &&
+ "Should only need at most three bytes of padding!");
+ WriteZeros(PaddingSize);
+
+ 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(getStream().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) {
+ // "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 {
+ // MS LINK expects to be able to replace all references to a function with a
+ // thunk to implement their /INCREMENTAL feature. Make sure we don't optimize
+ // away any relocations to functions.
+ uint16_t Type = cast<MCSymbolCOFF>(SymA).getType();
+ if (Asm.isIncrementalLinkerCompatible() &&
+ (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, bool &IsPCRel, 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 = getInitialOffset();
+
+ 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)) {
+ // Align the section data to a four byte boundary.
+ Offset = alignTo(Offset, 4);
+ 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;
+}
+
+void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
+ 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 *COMDAT = MCSec.getCOMDATSymbol();
+ assert(COMDAT);
+ COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(COMDAT);
+ assert(COMDATSymbol);
+ COFFSection *Assoc = COMDATSymbol->Section;
+ if (!Assoc)
+ report_fatal_error(
+ Twine("Missing associated COMDAT section for section ") +
+ MCSec.getSectionName());
+
+ // Skip this section if the associated section is unused.
+ if (Assoc->Number == -1)
+ continue;
+
+ Section->Symbol->Aux[0].Aux.SectionDefinition.Number = Assoc->Number;
+ }
+
+ 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(getStream().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(getStream());
+}
+
+MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_)
+ : Machine(Machine_) {}
+
+// Pin the vtable to this file.
+void MCWinCOFFObjectTargetWriter::anchor() {}
+
+//------------------------------------------------------------------------------
+// WinCOFFObjectWriter factory function
+
+MCObjectWriter *
+llvm::createWinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW,
+ raw_pwrite_stream &OS) {
+ return new WinCOFFObjectWriter(MOTW, OS);
+}