aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/MC
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-12-20 19:53:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-12-20 19:53:05 +0000
commit0b57cec536236d46e3dba9bd041533462f33dbb7 (patch)
tree56229dbdbbf76d18580f72f789003db17246c8d9 /contrib/llvm/lib/MC
parent718ef55ec7785aae63f98f8ca05dc07ed399c16d (diff)
Move all sources from the llvm project into contrib/llvm-project.
This uses the new layout of the upstream repository, which was recently migrated to GitHub, and converted into a "monorepo". That is, most of the earlier separate sub-projects with their own branches and tags were consolidated into one top-level directory, and are now branched and tagged together. Updating the vendor area to match this layout is next.
Notes
Notes: svn path=/head/; revision=355940
Diffstat (limited to 'contrib/llvm/lib/MC')
-rw-r--r--contrib/llvm/lib/MC/ConstantPools.cpp115
-rw-r--r--contrib/llvm/lib/MC/ELFObjectWriter.cpp1564
-rw-r--r--contrib/llvm/lib/MC/MCAsmBackend.cpp137
-rw-r--r--contrib/llvm/lib/MC/MCAsmInfo.cpp126
-rw-r--r--contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp68
-rw-r--r--contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp97
-rw-r--r--contrib/llvm/lib/MC/MCAsmInfoELF.cpp34
-rw-r--r--contrib/llvm/lib/MC/MCAsmInfoWasm.cpp25
-rw-r--r--contrib/llvm/lib/MC/MCAsmInfoXCOFF.cpp18
-rw-r--r--contrib/llvm/lib/MC/MCAsmMacro.cpp41
-rw-r--r--contrib/llvm/lib/MC/MCAsmStreamer.cpp1941
-rw-r--r--contrib/llvm/lib/MC/MCAssembler.cpp1154
-rw-r--r--contrib/llvm/lib/MC/MCCodeEmitter.cpp15
-rw-r--r--contrib/llvm/lib/MC/MCCodePadder.cpp370
-rw-r--r--contrib/llvm/lib/MC/MCCodeView.cpp696
-rw-r--r--contrib/llvm/lib/MC/MCContext.cpp707
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp343
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/Disassembler.h124
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp46
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp199
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp30
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/MCSymbolizer.cpp13
-rw-r--r--contrib/llvm/lib/MC/MCDwarf.cpp1950
-rw-r--r--contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp31
-rw-r--r--contrib/llvm/lib/MC/MCELFStreamer.cpp708
-rw-r--r--contrib/llvm/lib/MC/MCExpr.cpp931
-rw-r--r--contrib/llvm/lib/MC/MCFragment.cpp467
-rw-r--r--contrib/llvm/lib/MC/MCInst.cpp98
-rw-r--r--contrib/llvm/lib/MC/MCInstPrinter.cpp125
-rw-r--r--contrib/llvm/lib/MC/MCInstrAnalysis.cpp35
-rw-r--r--contrib/llvm/lib/MC/MCInstrDesc.cpp65
-rw-r--r--contrib/llvm/lib/MC/MCLabel.cpp25
-rw-r--r--contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp59
-rw-r--r--contrib/llvm/lib/MC/MCMachOStreamer.cpp519
-rw-r--r--contrib/llvm/lib/MC/MCMachObjectTargetWriter.cpp18
-rw-r--r--contrib/llvm/lib/MC/MCNullStreamer.cpp49
-rw-r--r--contrib/llvm/lib/MC/MCObjectFileInfo.cpp867
-rw-r--r--contrib/llvm/lib/MC/MCObjectStreamer.cpp731
-rw-r--r--contrib/llvm/lib/MC/MCObjectWriter.cpp52
-rw-r--r--contrib/llvm/lib/MC/MCParser/AsmLexer.cpp755
-rw-r--r--contrib/llvm/lib/MC/MCParser/AsmParser.cpp5962
-rw-r--r--contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp865
-rw-r--r--contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp1208
-rw-r--r--contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp899
-rw-r--r--contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp129
-rw-r--r--contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp136
-rw-r--r--contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp19
-rw-r--r--contrib/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp29
-rw-r--r--contrib/llvm/lib/MC/MCParser/WasmAsmParser.cpp255
-rw-r--r--contrib/llvm/lib/MC/MCRegisterInfo.cpp134
-rw-r--r--contrib/llvm/lib/MC/MCSchedule.cpp167
-rw-r--r--contrib/llvm/lib/MC/MCSection.cpp102
-rw-r--r--contrib/llvm/lib/MC/MCSectionCOFF.cpp113
-rw-r--r--contrib/llvm/lib/MC/MCSectionELF.cpp198
-rw-r--r--contrib/llvm/lib/MC/MCSectionMachO.cpp281
-rw-r--r--contrib/llvm/lib/MC/MCSectionWasm.cpp94
-rw-r--r--contrib/llvm/lib/MC/MCSectionXCOFF.cpp33
-rw-r--r--contrib/llvm/lib/MC/MCStreamer.cpp1106
-rw-r--r--contrib/llvm/lib/MC/MCSubtargetInfo.cpp317
-rw-r--r--contrib/llvm/lib/MC/MCSymbol.cpp88
-rw-r--r--contrib/llvm/lib/MC/MCSymbolELF.cpp201
-rw-r--r--contrib/llvm/lib/MC/MCTargetOptions.cpp23
-rw-r--r--contrib/llvm/lib/MC/MCValue.cpp61
-rw-r--r--contrib/llvm/lib/MC/MCWasmObjectTargetWriter.cpp17
-rw-r--r--contrib/llvm/lib/MC/MCWasmStreamer.cpp229
-rw-r--r--contrib/llvm/lib/MC/MCWin64EH.cpp680
-rw-r--r--contrib/llvm/lib/MC/MCWinCOFFStreamer.cpp325
-rw-r--r--contrib/llvm/lib/MC/MCWinEH.cpp25
-rw-r--r--contrib/llvm/lib/MC/MCXCOFFObjectTargetWriter.cpp16
-rw-r--r--contrib/llvm/lib/MC/MCXCOFFStreamer.cpp59
-rw-r--r--contrib/llvm/lib/MC/MachObjectWriter.cpp1048
-rw-r--r--contrib/llvm/lib/MC/StringTableBuilder.cpp195
-rw-r--r--contrib/llvm/lib/MC/SubtargetFeature.cpp82
-rw-r--r--contrib/llvm/lib/MC/WasmObjectWriter.cpp1622
-rw-r--r--contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp1102
-rw-r--r--contrib/llvm/lib/MC/XCOFFObjectWriter.cpp94
76 files changed, 0 insertions, 33262 deletions
diff --git a/contrib/llvm/lib/MC/ConstantPools.cpp b/contrib/llvm/lib/MC/ConstantPools.cpp
deleted file mode 100644
index 8cba6b3281a5..000000000000
--- a/contrib/llvm/lib/MC/ConstantPools.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-//===- ConstantPools.cpp - ConstantPool class -----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the ConstantPool and AssemblerConstantPools classes.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/ConstantPools.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDirectives.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/Support/Casting.h"
-
-using namespace llvm;
-
-//
-// ConstantPool implementation
-//
-// Emit the contents of the constant pool using the provided streamer.
-void ConstantPool::emitEntries(MCStreamer &Streamer) {
- if (Entries.empty())
- return;
- Streamer.EmitDataRegion(MCDR_DataRegion);
- for (const ConstantPoolEntry &Entry : Entries) {
- Streamer.EmitCodeAlignment(Entry.Size); // align naturally
- Streamer.EmitLabel(Entry.Label);
- Streamer.EmitValue(Entry.Value, Entry.Size, Entry.Loc);
- }
- Streamer.EmitDataRegion(MCDR_DataRegionEnd);
- Entries.clear();
-}
-
-const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context,
- unsigned Size, SMLoc Loc) {
- const MCConstantExpr *C = dyn_cast<MCConstantExpr>(Value);
-
- // Check if there is existing entry for the same constant. If so, reuse it.
- auto Itr = C ? CachedEntries.find(C->getValue()) : CachedEntries.end();
- if (Itr != CachedEntries.end())
- return Itr->second;
-
- MCSymbol *CPEntryLabel = Context.createTempSymbol();
-
- Entries.push_back(ConstantPoolEntry(CPEntryLabel, Value, Size, Loc));
- const auto SymRef = MCSymbolRefExpr::create(CPEntryLabel, Context);
- if (C)
- CachedEntries[C->getValue()] = SymRef;
- return SymRef;
-}
-
-bool ConstantPool::empty() { return Entries.empty(); }
-
-void ConstantPool::clearCache() {
- CachedEntries.clear();
-}
-
-//
-// AssemblerConstantPools implementation
-//
-ConstantPool *AssemblerConstantPools::getConstantPool(MCSection *Section) {
- ConstantPoolMapTy::iterator CP = ConstantPools.find(Section);
- if (CP == ConstantPools.end())
- return nullptr;
-
- return &CP->second;
-}
-
-ConstantPool &
-AssemblerConstantPools::getOrCreateConstantPool(MCSection *Section) {
- return ConstantPools[Section];
-}
-
-static void emitConstantPool(MCStreamer &Streamer, MCSection *Section,
- ConstantPool &CP) {
- if (!CP.empty()) {
- Streamer.SwitchSection(Section);
- CP.emitEntries(Streamer);
- }
-}
-
-void AssemblerConstantPools::emitAll(MCStreamer &Streamer) {
- // Dump contents of assembler constant pools.
- for (auto &CPI : ConstantPools) {
- MCSection *Section = CPI.first;
- ConstantPool &CP = CPI.second;
-
- emitConstantPool(Streamer, Section, CP);
- }
-}
-
-void AssemblerConstantPools::emitForCurrentSection(MCStreamer &Streamer) {
- MCSection *Section = Streamer.getCurrentSectionOnly();
- if (ConstantPool *CP = getConstantPool(Section))
- emitConstantPool(Streamer, Section, *CP);
-}
-
-void AssemblerConstantPools::clearCacheForCurrentSection(MCStreamer &Streamer) {
- MCSection *Section = Streamer.getCurrentSectionOnly();
- if (ConstantPool *CP = getConstantPool(Section))
- CP->clearCache();
-}
-
-const MCExpr *AssemblerConstantPools::addEntry(MCStreamer &Streamer,
- const MCExpr *Expr,
- unsigned Size, SMLoc Loc) {
- MCSection *Section = Streamer.getCurrentSectionOnly();
- return getOrCreateConstantPool(Section).addEntry(Expr, Streamer.getContext(),
- Size, Loc);
-}
diff --git a/contrib/llvm/lib/MC/ELFObjectWriter.cpp b/contrib/llvm/lib/MC/ELFObjectWriter.cpp
deleted file mode 100644
index 2c68723a12f8..000000000000
--- a/contrib/llvm/lib/MC/ELFObjectWriter.cpp
+++ /dev/null
@@ -1,1564 +0,0 @@
-//===- lib/MC/ELFObjectWriter.cpp - ELF File Writer -----------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements ELF object file writer information.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCAsmLayout.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCELFObjectWriter.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCFixup.h"
-#include "llvm/MC/MCFixupKindInfo.h"
-#include "llvm/MC/MCFragment.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCSectionELF.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCSymbolELF.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/MC/StringTableBuilder.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Compression.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/LEB128.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/SMLoc.h"
-#include "llvm/Support/StringSaver.h"
-#include "llvm/Support/SwapByteOrder.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-#include <map>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-using namespace llvm;
-
-#undef DEBUG_TYPE
-#define DEBUG_TYPE "reloc-info"
-
-namespace {
-
-using SectionIndexMapTy = DenseMap<const MCSectionELF *, uint32_t>;
-
-class ELFObjectWriter;
-struct ELFWriter;
-
-bool isDwoSection(const MCSectionELF &Sec) {
- return Sec.getSectionName().endswith(".dwo");
-}
-
-class SymbolTableWriter {
- ELFWriter &EWriter;
- bool Is64Bit;
-
- // indexes we are going to write to .symtab_shndx.
- std::vector<uint32_t> ShndxIndexes;
-
- // The numbel of symbols written so far.
- unsigned NumWritten;
-
- void createSymtabShndx();
-
- template <typename T> void write(T Value);
-
-public:
- SymbolTableWriter(ELFWriter &EWriter, bool Is64Bit);
-
- void writeSymbol(uint32_t name, uint8_t info, uint64_t value, uint64_t size,
- uint8_t other, uint32_t shndx, bool Reserved);
-
- ArrayRef<uint32_t> getShndxIndexes() const { return ShndxIndexes; }
-};
-
-struct ELFWriter {
- ELFObjectWriter &OWriter;
- support::endian::Writer W;
-
- enum DwoMode {
- AllSections,
- NonDwoOnly,
- DwoOnly,
- } Mode;
-
- static uint64_t SymbolValue(const MCSymbol &Sym, const MCAsmLayout &Layout);
- static bool isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol,
- bool Used, bool Renamed);
-
- /// Helper struct for containing some precomputed information on symbols.
- struct ELFSymbolData {
- const MCSymbolELF *Symbol;
- uint32_t SectionIndex;
- StringRef Name;
-
- // Support lexicographic sorting.
- bool operator<(const ELFSymbolData &RHS) const {
- unsigned LHSType = Symbol->getType();
- unsigned RHSType = RHS.Symbol->getType();
- if (LHSType == ELF::STT_SECTION && RHSType != ELF::STT_SECTION)
- return false;
- if (LHSType != ELF::STT_SECTION && RHSType == ELF::STT_SECTION)
- return true;
- if (LHSType == ELF::STT_SECTION && RHSType == ELF::STT_SECTION)
- return SectionIndex < RHS.SectionIndex;
- return Name < RHS.Name;
- }
- };
-
- /// @}
- /// @name Symbol Table Data
- /// @{
-
- StringTableBuilder StrTabBuilder{StringTableBuilder::ELF};
-
- /// @}
-
- // This holds the symbol table index of the last local symbol.
- unsigned LastLocalSymbolIndex;
- // This holds the .strtab section index.
- unsigned StringTableIndex;
- // This holds the .symtab section index.
- unsigned SymbolTableIndex;
-
- // Sections in the order they are to be output in the section table.
- std::vector<const MCSectionELF *> SectionTable;
- unsigned addToSectionTable(const MCSectionELF *Sec);
-
- // TargetObjectWriter wrappers.
- bool is64Bit() const;
- bool hasRelocationAddend() const;
-
- void align(unsigned Alignment);
-
- bool maybeWriteCompression(uint64_t Size,
- SmallVectorImpl<char> &CompressedContents,
- bool ZLibStyle, unsigned Alignment);
-
-public:
- ELFWriter(ELFObjectWriter &OWriter, raw_pwrite_stream &OS,
- bool IsLittleEndian, DwoMode Mode)
- : OWriter(OWriter),
- W(OS, IsLittleEndian ? support::little : support::big), Mode(Mode) {}
-
- void WriteWord(uint64_t Word) {
- if (is64Bit())
- W.write<uint64_t>(Word);
- else
- W.write<uint32_t>(Word);
- }
-
- template <typename T> void write(T Val) {
- W.write(Val);
- }
-
- void writeHeader(const MCAssembler &Asm);
-
- void writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex,
- ELFSymbolData &MSD, const MCAsmLayout &Layout);
-
- // Start and end offset of each section
- using SectionOffsetsTy =
- std::map<const MCSectionELF *, std::pair<uint64_t, uint64_t>>;
-
- // Map from a signature symbol to the group section index
- using RevGroupMapTy = DenseMap<const MCSymbol *, unsigned>;
-
- /// Compute the symbol table data
- ///
- /// \param Asm - The assembler.
- /// \param SectionIndexMap - Maps a section to its index.
- /// \param RevGroupMap - Maps a signature symbol to the group section.
- void computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout,
- const SectionIndexMapTy &SectionIndexMap,
- const RevGroupMapTy &RevGroupMap,
- SectionOffsetsTy &SectionOffsets);
-
- void writeAddrsigSection();
-
- MCSectionELF *createRelocationSection(MCContext &Ctx,
- const MCSectionELF &Sec);
-
- const MCSectionELF *createStringTable(MCContext &Ctx);
-
- void writeSectionHeader(const MCAsmLayout &Layout,
- const SectionIndexMapTy &SectionIndexMap,
- const SectionOffsetsTy &SectionOffsets);
-
- void writeSectionData(const MCAssembler &Asm, MCSection &Sec,
- const MCAsmLayout &Layout);
-
- void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
- uint64_t Address, uint64_t Offset, uint64_t Size,
- uint32_t Link, uint32_t Info, uint64_t Alignment,
- uint64_t EntrySize);
-
- void writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec);
-
- uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout);
- void writeSection(const SectionIndexMapTy &SectionIndexMap,
- uint32_t GroupSymbolIndex, uint64_t Offset, uint64_t Size,
- const MCSectionELF &Section);
-};
-
-class ELFObjectWriter : public MCObjectWriter {
- /// The target specific ELF writer instance.
- std::unique_ptr<MCELFObjectTargetWriter> TargetObjectWriter;
-
- DenseMap<const MCSectionELF *, std::vector<ELFRelocationEntry>> Relocations;
-
- DenseMap<const MCSymbolELF *, const MCSymbolELF *> Renames;
-
- bool EmitAddrsigSection = false;
- std::vector<const MCSymbol *> AddrsigSyms;
-
- bool hasRelocationAddend() const;
-
- bool shouldRelocateWithSymbol(const MCAssembler &Asm,
- const MCSymbolRefExpr *RefA,
- const MCSymbolELF *Sym, uint64_t C,
- unsigned Type) const;
-
-public:
- ELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW)
- : TargetObjectWriter(std::move(MOTW)) {}
-
- void reset() override {
- Relocations.clear();
- Renames.clear();
- MCObjectWriter::reset();
- }
-
- bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
- const MCSymbol &SymA,
- const MCFragment &FB, bool InSet,
- bool IsPCRel) const override;
-
- virtual bool checkRelocation(MCContext &Ctx, SMLoc Loc,
- const MCSectionELF *From,
- const MCSectionELF *To) {
- return true;
- }
-
- void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
- const MCFragment *Fragment, const MCFixup &Fixup,
- MCValue Target, uint64_t &FixedValue) override;
-
- void executePostLayoutBinding(MCAssembler &Asm,
- const MCAsmLayout &Layout) override;
-
- void emitAddrsigSection() override { EmitAddrsigSection = true; }
- void addAddrsigSymbol(const MCSymbol *Sym) override {
- AddrsigSyms.push_back(Sym);
- }
-
- friend struct ELFWriter;
-};
-
-class ELFSingleObjectWriter : public ELFObjectWriter {
- raw_pwrite_stream &OS;
- bool IsLittleEndian;
-
-public:
- ELFSingleObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
- raw_pwrite_stream &OS, bool IsLittleEndian)
- : ELFObjectWriter(std::move(MOTW)), OS(OS),
- IsLittleEndian(IsLittleEndian) {}
-
- uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override {
- return ELFWriter(*this, OS, IsLittleEndian, ELFWriter::AllSections)
- .writeObject(Asm, Layout);
- }
-
- friend struct ELFWriter;
-};
-
-class ELFDwoObjectWriter : public ELFObjectWriter {
- raw_pwrite_stream &OS, &DwoOS;
- bool IsLittleEndian;
-
-public:
- ELFDwoObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
- raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS,
- bool IsLittleEndian)
- : ELFObjectWriter(std::move(MOTW)), OS(OS), DwoOS(DwoOS),
- IsLittleEndian(IsLittleEndian) {}
-
- virtual bool checkRelocation(MCContext &Ctx, SMLoc Loc,
- const MCSectionELF *From,
- const MCSectionELF *To) override {
- if (isDwoSection(*From)) {
- Ctx.reportError(Loc, "A dwo section may not contain relocations");
- return false;
- }
- if (To && isDwoSection(*To)) {
- Ctx.reportError(Loc, "A relocation may not refer to a dwo section");
- return false;
- }
- return true;
- }
-
- uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override {
- uint64_t Size = ELFWriter(*this, OS, IsLittleEndian, ELFWriter::NonDwoOnly)
- .writeObject(Asm, Layout);
- Size += ELFWriter(*this, DwoOS, IsLittleEndian, ELFWriter::DwoOnly)
- .writeObject(Asm, Layout);
- return Size;
- }
-};
-
-} // end anonymous namespace
-
-void ELFWriter::align(unsigned Alignment) {
- uint64_t Padding = OffsetToAlignment(W.OS.tell(), Alignment);
- W.OS.write_zeros(Padding);
-}
-
-unsigned ELFWriter::addToSectionTable(const MCSectionELF *Sec) {
- SectionTable.push_back(Sec);
- StrTabBuilder.add(Sec->getSectionName());
- return SectionTable.size();
-}
-
-void SymbolTableWriter::createSymtabShndx() {
- if (!ShndxIndexes.empty())
- return;
-
- ShndxIndexes.resize(NumWritten);
-}
-
-template <typename T> void SymbolTableWriter::write(T Value) {
- EWriter.write(Value);
-}
-
-SymbolTableWriter::SymbolTableWriter(ELFWriter &EWriter, bool Is64Bit)
- : EWriter(EWriter), Is64Bit(Is64Bit), NumWritten(0) {}
-
-void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value,
- uint64_t size, uint8_t other,
- uint32_t shndx, bool Reserved) {
- bool LargeIndex = shndx >= ELF::SHN_LORESERVE && !Reserved;
-
- if (LargeIndex)
- createSymtabShndx();
-
- if (!ShndxIndexes.empty()) {
- if (LargeIndex)
- ShndxIndexes.push_back(shndx);
- else
- ShndxIndexes.push_back(0);
- }
-
- uint16_t Index = LargeIndex ? uint16_t(ELF::SHN_XINDEX) : shndx;
-
- if (Is64Bit) {
- write(name); // st_name
- write(info); // st_info
- write(other); // st_other
- write(Index); // st_shndx
- write(value); // st_value
- write(size); // st_size
- } else {
- write(name); // st_name
- write(uint32_t(value)); // st_value
- write(uint32_t(size)); // st_size
- write(info); // st_info
- write(other); // st_other
- write(Index); // st_shndx
- }
-
- ++NumWritten;
-}
-
-bool ELFWriter::is64Bit() const {
- return OWriter.TargetObjectWriter->is64Bit();
-}
-
-bool ELFWriter::hasRelocationAddend() const {
- return OWriter.hasRelocationAddend();
-}
-
-// Emit the ELF header.
-void ELFWriter::writeHeader(const MCAssembler &Asm) {
- // ELF Header
- // ----------
- //
- // Note
- // ----
- // emitWord method behaves differently for ELF32 and ELF64, writing
- // 4 bytes in the former and 8 in the latter.
-
- W.OS << ELF::ElfMagic; // e_ident[EI_MAG0] to e_ident[EI_MAG3]
-
- W.OS << char(is64Bit() ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS]
-
- // e_ident[EI_DATA]
- W.OS << char(W.Endian == support::little ? ELF::ELFDATA2LSB
- : ELF::ELFDATA2MSB);
-
- W.OS << char(ELF::EV_CURRENT); // e_ident[EI_VERSION]
- // e_ident[EI_OSABI]
- W.OS << char(OWriter.TargetObjectWriter->getOSABI());
- // e_ident[EI_ABIVERSION]
- W.OS << char(OWriter.TargetObjectWriter->getABIVersion());
-
- W.OS.write_zeros(ELF::EI_NIDENT - ELF::EI_PAD);
-
- W.write<uint16_t>(ELF::ET_REL); // e_type
-
- W.write<uint16_t>(OWriter.TargetObjectWriter->getEMachine()); // e_machine = target
-
- W.write<uint32_t>(ELF::EV_CURRENT); // e_version
- WriteWord(0); // e_entry, no entry point in .o file
- WriteWord(0); // e_phoff, no program header for .o
- WriteWord(0); // e_shoff = sec hdr table off in bytes
-
- // e_flags = whatever the target wants
- W.write<uint32_t>(Asm.getELFHeaderEFlags());
-
- // e_ehsize = ELF header size
- W.write<uint16_t>(is64Bit() ? sizeof(ELF::Elf64_Ehdr)
- : sizeof(ELF::Elf32_Ehdr));
-
- W.write<uint16_t>(0); // e_phentsize = prog header entry size
- W.write<uint16_t>(0); // e_phnum = # prog header entries = 0
-
- // e_shentsize = Section header entry size
- W.write<uint16_t>(is64Bit() ? sizeof(ELF::Elf64_Shdr)
- : sizeof(ELF::Elf32_Shdr));
-
- // e_shnum = # of section header ents
- W.write<uint16_t>(0);
-
- // e_shstrndx = Section # of '.shstrtab'
- assert(StringTableIndex < ELF::SHN_LORESERVE);
- W.write<uint16_t>(StringTableIndex);
-}
-
-uint64_t ELFWriter::SymbolValue(const MCSymbol &Sym,
- const MCAsmLayout &Layout) {
- if (Sym.isCommon() && (Sym.isTargetCommon() || Sym.isExternal()))
- return Sym.getCommonAlignment();
-
- uint64_t Res;
- if (!Layout.getSymbolOffset(Sym, Res))
- return 0;
-
- if (Layout.getAssembler().isThumbFunc(&Sym))
- Res |= 1;
-
- return Res;
-}
-
-static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType) {
- uint8_t Type = newType;
-
- // Propagation rules:
- // IFUNC > FUNC > OBJECT > NOTYPE
- // TLS_OBJECT > OBJECT > NOTYPE
- //
- // dont let the new type degrade the old type
- switch (origType) {
- default:
- break;
- case ELF::STT_GNU_IFUNC:
- if (Type == ELF::STT_FUNC || Type == ELF::STT_OBJECT ||
- Type == ELF::STT_NOTYPE || Type == ELF::STT_TLS)
- Type = ELF::STT_GNU_IFUNC;
- break;
- case ELF::STT_FUNC:
- if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE ||
- Type == ELF::STT_TLS)
- Type = ELF::STT_FUNC;
- break;
- case ELF::STT_OBJECT:
- if (Type == ELF::STT_NOTYPE)
- Type = ELF::STT_OBJECT;
- break;
- case ELF::STT_TLS:
- if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE ||
- Type == ELF::STT_GNU_IFUNC || Type == ELF::STT_FUNC)
- Type = ELF::STT_TLS;
- break;
- }
-
- return Type;
-}
-
-void ELFWriter::writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex,
- ELFSymbolData &MSD, const MCAsmLayout &Layout) {
- const auto &Symbol = cast<MCSymbolELF>(*MSD.Symbol);
- const MCSymbolELF *Base =
- cast_or_null<MCSymbolELF>(Layout.getBaseSymbol(Symbol));
-
- // This has to be in sync with when computeSymbolTable uses SHN_ABS or
- // SHN_COMMON.
- bool IsReserved = !Base || Symbol.isCommon();
-
- // Binding and Type share the same byte as upper and lower nibbles
- uint8_t Binding = Symbol.getBinding();
- uint8_t Type = Symbol.getType();
- if (Base) {
- Type = mergeTypeForSet(Type, Base->getType());
- }
- uint8_t Info = (Binding << 4) | Type;
-
- // Other and Visibility share the same byte with Visibility using the lower
- // 2 bits
- uint8_t Visibility = Symbol.getVisibility();
- uint8_t Other = Symbol.getOther() | Visibility;
-
- uint64_t Value = SymbolValue(*MSD.Symbol, Layout);
- uint64_t Size = 0;
-
- const MCExpr *ESize = MSD.Symbol->getSize();
- if (!ESize && Base)
- ESize = Base->getSize();
-
- if (ESize) {
- int64_t Res;
- if (!ESize->evaluateKnownAbsolute(Res, Layout))
- report_fatal_error("Size expression must be absolute.");
- Size = Res;
- }
-
- // Write out the symbol table entry
- Writer.writeSymbol(StringIndex, Info, Value, Size, Other, MSD.SectionIndex,
- IsReserved);
-}
-
-// True if the assembler knows nothing about the final value of the symbol.
-// This doesn't cover the comdat issues, since in those cases the assembler
-// can at least know that all symbols in the section will move together.
-static bool isWeak(const MCSymbolELF &Sym) {
- if (Sym.getType() == ELF::STT_GNU_IFUNC)
- return true;
-
- switch (Sym.getBinding()) {
- default:
- llvm_unreachable("Unknown binding");
- case ELF::STB_LOCAL:
- return false;
- case ELF::STB_GLOBAL:
- return false;
- case ELF::STB_WEAK:
- case ELF::STB_GNU_UNIQUE:
- return true;
- }
-}
-
-bool ELFWriter::isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol,
- bool Used, bool Renamed) {
- if (Symbol.isVariable()) {
- const MCExpr *Expr = Symbol.getVariableValue();
- // Target Expressions that are always inlined do not appear in the symtab
- if (const auto *T = dyn_cast<MCTargetExpr>(Expr))
- if (T->inlineAssignedExpr())
- return false;
- if (const MCSymbolRefExpr *Ref = dyn_cast<MCSymbolRefExpr>(Expr)) {
- if (Ref->getKind() == MCSymbolRefExpr::VK_WEAKREF)
- return false;
- }
- }
-
- if (Used)
- return true;
-
- if (Renamed)
- return false;
-
- if (Symbol.isVariable() && Symbol.isUndefined()) {
- // FIXME: this is here just to diagnose the case of a var = commmon_sym.
- Layout.getBaseSymbol(Symbol);
- return false;
- }
-
- if (Symbol.isUndefined() && !Symbol.isBindingSet())
- return false;
-
- if (Symbol.isTemporary())
- return false;
-
- if (Symbol.getType() == ELF::STT_SECTION)
- return false;
-
- return true;
-}
-
-void ELFWriter::computeSymbolTable(
- MCAssembler &Asm, const MCAsmLayout &Layout,
- const SectionIndexMapTy &SectionIndexMap, const RevGroupMapTy &RevGroupMap,
- SectionOffsetsTy &SectionOffsets) {
- MCContext &Ctx = Asm.getContext();
- SymbolTableWriter Writer(*this, is64Bit());
-
- // Symbol table
- unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
- MCSectionELF *SymtabSection =
- Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, EntrySize, "");
- SymtabSection->setAlignment(is64Bit() ? 8 : 4);
- SymbolTableIndex = addToSectionTable(SymtabSection);
-
- align(SymtabSection->getAlignment());
- uint64_t SecStart = W.OS.tell();
-
- // The first entry is the undefined symbol entry.
- Writer.writeSymbol(0, 0, 0, 0, 0, 0, false);
-
- std::vector<ELFSymbolData> LocalSymbolData;
- std::vector<ELFSymbolData> ExternalSymbolData;
-
- // Add the data for the symbols.
- bool HasLargeSectionIndex = false;
- for (const MCSymbol &S : Asm.symbols()) {
- const auto &Symbol = cast<MCSymbolELF>(S);
- bool Used = Symbol.isUsedInReloc();
- bool WeakrefUsed = Symbol.isWeakrefUsedInReloc();
- bool isSignature = Symbol.isSignature();
-
- if (!isInSymtab(Layout, Symbol, Used || WeakrefUsed || isSignature,
- OWriter.Renames.count(&Symbol)))
- continue;
-
- if (Symbol.isTemporary() && Symbol.isUndefined()) {
- Ctx.reportError(SMLoc(), "Undefined temporary symbol");
- continue;
- }
-
- ELFSymbolData MSD;
- MSD.Symbol = cast<MCSymbolELF>(&Symbol);
-
- bool Local = Symbol.getBinding() == ELF::STB_LOCAL;
- assert(Local || !Symbol.isTemporary());
-
- if (Symbol.isAbsolute()) {
- MSD.SectionIndex = ELF::SHN_ABS;
- } else if (Symbol.isCommon()) {
- if (Symbol.isTargetCommon()) {
- MSD.SectionIndex = Symbol.getIndex();
- } else {
- assert(!Local);
- MSD.SectionIndex = ELF::SHN_COMMON;
- }
- } else if (Symbol.isUndefined()) {
- if (isSignature && !Used) {
- MSD.SectionIndex = RevGroupMap.lookup(&Symbol);
- if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
- HasLargeSectionIndex = true;
- } else {
- MSD.SectionIndex = ELF::SHN_UNDEF;
- }
- } else {
- const MCSectionELF &Section =
- static_cast<const MCSectionELF &>(Symbol.getSection());
-
- // We may end up with a situation when section symbol is technically
- // defined, but should not be. That happens because we explicitly
- // pre-create few .debug_* sections to have accessors.
- // And if these sections were not really defined in the code, but were
- // referenced, we simply error out.
- if (!Section.isRegistered()) {
- assert(static_cast<const MCSymbolELF &>(Symbol).getType() ==
- ELF::STT_SECTION);
- Ctx.reportError(SMLoc(),
- "Undefined section reference: " + Symbol.getName());
- continue;
- }
-
- if (Mode == NonDwoOnly && isDwoSection(Section))
- continue;
- MSD.SectionIndex = SectionIndexMap.lookup(&Section);
- assert(MSD.SectionIndex && "Invalid section index!");
- if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
- HasLargeSectionIndex = true;
- }
-
- StringRef Name = Symbol.getName();
-
- // Sections have their own string table
- if (Symbol.getType() != ELF::STT_SECTION) {
- MSD.Name = Name;
- StrTabBuilder.add(Name);
- }
-
- if (Local)
- LocalSymbolData.push_back(MSD);
- else
- ExternalSymbolData.push_back(MSD);
- }
-
- // This holds the .symtab_shndx section index.
- unsigned SymtabShndxSectionIndex = 0;
-
- if (HasLargeSectionIndex) {
- MCSectionELF *SymtabShndxSection =
- Ctx.getELFSection(".symtab_shndx", ELF::SHT_SYMTAB_SHNDX, 0, 4, "");
- SymtabShndxSectionIndex = addToSectionTable(SymtabShndxSection);
- SymtabShndxSection->setAlignment(4);
- }
-
- ArrayRef<std::string> FileNames = Asm.getFileNames();
- for (const std::string &Name : FileNames)
- StrTabBuilder.add(Name);
-
- StrTabBuilder.finalize();
-
- // File symbols are emitted first and handled separately from normal symbols,
- // i.e. a non-STT_FILE symbol with the same name may appear.
- for (const std::string &Name : FileNames)
- Writer.writeSymbol(StrTabBuilder.getOffset(Name),
- ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT,
- ELF::SHN_ABS, true);
-
- // Symbols are required to be in lexicographic order.
- array_pod_sort(LocalSymbolData.begin(), LocalSymbolData.end());
- array_pod_sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
-
- // Set the symbol indices. Local symbols must come before all other
- // symbols with non-local bindings.
- unsigned Index = FileNames.size() + 1;
-
- for (ELFSymbolData &MSD : LocalSymbolData) {
- unsigned StringIndex = MSD.Symbol->getType() == ELF::STT_SECTION
- ? 0
- : StrTabBuilder.getOffset(MSD.Name);
- MSD.Symbol->setIndex(Index++);
- writeSymbol(Writer, StringIndex, MSD, Layout);
- }
-
- // Write the symbol table entries.
- LastLocalSymbolIndex = Index;
-
- for (ELFSymbolData &MSD : ExternalSymbolData) {
- unsigned StringIndex = StrTabBuilder.getOffset(MSD.Name);
- MSD.Symbol->setIndex(Index++);
- writeSymbol(Writer, StringIndex, MSD, Layout);
- assert(MSD.Symbol->getBinding() != ELF::STB_LOCAL);
- }
-
- uint64_t SecEnd = W.OS.tell();
- SectionOffsets[SymtabSection] = std::make_pair(SecStart, SecEnd);
-
- ArrayRef<uint32_t> ShndxIndexes = Writer.getShndxIndexes();
- if (ShndxIndexes.empty()) {
- assert(SymtabShndxSectionIndex == 0);
- return;
- }
- assert(SymtabShndxSectionIndex != 0);
-
- SecStart = W.OS.tell();
- const MCSectionELF *SymtabShndxSection =
- SectionTable[SymtabShndxSectionIndex - 1];
- for (uint32_t Index : ShndxIndexes)
- write(Index);
- SecEnd = W.OS.tell();
- SectionOffsets[SymtabShndxSection] = std::make_pair(SecStart, SecEnd);
-}
-
-void ELFWriter::writeAddrsigSection() {
- for (const MCSymbol *Sym : OWriter.AddrsigSyms)
- encodeULEB128(Sym->getIndex(), W.OS);
-}
-
-MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx,
- const MCSectionELF &Sec) {
- if (OWriter.Relocations[&Sec].empty())
- return nullptr;
-
- const StringRef SectionName = Sec.getSectionName();
- std::string RelaSectionName = hasRelocationAddend() ? ".rela" : ".rel";
- RelaSectionName += SectionName;
-
- unsigned EntrySize;
- if (hasRelocationAddend())
- EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rela) : sizeof(ELF::Elf32_Rela);
- else
- EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel);
-
- unsigned Flags = 0;
- if (Sec.getFlags() & ELF::SHF_GROUP)
- Flags = ELF::SHF_GROUP;
-
- MCSectionELF *RelaSection = Ctx.createELFRelSection(
- RelaSectionName, hasRelocationAddend() ? ELF::SHT_RELA : ELF::SHT_REL,
- Flags, EntrySize, Sec.getGroup(), &Sec);
- RelaSection->setAlignment(is64Bit() ? 8 : 4);
- return RelaSection;
-}
-
-// Include the debug info compression header.
-bool ELFWriter::maybeWriteCompression(
- uint64_t Size, SmallVectorImpl<char> &CompressedContents, bool ZLibStyle,
- unsigned Alignment) {
- if (ZLibStyle) {
- uint64_t HdrSize =
- is64Bit() ? sizeof(ELF::Elf32_Chdr) : sizeof(ELF::Elf64_Chdr);
- if (Size <= HdrSize + CompressedContents.size())
- return false;
- // Platform specific header is followed by compressed data.
- if (is64Bit()) {
- // Write Elf64_Chdr header.
- write(static_cast<ELF::Elf64_Word>(ELF::ELFCOMPRESS_ZLIB));
- write(static_cast<ELF::Elf64_Word>(0)); // ch_reserved field.
- write(static_cast<ELF::Elf64_Xword>(Size));
- write(static_cast<ELF::Elf64_Xword>(Alignment));
- } else {
- // Write Elf32_Chdr header otherwise.
- write(static_cast<ELF::Elf32_Word>(ELF::ELFCOMPRESS_ZLIB));
- write(static_cast<ELF::Elf32_Word>(Size));
- write(static_cast<ELF::Elf32_Word>(Alignment));
- }
- return true;
- }
-
- // "ZLIB" followed by 8 bytes representing the uncompressed size of the section,
- // useful for consumers to preallocate a buffer to decompress into.
- const StringRef Magic = "ZLIB";
- if (Size <= Magic.size() + sizeof(Size) + CompressedContents.size())
- return false;
- W.OS << Magic;
- support::endian::write(W.OS, Size, support::big);
- return true;
-}
-
-void ELFWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
- const MCAsmLayout &Layout) {
- MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);
- StringRef SectionName = Section.getSectionName();
-
- auto &MC = Asm.getContext();
- const auto &MAI = MC.getAsmInfo();
-
- // Compressing debug_frame requires handling alignment fragments which is
- // more work (possibly generalizing MCAssembler.cpp:writeFragment to allow
- // for writing to arbitrary buffers) for little benefit.
- bool CompressionEnabled =
- MAI->compressDebugSections() != DebugCompressionType::None;
- if (!CompressionEnabled || !SectionName.startswith(".debug_") ||
- SectionName == ".debug_frame") {
- Asm.writeSectionData(W.OS, &Section, Layout);
- return;
- }
-
- assert((MAI->compressDebugSections() == DebugCompressionType::Z ||
- MAI->compressDebugSections() == DebugCompressionType::GNU) &&
- "expected zlib or zlib-gnu style compression");
-
- SmallVector<char, 128> UncompressedData;
- raw_svector_ostream VecOS(UncompressedData);
- Asm.writeSectionData(VecOS, &Section, Layout);
-
- SmallVector<char, 128> CompressedContents;
- if (Error E = zlib::compress(
- StringRef(UncompressedData.data(), UncompressedData.size()),
- CompressedContents)) {
- consumeError(std::move(E));
- W.OS << UncompressedData;
- return;
- }
-
- bool ZlibStyle = MAI->compressDebugSections() == DebugCompressionType::Z;
- if (!maybeWriteCompression(UncompressedData.size(), CompressedContents,
- ZlibStyle, Sec.getAlignment())) {
- W.OS << UncompressedData;
- return;
- }
-
- if (ZlibStyle) {
- // Set the compressed flag. That is zlib style.
- Section.setFlags(Section.getFlags() | ELF::SHF_COMPRESSED);
- // Alignment field should reflect the requirements of
- // the compressed section header.
- Section.setAlignment(is64Bit() ? 8 : 4);
- } else {
- // Add "z" prefix to section name. This is zlib-gnu style.
- MC.renameELFSection(&Section, (".z" + SectionName.drop_front(1)).str());
- }
- W.OS << CompressedContents;
-}
-
-void ELFWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
- uint64_t Address, uint64_t Offset,
- uint64_t Size, uint32_t Link, uint32_t Info,
- uint64_t Alignment, uint64_t EntrySize) {
- W.write<uint32_t>(Name); // sh_name: index into string table
- W.write<uint32_t>(Type); // sh_type
- WriteWord(Flags); // sh_flags
- WriteWord(Address); // sh_addr
- WriteWord(Offset); // sh_offset
- WriteWord(Size); // sh_size
- W.write<uint32_t>(Link); // sh_link
- W.write<uint32_t>(Info); // sh_info
- WriteWord(Alignment); // sh_addralign
- WriteWord(EntrySize); // sh_entsize
-}
-
-void ELFWriter::writeRelocations(const MCAssembler &Asm,
- const MCSectionELF &Sec) {
- std::vector<ELFRelocationEntry> &Relocs = OWriter.Relocations[&Sec];
-
- // We record relocations by pushing to the end of a vector. Reverse the vector
- // to get the relocations in the order they were created.
- // In most cases that is not important, but it can be for special sections
- // (.eh_frame) or specific relocations (TLS optimizations on SystemZ).
- std::reverse(Relocs.begin(), Relocs.end());
-
- // Sort the relocation entries. MIPS needs this.
- OWriter.TargetObjectWriter->sortRelocs(Asm, Relocs);
-
- for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
- const ELFRelocationEntry &Entry = Relocs[e - i - 1];
- unsigned Index = Entry.Symbol ? Entry.Symbol->getIndex() : 0;
-
- if (is64Bit()) {
- write(Entry.Offset);
- if (OWriter.TargetObjectWriter->getEMachine() == ELF::EM_MIPS) {
- write(uint32_t(Index));
-
- write(OWriter.TargetObjectWriter->getRSsym(Entry.Type));
- write(OWriter.TargetObjectWriter->getRType3(Entry.Type));
- write(OWriter.TargetObjectWriter->getRType2(Entry.Type));
- write(OWriter.TargetObjectWriter->getRType(Entry.Type));
- } else {
- struct ELF::Elf64_Rela ERE64;
- ERE64.setSymbolAndType(Index, Entry.Type);
- write(ERE64.r_info);
- }
- if (hasRelocationAddend())
- write(Entry.Addend);
- } else {
- write(uint32_t(Entry.Offset));
-
- struct ELF::Elf32_Rela ERE32;
- ERE32.setSymbolAndType(Index, Entry.Type);
- write(ERE32.r_info);
-
- if (hasRelocationAddend())
- write(uint32_t(Entry.Addend));
-
- if (OWriter.TargetObjectWriter->getEMachine() == ELF::EM_MIPS) {
- if (uint32_t RType =
- OWriter.TargetObjectWriter->getRType2(Entry.Type)) {
- write(uint32_t(Entry.Offset));
-
- ERE32.setSymbolAndType(0, RType);
- write(ERE32.r_info);
- write(uint32_t(0));
- }
- if (uint32_t RType =
- OWriter.TargetObjectWriter->getRType3(Entry.Type)) {
- write(uint32_t(Entry.Offset));
-
- ERE32.setSymbolAndType(0, RType);
- write(ERE32.r_info);
- write(uint32_t(0));
- }
- }
- }
- }
-}
-
-const MCSectionELF *ELFWriter::createStringTable(MCContext &Ctx) {
- const MCSectionELF *StrtabSection = SectionTable[StringTableIndex - 1];
- StrTabBuilder.write(W.OS);
- return StrtabSection;
-}
-
-void ELFWriter::writeSection(const SectionIndexMapTy &SectionIndexMap,
- uint32_t GroupSymbolIndex, uint64_t Offset,
- uint64_t Size, const MCSectionELF &Section) {
- uint64_t sh_link = 0;
- uint64_t sh_info = 0;
-
- switch(Section.getType()) {
- default:
- // Nothing to do.
- break;
-
- case ELF::SHT_DYNAMIC:
- llvm_unreachable("SHT_DYNAMIC in a relocatable object");
-
- case ELF::SHT_REL:
- case ELF::SHT_RELA: {
- sh_link = SymbolTableIndex;
- assert(sh_link && ".symtab not found");
- const MCSection *InfoSection = Section.getAssociatedSection();
- sh_info = SectionIndexMap.lookup(cast<MCSectionELF>(InfoSection));
- break;
- }
-
- case ELF::SHT_SYMTAB:
- sh_link = StringTableIndex;
- sh_info = LastLocalSymbolIndex;
- break;
-
- case ELF::SHT_SYMTAB_SHNDX:
- case ELF::SHT_LLVM_CALL_GRAPH_PROFILE:
- case ELF::SHT_LLVM_ADDRSIG:
- sh_link = SymbolTableIndex;
- break;
-
- case ELF::SHT_GROUP:
- sh_link = SymbolTableIndex;
- sh_info = GroupSymbolIndex;
- break;
- }
-
- if (Section.getFlags() & ELF::SHF_LINK_ORDER) {
- const MCSymbol *Sym = Section.getAssociatedSymbol();
- const MCSectionELF *Sec = cast<MCSectionELF>(&Sym->getSection());
- sh_link = SectionIndexMap.lookup(Sec);
- }
-
- WriteSecHdrEntry(StrTabBuilder.getOffset(Section.getSectionName()),
- Section.getType(), Section.getFlags(), 0, Offset, Size,
- sh_link, sh_info, Section.getAlignment(),
- Section.getEntrySize());
-}
-
-void ELFWriter::writeSectionHeader(
- const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap,
- const SectionOffsetsTy &SectionOffsets) {
- const unsigned NumSections = SectionTable.size();
-
- // Null section first.
- uint64_t FirstSectionSize =
- (NumSections + 1) >= ELF::SHN_LORESERVE ? NumSections + 1 : 0;
- WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, 0, 0, 0, 0);
-
- for (const MCSectionELF *Section : SectionTable) {
- uint32_t GroupSymbolIndex;
- unsigned Type = Section->getType();
- if (Type != ELF::SHT_GROUP)
- GroupSymbolIndex = 0;
- else
- GroupSymbolIndex = Section->getGroup()->getIndex();
-
- const std::pair<uint64_t, uint64_t> &Offsets =
- SectionOffsets.find(Section)->second;
- uint64_t Size;
- if (Type == ELF::SHT_NOBITS)
- Size = Layout.getSectionAddressSize(Section);
- else
- Size = Offsets.second - Offsets.first;
-
- writeSection(SectionIndexMap, GroupSymbolIndex, Offsets.first, Size,
- *Section);
- }
-}
-
-uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) {
- uint64_t StartOffset = W.OS.tell();
-
- MCContext &Ctx = Asm.getContext();
- MCSectionELF *StrtabSection =
- Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0);
- StringTableIndex = addToSectionTable(StrtabSection);
-
- RevGroupMapTy RevGroupMap;
- SectionIndexMapTy SectionIndexMap;
-
- std::map<const MCSymbol *, std::vector<const MCSectionELF *>> GroupMembers;
-
- // Write out the ELF header ...
- writeHeader(Asm);
-
- // ... then the sections ...
- SectionOffsetsTy SectionOffsets;
- std::vector<MCSectionELF *> Groups;
- std::vector<MCSectionELF *> Relocations;
- for (MCSection &Sec : Asm) {
- MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);
- if (Mode == NonDwoOnly && isDwoSection(Section))
- continue;
- if (Mode == DwoOnly && !isDwoSection(Section))
- continue;
-
- align(Section.getAlignment());
-
- // Remember the offset into the file for this section.
- uint64_t SecStart = W.OS.tell();
-
- const MCSymbolELF *SignatureSymbol = Section.getGroup();
- writeSectionData(Asm, Section, Layout);
-
- uint64_t SecEnd = W.OS.tell();
- SectionOffsets[&Section] = std::make_pair(SecStart, SecEnd);
-
- MCSectionELF *RelSection = createRelocationSection(Ctx, Section);
-
- if (SignatureSymbol) {
- Asm.registerSymbol(*SignatureSymbol);
- unsigned &GroupIdx = RevGroupMap[SignatureSymbol];
- if (!GroupIdx) {
- MCSectionELF *Group = Ctx.createELFGroupSection(SignatureSymbol);
- GroupIdx = addToSectionTable(Group);
- Group->setAlignment(4);
- Groups.push_back(Group);
- }
- std::vector<const MCSectionELF *> &Members =
- GroupMembers[SignatureSymbol];
- Members.push_back(&Section);
- if (RelSection)
- Members.push_back(RelSection);
- }
-
- SectionIndexMap[&Section] = addToSectionTable(&Section);
- if (RelSection) {
- SectionIndexMap[RelSection] = addToSectionTable(RelSection);
- Relocations.push_back(RelSection);
- }
-
- OWriter.TargetObjectWriter->addTargetSectionFlags(Ctx, Section);
- }
-
- MCSectionELF *CGProfileSection = nullptr;
- if (!Asm.CGProfile.empty()) {
- CGProfileSection = Ctx.getELFSection(".llvm.call-graph-profile",
- ELF::SHT_LLVM_CALL_GRAPH_PROFILE,
- ELF::SHF_EXCLUDE, 16, "");
- SectionIndexMap[CGProfileSection] = addToSectionTable(CGProfileSection);
- }
-
- for (MCSectionELF *Group : Groups) {
- align(Group->getAlignment());
-
- // Remember the offset into the file for this section.
- uint64_t SecStart = W.OS.tell();
-
- const MCSymbol *SignatureSymbol = Group->getGroup();
- assert(SignatureSymbol);
- write(uint32_t(ELF::GRP_COMDAT));
- for (const MCSectionELF *Member : GroupMembers[SignatureSymbol]) {
- uint32_t SecIndex = SectionIndexMap.lookup(Member);
- write(SecIndex);
- }
-
- uint64_t SecEnd = W.OS.tell();
- SectionOffsets[Group] = std::make_pair(SecStart, SecEnd);
- }
-
- if (Mode == DwoOnly) {
- // dwo files don't have symbol tables or relocations, but they do have
- // string tables.
- StrTabBuilder.finalize();
- } else {
- MCSectionELF *AddrsigSection;
- if (OWriter.EmitAddrsigSection) {
- AddrsigSection = Ctx.getELFSection(".llvm_addrsig", ELF::SHT_LLVM_ADDRSIG,
- ELF::SHF_EXCLUDE);
- addToSectionTable(AddrsigSection);
- }
-
- // Compute symbol table information.
- computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap,
- SectionOffsets);
-
- for (MCSectionELF *RelSection : Relocations) {
- align(RelSection->getAlignment());
-
- // Remember the offset into the file for this section.
- uint64_t SecStart = W.OS.tell();
-
- writeRelocations(Asm,
- cast<MCSectionELF>(*RelSection->getAssociatedSection()));
-
- uint64_t SecEnd = W.OS.tell();
- SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd);
- }
-
- if (OWriter.EmitAddrsigSection) {
- uint64_t SecStart = W.OS.tell();
- writeAddrsigSection();
- uint64_t SecEnd = W.OS.tell();
- SectionOffsets[AddrsigSection] = std::make_pair(SecStart, SecEnd);
- }
- }
-
- if (CGProfileSection) {
- uint64_t SecStart = W.OS.tell();
- for (const MCAssembler::CGProfileEntry &CGPE : Asm.CGProfile) {
- W.write<uint32_t>(CGPE.From->getSymbol().getIndex());
- W.write<uint32_t>(CGPE.To->getSymbol().getIndex());
- W.write<uint64_t>(CGPE.Count);
- }
- uint64_t SecEnd = W.OS.tell();
- SectionOffsets[CGProfileSection] = std::make_pair(SecStart, SecEnd);
- }
-
- {
- uint64_t SecStart = W.OS.tell();
- const MCSectionELF *Sec = createStringTable(Ctx);
- uint64_t SecEnd = W.OS.tell();
- SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd);
- }
-
- uint64_t NaturalAlignment = is64Bit() ? 8 : 4;
- align(NaturalAlignment);
-
- const uint64_t SectionHeaderOffset = W.OS.tell();
-
- // ... then the section header table ...
- writeSectionHeader(Layout, SectionIndexMap, SectionOffsets);
-
- uint16_t NumSections = support::endian::byte_swap<uint16_t>(
- (SectionTable.size() + 1 >= ELF::SHN_LORESERVE) ? (uint16_t)ELF::SHN_UNDEF
- : SectionTable.size() + 1,
- W.Endian);
- unsigned NumSectionsOffset;
-
- auto &Stream = static_cast<raw_pwrite_stream &>(W.OS);
- if (is64Bit()) {
- uint64_t Val =
- support::endian::byte_swap<uint64_t>(SectionHeaderOffset, W.Endian);
- Stream.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
- offsetof(ELF::Elf64_Ehdr, e_shoff));
- NumSectionsOffset = offsetof(ELF::Elf64_Ehdr, e_shnum);
- } else {
- uint32_t Val =
- support::endian::byte_swap<uint32_t>(SectionHeaderOffset, W.Endian);
- Stream.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
- offsetof(ELF::Elf32_Ehdr, e_shoff));
- NumSectionsOffset = offsetof(ELF::Elf32_Ehdr, e_shnum);
- }
- Stream.pwrite(reinterpret_cast<char *>(&NumSections), sizeof(NumSections),
- NumSectionsOffset);
-
- return W.OS.tell() - StartOffset;
-}
-
-bool ELFObjectWriter::hasRelocationAddend() const {
- return TargetObjectWriter->hasRelocationAddend();
-}
-
-void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
- const MCAsmLayout &Layout) {
- // The presence of symbol versions causes undefined symbols and
- // versions declared with @@@ to be renamed.
- for (const std::pair<StringRef, const MCSymbol *> &P : Asm.Symvers) {
- StringRef AliasName = P.first;
- const auto &Symbol = cast<MCSymbolELF>(*P.second);
- size_t Pos = AliasName.find('@');
- assert(Pos != StringRef::npos);
-
- StringRef Prefix = AliasName.substr(0, Pos);
- StringRef Rest = AliasName.substr(Pos);
- StringRef Tail = Rest;
- if (Rest.startswith("@@@"))
- Tail = Rest.substr(Symbol.isUndefined() ? 2 : 1);
-
- auto *Alias =
- cast<MCSymbolELF>(Asm.getContext().getOrCreateSymbol(Prefix + Tail));
- Asm.registerSymbol(*Alias);
- const MCExpr *Value = MCSymbolRefExpr::create(&Symbol, Asm.getContext());
- Alias->setVariableValue(Value);
-
- // Aliases defined with .symvar copy the binding from the symbol they alias.
- // This is the first place we are able to copy this information.
- Alias->setExternal(Symbol.isExternal());
- Alias->setBinding(Symbol.getBinding());
- Alias->setOther(Symbol.getOther());
-
- if (!Symbol.isUndefined() && !Rest.startswith("@@@"))
- continue;
-
- // FIXME: Get source locations for these errors or diagnose them earlier.
- if (Symbol.isUndefined() && Rest.startswith("@@") &&
- !Rest.startswith("@@@")) {
- Asm.getContext().reportError(SMLoc(), "versioned symbol " + AliasName +
- " must be defined");
- continue;
- }
-
- if (Renames.count(&Symbol) && Renames[&Symbol] != Alias) {
- Asm.getContext().reportError(
- SMLoc(), llvm::Twine("multiple symbol versions defined for ") +
- Symbol.getName());
- continue;
- }
-
- Renames.insert(std::make_pair(&Symbol, Alias));
- }
-
- for (const MCSymbol *&Sym : AddrsigSyms) {
- if (const MCSymbol *R = Renames.lookup(cast<MCSymbolELF>(Sym)))
- Sym = R;
- if (Sym->isInSection() && Sym->getName().startswith(".L"))
- Sym = Sym->getSection().getBeginSymbol();
- Sym->setUsedInReloc();
- }
-}
-
-// It is always valid to create a relocation with a symbol. It is preferable
-// to use a relocation with a section if that is possible. Using the section
-// allows us to omit some local symbols from the symbol table.
-bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm,
- const MCSymbolRefExpr *RefA,
- const MCSymbolELF *Sym,
- uint64_t C,
- unsigned Type) const {
- // A PCRel relocation to an absolute value has no symbol (or section). We
- // represent that with a relocation to a null section.
- if (!RefA)
- return false;
-
- MCSymbolRefExpr::VariantKind Kind = RefA->getKind();
- switch (Kind) {
- default:
- break;
- // The .odp creation emits a relocation against the symbol ".TOC." which
- // create a R_PPC64_TOC relocation. However the relocation symbol name
- // in final object creation should be NULL, since the symbol does not
- // really exist, it is just the reference to TOC base for the current
- // object file. Since the symbol is undefined, returning false results
- // in a relocation with a null section which is the desired result.
- case MCSymbolRefExpr::VK_PPC_TOCBASE:
- return false;
-
- // These VariantKind cause the relocation to refer to something other than
- // the symbol itself, like a linker generated table. Since the address of
- // symbol is not relevant, we cannot replace the symbol with the
- // section and patch the difference in the addend.
- case MCSymbolRefExpr::VK_GOT:
- case MCSymbolRefExpr::VK_PLT:
- case MCSymbolRefExpr::VK_GOTPCREL:
- case MCSymbolRefExpr::VK_PPC_GOT_LO:
- case MCSymbolRefExpr::VK_PPC_GOT_HI:
- case MCSymbolRefExpr::VK_PPC_GOT_HA:
- return true;
- }
-
- // An undefined symbol is not in any section, so the relocation has to point
- // to the symbol itself.
- assert(Sym && "Expected a symbol");
- if (Sym->isUndefined())
- return true;
-
- unsigned Binding = Sym->getBinding();
- switch(Binding) {
- default:
- llvm_unreachable("Invalid Binding");
- case ELF::STB_LOCAL:
- break;
- case ELF::STB_WEAK:
- // If the symbol is weak, it might be overridden by a symbol in another
- // file. The relocation has to point to the symbol so that the linker
- // can update it.
- return true;
- case ELF::STB_GLOBAL:
- // Global ELF symbols can be preempted by the dynamic linker. The relocation
- // has to point to the symbol for a reason analogous to the STB_WEAK case.
- return true;
- }
-
- // Keep symbol type for a local ifunc because it may result in an IRELATIVE
- // reloc that the dynamic loader will use to resolve the address at startup
- // time.
- if (Sym->getType() == ELF::STT_GNU_IFUNC)
- return true;
-
- // If a relocation points to a mergeable section, we have to be careful.
- // If the offset is zero, a relocation with the section will encode the
- // same information. With a non-zero offset, the situation is different.
- // For example, a relocation can point 42 bytes past the end of a string.
- // If we change such a relocation to use the section, the linker would think
- // that it pointed to another string and subtracting 42 at runtime will
- // produce the wrong value.
- if (Sym->isInSection()) {
- auto &Sec = cast<MCSectionELF>(Sym->getSection());
- unsigned Flags = Sec.getFlags();
- if (Flags & ELF::SHF_MERGE) {
- if (C != 0)
- return true;
-
- // It looks like gold has a bug (http://sourceware.org/PR16794) and can
- // only handle section relocations to mergeable sections if using RELA.
- if (!hasRelocationAddend())
- return true;
- }
-
- // Most TLS relocations use a got, so they need the symbol. Even those that
- // are just an offset (@tpoff), require a symbol in gold versions before
- // 5efeedf61e4fe720fd3e9a08e6c91c10abb66d42 (2014-09-26) which fixed
- // http://sourceware.org/PR16773.
- if (Flags & ELF::SHF_TLS)
- return true;
- }
-
- // If the symbol is a thumb function the final relocation must set the lowest
- // bit. With a symbol that is done by just having the symbol have that bit
- // set, so we would lose the bit if we relocated with the section.
- // FIXME: We could use the section but add the bit to the relocation value.
- if (Asm.isThumbFunc(Sym))
- return true;
-
- if (TargetObjectWriter->needsRelocateWithSymbol(*Sym, Type))
- return true;
- return false;
-}
-
-void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup, MCValue Target,
- uint64_t &FixedValue) {
- MCAsmBackend &Backend = Asm.getBackend();
- bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
- MCFixupKindInfo::FKF_IsPCRel;
- const MCSectionELF &FixupSection = cast<MCSectionELF>(*Fragment->getParent());
- uint64_t C = Target.getConstant();
- uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
- MCContext &Ctx = Asm.getContext();
-
- if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
- // Let A, B and C being the components of Target and R be the location of
- // the fixup. If the fixup is not pcrel, we want to compute (A - B + C).
- // If it is pcrel, we want to compute (A - B + C - R).
-
- // In general, ELF has no relocations for -B. It can only represent (A + C)
- // or (A + C - R). If B = R + K and the relocation is not pcrel, we can
- // replace B to implement it: (A - R - K + C)
- if (IsPCRel) {
- Ctx.reportError(
- Fixup.getLoc(),
- "No relocation available to represent this relative expression");
- return;
- }
-
- const auto &SymB = cast<MCSymbolELF>(RefB->getSymbol());
-
- if (SymB.isUndefined()) {
- Ctx.reportError(Fixup.getLoc(),
- Twine("symbol '") + SymB.getName() +
- "' can not be undefined in a subtraction expression");
- return;
- }
-
- assert(!SymB.isAbsolute() && "Should have been folded");
- const MCSection &SecB = SymB.getSection();
- if (&SecB != &FixupSection) {
- Ctx.reportError(Fixup.getLoc(),
- "Cannot represent a difference across sections");
- return;
- }
-
- uint64_t SymBOffset = Layout.getSymbolOffset(SymB);
- uint64_t K = SymBOffset - FixupOffset;
- IsPCRel = true;
- C -= K;
- }
-
- // We either rejected the fixup or folded B into C at this point.
- const MCSymbolRefExpr *RefA = Target.getSymA();
- const auto *SymA = RefA ? cast<MCSymbolELF>(&RefA->getSymbol()) : nullptr;
-
- bool ViaWeakRef = false;
- if (SymA && SymA->isVariable()) {
- const MCExpr *Expr = SymA->getVariableValue();
- if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr)) {
- if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) {
- SymA = cast<MCSymbolELF>(&Inner->getSymbol());
- ViaWeakRef = true;
- }
- }
- }
-
- unsigned Type = TargetObjectWriter->getRelocType(Ctx, Target, Fixup, IsPCRel);
- uint64_t OriginalC = C;
- bool RelocateWithSymbol = shouldRelocateWithSymbol(Asm, RefA, SymA, C, Type);
- if (!RelocateWithSymbol && SymA && !SymA->isUndefined())
- C += Layout.getSymbolOffset(*SymA);
-
- uint64_t Addend = 0;
- if (hasRelocationAddend()) {
- Addend = C;
- C = 0;
- }
-
- FixedValue = C;
-
- const MCSectionELF *SecA = (SymA && SymA->isInSection())
- ? cast<MCSectionELF>(&SymA->getSection())
- : nullptr;
- if (!checkRelocation(Ctx, Fixup.getLoc(), &FixupSection, SecA))
- return;
-
- if (!RelocateWithSymbol) {
- const auto *SectionSymbol =
- SecA ? cast<MCSymbolELF>(SecA->getBeginSymbol()) : nullptr;
- if (SectionSymbol)
- SectionSymbol->setUsedInReloc();
- ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend, SymA,
- OriginalC);
- Relocations[&FixupSection].push_back(Rec);
- return;
- }
-
- const auto *RenamedSymA = SymA;
- if (SymA) {
- if (const MCSymbolELF *R = Renames.lookup(SymA))
- RenamedSymA = R;
-
- if (ViaWeakRef)
- RenamedSymA->setIsWeakrefUsedInReloc();
- else
- RenamedSymA->setUsedInReloc();
- }
- ELFRelocationEntry Rec(FixupOffset, RenamedSymA, Type, Addend, SymA,
- OriginalC);
- Relocations[&FixupSection].push_back(Rec);
-}
-
-bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
- const MCAssembler &Asm, const MCSymbol &SA, const MCFragment &FB,
- bool InSet, bool IsPCRel) const {
- const auto &SymA = cast<MCSymbolELF>(SA);
- if (IsPCRel) {
- assert(!InSet);
- if (isWeak(SymA))
- return false;
- }
- return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
- InSet, IsPCRel);
-}
-
-std::unique_ptr<MCObjectWriter>
-llvm::createELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
- raw_pwrite_stream &OS, bool IsLittleEndian) {
- return llvm::make_unique<ELFSingleObjectWriter>(std::move(MOTW), OS,
- IsLittleEndian);
-}
-
-std::unique_ptr<MCObjectWriter>
-llvm::createELFDwoObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
- raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS,
- bool IsLittleEndian) {
- return llvm::make_unique<ELFDwoObjectWriter>(std::move(MOTW), OS, DwoOS,
- IsLittleEndian);
-}
diff --git a/contrib/llvm/lib/MC/MCAsmBackend.cpp b/contrib/llvm/lib/MC/MCAsmBackend.cpp
deleted file mode 100644
index b800e9caee22..000000000000
--- a/contrib/llvm/lib/MC/MCAsmBackend.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-//===- MCAsmBackend.cpp - Target MC Assembly Backend ----------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/ADT/None.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/MC/MCCodePadder.h"
-#include "llvm/MC/MCELFObjectWriter.h"
-#include "llvm/MC/MCFixupKindInfo.h"
-#include "llvm/MC/MCMachObjectWriter.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCWasmObjectWriter.h"
-#include "llvm/MC/MCWinCOFFObjectWriter.h"
-#include "llvm/MC/MCXCOFFObjectWriter.h"
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-
-using namespace llvm;
-
-MCAsmBackend::MCAsmBackend(support::endianness Endian)
- : CodePadder(new MCCodePadder()), Endian(Endian) {}
-
-MCAsmBackend::~MCAsmBackend() = default;
-
-std::unique_ptr<MCObjectWriter>
-MCAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
- auto TW = createObjectTargetWriter();
- switch (TW->getFormat()) {
- case Triple::ELF:
- return createELFObjectWriter(cast<MCELFObjectTargetWriter>(std::move(TW)), OS,
- Endian == support::little);
- case Triple::MachO:
- return createMachObjectWriter(cast<MCMachObjectTargetWriter>(std::move(TW)),
- OS, Endian == support::little);
- case Triple::COFF:
- return createWinCOFFObjectWriter(
- cast<MCWinCOFFObjectTargetWriter>(std::move(TW)), OS);
- case Triple::Wasm:
- return createWasmObjectWriter(cast<MCWasmObjectTargetWriter>(std::move(TW)),
- OS);
- case Triple::XCOFF:
- return createXCOFFObjectWriter(
- cast<MCXCOFFObjectTargetWriter>(std::move(TW)), OS);
- default:
- llvm_unreachable("unexpected object format");
- }
-}
-
-std::unique_ptr<MCObjectWriter>
-MCAsmBackend::createDwoObjectWriter(raw_pwrite_stream &OS,
- raw_pwrite_stream &DwoOS) const {
- auto TW = createObjectTargetWriter();
- if (TW->getFormat() != Triple::ELF)
- report_fatal_error("dwo only supported with ELF");
- return createELFDwoObjectWriter(cast<MCELFObjectTargetWriter>(std::move(TW)),
- OS, DwoOS, Endian == support::little);
-}
-
-Optional<MCFixupKind> MCAsmBackend::getFixupKind(StringRef Name) const {
- return None;
-}
-
-const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
- static const MCFixupKindInfo Builtins[] = {
- {"FK_NONE", 0, 0, 0},
- {"FK_Data_1", 0, 8, 0},
- {"FK_Data_2", 0, 16, 0},
- {"FK_Data_4", 0, 32, 0},
- {"FK_Data_8", 0, 64, 0},
- {"FK_Data_6b", 0, 6, 0},
- {"FK_PCRel_1", 0, 8, MCFixupKindInfo::FKF_IsPCRel},
- {"FK_PCRel_2", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
- {"FK_PCRel_4", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
- {"FK_PCRel_8", 0, 64, MCFixupKindInfo::FKF_IsPCRel},
- {"FK_GPRel_1", 0, 8, 0},
- {"FK_GPRel_2", 0, 16, 0},
- {"FK_GPRel_4", 0, 32, 0},
- {"FK_GPRel_8", 0, 64, 0},
- {"FK_DTPRel_4", 0, 32, 0},
- {"FK_DTPRel_8", 0, 64, 0},
- {"FK_TPRel_4", 0, 32, 0},
- {"FK_TPRel_8", 0, 64, 0},
- {"FK_SecRel_1", 0, 8, 0},
- {"FK_SecRel_2", 0, 16, 0},
- {"FK_SecRel_4", 0, 32, 0},
- {"FK_SecRel_8", 0, 64, 0},
- {"FK_Data_Add_1", 0, 8, 0},
- {"FK_Data_Add_2", 0, 16, 0},
- {"FK_Data_Add_4", 0, 32, 0},
- {"FK_Data_Add_8", 0, 64, 0},
- {"FK_Data_Add_6b", 0, 6, 0},
- {"FK_Data_Sub_1", 0, 8, 0},
- {"FK_Data_Sub_2", 0, 16, 0},
- {"FK_Data_Sub_4", 0, 32, 0},
- {"FK_Data_Sub_8", 0, 64, 0},
- {"FK_Data_Sub_6b", 0, 6, 0}};
-
- assert((size_t)Kind <= array_lengthof(Builtins) && "Unknown fixup kind");
- return Builtins[Kind];
-}
-
-bool MCAsmBackend::fixupNeedsRelaxationAdvanced(
- const MCFixup &Fixup, bool Resolved, uint64_t Value,
- const MCRelaxableFragment *DF, const MCAsmLayout &Layout,
- const bool WasForced) const {
- if (!Resolved)
- return true;
- return fixupNeedsRelaxation(Fixup, Value, DF, Layout);
-}
-
-void MCAsmBackend::handleCodePaddingBasicBlockStart(
- MCObjectStreamer *OS, const MCCodePaddingContext &Context) {
- CodePadder->handleBasicBlockStart(OS, Context);
-}
-
-void MCAsmBackend::handleCodePaddingBasicBlockEnd(
- const MCCodePaddingContext &Context) {
- CodePadder->handleBasicBlockEnd(Context);
-}
-
-void MCAsmBackend::handleCodePaddingInstructionBegin(const MCInst &Inst) {
- CodePadder->handleInstructionBegin(Inst);
-}
-
-void MCAsmBackend::handleCodePaddingInstructionEnd(const MCInst &Inst) {
- CodePadder->handleInstructionEnd(Inst);
-}
-
-bool MCAsmBackend::relaxFragment(MCPaddingFragment *PF, MCAsmLayout &Layout) {
- return CodePadder->relaxFragment(PF, Layout);
-}
diff --git a/contrib/llvm/lib/MC/MCAsmInfo.cpp b/contrib/llvm/lib/MC/MCAsmInfo.cpp
deleted file mode 100644
index 71e51e320f8b..000000000000
--- a/contrib/llvm/lib/MC/MCAsmInfo.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-//===- MCAsmInfo.cpp - Asm Info -------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines target asm properties related what form asm statements
-// should take.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/BinaryFormat/Dwarf.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/Support/CommandLine.h"
-
-using namespace llvm;
-
-enum DefaultOnOff { Default, Enable, Disable };
-static cl::opt<DefaultOnOff> DwarfExtendedLoc(
- "dwarf-extended-loc", cl::Hidden,
- cl::desc("Disable emission of the extended flags in .loc directives."),
- cl::values(clEnumVal(Default, "Default for platform"),
- clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")),
- cl::init(Default));
-
-MCAsmInfo::MCAsmInfo() {
- SeparatorString = ";";
- CommentString = "#";
- LabelSuffix = ":";
- PrivateGlobalPrefix = "L";
- PrivateLabelPrefix = PrivateGlobalPrefix;
- LinkerPrivateGlobalPrefix = "";
- InlineAsmStart = "APP";
- InlineAsmEnd = "NO_APP";
- Code16Directive = ".code16";
- Code32Directive = ".code32";
- Code64Directive = ".code64";
- ZeroDirective = "\t.zero\t";
- AsciiDirective = "\t.ascii\t";
- AscizDirective = "\t.asciz\t";
- Data8bitsDirective = "\t.byte\t";
- Data16bitsDirective = "\t.short\t";
- Data32bitsDirective = "\t.long\t";
- Data64bitsDirective = "\t.quad\t";
- GlobalDirective = "\t.globl\t";
- WeakDirective = "\t.weak\t";
- if (DwarfExtendedLoc != Default)
- SupportsExtendedDwarfLocDirective = DwarfExtendedLoc == Enable;
-
- // FIXME: Clang's logic should be synced with the logic used to initialize
- // this member and the two implementations should be merged.
- // For reference:
- // - Solaris always enables the integrated assembler by default
- // - SparcELFMCAsmInfo and X86ELFMCAsmInfo are handling this case
- // - Windows always enables the integrated assembler by default
- // - MCAsmInfoCOFF is handling this case, should it be MCAsmInfoMicrosoft?
- // - MachO targets always enables the integrated assembler by default
- // - MCAsmInfoDarwin is handling this case
- // - Generic_GCC toolchains enable the integrated assembler on a per
- // architecture basis.
- // - The target subclasses for AArch64, ARM, and X86 handle these cases
- UseIntegratedAssembler = false;
- PreserveAsmComments = true;
-}
-
-MCAsmInfo::~MCAsmInfo() = default;
-
-void MCAsmInfo::addInitialFrameState(const MCCFIInstruction &Inst) {
- InitialFrameState.push_back(Inst);
-}
-
-bool MCAsmInfo::isSectionAtomizableBySymbols(const MCSection &Section) const {
- return false;
-}
-
-const MCExpr *
-MCAsmInfo::getExprForPersonalitySymbol(const MCSymbol *Sym,
- unsigned Encoding,
- MCStreamer &Streamer) const {
- return getExprForFDESymbol(Sym, Encoding, Streamer);
-}
-
-const MCExpr *
-MCAsmInfo::getExprForFDESymbol(const MCSymbol *Sym,
- unsigned Encoding,
- MCStreamer &Streamer) const {
- if (!(Encoding & dwarf::DW_EH_PE_pcrel))
- return MCSymbolRefExpr::create(Sym, Streamer.getContext());
-
- MCContext &Context = Streamer.getContext();
- const MCExpr *Res = MCSymbolRefExpr::create(Sym, Context);
- MCSymbol *PCSym = Context.createTempSymbol();
- Streamer.EmitLabel(PCSym);
- const MCExpr *PC = MCSymbolRefExpr::create(PCSym, Context);
- return MCBinaryExpr::createSub(Res, PC, Context);
-}
-
-static bool isAcceptableChar(char C) {
- return (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z') ||
- (C >= '0' && C <= '9') || C == '_' || C == '$' || C == '.' || C == '@';
-}
-
-bool MCAsmInfo::isValidUnquotedName(StringRef Name) const {
- if (Name.empty())
- return false;
-
- // If any of the characters in the string is an unacceptable character, force
- // quotes.
- for (char C : Name) {
- if (!isAcceptableChar(C))
- return false;
- }
-
- return true;
-}
-
-bool MCAsmInfo::shouldOmitSectionDirective(StringRef SectionName) const {
- // FIXME: Does .section .bss/.data/.text work everywhere??
- return SectionName == ".text" || SectionName == ".data" ||
- (SectionName == ".bss" && !usesELFSectionDirectiveForBSS());
-}
diff --git a/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp b/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp
deleted file mode 100644
index 9f19d163f57b..000000000000
--- a/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-//===- MCAsmInfoCOFF.cpp - COFF asm properties ----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines target asm properties related what form asm statements
-// should take in general on COFF-based targets
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCAsmInfoCOFF.h"
-#include "llvm/MC/MCDirectives.h"
-
-using namespace llvm;
-
-void MCAsmInfoCOFF::anchor() {}
-
-MCAsmInfoCOFF::MCAsmInfoCOFF() {
- // MingW 4.5 and later support .comm with log2 alignment, but .lcomm uses byte
- // alignment.
- COMMDirectiveAlignmentIsInBytes = false;
- LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment;
- HasDotTypeDotSizeDirective = false;
- HasSingleParameterDotFile = true;
- WeakRefDirective = "\t.weak\t";
- HasLinkOnceDirective = true;
-
- // Doesn't support visibility:
- HiddenVisibilityAttr = HiddenDeclarationVisibilityAttr = MCSA_Invalid;
- ProtectedVisibilityAttr = MCSA_Invalid;
-
- // Set up DWARF directives
- SupportsDebugInformation = true;
- NeedsDwarfSectionOffsetDirective = true;
-
- UseIntegratedAssembler = true;
-
- // At least MSVC inline-asm does AShr.
- UseLogicalShr = false;
-
- // If this is a COFF target, assume that it supports associative comdats. It's
- // part of the spec.
- HasCOFFAssociativeComdats = true;
-
- // We can generate constants in comdat sections that can be shared,
- // but in order not to create null typed symbols, we actually need to
- // make them global symbols as well.
- HasCOFFComdatConstants = true;
-}
-
-void MCAsmInfoMicrosoft::anchor() {}
-
-MCAsmInfoMicrosoft::MCAsmInfoMicrosoft() = default;
-
-void MCAsmInfoGNUCOFF::anchor() {}
-
-MCAsmInfoGNUCOFF::MCAsmInfoGNUCOFF() {
- // If this is a GNU environment (mingw or cygwin), don't use associative
- // comdats for jump tables, unwind information, and other data associated with
- // a function.
- HasCOFFAssociativeComdats = false;
-
- // We don't create constants in comdat sections for MinGW.
- HasCOFFComdatConstants = false;
-}
diff --git a/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp b/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp
deleted file mode 100644
index 62bc5b8c9418..000000000000
--- a/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-//===- MCAsmInfoDarwin.cpp - Darwin asm properties ------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines target asm properties related what form asm statements
-// should take in general on Darwin-based targets
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCAsmInfoDarwin.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/MC/MCDirectives.h"
-#include "llvm/MC/MCSectionMachO.h"
-
-using namespace llvm;
-
-bool MCAsmInfoDarwin::isSectionAtomizableBySymbols(
- const MCSection &Section) const {
- const MCSectionMachO &SMO = static_cast<const MCSectionMachO &>(Section);
-
- // Sections holding 1 byte strings are atomized based on the data they
- // contain.
- // Sections holding 2 byte strings require symbols in order to be atomized.
- // There is no dedicated section for 4 byte strings.
- if (SMO.getType() == MachO::S_CSTRING_LITERALS)
- return false;
-
- if (SMO.getSegmentName() == "__DATA" && SMO.getSectionName() == "__cfstring")
- return false;
-
- if (SMO.getSegmentName() == "__DATA" &&
- SMO.getSectionName() == "__objc_classrefs")
- return false;
-
- switch (SMO.getType()) {
- default:
- return true;
-
- // These sections are atomized at the element boundaries without using
- // symbols.
- case MachO::S_4BYTE_LITERALS:
- case MachO::S_8BYTE_LITERALS:
- case MachO::S_16BYTE_LITERALS:
- case MachO::S_LITERAL_POINTERS:
- case MachO::S_NON_LAZY_SYMBOL_POINTERS:
- case MachO::S_LAZY_SYMBOL_POINTERS:
- case MachO::S_THREAD_LOCAL_VARIABLE_POINTERS:
- case MachO::S_MOD_INIT_FUNC_POINTERS:
- case MachO::S_MOD_TERM_FUNC_POINTERS:
- case MachO::S_INTERPOSING:
- return false;
- }
-}
-
-MCAsmInfoDarwin::MCAsmInfoDarwin() {
- // Common settings for all Darwin targets.
- // Syntax:
- LinkerPrivateGlobalPrefix = "l";
- HasSingleParameterDotFile = false;
- HasSubsectionsViaSymbols = true;
-
- AlignmentIsInBytes = false;
- COMMDirectiveAlignmentIsInBytes = false;
- LCOMMDirectiveAlignmentType = LCOMM::Log2Alignment;
- InlineAsmStart = " InlineAsm Start";
- InlineAsmEnd = " InlineAsm End";
-
- // Directives:
- HasWeakDefDirective = true;
- HasWeakDefCanBeHiddenDirective = true;
- WeakRefDirective = "\t.weak_reference ";
- ZeroDirective = "\t.space\t"; // ".space N" emits N zeros.
- HasMachoZeroFillDirective = true; // Uses .zerofill
- HasMachoTBSSDirective = true; // Uses .tbss
-
- // FIXME: Change this once MC is the system assembler.
- HasAggressiveSymbolFolding = false;
-
- HiddenVisibilityAttr = MCSA_PrivateExtern;
- HiddenDeclarationVisibilityAttr = MCSA_Invalid;
-
- // Doesn't support protected visibility.
- ProtectedVisibilityAttr = MCSA_Invalid;
-
- HasDotTypeDotSizeDirective = false;
- HasNoDeadStrip = true;
- HasAltEntry = true;
-
- DwarfUsesRelocationsAcrossSections = false;
-
- UseIntegratedAssembler = true;
- SetDirectiveSuppressesReloc = true;
-}
diff --git a/contrib/llvm/lib/MC/MCAsmInfoELF.cpp b/contrib/llvm/lib/MC/MCAsmInfoELF.cpp
deleted file mode 100644
index a5e8aff7f129..000000000000
--- a/contrib/llvm/lib/MC/MCAsmInfoELF.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- MCAsmInfoELF.cpp - ELF asm properties ------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines target asm properties related what form asm statements
-// should take in general on ELF-based targets
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCAsmInfoELF.h"
-#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCSectionELF.h"
-
-using namespace llvm;
-
-void MCAsmInfoELF::anchor() {}
-
-MCSection *MCAsmInfoELF::getNonexecutableStackSection(MCContext &Ctx) const {
- if (!UsesNonexecutableStackSection)
- return nullptr;
- return Ctx.getELFSection(".note.GNU-stack", ELF::SHT_PROGBITS, 0);
-}
-
-MCAsmInfoELF::MCAsmInfoELF() {
- HasIdentDirective = true;
- WeakRefDirective = "\t.weak\t";
- PrivateGlobalPrefix = ".L";
- PrivateLabelPrefix = ".L";
-}
diff --git a/contrib/llvm/lib/MC/MCAsmInfoWasm.cpp b/contrib/llvm/lib/MC/MCAsmInfoWasm.cpp
deleted file mode 100644
index ce6ec7ef211e..000000000000
--- a/contrib/llvm/lib/MC/MCAsmInfoWasm.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-//===-- MCAsmInfoWasm.cpp - Wasm asm properties -----------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines target asm properties related what form asm statements
-// should take in general on Wasm-based targets
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCAsmInfoWasm.h"
-using namespace llvm;
-
-void MCAsmInfoWasm::anchor() {}
-
-MCAsmInfoWasm::MCAsmInfoWasm() {
- HasIdentDirective = true;
- HasNoDeadStrip = true;
- WeakRefDirective = "\t.weak\t";
- PrivateGlobalPrefix = ".L";
- PrivateLabelPrefix = ".L";
-}
diff --git a/contrib/llvm/lib/MC/MCAsmInfoXCOFF.cpp b/contrib/llvm/lib/MC/MCAsmInfoXCOFF.cpp
deleted file mode 100644
index 74c21f0c9e6d..000000000000
--- a/contrib/llvm/lib/MC/MCAsmInfoXCOFF.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-//===- MC/MCAsmInfoXCOFF.cpp - XCOFF asm properties ------------ *- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCAsmInfoXCOFF.h"
-
-using namespace llvm;
-
-void MCAsmInfoXCOFF::anchor() {}
-
-MCAsmInfoXCOFF::MCAsmInfoXCOFF() {
- IsLittleEndian = false;
- HasDotTypeDotSizeDirective = false;
-}
diff --git a/contrib/llvm/lib/MC/MCAsmMacro.cpp b/contrib/llvm/lib/MC/MCAsmMacro.cpp
deleted file mode 100644
index ba4fb7d4f387..000000000000
--- a/contrib/llvm/lib/MC/MCAsmMacro.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-//===- MCAsmMacro.h - Assembly Macros ---------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCAsmMacro.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-void MCAsmMacroParameter::dump(raw_ostream &OS) const {
- OS << "\"" << Name << "\"";
- if (Required)
- OS << ":req";
- if (Vararg)
- OS << ":vararg";
- if (!Value.empty()) {
- OS << " = ";
- bool first = true;
- for (const AsmToken &T : Value) {
- if (!first)
- OS << ", ";
- first = false;
- OS << T.getString();
- }
- }
- OS << "\n";
-}
-
-void MCAsmMacro::dump(raw_ostream &OS) const {
- OS << "Macro " << Name << ":\n";
- OS << " Parameters:\n";
- for (const MCAsmMacroParameter &P : Parameters) {
- OS << " ";
- P.dump();
- }
- OS << " (BEGIN BODY)" << Body << "(END BODY)\n";
-}
diff --git a/contrib/llvm/lib/MC/MCAsmStreamer.cpp b/contrib/llvm/lib/MC/MCAsmStreamer.cpp
deleted file mode 100644
index 7a2b0b8a1220..000000000000
--- a/contrib/llvm/lib/MC/MCAsmStreamer.cpp
+++ /dev/null
@@ -1,1941 +0,0 @@
-//===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output ----------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCCodeEmitter.h"
-#include "llvm/MC/MCCodeView.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCFixupKindInfo.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCInstPrinter.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCSectionMachO.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/LEB128.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/TargetRegistry.h"
-#include <cctype>
-
-using namespace llvm;
-
-namespace {
-
-class MCAsmStreamer final : public MCStreamer {
- std::unique_ptr<formatted_raw_ostream> OSOwner;
- formatted_raw_ostream &OS;
- const MCAsmInfo *MAI;
- std::unique_ptr<MCInstPrinter> InstPrinter;
- std::unique_ptr<MCAssembler> Assembler;
-
- SmallString<128> ExplicitCommentToEmit;
- SmallString<128> CommentToEmit;
- raw_svector_ostream CommentStream;
- raw_null_ostream NullStream;
-
- unsigned IsVerboseAsm : 1;
- unsigned ShowInst : 1;
- unsigned UseDwarfDirectory : 1;
-
- void EmitRegisterName(int64_t Register);
- void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
- void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
-
-public:
- MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os,
- bool isVerboseAsm, bool useDwarfDirectory,
- MCInstPrinter *printer, std::unique_ptr<MCCodeEmitter> emitter,
- std::unique_ptr<MCAsmBackend> asmbackend, bool showInst)
- : MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner),
- MAI(Context.getAsmInfo()), InstPrinter(printer),
- Assembler(llvm::make_unique<MCAssembler>(
- Context, std::move(asmbackend), std::move(emitter),
- (asmbackend) ? asmbackend->createObjectWriter(NullStream)
- : nullptr)),
- CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm),
- ShowInst(showInst), UseDwarfDirectory(useDwarfDirectory) {
- assert(InstPrinter);
- if (IsVerboseAsm)
- InstPrinter->setCommentStream(CommentStream);
- }
-
- MCAssembler &getAssembler() { return *Assembler; }
- MCAssembler *getAssemblerPtr() override { return nullptr; }
-
- inline void EmitEOL() {
- // Dump Explicit Comments here.
- emitExplicitComments();
- // If we don't have any comments, just emit a \n.
- if (!IsVerboseAsm) {
- OS << '\n';
- return;
- }
- EmitCommentsAndEOL();
- }
-
- void EmitSyntaxDirective() override;
-
- void EmitCommentsAndEOL();
-
- /// Return true if this streamer supports verbose assembly at all.
- bool isVerboseAsm() const override { return IsVerboseAsm; }
-
- /// Do we support EmitRawText?
- bool hasRawTextSupport() const override { return true; }
-
- /// Add a comment that can be emitted to the generated .s file to make the
- /// output of the compiler more readable. This only affects the MCAsmStreamer
- /// and only when verbose assembly output is enabled.
- void AddComment(const Twine &T, bool EOL = true) override;
-
- /// Add a comment showing the encoding of an instruction.
- void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &);
-
- /// Return a raw_ostream that comments can be written to.
- /// Unlike AddComment, you are required to terminate comments with \n if you
- /// use this method.
- raw_ostream &GetCommentOS() override {
- if (!IsVerboseAsm)
- return nulls(); // Discard comments unless in verbose asm mode.
- return CommentStream;
- }
-
- void emitRawComment(const Twine &T, bool TabPrefix = true) override;
-
- void addExplicitComment(const Twine &T) override;
- void emitExplicitComments() override;
-
- /// Emit a blank line to a .s file to pretty it up.
- void AddBlankLine() override {
- EmitEOL();
- }
-
- /// @name MCStreamer Interface
- /// @{
-
- void ChangeSection(MCSection *Section, const MCExpr *Subsection) override;
-
- void emitELFSymverDirective(StringRef AliasName,
- const MCSymbol *Aliasee) override;
-
- void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;
- void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
-
- void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
- void EmitLinkerOptions(ArrayRef<std::string> Options) override;
- void EmitDataRegion(MCDataRegionType Kind) override;
- void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
- unsigned Update, VersionTuple SDKVersion) override;
- void EmitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
- unsigned Update, VersionTuple SDKVersion) override;
- void EmitThumbFunc(MCSymbol *Func) override;
-
- void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
- void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
- bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
-
- void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
- void BeginCOFFSymbolDef(const MCSymbol *Symbol) override;
- void EmitCOFFSymbolStorageClass(int StorageClass) override;
- void EmitCOFFSymbolType(int Type) override;
- void EndCOFFSymbolDef() override;
- void EmitCOFFSafeSEH(MCSymbol const *Symbol) override;
- void EmitCOFFSymbolIndex(MCSymbol const *Symbol) override;
- void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
- void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
- void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
- void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
- void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
- unsigned ByteAlignment) override;
-
- /// Emit a local common (.lcomm) symbol.
- ///
- /// @param Symbol - The common symbol to emit.
- /// @param Size - The size of the common symbol.
- /// @param ByteAlignment - The alignment of the common symbol in bytes.
- void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
- unsigned ByteAlignment) override;
-
- void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
- uint64_t Size = 0, unsigned ByteAlignment = 0,
- SMLoc Loc = SMLoc()) override;
-
- void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
- unsigned ByteAlignment = 0) override;
-
- void EmitBinaryData(StringRef Data) override;
-
- void EmitBytes(StringRef Data) override;
-
- void EmitValueImpl(const MCExpr *Value, unsigned Size,
- SMLoc Loc = SMLoc()) override;
- void EmitIntValue(uint64_t Value, unsigned Size) override;
- void EmitIntValueInHex(uint64_t Value, unsigned Size) override;
-
- void EmitULEB128Value(const MCExpr *Value) override;
-
- void EmitSLEB128Value(const MCExpr *Value) override;
-
- void EmitDTPRel32Value(const MCExpr *Value) override;
- void EmitDTPRel64Value(const MCExpr *Value) override;
- void EmitTPRel32Value(const MCExpr *Value) override;
- void EmitTPRel64Value(const MCExpr *Value) override;
-
- void EmitGPRel64Value(const MCExpr *Value) override;
-
- void EmitGPRel32Value(const MCExpr *Value) override;
-
- void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
- SMLoc Loc = SMLoc()) override;
-
- void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
- SMLoc Loc = SMLoc()) override;
-
- void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
- unsigned ValueSize = 1,
- unsigned MaxBytesToEmit = 0) override;
-
- void EmitCodeAlignment(unsigned ByteAlignment,
- unsigned MaxBytesToEmit = 0) override;
-
- void emitValueToOffset(const MCExpr *Offset,
- unsigned char Value,
- SMLoc Loc) override;
-
- void EmitFileDirective(StringRef Filename) override;
- Expected<unsigned> tryEmitDwarfFileDirective(unsigned FileNo,
- StringRef Directory,
- StringRef Filename,
- Optional<MD5::MD5Result> Checksum = None,
- Optional<StringRef> Source = None,
- unsigned CUID = 0) override;
- void emitDwarfFile0Directive(StringRef Directory, StringRef Filename,
- Optional<MD5::MD5Result> Checksum,
- Optional<StringRef> Source,
- unsigned CUID = 0) override;
- void EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
- unsigned Column, unsigned Flags,
- unsigned Isa, unsigned Discriminator,
- StringRef FileName) override;
- MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
-
- bool EmitCVFileDirective(unsigned FileNo, StringRef Filename,
- ArrayRef<uint8_t> Checksum,
- unsigned ChecksumKind) override;
- bool EmitCVFuncIdDirective(unsigned FuncId) override;
- bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
- unsigned IAFile, unsigned IALine,
- unsigned IACol, SMLoc Loc) override;
- void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
- unsigned Column, bool PrologueEnd, bool IsStmt,
- StringRef FileName, SMLoc Loc) override;
- void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart,
- const MCSymbol *FnEnd) override;
- void EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
- unsigned SourceFileId,
- unsigned SourceLineNum,
- const MCSymbol *FnStartSym,
- const MCSymbol *FnEndSym) override;
- void EmitCVDefRangeDirective(
- ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
- StringRef FixedSizePortion) override;
- void EmitCVStringTableDirective() override;
- void EmitCVFileChecksumsDirective() override;
- void EmitCVFileChecksumOffsetDirective(unsigned FileNo) override;
- void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override;
-
- void EmitIdent(StringRef IdentString) override;
- void EmitCFIBKeyFrame() override;
- void EmitCFISections(bool EH, bool Debug) override;
- void EmitCFIDefCfa(int64_t Register, int64_t Offset) override;
- void EmitCFIDefCfaOffset(int64_t Offset) override;
- void EmitCFIDefCfaRegister(int64_t Register) override;
- void EmitCFIOffset(int64_t Register, int64_t Offset) override;
- void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override;
- void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) override;
- void EmitCFIRememberState() override;
- void EmitCFIRestoreState() override;
- void EmitCFIRestore(int64_t Register) override;
- void EmitCFISameValue(int64_t Register) override;
- void EmitCFIRelOffset(int64_t Register, int64_t Offset) override;
- void EmitCFIAdjustCfaOffset(int64_t Adjustment) override;
- void EmitCFIEscape(StringRef Values) override;
- void EmitCFIGnuArgsSize(int64_t Size) override;
- void EmitCFISignalFrame() override;
- void EmitCFIUndefined(int64_t Register) override;
- void EmitCFIRegister(int64_t Register1, int64_t Register2) override;
- void EmitCFIWindowSave() override;
- void EmitCFINegateRAState() override;
- void EmitCFIReturnColumn(int64_t Register) override;
-
- void EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override;
- void EmitWinCFIEndProc(SMLoc Loc) override;
- void EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) override;
- void EmitWinCFIStartChained(SMLoc Loc) override;
- void EmitWinCFIEndChained(SMLoc Loc) override;
- void EmitWinCFIPushReg(unsigned Register, SMLoc Loc) override;
- void EmitWinCFISetFrame(unsigned Register, unsigned Offset,
- SMLoc Loc) override;
- void EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) override;
- void EmitWinCFISaveReg(unsigned Register, unsigned Offset,
- SMLoc Loc) override;
- void EmitWinCFISaveXMM(unsigned Register, unsigned Offset,
- SMLoc Loc) override;
- void EmitWinCFIPushFrame(bool Code, SMLoc Loc) override;
- void EmitWinCFIEndProlog(SMLoc Loc) override;
-
- void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
- SMLoc Loc) override;
- void EmitWinEHHandlerData(SMLoc Loc) override;
-
- void emitCGProfileEntry(const MCSymbolRefExpr *From,
- const MCSymbolRefExpr *To, uint64_t Count) override;
-
- void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
-
- void EmitBundleAlignMode(unsigned AlignPow2) override;
- void EmitBundleLock(bool AlignToEnd) override;
- void EmitBundleUnlock() override;
-
- bool EmitRelocDirective(const MCExpr &Offset, StringRef Name,
- const MCExpr *Expr, SMLoc Loc,
- const MCSubtargetInfo &STI) override;
-
- void EmitAddrsig() override;
- void EmitAddrsigSym(const MCSymbol *Sym) override;
-
- /// If this file is backed by an assembly streamer, this dumps the specified
- /// string in the output .s file. This capability is indicated by the
- /// hasRawTextSupport() predicate.
- void EmitRawTextImpl(StringRef String) override;
-
- void FinishImpl() override;
-};
-
-} // end anonymous namespace.
-
-void MCAsmStreamer::AddComment(const Twine &T, bool EOL) {
- if (!IsVerboseAsm) return;
-
- T.toVector(CommentToEmit);
-
- if (EOL)
- CommentToEmit.push_back('\n'); // Place comment in a new line.
-}
-
-void MCAsmStreamer::EmitCommentsAndEOL() {
- if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) {
- OS << '\n';
- return;
- }
-
- StringRef Comments = CommentToEmit;
-
- assert(Comments.back() == '\n' &&
- "Comment array not newline terminated");
- do {
- // Emit a line of comments.
- OS.PadToColumn(MAI->getCommentColumn());
- size_t Position = Comments.find('\n');
- OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n';
-
- Comments = Comments.substr(Position+1);
- } while (!Comments.empty());
-
- CommentToEmit.clear();
-}
-
-static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
- assert(Bytes > 0 && Bytes <= 8 && "Invalid size!");
- return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
-}
-
-void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) {
- if (TabPrefix)
- OS << '\t';
- OS << MAI->getCommentString() << T;
- EmitEOL();
-}
-
-void MCAsmStreamer::addExplicitComment(const Twine &T) {
- StringRef c = T.getSingleStringRef();
- if (c.equals(StringRef(MAI->getSeparatorString())))
- return;
- if (c.startswith(StringRef("//"))) {
- ExplicitCommentToEmit.append("\t");
- ExplicitCommentToEmit.append(MAI->getCommentString());
- // drop //
- ExplicitCommentToEmit.append(c.slice(2, c.size()).str());
- } else if (c.startswith(StringRef("/*"))) {
- size_t p = 2, len = c.size() - 2;
- // emit each line in comment as separate newline.
- do {
- size_t newp = std::min(len, c.find_first_of("\r\n", p));
- ExplicitCommentToEmit.append("\t");
- ExplicitCommentToEmit.append(MAI->getCommentString());
- ExplicitCommentToEmit.append(c.slice(p, newp).str());
- // If we have another line in this comment add line
- if (newp < len)
- ExplicitCommentToEmit.append("\n");
- p = newp + 1;
- } while (p < len);
- } else if (c.startswith(StringRef(MAI->getCommentString()))) {
- ExplicitCommentToEmit.append("\t");
- ExplicitCommentToEmit.append(c.str());
- } else if (c.front() == '#') {
-
- ExplicitCommentToEmit.append("\t");
- ExplicitCommentToEmit.append(MAI->getCommentString());
- ExplicitCommentToEmit.append(c.slice(1, c.size()).str());
- } else
- assert(false && "Unexpected Assembly Comment");
- // full line comments immediately output
- if (c.back() == '\n')
- emitExplicitComments();
-}
-
-void MCAsmStreamer::emitExplicitComments() {
- StringRef Comments = ExplicitCommentToEmit;
- if (!Comments.empty())
- OS << Comments;
- ExplicitCommentToEmit.clear();
-}
-
-void MCAsmStreamer::ChangeSection(MCSection *Section,
- const MCExpr *Subsection) {
- assert(Section && "Cannot switch to a null section!");
- if (MCTargetStreamer *TS = getTargetStreamer()) {
- TS->changeSection(getCurrentSectionOnly(), Section, Subsection, OS);
- } else {
- Section->PrintSwitchToSection(
- *MAI, getContext().getObjectFileInfo()->getTargetTriple(), OS,
- Subsection);
- }
-}
-
-void MCAsmStreamer::emitELFSymverDirective(StringRef AliasName,
- const MCSymbol *Aliasee) {
- OS << ".symver ";
- Aliasee->print(OS, MAI);
- OS << ", " << AliasName;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
- MCStreamer::EmitLabel(Symbol, Loc);
-
- Symbol->print(OS, MAI);
- OS << MAI->getLabelSuffix();
-
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
- StringRef str = MCLOHIdToName(Kind);
-
-#ifndef NDEBUG
- int NbArgs = MCLOHIdToNbArgs(Kind);
- assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!");
- assert(str != "" && "Invalid LOH name");
-#endif
-
- OS << "\t" << MCLOHDirectiveName() << " " << str << "\t";
- bool IsFirst = true;
- for (const MCSymbol *Arg : Args) {
- if (!IsFirst)
- OS << ", ";
- IsFirst = false;
- Arg->print(OS, MAI);
- }
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
- switch (Flag) {
- case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break;
- case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
- case MCAF_Code16: OS << '\t'<< MAI->getCode16Directive();break;
- case MCAF_Code32: OS << '\t'<< MAI->getCode32Directive();break;
- case MCAF_Code64: OS << '\t'<< MAI->getCode64Directive();break;
- }
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) {
- assert(!Options.empty() && "At least one option is required!");
- OS << "\t.linker_option \"" << Options[0] << '"';
- for (ArrayRef<std::string>::iterator it = Options.begin() + 1,
- ie = Options.end(); it != ie; ++it) {
- OS << ", " << '"' << *it << '"';
- }
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) {
- if (!MAI->doesSupportDataRegionDirectives())
- return;
- switch (Kind) {
- case MCDR_DataRegion: OS << "\t.data_region"; break;
- case MCDR_DataRegionJT8: OS << "\t.data_region jt8"; break;
- case MCDR_DataRegionJT16: OS << "\t.data_region jt16"; break;
- case MCDR_DataRegionJT32: OS << "\t.data_region jt32"; break;
- case MCDR_DataRegionEnd: OS << "\t.end_data_region"; break;
- }
- EmitEOL();
-}
-
-static const char *getVersionMinDirective(MCVersionMinType Type) {
- switch (Type) {
- case MCVM_WatchOSVersionMin: return ".watchos_version_min";
- case MCVM_TvOSVersionMin: return ".tvos_version_min";
- case MCVM_IOSVersionMin: return ".ios_version_min";
- case MCVM_OSXVersionMin: return ".macosx_version_min";
- }
- llvm_unreachable("Invalid MC version min type");
-}
-
-static void EmitSDKVersionSuffix(raw_ostream &OS,
- const VersionTuple &SDKVersion) {
- if (SDKVersion.empty())
- return;
- OS << '\t' << "sdk_version " << SDKVersion.getMajor();
- if (auto Minor = SDKVersion.getMinor()) {
- OS << ", " << *Minor;
- if (auto Subminor = SDKVersion.getSubminor()) {
- OS << ", " << *Subminor;
- }
- }
-}
-
-void MCAsmStreamer::EmitVersionMin(MCVersionMinType Type, unsigned Major,
- unsigned Minor, unsigned Update,
- VersionTuple SDKVersion) {
- OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor;
- if (Update)
- OS << ", " << Update;
- EmitSDKVersionSuffix(OS, SDKVersion);
- EmitEOL();
-}
-
-static const char *getPlatformName(MachO::PlatformType Type) {
- switch (Type) {
- case MachO::PLATFORM_MACOS: return "macos";
- case MachO::PLATFORM_IOS: return "ios";
- case MachO::PLATFORM_TVOS: return "tvos";
- case MachO::PLATFORM_WATCHOS: return "watchos";
- case MachO::PLATFORM_BRIDGEOS: return "bridgeos";
- case MachO::PLATFORM_MACCATALYST: return "macCatalyst";
- case MachO::PLATFORM_IOSSIMULATOR: return "iossimulator";
- case MachO::PLATFORM_TVOSSIMULATOR: return "tvossimulator";
- case MachO::PLATFORM_WATCHOSSIMULATOR: return "watchossimulator";
- }
- llvm_unreachable("Invalid Mach-O platform type");
-}
-
-void MCAsmStreamer::EmitBuildVersion(unsigned Platform, unsigned Major,
- unsigned Minor, unsigned Update,
- VersionTuple SDKVersion) {
- const char *PlatformName = getPlatformName((MachO::PlatformType)Platform);
- OS << "\t.build_version " << PlatformName << ", " << Major << ", " << Minor;
- if (Update)
- OS << ", " << Update;
- EmitSDKVersionSuffix(OS, SDKVersion);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) {
- // This needs to emit to a temporary string to get properly quoted
- // MCSymbols when they have spaces in them.
- OS << "\t.thumb_func";
- // Only Mach-O hasSubsectionsViaSymbols()
- if (MAI->hasSubsectionsViaSymbols()) {
- OS << '\t';
- Func->print(OS, MAI);
- }
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
- // Do not emit a .set on inlined target assignments.
- bool EmitSet = true;
- if (auto *E = dyn_cast<MCTargetExpr>(Value))
- if (E->inlineAssignedExpr())
- EmitSet = false;
- if (EmitSet) {
- OS << ".set ";
- Symbol->print(OS, MAI);
- OS << ", ";
- Value->print(OS, MAI);
-
- EmitEOL();
- }
-
- MCStreamer::EmitAssignment(Symbol, Value);
-}
-
-void MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
- OS << ".weakref ";
- Alias->print(OS, MAI);
- OS << ", ";
- Symbol->print(OS, MAI);
- EmitEOL();
-}
-
-bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
- MCSymbolAttr Attribute) {
- switch (Attribute) {
- case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute");
- case MCSA_ELF_TypeFunction: /// .type _foo, STT_FUNC # aka @function
- case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC
- case MCSA_ELF_TypeObject: /// .type _foo, STT_OBJECT # aka @object
- case MCSA_ELF_TypeTLS: /// .type _foo, STT_TLS # aka @tls_object
- case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common
- case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype
- case MCSA_ELF_TypeGnuUniqueObject: /// .type _foo, @gnu_unique_object
- if (!MAI->hasDotTypeDotSizeDirective())
- return false; // Symbol attribute not supported
- OS << "\t.type\t";
- Symbol->print(OS, MAI);
- OS << ',' << ((MAI->getCommentString()[0] != '@') ? '@' : '%');
- switch (Attribute) {
- default: return false;
- case MCSA_ELF_TypeFunction: OS << "function"; break;
- case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break;
- case MCSA_ELF_TypeObject: OS << "object"; break;
- case MCSA_ELF_TypeTLS: OS << "tls_object"; break;
- case MCSA_ELF_TypeCommon: OS << "common"; break;
- case MCSA_ELF_TypeNoType: OS << "notype"; break;
- case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break;
- }
- EmitEOL();
- return true;
- case MCSA_Global: // .globl/.global
- OS << MAI->getGlobalDirective();
- break;
- case MCSA_Hidden: OS << "\t.hidden\t"; break;
- case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break;
- case MCSA_Internal: OS << "\t.internal\t"; break;
- case MCSA_LazyReference: OS << "\t.lazy_reference\t"; break;
- case MCSA_Local: OS << "\t.local\t"; break;
- case MCSA_NoDeadStrip:
- if (!MAI->hasNoDeadStrip())
- return false;
- OS << "\t.no_dead_strip\t";
- break;
- case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break;
- case MCSA_AltEntry: OS << "\t.alt_entry\t"; break;
- case MCSA_PrivateExtern:
- OS << "\t.private_extern\t";
- break;
- case MCSA_Protected: OS << "\t.protected\t"; break;
- case MCSA_Reference: OS << "\t.reference\t"; break;
- case MCSA_Weak: OS << MAI->getWeakDirective(); break;
- case MCSA_WeakDefinition:
- OS << "\t.weak_definition\t";
- break;
- // .weak_reference
- case MCSA_WeakReference: OS << MAI->getWeakRefDirective(); break;
- case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break;
- case MCSA_Cold:
- // Assemblers currently do not support a .cold directive.
- return false;
- }
-
- Symbol->print(OS, MAI);
- EmitEOL();
-
- return true;
-}
-
-void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
- OS << ".desc" << ' ';
- Symbol->print(OS, MAI);
- OS << ',' << DescValue;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitSyntaxDirective() {
- if (MAI->getAssemblerDialect() == 1) {
- OS << "\t.intel_syntax noprefix";
- EmitEOL();
- }
- // FIXME: Currently emit unprefix'ed registers.
- // The intel_syntax directive has one optional argument
- // with may have a value of prefix or noprefix.
-}
-
-void MCAsmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) {
- OS << "\t.def\t ";
- Symbol->print(OS, MAI);
- OS << ';';
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCOFFSymbolStorageClass (int StorageClass) {
- OS << "\t.scl\t" << StorageClass << ';';
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCOFFSymbolType (int Type) {
- OS << "\t.type\t" << Type << ';';
- EmitEOL();
-}
-
-void MCAsmStreamer::EndCOFFSymbolDef() {
- OS << "\t.endef";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
- OS << "\t.safeseh\t";
- Symbol->print(OS, MAI);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {
- OS << "\t.symidx\t";
- Symbol->print(OS, MAI);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
- OS << "\t.secidx\t";
- Symbol->print(OS, MAI);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {
- OS << "\t.secrel32\t";
- Symbol->print(OS, MAI);
- if (Offset != 0)
- OS << '+' << Offset;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {
- OS << "\t.rva\t";
- Symbol->print(OS, MAI);
- if (Offset > 0)
- OS << '+' << Offset;
- else if (Offset < 0)
- OS << '-' << -Offset;
- EmitEOL();
-}
-
-void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
- assert(MAI->hasDotTypeDotSizeDirective());
- OS << "\t.size\t";
- Symbol->print(OS, MAI);
- OS << ", ";
- Value->print(OS, MAI);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
- unsigned ByteAlignment) {
- OS << "\t.comm\t";
- Symbol->print(OS, MAI);
- OS << ',' << Size;
-
- if (ByteAlignment != 0) {
- if (MAI->getCOMMDirectiveAlignmentIsInBytes())
- OS << ',' << ByteAlignment;
- else
- OS << ',' << Log2_32(ByteAlignment);
- }
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
- unsigned ByteAlign) {
- OS << "\t.lcomm\t";
- Symbol->print(OS, MAI);
- OS << ',' << Size;
-
- if (ByteAlign > 1) {
- switch (MAI->getLCOMMDirectiveAlignmentType()) {
- case LCOMM::NoAlignment:
- llvm_unreachable("alignment not supported on .lcomm!");
- case LCOMM::ByteAlignment:
- OS << ',' << ByteAlign;
- break;
- case LCOMM::Log2Alignment:
- assert(isPowerOf2_32(ByteAlign) && "alignment must be a power of 2");
- OS << ',' << Log2_32(ByteAlign);
- break;
- }
- }
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment,
- SMLoc Loc) {
- if (Symbol)
- AssignFragment(Symbol, &Section->getDummyFragment());
-
- // Note: a .zerofill directive does not switch sections.
- OS << ".zerofill ";
-
- assert(Section->getVariant() == MCSection::SV_MachO &&
- ".zerofill is a Mach-O specific directive");
- // This is a mach-o specific directive.
-
- const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section);
- OS << MOSection->getSegmentName() << "," << MOSection->getSectionName();
-
- if (Symbol) {
- OS << ',';
- Symbol->print(OS, MAI);
- OS << ',' << Size;
- if (ByteAlignment != 0)
- OS << ',' << Log2_32(ByteAlignment);
- }
- EmitEOL();
-}
-
-// .tbss sym, size, align
-// This depends that the symbol has already been mangled from the original,
-// e.g. _a.
-void MCAsmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment) {
- AssignFragment(Symbol, &Section->getDummyFragment());
-
- assert(Symbol && "Symbol shouldn't be NULL!");
- // Instead of using the Section we'll just use the shortcut.
-
- assert(Section->getVariant() == MCSection::SV_MachO &&
- ".zerofill is a Mach-O specific directive");
- // This is a mach-o specific directive and section.
-
- OS << ".tbss ";
- Symbol->print(OS, MAI);
- OS << ", " << Size;
-
- // Output align if we have it. We default to 1 so don't bother printing
- // that.
- if (ByteAlignment > 1) OS << ", " << Log2_32(ByteAlignment);
-
- EmitEOL();
-}
-
-static inline char toOctal(int X) { return (X&7)+'0'; }
-
-static void PrintQuotedString(StringRef Data, raw_ostream &OS) {
- OS << '"';
-
- for (unsigned i = 0, e = Data.size(); i != e; ++i) {
- unsigned char C = Data[i];
- if (C == '"' || C == '\\') {
- OS << '\\' << (char)C;
- continue;
- }
-
- if (isPrint((unsigned char)C)) {
- OS << (char)C;
- continue;
- }
-
- switch (C) {
- case '\b': OS << "\\b"; break;
- case '\f': OS << "\\f"; break;
- case '\n': OS << "\\n"; break;
- case '\r': OS << "\\r"; break;
- case '\t': OS << "\\t"; break;
- default:
- OS << '\\';
- OS << toOctal(C >> 6);
- OS << toOctal(C >> 3);
- OS << toOctal(C >> 0);
- break;
- }
- }
-
- OS << '"';
-}
-
-void MCAsmStreamer::EmitBytes(StringRef Data) {
- assert(getCurrentSectionOnly() &&
- "Cannot emit contents before setting section!");
- if (Data.empty()) return;
-
- // If only single byte is provided or no ascii or asciz directives is
- // supported, emit as vector of 8bits data.
- if (Data.size() == 1 ||
- !(MAI->getAscizDirective() || MAI->getAsciiDirective())) {
- if (MCTargetStreamer *TS = getTargetStreamer()) {
- TS->emitRawBytes(Data);
- } else {
- const char *Directive = MAI->getData8bitsDirective();
- for (const unsigned char C : Data.bytes()) {
- OS << Directive << (unsigned)C;
- EmitEOL();
- }
- }
- return;
- }
-
- // If the data ends with 0 and the target supports .asciz, use it, otherwise
- // use .ascii
- if (MAI->getAscizDirective() && Data.back() == 0) {
- OS << MAI->getAscizDirective();
- Data = Data.substr(0, Data.size()-1);
- } else {
- OS << MAI->getAsciiDirective();
- }
-
- PrintQuotedString(Data, OS);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitBinaryData(StringRef Data) {
- // This is binary data. Print it in a grid of hex bytes for readability.
- const size_t Cols = 4;
- for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) {
- size_t J = I, EJ = std::min(I + Cols, Data.size());
- assert(EJ > 0);
- OS << MAI->getData8bitsDirective();
- for (; J < EJ - 1; ++J)
- OS << format("0x%02x", uint8_t(Data[J])) << ", ";
- OS << format("0x%02x", uint8_t(Data[J]));
- EmitEOL();
- }
-}
-
-void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size) {
- EmitValue(MCConstantExpr::create(Value, getContext()), Size);
-}
-
-void MCAsmStreamer::EmitIntValueInHex(uint64_t Value, unsigned Size) {
- EmitValue(MCConstantExpr::create(Value, getContext(), true), Size);
-}
-
-void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
- SMLoc Loc) {
- assert(Size <= 8 && "Invalid size");
- assert(getCurrentSectionOnly() &&
- "Cannot emit contents before setting section!");
- const char *Directive = nullptr;
- switch (Size) {
- default: break;
- case 1: Directive = MAI->getData8bitsDirective(); break;
- case 2: Directive = MAI->getData16bitsDirective(); break;
- case 4: Directive = MAI->getData32bitsDirective(); break;
- case 8: Directive = MAI->getData64bitsDirective(); break;
- }
-
- if (!Directive) {
- int64_t IntValue;
- if (!Value->evaluateAsAbsolute(IntValue))
- report_fatal_error("Don't know how to emit this value.");
-
- // We couldn't handle the requested integer size so we fallback by breaking
- // the request down into several, smaller, integers.
- // Since sizes greater or equal to "Size" are invalid, we use the greatest
- // power of 2 that is less than "Size" as our largest piece of granularity.
- bool IsLittleEndian = MAI->isLittleEndian();
- for (unsigned Emitted = 0; Emitted != Size;) {
- unsigned Remaining = Size - Emitted;
- // The size of our partial emission must be a power of two less than
- // Size.
- unsigned EmissionSize = PowerOf2Floor(std::min(Remaining, Size - 1));
- // Calculate the byte offset of our partial emission taking into account
- // the endianness of the target.
- unsigned ByteOffset =
- IsLittleEndian ? Emitted : (Remaining - EmissionSize);
- uint64_t ValueToEmit = IntValue >> (ByteOffset * 8);
- // We truncate our partial emission to fit within the bounds of the
- // emission domain. This produces nicer output and silences potential
- // truncation warnings when round tripping through another assembler.
- uint64_t Shift = 64 - EmissionSize * 8;
- assert(Shift < static_cast<uint64_t>(
- std::numeric_limits<unsigned long long>::digits) &&
- "undefined behavior");
- ValueToEmit &= ~0ULL >> Shift;
- EmitIntValue(ValueToEmit, EmissionSize);
- Emitted += EmissionSize;
- }
- return;
- }
-
- assert(Directive && "Invalid size for machine code value!");
- OS << Directive;
- if (MCTargetStreamer *TS = getTargetStreamer()) {
- TS->emitValue(Value);
- } else {
- Value->print(OS, MAI);
- EmitEOL();
- }
-}
-
-void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) {
- int64_t IntValue;
- if (Value->evaluateAsAbsolute(IntValue)) {
- EmitULEB128IntValue(IntValue);
- return;
- }
- OS << "\t.uleb128 ";
- Value->print(OS, MAI);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) {
- int64_t IntValue;
- if (Value->evaluateAsAbsolute(IntValue)) {
- EmitSLEB128IntValue(IntValue);
- return;
- }
- OS << "\t.sleb128 ";
- Value->print(OS, MAI);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitDTPRel64Value(const MCExpr *Value) {
- assert(MAI->getDTPRel64Directive() != nullptr);
- OS << MAI->getDTPRel64Directive();
- Value->print(OS, MAI);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitDTPRel32Value(const MCExpr *Value) {
- assert(MAI->getDTPRel32Directive() != nullptr);
- OS << MAI->getDTPRel32Directive();
- Value->print(OS, MAI);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitTPRel64Value(const MCExpr *Value) {
- assert(MAI->getTPRel64Directive() != nullptr);
- OS << MAI->getTPRel64Directive();
- Value->print(OS, MAI);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitTPRel32Value(const MCExpr *Value) {
- assert(MAI->getTPRel32Directive() != nullptr);
- OS << MAI->getTPRel32Directive();
- Value->print(OS, MAI);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitGPRel64Value(const MCExpr *Value) {
- assert(MAI->getGPRel64Directive() != nullptr);
- OS << MAI->getGPRel64Directive();
- Value->print(OS, MAI);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) {
- assert(MAI->getGPRel32Directive() != nullptr);
- OS << MAI->getGPRel32Directive();
- Value->print(OS, MAI);
- EmitEOL();
-}
-
-void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
- SMLoc Loc) {
- int64_t IntNumBytes;
- if (NumBytes.evaluateAsAbsolute(IntNumBytes) && IntNumBytes == 0)
- return;
-
- if (const char *ZeroDirective = MAI->getZeroDirective()) {
- // FIXME: Emit location directives
- OS << ZeroDirective;
- NumBytes.print(OS, MAI);
- if (FillValue != 0)
- OS << ',' << (int)FillValue;
- EmitEOL();
- return;
- }
-
- MCStreamer::emitFill(NumBytes, FillValue);
-}
-
-void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
- int64_t Expr, SMLoc Loc) {
- // FIXME: Emit location directives
- OS << "\t.fill\t";
- NumValues.print(OS, MAI);
- OS << ", " << Size << ", 0x";
- OS.write_hex(truncateToSize(Expr, 4));
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
- unsigned ValueSize,
- unsigned MaxBytesToEmit) {
- // Some assemblers don't support non-power of two alignments, so we always
- // emit alignments as a power of two if possible.
- if (isPowerOf2_32(ByteAlignment)) {
- switch (ValueSize) {
- default:
- llvm_unreachable("Invalid size for machine code value!");
- case 1:
- OS << "\t.p2align\t";
- break;
- case 2:
- OS << ".p2alignw ";
- break;
- case 4:
- OS << ".p2alignl ";
- break;
- case 8:
- llvm_unreachable("Unsupported alignment size!");
- }
-
- OS << Log2_32(ByteAlignment);
-
- if (Value || MaxBytesToEmit) {
- OS << ", 0x";
- OS.write_hex(truncateToSize(Value, ValueSize));
-
- if (MaxBytesToEmit)
- OS << ", " << MaxBytesToEmit;
- }
- EmitEOL();
- return;
- }
-
- // Non-power of two alignment. This is not widely supported by assemblers.
- // FIXME: Parameterize this based on MAI.
- switch (ValueSize) {
- default: llvm_unreachable("Invalid size for machine code value!");
- case 1: OS << ".balign"; break;
- case 2: OS << ".balignw"; break;
- case 4: OS << ".balignl"; break;
- case 8: llvm_unreachable("Unsupported alignment size!");
- }
-
- OS << ' ' << ByteAlignment;
- OS << ", " << truncateToSize(Value, ValueSize);
- if (MaxBytesToEmit)
- OS << ", " << MaxBytesToEmit;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment,
- unsigned MaxBytesToEmit) {
- // Emit with a text fill value.
- EmitValueToAlignment(ByteAlignment, MAI->getTextAlignFillValue(),
- 1, MaxBytesToEmit);
-}
-
-void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset,
- unsigned char Value,
- SMLoc Loc) {
- // FIXME: Verify that Offset is associated with the current section.
- OS << ".org ";
- Offset->print(OS, MAI);
- OS << ", " << (unsigned)Value;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitFileDirective(StringRef Filename) {
- assert(MAI->hasSingleParameterDotFile());
- OS << "\t.file\t";
- PrintQuotedString(Filename, OS);
- EmitEOL();
-}
-
-static void printDwarfFileDirective(unsigned FileNo, StringRef Directory,
- StringRef Filename,
- Optional<MD5::MD5Result> Checksum,
- Optional<StringRef> Source,
- bool UseDwarfDirectory,
- raw_svector_ostream &OS) {
- SmallString<128> FullPathName;
-
- if (!UseDwarfDirectory && !Directory.empty()) {
- if (sys::path::is_absolute(Filename))
- Directory = "";
- else {
- FullPathName = Directory;
- sys::path::append(FullPathName, Filename);
- Directory = "";
- Filename = FullPathName;
- }
- }
-
- OS << "\t.file\t" << FileNo << ' ';
- if (!Directory.empty()) {
- PrintQuotedString(Directory, OS);
- OS << ' ';
- }
- PrintQuotedString(Filename, OS);
- if (Checksum)
- OS << " md5 0x" << Checksum->digest();
- if (Source) {
- OS << " source ";
- PrintQuotedString(*Source, OS);
- }
-}
-
-Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective(
- unsigned FileNo, StringRef Directory, StringRef Filename,
- Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source, unsigned CUID) {
- assert(CUID == 0 && "multiple CUs not supported by MCAsmStreamer");
-
- MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
- unsigned NumFiles = Table.getMCDwarfFiles().size();
- Expected<unsigned> FileNoOrErr =
- Table.tryGetFile(Directory, Filename, Checksum, Source,
- getContext().getDwarfVersion(), FileNo);
- if (!FileNoOrErr)
- return FileNoOrErr.takeError();
- FileNo = FileNoOrErr.get();
- if (NumFiles == Table.getMCDwarfFiles().size())
- return FileNo;
-
- SmallString<128> Str;
- raw_svector_ostream OS1(Str);
- printDwarfFileDirective(FileNo, Directory, Filename, Checksum, Source,
- UseDwarfDirectory, OS1);
-
- if (MCTargetStreamer *TS = getTargetStreamer())
- TS->emitDwarfFileDirective(OS1.str());
- else
- EmitRawText(OS1.str());
-
- return FileNo;
-}
-
-void MCAsmStreamer::emitDwarfFile0Directive(StringRef Directory,
- StringRef Filename,
- Optional<MD5::MD5Result> Checksum,
- Optional<StringRef> Source,
- unsigned CUID) {
- assert(CUID == 0);
- // .file 0 is new for DWARF v5.
- if (getContext().getDwarfVersion() < 5)
- return;
- // Inform MCDwarf about the root file.
- getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum,
- Source);
-
- SmallString<128> Str;
- raw_svector_ostream OS1(Str);
- printDwarfFileDirective(0, Directory, Filename, Checksum, Source,
- UseDwarfDirectory, OS1);
-
- if (MCTargetStreamer *TS = getTargetStreamer())
- TS->emitDwarfFileDirective(OS1.str());
- else
- EmitRawText(OS1.str());
-}
-
-void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
- unsigned Column, unsigned Flags,
- unsigned Isa,
- unsigned Discriminator,
- StringRef FileName) {
- OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
- if (MAI->supportsExtendedDwarfLocDirective()) {
- if (Flags & DWARF2_FLAG_BASIC_BLOCK)
- OS << " basic_block";
- if (Flags & DWARF2_FLAG_PROLOGUE_END)
- OS << " prologue_end";
- if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN)
- OS << " epilogue_begin";
-
- unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags();
- if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) {
- OS << " is_stmt ";
-
- if (Flags & DWARF2_FLAG_IS_STMT)
- OS << "1";
- else
- OS << "0";
- }
-
- if (Isa)
- OS << " isa " << Isa;
- if (Discriminator)
- OS << " discriminator " << Discriminator;
- }
-
- if (IsVerboseAsm) {
- OS.PadToColumn(MAI->getCommentColumn());
- OS << MAI->getCommentString() << ' ' << FileName << ':'
- << Line << ':' << Column;
- }
- EmitEOL();
- this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags,
- Isa, Discriminator, FileName);
-}
-
-MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {
- // Always use the zeroth line table, since asm syntax only supports one line
- // table for now.
- return MCStreamer::getDwarfLineTableSymbol(0);
-}
-
-bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename,
- ArrayRef<uint8_t> Checksum,
- unsigned ChecksumKind) {
- if (!getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
- ChecksumKind))
- return false;
-
- OS << "\t.cv_file\t" << FileNo << ' ';
- PrintQuotedString(Filename, OS);
-
- if (!ChecksumKind) {
- EmitEOL();
- return true;
- }
-
- OS << ' ';
- PrintQuotedString(toHex(Checksum), OS);
- OS << ' ' << ChecksumKind;
-
- EmitEOL();
- return true;
-}
-
-bool MCAsmStreamer::EmitCVFuncIdDirective(unsigned FuncId) {
- OS << "\t.cv_func_id " << FuncId << '\n';
- return MCStreamer::EmitCVFuncIdDirective(FuncId);
-}
-
-bool MCAsmStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId,
- unsigned IAFunc,
- unsigned IAFile,
- unsigned IALine, unsigned IACol,
- SMLoc Loc) {
- OS << "\t.cv_inline_site_id " << FunctionId << " within " << IAFunc
- << " inlined_at " << IAFile << ' ' << IALine << ' ' << IACol << '\n';
- return MCStreamer::EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
- IALine, IACol, Loc);
-}
-
-void MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
- unsigned Line, unsigned Column,
- bool PrologueEnd, bool IsStmt,
- StringRef FileName, SMLoc Loc) {
- // Validate the directive.
- if (!checkCVLocSection(FunctionId, FileNo, Loc))
- return;
-
- OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "
- << Column;
- if (PrologueEnd)
- OS << " prologue_end";
-
- if (IsStmt)
- OS << " is_stmt 1";
-
- if (IsVerboseAsm) {
- OS.PadToColumn(MAI->getCommentColumn());
- OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':'
- << Column;
- }
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId,
- const MCSymbol *FnStart,
- const MCSymbol *FnEnd) {
- OS << "\t.cv_linetable\t" << FunctionId << ", ";
- FnStart->print(OS, MAI);
- OS << ", ";
- FnEnd->print(OS, MAI);
- EmitEOL();
- this->MCStreamer::EmitCVLinetableDirective(FunctionId, FnStart, FnEnd);
-}
-
-void MCAsmStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
- unsigned SourceFileId,
- unsigned SourceLineNum,
- const MCSymbol *FnStartSym,
- const MCSymbol *FnEndSym) {
- OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId
- << ' ' << SourceLineNum << ' ';
- FnStartSym->print(OS, MAI);
- OS << ' ';
- FnEndSym->print(OS, MAI);
- EmitEOL();
- this->MCStreamer::EmitCVInlineLinetableDirective(
- PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
-}
-
-void MCAsmStreamer::EmitCVDefRangeDirective(
- ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
- StringRef FixedSizePortion) {
- OS << "\t.cv_def_range\t";
- for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) {
- OS << ' ';
- Range.first->print(OS, MAI);
- OS << ' ';
- Range.second->print(OS, MAI);
- }
- OS << ", ";
- PrintQuotedString(FixedSizePortion, OS);
- EmitEOL();
- this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion);
-}
-
-void MCAsmStreamer::EmitCVStringTableDirective() {
- OS << "\t.cv_stringtable";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCVFileChecksumsDirective() {
- OS << "\t.cv_filechecksums";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) {
- OS << "\t.cv_filechecksumoffset\t" << FileNo;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) {
- OS << "\t.cv_fpo_data\t";
- ProcSym->print(OS, MAI);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitIdent(StringRef IdentString) {
- assert(MAI->hasIdentDirective() && ".ident directive not supported");
- OS << "\t.ident\t";
- PrintQuotedString(IdentString, OS);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFISections(bool EH, bool Debug) {
- MCStreamer::EmitCFISections(EH, Debug);
- OS << "\t.cfi_sections ";
- if (EH) {
- OS << ".eh_frame";
- if (Debug)
- OS << ", .debug_frame";
- } else if (Debug) {
- OS << ".debug_frame";
- }
-
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
- OS << "\t.cfi_startproc";
- if (Frame.IsSimple)
- OS << " simple";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
- MCStreamer::EmitCFIEndProcImpl(Frame);
- OS << "\t.cfi_endproc";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitRegisterName(int64_t Register) {
- if (!MAI->useDwarfRegNumForCFI()) {
- // User .cfi_* directives can use arbitrary DWARF register numbers, not
- // just ones that map to LLVM register numbers and have known names.
- // Fall back to using the original number directly if no name is known.
- const MCRegisterInfo *MRI = getContext().getRegisterInfo();
- int LLVMRegister = MRI->getLLVMRegNumFromEH(Register);
- if (LLVMRegister != -1) {
- InstPrinter->printRegName(OS, LLVMRegister);
- return;
- }
- }
- OS << Register;
-}
-
-void MCAsmStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) {
- MCStreamer::EmitCFIDefCfa(Register, Offset);
- OS << "\t.cfi_def_cfa ";
- EmitRegisterName(Register);
- OS << ", " << Offset;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) {
- MCStreamer::EmitCFIDefCfaOffset(Offset);
- OS << "\t.cfi_def_cfa_offset " << Offset;
- EmitEOL();
-}
-
-static void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) {
- OS << "\t.cfi_escape ";
- if (!Values.empty()) {
- size_t e = Values.size() - 1;
- for (size_t i = 0; i < e; ++i)
- OS << format("0x%02x", uint8_t(Values[i])) << ", ";
- OS << format("0x%02x", uint8_t(Values[e]));
- }
-}
-
-void MCAsmStreamer::EmitCFIEscape(StringRef Values) {
- MCStreamer::EmitCFIEscape(Values);
- PrintCFIEscape(OS, Values);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFIGnuArgsSize(int64_t Size) {
- MCStreamer::EmitCFIGnuArgsSize(Size);
-
- uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size };
- unsigned Len = encodeULEB128(Size, Buffer + 1) + 1;
-
- PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len));
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) {
- MCStreamer::EmitCFIDefCfaRegister(Register);
- OS << "\t.cfi_def_cfa_register ";
- EmitRegisterName(Register);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) {
- this->MCStreamer::EmitCFIOffset(Register, Offset);
- OS << "\t.cfi_offset ";
- EmitRegisterName(Register);
- OS << ", " << Offset;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym,
- unsigned Encoding) {
- MCStreamer::EmitCFIPersonality(Sym, Encoding);
- OS << "\t.cfi_personality " << Encoding << ", ";
- Sym->print(OS, MAI);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
- MCStreamer::EmitCFILsda(Sym, Encoding);
- OS << "\t.cfi_lsda " << Encoding << ", ";
- Sym->print(OS, MAI);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFIRememberState() {
- MCStreamer::EmitCFIRememberState();
- OS << "\t.cfi_remember_state";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFIRestoreState() {
- MCStreamer::EmitCFIRestoreState();
- OS << "\t.cfi_restore_state";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFIRestore(int64_t Register) {
- MCStreamer::EmitCFIRestore(Register);
- OS << "\t.cfi_restore ";
- EmitRegisterName(Register);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFISameValue(int64_t Register) {
- MCStreamer::EmitCFISameValue(Register);
- OS << "\t.cfi_same_value ";
- EmitRegisterName(Register);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) {
- MCStreamer::EmitCFIRelOffset(Register, Offset);
- OS << "\t.cfi_rel_offset ";
- EmitRegisterName(Register);
- OS << ", " << Offset;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) {
- MCStreamer::EmitCFIAdjustCfaOffset(Adjustment);
- OS << "\t.cfi_adjust_cfa_offset " << Adjustment;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFISignalFrame() {
- MCStreamer::EmitCFISignalFrame();
- OS << "\t.cfi_signal_frame";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFIUndefined(int64_t Register) {
- MCStreamer::EmitCFIUndefined(Register);
- OS << "\t.cfi_undefined " << Register;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) {
- MCStreamer::EmitCFIRegister(Register1, Register2);
- OS << "\t.cfi_register " << Register1 << ", " << Register2;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFIWindowSave() {
- MCStreamer::EmitCFIWindowSave();
- OS << "\t.cfi_window_save";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFINegateRAState() {
- MCStreamer::EmitCFINegateRAState();
- OS << "\t.cfi_negate_ra_state";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFIReturnColumn(int64_t Register) {
- MCStreamer::EmitCFIReturnColumn(Register);
- OS << "\t.cfi_return_column " << Register;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitCFIBKeyFrame() {
- MCStreamer::EmitCFIBKeyFrame();
- OS << "\t.cfi_b_key_frame";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
- MCStreamer::EmitWinCFIStartProc(Symbol, Loc);
-
- OS << ".seh_proc ";
- Symbol->print(OS, MAI);
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitWinCFIEndProc(SMLoc Loc) {
- MCStreamer::EmitWinCFIEndProc(Loc);
-
- OS << "\t.seh_endproc";
- EmitEOL();
-}
-
-// TODO: Implement
-void MCAsmStreamer::EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) {
-}
-
-void MCAsmStreamer::EmitWinCFIStartChained(SMLoc Loc) {
- MCStreamer::EmitWinCFIStartChained(Loc);
-
- OS << "\t.seh_startchained";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitWinCFIEndChained(SMLoc Loc) {
- MCStreamer::EmitWinCFIEndChained(Loc);
-
- OS << "\t.seh_endchained";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind,
- bool Except, SMLoc Loc) {
- MCStreamer::EmitWinEHHandler(Sym, Unwind, Except, Loc);
-
- OS << "\t.seh_handler ";
- Sym->print(OS, MAI);
- if (Unwind)
- OS << ", @unwind";
- if (Except)
- OS << ", @except";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitWinEHHandlerData(SMLoc Loc) {
- MCStreamer::EmitWinEHHandlerData(Loc);
-
- // Switch sections. Don't call SwitchSection directly, because that will
- // cause the section switch to be visible in the emitted assembly.
- // We only do this so the section switch that terminates the handler
- // data block is visible.
- WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo();
- MCSection *TextSec = &CurFrame->Function->getSection();
- MCSection *XData = getAssociatedXDataSection(TextSec);
- SwitchSectionNoChange(XData);
-
- OS << "\t.seh_handlerdata";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitWinCFIPushReg(unsigned Register, SMLoc Loc) {
- MCStreamer::EmitWinCFIPushReg(Register, Loc);
-
- OS << "\t.seh_pushreg " << Register;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset,
- SMLoc Loc) {
- MCStreamer::EmitWinCFISetFrame(Register, Offset, Loc);
-
- OS << "\t.seh_setframe " << Register << ", " << Offset;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
- MCStreamer::EmitWinCFIAllocStack(Size, Loc);
-
- OS << "\t.seh_stackalloc " << Size;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset,
- SMLoc Loc) {
- MCStreamer::EmitWinCFISaveReg(Register, Offset, Loc);
-
- OS << "\t.seh_savereg " << Register << ", " << Offset;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset,
- SMLoc Loc) {
- MCStreamer::EmitWinCFISaveXMM(Register, Offset, Loc);
-
- OS << "\t.seh_savexmm " << Register << ", " << Offset;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitWinCFIPushFrame(bool Code, SMLoc Loc) {
- MCStreamer::EmitWinCFIPushFrame(Code, Loc);
-
- OS << "\t.seh_pushframe";
- if (Code)
- OS << " @code";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitWinCFIEndProlog(SMLoc Loc) {
- MCStreamer::EmitWinCFIEndProlog(Loc);
-
- OS << "\t.seh_endprologue";
- EmitEOL();
-}
-
-void MCAsmStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
- const MCSymbolRefExpr *To,
- uint64_t Count) {
- OS << "\t.cg_profile ";
- From->getSymbol().print(OS, MAI);
- OS << ", ";
- To->getSymbol().print(OS, MAI);
- OS << ", " << Count;
- EmitEOL();
-}
-
-void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
- const MCSubtargetInfo &STI) {
- raw_ostream &OS = GetCommentOS();
- SmallString<256> Code;
- SmallVector<MCFixup, 4> Fixups;
- raw_svector_ostream VecOS(Code);
-
- // If we have no code emitter, don't emit code.
- if (!getAssembler().getEmitterPtr())
- return;
-
- getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
-
- // If we are showing fixups, create symbolic markers in the encoded
- // representation. We do this by making a per-bit map to the fixup item index,
- // then trying to display it as nicely as possible.
- SmallVector<uint8_t, 64> FixupMap;
- FixupMap.resize(Code.size() * 8);
- for (unsigned i = 0, e = Code.size() * 8; i != e; ++i)
- FixupMap[i] = 0;
-
- for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
- MCFixup &F = Fixups[i];
- const MCFixupKindInfo &Info =
- getAssembler().getBackend().getFixupKindInfo(F.getKind());
- for (unsigned j = 0; j != Info.TargetSize; ++j) {
- unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j;
- assert(Index < Code.size() * 8 && "Invalid offset in fixup!");
- FixupMap[Index] = 1 + i;
- }
- }
-
- // FIXME: Note the fixup comments for Thumb2 are completely bogus since the
- // high order halfword of a 32-bit Thumb2 instruction is emitted first.
- OS << "encoding: [";
- for (unsigned i = 0, e = Code.size(); i != e; ++i) {
- if (i)
- OS << ',';
-
- // See if all bits are the same map entry.
- uint8_t MapEntry = FixupMap[i * 8 + 0];
- for (unsigned j = 1; j != 8; ++j) {
- if (FixupMap[i * 8 + j] == MapEntry)
- continue;
-
- MapEntry = uint8_t(~0U);
- break;
- }
-
- if (MapEntry != uint8_t(~0U)) {
- if (MapEntry == 0) {
- OS << format("0x%02x", uint8_t(Code[i]));
- } else {
- if (Code[i]) {
- // FIXME: Some of the 8 bits require fix up.
- OS << format("0x%02x", uint8_t(Code[i])) << '\''
- << char('A' + MapEntry - 1) << '\'';
- } else
- OS << char('A' + MapEntry - 1);
- }
- } else {
- // Otherwise, write out in binary.
- OS << "0b";
- for (unsigned j = 8; j--;) {
- unsigned Bit = (Code[i] >> j) & 1;
-
- unsigned FixupBit;
- if (MAI->isLittleEndian())
- FixupBit = i * 8 + j;
- else
- FixupBit = i * 8 + (7-j);
-
- if (uint8_t MapEntry = FixupMap[FixupBit]) {
- assert(Bit == 0 && "Encoder wrote into fixed up bit!");
- OS << char('A' + MapEntry - 1);
- } else
- OS << Bit;
- }
- }
- }
- OS << "]\n";
-
- for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
- MCFixup &F = Fixups[i];
- const MCFixupKindInfo &Info =
- getAssembler().getBackend().getFixupKindInfo(F.getKind());
- OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset()
- << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n";
- }
-}
-
-void MCAsmStreamer::EmitInstruction(const MCInst &Inst,
- const MCSubtargetInfo &STI) {
- assert(getCurrentSectionOnly() &&
- "Cannot emit contents before setting section!");
-
- // Show the encoding in a comment if we have a code emitter.
- AddEncodingComment(Inst, STI);
-
- // Show the MCInst if enabled.
- if (ShowInst) {
- Inst.dump_pretty(GetCommentOS(), InstPrinter.get(), "\n ");
- GetCommentOS() << "\n";
- }
-
- if(getTargetStreamer())
- getTargetStreamer()->prettyPrintAsm(*InstPrinter, OS, Inst, STI);
- else
- InstPrinter->printInst(&Inst, OS, "", STI);
-
- StringRef Comments = CommentToEmit;
- if (Comments.size() && Comments.back() != '\n')
- GetCommentOS() << "\n";
-
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
- OS << "\t.bundle_align_mode " << AlignPow2;
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitBundleLock(bool AlignToEnd) {
- OS << "\t.bundle_lock";
- if (AlignToEnd)
- OS << " align_to_end";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitBundleUnlock() {
- OS << "\t.bundle_unlock";
- EmitEOL();
-}
-
-bool MCAsmStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name,
- const MCExpr *Expr, SMLoc,
- const MCSubtargetInfo &STI) {
- OS << "\t.reloc ";
- Offset.print(OS, MAI);
- OS << ", " << Name;
- if (Expr) {
- OS << ", ";
- Expr->print(OS, MAI);
- }
- EmitEOL();
- return false;
-}
-
-void MCAsmStreamer::EmitAddrsig() {
- OS << "\t.addrsig";
- EmitEOL();
-}
-
-void MCAsmStreamer::EmitAddrsigSym(const MCSymbol *Sym) {
- OS << "\t.addrsig_sym ";
- Sym->print(OS, MAI);
- EmitEOL();
-}
-
-/// EmitRawText - If this file is backed by an assembly streamer, this dumps
-/// the specified string in the output .s file. This capability is
-/// indicated by the hasRawTextSupport() predicate.
-void MCAsmStreamer::EmitRawTextImpl(StringRef String) {
- if (!String.empty() && String.back() == '\n')
- String = String.substr(0, String.size()-1);
- OS << String;
- EmitEOL();
-}
-
-void MCAsmStreamer::FinishImpl() {
- // If we are generating dwarf for assembly source files dump out the sections.
- if (getContext().getGenDwarfForAssembly())
- MCGenDwarfInfo::Emit(this);
-
- // Emit the label for the line table, if requested - since the rest of the
- // line table will be defined by .loc/.file directives, and not emitted
- // directly, the label is the only work required here.
- const auto &Tables = getContext().getMCDwarfLineTables();
- if (!Tables.empty()) {
- assert(Tables.size() == 1 && "asm output only supports one line table");
- if (auto *Label = Tables.begin()->second.getLabel()) {
- SwitchSection(getContext().getObjectFileInfo()->getDwarfLineSection());
- EmitLabel(Label);
- }
- }
-}
-
-MCStreamer *llvm::createAsmStreamer(MCContext &Context,
- std::unique_ptr<formatted_raw_ostream> OS,
- bool isVerboseAsm, bool useDwarfDirectory,
- MCInstPrinter *IP,
- std::unique_ptr<MCCodeEmitter> &&CE,
- std::unique_ptr<MCAsmBackend> &&MAB,
- bool ShowInst) {
- return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm,
- useDwarfDirectory, IP, std::move(CE), std::move(MAB),
- ShowInst);
-}
diff --git a/contrib/llvm/lib/MC/MCAssembler.cpp b/contrib/llvm/lib/MC/MCAssembler.cpp
deleted file mode 100644
index 22a8e73e4af3..000000000000
--- a/contrib/llvm/lib/MC/MCAssembler.cpp
+++ /dev/null
@@ -1,1154 +0,0 @@
-//===- lib/MC/MCAssembler.cpp - Assembler Backend Implementation ----------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCAsmLayout.h"
-#include "llvm/MC/MCCodeEmitter.h"
-#include "llvm/MC/MCCodeView.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDwarf.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCFixup.h"
-#include "llvm/MC/MCFixupKindInfo.h"
-#include "llvm/MC/MCFragment.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCSectionELF.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/LEB128.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <cstdint>
-#include <cstring>
-#include <tuple>
-#include <utility>
-
-using namespace llvm;
-
-#define DEBUG_TYPE "assembler"
-
-namespace {
-namespace stats {
-
-STATISTIC(EmittedFragments, "Number of emitted assembler fragments - total");
-STATISTIC(EmittedRelaxableFragments,
- "Number of emitted assembler fragments - relaxable");
-STATISTIC(EmittedDataFragments,
- "Number of emitted assembler fragments - data");
-STATISTIC(EmittedCompactEncodedInstFragments,
- "Number of emitted assembler fragments - compact encoded inst");
-STATISTIC(EmittedAlignFragments,
- "Number of emitted assembler fragments - align");
-STATISTIC(EmittedFillFragments,
- "Number of emitted assembler fragments - fill");
-STATISTIC(EmittedOrgFragments,
- "Number of emitted assembler fragments - org");
-STATISTIC(evaluateFixup, "Number of evaluated fixups");
-STATISTIC(FragmentLayouts, "Number of fragment layouts");
-STATISTIC(ObjectBytes, "Number of emitted object file bytes");
-STATISTIC(RelaxationSteps, "Number of assembler layout and relaxation steps");
-STATISTIC(RelaxedInstructions, "Number of relaxed instructions");
-STATISTIC(PaddingFragmentsRelaxations,
- "Number of Padding Fragments relaxations");
-STATISTIC(PaddingFragmentsBytes,
- "Total size of all padding from adding Fragments");
-
-} // end namespace stats
-} // end anonymous namespace
-
-// FIXME FIXME FIXME: There are number of places in this file where we convert
-// what is a 64-bit assembler value used for computation into a value in the
-// object file, which may truncate it. We should detect that truncation where
-// invalid and report errors back.
-
-/* *** */
-
-MCAssembler::MCAssembler(MCContext &Context,
- std::unique_ptr<MCAsmBackend> Backend,
- std::unique_ptr<MCCodeEmitter> Emitter,
- std::unique_ptr<MCObjectWriter> Writer)
- : Context(Context), Backend(std::move(Backend)),
- Emitter(std::move(Emitter)), Writer(std::move(Writer)),
- BundleAlignSize(0), RelaxAll(false), SubsectionsViaSymbols(false),
- IncrementalLinkerCompatible(false), ELFHeaderEFlags(0) {
- VersionInfo.Major = 0; // Major version == 0 for "none specified"
-}
-
-MCAssembler::~MCAssembler() = default;
-
-void MCAssembler::reset() {
- Sections.clear();
- Symbols.clear();
- IndirectSymbols.clear();
- DataRegions.clear();
- LinkerOptions.clear();
- FileNames.clear();
- ThumbFuncs.clear();
- BundleAlignSize = 0;
- RelaxAll = false;
- SubsectionsViaSymbols = false;
- IncrementalLinkerCompatible = false;
- ELFHeaderEFlags = 0;
- LOHContainer.reset();
- VersionInfo.Major = 0;
- VersionInfo.SDKVersion = VersionTuple();
-
- // reset objects owned by us
- if (getBackendPtr())
- getBackendPtr()->reset();
- if (getEmitterPtr())
- getEmitterPtr()->reset();
- if (getWriterPtr())
- getWriterPtr()->reset();
- getLOHContainer().reset();
-}
-
-bool MCAssembler::registerSection(MCSection &Section) {
- if (Section.isRegistered())
- return false;
- Sections.push_back(&Section);
- Section.setIsRegistered(true);
- return true;
-}
-
-bool MCAssembler::isThumbFunc(const MCSymbol *Symbol) const {
- if (ThumbFuncs.count(Symbol))
- return true;
-
- if (!Symbol->isVariable())
- return false;
-
- const MCExpr *Expr = Symbol->getVariableValue();
-
- MCValue V;
- if (!Expr->evaluateAsRelocatable(V, nullptr, nullptr))
- return false;
-
- if (V.getSymB() || V.getRefKind() != MCSymbolRefExpr::VK_None)
- return false;
-
- const MCSymbolRefExpr *Ref = V.getSymA();
- if (!Ref)
- return false;
-
- if (Ref->getKind() != MCSymbolRefExpr::VK_None)
- return false;
-
- const MCSymbol &Sym = Ref->getSymbol();
- if (!isThumbFunc(&Sym))
- return false;
-
- ThumbFuncs.insert(Symbol); // Cache it.
- return true;
-}
-
-bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const {
- // Non-temporary labels should always be visible to the linker.
- if (!Symbol.isTemporary())
- return true;
-
- // Absolute temporary labels are never visible.
- if (!Symbol.isInSection())
- return false;
-
- if (Symbol.isUsedInReloc())
- return true;
-
- return false;
-}
-
-const MCSymbol *MCAssembler::getAtom(const MCSymbol &S) const {
- // Linker visible symbols define atoms.
- if (isSymbolLinkerVisible(S))
- return &S;
-
- // Absolute and undefined symbols have no defining atom.
- if (!S.isInSection())
- return nullptr;
-
- // Non-linker visible symbols in sections which can't be atomized have no
- // defining atom.
- if (!getContext().getAsmInfo()->isSectionAtomizableBySymbols(
- *S.getFragment()->getParent()))
- return nullptr;
-
- // Otherwise, return the atom for the containing fragment.
- return S.getFragment()->getAtom();
-}
-
-bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
- const MCFixup &Fixup, const MCFragment *DF,
- MCValue &Target, uint64_t &Value,
- bool &WasForced) const {
- ++stats::evaluateFixup;
-
- // FIXME: This code has some duplication with recordRelocation. We should
- // probably merge the two into a single callback that tries to evaluate a
- // fixup and records a relocation if one is needed.
-
- // On error claim to have completely evaluated the fixup, to prevent any
- // further processing from being done.
- const MCExpr *Expr = Fixup.getValue();
- MCContext &Ctx = getContext();
- Value = 0;
- WasForced = false;
- if (!Expr->evaluateAsRelocatable(Target, &Layout, &Fixup)) {
- Ctx.reportError(Fixup.getLoc(), "expected relocatable expression");
- return true;
- }
- if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
- if (RefB->getKind() != MCSymbolRefExpr::VK_None) {
- Ctx.reportError(Fixup.getLoc(),
- "unsupported subtraction of qualified symbol");
- return true;
- }
- }
-
- assert(getBackendPtr() && "Expected assembler backend");
- bool IsPCRel = getBackendPtr()->getFixupKindInfo(Fixup.getKind()).Flags &
- MCFixupKindInfo::FKF_IsPCRel;
-
- bool IsResolved = false;
- if (IsPCRel) {
- if (Target.getSymB()) {
- IsResolved = false;
- } else if (!Target.getSymA()) {
- IsResolved = false;
- } else {
- const MCSymbolRefExpr *A = Target.getSymA();
- const MCSymbol &SA = A->getSymbol();
- if (A->getKind() != MCSymbolRefExpr::VK_None || SA.isUndefined()) {
- IsResolved = false;
- } else if (auto *Writer = getWriterPtr()) {
- IsResolved = Writer->isSymbolRefDifferenceFullyResolvedImpl(
- *this, SA, *DF, false, true);
- }
- }
- } else {
- IsResolved = Target.isAbsolute();
- }
-
- Value = Target.getConstant();
-
- if (const MCSymbolRefExpr *A = Target.getSymA()) {
- const MCSymbol &Sym = A->getSymbol();
- if (Sym.isDefined())
- Value += Layout.getSymbolOffset(Sym);
- }
- if (const MCSymbolRefExpr *B = Target.getSymB()) {
- const MCSymbol &Sym = B->getSymbol();
- if (Sym.isDefined())
- Value -= Layout.getSymbolOffset(Sym);
- }
-
- bool ShouldAlignPC = getBackend().getFixupKindInfo(Fixup.getKind()).Flags &
- MCFixupKindInfo::FKF_IsAlignedDownTo32Bits;
- assert((ShouldAlignPC ? IsPCRel : true) &&
- "FKF_IsAlignedDownTo32Bits is only allowed on PC-relative fixups!");
-
- if (IsPCRel) {
- uint32_t Offset = Layout.getFragmentOffset(DF) + Fixup.getOffset();
-
- // A number of ARM fixups in Thumb mode require that the effective PC
- // address be determined as the 32-bit aligned version of the actual offset.
- if (ShouldAlignPC) Offset &= ~0x3;
- Value -= Offset;
- }
-
- // Let the backend force a relocation if needed.
- if (IsResolved && getBackend().shouldForceRelocation(*this, Fixup, Target)) {
- IsResolved = false;
- WasForced = true;
- }
-
- return IsResolved;
-}
-
-uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
- const MCFragment &F) const {
- assert(getBackendPtr() && "Requires assembler backend");
- switch (F.getKind()) {
- case MCFragment::FT_Data:
- return cast<MCDataFragment>(F).getContents().size();
- case MCFragment::FT_Relaxable:
- return cast<MCRelaxableFragment>(F).getContents().size();
- case MCFragment::FT_CompactEncodedInst:
- return cast<MCCompactEncodedInstFragment>(F).getContents().size();
- case MCFragment::FT_Fill: {
- auto &FF = cast<MCFillFragment>(F);
- int64_t NumValues = 0;
- if (!FF.getNumValues().evaluateAsAbsolute(NumValues, Layout)) {
- getContext().reportError(FF.getLoc(),
- "expected assembly-time absolute expression");
- return 0;
- }
- int64_t Size = NumValues * FF.getValueSize();
- if (Size < 0) {
- getContext().reportError(FF.getLoc(), "invalid number of bytes");
- return 0;
- }
- return Size;
- }
-
- case MCFragment::FT_LEB:
- return cast<MCLEBFragment>(F).getContents().size();
-
- case MCFragment::FT_Padding:
- return cast<MCPaddingFragment>(F).getSize();
-
- case MCFragment::FT_SymbolId:
- return 4;
-
- case MCFragment::FT_Align: {
- const MCAlignFragment &AF = cast<MCAlignFragment>(F);
- unsigned Offset = Layout.getFragmentOffset(&AF);
- unsigned Size = OffsetToAlignment(Offset, AF.getAlignment());
-
- // Insert extra Nops for code alignment if the target define
- // shouldInsertExtraNopBytesForCodeAlign target hook.
- if (AF.getParent()->UseCodeAlign() && AF.hasEmitNops() &&
- getBackend().shouldInsertExtraNopBytesForCodeAlign(AF, Size))
- return Size;
-
- // If we are padding with nops, force the padding to be larger than the
- // minimum nop size.
- if (Size > 0 && AF.hasEmitNops()) {
- while (Size % getBackend().getMinimumNopSize())
- Size += AF.getAlignment();
- }
- if (Size > AF.getMaxBytesToEmit())
- return 0;
- return Size;
- }
-
- case MCFragment::FT_Org: {
- const MCOrgFragment &OF = cast<MCOrgFragment>(F);
- MCValue Value;
- if (!OF.getOffset().evaluateAsValue(Value, Layout)) {
- getContext().reportError(OF.getLoc(),
- "expected assembly-time absolute expression");
- return 0;
- }
-
- uint64_t FragmentOffset = Layout.getFragmentOffset(&OF);
- int64_t TargetLocation = Value.getConstant();
- if (const MCSymbolRefExpr *A = Value.getSymA()) {
- uint64_t Val;
- if (!Layout.getSymbolOffset(A->getSymbol(), Val)) {
- getContext().reportError(OF.getLoc(), "expected absolute expression");
- return 0;
- }
- TargetLocation += Val;
- }
- int64_t Size = TargetLocation - FragmentOffset;
- if (Size < 0 || Size >= 0x40000000) {
- getContext().reportError(
- OF.getLoc(), "invalid .org offset '" + Twine(TargetLocation) +
- "' (at offset '" + Twine(FragmentOffset) + "')");
- return 0;
- }
- return Size;
- }
-
- case MCFragment::FT_Dwarf:
- return cast<MCDwarfLineAddrFragment>(F).getContents().size();
- case MCFragment::FT_DwarfFrame:
- return cast<MCDwarfCallFrameFragment>(F).getContents().size();
- case MCFragment::FT_CVInlineLines:
- return cast<MCCVInlineLineTableFragment>(F).getContents().size();
- case MCFragment::FT_CVDefRange:
- return cast<MCCVDefRangeFragment>(F).getContents().size();
- case MCFragment::FT_Dummy:
- llvm_unreachable("Should not have been added");
- }
-
- llvm_unreachable("invalid fragment kind");
-}
-
-void MCAsmLayout::layoutFragment(MCFragment *F) {
- MCFragment *Prev = F->getPrevNode();
-
- // We should never try to recompute something which is valid.
- assert(!isFragmentValid(F) && "Attempt to recompute a valid fragment!");
- // We should never try to compute the fragment layout if its predecessor
- // isn't valid.
- assert((!Prev || isFragmentValid(Prev)) &&
- "Attempt to compute fragment before its predecessor!");
-
- ++stats::FragmentLayouts;
-
- // Compute fragment offset and size.
- if (Prev)
- F->Offset = Prev->Offset + getAssembler().computeFragmentSize(*this, *Prev);
- else
- F->Offset = 0;
- LastValidFragment[F->getParent()] = F;
-
- // If bundling is enabled and this fragment has instructions in it, it has to
- // obey the bundling restrictions. With padding, we'll have:
- //
- //
- // BundlePadding
- // |||
- // -------------------------------------
- // Prev |##########| F |
- // -------------------------------------
- // ^
- // |
- // F->Offset
- //
- // The fragment's offset will point to after the padding, and its computed
- // size won't include the padding.
- //
- // When the -mc-relax-all flag is used, we optimize bundling by writting the
- // padding directly into fragments when the instructions are emitted inside
- // the streamer. When the fragment is larger than the bundle size, we need to
- // ensure that it's bundle aligned. This means that if we end up with
- // multiple fragments, we must emit bundle padding between fragments.
- //
- // ".align N" is an example of a directive that introduces multiple
- // fragments. We could add a special case to handle ".align N" by emitting
- // within-fragment padding (which would produce less padding when N is less
- // than the bundle size), but for now we don't.
- //
- if (Assembler.isBundlingEnabled() && F->hasInstructions()) {
- assert(isa<MCEncodedFragment>(F) &&
- "Only MCEncodedFragment implementations have instructions");
- MCEncodedFragment *EF = cast<MCEncodedFragment>(F);
- uint64_t FSize = Assembler.computeFragmentSize(*this, *EF);
-
- if (!Assembler.getRelaxAll() && FSize > Assembler.getBundleAlignSize())
- report_fatal_error("Fragment can't be larger than a bundle size");
-
- uint64_t RequiredBundlePadding =
- computeBundlePadding(Assembler, EF, EF->Offset, FSize);
- if (RequiredBundlePadding > UINT8_MAX)
- report_fatal_error("Padding cannot exceed 255 bytes");
- EF->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding));
- EF->Offset += RequiredBundlePadding;
- }
-}
-
-void MCAssembler::registerSymbol(const MCSymbol &Symbol, bool *Created) {
- bool New = !Symbol.isRegistered();
- if (Created)
- *Created = New;
- if (New) {
- Symbol.setIsRegistered(true);
- Symbols.push_back(&Symbol);
- }
-}
-
-void MCAssembler::writeFragmentPadding(raw_ostream &OS,
- const MCEncodedFragment &EF,
- uint64_t FSize) const {
- assert(getBackendPtr() && "Expected assembler backend");
- // Should NOP padding be written out before this fragment?
- unsigned BundlePadding = EF.getBundlePadding();
- if (BundlePadding > 0) {
- assert(isBundlingEnabled() &&
- "Writing bundle padding with disabled bundling");
- assert(EF.hasInstructions() &&
- "Writing bundle padding for a fragment without instructions");
-
- unsigned TotalLength = BundlePadding + static_cast<unsigned>(FSize);
- if (EF.alignToBundleEnd() && TotalLength > getBundleAlignSize()) {
- // If the padding itself crosses a bundle boundary, it must be emitted
- // in 2 pieces, since even nop instructions must not cross boundaries.
- // v--------------v <- BundleAlignSize
- // v---------v <- BundlePadding
- // ----------------------------
- // | Prev |####|####| F |
- // ----------------------------
- // ^-------------------^ <- TotalLength
- unsigned DistanceToBoundary = TotalLength - getBundleAlignSize();
- if (!getBackend().writeNopData(OS, DistanceToBoundary))
- report_fatal_error("unable to write NOP sequence of " +
- Twine(DistanceToBoundary) + " bytes");
- BundlePadding -= DistanceToBoundary;
- }
- if (!getBackend().writeNopData(OS, BundlePadding))
- report_fatal_error("unable to write NOP sequence of " +
- Twine(BundlePadding) + " bytes");
- }
-}
-
-/// Write the fragment \p F to the output file.
-static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
- const MCAsmLayout &Layout, const MCFragment &F) {
- // FIXME: Embed in fragments instead?
- uint64_t FragmentSize = Asm.computeFragmentSize(Layout, F);
-
- support::endianness Endian = Asm.getBackend().Endian;
-
- if (const MCEncodedFragment *EF = dyn_cast<MCEncodedFragment>(&F))
- Asm.writeFragmentPadding(OS, *EF, FragmentSize);
-
- // This variable (and its dummy usage) is to participate in the assert at
- // the end of the function.
- uint64_t Start = OS.tell();
- (void) Start;
-
- ++stats::EmittedFragments;
-
- switch (F.getKind()) {
- case MCFragment::FT_Align: {
- ++stats::EmittedAlignFragments;
- const MCAlignFragment &AF = cast<MCAlignFragment>(F);
- assert(AF.getValueSize() && "Invalid virtual align in concrete fragment!");
-
- uint64_t Count = FragmentSize / AF.getValueSize();
-
- // FIXME: This error shouldn't actually occur (the front end should emit
- // multiple .align directives to enforce the semantics it wants), but is
- // severe enough that we want to report it. How to handle this?
- if (Count * AF.getValueSize() != FragmentSize)
- report_fatal_error("undefined .align directive, value size '" +
- Twine(AF.getValueSize()) +
- "' is not a divisor of padding size '" +
- Twine(FragmentSize) + "'");
-
- // See if we are aligning with nops, and if so do that first to try to fill
- // the Count bytes. Then if that did not fill any bytes or there are any
- // bytes left to fill use the Value and ValueSize to fill the rest.
- // If we are aligning with nops, ask that target to emit the right data.
- if (AF.hasEmitNops()) {
- if (!Asm.getBackend().writeNopData(OS, Count))
- report_fatal_error("unable to write nop sequence of " +
- Twine(Count) + " bytes");
- break;
- }
-
- // Otherwise, write out in multiples of the value size.
- for (uint64_t i = 0; i != Count; ++i) {
- switch (AF.getValueSize()) {
- default: llvm_unreachable("Invalid size!");
- case 1: OS << char(AF.getValue()); break;
- case 2:
- support::endian::write<uint16_t>(OS, AF.getValue(), Endian);
- break;
- case 4:
- support::endian::write<uint32_t>(OS, AF.getValue(), Endian);
- break;
- case 8:
- support::endian::write<uint64_t>(OS, AF.getValue(), Endian);
- break;
- }
- }
- break;
- }
-
- case MCFragment::FT_Data:
- ++stats::EmittedDataFragments;
- OS << cast<MCDataFragment>(F).getContents();
- break;
-
- case MCFragment::FT_Relaxable:
- ++stats::EmittedRelaxableFragments;
- OS << cast<MCRelaxableFragment>(F).getContents();
- break;
-
- case MCFragment::FT_CompactEncodedInst:
- ++stats::EmittedCompactEncodedInstFragments;
- OS << cast<MCCompactEncodedInstFragment>(F).getContents();
- break;
-
- case MCFragment::FT_Fill: {
- ++stats::EmittedFillFragments;
- const MCFillFragment &FF = cast<MCFillFragment>(F);
- uint64_t V = FF.getValue();
- unsigned VSize = FF.getValueSize();
- const unsigned MaxChunkSize = 16;
- char Data[MaxChunkSize];
- // Duplicate V into Data as byte vector to reduce number of
- // writes done. As such, do endian conversion here.
- for (unsigned I = 0; I != VSize; ++I) {
- unsigned index = Endian == support::little ? I : (VSize - I - 1);
- Data[I] = uint8_t(V >> (index * 8));
- }
- for (unsigned I = VSize; I < MaxChunkSize; ++I)
- Data[I] = Data[I - VSize];
-
- // Set to largest multiple of VSize in Data.
- const unsigned NumPerChunk = MaxChunkSize / VSize;
- // Set ChunkSize to largest multiple of VSize in Data
- const unsigned ChunkSize = VSize * NumPerChunk;
-
- // Do copies by chunk.
- StringRef Ref(Data, ChunkSize);
- for (uint64_t I = 0, E = FragmentSize / ChunkSize; I != E; ++I)
- OS << Ref;
-
- // do remainder if needed.
- unsigned TrailingCount = FragmentSize % ChunkSize;
- if (TrailingCount)
- OS.write(Data, TrailingCount);
- break;
- }
-
- case MCFragment::FT_LEB: {
- const MCLEBFragment &LF = cast<MCLEBFragment>(F);
- OS << LF.getContents();
- break;
- }
-
- case MCFragment::FT_Padding: {
- if (!Asm.getBackend().writeNopData(OS, FragmentSize))
- report_fatal_error("unable to write nop sequence of " +
- Twine(FragmentSize) + " bytes");
- break;
- }
-
- case MCFragment::FT_SymbolId: {
- const MCSymbolIdFragment &SF = cast<MCSymbolIdFragment>(F);
- support::endian::write<uint32_t>(OS, SF.getSymbol()->getIndex(), Endian);
- break;
- }
-
- case MCFragment::FT_Org: {
- ++stats::EmittedOrgFragments;
- const MCOrgFragment &OF = cast<MCOrgFragment>(F);
-
- for (uint64_t i = 0, e = FragmentSize; i != e; ++i)
- OS << char(OF.getValue());
-
- break;
- }
-
- case MCFragment::FT_Dwarf: {
- const MCDwarfLineAddrFragment &OF = cast<MCDwarfLineAddrFragment>(F);
- OS << OF.getContents();
- break;
- }
- case MCFragment::FT_DwarfFrame: {
- const MCDwarfCallFrameFragment &CF = cast<MCDwarfCallFrameFragment>(F);
- OS << CF.getContents();
- break;
- }
- case MCFragment::FT_CVInlineLines: {
- const auto &OF = cast<MCCVInlineLineTableFragment>(F);
- OS << OF.getContents();
- break;
- }
- case MCFragment::FT_CVDefRange: {
- const auto &DRF = cast<MCCVDefRangeFragment>(F);
- OS << DRF.getContents();
- break;
- }
- case MCFragment::FT_Dummy:
- llvm_unreachable("Should not have been added");
- }
-
- assert(OS.tell() - Start == FragmentSize &&
- "The stream should advance by fragment size");
-}
-
-void MCAssembler::writeSectionData(raw_ostream &OS, const MCSection *Sec,
- const MCAsmLayout &Layout) const {
- assert(getBackendPtr() && "Expected assembler backend");
-
- // Ignore virtual sections.
- if (Sec->isVirtualSection()) {
- assert(Layout.getSectionFileSize(Sec) == 0 && "Invalid size for section!");
-
- // Check that contents are only things legal inside a virtual section.
- for (const MCFragment &F : *Sec) {
- switch (F.getKind()) {
- default: llvm_unreachable("Invalid fragment in virtual section!");
- case MCFragment::FT_Data: {
- // Check that we aren't trying to write a non-zero contents (or fixups)
- // into a virtual section. This is to support clients which use standard
- // directives to fill the contents of virtual sections.
- const MCDataFragment &DF = cast<MCDataFragment>(F);
- if (DF.fixup_begin() != DF.fixup_end())
- report_fatal_error("cannot have fixups in virtual section!");
- for (unsigned i = 0, e = DF.getContents().size(); i != e; ++i)
- if (DF.getContents()[i]) {
- if (auto *ELFSec = dyn_cast<const MCSectionELF>(Sec))
- report_fatal_error("non-zero initializer found in section '" +
- ELFSec->getSectionName() + "'");
- else
- report_fatal_error("non-zero initializer found in virtual section");
- }
- break;
- }
- case MCFragment::FT_Align:
- // Check that we aren't trying to write a non-zero value into a virtual
- // section.
- assert((cast<MCAlignFragment>(F).getValueSize() == 0 ||
- cast<MCAlignFragment>(F).getValue() == 0) &&
- "Invalid align in virtual section!");
- break;
- case MCFragment::FT_Fill:
- assert((cast<MCFillFragment>(F).getValue() == 0) &&
- "Invalid fill in virtual section!");
- break;
- }
- }
-
- return;
- }
-
- uint64_t Start = OS.tell();
- (void)Start;
-
- for (const MCFragment &F : *Sec)
- writeFragment(OS, *this, Layout, F);
-
- assert(OS.tell() - Start == Layout.getSectionAddressSize(Sec));
-}
-
-std::tuple<MCValue, uint64_t, bool>
-MCAssembler::handleFixup(const MCAsmLayout &Layout, MCFragment &F,
- const MCFixup &Fixup) {
- // Evaluate the fixup.
- MCValue Target;
- uint64_t FixedValue;
- bool WasForced;
- bool IsResolved = evaluateFixup(Layout, Fixup, &F, Target, FixedValue,
- WasForced);
- if (!IsResolved) {
- // The fixup was unresolved, we need a relocation. Inform the object
- // writer of the relocation, and give it an opportunity to adjust the
- // fixup value if need be.
- if (Target.getSymA() && Target.getSymB() &&
- getBackend().requiresDiffExpressionRelocations()) {
- // The fixup represents the difference between two symbols, which the
- // backend has indicated must be resolved at link time. Split up the fixup
- // into two relocations, one for the add, and one for the sub, and emit
- // both of these. The constant will be associated with the add half of the
- // expression.
- MCFixup FixupAdd = MCFixup::createAddFor(Fixup);
- MCValue TargetAdd =
- MCValue::get(Target.getSymA(), nullptr, Target.getConstant());
- getWriter().recordRelocation(*this, Layout, &F, FixupAdd, TargetAdd,
- FixedValue);
- MCFixup FixupSub = MCFixup::createSubFor(Fixup);
- MCValue TargetSub = MCValue::get(Target.getSymB());
- getWriter().recordRelocation(*this, Layout, &F, FixupSub, TargetSub,
- FixedValue);
- } else {
- getWriter().recordRelocation(*this, Layout, &F, Fixup, Target,
- FixedValue);
- }
- }
- return std::make_tuple(Target, FixedValue, IsResolved);
-}
-
-void MCAssembler::layout(MCAsmLayout &Layout) {
- assert(getBackendPtr() && "Expected assembler backend");
- DEBUG_WITH_TYPE("mc-dump", {
- errs() << "assembler backend - pre-layout\n--\n";
- dump(); });
-
- // Create dummy fragments and assign section ordinals.
- unsigned SectionIndex = 0;
- for (MCSection &Sec : *this) {
- // Create dummy fragments to eliminate any empty sections, this simplifies
- // layout.
- if (Sec.getFragmentList().empty())
- new MCDataFragment(&Sec);
-
- Sec.setOrdinal(SectionIndex++);
- }
-
- // Assign layout order indices to sections and fragments.
- for (unsigned i = 0, e = Layout.getSectionOrder().size(); i != e; ++i) {
- MCSection *Sec = Layout.getSectionOrder()[i];
- Sec->setLayoutOrder(i);
-
- unsigned FragmentIndex = 0;
- for (MCFragment &Frag : *Sec)
- Frag.setLayoutOrder(FragmentIndex++);
- }
-
- // Layout until everything fits.
- while (layoutOnce(Layout))
- if (getContext().hadError())
- return;
-
- DEBUG_WITH_TYPE("mc-dump", {
- errs() << "assembler backend - post-relaxation\n--\n";
- dump(); });
-
- // Finalize the layout, including fragment lowering.
- finishLayout(Layout);
-
- DEBUG_WITH_TYPE("mc-dump", {
- errs() << "assembler backend - final-layout\n--\n";
- dump(); });
-
- // Allow the object writer a chance to perform post-layout binding (for
- // example, to set the index fields in the symbol data).
- getWriter().executePostLayoutBinding(*this, Layout);
-
- // Evaluate and apply the fixups, generating relocation entries as necessary.
- for (MCSection &Sec : *this) {
- for (MCFragment &Frag : Sec) {
- // Data and relaxable fragments both have fixups. So only process
- // those here.
- // FIXME: Is there a better way to do this? MCEncodedFragmentWithFixups
- // being templated makes this tricky.
- if (isa<MCEncodedFragment>(&Frag) &&
- isa<MCCompactEncodedInstFragment>(&Frag))
- continue;
- if (!isa<MCEncodedFragment>(&Frag) && !isa<MCCVDefRangeFragment>(&Frag) &&
- !isa<MCAlignFragment>(&Frag))
- continue;
- ArrayRef<MCFixup> Fixups;
- MutableArrayRef<char> Contents;
- const MCSubtargetInfo *STI = nullptr;
- if (auto *FragWithFixups = dyn_cast<MCDataFragment>(&Frag)) {
- Fixups = FragWithFixups->getFixups();
- Contents = FragWithFixups->getContents();
- STI = FragWithFixups->getSubtargetInfo();
- assert(!FragWithFixups->hasInstructions() || STI != nullptr);
- } else if (auto *FragWithFixups = dyn_cast<MCRelaxableFragment>(&Frag)) {
- Fixups = FragWithFixups->getFixups();
- Contents = FragWithFixups->getContents();
- STI = FragWithFixups->getSubtargetInfo();
- assert(!FragWithFixups->hasInstructions() || STI != nullptr);
- } else if (auto *FragWithFixups = dyn_cast<MCCVDefRangeFragment>(&Frag)) {
- Fixups = FragWithFixups->getFixups();
- Contents = FragWithFixups->getContents();
- } else if (auto *FragWithFixups = dyn_cast<MCDwarfLineAddrFragment>(&Frag)) {
- Fixups = FragWithFixups->getFixups();
- Contents = FragWithFixups->getContents();
- } else if (auto *AF = dyn_cast<MCAlignFragment>(&Frag)) {
- // Insert fixup type for code alignment if the target define
- // shouldInsertFixupForCodeAlign target hook.
- if (Sec.UseCodeAlign() && AF->hasEmitNops()) {
- getBackend().shouldInsertFixupForCodeAlign(*this, Layout, *AF);
- }
- continue;
- } else if (auto *FragWithFixups =
- dyn_cast<MCDwarfCallFrameFragment>(&Frag)) {
- Fixups = FragWithFixups->getFixups();
- Contents = FragWithFixups->getContents();
- } else
- llvm_unreachable("Unknown fragment with fixups!");
- for (const MCFixup &Fixup : Fixups) {
- uint64_t FixedValue;
- bool IsResolved;
- MCValue Target;
- std::tie(Target, FixedValue, IsResolved) =
- handleFixup(Layout, Frag, Fixup);
- getBackend().applyFixup(*this, Fixup, Target, Contents, FixedValue,
- IsResolved, STI);
- }
- }
- }
-}
-
-void MCAssembler::Finish() {
- // Create the layout object.
- MCAsmLayout Layout(*this);
- layout(Layout);
-
- // Write the object file.
- stats::ObjectBytes += getWriter().writeObject(*this, Layout);
-}
-
-bool MCAssembler::fixupNeedsRelaxation(const MCFixup &Fixup,
- const MCRelaxableFragment *DF,
- const MCAsmLayout &Layout) const {
- assert(getBackendPtr() && "Expected assembler backend");
- MCValue Target;
- uint64_t Value;
- bool WasForced;
- bool Resolved = evaluateFixup(Layout, Fixup, DF, Target, Value, WasForced);
- if (Target.getSymA() &&
- Target.getSymA()->getKind() == MCSymbolRefExpr::VK_X86_ABS8 &&
- Fixup.getKind() == FK_Data_1)
- return false;
- return getBackend().fixupNeedsRelaxationAdvanced(Fixup, Resolved, Value, DF,
- Layout, WasForced);
-}
-
-bool MCAssembler::fragmentNeedsRelaxation(const MCRelaxableFragment *F,
- const MCAsmLayout &Layout) const {
- assert(getBackendPtr() && "Expected assembler backend");
- // If this inst doesn't ever need relaxation, ignore it. This occurs when we
- // are intentionally pushing out inst fragments, or because we relaxed a
- // previous instruction to one that doesn't need relaxation.
- if (!getBackend().mayNeedRelaxation(F->getInst(), *F->getSubtargetInfo()))
- return false;
-
- for (const MCFixup &Fixup : F->getFixups())
- if (fixupNeedsRelaxation(Fixup, F, Layout))
- return true;
-
- return false;
-}
-
-bool MCAssembler::relaxInstruction(MCAsmLayout &Layout,
- MCRelaxableFragment &F) {
- assert(getEmitterPtr() &&
- "Expected CodeEmitter defined for relaxInstruction");
- if (!fragmentNeedsRelaxation(&F, Layout))
- return false;
-
- ++stats::RelaxedInstructions;
-
- // FIXME-PERF: We could immediately lower out instructions if we can tell
- // they are fully resolved, to avoid retesting on later passes.
-
- // Relax the fragment.
-
- MCInst Relaxed;
- getBackend().relaxInstruction(F.getInst(), *F.getSubtargetInfo(), Relaxed);
-
- // Encode the new instruction.
- //
- // FIXME-PERF: If it matters, we could let the target do this. It can
- // probably do so more efficiently in many cases.
- SmallVector<MCFixup, 4> Fixups;
- SmallString<256> Code;
- raw_svector_ostream VecOS(Code);
- getEmitter().encodeInstruction(Relaxed, VecOS, Fixups, *F.getSubtargetInfo());
-
- // Update the fragment.
- F.setInst(Relaxed);
- F.getContents() = Code;
- F.getFixups() = Fixups;
-
- return true;
-}
-
-bool MCAssembler::relaxPaddingFragment(MCAsmLayout &Layout,
- MCPaddingFragment &PF) {
- assert(getBackendPtr() && "Expected assembler backend");
- uint64_t OldSize = PF.getSize();
- if (!getBackend().relaxFragment(&PF, Layout))
- return false;
- uint64_t NewSize = PF.getSize();
-
- ++stats::PaddingFragmentsRelaxations;
- stats::PaddingFragmentsBytes += NewSize;
- stats::PaddingFragmentsBytes -= OldSize;
- return true;
-}
-
-bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) {
- uint64_t OldSize = LF.getContents().size();
- int64_t Value;
- bool Abs = LF.getValue().evaluateKnownAbsolute(Value, Layout);
- if (!Abs)
- report_fatal_error("sleb128 and uleb128 expressions must be absolute");
- SmallString<8> &Data = LF.getContents();
- Data.clear();
- raw_svector_ostream OSE(Data);
- // The compiler can generate EH table assembly that is impossible to assemble
- // without either adding padding to an LEB fragment or adding extra padding
- // to a later alignment fragment. To accommodate such tables, relaxation can
- // only increase an LEB fragment size here, not decrease it. See PR35809.
- if (LF.isSigned())
- encodeSLEB128(Value, OSE, OldSize);
- else
- encodeULEB128(Value, OSE, OldSize);
- return OldSize != LF.getContents().size();
-}
-
-bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout,
- MCDwarfLineAddrFragment &DF) {
- MCContext &Context = Layout.getAssembler().getContext();
- uint64_t OldSize = DF.getContents().size();
- int64_t AddrDelta;
- bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout);
- assert(Abs && "We created a line delta with an invalid expression");
- (void)Abs;
- int64_t LineDelta;
- LineDelta = DF.getLineDelta();
- SmallVectorImpl<char> &Data = DF.getContents();
- Data.clear();
- raw_svector_ostream OSE(Data);
- DF.getFixups().clear();
-
- if (!getBackend().requiresDiffExpressionRelocations()) {
- MCDwarfLineAddr::Encode(Context, getDWARFLinetableParams(), LineDelta,
- AddrDelta, OSE);
- } else {
- uint32_t Offset;
- uint32_t Size;
- bool SetDelta = MCDwarfLineAddr::FixedEncode(Context,
- getDWARFLinetableParams(),
- LineDelta, AddrDelta,
- OSE, &Offset, &Size);
- // Add Fixups for address delta or new address.
- const MCExpr *FixupExpr;
- if (SetDelta) {
- FixupExpr = &DF.getAddrDelta();
- } else {
- const MCBinaryExpr *ABE = cast<MCBinaryExpr>(&DF.getAddrDelta());
- FixupExpr = ABE->getLHS();
- }
- DF.getFixups().push_back(
- MCFixup::create(Offset, FixupExpr,
- MCFixup::getKindForSize(Size, false /*isPCRel*/)));
- }
-
- return OldSize != Data.size();
-}
-
-bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout,
- MCDwarfCallFrameFragment &DF) {
- MCContext &Context = Layout.getAssembler().getContext();
- uint64_t OldSize = DF.getContents().size();
- int64_t AddrDelta;
- bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout);
- assert(Abs && "We created call frame with an invalid expression");
- (void) Abs;
- SmallVectorImpl<char> &Data = DF.getContents();
- Data.clear();
- raw_svector_ostream OSE(Data);
- DF.getFixups().clear();
-
- if (getBackend().requiresDiffExpressionRelocations()) {
- uint32_t Offset;
- uint32_t Size;
- MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OSE, &Offset,
- &Size);
- if (Size) {
- DF.getFixups().push_back(MCFixup::create(
- Offset, &DF.getAddrDelta(),
- MCFixup::getKindForSizeInBits(Size /*In bits.*/, false /*isPCRel*/)));
- }
- } else {
- MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OSE);
- }
-
- return OldSize != Data.size();
-}
-
-bool MCAssembler::relaxCVInlineLineTable(MCAsmLayout &Layout,
- MCCVInlineLineTableFragment &F) {
- unsigned OldSize = F.getContents().size();
- getContext().getCVContext().encodeInlineLineTable(Layout, F);
- return OldSize != F.getContents().size();
-}
-
-bool MCAssembler::relaxCVDefRange(MCAsmLayout &Layout,
- MCCVDefRangeFragment &F) {
- unsigned OldSize = F.getContents().size();
- getContext().getCVContext().encodeDefRange(Layout, F);
- return OldSize != F.getContents().size();
-}
-
-bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec) {
- // Holds the first fragment which needed relaxing during this layout. It will
- // remain NULL if none were relaxed.
- // When a fragment is relaxed, all the fragments following it should get
- // invalidated because their offset is going to change.
- MCFragment *FirstRelaxedFragment = nullptr;
-
- // Attempt to relax all the fragments in the section.
- for (MCSection::iterator I = Sec.begin(), IE = Sec.end(); I != IE; ++I) {
- // Check if this is a fragment that needs relaxation.
- bool RelaxedFrag = false;
- switch(I->getKind()) {
- default:
- break;
- case MCFragment::FT_Relaxable:
- assert(!getRelaxAll() &&
- "Did not expect a MCRelaxableFragment in RelaxAll mode");
- RelaxedFrag = relaxInstruction(Layout, *cast<MCRelaxableFragment>(I));
- break;
- case MCFragment::FT_Dwarf:
- RelaxedFrag = relaxDwarfLineAddr(Layout,
- *cast<MCDwarfLineAddrFragment>(I));
- break;
- case MCFragment::FT_DwarfFrame:
- RelaxedFrag =
- relaxDwarfCallFrameFragment(Layout,
- *cast<MCDwarfCallFrameFragment>(I));
- break;
- case MCFragment::FT_LEB:
- RelaxedFrag = relaxLEB(Layout, *cast<MCLEBFragment>(I));
- break;
- case MCFragment::FT_Padding:
- RelaxedFrag = relaxPaddingFragment(Layout, *cast<MCPaddingFragment>(I));
- break;
- case MCFragment::FT_CVInlineLines:
- RelaxedFrag =
- relaxCVInlineLineTable(Layout, *cast<MCCVInlineLineTableFragment>(I));
- break;
- case MCFragment::FT_CVDefRange:
- RelaxedFrag = relaxCVDefRange(Layout, *cast<MCCVDefRangeFragment>(I));
- break;
- }
- if (RelaxedFrag && !FirstRelaxedFragment)
- FirstRelaxedFragment = &*I;
- }
- if (FirstRelaxedFragment) {
- Layout.invalidateFragmentsFrom(FirstRelaxedFragment);
- return true;
- }
- return false;
-}
-
-bool MCAssembler::layoutOnce(MCAsmLayout &Layout) {
- ++stats::RelaxationSteps;
-
- bool WasRelaxed = false;
- for (iterator it = begin(), ie = end(); it != ie; ++it) {
- MCSection &Sec = *it;
- while (layoutSectionOnce(Layout, Sec))
- WasRelaxed = true;
- }
-
- return WasRelaxed;
-}
-
-void MCAssembler::finishLayout(MCAsmLayout &Layout) {
- assert(getBackendPtr() && "Expected assembler backend");
- // The layout is done. Mark every fragment as valid.
- for (unsigned int i = 0, n = Layout.getSectionOrder().size(); i != n; ++i) {
- MCSection &Section = *Layout.getSectionOrder()[i];
- Layout.getFragmentOffset(&*Section.rbegin());
- computeFragmentSize(Layout, *Section.rbegin());
- }
- getBackend().finishLayout(*this, Layout);
-}
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void MCAssembler::dump() const{
- raw_ostream &OS = errs();
-
- OS << "<MCAssembler\n";
- OS << " Sections:[\n ";
- for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
- if (it != begin()) OS << ",\n ";
- it->dump();
- }
- OS << "],\n";
- OS << " Symbols:[";
-
- for (const_symbol_iterator it = symbol_begin(), ie = symbol_end(); it != ie; ++it) {
- if (it != symbol_begin()) OS << ",\n ";
- OS << "(";
- it->dump();
- OS << ", Index:" << it->getIndex() << ", ";
- OS << ")";
- }
- OS << "]>\n";
-}
-#endif
diff --git a/contrib/llvm/lib/MC/MCCodeEmitter.cpp b/contrib/llvm/lib/MC/MCCodeEmitter.cpp
deleted file mode 100644
index 0d114f12d58c..000000000000
--- a/contrib/llvm/lib/MC/MCCodeEmitter.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-//===- MCCodeEmitter.cpp - Instruction Encoding ---------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCCodeEmitter.h"
-
-using namespace llvm;
-
-MCCodeEmitter::MCCodeEmitter() = default;
-
-MCCodeEmitter::~MCCodeEmitter() = default;
diff --git a/contrib/llvm/lib/MC/MCCodePadder.cpp b/contrib/llvm/lib/MC/MCCodePadder.cpp
deleted file mode 100644
index 27a62f95a529..000000000000
--- a/contrib/llvm/lib/MC/MCCodePadder.cpp
+++ /dev/null
@@ -1,370 +0,0 @@
-//===- MCCodePadder.cpp - Target MC Code Padder ---------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCAsmLayout.h"
-#include "llvm/MC/MCCodePadder.h"
-#include "llvm/MC/MCObjectStreamer.h"
-#include <algorithm>
-#include <limits>
-#include <numeric>
-
-using namespace llvm;
-
-//---------------------------------------------------------------------------
-// MCCodePadder
-//
-
-MCCodePadder::~MCCodePadder() {
- for (auto *Policy : CodePaddingPolicies)
- delete Policy;
-}
-
-bool MCCodePadder::addPolicy(MCCodePaddingPolicy *Policy) {
- assert(Policy && "Policy must be valid");
- return CodePaddingPolicies.insert(Policy).second;
-}
-
-void MCCodePadder::handleBasicBlockStart(MCObjectStreamer *OS,
- const MCCodePaddingContext &Context) {
- assert(OS != nullptr && "OS must be valid");
- assert(this->OS == nullptr && "Still handling another basic block");
- this->OS = OS;
-
- ArePoliciesActive = usePoliciesForBasicBlock(Context);
-
- bool InsertionPoint = basicBlockRequiresInsertionPoint(Context);
- assert((!InsertionPoint ||
- OS->getCurrentFragment()->getKind() != MCFragment::FT_Align) &&
- "Cannot insert padding nops right after an alignment fragment as it "
- "will ruin the alignment");
-
- uint64_t PoliciesMask = MCPaddingFragment::PFK_None;
- if (ArePoliciesActive) {
- PoliciesMask = std::accumulate(
- CodePaddingPolicies.begin(), CodePaddingPolicies.end(),
- MCPaddingFragment::PFK_None,
- [&Context](uint64_t Mask,
- const MCCodePaddingPolicy *Policy) -> uint64_t {
- return Policy->basicBlockRequiresPaddingFragment(Context)
- ? (Mask | Policy->getKindMask())
- : Mask;
- });
- }
-
- if (InsertionPoint || PoliciesMask != MCPaddingFragment::PFK_None) {
- MCPaddingFragment *PaddingFragment = OS->getOrCreatePaddingFragment();
- if (InsertionPoint)
- PaddingFragment->setAsInsertionPoint();
- PaddingFragment->setPaddingPoliciesMask(
- PaddingFragment->getPaddingPoliciesMask() | PoliciesMask);
- }
-}
-
-void MCCodePadder::handleBasicBlockEnd(const MCCodePaddingContext &Context) {
- assert(this->OS != nullptr && "Not handling a basic block");
- OS = nullptr;
-}
-
-void MCCodePadder::handleInstructionBegin(const MCInst &Inst) {
- if (!OS)
- return; // instruction was emitted outside a function
-
- assert(CurrHandledInstFragment == nullptr && "Can't start handling an "
- "instruction while still "
- "handling another instruction");
-
- bool InsertionPoint = instructionRequiresInsertionPoint(Inst);
- assert((!InsertionPoint ||
- OS->getCurrentFragment()->getKind() != MCFragment::FT_Align) &&
- "Cannot insert padding nops right after an alignment fragment as it "
- "will ruin the alignment");
-
- uint64_t PoliciesMask = MCPaddingFragment::PFK_None;
- if (ArePoliciesActive) {
- PoliciesMask = std::accumulate(
- CodePaddingPolicies.begin(), CodePaddingPolicies.end(),
- MCPaddingFragment::PFK_None,
- [&Inst](uint64_t Mask, const MCCodePaddingPolicy *Policy) -> uint64_t {
- return Policy->instructionRequiresPaddingFragment(Inst)
- ? (Mask | Policy->getKindMask())
- : Mask;
- });
- }
- MCFragment *CurrFragment = OS->getCurrentFragment();
- // CurrFragment can be a previously created MCPaddingFragment. If so, let's
- // update it with the information we have, such as the instruction that it
- // should point to.
- bool needToUpdateCurrFragment =
- CurrFragment != nullptr &&
- CurrFragment->getKind() == MCFragment::FT_Padding;
- if (InsertionPoint || PoliciesMask != MCPaddingFragment::PFK_None ||
- needToUpdateCurrFragment) {
- // temporarily holding the fragment as CurrHandledInstFragment, to be
- // updated after the instruction will be written
- CurrHandledInstFragment = OS->getOrCreatePaddingFragment();
- if (InsertionPoint)
- CurrHandledInstFragment->setAsInsertionPoint();
- CurrHandledInstFragment->setPaddingPoliciesMask(
- CurrHandledInstFragment->getPaddingPoliciesMask() | PoliciesMask);
- }
-}
-
-void MCCodePadder::handleInstructionEnd(const MCInst &Inst) {
- if (!OS)
- return; // instruction was emitted outside a function
- if (CurrHandledInstFragment == nullptr)
- return;
-
- MCFragment *InstFragment = OS->getCurrentFragment();
- if (MCDataFragment *InstDataFragment =
- dyn_cast_or_null<MCDataFragment>(InstFragment))
- // Inst is a fixed size instruction and was encoded into a MCDataFragment.
- // Let the fragment hold it and its size. Its size is the current size of
- // the data fragment, as the padding fragment was inserted right before it
- // and nothing was written yet except Inst
- CurrHandledInstFragment->setInstAndInstSize(
- Inst, InstDataFragment->getContents().size());
- else if (MCRelaxableFragment *InstRelaxableFragment =
- dyn_cast_or_null<MCRelaxableFragment>(InstFragment))
- // Inst may be relaxed and its size may vary.
- // Let the fragment hold the instruction and the MCRelaxableFragment
- // that's holding it.
- CurrHandledInstFragment->setInstAndInstFragment(Inst,
- InstRelaxableFragment);
- else
- llvm_unreachable("After encoding an instruction current fragment must be "
- "either a MCDataFragment or a MCRelaxableFragment");
-
- CurrHandledInstFragment = nullptr;
-}
-
-MCPFRange &MCCodePadder::getJurisdiction(MCPaddingFragment *Fragment,
- MCAsmLayout &Layout) {
- auto JurisdictionLocation = FragmentToJurisdiction.find(Fragment);
- if (JurisdictionLocation != FragmentToJurisdiction.end())
- return JurisdictionLocation->second;
-
- MCPFRange Jurisdiction;
-
- // Forward scanning the fragments in this section, starting from the given
- // fragments, and adding relevant MCPaddingFragments to the Jurisdiction
- for (MCFragment *CurrFragment = Fragment; CurrFragment != nullptr;
- CurrFragment = CurrFragment->getNextNode()) {
-
- MCPaddingFragment *CurrPaddingFragment =
- dyn_cast<MCPaddingFragment>(CurrFragment);
- if (CurrPaddingFragment == nullptr)
- continue;
-
- if (CurrPaddingFragment != Fragment &&
- CurrPaddingFragment->isInsertionPoint())
- // Found next insertion point Fragment. From now on it's its jurisdiction.
- break;
- for (const auto *Policy : CodePaddingPolicies) {
- if (CurrPaddingFragment->hasPaddingPolicy(Policy->getKindMask())) {
- Jurisdiction.push_back(CurrPaddingFragment);
- break;
- }
- }
- }
-
- auto InsertionResult =
- FragmentToJurisdiction.insert(std::make_pair(Fragment, Jurisdiction));
- assert(InsertionResult.second &&
- "Insertion to FragmentToJurisdiction failed");
- return InsertionResult.first->second;
-}
-
-uint64_t MCCodePadder::getMaxWindowSize(MCPaddingFragment *Fragment,
- MCAsmLayout &Layout) {
- auto MaxFragmentSizeLocation = FragmentToMaxWindowSize.find(Fragment);
- if (MaxFragmentSizeLocation != FragmentToMaxWindowSize.end())
- return MaxFragmentSizeLocation->second;
-
- MCPFRange &Jurisdiction = getJurisdiction(Fragment, Layout);
- uint64_t JurisdictionMask = MCPaddingFragment::PFK_None;
- for (const auto *Protege : Jurisdiction)
- JurisdictionMask |= Protege->getPaddingPoliciesMask();
-
- uint64_t MaxFragmentSize = UINT64_C(0);
- for (const auto *Policy : CodePaddingPolicies)
- if ((JurisdictionMask & Policy->getKindMask()) !=
- MCPaddingFragment::PFK_None)
- MaxFragmentSize = std::max(MaxFragmentSize, Policy->getWindowSize());
-
- auto InsertionResult =
- FragmentToMaxWindowSize.insert(std::make_pair(Fragment, MaxFragmentSize));
- assert(InsertionResult.second &&
- "Insertion to FragmentToMaxWindowSize failed");
- return InsertionResult.first->second;
-}
-
-bool MCCodePadder::relaxFragment(MCPaddingFragment *Fragment,
- MCAsmLayout &Layout) {
- if (!Fragment->isInsertionPoint())
- return false;
- uint64_t OldSize = Fragment->getSize();
-
- uint64_t MaxWindowSize = getMaxWindowSize(Fragment, Layout);
- if (MaxWindowSize == UINT64_C(0))
- return false;
- assert(isPowerOf2_64(MaxWindowSize) &&
- "MaxWindowSize must be an integer power of 2");
- uint64_t SectionAlignment = Fragment->getParent()->getAlignment();
- assert(isPowerOf2_64(SectionAlignment) &&
- "SectionAlignment must be an integer power of 2");
-
- MCPFRange &Jurisdiction = getJurisdiction(Fragment, Layout);
- uint64_t OptimalSize = UINT64_C(0);
- double OptimalWeight = std::numeric_limits<double>::max();
- uint64_t MaxFragmentSize = MaxWindowSize - UINT16_C(1);
- for (uint64_t Size = UINT64_C(0); Size <= MaxFragmentSize; ++Size) {
- Fragment->setSize(Size);
- Layout.invalidateFragmentsFrom(Fragment);
- double SizeWeight = 0.0;
- // The section is guaranteed to be aligned to SectionAlignment, but that
- // doesn't guarantee the exact section offset w.r.t. the policies window
- // size.
- // As a concrete example, the section could be aligned to 16B, but a
- // policy's window size can be 32B. That means that the section actual start
- // address can either be 0mod32 or 16mod32. The said policy will act
- // differently for each case, so we need to take both into consideration.
- for (uint64_t Offset = UINT64_C(0); Offset < MaxWindowSize;
- Offset += SectionAlignment) {
- double OffsetWeight = std::accumulate(
- CodePaddingPolicies.begin(), CodePaddingPolicies.end(), 0.0,
- [&Jurisdiction, &Offset, &Layout](
- double Weight, const MCCodePaddingPolicy *Policy) -> double {
- double PolicyWeight =
- Policy->computeRangePenaltyWeight(Jurisdiction, Offset, Layout);
- assert(PolicyWeight >= 0.0 && "A penalty weight must be positive");
- return Weight + PolicyWeight;
- });
- SizeWeight = std::max(SizeWeight, OffsetWeight);
- }
- if (SizeWeight < OptimalWeight) {
- OptimalWeight = SizeWeight;
- OptimalSize = Size;
- }
- if (OptimalWeight == 0.0)
- break;
- }
-
- Fragment->setSize(OptimalSize);
- Layout.invalidateFragmentsFrom(Fragment);
- return OldSize != OptimalSize;
-}
-
-//---------------------------------------------------------------------------
-// MCCodePaddingPolicy
-//
-
-uint64_t MCCodePaddingPolicy::getNextFragmentOffset(const MCFragment *Fragment,
- const MCAsmLayout &Layout) {
- assert(Fragment != nullptr && "Fragment cannot be null");
- MCFragment const *NextFragment = Fragment->getNextNode();
- return NextFragment == nullptr
- ? Layout.getSectionAddressSize(Fragment->getParent())
- : Layout.getFragmentOffset(NextFragment);
-}
-
-uint64_t
-MCCodePaddingPolicy::getFragmentInstByte(const MCPaddingFragment *Fragment,
- MCAsmLayout &Layout) const {
- uint64_t InstByte = getNextFragmentOffset(Fragment, Layout);
- if (InstByteIsLastByte)
- InstByte += Fragment->getInstSize() - UINT64_C(1);
- return InstByte;
-}
-
-uint64_t
-MCCodePaddingPolicy::computeWindowEndAddress(const MCPaddingFragment *Fragment,
- uint64_t Offset,
- MCAsmLayout &Layout) const {
- uint64_t InstByte = getFragmentInstByte(Fragment, Layout);
- return alignTo(InstByte + UINT64_C(1) + Offset, WindowSize) - Offset;
-}
-
-double MCCodePaddingPolicy::computeRangePenaltyWeight(
- const MCPFRange &Range, uint64_t Offset, MCAsmLayout &Layout) const {
-
- SmallVector<MCPFRange, 8> Windows;
- SmallVector<MCPFRange, 8>::iterator CurrWindowLocation = Windows.end();
- for (const MCPaddingFragment *Fragment : Range) {
- if (!Fragment->hasPaddingPolicy(getKindMask()))
- continue;
- uint64_t FragmentWindowEndAddress =
- computeWindowEndAddress(Fragment, Offset, Layout);
- if (CurrWindowLocation == Windows.end() ||
- FragmentWindowEndAddress !=
- computeWindowEndAddress(*CurrWindowLocation->begin(), Offset,
- Layout)) {
- // next window is starting
- Windows.push_back(MCPFRange());
- CurrWindowLocation = Windows.end() - 1;
- }
- CurrWindowLocation->push_back(Fragment);
- }
-
- if (Windows.empty())
- return 0.0;
-
- double RangeWeight = 0.0;
- SmallVector<MCPFRange, 8>::iterator I = Windows.begin();
- RangeWeight += computeFirstWindowPenaltyWeight(*I, Offset, Layout);
- ++I;
- RangeWeight += std::accumulate(
- I, Windows.end(), 0.0,
- [this, &Layout, &Offset](double Weight, MCPFRange &Window) -> double {
- return Weight += computeWindowPenaltyWeight(Window, Offset, Layout);
- });
- return RangeWeight;
-}
-
-double MCCodePaddingPolicy::computeFirstWindowPenaltyWeight(
- const MCPFRange &Window, uint64_t Offset, MCAsmLayout &Layout) const {
- if (Window.empty())
- return 0.0;
- uint64_t WindowEndAddress =
- computeWindowEndAddress(*Window.begin(), Offset, Layout);
-
- MCPFRange FullWindowFirstPart; // will hold all the fragments that are in the
- // same window as the fragments in the given
- // window but their penalty weight should not
- // be added
- for (const MCFragment *Fragment = (*Window.begin())->getPrevNode();
- Fragment != nullptr; Fragment = Fragment->getPrevNode()) {
- const MCPaddingFragment *PaddingNopFragment =
- dyn_cast<MCPaddingFragment>(Fragment);
- if (PaddingNopFragment == nullptr ||
- !PaddingNopFragment->hasPaddingPolicy(getKindMask()))
- continue;
- if (WindowEndAddress !=
- computeWindowEndAddress(PaddingNopFragment, Offset, Layout))
- break;
-
- FullWindowFirstPart.push_back(PaddingNopFragment);
- }
-
- std::reverse(FullWindowFirstPart.begin(), FullWindowFirstPart.end());
- double FullWindowFirstPartWeight =
- computeWindowPenaltyWeight(FullWindowFirstPart, Offset, Layout);
-
- MCPFRange FullWindow(
- FullWindowFirstPart); // will hold all the fragments that are in the
- // same window as the fragments in the given
- // window, whether their weight should be added
- // or not
- FullWindow.append(Window.begin(), Window.end());
- double FullWindowWeight =
- computeWindowPenaltyWeight(FullWindow, Offset, Layout);
-
- assert(FullWindowWeight >= FullWindowFirstPartWeight &&
- "More fragments necessarily means bigger weight");
- return FullWindowWeight - FullWindowFirstPartWeight;
-}
diff --git a/contrib/llvm/lib/MC/MCCodeView.cpp b/contrib/llvm/lib/MC/MCCodeView.cpp
deleted file mode 100644
index 1a71b542bd06..000000000000
--- a/contrib/llvm/lib/MC/MCCodeView.cpp
+++ /dev/null
@@ -1,696 +0,0 @@
-//===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Holds state from .cv_file and .cv_loc directives for later emission.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCCodeView.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/CodeView/Line.h"
-#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
-#include "llvm/MC/MCAsmLayout.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCObjectStreamer.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/Support/EndianStream.h"
-
-using namespace llvm;
-using namespace llvm::codeview;
-
-CodeViewContext::CodeViewContext() {}
-
-CodeViewContext::~CodeViewContext() {
- // If someone inserted strings into the string table but never actually
- // emitted them somewhere, clean up the fragment.
- if (!InsertedStrTabFragment)
- delete StrTabFragment;
-}
-
-/// This is a valid number for use with .cv_loc if we've already seen a .cv_file
-/// for it.
-bool CodeViewContext::isValidFileNumber(unsigned FileNumber) const {
- unsigned Idx = FileNumber - 1;
- if (Idx < Files.size())
- return Files[Idx].Assigned;
- return false;
-}
-
-bool CodeViewContext::addFile(MCStreamer &OS, unsigned FileNumber,
- StringRef Filename,
- ArrayRef<uint8_t> ChecksumBytes,
- uint8_t ChecksumKind) {
- assert(FileNumber > 0);
- auto FilenameOffset = addToStringTable(Filename);
- Filename = FilenameOffset.first;
- unsigned Idx = FileNumber - 1;
- if (Idx >= Files.size())
- Files.resize(Idx + 1);
-
- if (Filename.empty())
- Filename = "<stdin>";
-
- if (Files[Idx].Assigned)
- return false;
-
- FilenameOffset = addToStringTable(Filename);
- Filename = FilenameOffset.first;
- unsigned Offset = FilenameOffset.second;
-
- auto ChecksumOffsetSymbol =
- OS.getContext().createTempSymbol("checksum_offset", false);
- Files[Idx].StringTableOffset = Offset;
- Files[Idx].ChecksumTableOffset = ChecksumOffsetSymbol;
- Files[Idx].Assigned = true;
- Files[Idx].Checksum = ChecksumBytes;
- Files[Idx].ChecksumKind = ChecksumKind;
-
- return true;
-}
-
-MCCVFunctionInfo *CodeViewContext::getCVFunctionInfo(unsigned FuncId) {
- if (FuncId >= Functions.size())
- return nullptr;
- if (Functions[FuncId].isUnallocatedFunctionInfo())
- return nullptr;
- return &Functions[FuncId];
-}
-
-bool CodeViewContext::recordFunctionId(unsigned FuncId) {
- if (FuncId >= Functions.size())
- Functions.resize(FuncId + 1);
-
- // Return false if this function info was already allocated.
- if (!Functions[FuncId].isUnallocatedFunctionInfo())
- return false;
-
- // Mark this as an allocated normal function, and leave the rest alone.
- Functions[FuncId].ParentFuncIdPlusOne = MCCVFunctionInfo::FunctionSentinel;
- return true;
-}
-
-bool CodeViewContext::recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc,
- unsigned IAFile, unsigned IALine,
- unsigned IACol) {
- if (FuncId >= Functions.size())
- Functions.resize(FuncId + 1);
-
- // Return false if this function info was already allocated.
- if (!Functions[FuncId].isUnallocatedFunctionInfo())
- return false;
-
- MCCVFunctionInfo::LineInfo InlinedAt;
- InlinedAt.File = IAFile;
- InlinedAt.Line = IALine;
- InlinedAt.Col = IACol;
-
- // Mark this as an inlined call site and record call site line info.
- MCCVFunctionInfo *Info = &Functions[FuncId];
- Info->ParentFuncIdPlusOne = IAFunc + 1;
- Info->InlinedAt = InlinedAt;
-
- // Walk up the call chain adding this function id to the InlinedAtMap of all
- // transitive callers until we hit a real function.
- while (Info->isInlinedCallSite()) {
- InlinedAt = Info->InlinedAt;
- Info = getCVFunctionInfo(Info->getParentFuncId());
- Info->InlinedAtMap[FuncId] = InlinedAt;
- }
-
- return true;
-}
-
-void CodeViewContext::recordCVLoc(MCContext &Ctx, const MCSymbol *Label,
- unsigned FunctionId, unsigned FileNo,
- unsigned Line, unsigned Column,
- bool PrologueEnd, bool IsStmt) {
- addLineEntry(MCCVLoc{
- Label, FunctionId, FileNo, Line, Column, PrologueEnd, IsStmt});
-}
-
-MCDataFragment *CodeViewContext::getStringTableFragment() {
- if (!StrTabFragment) {
- StrTabFragment = new MCDataFragment();
- // Start a new string table out with a null byte.
- StrTabFragment->getContents().push_back('\0');
- }
- return StrTabFragment;
-}
-
-std::pair<StringRef, unsigned> CodeViewContext::addToStringTable(StringRef S) {
- SmallVectorImpl<char> &Contents = getStringTableFragment()->getContents();
- auto Insertion =
- StringTable.insert(std::make_pair(S, unsigned(Contents.size())));
- // Return the string from the table, since it is stable.
- std::pair<StringRef, unsigned> Ret =
- std::make_pair(Insertion.first->first(), Insertion.first->second);
- if (Insertion.second) {
- // The string map key is always null terminated.
- Contents.append(Ret.first.begin(), Ret.first.end() + 1);
- }
- return Ret;
-}
-
-unsigned CodeViewContext::getStringTableOffset(StringRef S) {
- // A string table offset of zero is always the empty string.
- if (S.empty())
- return 0;
- auto I = StringTable.find(S);
- assert(I != StringTable.end());
- return I->second;
-}
-
-void CodeViewContext::emitStringTable(MCObjectStreamer &OS) {
- MCContext &Ctx = OS.getContext();
- MCSymbol *StringBegin = Ctx.createTempSymbol("strtab_begin", false),
- *StringEnd = Ctx.createTempSymbol("strtab_end", false);
-
- OS.EmitIntValue(unsigned(DebugSubsectionKind::StringTable), 4);
- OS.emitAbsoluteSymbolDiff(StringEnd, StringBegin, 4);
- OS.EmitLabel(StringBegin);
-
- // Put the string table data fragment here, if we haven't already put it
- // somewhere else. If somebody wants two string tables in their .s file, one
- // will just be empty.
- if (!InsertedStrTabFragment) {
- OS.insert(getStringTableFragment());
- InsertedStrTabFragment = true;
- }
-
- OS.EmitValueToAlignment(4, 0);
-
- OS.EmitLabel(StringEnd);
-}
-
-void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) {
- // Do nothing if there are no file checksums. Microsoft's linker rejects empty
- // CodeView substreams.
- if (Files.empty())
- return;
-
- MCContext &Ctx = OS.getContext();
- MCSymbol *FileBegin = Ctx.createTempSymbol("filechecksums_begin", false),
- *FileEnd = Ctx.createTempSymbol("filechecksums_end", false);
-
- OS.EmitIntValue(unsigned(DebugSubsectionKind::FileChecksums), 4);
- OS.emitAbsoluteSymbolDiff(FileEnd, FileBegin, 4);
- OS.EmitLabel(FileBegin);
-
- unsigned CurrentOffset = 0;
-
- // Emit an array of FileChecksum entries. We index into this table using the
- // user-provided file number. Each entry may be a variable number of bytes
- // determined by the checksum kind and size.
- for (auto File : Files) {
- OS.EmitAssignment(File.ChecksumTableOffset,
- MCConstantExpr::create(CurrentOffset, Ctx));
- CurrentOffset += 4; // String table offset.
- if (!File.ChecksumKind) {
- CurrentOffset +=
- 4; // One byte each for checksum size and kind, then align to 4 bytes.
- } else {
- CurrentOffset += 2; // One byte each for checksum size and kind.
- CurrentOffset += File.Checksum.size();
- CurrentOffset = alignTo(CurrentOffset, 4);
- }
-
- OS.EmitIntValue(File.StringTableOffset, 4);
-
- if (!File.ChecksumKind) {
- // There is no checksum. Therefore zero the next two fields and align
- // back to 4 bytes.
- OS.EmitIntValue(0, 4);
- continue;
- }
- OS.EmitIntValue(static_cast<uint8_t>(File.Checksum.size()), 1);
- OS.EmitIntValue(File.ChecksumKind, 1);
- OS.EmitBytes(toStringRef(File.Checksum));
- OS.EmitValueToAlignment(4);
- }
-
- OS.EmitLabel(FileEnd);
-
- ChecksumOffsetsAssigned = true;
-}
-
-// Output checksum table offset of the given file number. It is possible that
-// not all files have been registered yet, and so the offset cannot be
-// calculated. In this case a symbol representing the offset is emitted, and
-// the value of this symbol will be fixed up at a later time.
-void CodeViewContext::emitFileChecksumOffset(MCObjectStreamer &OS,
- unsigned FileNo) {
- unsigned Idx = FileNo - 1;
-
- if (Idx >= Files.size())
- Files.resize(Idx + 1);
-
- if (ChecksumOffsetsAssigned) {
- OS.EmitSymbolValue(Files[Idx].ChecksumTableOffset, 4);
- return;
- }
-
- const MCSymbolRefExpr *SRE =
- MCSymbolRefExpr::create(Files[Idx].ChecksumTableOffset, OS.getContext());
-
- OS.EmitValueImpl(SRE, 4);
-}
-
-void CodeViewContext::addLineEntry(const MCCVLoc &LineEntry) {
- size_t Offset = MCCVLines.size();
- auto I = MCCVLineStartStop.insert(
- {LineEntry.getFunctionId(), {Offset, Offset + 1}});
- if (!I.second)
- I.first->second.second = Offset + 1;
- MCCVLines.push_back(LineEntry);
-}
-
-std::vector<MCCVLoc>
-CodeViewContext::getFunctionLineEntries(unsigned FuncId) {
- std::vector<MCCVLoc> FilteredLines;
- auto I = MCCVLineStartStop.find(FuncId);
- if (I != MCCVLineStartStop.end()) {
- MCCVFunctionInfo *SiteInfo = getCVFunctionInfo(FuncId);
- for (size_t Idx = I->second.first, End = I->second.second; Idx != End;
- ++Idx) {
- unsigned LocationFuncId = MCCVLines[Idx].getFunctionId();
- if (LocationFuncId == FuncId) {
- // This was a .cv_loc directly for FuncId, so record it.
- FilteredLines.push_back(MCCVLines[Idx]);
- } else {
- // Check if the current location is inlined in this function. If it is,
- // synthesize a statement .cv_loc at the original inlined call site.
- auto I = SiteInfo->InlinedAtMap.find(LocationFuncId);
- if (I != SiteInfo->InlinedAtMap.end()) {
- MCCVFunctionInfo::LineInfo &IA = I->second;
- // Only add the location if it differs from the previous location.
- // Large inlined calls will have many .cv_loc entries and we only need
- // one line table entry in the parent function.
- if (FilteredLines.empty() ||
- FilteredLines.back().getFileNum() != IA.File ||
- FilteredLines.back().getLine() != IA.Line ||
- FilteredLines.back().getColumn() != IA.Col) {
- FilteredLines.push_back(MCCVLoc(
- MCCVLines[Idx].getLabel(),
- FuncId, IA.File, IA.Line, IA.Col, false, false));
- }
- }
- }
- }
- }
- return FilteredLines;
-}
-
-std::pair<size_t, size_t> CodeViewContext::getLineExtent(unsigned FuncId) {
- auto I = MCCVLineStartStop.find(FuncId);
- // Return an empty extent if there are no cv_locs for this function id.
- if (I == MCCVLineStartStop.end())
- return {~0ULL, 0};
- return I->second;
-}
-
-ArrayRef<MCCVLoc> CodeViewContext::getLinesForExtent(size_t L, size_t R) {
- if (R <= L)
- return None;
- if (L >= MCCVLines.size())
- return None;
- return makeArrayRef(&MCCVLines[L], R - L);
-}
-
-void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS,
- unsigned FuncId,
- const MCSymbol *FuncBegin,
- const MCSymbol *FuncEnd) {
- MCContext &Ctx = OS.getContext();
- MCSymbol *LineBegin = Ctx.createTempSymbol("linetable_begin", false),
- *LineEnd = Ctx.createTempSymbol("linetable_end", false);
-
- OS.EmitIntValue(unsigned(DebugSubsectionKind::Lines), 4);
- OS.emitAbsoluteSymbolDiff(LineEnd, LineBegin, 4);
- OS.EmitLabel(LineBegin);
- OS.EmitCOFFSecRel32(FuncBegin, /*Offset=*/0);
- OS.EmitCOFFSectionIndex(FuncBegin);
-
- // Actual line info.
- std::vector<MCCVLoc> Locs = getFunctionLineEntries(FuncId);
- bool HaveColumns = any_of(Locs, [](const MCCVLoc &LineEntry) {
- return LineEntry.getColumn() != 0;
- });
- OS.EmitIntValue(HaveColumns ? int(LF_HaveColumns) : 0, 2);
- OS.emitAbsoluteSymbolDiff(FuncEnd, FuncBegin, 4);
-
- for (auto I = Locs.begin(), E = Locs.end(); I != E;) {
- // Emit a file segment for the run of locations that share a file id.
- unsigned CurFileNum = I->getFileNum();
- auto FileSegEnd =
- std::find_if(I, E, [CurFileNum](const MCCVLoc &Loc) {
- return Loc.getFileNum() != CurFileNum;
- });
- unsigned EntryCount = FileSegEnd - I;
- OS.AddComment(
- "Segment for file '" +
- Twine(getStringTableFragment()
- ->getContents()[Files[CurFileNum - 1].StringTableOffset]) +
- "' begins");
- OS.EmitCVFileChecksumOffsetDirective(CurFileNum);
- OS.EmitIntValue(EntryCount, 4);
- uint32_t SegmentSize = 12;
- SegmentSize += 8 * EntryCount;
- if (HaveColumns)
- SegmentSize += 4 * EntryCount;
- OS.EmitIntValue(SegmentSize, 4);
-
- for (auto J = I; J != FileSegEnd; ++J) {
- OS.emitAbsoluteSymbolDiff(J->getLabel(), FuncBegin, 4);
- unsigned LineData = J->getLine();
- if (J->isStmt())
- LineData |= LineInfo::StatementFlag;
- OS.EmitIntValue(LineData, 4);
- }
- if (HaveColumns) {
- for (auto J = I; J != FileSegEnd; ++J) {
- OS.EmitIntValue(J->getColumn(), 2);
- OS.EmitIntValue(0, 2);
- }
- }
- I = FileSegEnd;
- }
- OS.EmitLabel(LineEnd);
-}
-
-static bool compressAnnotation(uint32_t Data, SmallVectorImpl<char> &Buffer) {
- if (isUInt<7>(Data)) {
- Buffer.push_back(Data);
- return true;
- }
-
- if (isUInt<14>(Data)) {
- Buffer.push_back((Data >> 8) | 0x80);
- Buffer.push_back(Data & 0xff);
- return true;
- }
-
- if (isUInt<29>(Data)) {
- Buffer.push_back((Data >> 24) | 0xC0);
- Buffer.push_back((Data >> 16) & 0xff);
- Buffer.push_back((Data >> 8) & 0xff);
- Buffer.push_back(Data & 0xff);
- return true;
- }
-
- return false;
-}
-
-static bool compressAnnotation(BinaryAnnotationsOpCode Annotation,
- SmallVectorImpl<char> &Buffer) {
- return compressAnnotation(static_cast<uint32_t>(Annotation), Buffer);
-}
-
-static uint32_t encodeSignedNumber(uint32_t Data) {
- if (Data >> 31)
- return ((-Data) << 1) | 1;
- return Data << 1;
-}
-
-void CodeViewContext::emitInlineLineTableForFunction(MCObjectStreamer &OS,
- unsigned PrimaryFunctionId,
- unsigned SourceFileId,
- unsigned SourceLineNum,
- const MCSymbol *FnStartSym,
- const MCSymbol *FnEndSym) {
- // Create and insert a fragment into the current section that will be encoded
- // later.
- new MCCVInlineLineTableFragment(PrimaryFunctionId, SourceFileId,
- SourceLineNum, FnStartSym, FnEndSym,
- OS.getCurrentSectionOnly());
-}
-
-MCFragment *CodeViewContext::emitDefRange(
- MCObjectStreamer &OS,
- ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
- StringRef FixedSizePortion) {
- // Create and insert a fragment into the current section that will be encoded
- // later.
- return new MCCVDefRangeFragment(Ranges, FixedSizePortion,
- OS.getCurrentSectionOnly());
-}
-
-static unsigned computeLabelDiff(MCAsmLayout &Layout, const MCSymbol *Begin,
- const MCSymbol *End) {
- MCContext &Ctx = Layout.getAssembler().getContext();
- MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
- const MCExpr *BeginRef = MCSymbolRefExpr::create(Begin, Variant, Ctx),
- *EndRef = MCSymbolRefExpr::create(End, Variant, Ctx);
- const MCExpr *AddrDelta =
- MCBinaryExpr::create(MCBinaryExpr::Sub, EndRef, BeginRef, Ctx);
- int64_t Result;
- bool Success = AddrDelta->evaluateKnownAbsolute(Result, Layout);
- assert(Success && "failed to evaluate label difference as absolute");
- (void)Success;
- assert(Result >= 0 && "negative label difference requested");
- assert(Result < UINT_MAX && "label difference greater than 2GB");
- return unsigned(Result);
-}
-
-void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
- MCCVInlineLineTableFragment &Frag) {
- size_t LocBegin;
- size_t LocEnd;
- std::tie(LocBegin, LocEnd) = getLineExtent(Frag.SiteFuncId);
-
- // Include all child inline call sites in our .cv_loc extent.
- MCCVFunctionInfo *SiteInfo = getCVFunctionInfo(Frag.SiteFuncId);
- for (auto &KV : SiteInfo->InlinedAtMap) {
- unsigned ChildId = KV.first;
- auto Extent = getLineExtent(ChildId);
- LocBegin = std::min(LocBegin, Extent.first);
- LocEnd = std::max(LocEnd, Extent.second);
- }
-
- if (LocBegin >= LocEnd)
- return;
- ArrayRef<MCCVLoc> Locs = getLinesForExtent(LocBegin, LocEnd);
- if (Locs.empty())
- return;
-
- // Check that the locations are all in the same section.
-#ifndef NDEBUG
- const MCSection *FirstSec = &Locs.front().getLabel()->getSection();
- for (const MCCVLoc &Loc : Locs) {
- if (&Loc.getLabel()->getSection() != FirstSec) {
- errs() << ".cv_loc " << Loc.getFunctionId() << ' ' << Loc.getFileNum()
- << ' ' << Loc.getLine() << ' ' << Loc.getColumn()
- << " is in the wrong section\n";
- llvm_unreachable(".cv_loc crosses sections");
- }
- }
-#endif
-
- // Make an artificial start location using the function start and the inlinee
- // lines start location information. All deltas start relative to this
- // location.
- MCCVLoc StartLoc = Locs.front();
- StartLoc.setLabel(Frag.getFnStartSym());
- StartLoc.setFileNum(Frag.StartFileId);
- StartLoc.setLine(Frag.StartLineNum);
- bool HaveOpenRange = false;
-
- const MCSymbol *LastLabel = Frag.getFnStartSym();
- MCCVFunctionInfo::LineInfo LastSourceLoc, CurSourceLoc;
- LastSourceLoc.File = Frag.StartFileId;
- LastSourceLoc.Line = Frag.StartLineNum;
-
- SmallVectorImpl<char> &Buffer = Frag.getContents();
- Buffer.clear(); // Clear old contents if we went through relaxation.
- for (const MCCVLoc &Loc : Locs) {
- // Exit early if our line table would produce an oversized InlineSiteSym
- // record. Account for the ChangeCodeLength annotation emitted after the
- // loop ends.
- constexpr uint32_t InlineSiteSize = 12;
- constexpr uint32_t AnnotationSize = 8;
- size_t MaxBufferSize = MaxRecordLength - InlineSiteSize - AnnotationSize;
- if (Buffer.size() >= MaxBufferSize)
- break;
-
- if (Loc.getFunctionId() == Frag.SiteFuncId) {
- CurSourceLoc.File = Loc.getFileNum();
- CurSourceLoc.Line = Loc.getLine();
- } else {
- auto I = SiteInfo->InlinedAtMap.find(Loc.getFunctionId());
- if (I != SiteInfo->InlinedAtMap.end()) {
- // This .cv_loc is from a child inline call site. Use the source
- // location of the inlined call site instead of the .cv_loc directive
- // source location.
- CurSourceLoc = I->second;
- } else {
- // We've hit a cv_loc not attributed to this inline call site. Use this
- // label to end the PC range.
- if (HaveOpenRange) {
- unsigned Length = computeLabelDiff(Layout, LastLabel, Loc.getLabel());
- compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer);
- compressAnnotation(Length, Buffer);
- LastLabel = Loc.getLabel();
- }
- HaveOpenRange = false;
- continue;
- }
- }
-
- // Skip this .cv_loc if we have an open range and this isn't a meaningful
- // source location update. The current table format does not support column
- // info, so we can skip updates for those.
- if (HaveOpenRange && CurSourceLoc.File == LastSourceLoc.File &&
- CurSourceLoc.Line == LastSourceLoc.Line)
- continue;
-
- HaveOpenRange = true;
-
- if (CurSourceLoc.File != LastSourceLoc.File) {
- unsigned FileOffset = static_cast<const MCConstantExpr *>(
- Files[CurSourceLoc.File - 1]
- .ChecksumTableOffset->getVariableValue())
- ->getValue();
- compressAnnotation(BinaryAnnotationsOpCode::ChangeFile, Buffer);
- compressAnnotation(FileOffset, Buffer);
- }
-
- int LineDelta = CurSourceLoc.Line - LastSourceLoc.Line;
- unsigned EncodedLineDelta = encodeSignedNumber(LineDelta);
- unsigned CodeDelta = computeLabelDiff(Layout, LastLabel, Loc.getLabel());
- if (CodeDelta == 0 && LineDelta != 0) {
- compressAnnotation(BinaryAnnotationsOpCode::ChangeLineOffset, Buffer);
- compressAnnotation(EncodedLineDelta, Buffer);
- } else if (EncodedLineDelta < 0x8 && CodeDelta <= 0xf) {
- // The ChangeCodeOffsetAndLineOffset combination opcode is used when the
- // encoded line delta uses 3 or fewer set bits and the code offset fits
- // in one nibble.
- unsigned Operand = (EncodedLineDelta << 4) | CodeDelta;
- compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset,
- Buffer);
- compressAnnotation(Operand, Buffer);
- } else {
- // Otherwise use the separate line and code deltas.
- if (LineDelta != 0) {
- compressAnnotation(BinaryAnnotationsOpCode::ChangeLineOffset, Buffer);
- compressAnnotation(EncodedLineDelta, Buffer);
- }
- compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeOffset, Buffer);
- compressAnnotation(CodeDelta, Buffer);
- }
-
- LastLabel = Loc.getLabel();
- LastSourceLoc = CurSourceLoc;
- }
-
- assert(HaveOpenRange);
-
- unsigned EndSymLength =
- computeLabelDiff(Layout, LastLabel, Frag.getFnEndSym());
- unsigned LocAfterLength = ~0U;
- ArrayRef<MCCVLoc> LocAfter = getLinesForExtent(LocEnd, LocEnd + 1);
- if (!LocAfter.empty()) {
- // Only try to compute this difference if we're in the same section.
- const MCCVLoc &Loc = LocAfter[0];
- if (&Loc.getLabel()->getSection() == &LastLabel->getSection())
- LocAfterLength = computeLabelDiff(Layout, LastLabel, Loc.getLabel());
- }
-
- compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer);
- compressAnnotation(std::min(EndSymLength, LocAfterLength), Buffer);
-}
-
-void CodeViewContext::encodeDefRange(MCAsmLayout &Layout,
- MCCVDefRangeFragment &Frag) {
- MCContext &Ctx = Layout.getAssembler().getContext();
- SmallVectorImpl<char> &Contents = Frag.getContents();
- Contents.clear();
- SmallVectorImpl<MCFixup> &Fixups = Frag.getFixups();
- Fixups.clear();
- raw_svector_ostream OS(Contents);
-
- // Compute all the sizes up front.
- SmallVector<std::pair<unsigned, unsigned>, 4> GapAndRangeSizes;
- const MCSymbol *LastLabel = nullptr;
- for (std::pair<const MCSymbol *, const MCSymbol *> Range : Frag.getRanges()) {
- unsigned GapSize =
- LastLabel ? computeLabelDiff(Layout, LastLabel, Range.first) : 0;
- unsigned RangeSize = computeLabelDiff(Layout, Range.first, Range.second);
- GapAndRangeSizes.push_back({GapSize, RangeSize});
- LastLabel = Range.second;
- }
-
- // Write down each range where the variable is defined.
- for (size_t I = 0, E = Frag.getRanges().size(); I != E;) {
- // If the range size of multiple consecutive ranges is under the max,
- // combine the ranges and emit some gaps.
- const MCSymbol *RangeBegin = Frag.getRanges()[I].first;
- unsigned RangeSize = GapAndRangeSizes[I].second;
- size_t J = I + 1;
- for (; J != E; ++J) {
- unsigned GapAndRangeSize = GapAndRangeSizes[J].first + GapAndRangeSizes[J].second;
- if (RangeSize + GapAndRangeSize > MaxDefRange)
- break;
- RangeSize += GapAndRangeSize;
- }
- unsigned NumGaps = J - I - 1;
-
- support::endian::Writer LEWriter(OS, support::little);
-
- unsigned Bias = 0;
- // We must split the range into chunks of MaxDefRange, this is a fundamental
- // limitation of the file format.
- do {
- uint16_t Chunk = std::min((uint32_t)MaxDefRange, RangeSize);
-
- const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(RangeBegin, Ctx);
- const MCBinaryExpr *BE =
- MCBinaryExpr::createAdd(SRE, MCConstantExpr::create(Bias, Ctx), Ctx);
- MCValue Res;
- BE->evaluateAsRelocatable(Res, &Layout, /*Fixup=*/nullptr);
-
- // Each record begins with a 2-byte number indicating how large the record
- // is.
- StringRef FixedSizePortion = Frag.getFixedSizePortion();
- // Our record is a fixed sized prefix and a LocalVariableAddrRange that we
- // are artificially constructing.
- size_t RecordSize = FixedSizePortion.size() +
- sizeof(LocalVariableAddrRange) + 4 * NumGaps;
- // Write out the record size.
- LEWriter.write<uint16_t>(RecordSize);
- // Write out the fixed size prefix.
- OS << FixedSizePortion;
- // Make space for a fixup that will eventually have a section relative
- // relocation pointing at the offset where the variable becomes live.
- Fixups.push_back(MCFixup::create(Contents.size(), BE, FK_SecRel_4));
- LEWriter.write<uint32_t>(0); // Fixup for code start.
- // Make space for a fixup that will record the section index for the code.
- Fixups.push_back(MCFixup::create(Contents.size(), BE, FK_SecRel_2));
- LEWriter.write<uint16_t>(0); // Fixup for section index.
- // Write down the range's extent.
- LEWriter.write<uint16_t>(Chunk);
-
- // Move on to the next range.
- Bias += Chunk;
- RangeSize -= Chunk;
- } while (RangeSize > 0);
-
- // Emit the gaps afterwards.
- assert((NumGaps == 0 || Bias <= MaxDefRange) &&
- "large ranges should not have gaps");
- unsigned GapStartOffset = GapAndRangeSizes[I].second;
- for (++I; I != J; ++I) {
- unsigned GapSize, RangeSize;
- assert(I < GapAndRangeSizes.size());
- std::tie(GapSize, RangeSize) = GapAndRangeSizes[I];
- LEWriter.write<uint16_t>(GapStartOffset);
- LEWriter.write<uint16_t>(GapSize);
- GapStartOffset += GapSize + RangeSize;
- }
- }
-}
diff --git a/contrib/llvm/lib/MC/MCContext.cpp b/contrib/llvm/lib/MC/MCContext.cpp
deleted file mode 100644
index 6f9efec36361..000000000000
--- a/contrib/llvm/lib/MC/MCContext.cpp
+++ /dev/null
@@ -1,707 +0,0 @@
-//===- lib/MC/MCContext.cpp - Machine Code Context ------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCContext.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/COFF.h"
-#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCCodeView.h"
-#include "llvm/MC/MCDwarf.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCFragment.h"
-#include "llvm/MC/MCLabel.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCSectionCOFF.h"
-#include "llvm/MC/MCSectionELF.h"
-#include "llvm/MC/MCSectionMachO.h"
-#include "llvm/MC/MCSectionWasm.h"
-#include "llvm/MC/MCSectionXCOFF.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCSymbolCOFF.h"
-#include "llvm/MC/MCSymbolELF.h"
-#include "llvm/MC/MCSymbolMachO.h"
-#include "llvm/MC/MCSymbolWasm.h"
-#include "llvm/MC/MCSymbolXCOFF.h"
-#include "llvm/MC/SectionKind.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/Signals.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <cstdlib>
-#include <tuple>
-#include <utility>
-
-using namespace llvm;
-
-static cl::opt<char*>
-AsSecureLogFileName("as-secure-log-file-name",
- cl::desc("As secure log file name (initialized from "
- "AS_SECURE_LOG_FILE env variable)"),
- cl::init(getenv("AS_SECURE_LOG_FILE")), cl::Hidden);
-
-MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri,
- const MCObjectFileInfo *mofi, const SourceMgr *mgr,
- bool DoAutoReset)
- : SrcMgr(mgr), InlineSrcMgr(nullptr), MAI(mai), MRI(mri), MOFI(mofi),
- Symbols(Allocator), UsedNames(Allocator),
- InlineAsmUsedLabelNames(Allocator),
- CurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0),
- AutoReset(DoAutoReset) {
- SecureLogFile = AsSecureLogFileName;
-
- if (SrcMgr && SrcMgr->getNumBuffers())
- MainFileName =
- SrcMgr->getMemoryBuffer(SrcMgr->getMainFileID())->getBufferIdentifier();
-}
-
-MCContext::~MCContext() {
- if (AutoReset)
- reset();
-
- // NOTE: The symbols are all allocated out of a bump pointer allocator,
- // we don't need to free them here.
-}
-
-//===----------------------------------------------------------------------===//
-// Module Lifetime Management
-//===----------------------------------------------------------------------===//
-
-void MCContext::reset() {
- // Call the destructors so the fragments are freed
- COFFAllocator.DestroyAll();
- ELFAllocator.DestroyAll();
- MachOAllocator.DestroyAll();
- XCOFFAllocator.DestroyAll();
-
- MCSubtargetAllocator.DestroyAll();
- InlineAsmUsedLabelNames.clear();
- UsedNames.clear();
- Symbols.clear();
- Allocator.Reset();
- Instances.clear();
- CompilationDir.clear();
- MainFileName.clear();
- MCDwarfLineTablesCUMap.clear();
- SectionsForRanges.clear();
- MCGenDwarfLabelEntries.clear();
- DwarfDebugFlags = StringRef();
- DwarfCompileUnitID = 0;
- CurrentDwarfLoc = MCDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0);
-
- CVContext.reset();
-
- MachOUniquingMap.clear();
- ELFUniquingMap.clear();
- COFFUniquingMap.clear();
- WasmUniquingMap.clear();
- XCOFFUniquingMap.clear();
-
- NextID.clear();
- AllowTemporaryLabels = true;
- DwarfLocSeen = false;
- GenDwarfForAssembly = false;
- GenDwarfFileNumber = 0;
-
- HadError = false;
-}
-
-//===----------------------------------------------------------------------===//
-// Symbol Manipulation
-//===----------------------------------------------------------------------===//
-
-MCSymbol *MCContext::getOrCreateSymbol(const Twine &Name) {
- SmallString<128> NameSV;
- StringRef NameRef = Name.toStringRef(NameSV);
-
- assert(!NameRef.empty() && "Normal symbols cannot be unnamed!");
-
- MCSymbol *&Sym = Symbols[NameRef];
- if (!Sym)
- Sym = createSymbol(NameRef, false, false);
-
- return Sym;
-}
-
-MCSymbol *MCContext::getOrCreateFrameAllocSymbol(StringRef FuncName,
- unsigned Idx) {
- return getOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + FuncName +
- "$frame_escape_" + Twine(Idx));
-}
-
-MCSymbol *MCContext::getOrCreateParentFrameOffsetSymbol(StringRef FuncName) {
- return getOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + FuncName +
- "$parent_frame_offset");
-}
-
-MCSymbol *MCContext::getOrCreateLSDASymbol(StringRef FuncName) {
- return getOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + "__ehtable$" +
- FuncName);
-}
-
-MCSymbol *MCContext::createSymbolImpl(const StringMapEntry<bool> *Name,
- bool IsTemporary) {
- if (MOFI) {
- switch (MOFI->getObjectFileType()) {
- case MCObjectFileInfo::IsCOFF:
- return new (Name, *this) MCSymbolCOFF(Name, IsTemporary);
- case MCObjectFileInfo::IsELF:
- return new (Name, *this) MCSymbolELF(Name, IsTemporary);
- case MCObjectFileInfo::IsMachO:
- return new (Name, *this) MCSymbolMachO(Name, IsTemporary);
- case MCObjectFileInfo::IsWasm:
- return new (Name, *this) MCSymbolWasm(Name, IsTemporary);
- case MCObjectFileInfo::IsXCOFF:
- return new (Name, *this) MCSymbolXCOFF(Name, IsTemporary);
- }
- }
- return new (Name, *this) MCSymbol(MCSymbol::SymbolKindUnset, Name,
- IsTemporary);
-}
-
-MCSymbol *MCContext::createSymbol(StringRef Name, bool AlwaysAddSuffix,
- bool CanBeUnnamed) {
- if (CanBeUnnamed && !UseNamesOnTempLabels)
- return createSymbolImpl(nullptr, true);
-
- // Determine whether this is a user written assembler temporary or normal
- // label, if used.
- bool IsTemporary = CanBeUnnamed;
- if (AllowTemporaryLabels && !IsTemporary)
- IsTemporary = Name.startswith(MAI->getPrivateGlobalPrefix());
-
- SmallString<128> NewName = Name;
- bool AddSuffix = AlwaysAddSuffix;
- unsigned &NextUniqueID = NextID[Name];
- while (true) {
- if (AddSuffix) {
- NewName.resize(Name.size());
- raw_svector_ostream(NewName) << NextUniqueID++;
- }
- auto NameEntry = UsedNames.insert(std::make_pair(NewName, true));
- if (NameEntry.second || !NameEntry.first->second) {
- // Ok, we found a name.
- // Mark it as used for a non-section symbol.
- NameEntry.first->second = true;
- // Have the MCSymbol object itself refer to the copy of the string that is
- // embedded in the UsedNames entry.
- return createSymbolImpl(&*NameEntry.first, IsTemporary);
- }
- assert(IsTemporary && "Cannot rename non-temporary symbols");
- AddSuffix = true;
- }
- llvm_unreachable("Infinite loop");
-}
-
-MCSymbol *MCContext::createTempSymbol(const Twine &Name, bool AlwaysAddSuffix,
- bool CanBeUnnamed) {
- SmallString<128> NameSV;
- raw_svector_ostream(NameSV) << MAI->getPrivateGlobalPrefix() << Name;
- return createSymbol(NameSV, AlwaysAddSuffix, CanBeUnnamed);
-}
-
-MCSymbol *MCContext::createLinkerPrivateTempSymbol() {
- SmallString<128> NameSV;
- raw_svector_ostream(NameSV) << MAI->getLinkerPrivateGlobalPrefix() << "tmp";
- return createSymbol(NameSV, true, false);
-}
-
-MCSymbol *MCContext::createTempSymbol(bool CanBeUnnamed) {
- return createTempSymbol("tmp", true, CanBeUnnamed);
-}
-
-unsigned MCContext::NextInstance(unsigned LocalLabelVal) {
- MCLabel *&Label = Instances[LocalLabelVal];
- if (!Label)
- Label = new (*this) MCLabel(0);
- return Label->incInstance();
-}
-
-unsigned MCContext::GetInstance(unsigned LocalLabelVal) {
- MCLabel *&Label = Instances[LocalLabelVal];
- if (!Label)
- Label = new (*this) MCLabel(0);
- return Label->getInstance();
-}
-
-MCSymbol *MCContext::getOrCreateDirectionalLocalSymbol(unsigned LocalLabelVal,
- unsigned Instance) {
- MCSymbol *&Sym = LocalSymbols[std::make_pair(LocalLabelVal, Instance)];
- if (!Sym)
- Sym = createTempSymbol(false);
- return Sym;
-}
-
-MCSymbol *MCContext::createDirectionalLocalSymbol(unsigned LocalLabelVal) {
- unsigned Instance = NextInstance(LocalLabelVal);
- return getOrCreateDirectionalLocalSymbol(LocalLabelVal, Instance);
-}
-
-MCSymbol *MCContext::getDirectionalLocalSymbol(unsigned LocalLabelVal,
- bool Before) {
- unsigned Instance = GetInstance(LocalLabelVal);
- if (!Before)
- ++Instance;
- return getOrCreateDirectionalLocalSymbol(LocalLabelVal, Instance);
-}
-
-MCSymbol *MCContext::lookupSymbol(const Twine &Name) const {
- SmallString<128> NameSV;
- StringRef NameRef = Name.toStringRef(NameSV);
- return Symbols.lookup(NameRef);
-}
-
-void MCContext::setSymbolValue(MCStreamer &Streamer,
- StringRef Sym,
- uint64_t Val) {
- auto Symbol = getOrCreateSymbol(Sym);
- Streamer.EmitAssignment(Symbol, MCConstantExpr::create(Val, *this));
-}
-
-void MCContext::registerInlineAsmLabel(MCSymbol *Sym) {
- InlineAsmUsedLabelNames[Sym->getName()] = Sym;
-}
-
-//===----------------------------------------------------------------------===//
-// Section Management
-//===----------------------------------------------------------------------===//
-
-MCSectionMachO *MCContext::getMachOSection(StringRef Segment, StringRef Section,
- unsigned TypeAndAttributes,
- unsigned Reserved2, SectionKind Kind,
- const char *BeginSymName) {
- // We unique sections by their segment/section pair. The returned section
- // may not have the same flags as the requested section, if so this should be
- // diagnosed by the client as an error.
-
- // Form the name to look up.
- SmallString<64> Name;
- Name += Segment;
- Name.push_back(',');
- Name += Section;
-
- // Do the lookup, if we have a hit, return it.
- MCSectionMachO *&Entry = MachOUniquingMap[Name];
- if (Entry)
- return Entry;
-
- MCSymbol *Begin = nullptr;
- if (BeginSymName)
- Begin = createTempSymbol(BeginSymName, false);
-
- // Otherwise, return a new section.
- return Entry = new (MachOAllocator.Allocate()) MCSectionMachO(
- Segment, Section, TypeAndAttributes, Reserved2, Kind, Begin);
-}
-
-void MCContext::renameELFSection(MCSectionELF *Section, StringRef Name) {
- StringRef GroupName;
- if (const MCSymbol *Group = Section->getGroup())
- GroupName = Group->getName();
-
- unsigned UniqueID = Section->getUniqueID();
- ELFUniquingMap.erase(
- ELFSectionKey{Section->getSectionName(), GroupName, UniqueID});
- auto I = ELFUniquingMap.insert(std::make_pair(
- ELFSectionKey{Name, GroupName, UniqueID},
- Section))
- .first;
- StringRef CachedName = I->first.SectionName;
- const_cast<MCSectionELF *>(Section)->setSectionName(CachedName);
-}
-
-MCSectionELF *MCContext::createELFSectionImpl(StringRef Section, unsigned Type,
- unsigned Flags, SectionKind K,
- unsigned EntrySize,
- const MCSymbolELF *Group,
- unsigned UniqueID,
- const MCSymbolELF *Associated) {
- MCSymbolELF *R;
- MCSymbol *&Sym = Symbols[Section];
- // A section symbol can not redefine regular symbols. There may be multiple
- // sections with the same name, in which case the first such section wins.
- if (Sym && Sym->isDefined() &&
- (!Sym->isInSection() || Sym->getSection().getBeginSymbol() != Sym))
- reportError(SMLoc(), "invalid symbol redefinition");
- if (Sym && Sym->isUndefined()) {
- R = cast<MCSymbolELF>(Sym);
- } else {
- auto NameIter = UsedNames.insert(std::make_pair(Section, false)).first;
- R = new (&*NameIter, *this) MCSymbolELF(&*NameIter, /*isTemporary*/ false);
- if (!Sym)
- Sym = R;
- }
- R->setBinding(ELF::STB_LOCAL);
- R->setType(ELF::STT_SECTION);
-
- auto *Ret = new (ELFAllocator.Allocate()) MCSectionELF(
- Section, Type, Flags, K, EntrySize, Group, UniqueID, R, Associated);
-
- auto *F = new MCDataFragment();
- Ret->getFragmentList().insert(Ret->begin(), F);
- F->setParent(Ret);
- R->setFragment(F);
-
- return Ret;
-}
-
-MCSectionELF *MCContext::createELFRelSection(const Twine &Name, unsigned Type,
- unsigned Flags, unsigned EntrySize,
- const MCSymbolELF *Group,
- const MCSectionELF *RelInfoSection) {
- StringMap<bool>::iterator I;
- bool Inserted;
- std::tie(I, Inserted) =
- RelSecNames.insert(std::make_pair(Name.str(), true));
-
- return createELFSectionImpl(
- I->getKey(), Type, Flags, SectionKind::getReadOnly(), EntrySize, Group,
- true, cast<MCSymbolELF>(RelInfoSection->getBeginSymbol()));
-}
-
-MCSectionELF *MCContext::getELFNamedSection(const Twine &Prefix,
- const Twine &Suffix, unsigned Type,
- unsigned Flags,
- unsigned EntrySize) {
- return getELFSection(Prefix + "." + Suffix, Type, Flags, EntrySize, Suffix);
-}
-
-MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type,
- unsigned Flags, unsigned EntrySize,
- const Twine &Group, unsigned UniqueID,
- const MCSymbolELF *Associated) {
- MCSymbolELF *GroupSym = nullptr;
- if (!Group.isTriviallyEmpty() && !Group.str().empty())
- GroupSym = cast<MCSymbolELF>(getOrCreateSymbol(Group));
-
- return getELFSection(Section, Type, Flags, EntrySize, GroupSym, UniqueID,
- Associated);
-}
-
-MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type,
- unsigned Flags, unsigned EntrySize,
- const MCSymbolELF *GroupSym,
- unsigned UniqueID,
- const MCSymbolELF *Associated) {
- StringRef Group = "";
- if (GroupSym)
- Group = GroupSym->getName();
- // Do the lookup, if we have a hit, return it.
- auto IterBool = ELFUniquingMap.insert(
- std::make_pair(ELFSectionKey{Section.str(), Group, UniqueID}, nullptr));
- auto &Entry = *IterBool.first;
- if (!IterBool.second)
- return Entry.second;
-
- StringRef CachedName = Entry.first.SectionName;
-
- SectionKind Kind;
- if (Flags & ELF::SHF_ARM_PURECODE)
- Kind = SectionKind::getExecuteOnly();
- else if (Flags & ELF::SHF_EXECINSTR)
- Kind = SectionKind::getText();
- else
- Kind = SectionKind::getReadOnly();
-
- MCSectionELF *Result = createELFSectionImpl(
- CachedName, Type, Flags, Kind, EntrySize, GroupSym, UniqueID, Associated);
- Entry.second = Result;
- return Result;
-}
-
-MCSectionELF *MCContext::createELFGroupSection(const MCSymbolELF *Group) {
- return createELFSectionImpl(".group", ELF::SHT_GROUP, 0,
- SectionKind::getReadOnly(), 4, Group, ~0,
- nullptr);
-}
-
-MCSectionCOFF *MCContext::getCOFFSection(StringRef Section,
- unsigned Characteristics,
- SectionKind Kind,
- StringRef COMDATSymName, int Selection,
- unsigned UniqueID,
- const char *BeginSymName) {
- MCSymbol *COMDATSymbol = nullptr;
- if (!COMDATSymName.empty()) {
- COMDATSymbol = getOrCreateSymbol(COMDATSymName);
- COMDATSymName = COMDATSymbol->getName();
- }
-
-
- // Do the lookup, if we have a hit, return it.
- COFFSectionKey T{Section, COMDATSymName, Selection, UniqueID};
- auto IterBool = COFFUniquingMap.insert(std::make_pair(T, nullptr));
- auto Iter = IterBool.first;
- if (!IterBool.second)
- return Iter->second;
-
- MCSymbol *Begin = nullptr;
- if (BeginSymName)
- Begin = createTempSymbol(BeginSymName, false);
-
- StringRef CachedName = Iter->first.SectionName;
- MCSectionCOFF *Result = new (COFFAllocator.Allocate()) MCSectionCOFF(
- CachedName, Characteristics, COMDATSymbol, Selection, Kind, Begin);
-
- Iter->second = Result;
- return Result;
-}
-
-MCSectionCOFF *MCContext::getCOFFSection(StringRef Section,
- unsigned Characteristics,
- SectionKind Kind,
- const char *BeginSymName) {
- return getCOFFSection(Section, Characteristics, Kind, "", 0, GenericSectionID,
- BeginSymName);
-}
-
-MCSectionCOFF *MCContext::getAssociativeCOFFSection(MCSectionCOFF *Sec,
- const MCSymbol *KeySym,
- unsigned UniqueID) {
- // Return the normal section if we don't have to be associative or unique.
- if (!KeySym && UniqueID == GenericSectionID)
- return Sec;
-
- // If we have a key symbol, make an associative section with the same name and
- // kind as the normal section.
- unsigned Characteristics = Sec->getCharacteristics();
- if (KeySym) {
- Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
- return getCOFFSection(Sec->getSectionName(), Characteristics,
- Sec->getKind(), KeySym->getName(),
- COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, UniqueID);
- }
-
- return getCOFFSection(Sec->getSectionName(), Characteristics, Sec->getKind(),
- "", 0, UniqueID);
-}
-
-MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind K,
- const Twine &Group, unsigned UniqueID,
- const char *BeginSymName) {
- MCSymbolWasm *GroupSym = nullptr;
- if (!Group.isTriviallyEmpty() && !Group.str().empty()) {
- GroupSym = cast<MCSymbolWasm>(getOrCreateSymbol(Group));
- GroupSym->setComdat(true);
- }
-
- return getWasmSection(Section, K, GroupSym, UniqueID, BeginSymName);
-}
-
-MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind Kind,
- const MCSymbolWasm *GroupSym,
- unsigned UniqueID,
- const char *BeginSymName) {
- StringRef Group = "";
- if (GroupSym)
- Group = GroupSym->getName();
- // Do the lookup, if we have a hit, return it.
- auto IterBool = WasmUniquingMap.insert(
- std::make_pair(WasmSectionKey{Section.str(), Group, UniqueID}, nullptr));
- auto &Entry = *IterBool.first;
- if (!IterBool.second)
- return Entry.second;
-
- StringRef CachedName = Entry.first.SectionName;
-
- MCSymbol *Begin = createSymbol(CachedName, false, false);
- cast<MCSymbolWasm>(Begin)->setType(wasm::WASM_SYMBOL_TYPE_SECTION);
-
- MCSectionWasm *Result = new (WasmAllocator.Allocate())
- MCSectionWasm(CachedName, Kind, GroupSym, UniqueID, Begin);
- Entry.second = Result;
-
- auto *F = new MCDataFragment();
- Result->getFragmentList().insert(Result->begin(), F);
- F->setParent(Result);
- Begin->setFragment(F);
-
- return Result;
-}
-
-MCSectionXCOFF *MCContext::getXCOFFSection(StringRef Section,
- XCOFF::StorageMappingClass SMC,
- SectionKind Kind,
- const char *BeginSymName) {
- // Do the lookup. If we have a hit, return it.
- auto IterBool = XCOFFUniquingMap.insert(
- std::make_pair(XCOFFSectionKey{Section.str(), SMC}, nullptr));
- auto &Entry = *IterBool.first;
- if (!IterBool.second)
- return Entry.second;
-
- // Otherwise, return a new section.
- StringRef CachedName = Entry.first.SectionName;
-
- MCSymbol *Begin = nullptr;
- if (BeginSymName)
- Begin = createTempSymbol(BeginSymName, false);
-
- MCSectionXCOFF *Result = new (XCOFFAllocator.Allocate())
- MCSectionXCOFF(CachedName, SMC, Kind, Begin);
- Entry.second = Result;
-
- auto *F = new MCDataFragment();
- Result->getFragmentList().insert(Result->begin(), F);
- F->setParent(Result);
-
- if (Begin)
- Begin->setFragment(F);
-
- return Result;
-}
-
-MCSubtargetInfo &MCContext::getSubtargetCopy(const MCSubtargetInfo &STI) {
- return *new (MCSubtargetAllocator.Allocate()) MCSubtargetInfo(STI);
-}
-
-void MCContext::addDebugPrefixMapEntry(const std::string &From,
- const std::string &To) {
- DebugPrefixMap.insert(std::make_pair(From, To));
-}
-
-void MCContext::RemapDebugPaths() {
- const auto &DebugPrefixMap = this->DebugPrefixMap;
- const auto RemapDebugPath = [&DebugPrefixMap](std::string &Path) {
- for (const auto &Entry : DebugPrefixMap)
- if (StringRef(Path).startswith(Entry.first)) {
- std::string RemappedPath =
- (Twine(Entry.second) + Path.substr(Entry.first.size())).str();
- Path.swap(RemappedPath);
- }
- };
-
- // Remap compilation directory.
- std::string CompDir = CompilationDir.str();
- RemapDebugPath(CompDir);
- CompilationDir = CompDir;
-
- // Remap MCDwarfDirs in all compilation units.
- for (auto &CUIDTablePair : MCDwarfLineTablesCUMap)
- for (auto &Dir : CUIDTablePair.second.getMCDwarfDirs())
- RemapDebugPath(Dir);
-}
-
-//===----------------------------------------------------------------------===//
-// Dwarf Management
-//===----------------------------------------------------------------------===//
-
-void MCContext::setGenDwarfRootFile(StringRef InputFileName, StringRef Buffer) {
- // MCDwarf needs the root file as well as the compilation directory.
- // If we find a '.file 0' directive that will supersede these values.
- Optional<MD5::MD5Result> Cksum;
- if (getDwarfVersion() >= 5) {
- MD5 Hash;
- MD5::MD5Result Sum;
- Hash.update(Buffer);
- Hash.final(Sum);
- Cksum = Sum;
- }
- // Canonicalize the root filename. It cannot be empty, and should not
- // repeat the compilation dir.
- // The MCContext ctor initializes MainFileName to the name associated with
- // the SrcMgr's main file ID, which might be the same as InputFileName (and
- // possibly include directory components).
- // Or, MainFileName might have been overridden by a -main-file-name option,
- // which is supposed to be just a base filename with no directory component.
- // So, if the InputFileName and MainFileName are not equal, assume
- // MainFileName is a substitute basename and replace the last component.
- SmallString<1024> FileNameBuf = InputFileName;
- if (FileNameBuf.empty() || FileNameBuf == "-")
- FileNameBuf = "<stdin>";
- if (!getMainFileName().empty() && FileNameBuf != getMainFileName()) {
- llvm::sys::path::remove_filename(FileNameBuf);
- llvm::sys::path::append(FileNameBuf, getMainFileName());
- }
- StringRef FileName = FileNameBuf;
- if (FileName.consume_front(getCompilationDir()))
- if (llvm::sys::path::is_separator(FileName.front()))
- FileName = FileName.drop_front();
- assert(!FileName.empty());
- setMCLineTableRootFile(
- /*CUID=*/0, getCompilationDir(), FileName, Cksum, None);
-}
-
-/// getDwarfFile - takes a file name and number to place in the dwarf file and
-/// directory tables. If the file number has already been allocated it is an
-/// error and zero is returned and the client reports the error, else the
-/// allocated file number is returned. The file numbers may be in any order.
-Expected<unsigned> MCContext::getDwarfFile(StringRef Directory,
- StringRef FileName,
- unsigned FileNumber,
- Optional<MD5::MD5Result> Checksum,
- Optional<StringRef> Source,
- unsigned CUID) {
- MCDwarfLineTable &Table = MCDwarfLineTablesCUMap[CUID];
- return Table.tryGetFile(Directory, FileName, Checksum, Source, DwarfVersion,
- FileNumber);
-}
-
-/// isValidDwarfFileNumber - takes a dwarf file number and returns true if it
-/// currently is assigned and false otherwise.
-bool MCContext::isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID) {
- const MCDwarfLineTable &LineTable = getMCDwarfLineTable(CUID);
- if (FileNumber == 0)
- return getDwarfVersion() >= 5;
- if (FileNumber >= LineTable.getMCDwarfFiles().size())
- return false;
-
- return !LineTable.getMCDwarfFiles()[FileNumber].Name.empty();
-}
-
-/// Remove empty sections from SectionsForRanges, to avoid generating
-/// useless debug info for them.
-void MCContext::finalizeDwarfSections(MCStreamer &MCOS) {
- SectionsForRanges.remove_if(
- [&](MCSection *Sec) { return !MCOS.mayHaveInstructions(*Sec); });
-}
-
-CodeViewContext &MCContext::getCVContext() {
- if (!CVContext.get())
- CVContext.reset(new CodeViewContext);
- return *CVContext.get();
-}
-
-//===----------------------------------------------------------------------===//
-// Error Reporting
-//===----------------------------------------------------------------------===//
-
-void MCContext::reportError(SMLoc Loc, const Twine &Msg) {
- HadError = true;
-
- // If we have a source manager use it. Otherwise, try using the inline source
- // manager.
- // If that fails, use the generic report_fatal_error().
- if (SrcMgr)
- SrcMgr->PrintMessage(Loc, SourceMgr::DK_Error, Msg);
- else if (InlineSrcMgr)
- InlineSrcMgr->PrintMessage(Loc, SourceMgr::DK_Error, Msg);
- else
- report_fatal_error(Msg, false);
-}
-
-void MCContext::reportFatalError(SMLoc Loc, const Twine &Msg) {
- reportError(Loc, Msg);
-
- // If we reached here, we are failing ungracefully. Run the interrupt handlers
- // to make sure any special cleanups get done, in particular that we remove
- // files registered with RemoveFileOnSignal.
- sys::RunInterruptHandlers();
- exit(1);
-}
diff --git a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp
deleted file mode 100644
index 21bdc2eaea3e..000000000000
--- a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp
+++ /dev/null
@@ -1,343 +0,0 @@
-//===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface ---------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "Disassembler.h"
-#include "llvm-c/Disassembler.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDisassembler/MCDisassembler.h"
-#include "llvm/MC/MCDisassembler/MCRelocationInfo.h"
-#include "llvm/MC/MCDisassembler/MCSymbolizer.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCInstPrinter.h"
-#include "llvm/MC/MCInstrDesc.h"
-#include "llvm/MC/MCInstrInfo.h"
-#include "llvm/MC/MCInstrItineraries.h"
-#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCSchedule.h"
-#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/TargetRegistry.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <cstddef>
-#include <cstring>
-
-using namespace llvm;
-
-// LLVMCreateDisasm() creates a disassembler for the TripleName. Symbolic
-// disassembly is supported by passing a block of information in the DisInfo
-// parameter and specifying the TagType and callback functions as described in
-// the header llvm-c/Disassembler.h . The pointer to the block and the
-// functions can all be passed as NULL. If successful, this returns a
-// disassembler context. If not, it returns NULL.
-//
-LLVMDisasmContextRef
-LLVMCreateDisasmCPUFeatures(const char *TT, const char *CPU,
- const char *Features, void *DisInfo, int TagType,
- LLVMOpInfoCallback GetOpInfo,
- LLVMSymbolLookupCallback SymbolLookUp) {
- // Get the target.
- std::string Error;
- const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error);
- if (!TheTarget)
- return nullptr;
-
- std::unique_ptr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
- if (!MRI)
- return nullptr;
-
- // Get the assembler info needed to setup the MCContext.
- std::unique_ptr<const MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT));
- if (!MAI)
- return nullptr;
-
- std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
- if (!MII)
- return nullptr;
-
- std::unique_ptr<const MCSubtargetInfo> STI(
- TheTarget->createMCSubtargetInfo(TT, CPU, Features));
- if (!STI)
- return nullptr;
-
- // Set up the MCContext for creating symbols and MCExpr's.
- std::unique_ptr<MCContext> Ctx(new MCContext(MAI.get(), MRI.get(), nullptr));
- if (!Ctx)
- return nullptr;
-
- // Set up disassembler.
- std::unique_ptr<MCDisassembler> DisAsm(
- TheTarget->createMCDisassembler(*STI, *Ctx));
- if (!DisAsm)
- return nullptr;
-
- std::unique_ptr<MCRelocationInfo> RelInfo(
- TheTarget->createMCRelocationInfo(TT, *Ctx));
- if (!RelInfo)
- return nullptr;
-
- std::unique_ptr<MCSymbolizer> Symbolizer(TheTarget->createMCSymbolizer(
- TT, GetOpInfo, SymbolLookUp, DisInfo, Ctx.get(), std::move(RelInfo)));
- DisAsm->setSymbolizer(std::move(Symbolizer));
-
- // Set up the instruction printer.
- int AsmPrinterVariant = MAI->getAssemblerDialect();
- std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
- Triple(TT), AsmPrinterVariant, *MAI, *MII, *MRI));
- if (!IP)
- return nullptr;
-
- LLVMDisasmContext *DC = new LLVMDisasmContext(
- TT, DisInfo, TagType, GetOpInfo, SymbolLookUp, TheTarget, std::move(MAI),
- std::move(MRI), std::move(STI), std::move(MII), std::move(Ctx),
- std::move(DisAsm), std::move(IP));
- if (!DC)
- return nullptr;
-
- DC->setCPU(CPU);
- return DC;
-}
-
-LLVMDisasmContextRef
-LLVMCreateDisasmCPU(const char *TT, const char *CPU, void *DisInfo, int TagType,
- LLVMOpInfoCallback GetOpInfo,
- LLVMSymbolLookupCallback SymbolLookUp) {
- return LLVMCreateDisasmCPUFeatures(TT, CPU, "", DisInfo, TagType, GetOpInfo,
- SymbolLookUp);
-}
-
-LLVMDisasmContextRef LLVMCreateDisasm(const char *TT, void *DisInfo,
- int TagType, LLVMOpInfoCallback GetOpInfo,
- LLVMSymbolLookupCallback SymbolLookUp) {
- return LLVMCreateDisasmCPUFeatures(TT, "", "", DisInfo, TagType, GetOpInfo,
- SymbolLookUp);
-}
-
-//
-// LLVMDisasmDispose() disposes of the disassembler specified by the context.
-//
-void LLVMDisasmDispose(LLVMDisasmContextRef DCR){
- LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR);
- delete DC;
-}
-
-/// Emits the comments that are stored in \p DC comment stream.
-/// Each comment in the comment stream must end with a newline.
-static void emitComments(LLVMDisasmContext *DC,
- formatted_raw_ostream &FormattedOS) {
- // Flush the stream before taking its content.
- StringRef Comments = DC->CommentsToEmit.str();
- // Get the default information for printing a comment.
- const MCAsmInfo *MAI = DC->getAsmInfo();
- StringRef CommentBegin = MAI->getCommentString();
- unsigned CommentColumn = MAI->getCommentColumn();
- bool IsFirst = true;
- while (!Comments.empty()) {
- if (!IsFirst)
- FormattedOS << '\n';
- // Emit a line of comments.
- FormattedOS.PadToColumn(CommentColumn);
- size_t Position = Comments.find('\n');
- FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
- // Move after the newline character.
- Comments = Comments.substr(Position+1);
- IsFirst = false;
- }
- FormattedOS.flush();
-
- // Tell the comment stream that the vector changed underneath it.
- DC->CommentsToEmit.clear();
-}
-
-/// Gets latency information for \p Inst from the itinerary
-/// scheduling model, based on \p DC information.
-/// \return The maximum expected latency over all the operands or -1
-/// if no information is available.
-static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
- const int NoInformationAvailable = -1;
-
- // Check if we have a CPU to get the itinerary information.
- if (DC->getCPU().empty())
- return NoInformationAvailable;
-
- // Get itinerary information.
- const MCSubtargetInfo *STI = DC->getSubtargetInfo();
- InstrItineraryData IID = STI->getInstrItineraryForCPU(DC->getCPU());
- // Get the scheduling class of the requested instruction.
- const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
- unsigned SCClass = Desc.getSchedClass();
-
- int Latency = 0;
- for (unsigned OpIdx = 0, OpIdxEnd = Inst.getNumOperands(); OpIdx != OpIdxEnd;
- ++OpIdx)
- Latency = std::max(Latency, IID.getOperandCycle(SCClass, OpIdx));
-
- return Latency;
-}
-
-/// Gets latency information for \p Inst, based on \p DC information.
-/// \return The maximum expected latency over all the definitions or -1
-/// if no information is available.
-static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
- // Try to compute scheduling information.
- const MCSubtargetInfo *STI = DC->getSubtargetInfo();
- const MCSchedModel SCModel = STI->getSchedModel();
- const int NoInformationAvailable = -1;
-
- // Check if we have a scheduling model for instructions.
- if (!SCModel.hasInstrSchedModel())
- // Try to fall back to the itinerary model if the scheduling model doesn't
- // have a scheduling table. Note the default does not have a table.
- return getItineraryLatency(DC, Inst);
-
- // Get the scheduling class of the requested instruction.
- const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
- unsigned SCClass = Desc.getSchedClass();
- const MCSchedClassDesc *SCDesc = SCModel.getSchedClassDesc(SCClass);
- // Resolving the variant SchedClass requires an MI to pass to
- // SubTargetInfo::resolveSchedClass.
- if (!SCDesc || !SCDesc->isValid() || SCDesc->isVariant())
- return NoInformationAvailable;
-
- // Compute output latency.
- int16_t Latency = 0;
- for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries;
- DefIdx != DefEnd; ++DefIdx) {
- // Lookup the definition's write latency in SubtargetInfo.
- const MCWriteLatencyEntry *WLEntry = STI->getWriteLatencyEntry(SCDesc,
- DefIdx);
- Latency = std::max(Latency, WLEntry->Cycles);
- }
-
- return Latency;
-}
-
-/// Emits latency information in DC->CommentStream for \p Inst, based
-/// on the information available in \p DC.
-static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
- int Latency = getLatency(DC, Inst);
-
- // Report only interesting latencies.
- if (Latency < 2)
- return;
-
- DC->CommentStream << "Latency: " << Latency << '\n';
-}
-
-//
-// LLVMDisasmInstruction() disassembles a single instruction using the
-// disassembler context specified in the parameter DC. The bytes of the
-// instruction are specified in the parameter Bytes, and contains at least
-// BytesSize number of bytes. The instruction is at the address specified by
-// the PC parameter. If a valid instruction can be disassembled its string is
-// returned indirectly in OutString which whos size is specified in the
-// parameter OutStringSize. This function returns the number of bytes in the
-// instruction or zero if there was no valid instruction. If this function
-// returns zero the caller will have to pick how many bytes they want to step
-// over by printing a .byte, .long etc. to continue.
-//
-size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes,
- uint64_t BytesSize, uint64_t PC, char *OutString,
- size_t OutStringSize){
- LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR);
- // Wrap the pointer to the Bytes, BytesSize and PC in a MemoryObject.
- ArrayRef<uint8_t> Data(Bytes, BytesSize);
-
- uint64_t Size;
- MCInst Inst;
- const MCDisassembler *DisAsm = DC->getDisAsm();
- MCInstPrinter *IP = DC->getIP();
- MCDisassembler::DecodeStatus S;
- SmallVector<char, 64> InsnStr;
- raw_svector_ostream Annotations(InsnStr);
- S = DisAsm->getInstruction(Inst, Size, Data, PC,
- /*REMOVE*/ nulls(), Annotations);
- switch (S) {
- case MCDisassembler::Fail:
- case MCDisassembler::SoftFail:
- // FIXME: Do something different for soft failure modes?
- return 0;
-
- case MCDisassembler::Success: {
- StringRef AnnotationsStr = Annotations.str();
-
- SmallVector<char, 64> InsnStr;
- raw_svector_ostream OS(InsnStr);
- formatted_raw_ostream FormattedOS(OS);
- IP->printInst(&Inst, FormattedOS, AnnotationsStr, *DC->getSubtargetInfo());
-
- if (DC->getOptions() & LLVMDisassembler_Option_PrintLatency)
- emitLatency(DC, Inst);
-
- emitComments(DC, FormattedOS);
-
- assert(OutStringSize != 0 && "Output buffer cannot be zero size");
- size_t OutputSize = std::min(OutStringSize-1, InsnStr.size());
- std::memcpy(OutString, InsnStr.data(), OutputSize);
- OutString[OutputSize] = '\0'; // Terminate string.
-
- return Size;
- }
- }
- llvm_unreachable("Invalid DecodeStatus!");
-}
-
-//
-// LLVMSetDisasmOptions() sets the disassembler's options. It returns 1 if it
-// can set all the Options and 0 otherwise.
-//
-int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){
- if (Options & LLVMDisassembler_Option_UseMarkup){
- LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR);
- MCInstPrinter *IP = DC->getIP();
- IP->setUseMarkup(true);
- DC->addOptions(LLVMDisassembler_Option_UseMarkup);
- Options &= ~LLVMDisassembler_Option_UseMarkup;
- }
- if (Options & LLVMDisassembler_Option_PrintImmHex){
- LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR);
- MCInstPrinter *IP = DC->getIP();
- IP->setPrintImmHex(true);
- DC->addOptions(LLVMDisassembler_Option_PrintImmHex);
- Options &= ~LLVMDisassembler_Option_PrintImmHex;
- }
- if (Options & LLVMDisassembler_Option_AsmPrinterVariant){
- LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR);
- // Try to set up the new instruction printer.
- const MCAsmInfo *MAI = DC->getAsmInfo();
- const MCInstrInfo *MII = DC->getInstrInfo();
- const MCRegisterInfo *MRI = DC->getRegisterInfo();
- int AsmPrinterVariant = MAI->getAssemblerDialect();
- AsmPrinterVariant = AsmPrinterVariant == 0 ? 1 : 0;
- MCInstPrinter *IP = DC->getTarget()->createMCInstPrinter(
- Triple(DC->getTripleName()), AsmPrinterVariant, *MAI, *MII, *MRI);
- if (IP) {
- DC->setIP(IP);
- DC->addOptions(LLVMDisassembler_Option_AsmPrinterVariant);
- Options &= ~LLVMDisassembler_Option_AsmPrinterVariant;
- }
- }
- if (Options & LLVMDisassembler_Option_SetInstrComments) {
- LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR);
- MCInstPrinter *IP = DC->getIP();
- IP->setCommentStream(DC->CommentStream);
- DC->addOptions(LLVMDisassembler_Option_SetInstrComments);
- Options &= ~LLVMDisassembler_Option_SetInstrComments;
- }
- if (Options & LLVMDisassembler_Option_PrintLatency) {
- LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR);
- DC->addOptions(LLVMDisassembler_Option_PrintLatency);
- Options &= ~LLVMDisassembler_Option_PrintLatency;
- }
- return (Options == 0);
-}
diff --git a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h
deleted file mode 100644
index e5aab53a7613..000000000000
--- a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h
+++ /dev/null
@@ -1,124 +0,0 @@
-//===------------- Disassembler.h - LLVM Disassembler -----------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the interface for the Disassembly library's disassembler
-// context. The disassembler is responsible for producing strings for
-// individual instructions according to a given architecture and disassembly
-// syntax.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LIB_MC_MCDISASSEMBLER_DISASSEMBLER_H
-#define LLVM_LIB_MC_MCDISASSEMBLER_DISASSEMBLER_H
-
-#include "llvm-c/Disassembler.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDisassembler/MCDisassembler.h"
-#include "llvm/MC/MCInstPrinter.h"
-#include "llvm/MC/MCInstrInfo.h"
-#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Support/raw_ostream.h"
-#include <string>
-#include <utility>
-
-namespace llvm {
-class Target;
-
-//
-// This is the disassembler context returned by LLVMCreateDisasm().
-//
-class LLVMDisasmContext {
-private:
- //
- // The passed parameters when the disassembler context is created.
- //
- // The TripleName for this disassembler.
- std::string TripleName;
- // The pointer to the caller's block of symbolic information.
- void *DisInfo;
- // The Triple specific symbolic information type returned by GetOpInfo.
- int TagType;
- // The function to get the symbolic information for operands.
- LLVMOpInfoCallback GetOpInfo;
- // The function to look up a symbol name.
- LLVMSymbolLookupCallback SymbolLookUp;
- //
- // The objects created and saved by LLVMCreateDisasm() then used by
- // LLVMDisasmInstruction().
- //
- // The LLVM target corresponding to the disassembler.
- // FIXME: using std::unique_ptr<const llvm::Target> causes a malloc error
- // when this LLVMDisasmContext is deleted.
- const Target *TheTarget;
- // The assembly information for the target architecture.
- std::unique_ptr<const llvm::MCAsmInfo> MAI;
- // The register information for the target architecture.
- std::unique_ptr<const llvm::MCRegisterInfo> MRI;
- // The subtarget information for the target architecture.
- std::unique_ptr<const llvm::MCSubtargetInfo> MSI;
- // The instruction information for the target architecture.
- std::unique_ptr<const llvm::MCInstrInfo> MII;
- // The assembly context for creating symbols and MCExprs.
- std::unique_ptr<const llvm::MCContext> Ctx;
- // The disassembler for the target architecture.
- std::unique_ptr<const llvm::MCDisassembler> DisAsm;
- // The instruction printer for the target architecture.
- std::unique_ptr<llvm::MCInstPrinter> IP;
- // The options used to set up the disassembler.
- uint64_t Options;
- // The CPU string.
- std::string CPU;
-
-public:
- // Comment stream and backing vector.
- SmallString<128> CommentsToEmit;
- raw_svector_ostream CommentStream;
-
- LLVMDisasmContext(std::string TripleName, void *DisInfo, int TagType,
- LLVMOpInfoCallback GetOpInfo,
- LLVMSymbolLookupCallback SymbolLookUp,
- const Target *TheTarget,
- std::unique_ptr<const MCAsmInfo> &&MAI,
- std::unique_ptr<const MCRegisterInfo> &&MRI,
- std::unique_ptr<const MCSubtargetInfo> &&MSI,
- std::unique_ptr<const MCInstrInfo> &&MII,
- std::unique_ptr<const llvm::MCContext> &&Ctx,
- std::unique_ptr<const MCDisassembler> &&DisAsm,
- std::unique_ptr<MCInstPrinter> &&IP)
- : TripleName(std::move(TripleName)), DisInfo(DisInfo), TagType(TagType),
- GetOpInfo(GetOpInfo), SymbolLookUp(SymbolLookUp), TheTarget(TheTarget),
- MAI(std::move(MAI)), MRI(std::move(MRI)), MSI(std::move(MSI)),
- MII(std::move(MII)), Ctx(std::move(Ctx)), DisAsm(std::move(DisAsm)),
- IP(std::move(IP)), Options(0), CommentStream(CommentsToEmit) {}
- const std::string &getTripleName() const { return TripleName; }
- void *getDisInfo() const { return DisInfo; }
- int getTagType() const { return TagType; }
- LLVMOpInfoCallback getGetOpInfo() const { return GetOpInfo; }
- LLVMSymbolLookupCallback getSymbolLookupCallback() const {
- return SymbolLookUp;
- }
- const Target *getTarget() const { return TheTarget; }
- const MCDisassembler *getDisAsm() const { return DisAsm.get(); }
- const MCAsmInfo *getAsmInfo() const { return MAI.get(); }
- const MCInstrInfo *getInstrInfo() const { return MII.get(); }
- const MCRegisterInfo *getRegisterInfo() const { return MRI.get(); }
- const MCSubtargetInfo *getSubtargetInfo() const { return MSI.get(); }
- MCInstPrinter *getIP() { return IP.get(); }
- void setIP(MCInstPrinter *NewIP) { IP.reset(NewIP); }
- uint64_t getOptions() const { return Options; }
- void addOptions(uint64_t Options) { this->Options |= Options; }
- StringRef getCPU() const { return CPU; }
- void setCPU(const char *CPU) { this->CPU = CPU; }
-};
-
-} // namespace llvm
-
-#endif
diff --git a/contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp b/contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp
deleted file mode 100644
index 063f7e706024..000000000000
--- a/contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-//===- MCDisassembler.cpp - Disassembler interface ------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCDisassembler/MCDisassembler.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-
-using namespace llvm;
-
-MCDisassembler::~MCDisassembler() = default;
-
-MCDisassembler::DecodeStatus MCDisassembler::onSymbolStart(
- StringRef Name, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address,
- raw_ostream &VStream, raw_ostream &CStream) const {
- Size = 0;
- return MCDisassembler::Success;
-}
-
-bool MCDisassembler::tryAddingSymbolicOperand(MCInst &Inst, int64_t Value,
- uint64_t Address, bool IsBranch,
- uint64_t Offset,
- uint64_t InstSize) const {
- raw_ostream &cStream = CommentStream ? *CommentStream : nulls();
- if (Symbolizer)
- return Symbolizer->tryAddingSymbolicOperand(Inst, cStream, Value, Address,
- IsBranch, Offset, InstSize);
- return false;
-}
-
-void MCDisassembler::tryAddingPcLoadReferenceComment(int64_t Value,
- uint64_t Address) const {
- raw_ostream &cStream = CommentStream ? *CommentStream : nulls();
- if (Symbolizer)
- Symbolizer->tryAddingPcLoadReferenceComment(cStream, Value, Address);
-}
-
-void MCDisassembler::setSymbolizer(std::unique_ptr<MCSymbolizer> Symzer) {
- Symbolizer = std::move(Symzer);
-}
diff --git a/contrib/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp b/contrib/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp
deleted file mode 100644
index 7befef86303c..000000000000
--- a/contrib/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-//===-- MCExternalSymbolizer.cpp - External symbolizer --------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCDisassembler/MCExternalSymbolizer.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cstring>
-
-using namespace llvm;
-
-namespace llvm {
-class Triple;
-}
-
-// This function tries to add a symbolic operand in place of the immediate
-// Value in the MCInst. The immediate Value has had any PC adjustment made by
-// the caller. If the instruction is a branch instruction then IsBranch is true,
-// else false. If the getOpInfo() function was set as part of the
-// setupForSymbolicDisassembly() call then that function is called to get any
-// symbolic information at the Address for this instruction. If that returns
-// non-zero then the symbolic information it returns is used to create an MCExpr
-// and that is added as an operand to the MCInst. If getOpInfo() returns zero
-// and IsBranch is true then a symbol look up for Value is done and if a symbol
-// is found an MCExpr is created with that, else an MCExpr with Value is
-// created. This function returns true if it adds an operand to the MCInst and
-// false otherwise.
-bool MCExternalSymbolizer::tryAddingSymbolicOperand(MCInst &MI,
- raw_ostream &cStream,
- int64_t Value,
- uint64_t Address,
- bool IsBranch,
- uint64_t Offset,
- uint64_t InstSize) {
- struct LLVMOpInfo1 SymbolicOp;
- std::memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1));
- SymbolicOp.Value = Value;
-
- if (!GetOpInfo ||
- !GetOpInfo(DisInfo, Address, Offset, InstSize, 1, &SymbolicOp)) {
- // Clear SymbolicOp.Value from above and also all other fields.
- std::memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1));
-
- // At this point, GetOpInfo() did not find any relocation information about
- // this operand and we are left to use the SymbolLookUp() call back to guess
- // if the Value is the address of a symbol. In the case this is a branch
- // that always makes sense to guess. But in the case of an immediate it is
- // a bit more questionable if it is an address of a symbol or some other
- // reference. So if the immediate Value comes from a width of 1 byte,
- // InstSize, we will not guess it is an address of a symbol. Because in
- // object files assembled starting at address 0 this usually leads to
- // incorrect symbolication.
- if (!SymbolLookUp || (InstSize == 1 && !IsBranch))
- return false;
-
- uint64_t ReferenceType;
- if (IsBranch)
- ReferenceType = LLVMDisassembler_ReferenceType_In_Branch;
- else
- ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
- const char *ReferenceName;
- const char *Name = SymbolLookUp(DisInfo, Value, &ReferenceType, Address,
- &ReferenceName);
- if (Name) {
- SymbolicOp.AddSymbol.Name = Name;
- SymbolicOp.AddSymbol.Present = true;
- // If Name is a C++ symbol name put the human readable name in a comment.
- if(ReferenceType == LLVMDisassembler_ReferenceType_DeMangled_Name)
- cStream << ReferenceName;
- }
- // For branches always create an MCExpr so it gets printed as hex address.
- else if (IsBranch) {
- SymbolicOp.Value = Value;
- }
- if(ReferenceType == LLVMDisassembler_ReferenceType_Out_SymbolStub)
- cStream << "symbol stub for: " << ReferenceName;
- else if(ReferenceType == LLVMDisassembler_ReferenceType_Out_Objc_Message)
- cStream << "Objc message: " << ReferenceName;
- if (!Name && !IsBranch)
- return false;
- }
-
- const MCExpr *Add = nullptr;
- if (SymbolicOp.AddSymbol.Present) {
- if (SymbolicOp.AddSymbol.Name) {
- StringRef Name(SymbolicOp.AddSymbol.Name);
- MCSymbol *Sym = Ctx.getOrCreateSymbol(Name);
- Add = MCSymbolRefExpr::create(Sym, Ctx);
- } else {
- Add = MCConstantExpr::create((int)SymbolicOp.AddSymbol.Value, Ctx);
- }
- }
-
- const MCExpr *Sub = nullptr;
- if (SymbolicOp.SubtractSymbol.Present) {
- if (SymbolicOp.SubtractSymbol.Name) {
- StringRef Name(SymbolicOp.SubtractSymbol.Name);
- MCSymbol *Sym = Ctx.getOrCreateSymbol(Name);
- Sub = MCSymbolRefExpr::create(Sym, Ctx);
- } else {
- Sub = MCConstantExpr::create((int)SymbolicOp.SubtractSymbol.Value, Ctx);
- }
- }
-
- const MCExpr *Off = nullptr;
- if (SymbolicOp.Value != 0)
- Off = MCConstantExpr::create(SymbolicOp.Value, Ctx);
-
- const MCExpr *Expr;
- if (Sub) {
- const MCExpr *LHS;
- if (Add)
- LHS = MCBinaryExpr::createSub(Add, Sub, Ctx);
- else
- LHS = MCUnaryExpr::createMinus(Sub, Ctx);
- if (Off)
- Expr = MCBinaryExpr::createAdd(LHS, Off, Ctx);
- else
- Expr = LHS;
- } else if (Add) {
- if (Off)
- Expr = MCBinaryExpr::createAdd(Add, Off, Ctx);
- else
- Expr = Add;
- } else {
- if (Off)
- Expr = Off;
- else
- Expr = MCConstantExpr::create(0, Ctx);
- }
-
- Expr = RelInfo->createExprForCAPIVariantKind(Expr, SymbolicOp.VariantKind);
- if (!Expr)
- return false;
-
- MI.addOperand(MCOperand::createExpr(Expr));
- return true;
-}
-
-// This function tries to add a comment as to what is being referenced by a load
-// instruction with the base register that is the Pc. These can often be values
-// in a literal pool near the Address of the instruction. The Address of the
-// instruction and its immediate Value are used as a possible literal pool entry.
-// The SymbolLookUp call back will return the name of a symbol referenced by the
-// literal pool's entry if the referenced address is that of a symbol. Or it
-// will return a pointer to a literal 'C' string if the referenced address of
-// the literal pool's entry is an address into a section with C string literals.
-// Or if the reference is to an Objective-C data structure it will return a
-// specific reference type for it and a string.
-void MCExternalSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream,
- int64_t Value,
- uint64_t Address) {
- if (SymbolLookUp) {
- uint64_t ReferenceType = LLVMDisassembler_ReferenceType_In_PCrel_Load;
- const char *ReferenceName;
- (void)SymbolLookUp(DisInfo, Value, &ReferenceType, Address, &ReferenceName);
- if(ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr)
- cStream << "literal pool symbol address: " << ReferenceName;
- else if(ReferenceType ==
- LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr) {
- cStream << "literal pool for: \"";
- cStream.write_escaped(ReferenceName);
- cStream << "\"";
- }
- else if(ReferenceType ==
- LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref)
- cStream << "Objc cfstring ref: @\"" << ReferenceName << "\"";
- else if(ReferenceType ==
- LLVMDisassembler_ReferenceType_Out_Objc_Message)
- cStream << "Objc message: " << ReferenceName;
- else if(ReferenceType ==
- LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref)
- cStream << "Objc message ref: " << ReferenceName;
- else if(ReferenceType ==
- LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref)
- cStream << "Objc selector ref: " << ReferenceName;
- else if(ReferenceType ==
- LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref)
- cStream << "Objc class ref: " << ReferenceName;
- }
-}
-
-namespace llvm {
-MCSymbolizer *createMCSymbolizer(const Triple &TT, LLVMOpInfoCallback GetOpInfo,
- LLVMSymbolLookupCallback SymbolLookUp,
- void *DisInfo, MCContext *Ctx,
- std::unique_ptr<MCRelocationInfo> &&RelInfo) {
- assert(Ctx && "No MCContext given for symbolic disassembly");
-
- return new MCExternalSymbolizer(*Ctx, std::move(RelInfo), GetOpInfo,
- SymbolLookUp, DisInfo);
-}
-}
diff --git a/contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp b/contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp
deleted file mode 100644
index 64e216e0051d..000000000000
--- a/contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-//===-- MCRelocationInfo.cpp ----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCDisassembler/MCRelocationInfo.h"
-#include "llvm-c/Disassembler.h"
-#include "llvm/Support/TargetRegistry.h"
-
-using namespace llvm;
-
-MCRelocationInfo::MCRelocationInfo(MCContext &Ctx) : Ctx(Ctx) {}
-
-MCRelocationInfo::~MCRelocationInfo() = default;
-
-const MCExpr *
-MCRelocationInfo::createExprForCAPIVariantKind(const MCExpr *SubExpr,
- unsigned VariantKind) {
- if (VariantKind != LLVMDisassembler_VariantKind_None)
- return nullptr;
- return SubExpr;
-}
-
-MCRelocationInfo *llvm::createMCRelocationInfo(const Triple &TT,
- MCContext &Ctx) {
- return new MCRelocationInfo(Ctx);
-}
diff --git a/contrib/llvm/lib/MC/MCDisassembler/MCSymbolizer.cpp b/contrib/llvm/lib/MC/MCDisassembler/MCSymbolizer.cpp
deleted file mode 100644
index 8214a196afb1..000000000000
--- a/contrib/llvm/lib/MC/MCDisassembler/MCSymbolizer.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-//===-- llvm/MC/MCSymbolizer.cpp - MCSymbolizer class ---------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCDisassembler/MCSymbolizer.h"
-
-using namespace llvm;
-
-MCSymbolizer::~MCSymbolizer() = default;
diff --git a/contrib/llvm/lib/MC/MCDwarf.cpp b/contrib/llvm/lib/MC/MCDwarf.cpp
deleted file mode 100644
index 8456b3421bcd..000000000000
--- a/contrib/llvm/lib/MC/MCDwarf.cpp
+++ /dev/null
@@ -1,1950 +0,0 @@
-//===- lib/MC/MCDwarf.cpp - MCDwarf implementation ------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCDwarf.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/Dwarf.h"
-#include "llvm/Config/config.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCObjectStreamer.h"
-#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/StringTableBuilder.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/EndianStream.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/LEB128.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <cstdint>
-#include <string>
-#include <utility>
-#include <vector>
-
-using namespace llvm;
-
-/// Manage the .debug_line_str section contents, if we use it.
-class llvm::MCDwarfLineStr {
- MCSymbol *LineStrLabel = nullptr;
- StringTableBuilder LineStrings{StringTableBuilder::DWARF};
- bool UseRelocs = false;
-
-public:
- /// Construct an instance that can emit .debug_line_str (for use in a normal
- /// v5 line table).
- explicit MCDwarfLineStr(MCContext &Ctx) {
- UseRelocs = Ctx.getAsmInfo()->doesDwarfUseRelocationsAcrossSections();
- if (UseRelocs)
- LineStrLabel =
- Ctx.getObjectFileInfo()->getDwarfLineStrSection()->getBeginSymbol();
- }
-
- /// Emit a reference to the string.
- void emitRef(MCStreamer *MCOS, StringRef Path);
-
- /// Emit the .debug_line_str section if appropriate.
- void emitSection(MCStreamer *MCOS);
-};
-
-static inline uint64_t ScaleAddrDelta(MCContext &Context, uint64_t AddrDelta) {
- unsigned MinInsnLength = Context.getAsmInfo()->getMinInstAlignment();
- if (MinInsnLength == 1)
- return AddrDelta;
- if (AddrDelta % MinInsnLength != 0) {
- // TODO: report this error, but really only once.
- ;
- }
- return AddrDelta / MinInsnLength;
-}
-
-//
-// This is called when an instruction is assembled into the specified section
-// and if there is information from the last .loc directive that has yet to have
-// a line entry made for it is made.
-//
-void MCDwarfLineEntry::Make(MCObjectStreamer *MCOS, MCSection *Section) {
- if (!MCOS->getContext().getDwarfLocSeen())
- return;
-
- // Create a symbol at in the current section for use in the line entry.
- MCSymbol *LineSym = MCOS->getContext().createTempSymbol();
- // Set the value of the symbol to use for the MCDwarfLineEntry.
- MCOS->EmitLabel(LineSym);
-
- // Get the current .loc info saved in the context.
- const MCDwarfLoc &DwarfLoc = MCOS->getContext().getCurrentDwarfLoc();
-
- // Create a (local) line entry with the symbol and the current .loc info.
- MCDwarfLineEntry LineEntry(LineSym, DwarfLoc);
-
- // clear DwarfLocSeen saying the current .loc info is now used.
- MCOS->getContext().clearDwarfLocSeen();
-
- // Add the line entry to this section's entries.
- MCOS->getContext()
- .getMCDwarfLineTable(MCOS->getContext().getDwarfCompileUnitID())
- .getMCLineSections()
- .addLineEntry(LineEntry, Section);
-}
-
-//
-// This helper routine returns an expression of End - Start + IntVal .
-//
-static inline const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS,
- const MCSymbol &Start,
- const MCSymbol &End,
- int IntVal) {
- MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
- const MCExpr *Res =
- MCSymbolRefExpr::create(&End, Variant, MCOS.getContext());
- const MCExpr *RHS =
- MCSymbolRefExpr::create(&Start, Variant, MCOS.getContext());
- const MCExpr *Res1 =
- MCBinaryExpr::create(MCBinaryExpr::Sub, Res, RHS, MCOS.getContext());
- const MCExpr *Res2 =
- MCConstantExpr::create(IntVal, MCOS.getContext());
- const MCExpr *Res3 =
- MCBinaryExpr::create(MCBinaryExpr::Sub, Res1, Res2, MCOS.getContext());
- return Res3;
-}
-
-//
-// This helper routine returns an expression of Start + IntVal .
-//
-static inline const MCExpr *
-makeStartPlusIntExpr(MCContext &Ctx, const MCSymbol &Start, int IntVal) {
- MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
- const MCExpr *LHS = MCSymbolRefExpr::create(&Start, Variant, Ctx);
- const MCExpr *RHS = MCConstantExpr::create(IntVal, Ctx);
- const MCExpr *Res = MCBinaryExpr::create(MCBinaryExpr::Add, LHS, RHS, Ctx);
- return Res;
-}
-
-//
-// This emits the Dwarf line table for the specified section from the entries
-// in the LineSection.
-//
-static inline void
-EmitDwarfLineTable(MCObjectStreamer *MCOS, MCSection *Section,
- const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
- unsigned FileNum = 1;
- unsigned LastLine = 1;
- unsigned Column = 0;
- unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
- unsigned Isa = 0;
- unsigned Discriminator = 0;
- MCSymbol *LastLabel = nullptr;
-
- // Loop through each MCDwarfLineEntry and encode the dwarf line number table.
- for (const MCDwarfLineEntry &LineEntry : LineEntries) {
- int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;
-
- if (FileNum != LineEntry.getFileNum()) {
- FileNum = LineEntry.getFileNum();
- MCOS->EmitIntValue(dwarf::DW_LNS_set_file, 1);
- MCOS->EmitULEB128IntValue(FileNum);
- }
- if (Column != LineEntry.getColumn()) {
- Column = LineEntry.getColumn();
- MCOS->EmitIntValue(dwarf::DW_LNS_set_column, 1);
- MCOS->EmitULEB128IntValue(Column);
- }
- if (Discriminator != LineEntry.getDiscriminator() &&
- MCOS->getContext().getDwarfVersion() >= 4) {
- Discriminator = LineEntry.getDiscriminator();
- unsigned Size = getULEB128Size(Discriminator);
- MCOS->EmitIntValue(dwarf::DW_LNS_extended_op, 1);
- MCOS->EmitULEB128IntValue(Size + 1);
- MCOS->EmitIntValue(dwarf::DW_LNE_set_discriminator, 1);
- MCOS->EmitULEB128IntValue(Discriminator);
- }
- if (Isa != LineEntry.getIsa()) {
- Isa = LineEntry.getIsa();
- MCOS->EmitIntValue(dwarf::DW_LNS_set_isa, 1);
- MCOS->EmitULEB128IntValue(Isa);
- }
- if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
- Flags = LineEntry.getFlags();
- MCOS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1);
- }
- if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)
- MCOS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1);
- if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)
- MCOS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1);
- if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
- MCOS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1);
-
- MCSymbol *Label = LineEntry.getLabel();
-
- // At this point we want to emit/create the sequence to encode the delta in
- // line numbers and the increment of the address from the previous Label
- // and the current Label.
- const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo();
- MCOS->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
- asmInfo->getCodePointerSize());
-
- Discriminator = 0;
- LastLine = LineEntry.getLine();
- LastLabel = Label;
- }
-
- // Emit a DW_LNE_end_sequence for the end of the section.
- // Use the section end label to compute the address delta and use INT64_MAX
- // as the line delta which is the signal that this is actually a
- // DW_LNE_end_sequence.
- MCSymbol *SectionEnd = MCOS->endSection(Section);
-
- // Switch back the dwarf line section, in case endSection had to switch the
- // section.
- MCContext &Ctx = MCOS->getContext();
- MCOS->SwitchSection(Ctx.getObjectFileInfo()->getDwarfLineSection());
-
- const MCAsmInfo *AsmInfo = Ctx.getAsmInfo();
- MCOS->EmitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd,
- AsmInfo->getCodePointerSize());
-}
-
-//
-// This emits the Dwarf file and the line tables.
-//
-void MCDwarfLineTable::Emit(MCObjectStreamer *MCOS,
- MCDwarfLineTableParams Params) {
- MCContext &context = MCOS->getContext();
-
- auto &LineTables = context.getMCDwarfLineTables();
-
- // Bail out early so we don't switch to the debug_line section needlessly and
- // in doing so create an unnecessary (if empty) section.
- if (LineTables.empty())
- return;
-
- // In a v5 non-split line table, put the strings in a separate section.
- Optional<MCDwarfLineStr> LineStr;
- if (context.getDwarfVersion() >= 5)
- LineStr = MCDwarfLineStr(context);
-
- // Switch to the section where the table will be emitted into.
- MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection());
-
- // Handle the rest of the Compile Units.
- for (const auto &CUIDTablePair : LineTables) {
- CUIDTablePair.second.EmitCU(MCOS, Params, LineStr);
- }
-
- if (LineStr)
- LineStr->emitSection(MCOS);
-}
-
-void MCDwarfDwoLineTable::Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params,
- MCSection *Section) const {
- if (!HasSplitLineTable)
- return;
- Optional<MCDwarfLineStr> NoLineStr(None);
- MCOS.SwitchSection(Section);
- MCOS.EmitLabel(Header.Emit(&MCOS, Params, None, NoLineStr).second);
-}
-
-std::pair<MCSymbol *, MCSymbol *>
-MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
- Optional<MCDwarfLineStr> &LineStr) const {
- static const char StandardOpcodeLengths[] = {
- 0, // length of DW_LNS_copy
- 1, // length of DW_LNS_advance_pc
- 1, // length of DW_LNS_advance_line
- 1, // length of DW_LNS_set_file
- 1, // length of DW_LNS_set_column
- 0, // length of DW_LNS_negate_stmt
- 0, // length of DW_LNS_set_basic_block
- 0, // length of DW_LNS_const_add_pc
- 1, // length of DW_LNS_fixed_advance_pc
- 0, // length of DW_LNS_set_prologue_end
- 0, // length of DW_LNS_set_epilogue_begin
- 1 // DW_LNS_set_isa
- };
- assert(array_lengthof(StandardOpcodeLengths) >=
- (Params.DWARF2LineOpcodeBase - 1U));
- return Emit(
- MCOS, Params,
- makeArrayRef(StandardOpcodeLengths, Params.DWARF2LineOpcodeBase - 1),
- LineStr);
-}
-
-static const MCExpr *forceExpAbs(MCStreamer &OS, const MCExpr* Expr) {
- MCContext &Context = OS.getContext();
- assert(!isa<MCSymbolRefExpr>(Expr));
- if (Context.getAsmInfo()->hasAggressiveSymbolFolding())
- return Expr;
-
- MCSymbol *ABS = Context.createTempSymbol();
- OS.EmitAssignment(ABS, Expr);
- return MCSymbolRefExpr::create(ABS, Context);
-}
-
-static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size) {
- const MCExpr *ABS = forceExpAbs(OS, Value);
- OS.EmitValue(ABS, Size);
-}
-
-void MCDwarfLineStr::emitSection(MCStreamer *MCOS) {
- // Switch to the .debug_line_str section.
- MCOS->SwitchSection(
- MCOS->getContext().getObjectFileInfo()->getDwarfLineStrSection());
- // Emit the strings without perturbing the offsets we used.
- LineStrings.finalizeInOrder();
- SmallString<0> Data;
- Data.resize(LineStrings.getSize());
- LineStrings.write((uint8_t *)Data.data());
- MCOS->EmitBinaryData(Data.str());
-}
-
-void MCDwarfLineStr::emitRef(MCStreamer *MCOS, StringRef Path) {
- int RefSize = 4; // FIXME: Support DWARF-64
- size_t Offset = LineStrings.add(Path);
- if (UseRelocs) {
- MCContext &Ctx = MCOS->getContext();
- MCOS->EmitValue(makeStartPlusIntExpr(Ctx, *LineStrLabel, Offset), RefSize);
- } else
- MCOS->EmitIntValue(Offset, RefSize);
-}
-
-void MCDwarfLineTableHeader::emitV2FileDirTables(MCStreamer *MCOS) const {
- // First the directory table.
- for (auto &Dir : MCDwarfDirs) {
- MCOS->EmitBytes(Dir); // The DirectoryName, and...
- MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
- }
- MCOS->EmitIntValue(0, 1); // Terminate the directory list.
-
- // Second the file table.
- for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
- assert(!MCDwarfFiles[i].Name.empty());
- MCOS->EmitBytes(MCDwarfFiles[i].Name); // FileName and...
- MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
- MCOS->EmitULEB128IntValue(MCDwarfFiles[i].DirIndex); // Directory number.
- MCOS->EmitIntValue(0, 1); // Last modification timestamp (always 0).
- MCOS->EmitIntValue(0, 1); // File size (always 0).
- }
- MCOS->EmitIntValue(0, 1); // Terminate the file list.
-}
-
-static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile,
- bool EmitMD5, bool HasSource,
- Optional<MCDwarfLineStr> &LineStr) {
- assert(!DwarfFile.Name.empty());
- if (LineStr)
- LineStr->emitRef(MCOS, DwarfFile.Name);
- else {
- MCOS->EmitBytes(DwarfFile.Name); // FileName and...
- MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
- }
- MCOS->EmitULEB128IntValue(DwarfFile.DirIndex); // Directory number.
- if (EmitMD5) {
- const MD5::MD5Result &Cksum = *DwarfFile.Checksum;
- MCOS->EmitBinaryData(
- StringRef(reinterpret_cast<const char *>(Cksum.Bytes.data()),
- Cksum.Bytes.size()));
- }
- if (HasSource) {
- if (LineStr)
- LineStr->emitRef(MCOS, DwarfFile.Source.getValueOr(StringRef()));
- else {
- MCOS->EmitBytes(
- DwarfFile.Source.getValueOr(StringRef())); // Source and...
- MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
- }
- }
-}
-
-void MCDwarfLineTableHeader::emitV5FileDirTables(
- MCStreamer *MCOS, Optional<MCDwarfLineStr> &LineStr) const {
- // The directory format, which is just a list of the directory paths. In a
- // non-split object, these are references to .debug_line_str; in a split
- // object, they are inline strings.
- MCOS->EmitIntValue(1, 1);
- MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path);
- MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
- : dwarf::DW_FORM_string);
- MCOS->EmitULEB128IntValue(MCDwarfDirs.size() + 1);
- // Try not to emit an empty compilation directory.
- const StringRef CompDir = CompilationDir.empty()
- ? MCOS->getContext().getCompilationDir()
- : StringRef(CompilationDir);
- if (LineStr) {
- // Record path strings, emit references here.
- LineStr->emitRef(MCOS, CompDir);
- for (const auto &Dir : MCDwarfDirs)
- LineStr->emitRef(MCOS, Dir);
- } else {
- // The list of directory paths. Compilation directory comes first.
- MCOS->EmitBytes(CompDir);
- MCOS->EmitBytes(StringRef("\0", 1));
- for (const auto &Dir : MCDwarfDirs) {
- MCOS->EmitBytes(Dir); // The DirectoryName, and...
- MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
- }
- }
-
- // The file format, which is the inline null-terminated filename and a
- // directory index. We don't track file size/timestamp so don't emit them
- // in the v5 table. Emit MD5 checksums and source if we have them.
- uint64_t Entries = 2;
- if (HasAllMD5)
- Entries += 1;
- if (HasSource)
- Entries += 1;
- MCOS->EmitIntValue(Entries, 1);
- MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path);
- MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
- : dwarf::DW_FORM_string);
- MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_directory_index);
- MCOS->EmitULEB128IntValue(dwarf::DW_FORM_udata);
- if (HasAllMD5) {
- MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_MD5);
- MCOS->EmitULEB128IntValue(dwarf::DW_FORM_data16);
- }
- if (HasSource) {
- MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_LLVM_source);
- MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
- : dwarf::DW_FORM_string);
- }
- // Then the counted list of files. The root file is file #0, then emit the
- // files as provide by .file directives.
- // MCDwarfFiles has an unused element [0] so use size() not size()+1.
- // But sometimes MCDwarfFiles is empty, in which case we still emit one file.
- MCOS->EmitULEB128IntValue(MCDwarfFiles.empty() ? 1 : MCDwarfFiles.size());
- // To accommodate assembler source written for DWARF v4 but trying to emit
- // v5: If we didn't see a root file explicitly, replicate file #1.
- assert((!RootFile.Name.empty() || MCDwarfFiles.size() >= 1) &&
- "No root file and no .file directives");
- emitOneV5FileEntry(MCOS, RootFile.Name.empty() ? MCDwarfFiles[1] : RootFile,
- HasAllMD5, HasSource, LineStr);
- for (unsigned i = 1; i < MCDwarfFiles.size(); ++i)
- emitOneV5FileEntry(MCOS, MCDwarfFiles[i], HasAllMD5, HasSource, LineStr);
-}
-
-std::pair<MCSymbol *, MCSymbol *>
-MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
- ArrayRef<char> StandardOpcodeLengths,
- Optional<MCDwarfLineStr> &LineStr) const {
- MCContext &context = MCOS->getContext();
-
- // Create a symbol at the beginning of the line table.
- MCSymbol *LineStartSym = Label;
- if (!LineStartSym)
- LineStartSym = context.createTempSymbol();
- // Set the value of the symbol, as we are at the start of the line table.
- MCOS->EmitLabel(LineStartSym);
-
- // Create a symbol for the end of the section (to be set when we get there).
- MCSymbol *LineEndSym = context.createTempSymbol();
-
- // The first 4 bytes is the total length of the information for this
- // compilation unit (not including these 4 bytes for the length).
- emitAbsValue(*MCOS,
- MakeStartMinusEndExpr(*MCOS, *LineStartSym, *LineEndSym, 4), 4);
-
- // Next 2 bytes is the Version.
- unsigned LineTableVersion = context.getDwarfVersion();
- MCOS->EmitIntValue(LineTableVersion, 2);
-
- // Keep track of the bytes between the very start and where the header length
- // comes out.
- unsigned PreHeaderLengthBytes = 4 + 2;
-
- // In v5, we get address info next.
- if (LineTableVersion >= 5) {
- MCOS->EmitIntValue(context.getAsmInfo()->getCodePointerSize(), 1);
- MCOS->EmitIntValue(0, 1); // Segment selector; same as EmitGenDwarfAranges.
- PreHeaderLengthBytes += 2;
- }
-
- // Create a symbol for the end of the prologue (to be set when we get there).
- MCSymbol *ProEndSym = context.createTempSymbol(); // Lprologue_end
-
- // Length of the prologue, is the next 4 bytes. This is actually the length
- // from after the length word, to the end of the prologue.
- emitAbsValue(*MCOS,
- MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym,
- (PreHeaderLengthBytes + 4)),
- 4);
-
- // Parameters of the state machine, are next.
- MCOS->EmitIntValue(context.getAsmInfo()->getMinInstAlignment(), 1);
- // maximum_operations_per_instruction
- // For non-VLIW architectures this field is always 1.
- // FIXME: VLIW architectures need to update this field accordingly.
- if (LineTableVersion >= 4)
- MCOS->EmitIntValue(1, 1);
- MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1);
- MCOS->EmitIntValue(Params.DWARF2LineBase, 1);
- MCOS->EmitIntValue(Params.DWARF2LineRange, 1);
- MCOS->EmitIntValue(StandardOpcodeLengths.size() + 1, 1);
-
- // Standard opcode lengths
- for (char Length : StandardOpcodeLengths)
- MCOS->EmitIntValue(Length, 1);
-
- // Put out the directory and file tables. The formats vary depending on
- // the version.
- if (LineTableVersion >= 5)
- emitV5FileDirTables(MCOS, LineStr);
- else
- emitV2FileDirTables(MCOS);
-
- // This is the end of the prologue, so set the value of the symbol at the
- // end of the prologue (that was used in a previous expression).
- MCOS->EmitLabel(ProEndSym);
-
- return std::make_pair(LineStartSym, LineEndSym);
-}
-
-void MCDwarfLineTable::EmitCU(MCObjectStreamer *MCOS,
- MCDwarfLineTableParams Params,
- Optional<MCDwarfLineStr> &LineStr) const {
- MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;
-
- // Put out the line tables.
- for (const auto &LineSec : MCLineSections.getMCLineEntries())
- EmitDwarfLineTable(MCOS, LineSec.first, LineSec.second);
-
- // This is the end of the section, so set the value of the symbol at the end
- // of this section (that was used in a previous expression).
- MCOS->EmitLabel(LineEndSym);
-}
-
-Expected<unsigned> MCDwarfLineTable::tryGetFile(StringRef &Directory,
- StringRef &FileName,
- Optional<MD5::MD5Result> Checksum,
- Optional<StringRef> Source,
- uint16_t DwarfVersion,
- unsigned FileNumber) {
- return Header.tryGetFile(Directory, FileName, Checksum, Source, DwarfVersion,
- FileNumber);
-}
-
-bool isRootFile(const MCDwarfFile &RootFile, StringRef &Directory,
- StringRef &FileName, Optional<MD5::MD5Result> Checksum) {
- if (RootFile.Name.empty() || RootFile.Name != FileName.data())
- return false;
- return RootFile.Checksum == Checksum;
-}
-
-Expected<unsigned>
-MCDwarfLineTableHeader::tryGetFile(StringRef &Directory,
- StringRef &FileName,
- Optional<MD5::MD5Result> Checksum,
- Optional<StringRef> Source,
- uint16_t DwarfVersion,
- unsigned FileNumber) {
- if (Directory == CompilationDir)
- Directory = "";
- if (FileName.empty()) {
- FileName = "<stdin>";
- Directory = "";
- }
- assert(!FileName.empty());
- // Keep track of whether any or all files have an MD5 checksum.
- // If any files have embedded source, they all must.
- if (MCDwarfFiles.empty()) {
- trackMD5Usage(Checksum.hasValue());
- HasSource = (Source != None);
- }
- if (isRootFile(RootFile, Directory, FileName, Checksum) && DwarfVersion >= 5)
- return 0;
- if (FileNumber == 0) {
- // File numbers start with 1 and/or after any file numbers
- // allocated by inline-assembler .file directives.
- FileNumber = MCDwarfFiles.empty() ? 1 : MCDwarfFiles.size();
- SmallString<256> Buffer;
- auto IterBool = SourceIdMap.insert(
- std::make_pair((Directory + Twine('\0') + FileName).toStringRef(Buffer),
- FileNumber));
- if (!IterBool.second)
- return IterBool.first->second;
- }
- // Make space for this FileNumber in the MCDwarfFiles vector if needed.
- if (FileNumber >= MCDwarfFiles.size())
- MCDwarfFiles.resize(FileNumber + 1);
-
- // Get the new MCDwarfFile slot for this FileNumber.
- MCDwarfFile &File = MCDwarfFiles[FileNumber];
-
- // It is an error to see the same number more than once.
- if (!File.Name.empty())
- return make_error<StringError>("file number already allocated",
- inconvertibleErrorCode());
-
- // If any files have embedded source, they all must.
- if (HasSource != (Source != None))
- return make_error<StringError>("inconsistent use of embedded source",
- inconvertibleErrorCode());
-
- if (Directory.empty()) {
- // Separate the directory part from the basename of the FileName.
- StringRef tFileName = sys::path::filename(FileName);
- if (!tFileName.empty()) {
- Directory = sys::path::parent_path(FileName);
- if (!Directory.empty())
- FileName = tFileName;
- }
- }
-
- // Find or make an entry in the MCDwarfDirs vector for this Directory.
- // Capture directory name.
- unsigned DirIndex;
- if (Directory.empty()) {
- // For FileNames with no directories a DirIndex of 0 is used.
- DirIndex = 0;
- } else {
- DirIndex = llvm::find(MCDwarfDirs, Directory) - MCDwarfDirs.begin();
- if (DirIndex >= MCDwarfDirs.size())
- MCDwarfDirs.push_back(Directory);
- // The DirIndex is one based, as DirIndex of 0 is used for FileNames with
- // no directories. MCDwarfDirs[] is unlike MCDwarfFiles[] in that the
- // directory names are stored at MCDwarfDirs[DirIndex-1] where FileNames
- // are stored at MCDwarfFiles[FileNumber].Name .
- DirIndex++;
- }
-
- File.Name = FileName;
- File.DirIndex = DirIndex;
- File.Checksum = Checksum;
- trackMD5Usage(Checksum.hasValue());
- File.Source = Source;
- if (Source)
- HasSource = true;
-
- // return the allocated FileNumber.
- return FileNumber;
-}
-
-/// Utility function to emit the encoding to a streamer.
-void MCDwarfLineAddr::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
- int64_t LineDelta, uint64_t AddrDelta) {
- MCContext &Context = MCOS->getContext();
- SmallString<256> Tmp;
- raw_svector_ostream OS(Tmp);
- MCDwarfLineAddr::Encode(Context, Params, LineDelta, AddrDelta, OS);
- MCOS->EmitBytes(OS.str());
-}
-
-/// Given a special op, return the address skip amount (in units of
-/// DWARF2_LINE_MIN_INSN_LENGTH).
-static uint64_t SpecialAddr(MCDwarfLineTableParams Params, uint64_t op) {
- return (op - Params.DWARF2LineOpcodeBase) / Params.DWARF2LineRange;
-}
-
-/// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.
-void MCDwarfLineAddr::Encode(MCContext &Context, MCDwarfLineTableParams Params,
- int64_t LineDelta, uint64_t AddrDelta,
- raw_ostream &OS) {
- uint64_t Temp, Opcode;
- bool NeedCopy = false;
-
- // The maximum address skip amount that can be encoded with a special op.
- uint64_t MaxSpecialAddrDelta = SpecialAddr(Params, 255);
-
- // Scale the address delta by the minimum instruction length.
- AddrDelta = ScaleAddrDelta(Context, AddrDelta);
-
- // A LineDelta of INT64_MAX is a signal that this is actually a
- // DW_LNE_end_sequence. We cannot use special opcodes here, since we want the
- // end_sequence to emit the matrix entry.
- if (LineDelta == INT64_MAX) {
- if (AddrDelta == MaxSpecialAddrDelta)
- OS << char(dwarf::DW_LNS_const_add_pc);
- else if (AddrDelta) {
- OS << char(dwarf::DW_LNS_advance_pc);
- encodeULEB128(AddrDelta, OS);
- }
- OS << char(dwarf::DW_LNS_extended_op);
- OS << char(1);
- OS << char(dwarf::DW_LNE_end_sequence);
- return;
- }
-
- // Bias the line delta by the base.
- Temp = LineDelta - Params.DWARF2LineBase;
-
- // If the line increment is out of range of a special opcode, we must encode
- // it with DW_LNS_advance_line.
- if (Temp >= Params.DWARF2LineRange ||
- Temp + Params.DWARF2LineOpcodeBase > 255) {
- OS << char(dwarf::DW_LNS_advance_line);
- encodeSLEB128(LineDelta, OS);
-
- LineDelta = 0;
- Temp = 0 - Params.DWARF2LineBase;
- NeedCopy = true;
- }
-
- // Use DW_LNS_copy instead of a "line +0, addr +0" special opcode.
- if (LineDelta == 0 && AddrDelta == 0) {
- OS << char(dwarf::DW_LNS_copy);
- return;
- }
-
- // Bias the opcode by the special opcode base.
- Temp += Params.DWARF2LineOpcodeBase;
-
- // Avoid overflow when addr_delta is large.
- if (AddrDelta < 256 + MaxSpecialAddrDelta) {
- // Try using a special opcode.
- Opcode = Temp + AddrDelta * Params.DWARF2LineRange;
- if (Opcode <= 255) {
- OS << char(Opcode);
- return;
- }
-
- // Try using DW_LNS_const_add_pc followed by special op.
- Opcode = Temp + (AddrDelta - MaxSpecialAddrDelta) * Params.DWARF2LineRange;
- if (Opcode <= 255) {
- OS << char(dwarf::DW_LNS_const_add_pc);
- OS << char(Opcode);
- return;
- }
- }
-
- // Otherwise use DW_LNS_advance_pc.
- OS << char(dwarf::DW_LNS_advance_pc);
- encodeULEB128(AddrDelta, OS);
-
- if (NeedCopy)
- OS << char(dwarf::DW_LNS_copy);
- else {
- assert(Temp <= 255 && "Buggy special opcode encoding.");
- OS << char(Temp);
- }
-}
-
-bool MCDwarfLineAddr::FixedEncode(MCContext &Context,
- MCDwarfLineTableParams Params,
- int64_t LineDelta, uint64_t AddrDelta,
- raw_ostream &OS,
- uint32_t *Offset, uint32_t *Size) {
- if (LineDelta != INT64_MAX) {
- OS << char(dwarf::DW_LNS_advance_line);
- encodeSLEB128(LineDelta, OS);
- }
-
- // Use address delta to adjust address or use absolute address to adjust
- // address.
- bool SetDelta;
- // According to DWARF spec., the DW_LNS_fixed_advance_pc opcode takes a
- // single uhalf (unencoded) operand. So, the maximum value of AddrDelta
- // is 65535. We set a conservative upper bound for it for relaxation.
- if (AddrDelta > 60000) {
- const MCAsmInfo *asmInfo = Context.getAsmInfo();
- unsigned AddrSize = asmInfo->getCodePointerSize();
-
- OS << char(dwarf::DW_LNS_extended_op);
- encodeULEB128(1 + AddrSize, OS);
- OS << char(dwarf::DW_LNE_set_address);
- // Generate fixup for the address.
- *Offset = OS.tell();
- *Size = AddrSize;
- SetDelta = false;
- OS.write_zeros(AddrSize);
- } else {
- OS << char(dwarf::DW_LNS_fixed_advance_pc);
- // Generate fixup for 2-bytes address delta.
- *Offset = OS.tell();
- *Size = 2;
- SetDelta = true;
- OS << char(0);
- OS << char(0);
- }
-
- if (LineDelta == INT64_MAX) {
- OS << char(dwarf::DW_LNS_extended_op);
- OS << char(1);
- OS << char(dwarf::DW_LNE_end_sequence);
- } else {
- OS << char(dwarf::DW_LNS_copy);
- }
-
- return SetDelta;
-}
-
-// Utility function to write a tuple for .debug_abbrev.
-static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) {
- MCOS->EmitULEB128IntValue(Name);
- MCOS->EmitULEB128IntValue(Form);
-}
-
-// When generating dwarf for assembly source files this emits
-// the data for .debug_abbrev section which contains three DIEs.
-static void EmitGenDwarfAbbrev(MCStreamer *MCOS) {
- MCContext &context = MCOS->getContext();
- MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
-
- // DW_TAG_compile_unit DIE abbrev (1).
- MCOS->EmitULEB128IntValue(1);
- MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit);
- MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1);
- EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, context.getDwarfVersion() >= 4
- ? dwarf::DW_FORM_sec_offset
- : dwarf::DW_FORM_data4);
- if (context.getGenDwarfSectionSyms().size() > 1 &&
- context.getDwarfVersion() >= 3) {
- EmitAbbrev(MCOS, dwarf::DW_AT_ranges, context.getDwarfVersion() >= 4
- ? dwarf::DW_FORM_sec_offset
- : dwarf::DW_FORM_data4);
- } else {
- EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
- EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr);
- }
- EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
- if (!context.getCompilationDir().empty())
- EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string);
- StringRef DwarfDebugFlags = context.getDwarfDebugFlags();
- if (!DwarfDebugFlags.empty())
- EmitAbbrev(MCOS, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string);
- EmitAbbrev(MCOS, dwarf::DW_AT_producer, dwarf::DW_FORM_string);
- EmitAbbrev(MCOS, dwarf::DW_AT_language, dwarf::DW_FORM_data2);
- EmitAbbrev(MCOS, 0, 0);
-
- // DW_TAG_label DIE abbrev (2).
- MCOS->EmitULEB128IntValue(2);
- MCOS->EmitULEB128IntValue(dwarf::DW_TAG_label);
- MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1);
- EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
- EmitAbbrev(MCOS, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data4);
- EmitAbbrev(MCOS, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data4);
- EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
- EmitAbbrev(MCOS, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag);
- EmitAbbrev(MCOS, 0, 0);
-
- // DW_TAG_unspecified_parameters DIE abbrev (3).
- MCOS->EmitULEB128IntValue(3);
- MCOS->EmitULEB128IntValue(dwarf::DW_TAG_unspecified_parameters);
- MCOS->EmitIntValue(dwarf::DW_CHILDREN_no, 1);
- EmitAbbrev(MCOS, 0, 0);
-
- // Terminate the abbreviations for this compilation unit.
- MCOS->EmitIntValue(0, 1);
-}
-
-// When generating dwarf for assembly source files this emits the data for
-// .debug_aranges section. This section contains a header and a table of pairs
-// of PointerSize'ed values for the address and size of section(s) with line
-// table entries.
-static void EmitGenDwarfAranges(MCStreamer *MCOS,
- const MCSymbol *InfoSectionSymbol) {
- MCContext &context = MCOS->getContext();
-
- auto &Sections = context.getGenDwarfSectionSyms();
-
- MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
-
- // This will be the length of the .debug_aranges section, first account for
- // the size of each item in the header (see below where we emit these items).
- int Length = 4 + 2 + 4 + 1 + 1;
-
- // Figure the padding after the header before the table of address and size
- // pairs who's values are PointerSize'ed.
- const MCAsmInfo *asmInfo = context.getAsmInfo();
- int AddrSize = asmInfo->getCodePointerSize();
- int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1));
- if (Pad == 2 * AddrSize)
- Pad = 0;
- Length += Pad;
-
- // Add the size of the pair of PointerSize'ed values for the address and size
- // of each section we have in the table.
- Length += 2 * AddrSize * Sections.size();
- // And the pair of terminating zeros.
- Length += 2 * AddrSize;
-
- // Emit the header for this section.
- // The 4 byte length not including the 4 byte value for the length.
- MCOS->EmitIntValue(Length - 4, 4);
- // The 2 byte version, which is 2.
- MCOS->EmitIntValue(2, 2);
- // The 4 byte offset to the compile unit in the .debug_info from the start
- // of the .debug_info.
- if (InfoSectionSymbol)
- MCOS->EmitSymbolValue(InfoSectionSymbol, 4,
- asmInfo->needsDwarfSectionOffsetDirective());
- else
- MCOS->EmitIntValue(0, 4);
- // The 1 byte size of an address.
- MCOS->EmitIntValue(AddrSize, 1);
- // The 1 byte size of a segment descriptor, we use a value of zero.
- MCOS->EmitIntValue(0, 1);
- // Align the header with the padding if needed, before we put out the table.
- for(int i = 0; i < Pad; i++)
- MCOS->EmitIntValue(0, 1);
-
- // Now emit the table of pairs of PointerSize'ed values for the section
- // addresses and sizes.
- for (MCSection *Sec : Sections) {
- const MCSymbol *StartSymbol = Sec->getBeginSymbol();
- MCSymbol *EndSymbol = Sec->getEndSymbol(context);
- assert(StartSymbol && "StartSymbol must not be NULL");
- assert(EndSymbol && "EndSymbol must not be NULL");
-
- const MCExpr *Addr = MCSymbolRefExpr::create(
- StartSymbol, MCSymbolRefExpr::VK_None, context);
- const MCExpr *Size = MakeStartMinusEndExpr(*MCOS,
- *StartSymbol, *EndSymbol, 0);
- MCOS->EmitValue(Addr, AddrSize);
- emitAbsValue(*MCOS, Size, AddrSize);
- }
-
- // And finally the pair of terminating zeros.
- MCOS->EmitIntValue(0, AddrSize);
- MCOS->EmitIntValue(0, AddrSize);
-}
-
-// When generating dwarf for assembly source files this emits the data for
-// .debug_info section which contains three parts. The header, the compile_unit
-// DIE and a list of label DIEs.
-static void EmitGenDwarfInfo(MCStreamer *MCOS,
- const MCSymbol *AbbrevSectionSymbol,
- const MCSymbol *LineSectionSymbol,
- const MCSymbol *RangesSectionSymbol) {
- MCContext &context = MCOS->getContext();
-
- MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
-
- // Create a symbol at the start and end of this section used in here for the
- // expression to calculate the length in the header.
- MCSymbol *InfoStart = context.createTempSymbol();
- MCOS->EmitLabel(InfoStart);
- MCSymbol *InfoEnd = context.createTempSymbol();
-
- // First part: the header.
-
- // The 4 byte total length of the information for this compilation unit, not
- // including these 4 bytes.
- const MCExpr *Length = MakeStartMinusEndExpr(*MCOS, *InfoStart, *InfoEnd, 4);
- emitAbsValue(*MCOS, Length, 4);
-
- // The 2 byte DWARF version.
- MCOS->EmitIntValue(context.getDwarfVersion(), 2);
-
- // The DWARF v5 header has unit type, address size, abbrev offset.
- // Earlier versions have abbrev offset, address size.
- const MCAsmInfo &AsmInfo = *context.getAsmInfo();
- int AddrSize = AsmInfo.getCodePointerSize();
- if (context.getDwarfVersion() >= 5) {
- MCOS->EmitIntValue(dwarf::DW_UT_compile, 1);
- MCOS->EmitIntValue(AddrSize, 1);
- }
- // The 4 byte offset to the debug abbrevs from the start of the .debug_abbrev,
- // it is at the start of that section so this is zero.
- if (AbbrevSectionSymbol == nullptr)
- MCOS->EmitIntValue(0, 4);
- else
- MCOS->EmitSymbolValue(AbbrevSectionSymbol, 4,
- AsmInfo.needsDwarfSectionOffsetDirective());
- if (context.getDwarfVersion() <= 4)
- MCOS->EmitIntValue(AddrSize, 1);
-
- // Second part: the compile_unit DIE.
-
- // The DW_TAG_compile_unit DIE abbrev (1).
- MCOS->EmitULEB128IntValue(1);
-
- // DW_AT_stmt_list, a 4 byte offset from the start of the .debug_line section,
- // which is at the start of that section so this is zero.
- if (LineSectionSymbol)
- MCOS->EmitSymbolValue(LineSectionSymbol, 4,
- AsmInfo.needsDwarfSectionOffsetDirective());
- else
- MCOS->EmitIntValue(0, 4);
-
- if (RangesSectionSymbol) {
- // There are multiple sections containing code, so we must use the
- // .debug_ranges sections.
-
- // AT_ranges, the 4 byte offset from the start of the .debug_ranges section
- // to the address range list for this compilation unit.
- MCOS->EmitSymbolValue(RangesSectionSymbol, 4);
- } else {
- // If we only have one non-empty code section, we can use the simpler
- // AT_low_pc and AT_high_pc attributes.
-
- // Find the first (and only) non-empty text section
- auto &Sections = context.getGenDwarfSectionSyms();
- const auto TextSection = Sections.begin();
- assert(TextSection != Sections.end() && "No text section found");
-
- MCSymbol *StartSymbol = (*TextSection)->getBeginSymbol();
- MCSymbol *EndSymbol = (*TextSection)->getEndSymbol(context);
- assert(StartSymbol && "StartSymbol must not be NULL");
- assert(EndSymbol && "EndSymbol must not be NULL");
-
- // AT_low_pc, the first address of the default .text section.
- const MCExpr *Start = MCSymbolRefExpr::create(
- StartSymbol, MCSymbolRefExpr::VK_None, context);
- MCOS->EmitValue(Start, AddrSize);
-
- // AT_high_pc, the last address of the default .text section.
- const MCExpr *End = MCSymbolRefExpr::create(
- EndSymbol, MCSymbolRefExpr::VK_None, context);
- MCOS->EmitValue(End, AddrSize);
- }
-
- // AT_name, the name of the source file. Reconstruct from the first directory
- // and file table entries.
- const SmallVectorImpl<std::string> &MCDwarfDirs = context.getMCDwarfDirs();
- if (MCDwarfDirs.size() > 0) {
- MCOS->EmitBytes(MCDwarfDirs[0]);
- MCOS->EmitBytes(sys::path::get_separator());
- }
- const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles = context.getMCDwarfFiles();
- // MCDwarfFiles might be empty if we have an empty source file.
- // If it's not empty, [0] is unused and [1] is the first actual file.
- assert(MCDwarfFiles.empty() || MCDwarfFiles.size() >= 2);
- const MCDwarfFile &RootFile =
- MCDwarfFiles.empty()
- ? context.getMCDwarfLineTable(/*CUID=*/0).getRootFile()
- : MCDwarfFiles[1];
- MCOS->EmitBytes(RootFile.Name);
- MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
-
- // AT_comp_dir, the working directory the assembly was done in.
- if (!context.getCompilationDir().empty()) {
- MCOS->EmitBytes(context.getCompilationDir());
- MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
- }
-
- // AT_APPLE_flags, the command line arguments of the assembler tool.
- StringRef DwarfDebugFlags = context.getDwarfDebugFlags();
- if (!DwarfDebugFlags.empty()){
- MCOS->EmitBytes(DwarfDebugFlags);
- MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
- }
-
- // AT_producer, the version of the assembler tool.
- StringRef DwarfDebugProducer = context.getDwarfDebugProducer();
- if (!DwarfDebugProducer.empty())
- MCOS->EmitBytes(DwarfDebugProducer);
- else
- MCOS->EmitBytes(StringRef("llvm-mc (based on LLVM " PACKAGE_VERSION ")"));
- MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
-
- // AT_language, a 4 byte value. We use DW_LANG_Mips_Assembler as the dwarf2
- // draft has no standard code for assembler.
- MCOS->EmitIntValue(dwarf::DW_LANG_Mips_Assembler, 2);
-
- // Third part: the list of label DIEs.
-
- // Loop on saved info for dwarf labels and create the DIEs for them.
- const std::vector<MCGenDwarfLabelEntry> &Entries =
- MCOS->getContext().getMCGenDwarfLabelEntries();
- for (const auto &Entry : Entries) {
- // The DW_TAG_label DIE abbrev (2).
- MCOS->EmitULEB128IntValue(2);
-
- // AT_name, of the label without any leading underbar.
- MCOS->EmitBytes(Entry.getName());
- MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
-
- // AT_decl_file, index into the file table.
- MCOS->EmitIntValue(Entry.getFileNumber(), 4);
-
- // AT_decl_line, source line number.
- MCOS->EmitIntValue(Entry.getLineNumber(), 4);
-
- // AT_low_pc, start address of the label.
- const MCExpr *AT_low_pc = MCSymbolRefExpr::create(Entry.getLabel(),
- MCSymbolRefExpr::VK_None, context);
- MCOS->EmitValue(AT_low_pc, AddrSize);
-
- // DW_AT_prototyped, a one byte flag value of 0 saying we have no prototype.
- MCOS->EmitIntValue(0, 1);
-
- // The DW_TAG_unspecified_parameters DIE abbrev (3).
- MCOS->EmitULEB128IntValue(3);
-
- // Add the NULL DIE terminating the DW_TAG_unspecified_parameters DIE's.
- MCOS->EmitIntValue(0, 1);
- }
-
- // Add the NULL DIE terminating the Compile Unit DIE's.
- MCOS->EmitIntValue(0, 1);
-
- // Now set the value of the symbol at the end of the info section.
- MCOS->EmitLabel(InfoEnd);
-}
-
-// When generating dwarf for assembly source files this emits the data for
-// .debug_ranges section. We only emit one range list, which spans all of the
-// executable sections of this file.
-static void EmitGenDwarfRanges(MCStreamer *MCOS) {
- MCContext &context = MCOS->getContext();
- auto &Sections = context.getGenDwarfSectionSyms();
-
- const MCAsmInfo *AsmInfo = context.getAsmInfo();
- int AddrSize = AsmInfo->getCodePointerSize();
-
- MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection());
-
- for (MCSection *Sec : Sections) {
- const MCSymbol *StartSymbol = Sec->getBeginSymbol();
- MCSymbol *EndSymbol = Sec->getEndSymbol(context);
- assert(StartSymbol && "StartSymbol must not be NULL");
- assert(EndSymbol && "EndSymbol must not be NULL");
-
- // Emit a base address selection entry for the start of this section
- const MCExpr *SectionStartAddr = MCSymbolRefExpr::create(
- StartSymbol, MCSymbolRefExpr::VK_None, context);
- MCOS->emitFill(AddrSize, 0xFF);
- MCOS->EmitValue(SectionStartAddr, AddrSize);
-
- // Emit a range list entry spanning this section
- const MCExpr *SectionSize = MakeStartMinusEndExpr(*MCOS,
- *StartSymbol, *EndSymbol, 0);
- MCOS->EmitIntValue(0, AddrSize);
- emitAbsValue(*MCOS, SectionSize, AddrSize);
- }
-
- // Emit end of list entry
- MCOS->EmitIntValue(0, AddrSize);
- MCOS->EmitIntValue(0, AddrSize);
-}
-
-//
-// When generating dwarf for assembly source files this emits the Dwarf
-// sections.
-//
-void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
- MCContext &context = MCOS->getContext();
-
- // Create the dwarf sections in this order (.debug_line already created).
- const MCAsmInfo *AsmInfo = context.getAsmInfo();
- bool CreateDwarfSectionSymbols =
- AsmInfo->doesDwarfUseRelocationsAcrossSections();
- MCSymbol *LineSectionSymbol = nullptr;
- if (CreateDwarfSectionSymbols)
- LineSectionSymbol = MCOS->getDwarfLineTableSymbol(0);
- MCSymbol *AbbrevSectionSymbol = nullptr;
- MCSymbol *InfoSectionSymbol = nullptr;
- MCSymbol *RangesSectionSymbol = nullptr;
-
- // Create end symbols for each section, and remove empty sections
- MCOS->getContext().finalizeDwarfSections(*MCOS);
-
- // If there are no sections to generate debug info for, we don't need
- // to do anything
- if (MCOS->getContext().getGenDwarfSectionSyms().empty())
- return;
-
- // We only use the .debug_ranges section if we have multiple code sections,
- // and we are emitting a DWARF version which supports it.
- const bool UseRangesSection =
- MCOS->getContext().getGenDwarfSectionSyms().size() > 1 &&
- MCOS->getContext().getDwarfVersion() >= 3;
- CreateDwarfSectionSymbols |= UseRangesSection;
-
- MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
- if (CreateDwarfSectionSymbols) {
- InfoSectionSymbol = context.createTempSymbol();
- MCOS->EmitLabel(InfoSectionSymbol);
- }
- MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
- if (CreateDwarfSectionSymbols) {
- AbbrevSectionSymbol = context.createTempSymbol();
- MCOS->EmitLabel(AbbrevSectionSymbol);
- }
- if (UseRangesSection) {
- MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection());
- if (CreateDwarfSectionSymbols) {
- RangesSectionSymbol = context.createTempSymbol();
- MCOS->EmitLabel(RangesSectionSymbol);
- }
- }
-
- assert((RangesSectionSymbol != nullptr) || !UseRangesSection);
-
- MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
-
- // Output the data for .debug_aranges section.
- EmitGenDwarfAranges(MCOS, InfoSectionSymbol);
-
- if (UseRangesSection)
- EmitGenDwarfRanges(MCOS);
-
- // Output the data for .debug_abbrev section.
- EmitGenDwarfAbbrev(MCOS);
-
- // Output the data for .debug_info section.
- EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol,
- RangesSectionSymbol);
-}
-
-//
-// When generating dwarf for assembly source files this is called when symbol
-// for a label is created. If this symbol is not a temporary and is in the
-// section that dwarf is being generated for, save the needed info to create
-// a dwarf label.
-//
-void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS,
- SourceMgr &SrcMgr, SMLoc &Loc) {
- // We won't create dwarf labels for temporary symbols.
- if (Symbol->isTemporary())
- return;
- MCContext &context = MCOS->getContext();
- // We won't create dwarf labels for symbols in sections that we are not
- // generating debug info for.
- if (!context.getGenDwarfSectionSyms().count(MCOS->getCurrentSectionOnly()))
- return;
-
- // The dwarf label's name does not have the symbol name's leading
- // underbar if any.
- StringRef Name = Symbol->getName();
- if (Name.startswith("_"))
- Name = Name.substr(1, Name.size()-1);
-
- // Get the dwarf file number to be used for the dwarf label.
- unsigned FileNumber = context.getGenDwarfFileNumber();
-
- // Finding the line number is the expensive part which is why we just don't
- // pass it in as for some symbols we won't create a dwarf label.
- unsigned CurBuffer = SrcMgr.FindBufferContainingLoc(Loc);
- unsigned LineNumber = SrcMgr.FindLineNumber(Loc, CurBuffer);
-
- // We create a temporary symbol for use for the AT_high_pc and AT_low_pc
- // values so that they don't have things like an ARM thumb bit from the
- // original symbol. So when used they won't get a low bit set after
- // relocation.
- MCSymbol *Label = context.createTempSymbol();
- MCOS->EmitLabel(Label);
-
- // Create and entry for the info and add it to the other entries.
- MCOS->getContext().addMCGenDwarfLabelEntry(
- MCGenDwarfLabelEntry(Name, FileNumber, LineNumber, Label));
-}
-
-static int getDataAlignmentFactor(MCStreamer &streamer) {
- MCContext &context = streamer.getContext();
- const MCAsmInfo *asmInfo = context.getAsmInfo();
- int size = asmInfo->getCalleeSaveStackSlotSize();
- if (asmInfo->isStackGrowthDirectionUp())
- return size;
- else
- return -size;
-}
-
-static unsigned getSizeForEncoding(MCStreamer &streamer,
- unsigned symbolEncoding) {
- MCContext &context = streamer.getContext();
- unsigned format = symbolEncoding & 0x0f;
- switch (format) {
- default: llvm_unreachable("Unknown Encoding");
- case dwarf::DW_EH_PE_absptr:
- case dwarf::DW_EH_PE_signed:
- return context.getAsmInfo()->getCodePointerSize();
- case dwarf::DW_EH_PE_udata2:
- case dwarf::DW_EH_PE_sdata2:
- return 2;
- case dwarf::DW_EH_PE_udata4:
- case dwarf::DW_EH_PE_sdata4:
- return 4;
- case dwarf::DW_EH_PE_udata8:
- case dwarf::DW_EH_PE_sdata8:
- return 8;
- }
-}
-
-static void emitFDESymbol(MCObjectStreamer &streamer, const MCSymbol &symbol,
- unsigned symbolEncoding, bool isEH) {
- MCContext &context = streamer.getContext();
- const MCAsmInfo *asmInfo = context.getAsmInfo();
- const MCExpr *v = asmInfo->getExprForFDESymbol(&symbol,
- symbolEncoding,
- streamer);
- unsigned size = getSizeForEncoding(streamer, symbolEncoding);
- if (asmInfo->doDwarfFDESymbolsUseAbsDiff() && isEH)
- emitAbsValue(streamer, v, size);
- else
- streamer.EmitValue(v, size);
-}
-
-static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol,
- unsigned symbolEncoding) {
- MCContext &context = streamer.getContext();
- const MCAsmInfo *asmInfo = context.getAsmInfo();
- const MCExpr *v = asmInfo->getExprForPersonalitySymbol(&symbol,
- symbolEncoding,
- streamer);
- unsigned size = getSizeForEncoding(streamer, symbolEncoding);
- streamer.EmitValue(v, size);
-}
-
-namespace {
-
-class FrameEmitterImpl {
- int CFAOffset = 0;
- int InitialCFAOffset = 0;
- bool IsEH;
- MCObjectStreamer &Streamer;
-
-public:
- FrameEmitterImpl(bool IsEH, MCObjectStreamer &Streamer)
- : IsEH(IsEH), Streamer(Streamer) {}
-
- /// Emit the unwind information in a compact way.
- void EmitCompactUnwind(const MCDwarfFrameInfo &frame);
-
- const MCSymbol &EmitCIE(const MCDwarfFrameInfo &F);
- void EmitFDE(const MCSymbol &cieStart, const MCDwarfFrameInfo &frame,
- bool LastInSection, const MCSymbol &SectionStart);
- void EmitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,
- MCSymbol *BaseLabel);
- void EmitCFIInstruction(const MCCFIInstruction &Instr);
-};
-
-} // end anonymous namespace
-
-static void emitEncodingByte(MCObjectStreamer &Streamer, unsigned Encoding) {
- Streamer.EmitIntValue(Encoding, 1);
-}
-
-void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
- int dataAlignmentFactor = getDataAlignmentFactor(Streamer);
- auto *MRI = Streamer.getContext().getRegisterInfo();
-
- switch (Instr.getOperation()) {
- case MCCFIInstruction::OpRegister: {
- unsigned Reg1 = Instr.getRegister();
- unsigned Reg2 = Instr.getRegister2();
- if (!IsEH) {
- Reg1 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg1);
- Reg2 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg2);
- }
- Streamer.EmitIntValue(dwarf::DW_CFA_register, 1);
- Streamer.EmitULEB128IntValue(Reg1);
- Streamer.EmitULEB128IntValue(Reg2);
- return;
- }
- case MCCFIInstruction::OpWindowSave:
- Streamer.EmitIntValue(dwarf::DW_CFA_GNU_window_save, 1);
- return;
-
- case MCCFIInstruction::OpNegateRAState:
- Streamer.EmitIntValue(dwarf::DW_CFA_AARCH64_negate_ra_state, 1);
- return;
-
- case MCCFIInstruction::OpUndefined: {
- unsigned Reg = Instr.getRegister();
- Streamer.EmitIntValue(dwarf::DW_CFA_undefined, 1);
- Streamer.EmitULEB128IntValue(Reg);
- return;
- }
- case MCCFIInstruction::OpAdjustCfaOffset:
- case MCCFIInstruction::OpDefCfaOffset: {
- const bool IsRelative =
- Instr.getOperation() == MCCFIInstruction::OpAdjustCfaOffset;
-
- Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1);
-
- if (IsRelative)
- CFAOffset += Instr.getOffset();
- else
- CFAOffset = -Instr.getOffset();
-
- Streamer.EmitULEB128IntValue(CFAOffset);
-
- return;
- }
- case MCCFIInstruction::OpDefCfa: {
- unsigned Reg = Instr.getRegister();
- if (!IsEH)
- Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
- Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1);
- Streamer.EmitULEB128IntValue(Reg);
- CFAOffset = -Instr.getOffset();
- Streamer.EmitULEB128IntValue(CFAOffset);
-
- return;
- }
- case MCCFIInstruction::OpDefCfaRegister: {
- unsigned Reg = Instr.getRegister();
- if (!IsEH)
- Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
- Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1);
- Streamer.EmitULEB128IntValue(Reg);
-
- return;
- }
- case MCCFIInstruction::OpOffset:
- case MCCFIInstruction::OpRelOffset: {
- const bool IsRelative =
- Instr.getOperation() == MCCFIInstruction::OpRelOffset;
-
- unsigned Reg = Instr.getRegister();
- if (!IsEH)
- Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
-
- int Offset = Instr.getOffset();
- if (IsRelative)
- Offset -= CFAOffset;
- Offset = Offset / dataAlignmentFactor;
-
- if (Offset < 0) {
- Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1);
- Streamer.EmitULEB128IntValue(Reg);
- Streamer.EmitSLEB128IntValue(Offset);
- } else if (Reg < 64) {
- Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1);
- Streamer.EmitULEB128IntValue(Offset);
- } else {
- Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1);
- Streamer.EmitULEB128IntValue(Reg);
- Streamer.EmitULEB128IntValue(Offset);
- }
- return;
- }
- case MCCFIInstruction::OpRememberState:
- Streamer.EmitIntValue(dwarf::DW_CFA_remember_state, 1);
- return;
- case MCCFIInstruction::OpRestoreState:
- Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1);
- return;
- case MCCFIInstruction::OpSameValue: {
- unsigned Reg = Instr.getRegister();
- Streamer.EmitIntValue(dwarf::DW_CFA_same_value, 1);
- Streamer.EmitULEB128IntValue(Reg);
- return;
- }
- case MCCFIInstruction::OpRestore: {
- unsigned Reg = Instr.getRegister();
- if (!IsEH)
- Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
- if (Reg < 64) {
- Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1);
- } else {
- Streamer.EmitIntValue(dwarf::DW_CFA_restore_extended, 1);
- Streamer.EmitULEB128IntValue(Reg);
- }
- return;
- }
- case MCCFIInstruction::OpGnuArgsSize:
- Streamer.EmitIntValue(dwarf::DW_CFA_GNU_args_size, 1);
- Streamer.EmitULEB128IntValue(Instr.getOffset());
- return;
-
- case MCCFIInstruction::OpEscape:
- Streamer.EmitBytes(Instr.getValues());
- return;
- }
- llvm_unreachable("Unhandled case in switch");
-}
-
-/// Emit frame instructions to describe the layout of the frame.
-void FrameEmitterImpl::EmitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,
- MCSymbol *BaseLabel) {
- for (const MCCFIInstruction &Instr : Instrs) {
- MCSymbol *Label = Instr.getLabel();
- // Throw out move if the label is invalid.
- if (Label && !Label->isDefined()) continue; // Not emitted, in dead code.
-
- // Advance row if new location.
- if (BaseLabel && Label) {
- MCSymbol *ThisSym = Label;
- if (ThisSym != BaseLabel) {
- Streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym);
- BaseLabel = ThisSym;
- }
- }
-
- EmitCFIInstruction(Instr);
- }
-}
-
-/// Emit the unwind information in a compact way.
-void FrameEmitterImpl::EmitCompactUnwind(const MCDwarfFrameInfo &Frame) {
- MCContext &Context = Streamer.getContext();
- const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();
-
- // range-start range-length compact-unwind-enc personality-func lsda
- // _foo LfooEnd-_foo 0x00000023 0 0
- // _bar LbarEnd-_bar 0x00000025 __gxx_personality except_tab1
- //
- // .section __LD,__compact_unwind,regular,debug
- //
- // # compact unwind for _foo
- // .quad _foo
- // .set L1,LfooEnd-_foo
- // .long L1
- // .long 0x01010001
- // .quad 0
- // .quad 0
- //
- // # compact unwind for _bar
- // .quad _bar
- // .set L2,LbarEnd-_bar
- // .long L2
- // .long 0x01020011
- // .quad __gxx_personality
- // .quad except_tab1
-
- uint32_t Encoding = Frame.CompactUnwindEncoding;
- if (!Encoding) return;
- bool DwarfEHFrameOnly = (Encoding == MOFI->getCompactUnwindDwarfEHFrameOnly());
-
- // The encoding needs to know we have an LSDA.
- if (!DwarfEHFrameOnly && Frame.Lsda)
- Encoding |= 0x40000000;
-
- // Range Start
- unsigned FDEEncoding = MOFI->getFDEEncoding();
- unsigned Size = getSizeForEncoding(Streamer, FDEEncoding);
- Streamer.EmitSymbolValue(Frame.Begin, Size);
-
- // Range Length
- const MCExpr *Range = MakeStartMinusEndExpr(Streamer, *Frame.Begin,
- *Frame.End, 0);
- emitAbsValue(Streamer, Range, 4);
-
- // Compact Encoding
- Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4);
- Streamer.EmitIntValue(Encoding, Size);
-
- // Personality Function
- Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_absptr);
- if (!DwarfEHFrameOnly && Frame.Personality)
- Streamer.EmitSymbolValue(Frame.Personality, Size);
- else
- Streamer.EmitIntValue(0, Size); // No personality fn
-
- // LSDA
- Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding);
- if (!DwarfEHFrameOnly && Frame.Lsda)
- Streamer.EmitSymbolValue(Frame.Lsda, Size);
- else
- Streamer.EmitIntValue(0, Size); // No LSDA
-}
-
-static unsigned getCIEVersion(bool IsEH, unsigned DwarfVersion) {
- if (IsEH)
- return 1;
- switch (DwarfVersion) {
- case 2:
- return 1;
- case 3:
- return 3;
- case 4:
- case 5:
- return 4;
- }
- llvm_unreachable("Unknown version");
-}
-
-const MCSymbol &FrameEmitterImpl::EmitCIE(const MCDwarfFrameInfo &Frame) {
- MCContext &context = Streamer.getContext();
- const MCRegisterInfo *MRI = context.getRegisterInfo();
- const MCObjectFileInfo *MOFI = context.getObjectFileInfo();
-
- MCSymbol *sectionStart = context.createTempSymbol();
- Streamer.EmitLabel(sectionStart);
-
- MCSymbol *sectionEnd = context.createTempSymbol();
-
- // Length
- const MCExpr *Length =
- MakeStartMinusEndExpr(Streamer, *sectionStart, *sectionEnd, 4);
- emitAbsValue(Streamer, Length, 4);
-
- // CIE ID
- unsigned CIE_ID = IsEH ? 0 : -1;
- Streamer.EmitIntValue(CIE_ID, 4);
-
- // Version
- uint8_t CIEVersion = getCIEVersion(IsEH, context.getDwarfVersion());
- Streamer.EmitIntValue(CIEVersion, 1);
-
- if (IsEH) {
- SmallString<8> Augmentation;
- Augmentation += "z";
- if (Frame.Personality)
- Augmentation += "P";
- if (Frame.Lsda)
- Augmentation += "L";
- Augmentation += "R";
- if (Frame.IsSignalFrame)
- Augmentation += "S";
- if (Frame.IsBKeyFrame)
- Augmentation += "B";
- Streamer.EmitBytes(Augmentation);
- }
- Streamer.EmitIntValue(0, 1);
-
- if (CIEVersion >= 4) {
- // Address Size
- Streamer.EmitIntValue(context.getAsmInfo()->getCodePointerSize(), 1);
-
- // Segment Descriptor Size
- Streamer.EmitIntValue(0, 1);
- }
-
- // Code Alignment Factor
- Streamer.EmitULEB128IntValue(context.getAsmInfo()->getMinInstAlignment());
-
- // Data Alignment Factor
- Streamer.EmitSLEB128IntValue(getDataAlignmentFactor(Streamer));
-
- // Return Address Register
- unsigned RAReg = Frame.RAReg;
- if (RAReg == static_cast<unsigned>(INT_MAX))
- RAReg = MRI->getDwarfRegNum(MRI->getRARegister(), IsEH);
-
- if (CIEVersion == 1) {
- assert(RAReg <= 255 &&
- "DWARF 2 encodes return_address_register in one byte");
- Streamer.EmitIntValue(RAReg, 1);
- } else {
- Streamer.EmitULEB128IntValue(RAReg);
- }
-
- // Augmentation Data Length (optional)
- unsigned augmentationLength = 0;
- if (IsEH) {
- if (Frame.Personality) {
- // Personality Encoding
- augmentationLength += 1;
- // Personality
- augmentationLength +=
- getSizeForEncoding(Streamer, Frame.PersonalityEncoding);
- }
- if (Frame.Lsda)
- augmentationLength += 1;
- // Encoding of the FDE pointers
- augmentationLength += 1;
-
- Streamer.EmitULEB128IntValue(augmentationLength);
-
- // Augmentation Data (optional)
- if (Frame.Personality) {
- // Personality Encoding
- emitEncodingByte(Streamer, Frame.PersonalityEncoding);
- // Personality
- EmitPersonality(Streamer, *Frame.Personality, Frame.PersonalityEncoding);
- }
-
- if (Frame.Lsda)
- emitEncodingByte(Streamer, Frame.LsdaEncoding);
-
- // Encoding of the FDE pointers
- emitEncodingByte(Streamer, MOFI->getFDEEncoding());
- }
-
- // Initial Instructions
-
- const MCAsmInfo *MAI = context.getAsmInfo();
- if (!Frame.IsSimple) {
- const std::vector<MCCFIInstruction> &Instructions =
- MAI->getInitialFrameState();
- EmitCFIInstructions(Instructions, nullptr);
- }
-
- InitialCFAOffset = CFAOffset;
-
- // Padding
- Streamer.EmitValueToAlignment(IsEH ? 4 : MAI->getCodePointerSize());
-
- Streamer.EmitLabel(sectionEnd);
- return *sectionStart;
-}
-
-void FrameEmitterImpl::EmitFDE(const MCSymbol &cieStart,
- const MCDwarfFrameInfo &frame,
- bool LastInSection,
- const MCSymbol &SectionStart) {
- MCContext &context = Streamer.getContext();
- MCSymbol *fdeStart = context.createTempSymbol();
- MCSymbol *fdeEnd = context.createTempSymbol();
- const MCObjectFileInfo *MOFI = context.getObjectFileInfo();
-
- CFAOffset = InitialCFAOffset;
-
- // Length
- const MCExpr *Length = MakeStartMinusEndExpr(Streamer, *fdeStart, *fdeEnd, 0);
- emitAbsValue(Streamer, Length, 4);
-
- Streamer.EmitLabel(fdeStart);
-
- // CIE Pointer
- const MCAsmInfo *asmInfo = context.getAsmInfo();
- if (IsEH) {
- const MCExpr *offset =
- MakeStartMinusEndExpr(Streamer, cieStart, *fdeStart, 0);
- emitAbsValue(Streamer, offset, 4);
- } else if (!asmInfo->doesDwarfUseRelocationsAcrossSections()) {
- const MCExpr *offset =
- MakeStartMinusEndExpr(Streamer, SectionStart, cieStart, 0);
- emitAbsValue(Streamer, offset, 4);
- } else {
- Streamer.EmitSymbolValue(&cieStart, 4);
- }
-
- // PC Begin
- unsigned PCEncoding =
- IsEH ? MOFI->getFDEEncoding() : (unsigned)dwarf::DW_EH_PE_absptr;
- unsigned PCSize = getSizeForEncoding(Streamer, PCEncoding);
- emitFDESymbol(Streamer, *frame.Begin, PCEncoding, IsEH);
-
- // PC Range
- const MCExpr *Range =
- MakeStartMinusEndExpr(Streamer, *frame.Begin, *frame.End, 0);
- emitAbsValue(Streamer, Range, PCSize);
-
- if (IsEH) {
- // Augmentation Data Length
- unsigned augmentationLength = 0;
-
- if (frame.Lsda)
- augmentationLength += getSizeForEncoding(Streamer, frame.LsdaEncoding);
-
- Streamer.EmitULEB128IntValue(augmentationLength);
-
- // Augmentation Data
- if (frame.Lsda)
- emitFDESymbol(Streamer, *frame.Lsda, frame.LsdaEncoding, true);
- }
-
- // Call Frame Instructions
- EmitCFIInstructions(frame.Instructions, frame.Begin);
-
- // Padding
- // The size of a .eh_frame section has to be a multiple of the alignment
- // since a null CIE is interpreted as the end. Old systems overaligned
- // .eh_frame, so we do too and account for it in the last FDE.
- unsigned Align = LastInSection ? asmInfo->getCodePointerSize() : PCSize;
- Streamer.EmitValueToAlignment(Align);
-
- Streamer.EmitLabel(fdeEnd);
-}
-
-namespace {
-
-struct CIEKey {
- static const CIEKey getEmptyKey() {
- return CIEKey(nullptr, 0, -1, false, false, static_cast<unsigned>(INT_MAX),
- false);
- }
-
- static const CIEKey getTombstoneKey() {
- return CIEKey(nullptr, -1, 0, false, false, static_cast<unsigned>(INT_MAX),
- false);
- }
-
- CIEKey(const MCSymbol *Personality, unsigned PersonalityEncoding,
- unsigned LSDAEncoding, bool IsSignalFrame, bool IsSimple,
- unsigned RAReg, bool IsBKeyFrame)
- : Personality(Personality), PersonalityEncoding(PersonalityEncoding),
- LsdaEncoding(LSDAEncoding), IsSignalFrame(IsSignalFrame),
- IsSimple(IsSimple), RAReg(RAReg), IsBKeyFrame(IsBKeyFrame) {}
-
- explicit CIEKey(const MCDwarfFrameInfo &Frame)
- : Personality(Frame.Personality),
- PersonalityEncoding(Frame.PersonalityEncoding),
- LsdaEncoding(Frame.LsdaEncoding), IsSignalFrame(Frame.IsSignalFrame),
- IsSimple(Frame.IsSimple), RAReg(Frame.RAReg),
- IsBKeyFrame(Frame.IsBKeyFrame) {}
-
- StringRef PersonalityName() const {
- if (!Personality)
- return StringRef();
- return Personality->getName();
- }
-
- bool operator<(const CIEKey &Other) const {
- return std::make_tuple(PersonalityName(), PersonalityEncoding, LsdaEncoding,
- IsSignalFrame, IsSimple, RAReg) <
- std::make_tuple(Other.PersonalityName(), Other.PersonalityEncoding,
- Other.LsdaEncoding, Other.IsSignalFrame,
- Other.IsSimple, Other.RAReg);
- }
-
- const MCSymbol *Personality;
- unsigned PersonalityEncoding;
- unsigned LsdaEncoding;
- bool IsSignalFrame;
- bool IsSimple;
- unsigned RAReg;
- bool IsBKeyFrame;
-};
-
-} // end anonymous namespace
-
-namespace llvm {
-
-template <> struct DenseMapInfo<CIEKey> {
- static CIEKey getEmptyKey() { return CIEKey::getEmptyKey(); }
- static CIEKey getTombstoneKey() { return CIEKey::getTombstoneKey(); }
-
- static unsigned getHashValue(const CIEKey &Key) {
- return static_cast<unsigned>(hash_combine(
- Key.Personality, Key.PersonalityEncoding, Key.LsdaEncoding,
- Key.IsSignalFrame, Key.IsSimple, Key.RAReg, Key.IsBKeyFrame));
- }
-
- static bool isEqual(const CIEKey &LHS, const CIEKey &RHS) {
- return LHS.Personality == RHS.Personality &&
- LHS.PersonalityEncoding == RHS.PersonalityEncoding &&
- LHS.LsdaEncoding == RHS.LsdaEncoding &&
- LHS.IsSignalFrame == RHS.IsSignalFrame &&
- LHS.IsSimple == RHS.IsSimple && LHS.RAReg == RHS.RAReg &&
- LHS.IsBKeyFrame == RHS.IsBKeyFrame;
- }
-};
-
-} // end namespace llvm
-
-void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB,
- bool IsEH) {
- Streamer.generateCompactUnwindEncodings(MAB);
-
- MCContext &Context = Streamer.getContext();
- const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();
- const MCAsmInfo *AsmInfo = Context.getAsmInfo();
- FrameEmitterImpl Emitter(IsEH, Streamer);
- ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getDwarfFrameInfos();
-
- // Emit the compact unwind info if available.
- bool NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame();
- if (IsEH && MOFI->getCompactUnwindSection()) {
- bool SectionEmitted = false;
- for (const MCDwarfFrameInfo &Frame : FrameArray) {
- if (Frame.CompactUnwindEncoding == 0) continue;
- if (!SectionEmitted) {
- Streamer.SwitchSection(MOFI->getCompactUnwindSection());
- Streamer.EmitValueToAlignment(AsmInfo->getCodePointerSize());
- SectionEmitted = true;
- }
- NeedsEHFrameSection |=
- Frame.CompactUnwindEncoding ==
- MOFI->getCompactUnwindDwarfEHFrameOnly();
- Emitter.EmitCompactUnwind(Frame);
- }
- }
-
- if (!NeedsEHFrameSection) return;
-
- MCSection &Section =
- IsEH ? *const_cast<MCObjectFileInfo *>(MOFI)->getEHFrameSection()
- : *MOFI->getDwarfFrameSection();
-
- Streamer.SwitchSection(&Section);
- MCSymbol *SectionStart = Context.createTempSymbol();
- Streamer.EmitLabel(SectionStart);
-
- DenseMap<CIEKey, const MCSymbol *> CIEStarts;
-
- const MCSymbol *DummyDebugKey = nullptr;
- bool CanOmitDwarf = MOFI->getOmitDwarfIfHaveCompactUnwind();
- // Sort the FDEs by their corresponding CIE before we emit them.
- // This isn't technically necessary according to the DWARF standard,
- // but the Android libunwindstack rejects eh_frame sections where
- // an FDE refers to a CIE other than the closest previous CIE.
- std::vector<MCDwarfFrameInfo> FrameArrayX(FrameArray.begin(), FrameArray.end());
- llvm::stable_sort(FrameArrayX,
- [](const MCDwarfFrameInfo &X, const MCDwarfFrameInfo &Y) {
- return CIEKey(X) < CIEKey(Y);
- });
- for (auto I = FrameArrayX.begin(), E = FrameArrayX.end(); I != E;) {
- const MCDwarfFrameInfo &Frame = *I;
- ++I;
- if (CanOmitDwarf && Frame.CompactUnwindEncoding !=
- MOFI->getCompactUnwindDwarfEHFrameOnly())
- // Don't generate an EH frame if we don't need one. I.e., it's taken care
- // of by the compact unwind encoding.
- continue;
-
- CIEKey Key(Frame);
- const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey;
- if (!CIEStart)
- CIEStart = &Emitter.EmitCIE(Frame);
-
- Emitter.EmitFDE(*CIEStart, Frame, I == E, *SectionStart);
- }
-}
-
-void MCDwarfFrameEmitter::EmitAdvanceLoc(MCObjectStreamer &Streamer,
- uint64_t AddrDelta) {
- MCContext &Context = Streamer.getContext();
- SmallString<256> Tmp;
- raw_svector_ostream OS(Tmp);
- MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OS);
- Streamer.EmitBytes(OS.str());
-}
-
-void MCDwarfFrameEmitter::EncodeAdvanceLoc(MCContext &Context,
- uint64_t AddrDelta, raw_ostream &OS,
- uint32_t *Offset, uint32_t *Size) {
- // Scale the address delta by the minimum instruction length.
- AddrDelta = ScaleAddrDelta(Context, AddrDelta);
-
- bool WithFixups = false;
- if (Offset && Size)
- WithFixups = true;
-
- support::endianness E =
- Context.getAsmInfo()->isLittleEndian() ? support::little : support::big;
- if (AddrDelta == 0) {
- if (WithFixups) {
- *Offset = 0;
- *Size = 0;
- }
- } else if (isUIntN(6, AddrDelta)) {
- uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta;
- if (WithFixups) {
- *Offset = OS.tell();
- *Size = 6;
- OS << uint8_t(dwarf::DW_CFA_advance_loc);
- } else
- OS << Opcode;
- } else if (isUInt<8>(AddrDelta)) {
- OS << uint8_t(dwarf::DW_CFA_advance_loc1);
- if (WithFixups) {
- *Offset = OS.tell();
- *Size = 8;
- OS.write_zeros(1);
- } else
- OS << uint8_t(AddrDelta);
- } else if (isUInt<16>(AddrDelta)) {
- OS << uint8_t(dwarf::DW_CFA_advance_loc2);
- if (WithFixups) {
- *Offset = OS.tell();
- *Size = 16;
- OS.write_zeros(2);
- } else
- support::endian::write<uint16_t>(OS, AddrDelta, E);
- } else {
- assert(isUInt<32>(AddrDelta));
- OS << uint8_t(dwarf::DW_CFA_advance_loc4);
- if (WithFixups) {
- *Offset = OS.tell();
- *Size = 32;
- OS.write_zeros(4);
- } else
- support::endian::write<uint32_t>(OS, AddrDelta, E);
- }
-}
diff --git a/contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp b/contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp
deleted file mode 100644
index a81eab9ca296..000000000000
--- a/contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-//===-- MCELFObjectTargetWriter.cpp - ELF Target Writer Subclass ----------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCELFObjectWriter.h"
-
-using namespace llvm;
-
-MCELFObjectTargetWriter::MCELFObjectTargetWriter(bool Is64Bit_, uint8_t OSABI_,
- uint16_t EMachine_,
- bool HasRelocationAddend_,
- uint8_t ABIVersion_)
- : OSABI(OSABI_), ABIVersion(ABIVersion_), EMachine(EMachine_),
- HasRelocationAddend(HasRelocationAddend_), Is64Bit(Is64Bit_) {}
-
-bool MCELFObjectTargetWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
- unsigned Type) const {
- return false;
-}
-
-void
-MCELFObjectTargetWriter::sortRelocs(const MCAssembler &Asm,
- std::vector<ELFRelocationEntry> &Relocs) {
-}
-
-void MCELFObjectTargetWriter::addTargetSectionFlags(MCContext &Ctx,
- MCSectionELF &Sec) {}
diff --git a/contrib/llvm/lib/MC/MCELFStreamer.cpp b/contrib/llvm/lib/MC/MCELFStreamer.cpp
deleted file mode 100644
index 245dd063004f..000000000000
--- a/contrib/llvm/lib/MC/MCELFStreamer.cpp
+++ /dev/null
@@ -1,708 +0,0 @@
-//===- lib/MC/MCELFStreamer.cpp - ELF Object Output -----------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file assembles .s files and emits ELF .o object files.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCELFStreamer.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCCodeEmitter.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCFixup.h"
-#include "llvm/MC/MCFragment.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCSectionELF.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCSymbolELF.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/TargetRegistry.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <cstdint>
-
-using namespace llvm;
-
-MCELFStreamer::MCELFStreamer(MCContext &Context,
- std::unique_ptr<MCAsmBackend> TAB,
- std::unique_ptr<MCObjectWriter> OW,
- std::unique_ptr<MCCodeEmitter> Emitter)
- : MCObjectStreamer(Context, std::move(TAB), std::move(OW),
- std::move(Emitter)) {}
-
-bool MCELFStreamer::isBundleLocked() const {
- return getCurrentSectionOnly()->isBundleLocked();
-}
-
-void MCELFStreamer::mergeFragment(MCDataFragment *DF,
- MCDataFragment *EF) {
- MCAssembler &Assembler = getAssembler();
-
- if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) {
- uint64_t FSize = EF->getContents().size();
-
- if (FSize > Assembler.getBundleAlignSize())
- report_fatal_error("Fragment can't be larger than a bundle size");
-
- uint64_t RequiredBundlePadding = computeBundlePadding(
- Assembler, EF, DF->getContents().size(), FSize);
-
- if (RequiredBundlePadding > UINT8_MAX)
- report_fatal_error("Padding cannot exceed 255 bytes");
-
- if (RequiredBundlePadding > 0) {
- SmallString<256> Code;
- raw_svector_ostream VecOS(Code);
- EF->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding));
- Assembler.writeFragmentPadding(VecOS, *EF, FSize);
-
- DF->getContents().append(Code.begin(), Code.end());
- }
- }
-
- flushPendingLabels(DF, DF->getContents().size());
-
- for (unsigned i = 0, e = EF->getFixups().size(); i != e; ++i) {
- EF->getFixups()[i].setOffset(EF->getFixups()[i].getOffset() +
- DF->getContents().size());
- DF->getFixups().push_back(EF->getFixups()[i]);
- }
- if (DF->getSubtargetInfo() == nullptr && EF->getSubtargetInfo())
- DF->setHasInstructions(*EF->getSubtargetInfo());
- DF->getContents().append(EF->getContents().begin(), EF->getContents().end());
-}
-
-void MCELFStreamer::InitSections(bool NoExecStack) {
- MCContext &Ctx = getContext();
- SwitchSection(Ctx.getObjectFileInfo()->getTextSection());
- EmitCodeAlignment(4);
-
- if (NoExecStack)
- SwitchSection(Ctx.getAsmInfo()->getNonexecutableStackSection(Ctx));
-}
-
-void MCELFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) {
- auto *Symbol = cast<MCSymbolELF>(S);
- MCObjectStreamer::EmitLabel(Symbol, Loc);
-
- const MCSectionELF &Section =
- static_cast<const MCSectionELF &>(*getCurrentSectionOnly());
- if (Section.getFlags() & ELF::SHF_TLS)
- Symbol->setType(ELF::STT_TLS);
-}
-
-void MCELFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc, MCFragment *F) {
- auto *Symbol = cast<MCSymbolELF>(S);
- MCObjectStreamer::EmitLabel(Symbol, Loc, F);
-
- const MCSectionELF &Section =
- static_cast<const MCSectionELF &>(*getCurrentSectionOnly());
- if (Section.getFlags() & ELF::SHF_TLS)
- Symbol->setType(ELF::STT_TLS);
-}
-
-void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
- // Let the target do whatever target specific stuff it needs to do.
- getAssembler().getBackend().handleAssemblerFlag(Flag);
- // Do any generic stuff we need to do.
- switch (Flag) {
- case MCAF_SyntaxUnified: return; // no-op here.
- case MCAF_Code16: return; // Change parsing mode; no-op here.
- case MCAF_Code32: return; // Change parsing mode; no-op here.
- case MCAF_Code64: return; // Change parsing mode; no-op here.
- case MCAF_SubsectionsViaSymbols:
- getAssembler().setSubsectionsViaSymbols(true);
- return;
- }
-
- llvm_unreachable("invalid assembler flag!");
-}
-
-// If bundle alignment is used and there are any instructions in the section, it
-// needs to be aligned to at least the bundle size.
-static void setSectionAlignmentForBundling(const MCAssembler &Assembler,
- MCSection *Section) {
- if (Section && Assembler.isBundlingEnabled() && Section->hasInstructions() &&
- Section->getAlignment() < Assembler.getBundleAlignSize())
- Section->setAlignment(Assembler.getBundleAlignSize());
-}
-
-void MCELFStreamer::ChangeSection(MCSection *Section,
- const MCExpr *Subsection) {
- MCSection *CurSection = getCurrentSectionOnly();
- if (CurSection && isBundleLocked())
- report_fatal_error("Unterminated .bundle_lock when changing a section");
-
- MCAssembler &Asm = getAssembler();
- // Ensure the previous section gets aligned if necessary.
- setSectionAlignmentForBundling(Asm, CurSection);
- auto *SectionELF = static_cast<const MCSectionELF *>(Section);
- const MCSymbol *Grp = SectionELF->getGroup();
- if (Grp)
- Asm.registerSymbol(*Grp);
-
- changeSectionImpl(Section, Subsection);
- Asm.registerSymbol(*Section->getBeginSymbol());
-}
-
-void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
- getAssembler().registerSymbol(*Symbol);
- const MCExpr *Value = MCSymbolRefExpr::create(
- Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext());
- Alias->setVariableValue(Value);
-}
-
-// When GNU as encounters more than one .type declaration for an object it seems
-// to use a mechanism similar to the one below to decide which type is actually
-// used in the object file. The greater of T1 and T2 is selected based on the
-// following ordering:
-// STT_NOTYPE < STT_OBJECT < STT_FUNC < STT_GNU_IFUNC < STT_TLS < anything else
-// If neither T1 < T2 nor T2 < T1 according to this ordering, use T2 (the user
-// provided type).
-static unsigned CombineSymbolTypes(unsigned T1, unsigned T2) {
- for (unsigned Type : {ELF::STT_NOTYPE, ELF::STT_OBJECT, ELF::STT_FUNC,
- ELF::STT_GNU_IFUNC, ELF::STT_TLS}) {
- if (T1 == Type)
- return T2;
- if (T2 == Type)
- return T1;
- }
-
- return T2;
-}
-
-bool MCELFStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
- auto *Symbol = cast<MCSymbolELF>(S);
-
- // Adding a symbol attribute always introduces the symbol, note that an
- // important side effect of calling registerSymbol here is to register
- // the symbol with the assembler.
- getAssembler().registerSymbol(*Symbol);
-
- // The implementation of symbol attributes is designed to match 'as', but it
- // leaves much to desired. It doesn't really make sense to arbitrarily add and
- // remove flags, but 'as' allows this (in particular, see .desc).
- //
- // In the future it might be worth trying to make these operations more well
- // defined.
- switch (Attribute) {
- case MCSA_Cold:
- case MCSA_LazyReference:
- case MCSA_Reference:
- case MCSA_SymbolResolver:
- case MCSA_PrivateExtern:
- case MCSA_WeakDefinition:
- case MCSA_WeakDefAutoPrivate:
- case MCSA_Invalid:
- case MCSA_IndirectSymbol:
- return false;
-
- case MCSA_NoDeadStrip:
- // Ignore for now.
- break;
-
- case MCSA_ELF_TypeGnuUniqueObject:
- Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT));
- Symbol->setBinding(ELF::STB_GNU_UNIQUE);
- Symbol->setExternal(true);
- break;
-
- case MCSA_Global:
- Symbol->setBinding(ELF::STB_GLOBAL);
- Symbol->setExternal(true);
- break;
-
- case MCSA_WeakReference:
- case MCSA_Weak:
- Symbol->setBinding(ELF::STB_WEAK);
- Symbol->setExternal(true);
- break;
-
- case MCSA_Local:
- Symbol->setBinding(ELF::STB_LOCAL);
- Symbol->setExternal(false);
- break;
-
- case MCSA_ELF_TypeFunction:
- Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_FUNC));
- break;
-
- case MCSA_ELF_TypeIndFunction:
- Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_GNU_IFUNC));
- break;
-
- case MCSA_ELF_TypeObject:
- Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT));
- break;
-
- case MCSA_ELF_TypeTLS:
- Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_TLS));
- break;
-
- case MCSA_ELF_TypeCommon:
- // TODO: Emit these as a common symbol.
- Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT));
- break;
-
- case MCSA_ELF_TypeNoType:
- Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_NOTYPE));
- break;
-
- case MCSA_Protected:
- Symbol->setVisibility(ELF::STV_PROTECTED);
- break;
-
- case MCSA_Hidden:
- Symbol->setVisibility(ELF::STV_HIDDEN);
- break;
-
- case MCSA_Internal:
- Symbol->setVisibility(ELF::STV_INTERNAL);
- break;
-
- case MCSA_AltEntry:
- llvm_unreachable("ELF doesn't support the .alt_entry attribute");
- }
-
- return true;
-}
-
-void MCELFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
- unsigned ByteAlignment) {
- auto *Symbol = cast<MCSymbolELF>(S);
- getAssembler().registerSymbol(*Symbol);
-
- if (!Symbol->isBindingSet()) {
- Symbol->setBinding(ELF::STB_GLOBAL);
- Symbol->setExternal(true);
- }
-
- Symbol->setType(ELF::STT_OBJECT);
-
- if (Symbol->getBinding() == ELF::STB_LOCAL) {
- MCSection &Section = *getAssembler().getContext().getELFSection(
- ".bss", ELF::SHT_NOBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
- MCSectionSubPair P = getCurrentSection();
- SwitchSection(&Section);
-
- EmitValueToAlignment(ByteAlignment, 0, 1, 0);
- EmitLabel(Symbol);
- EmitZeros(Size);
-
- // Update the maximum alignment of the section if necessary.
- if (ByteAlignment > Section.getAlignment())
- Section.setAlignment(ByteAlignment);
-
- SwitchSection(P.first, P.second);
- } else {
- if(Symbol->declareCommon(Size, ByteAlignment))
- report_fatal_error("Symbol: " + Symbol->getName() +
- " redeclared as different type");
- }
-
- cast<MCSymbolELF>(Symbol)
- ->setSize(MCConstantExpr::create(Size, getContext()));
-}
-
-void MCELFStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
- cast<MCSymbolELF>(Symbol)->setSize(Value);
-}
-
-void MCELFStreamer::emitELFSymverDirective(StringRef AliasName,
- const MCSymbol *Aliasee) {
- getAssembler().Symvers.push_back({AliasName, Aliasee});
-}
-
-void MCELFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
- unsigned ByteAlignment) {
- auto *Symbol = cast<MCSymbolELF>(S);
- // FIXME: Should this be caught and done earlier?
- getAssembler().registerSymbol(*Symbol);
- Symbol->setBinding(ELF::STB_LOCAL);
- Symbol->setExternal(false);
- EmitCommonSymbol(Symbol, Size, ByteAlignment);
-}
-
-void MCELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
- SMLoc Loc) {
- if (isBundleLocked())
- report_fatal_error("Emitting values inside a locked bundle is forbidden");
- fixSymbolsInTLSFixups(Value);
- MCObjectStreamer::EmitValueImpl(Value, Size, Loc);
-}
-
-void MCELFStreamer::EmitValueToAlignment(unsigned ByteAlignment,
- int64_t Value,
- unsigned ValueSize,
- unsigned MaxBytesToEmit) {
- if (isBundleLocked())
- report_fatal_error("Emitting values inside a locked bundle is forbidden");
- MCObjectStreamer::EmitValueToAlignment(ByteAlignment, Value,
- ValueSize, MaxBytesToEmit);
-}
-
-void MCELFStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
- const MCSymbolRefExpr *To,
- uint64_t Count) {
- getAssembler().CGProfile.push_back({From, To, Count});
-}
-
-void MCELFStreamer::EmitIdent(StringRef IdentString) {
- MCSection *Comment = getAssembler().getContext().getELFSection(
- ".comment", ELF::SHT_PROGBITS, ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, "");
- PushSection();
- SwitchSection(Comment);
- if (!SeenIdent) {
- EmitIntValue(0, 1);
- SeenIdent = true;
- }
- EmitBytes(IdentString);
- EmitIntValue(0, 1);
- PopSection();
-}
-
-void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) {
- switch (expr->getKind()) {
- case MCExpr::Target:
- cast<MCTargetExpr>(expr)->fixELFSymbolsInTLSFixups(getAssembler());
- break;
- case MCExpr::Constant:
- break;
-
- case MCExpr::Binary: {
- const MCBinaryExpr *be = cast<MCBinaryExpr>(expr);
- fixSymbolsInTLSFixups(be->getLHS());
- fixSymbolsInTLSFixups(be->getRHS());
- break;
- }
-
- case MCExpr::SymbolRef: {
- const MCSymbolRefExpr &symRef = *cast<MCSymbolRefExpr>(expr);
- switch (symRef.getKind()) {
- default:
- return;
- case MCSymbolRefExpr::VK_GOTTPOFF:
- case MCSymbolRefExpr::VK_INDNTPOFF:
- case MCSymbolRefExpr::VK_NTPOFF:
- case MCSymbolRefExpr::VK_GOTNTPOFF:
- case MCSymbolRefExpr::VK_TLSCALL:
- case MCSymbolRefExpr::VK_TLSDESC:
- case MCSymbolRefExpr::VK_TLSGD:
- case MCSymbolRefExpr::VK_TLSLD:
- case MCSymbolRefExpr::VK_TLSLDM:
- case MCSymbolRefExpr::VK_TPOFF:
- case MCSymbolRefExpr::VK_TPREL:
- case MCSymbolRefExpr::VK_DTPOFF:
- case MCSymbolRefExpr::VK_DTPREL:
- case MCSymbolRefExpr::VK_PPC_DTPMOD:
- case MCSymbolRefExpr::VK_PPC_TPREL_LO:
- case MCSymbolRefExpr::VK_PPC_TPREL_HI:
- case MCSymbolRefExpr::VK_PPC_TPREL_HA:
- case MCSymbolRefExpr::VK_PPC_TPREL_HIGH:
- case MCSymbolRefExpr::VK_PPC_TPREL_HIGHA:
- case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
- case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
- case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
- case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
- case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
- case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
- case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
- case MCSymbolRefExpr::VK_PPC_DTPREL_HIGH:
- case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHA:
- case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
- case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
- case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
- case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
- case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
- case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
- case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
- case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
- case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
- case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
- case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
- case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
- case MCSymbolRefExpr::VK_PPC_TLS:
- case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
- case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
- case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
- case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
- case MCSymbolRefExpr::VK_PPC_TLSGD:
- case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
- case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
- case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
- case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
- case MCSymbolRefExpr::VK_PPC_TLSLD:
- break;
- }
- getAssembler().registerSymbol(symRef.getSymbol());
- cast<MCSymbolELF>(symRef.getSymbol()).setType(ELF::STT_TLS);
- break;
- }
-
- case MCExpr::Unary:
- fixSymbolsInTLSFixups(cast<MCUnaryExpr>(expr)->getSubExpr());
- break;
- }
-}
-
-void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE) {
- const MCSymbol *S = &SRE->getSymbol();
- if (S->isTemporary()) {
- if (!S->isInSection()) {
- getContext().reportError(
- SRE->getLoc(), Twine("Reference to undefined temporary symbol ") +
- "`" + S->getName() + "`");
- return;
- }
- S = S->getSection().getBeginSymbol();
- S->setUsedInReloc();
- SRE =
- MCSymbolRefExpr::create(S, SRE->getKind(), getContext(), SRE->getLoc());
- return;
- }
- // Not a temporary, referece it as a weak undefined.
- bool Created;
- getAssembler().registerSymbol(*S, &Created);
- if (Created) {
- cast<MCSymbolELF>(S)->setBinding(ELF::STB_WEAK);
- cast<MCSymbolELF>(S)->setExternal(true);
- }
-}
-
-void MCELFStreamer::finalizeCGProfile() {
- for (MCAssembler::CGProfileEntry &E : getAssembler().CGProfile) {
- finalizeCGProfileEntry(E.From);
- finalizeCGProfileEntry(E.To);
- }
-}
-
-void MCELFStreamer::EmitInstToFragment(const MCInst &Inst,
- const MCSubtargetInfo &STI) {
- this->MCObjectStreamer::EmitInstToFragment(Inst, STI);
- MCRelaxableFragment &F = *cast<MCRelaxableFragment>(getCurrentFragment());
-
- for (unsigned i = 0, e = F.getFixups().size(); i != e; ++i)
- fixSymbolsInTLSFixups(F.getFixups()[i].getValue());
-}
-
-// A fragment can only have one Subtarget, and when bundling is enabled we
-// sometimes need to use the same fragment. We give an error if there
-// are conflicting Subtargets.
-static void CheckBundleSubtargets(const MCSubtargetInfo *OldSTI,
- const MCSubtargetInfo *NewSTI) {
- if (OldSTI && NewSTI && OldSTI != NewSTI)
- report_fatal_error("A Bundle can only have one Subtarget.");
-}
-
-void MCELFStreamer::EmitInstToData(const MCInst &Inst,
- const MCSubtargetInfo &STI) {
- MCAssembler &Assembler = getAssembler();
- SmallVector<MCFixup, 4> Fixups;
- SmallString<256> Code;
- raw_svector_ostream VecOS(Code);
- Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
-
- for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
- fixSymbolsInTLSFixups(Fixups[i].getValue());
-
- // There are several possibilities here:
- //
- // If bundling is disabled, append the encoded instruction to the current data
- // fragment (or create a new such fragment if the current fragment is not a
- // data fragment, or the Subtarget has changed).
- //
- // If bundling is enabled:
- // - If we're not in a bundle-locked group, emit the instruction into a
- // fragment of its own. If there are no fixups registered for the
- // instruction, emit a MCCompactEncodedInstFragment. Otherwise, emit a
- // MCDataFragment.
- // - If we're in a bundle-locked group, append the instruction to the current
- // data fragment because we want all the instructions in a group to get into
- // the same fragment. Be careful not to do that for the first instruction in
- // the group, though.
- MCDataFragment *DF;
-
- if (Assembler.isBundlingEnabled()) {
- MCSection &Sec = *getCurrentSectionOnly();
- if (Assembler.getRelaxAll() && isBundleLocked()) {
- // If the -mc-relax-all flag is used and we are bundle-locked, we re-use
- // the current bundle group.
- DF = BundleGroups.back();
- CheckBundleSubtargets(DF->getSubtargetInfo(), &STI);
- }
- else if (Assembler.getRelaxAll() && !isBundleLocked())
- // When not in a bundle-locked group and the -mc-relax-all flag is used,
- // we create a new temporary fragment which will be later merged into
- // the current fragment.
- DF = new MCDataFragment();
- else if (isBundleLocked() && !Sec.isBundleGroupBeforeFirstInst()) {
- // If we are bundle-locked, we re-use the current fragment.
- // The bundle-locking directive ensures this is a new data fragment.
- DF = cast<MCDataFragment>(getCurrentFragment());
- CheckBundleSubtargets(DF->getSubtargetInfo(), &STI);
- }
- else if (!isBundleLocked() && Fixups.size() == 0) {
- // Optimize memory usage by emitting the instruction to a
- // MCCompactEncodedInstFragment when not in a bundle-locked group and
- // there are no fixups registered.
- MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment();
- insert(CEIF);
- CEIF->getContents().append(Code.begin(), Code.end());
- CEIF->setHasInstructions(STI);
- return;
- } else {
- DF = new MCDataFragment();
- insert(DF);
- }
- if (Sec.getBundleLockState() == MCSection::BundleLockedAlignToEnd) {
- // If this fragment is for a group marked "align_to_end", set a flag
- // in the fragment. This can happen after the fragment has already been
- // created if there are nested bundle_align groups and an inner one
- // is the one marked align_to_end.
- DF->setAlignToBundleEnd(true);
- }
-
- // We're now emitting an instruction in a bundle group, so this flag has
- // to be turned off.
- Sec.setBundleGroupBeforeFirstInst(false);
- } else {
- DF = getOrCreateDataFragment(&STI);
- }
-
- // Add the fixups and data.
- for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
- Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
- DF->getFixups().push_back(Fixups[i]);
- }
- DF->setHasInstructions(STI);
- DF->getContents().append(Code.begin(), Code.end());
-
- if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) {
- if (!isBundleLocked()) {
- mergeFragment(getOrCreateDataFragment(&STI), DF);
- delete DF;
- }
- }
-}
-
-void MCELFStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
- assert(AlignPow2 <= 30 && "Invalid bundle alignment");
- MCAssembler &Assembler = getAssembler();
- if (AlignPow2 > 0 && (Assembler.getBundleAlignSize() == 0 ||
- Assembler.getBundleAlignSize() == 1U << AlignPow2))
- Assembler.setBundleAlignSize(1U << AlignPow2);
- else
- report_fatal_error(".bundle_align_mode cannot be changed once set");
-}
-
-void MCELFStreamer::EmitBundleLock(bool AlignToEnd) {
- MCSection &Sec = *getCurrentSectionOnly();
-
- // Sanity checks
- //
- if (!getAssembler().isBundlingEnabled())
- report_fatal_error(".bundle_lock forbidden when bundling is disabled");
-
- if (!isBundleLocked())
- Sec.setBundleGroupBeforeFirstInst(true);
-
- if (getAssembler().getRelaxAll() && !isBundleLocked()) {
- // TODO: drop the lock state and set directly in the fragment
- MCDataFragment *DF = new MCDataFragment();
- BundleGroups.push_back(DF);
- }
-
- Sec.setBundleLockState(AlignToEnd ? MCSection::BundleLockedAlignToEnd
- : MCSection::BundleLocked);
-}
-
-void MCELFStreamer::EmitBundleUnlock() {
- MCSection &Sec = *getCurrentSectionOnly();
-
- // Sanity checks
- if (!getAssembler().isBundlingEnabled())
- report_fatal_error(".bundle_unlock forbidden when bundling is disabled");
- else if (!isBundleLocked())
- report_fatal_error(".bundle_unlock without matching lock");
- else if (Sec.isBundleGroupBeforeFirstInst())
- report_fatal_error("Empty bundle-locked group is forbidden");
-
- // When the -mc-relax-all flag is used, we emit instructions to fragments
- // stored on a stack. When the bundle unlock is emitted, we pop a fragment
- // from the stack a merge it to the one below.
- if (getAssembler().getRelaxAll()) {
- assert(!BundleGroups.empty() && "There are no bundle groups");
- MCDataFragment *DF = BundleGroups.back();
-
- // FIXME: Use BundleGroups to track the lock state instead.
- Sec.setBundleLockState(MCSection::NotBundleLocked);
-
- // FIXME: Use more separate fragments for nested groups.
- if (!isBundleLocked()) {
- mergeFragment(getOrCreateDataFragment(DF->getSubtargetInfo()), DF);
- BundleGroups.pop_back();
- delete DF;
- }
-
- if (Sec.getBundleLockState() != MCSection::BundleLockedAlignToEnd)
- getOrCreateDataFragment()->setAlignToBundleEnd(false);
- } else
- Sec.setBundleLockState(MCSection::NotBundleLocked);
-}
-
-void MCELFStreamer::FinishImpl() {
- // Ensure the last section gets aligned if necessary.
- MCSection *CurSection = getCurrentSectionOnly();
- setSectionAlignmentForBundling(getAssembler(), CurSection);
-
- finalizeCGProfile();
- EmitFrames(nullptr);
-
- this->MCObjectStreamer::FinishImpl();
-}
-
-void MCELFStreamer::EmitThumbFunc(MCSymbol *Func) {
- llvm_unreachable("Generic ELF doesn't support this directive");
-}
-
-void MCELFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
- llvm_unreachable("ELF doesn't support this directive");
-}
-
-void MCELFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment,
- SMLoc Loc) {
- llvm_unreachable("ELF doesn't support this directive");
-}
-
-void MCELFStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment) {
- llvm_unreachable("ELF doesn't support this directive");
-}
-
-MCStreamer *llvm::createELFStreamer(MCContext &Context,
- std::unique_ptr<MCAsmBackend> &&MAB,
- std::unique_ptr<MCObjectWriter> &&OW,
- std::unique_ptr<MCCodeEmitter> &&CE,
- bool RelaxAll) {
- MCELFStreamer *S =
- new MCELFStreamer(Context, std::move(MAB), std::move(OW), std::move(CE));
- if (RelaxAll)
- S->getAssembler().setRelaxAll(true);
- return S;
-}
diff --git a/contrib/llvm/lib/MC/MCExpr.cpp b/contrib/llvm/lib/MC/MCExpr.cpp
deleted file mode 100644
index 543b0661905c..000000000000
--- a/contrib/llvm/lib/MC/MCExpr.cpp
+++ /dev/null
@@ -1,931 +0,0 @@
-//===- MCExpr.cpp - Assembly Level Expression Implementation --------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCExpr.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCAsmLayout.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <cstdint>
-
-using namespace llvm;
-
-#define DEBUG_TYPE "mcexpr"
-
-namespace {
-namespace stats {
-
-STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations");
-
-} // end namespace stats
-} // end anonymous namespace
-
-void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const {
- switch (getKind()) {
- case MCExpr::Target:
- return cast<MCTargetExpr>(this)->printImpl(OS, MAI);
- case MCExpr::Constant: {
- auto Value = cast<MCConstantExpr>(*this).getValue();
- auto PrintInHex = cast<MCConstantExpr>(*this).useHexFormat();
- if (PrintInHex)
- OS << "0x" << Twine::utohexstr(Value);
- else
- OS << Value;
- return;
- }
- case MCExpr::SymbolRef: {
- const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this);
- const MCSymbol &Sym = SRE.getSymbol();
- // Parenthesize names that start with $ so that they don't look like
- // absolute names.
- bool UseParens =
- !InParens && !Sym.getName().empty() && Sym.getName()[0] == '$';
- if (UseParens) {
- OS << '(';
- Sym.print(OS, MAI);
- OS << ')';
- } else
- Sym.print(OS, MAI);
-
- if (SRE.getKind() != MCSymbolRefExpr::VK_None)
- SRE.printVariantKind(OS);
-
- return;
- }
-
- case MCExpr::Unary: {
- const MCUnaryExpr &UE = cast<MCUnaryExpr>(*this);
- switch (UE.getOpcode()) {
- case MCUnaryExpr::LNot: OS << '!'; break;
- case MCUnaryExpr::Minus: OS << '-'; break;
- case MCUnaryExpr::Not: OS << '~'; break;
- case MCUnaryExpr::Plus: OS << '+'; break;
- }
- bool Binary = UE.getSubExpr()->getKind() == MCExpr::Binary;
- if (Binary) OS << "(";
- UE.getSubExpr()->print(OS, MAI);
- if (Binary) OS << ")";
- return;
- }
-
- case MCExpr::Binary: {
- const MCBinaryExpr &BE = cast<MCBinaryExpr>(*this);
-
- // Only print parens around the LHS if it is non-trivial.
- if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) {
- BE.getLHS()->print(OS, MAI);
- } else {
- OS << '(';
- BE.getLHS()->print(OS, MAI);
- OS << ')';
- }
-
- switch (BE.getOpcode()) {
- case MCBinaryExpr::Add:
- // Print "X-42" instead of "X+-42".
- if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(BE.getRHS())) {
- if (RHSC->getValue() < 0) {
- OS << RHSC->getValue();
- return;
- }
- }
-
- OS << '+';
- break;
- case MCBinaryExpr::AShr: OS << ">>"; break;
- case MCBinaryExpr::And: OS << '&'; break;
- case MCBinaryExpr::Div: OS << '/'; break;
- case MCBinaryExpr::EQ: OS << "=="; break;
- case MCBinaryExpr::GT: OS << '>'; break;
- case MCBinaryExpr::GTE: OS << ">="; break;
- case MCBinaryExpr::LAnd: OS << "&&"; break;
- case MCBinaryExpr::LOr: OS << "||"; break;
- case MCBinaryExpr::LShr: OS << ">>"; break;
- case MCBinaryExpr::LT: OS << '<'; break;
- case MCBinaryExpr::LTE: OS << "<="; break;
- case MCBinaryExpr::Mod: OS << '%'; break;
- case MCBinaryExpr::Mul: OS << '*'; break;
- case MCBinaryExpr::NE: OS << "!="; break;
- case MCBinaryExpr::Or: OS << '|'; break;
- case MCBinaryExpr::Shl: OS << "<<"; break;
- case MCBinaryExpr::Sub: OS << '-'; break;
- case MCBinaryExpr::Xor: OS << '^'; break;
- }
-
- // Only print parens around the LHS if it is non-trivial.
- if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) {
- BE.getRHS()->print(OS, MAI);
- } else {
- OS << '(';
- BE.getRHS()->print(OS, MAI);
- OS << ')';
- }
- return;
- }
- }
-
- llvm_unreachable("Invalid expression kind!");
-}
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void MCExpr::dump() const {
- dbgs() << *this;
- dbgs() << '\n';
-}
-#endif
-
-/* *** */
-
-const MCBinaryExpr *MCBinaryExpr::create(Opcode Opc, const MCExpr *LHS,
- const MCExpr *RHS, MCContext &Ctx,
- SMLoc Loc) {
- return new (Ctx) MCBinaryExpr(Opc, LHS, RHS, Loc);
-}
-
-const MCUnaryExpr *MCUnaryExpr::create(Opcode Opc, const MCExpr *Expr,
- MCContext &Ctx, SMLoc Loc) {
- return new (Ctx) MCUnaryExpr(Opc, Expr, Loc);
-}
-
-const MCConstantExpr *MCConstantExpr::create(int64_t Value, MCContext &Ctx,
- bool PrintInHex) {
- return new (Ctx) MCConstantExpr(Value, PrintInHex);
-}
-
-/* *** */
-
-MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind,
- const MCAsmInfo *MAI, SMLoc Loc)
- : MCExpr(MCExpr::SymbolRef, Loc), Kind(Kind),
- UseParensForSymbolVariant(MAI->useParensForSymbolVariant()),
- HasSubsectionsViaSymbols(MAI->hasSubsectionsViaSymbols()),
- Symbol(Symbol) {
- assert(Symbol);
-}
-
-const MCSymbolRefExpr *MCSymbolRefExpr::create(const MCSymbol *Sym,
- VariantKind Kind,
- MCContext &Ctx, SMLoc Loc) {
- return new (Ctx) MCSymbolRefExpr(Sym, Kind, Ctx.getAsmInfo(), Loc);
-}
-
-const MCSymbolRefExpr *MCSymbolRefExpr::create(StringRef Name, VariantKind Kind,
- MCContext &Ctx) {
- return create(Ctx.getOrCreateSymbol(Name), Kind, Ctx);
-}
-
-StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
- switch (Kind) {
- case VK_Invalid: return "<<invalid>>";
- case VK_None: return "<<none>>";
-
- case VK_DTPOFF: return "DTPOFF";
- case VK_DTPREL: return "DTPREL";
- case VK_GOT: return "GOT";
- case VK_GOTOFF: return "GOTOFF";
- case VK_GOTREL: return "GOTREL";
- case VK_GOTPCREL: return "GOTPCREL";
- case VK_GOTTPOFF: return "GOTTPOFF";
- case VK_INDNTPOFF: return "INDNTPOFF";
- case VK_NTPOFF: return "NTPOFF";
- case VK_GOTNTPOFF: return "GOTNTPOFF";
- case VK_PLT: return "PLT";
- case VK_TLSGD: return "TLSGD";
- case VK_TLSLD: return "TLSLD";
- case VK_TLSLDM: return "TLSLDM";
- case VK_TPOFF: return "TPOFF";
- case VK_TPREL: return "TPREL";
- case VK_TLSCALL: return "tlscall";
- case VK_TLSDESC: return "tlsdesc";
- case VK_TLVP: return "TLVP";
- case VK_TLVPPAGE: return "TLVPPAGE";
- case VK_TLVPPAGEOFF: return "TLVPPAGEOFF";
- case VK_PAGE: return "PAGE";
- case VK_PAGEOFF: return "PAGEOFF";
- case VK_GOTPAGE: return "GOTPAGE";
- case VK_GOTPAGEOFF: return "GOTPAGEOFF";
- case VK_SECREL: return "SECREL32";
- case VK_SIZE: return "SIZE";
- case VK_WEAKREF: return "WEAKREF";
- case VK_X86_ABS8: return "ABS8";
- case VK_ARM_NONE: return "none";
- case VK_ARM_GOT_PREL: return "GOT_PREL";
- case VK_ARM_TARGET1: return "target1";
- case VK_ARM_TARGET2: return "target2";
- case VK_ARM_PREL31: return "prel31";
- case VK_ARM_SBREL: return "sbrel";
- case VK_ARM_TLSLDO: return "tlsldo";
- case VK_ARM_TLSDESCSEQ: return "tlsdescseq";
- case VK_AVR_NONE: return "none";
- case VK_AVR_LO8: return "lo8";
- case VK_AVR_HI8: return "hi8";
- case VK_AVR_HLO8: return "hlo8";
- case VK_AVR_DIFF8: return "diff8";
- case VK_AVR_DIFF16: return "diff16";
- case VK_AVR_DIFF32: return "diff32";
- case VK_PPC_LO: return "l";
- case VK_PPC_HI: return "h";
- case VK_PPC_HA: return "ha";
- case VK_PPC_HIGH: return "high";
- case VK_PPC_HIGHA: return "higha";
- case VK_PPC_HIGHER: return "higher";
- case VK_PPC_HIGHERA: return "highera";
- case VK_PPC_HIGHEST: return "highest";
- case VK_PPC_HIGHESTA: return "highesta";
- case VK_PPC_GOT_LO: return "got@l";
- case VK_PPC_GOT_HI: return "got@h";
- case VK_PPC_GOT_HA: return "got@ha";
- case VK_PPC_TOCBASE: return "tocbase";
- case VK_PPC_TOC: return "toc";
- case VK_PPC_TOC_LO: return "toc@l";
- case VK_PPC_TOC_HI: return "toc@h";
- case VK_PPC_TOC_HA: return "toc@ha";
- case VK_PPC_DTPMOD: return "dtpmod";
- case VK_PPC_TPREL_LO: return "tprel@l";
- case VK_PPC_TPREL_HI: return "tprel@h";
- case VK_PPC_TPREL_HA: return "tprel@ha";
- case VK_PPC_TPREL_HIGH: return "tprel@high";
- case VK_PPC_TPREL_HIGHA: return "tprel@higha";
- case VK_PPC_TPREL_HIGHER: return "tprel@higher";
- case VK_PPC_TPREL_HIGHERA: return "tprel@highera";
- case VK_PPC_TPREL_HIGHEST: return "tprel@highest";
- case VK_PPC_TPREL_HIGHESTA: return "tprel@highesta";
- case VK_PPC_DTPREL_LO: return "dtprel@l";
- case VK_PPC_DTPREL_HI: return "dtprel@h";
- case VK_PPC_DTPREL_HA: return "dtprel@ha";
- case VK_PPC_DTPREL_HIGH: return "dtprel@high";
- case VK_PPC_DTPREL_HIGHA: return "dtprel@higha";
- case VK_PPC_DTPREL_HIGHER: return "dtprel@higher";
- case VK_PPC_DTPREL_HIGHERA: return "dtprel@highera";
- case VK_PPC_DTPREL_HIGHEST: return "dtprel@highest";
- case VK_PPC_DTPREL_HIGHESTA: return "dtprel@highesta";
- case VK_PPC_GOT_TPREL: return "got@tprel";
- case VK_PPC_GOT_TPREL_LO: return "got@tprel@l";
- case VK_PPC_GOT_TPREL_HI: return "got@tprel@h";
- case VK_PPC_GOT_TPREL_HA: return "got@tprel@ha";
- case VK_PPC_GOT_DTPREL: return "got@dtprel";
- case VK_PPC_GOT_DTPREL_LO: return "got@dtprel@l";
- case VK_PPC_GOT_DTPREL_HI: return "got@dtprel@h";
- case VK_PPC_GOT_DTPREL_HA: return "got@dtprel@ha";
- case VK_PPC_TLS: return "tls";
- case VK_PPC_GOT_TLSGD: return "got@tlsgd";
- case VK_PPC_GOT_TLSGD_LO: return "got@tlsgd@l";
- case VK_PPC_GOT_TLSGD_HI: return "got@tlsgd@h";
- case VK_PPC_GOT_TLSGD_HA: return "got@tlsgd@ha";
- case VK_PPC_TLSGD: return "tlsgd";
- case VK_PPC_GOT_TLSLD: return "got@tlsld";
- case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l";
- case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h";
- case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha";
- case VK_PPC_TLSLD: return "tlsld";
- case VK_PPC_LOCAL: return "local";
- case VK_COFF_IMGREL32: return "IMGREL";
- case VK_Hexagon_PCREL: return "PCREL";
- case VK_Hexagon_LO16: return "LO16";
- case VK_Hexagon_HI16: return "HI16";
- case VK_Hexagon_GPREL: return "GPREL";
- case VK_Hexagon_GD_GOT: return "GDGOT";
- case VK_Hexagon_LD_GOT: return "LDGOT";
- case VK_Hexagon_GD_PLT: return "GDPLT";
- case VK_Hexagon_LD_PLT: return "LDPLT";
- case VK_Hexagon_IE: return "IE";
- case VK_Hexagon_IE_GOT: return "IEGOT";
- case VK_WASM_TYPEINDEX: return "TYPEINDEX";
- case VK_WASM_MBREL: return "MBREL";
- case VK_WASM_TBREL: return "TBREL";
- case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo";
- case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi";
- case VK_AMDGPU_REL32_LO: return "rel32@lo";
- case VK_AMDGPU_REL32_HI: return "rel32@hi";
- case VK_AMDGPU_REL64: return "rel64";
- case VK_AMDGPU_ABS32_LO: return "abs32@lo";
- case VK_AMDGPU_ABS32_HI: return "abs32@hi";
- }
- llvm_unreachable("Invalid variant kind");
-}
-
-MCSymbolRefExpr::VariantKind
-MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
- return StringSwitch<VariantKind>(Name.lower())
- .Case("dtprel", VK_DTPREL)
- .Case("dtpoff", VK_DTPOFF)
- .Case("got", VK_GOT)
- .Case("gotoff", VK_GOTOFF)
- .Case("gotrel", VK_GOTREL)
- .Case("gotpcrel", VK_GOTPCREL)
- .Case("gottpoff", VK_GOTTPOFF)
- .Case("indntpoff", VK_INDNTPOFF)
- .Case("ntpoff", VK_NTPOFF)
- .Case("gotntpoff", VK_GOTNTPOFF)
- .Case("plt", VK_PLT)
- .Case("tlscall", VK_TLSCALL)
- .Case("tlsdesc", VK_TLSDESC)
- .Case("tlsgd", VK_TLSGD)
- .Case("tlsld", VK_TLSLD)
- .Case("tlsldm", VK_TLSLDM)
- .Case("tpoff", VK_TPOFF)
- .Case("tprel", VK_TPREL)
- .Case("tlvp", VK_TLVP)
- .Case("tlvppage", VK_TLVPPAGE)
- .Case("tlvppageoff", VK_TLVPPAGEOFF)
- .Case("page", VK_PAGE)
- .Case("pageoff", VK_PAGEOFF)
- .Case("gotpage", VK_GOTPAGE)
- .Case("gotpageoff", VK_GOTPAGEOFF)
- .Case("imgrel", VK_COFF_IMGREL32)
- .Case("secrel32", VK_SECREL)
- .Case("size", VK_SIZE)
- .Case("abs8", VK_X86_ABS8)
- .Case("l", VK_PPC_LO)
- .Case("h", VK_PPC_HI)
- .Case("ha", VK_PPC_HA)
- .Case("high", VK_PPC_HIGH)
- .Case("higha", VK_PPC_HIGHA)
- .Case("higher", VK_PPC_HIGHER)
- .Case("highera", VK_PPC_HIGHERA)
- .Case("highest", VK_PPC_HIGHEST)
- .Case("highesta", VK_PPC_HIGHESTA)
- .Case("got@l", VK_PPC_GOT_LO)
- .Case("got@h", VK_PPC_GOT_HI)
- .Case("got@ha", VK_PPC_GOT_HA)
- .Case("local", VK_PPC_LOCAL)
- .Case("tocbase", VK_PPC_TOCBASE)
- .Case("toc", VK_PPC_TOC)
- .Case("toc@l", VK_PPC_TOC_LO)
- .Case("toc@h", VK_PPC_TOC_HI)
- .Case("toc@ha", VK_PPC_TOC_HA)
- .Case("tls", VK_PPC_TLS)
- .Case("dtpmod", VK_PPC_DTPMOD)
- .Case("tprel@l", VK_PPC_TPREL_LO)
- .Case("tprel@h", VK_PPC_TPREL_HI)
- .Case("tprel@ha", VK_PPC_TPREL_HA)
- .Case("tprel@high", VK_PPC_TPREL_HIGH)
- .Case("tprel@higha", VK_PPC_TPREL_HIGHA)
- .Case("tprel@higher", VK_PPC_TPREL_HIGHER)
- .Case("tprel@highera", VK_PPC_TPREL_HIGHERA)
- .Case("tprel@highest", VK_PPC_TPREL_HIGHEST)
- .Case("tprel@highesta", VK_PPC_TPREL_HIGHESTA)
- .Case("dtprel@l", VK_PPC_DTPREL_LO)
- .Case("dtprel@h", VK_PPC_DTPREL_HI)
- .Case("dtprel@ha", VK_PPC_DTPREL_HA)
- .Case("dtprel@high", VK_PPC_DTPREL_HIGH)
- .Case("dtprel@higha", VK_PPC_DTPREL_HIGHA)
- .Case("dtprel@higher", VK_PPC_DTPREL_HIGHER)
- .Case("dtprel@highera", VK_PPC_DTPREL_HIGHERA)
- .Case("dtprel@highest", VK_PPC_DTPREL_HIGHEST)
- .Case("dtprel@highesta", VK_PPC_DTPREL_HIGHESTA)
- .Case("got@tprel", VK_PPC_GOT_TPREL)
- .Case("got@tprel@l", VK_PPC_GOT_TPREL_LO)
- .Case("got@tprel@h", VK_PPC_GOT_TPREL_HI)
- .Case("got@tprel@ha", VK_PPC_GOT_TPREL_HA)
- .Case("got@dtprel", VK_PPC_GOT_DTPREL)
- .Case("got@dtprel@l", VK_PPC_GOT_DTPREL_LO)
- .Case("got@dtprel@h", VK_PPC_GOT_DTPREL_HI)
- .Case("got@dtprel@ha", VK_PPC_GOT_DTPREL_HA)
- .Case("got@tlsgd", VK_PPC_GOT_TLSGD)
- .Case("got@tlsgd@l", VK_PPC_GOT_TLSGD_LO)
- .Case("got@tlsgd@h", VK_PPC_GOT_TLSGD_HI)
- .Case("got@tlsgd@ha", VK_PPC_GOT_TLSGD_HA)
- .Case("got@tlsld", VK_PPC_GOT_TLSLD)
- .Case("got@tlsld@l", VK_PPC_GOT_TLSLD_LO)
- .Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI)
- .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA)
- .Case("gdgot", VK_Hexagon_GD_GOT)
- .Case("gdplt", VK_Hexagon_GD_PLT)
- .Case("iegot", VK_Hexagon_IE_GOT)
- .Case("ie", VK_Hexagon_IE)
- .Case("ldgot", VK_Hexagon_LD_GOT)
- .Case("ldplt", VK_Hexagon_LD_PLT)
- .Case("pcrel", VK_Hexagon_PCREL)
- .Case("none", VK_ARM_NONE)
- .Case("got_prel", VK_ARM_GOT_PREL)
- .Case("target1", VK_ARM_TARGET1)
- .Case("target2", VK_ARM_TARGET2)
- .Case("prel31", VK_ARM_PREL31)
- .Case("sbrel", VK_ARM_SBREL)
- .Case("tlsldo", VK_ARM_TLSLDO)
- .Case("lo8", VK_AVR_LO8)
- .Case("hi8", VK_AVR_HI8)
- .Case("hlo8", VK_AVR_HLO8)
- .Case("typeindex", VK_WASM_TYPEINDEX)
- .Case("tbrel", VK_WASM_TBREL)
- .Case("mbrel", VK_WASM_MBREL)
- .Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO)
- .Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI)
- .Case("rel32@lo", VK_AMDGPU_REL32_LO)
- .Case("rel32@hi", VK_AMDGPU_REL32_HI)
- .Case("rel64", VK_AMDGPU_REL64)
- .Case("abs32@lo", VK_AMDGPU_ABS32_LO)
- .Case("abs32@hi", VK_AMDGPU_ABS32_HI)
- .Default(VK_Invalid);
-}
-
-void MCSymbolRefExpr::printVariantKind(raw_ostream &OS) const {
- if (UseParensForSymbolVariant)
- OS << '(' << MCSymbolRefExpr::getVariantKindName(getKind()) << ')';
- else
- OS << '@' << MCSymbolRefExpr::getVariantKindName(getKind());
-}
-
-/* *** */
-
-void MCTargetExpr::anchor() {}
-
-/* *** */
-
-bool MCExpr::evaluateAsAbsolute(int64_t &Res) const {
- return evaluateAsAbsolute(Res, nullptr, nullptr, nullptr);
-}
-
-bool MCExpr::evaluateAsAbsolute(int64_t &Res,
- const MCAsmLayout &Layout) const {
- return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr);
-}
-
-bool MCExpr::evaluateAsAbsolute(int64_t &Res,
- const MCAsmLayout &Layout,
- const SectionAddrMap &Addrs) const {
- return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs);
-}
-
-bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const {
- return evaluateAsAbsolute(Res, &Asm, nullptr, nullptr);
-}
-
-bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const {
- return evaluateAsAbsolute(Res, Asm, nullptr, nullptr);
-}
-
-bool MCExpr::evaluateKnownAbsolute(int64_t &Res,
- const MCAsmLayout &Layout) const {
- return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr,
- true);
-}
-
-bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
- const MCAsmLayout *Layout,
- const SectionAddrMap *Addrs) const {
- // FIXME: The use if InSet = Addrs is a hack. Setting InSet causes us
- // absolutize differences across sections and that is what the MachO writer
- // uses Addrs for.
- return evaluateAsAbsolute(Res, Asm, Layout, Addrs, Addrs);
-}
-
-bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
- const MCAsmLayout *Layout,
- const SectionAddrMap *Addrs, bool InSet) const {
- MCValue Value;
-
- // Fast path constants.
- if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(this)) {
- Res = CE->getValue();
- return true;
- }
-
- bool IsRelocatable =
- evaluateAsRelocatableImpl(Value, Asm, Layout, nullptr, Addrs, InSet);
-
- // Record the current value.
- Res = Value.getConstant();
-
- return IsRelocatable && Value.isAbsolute();
-}
-
-/// Helper method for \see EvaluateSymbolAdd().
-static void AttemptToFoldSymbolOffsetDifference(
- const MCAssembler *Asm, const MCAsmLayout *Layout,
- const SectionAddrMap *Addrs, bool InSet, const MCSymbolRefExpr *&A,
- const MCSymbolRefExpr *&B, int64_t &Addend) {
- if (!A || !B)
- return;
-
- const MCSymbol &SA = A->getSymbol();
- const MCSymbol &SB = B->getSymbol();
-
- if (SA.isUndefined() || SB.isUndefined())
- return;
-
- if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet))
- return;
-
- if (SA.getFragment() == SB.getFragment() && !SA.isVariable() &&
- !SA.isUnset() && !SB.isVariable() && !SB.isUnset()) {
- Addend += (SA.getOffset() - SB.getOffset());
-
- // Pointers to Thumb symbols need to have their low-bit set to allow
- // for interworking.
- if (Asm->isThumbFunc(&SA))
- Addend |= 1;
-
- // If symbol is labeled as micromips, we set low-bit to ensure
- // correct offset in .gcc_except_table
- if (Asm->getBackend().isMicroMips(&SA))
- Addend |= 1;
-
- // Clear the symbol expr pointers to indicate we have folded these
- // operands.
- A = B = nullptr;
- return;
- }
-
- if (!Layout)
- return;
-
- const MCSection &SecA = *SA.getFragment()->getParent();
- const MCSection &SecB = *SB.getFragment()->getParent();
-
- if ((&SecA != &SecB) && !Addrs)
- return;
-
- // Eagerly evaluate.
- Addend += Layout->getSymbolOffset(A->getSymbol()) -
- Layout->getSymbolOffset(B->getSymbol());
- if (Addrs && (&SecA != &SecB))
- Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB));
-
- // Pointers to Thumb symbols need to have their low-bit set to allow
- // for interworking.
- if (Asm->isThumbFunc(&SA))
- Addend |= 1;
-
- // If symbol is labeled as micromips, we set low-bit to ensure
- // correct offset in .gcc_except_table
- if (Asm->getBackend().isMicroMips(&SA))
- Addend |= 1;
-
- // Clear the symbol expr pointers to indicate we have folded these
- // operands.
- A = B = nullptr;
-}
-
-static bool canFold(const MCAssembler *Asm, const MCSymbolRefExpr *A,
- const MCSymbolRefExpr *B, bool InSet) {
- if (InSet)
- return true;
-
- if (!Asm->getBackend().requiresDiffExpressionRelocations())
- return true;
-
- const MCSymbol &CheckSym = A ? A->getSymbol() : B->getSymbol();
- if (!CheckSym.isInSection())
- return true;
-
- if (!CheckSym.getSection().hasInstructions())
- return true;
-
- return false;
-}
-
-/// Evaluate the result of an add between (conceptually) two MCValues.
-///
-/// This routine conceptually attempts to construct an MCValue:
-/// Result = (Result_A - Result_B + Result_Cst)
-/// from two MCValue's LHS and RHS where
-/// Result = LHS + RHS
-/// and
-/// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).
-///
-/// This routine attempts to aggresively fold the operands such that the result
-/// is representable in an MCValue, but may not always succeed.
-///
-/// \returns True on success, false if the result is not representable in an
-/// MCValue.
-
-/// NOTE: It is really important to have both the Asm and Layout arguments.
-/// They might look redundant, but this function can be used before layout
-/// is done (see the object streamer for example) and having the Asm argument
-/// lets us avoid relaxations early.
-static bool
-EvaluateSymbolicAdd(const MCAssembler *Asm, const MCAsmLayout *Layout,
- const SectionAddrMap *Addrs, bool InSet, const MCValue &LHS,
- const MCSymbolRefExpr *RHS_A, const MCSymbolRefExpr *RHS_B,
- int64_t RHS_Cst, MCValue &Res) {
- // FIXME: This routine (and other evaluation parts) are *incredibly* sloppy
- // about dealing with modifiers. This will ultimately bite us, one day.
- const MCSymbolRefExpr *LHS_A = LHS.getSymA();
- const MCSymbolRefExpr *LHS_B = LHS.getSymB();
- int64_t LHS_Cst = LHS.getConstant();
-
- // Fold the result constant immediately.
- int64_t Result_Cst = LHS_Cst + RHS_Cst;
-
- assert((!Layout || Asm) &&
- "Must have an assembler object if layout is given!");
-
- // If we have a layout, we can fold resolved differences. Do not do this if
- // the backend requires this to be emitted as individual relocations, unless
- // the InSet flag is set to get the current difference anyway (used for
- // example to calculate symbol sizes).
- if (Asm && canFold(Asm, LHS_A, LHS_B, InSet)) {
- // First, fold out any differences which are fully resolved. By
- // reassociating terms in
- // Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).
- // we have the four possible differences:
- // (LHS_A - LHS_B),
- // (LHS_A - RHS_B),
- // (RHS_A - LHS_B),
- // (RHS_A - RHS_B).
- // Since we are attempting to be as aggressive as possible about folding, we
- // attempt to evaluate each possible alternative.
- AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, LHS_B,
- Result_Cst);
- AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, RHS_B,
- Result_Cst);
- AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, LHS_B,
- Result_Cst);
- AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, RHS_B,
- Result_Cst);
- }
-
- // We can't represent the addition or subtraction of two symbols.
- if ((LHS_A && RHS_A) || (LHS_B && RHS_B))
- return false;
-
- // At this point, we have at most one additive symbol and one subtractive
- // symbol -- find them.
- const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A;
- const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B;
-
- Res = MCValue::get(A, B, Result_Cst);
- return true;
-}
-
-bool MCExpr::evaluateAsRelocatable(MCValue &Res,
- const MCAsmLayout *Layout,
- const MCFixup *Fixup) const {
- MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr;
- return evaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr,
- false);
-}
-
-bool MCExpr::evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const {
- MCAssembler *Assembler = &Layout.getAssembler();
- return evaluateAsRelocatableImpl(Res, Assembler, &Layout, nullptr, nullptr,
- true);
-}
-
-static bool canExpand(const MCSymbol &Sym, bool InSet) {
- const MCExpr *Expr = Sym.getVariableValue();
- const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr);
- if (Inner) {
- if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
- return false;
- }
-
- if (InSet)
- return true;
- return !Sym.isInSection();
-}
-
-bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
- const MCAsmLayout *Layout,
- const MCFixup *Fixup,
- const SectionAddrMap *Addrs,
- bool InSet) const {
- ++stats::MCExprEvaluate;
-
- switch (getKind()) {
- case Target:
- return cast<MCTargetExpr>(this)->evaluateAsRelocatableImpl(Res, Layout,
- Fixup);
-
- case Constant:
- Res = MCValue::get(cast<MCConstantExpr>(this)->getValue());
- return true;
-
- case SymbolRef: {
- const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this);
- const MCSymbol &Sym = SRE->getSymbol();
-
- // Evaluate recursively if this is a variable.
- if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None &&
- canExpand(Sym, InSet)) {
- bool IsMachO = SRE->hasSubsectionsViaSymbols();
- if (Sym.getVariableValue()->evaluateAsRelocatableImpl(
- Res, Asm, Layout, Fixup, Addrs, InSet || IsMachO)) {
- if (!IsMachO)
- return true;
-
- const MCSymbolRefExpr *A = Res.getSymA();
- const MCSymbolRefExpr *B = Res.getSymB();
- // FIXME: This is small hack. Given
- // a = b + 4
- // .long a
- // the OS X assembler will completely drop the 4. We should probably
- // include it in the relocation or produce an error if that is not
- // possible.
- // Allow constant expressions.
- if (!A && !B)
- return true;
- // Allows aliases with zero offset.
- if (Res.getConstant() == 0 && (!A || !B))
- return true;
- }
- }
-
- Res = MCValue::get(SRE, nullptr, 0);
- return true;
- }
-
- case Unary: {
- const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
- MCValue Value;
-
- if (!AUE->getSubExpr()->evaluateAsRelocatableImpl(Value, Asm, Layout, Fixup,
- Addrs, InSet))
- return false;
-
- switch (AUE->getOpcode()) {
- case MCUnaryExpr::LNot:
- if (!Value.isAbsolute())
- return false;
- Res = MCValue::get(!Value.getConstant());
- break;
- case MCUnaryExpr::Minus:
- /// -(a - b + const) ==> (b - a - const)
- if (Value.getSymA() && !Value.getSymB())
- return false;
-
- // The cast avoids undefined behavior if the constant is INT64_MIN.
- Res = MCValue::get(Value.getSymB(), Value.getSymA(),
- -(uint64_t)Value.getConstant());
- break;
- case MCUnaryExpr::Not:
- if (!Value.isAbsolute())
- return false;
- Res = MCValue::get(~Value.getConstant());
- break;
- case MCUnaryExpr::Plus:
- Res = Value;
- break;
- }
-
- return true;
- }
-
- case Binary: {
- const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
- MCValue LHSValue, RHSValue;
-
- if (!ABE->getLHS()->evaluateAsRelocatableImpl(LHSValue, Asm, Layout, Fixup,
- Addrs, InSet) ||
- !ABE->getRHS()->evaluateAsRelocatableImpl(RHSValue, Asm, Layout, Fixup,
- Addrs, InSet)) {
- // Check if both are Target Expressions, see if we can compare them.
- if (const MCTargetExpr *L = dyn_cast<MCTargetExpr>(ABE->getLHS()))
- if (const MCTargetExpr *R = cast<MCTargetExpr>(ABE->getRHS())) {
- switch (ABE->getOpcode()) {
- case MCBinaryExpr::EQ:
- Res = MCValue::get((L->isEqualTo(R)) ? -1 : 0);
- return true;
- case MCBinaryExpr::NE:
- Res = MCValue::get((R->isEqualTo(R)) ? 0 : -1);
- return true;
- default: break;
- }
- }
- return false;
- }
-
- // We only support a few operations on non-constant expressions, handle
- // those first.
- if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) {
- switch (ABE->getOpcode()) {
- default:
- return false;
- case MCBinaryExpr::Sub:
- // Negate RHS and add.
- // The cast avoids undefined behavior if the constant is INT64_MIN.
- return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
- RHSValue.getSymB(), RHSValue.getSymA(),
- -(uint64_t)RHSValue.getConstant(), Res);
-
- case MCBinaryExpr::Add:
- return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
- RHSValue.getSymA(), RHSValue.getSymB(),
- RHSValue.getConstant(), Res);
- }
- }
-
- // FIXME: We need target hooks for the evaluation. It may be limited in
- // width, and gas defines the result of comparisons differently from
- // Apple as.
- int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
- int64_t Result = 0;
- auto Op = ABE->getOpcode();
- switch (Op) {
- case MCBinaryExpr::AShr: Result = LHS >> RHS; break;
- case MCBinaryExpr::Add: Result = LHS + RHS; break;
- case MCBinaryExpr::And: Result = LHS & RHS; break;
- case MCBinaryExpr::Div:
- case MCBinaryExpr::Mod:
- // Handle division by zero. gas just emits a warning and keeps going,
- // we try to be stricter.
- // FIXME: Currently the caller of this function has no way to understand
- // we're bailing out because of 'division by zero'. Therefore, it will
- // emit a 'expected relocatable expression' error. It would be nice to
- // change this code to emit a better diagnostic.
- if (RHS == 0)
- return false;
- if (ABE->getOpcode() == MCBinaryExpr::Div)
- Result = LHS / RHS;
- else
- Result = LHS % RHS;
- break;
- case MCBinaryExpr::EQ: Result = LHS == RHS; break;
- case MCBinaryExpr::GT: Result = LHS > RHS; break;
- case MCBinaryExpr::GTE: Result = LHS >= RHS; break;
- case MCBinaryExpr::LAnd: Result = LHS && RHS; break;
- case MCBinaryExpr::LOr: Result = LHS || RHS; break;
- case MCBinaryExpr::LShr: Result = uint64_t(LHS) >> uint64_t(RHS); break;
- case MCBinaryExpr::LT: Result = LHS < RHS; break;
- case MCBinaryExpr::LTE: Result = LHS <= RHS; break;
- case MCBinaryExpr::Mul: Result = LHS * RHS; break;
- case MCBinaryExpr::NE: Result = LHS != RHS; break;
- case MCBinaryExpr::Or: Result = LHS | RHS; break;
- case MCBinaryExpr::Shl: Result = uint64_t(LHS) << uint64_t(RHS); break;
- case MCBinaryExpr::Sub: Result = LHS - RHS; break;
- case MCBinaryExpr::Xor: Result = LHS ^ RHS; break;
- }
-
- switch (Op) {
- default:
- Res = MCValue::get(Result);
- break;
- case MCBinaryExpr::EQ:
- case MCBinaryExpr::GT:
- case MCBinaryExpr::GTE:
- case MCBinaryExpr::LT:
- case MCBinaryExpr::LTE:
- case MCBinaryExpr::NE:
- // A comparison operator returns a -1 if true and 0 if false.
- Res = MCValue::get(Result ? -1 : 0);
- break;
- }
-
- return true;
- }
- }
-
- llvm_unreachable("Invalid assembly expression kind!");
-}
-
-MCFragment *MCExpr::findAssociatedFragment() const {
- switch (getKind()) {
- case Target:
- // We never look through target specific expressions.
- return cast<MCTargetExpr>(this)->findAssociatedFragment();
-
- case Constant:
- return MCSymbol::AbsolutePseudoFragment;
-
- case SymbolRef: {
- const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this);
- const MCSymbol &Sym = SRE->getSymbol();
- return Sym.getFragment();
- }
-
- case Unary:
- return cast<MCUnaryExpr>(this)->getSubExpr()->findAssociatedFragment();
-
- case Binary: {
- const MCBinaryExpr *BE = cast<MCBinaryExpr>(this);
- MCFragment *LHS_F = BE->getLHS()->findAssociatedFragment();
- MCFragment *RHS_F = BE->getRHS()->findAssociatedFragment();
-
- // If either is absolute, return the other.
- if (LHS_F == MCSymbol::AbsolutePseudoFragment)
- return RHS_F;
- if (RHS_F == MCSymbol::AbsolutePseudoFragment)
- return LHS_F;
-
- // Not always correct, but probably the best we can do without more context.
- if (BE->getOpcode() == MCBinaryExpr::Sub)
- return MCSymbol::AbsolutePseudoFragment;
-
- // Otherwise, return the first non-null fragment.
- return LHS_F ? LHS_F : RHS_F;
- }
- }
-
- llvm_unreachable("Invalid assembly expression kind!");
-}
diff --git a/contrib/llvm/lib/MC/MCFragment.cpp b/contrib/llvm/lib/MC/MCFragment.cpp
deleted file mode 100644
index ae5bd65507bc..000000000000
--- a/contrib/llvm/lib/MC/MCFragment.cpp
+++ /dev/null
@@ -1,467 +0,0 @@
-//===- lib/MC/MCFragment.cpp - Assembler Fragment Implementation ----------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCFragment.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/MC/MCAsmLayout.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCFixup.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <cstdint>
-#include <utility>
-
-using namespace llvm;
-
-MCAsmLayout::MCAsmLayout(MCAssembler &Asm) : Assembler(Asm) {
- // Compute the section layout order. Virtual sections must go last.
- for (MCSection &Sec : Asm)
- if (!Sec.isVirtualSection())
- SectionOrder.push_back(&Sec);
- for (MCSection &Sec : Asm)
- if (Sec.isVirtualSection())
- SectionOrder.push_back(&Sec);
-}
-
-bool MCAsmLayout::isFragmentValid(const MCFragment *F) const {
- const MCSection *Sec = F->getParent();
- const MCFragment *LastValid = LastValidFragment.lookup(Sec);
- if (!LastValid)
- return false;
- assert(LastValid->getParent() == Sec);
- return F->getLayoutOrder() <= LastValid->getLayoutOrder();
-}
-
-void MCAsmLayout::invalidateFragmentsFrom(MCFragment *F) {
- // If this fragment wasn't already valid, we don't need to do anything.
- if (!isFragmentValid(F))
- return;
-
- // Otherwise, reset the last valid fragment to the previous fragment
- // (if this is the first fragment, it will be NULL).
- LastValidFragment[F->getParent()] = F->getPrevNode();
-}
-
-void MCAsmLayout::ensureValid(const MCFragment *F) const {
- MCSection *Sec = F->getParent();
- MCSection::iterator I;
- if (MCFragment *Cur = LastValidFragment[Sec])
- I = ++MCSection::iterator(Cur);
- else
- I = Sec->begin();
-
- // Advance the layout position until the fragment is valid.
- while (!isFragmentValid(F)) {
- assert(I != Sec->end() && "Layout bookkeeping error");
- const_cast<MCAsmLayout *>(this)->layoutFragment(&*I);
- ++I;
- }
-}
-
-uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const {
- ensureValid(F);
- assert(F->Offset != ~UINT64_C(0) && "Address not set!");
- return F->Offset;
-}
-
-// Simple getSymbolOffset helper for the non-variable case.
-static bool getLabelOffset(const MCAsmLayout &Layout, const MCSymbol &S,
- bool ReportError, uint64_t &Val) {
- if (!S.getFragment()) {
- if (ReportError)
- report_fatal_error("unable to evaluate offset to undefined symbol '" +
- S.getName() + "'");
- return false;
- }
- Val = Layout.getFragmentOffset(S.getFragment()) + S.getOffset();
- return true;
-}
-
-static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, const MCSymbol &S,
- bool ReportError, uint64_t &Val) {
- if (!S.isVariable())
- return getLabelOffset(Layout, S, ReportError, Val);
-
- // If SD is a variable, evaluate it.
- MCValue Target;
- if (!S.getVariableValue()->evaluateAsValue(Target, Layout))
- report_fatal_error("unable to evaluate offset for variable '" +
- S.getName() + "'");
-
- uint64_t Offset = Target.getConstant();
-
- const MCSymbolRefExpr *A = Target.getSymA();
- if (A) {
- uint64_t ValA;
- if (!getLabelOffset(Layout, A->getSymbol(), ReportError, ValA))
- return false;
- Offset += ValA;
- }
-
- const MCSymbolRefExpr *B = Target.getSymB();
- if (B) {
- uint64_t ValB;
- if (!getLabelOffset(Layout, B->getSymbol(), ReportError, ValB))
- return false;
- Offset -= ValB;
- }
-
- Val = Offset;
- return true;
-}
-
-bool MCAsmLayout::getSymbolOffset(const MCSymbol &S, uint64_t &Val) const {
- return getSymbolOffsetImpl(*this, S, false, Val);
-}
-
-uint64_t MCAsmLayout::getSymbolOffset(const MCSymbol &S) const {
- uint64_t Val;
- getSymbolOffsetImpl(*this, S, true, Val);
- return Val;
-}
-
-const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const {
- if (!Symbol.isVariable())
- return &Symbol;
-
- const MCExpr *Expr = Symbol.getVariableValue();
- MCValue Value;
- if (!Expr->evaluateAsValue(Value, *this)) {
- Assembler.getContext().reportError(
- Expr->getLoc(), "expression could not be evaluated");
- return nullptr;
- }
-
- const MCSymbolRefExpr *RefB = Value.getSymB();
- if (RefB) {
- Assembler.getContext().reportError(
- Expr->getLoc(), Twine("symbol '") + RefB->getSymbol().getName() +
- "' could not be evaluated in a subtraction expression");
- return nullptr;
- }
-
- const MCSymbolRefExpr *A = Value.getSymA();
- if (!A)
- return nullptr;
-
- const MCSymbol &ASym = A->getSymbol();
- const MCAssembler &Asm = getAssembler();
- if (ASym.isCommon()) {
- Asm.getContext().reportError(Expr->getLoc(),
- "Common symbol '" + ASym.getName() +
- "' cannot be used in assignment expr");
- return nullptr;
- }
-
- return &ASym;
-}
-
-uint64_t MCAsmLayout::getSectionAddressSize(const MCSection *Sec) const {
- // The size is the last fragment's end offset.
- const MCFragment &F = Sec->getFragmentList().back();
- return getFragmentOffset(&F) + getAssembler().computeFragmentSize(*this, F);
-}
-
-uint64_t MCAsmLayout::getSectionFileSize(const MCSection *Sec) const {
- // Virtual sections have no file size.
- if (Sec->isVirtualSection())
- return 0;
-
- // Otherwise, the file size is the same as the address space size.
- return getSectionAddressSize(Sec);
-}
-
-uint64_t llvm::computeBundlePadding(const MCAssembler &Assembler,
- const MCEncodedFragment *F,
- uint64_t FOffset, uint64_t FSize) {
- uint64_t BundleSize = Assembler.getBundleAlignSize();
- assert(BundleSize > 0 &&
- "computeBundlePadding should only be called if bundling is enabled");
- uint64_t BundleMask = BundleSize - 1;
- uint64_t OffsetInBundle = FOffset & BundleMask;
- uint64_t EndOfFragment = OffsetInBundle + FSize;
-
- // There are two kinds of bundling restrictions:
- //
- // 1) For alignToBundleEnd(), add padding to ensure that the fragment will
- // *end* on a bundle boundary.
- // 2) Otherwise, check if the fragment would cross a bundle boundary. If it
- // would, add padding until the end of the bundle so that the fragment
- // will start in a new one.
- if (F->alignToBundleEnd()) {
- // Three possibilities here:
- //
- // A) The fragment just happens to end at a bundle boundary, so we're good.
- // B) The fragment ends before the current bundle boundary: pad it just
- // enough to reach the boundary.
- // C) The fragment ends after the current bundle boundary: pad it until it
- // reaches the end of the next bundle boundary.
- //
- // Note: this code could be made shorter with some modulo trickery, but it's
- // intentionally kept in its more explicit form for simplicity.
- if (EndOfFragment == BundleSize)
- return 0;
- else if (EndOfFragment < BundleSize)
- return BundleSize - EndOfFragment;
- else { // EndOfFragment > BundleSize
- return 2 * BundleSize - EndOfFragment;
- }
- } else if (OffsetInBundle > 0 && EndOfFragment > BundleSize)
- return BundleSize - OffsetInBundle;
- else
- return 0;
-}
-
-/* *** */
-
-void ilist_alloc_traits<MCFragment>::deleteNode(MCFragment *V) { V->destroy(); }
-
-MCFragment::~MCFragment() = default;
-
-MCFragment::MCFragment(FragmentType Kind, bool HasInstructions,
- MCSection *Parent)
- : Kind(Kind), HasInstructions(HasInstructions), LayoutOrder(0),
- Parent(Parent), Atom(nullptr), Offset(~UINT64_C(0)) {
- if (Parent && !isDummy())
- Parent->getFragmentList().push_back(this);
-}
-
-void MCFragment::destroy() {
- // First check if we are the sentinal.
- if (Kind == FragmentType(~0)) {
- delete this;
- return;
- }
-
- switch (Kind) {
- case FT_Align:
- delete cast<MCAlignFragment>(this);
- return;
- case FT_Data:
- delete cast<MCDataFragment>(this);
- return;
- case FT_CompactEncodedInst:
- delete cast<MCCompactEncodedInstFragment>(this);
- return;
- case FT_Fill:
- delete cast<MCFillFragment>(this);
- return;
- case FT_Relaxable:
- delete cast<MCRelaxableFragment>(this);
- return;
- case FT_Org:
- delete cast<MCOrgFragment>(this);
- return;
- case FT_Dwarf:
- delete cast<MCDwarfLineAddrFragment>(this);
- return;
- case FT_DwarfFrame:
- delete cast<MCDwarfCallFrameFragment>(this);
- return;
- case FT_LEB:
- delete cast<MCLEBFragment>(this);
- return;
- case FT_Padding:
- delete cast<MCPaddingFragment>(this);
- return;
- case FT_SymbolId:
- delete cast<MCSymbolIdFragment>(this);
- return;
- case FT_CVInlineLines:
- delete cast<MCCVInlineLineTableFragment>(this);
- return;
- case FT_CVDefRange:
- delete cast<MCCVDefRangeFragment>(this);
- return;
- case FT_Dummy:
- delete cast<MCDummyFragment>(this);
- return;
- }
-}
-
-// Debugging methods
-
-namespace llvm {
-
-raw_ostream &operator<<(raw_ostream &OS, const MCFixup &AF) {
- OS << "<MCFixup" << " Offset:" << AF.getOffset()
- << " Value:" << *AF.getValue()
- << " Kind:" << AF.getKind() << ">";
- return OS;
-}
-
-} // end namespace llvm
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void MCFragment::dump() const {
- raw_ostream &OS = errs();
-
- OS << "<";
- switch (getKind()) {
- case MCFragment::FT_Align: OS << "MCAlignFragment"; break;
- case MCFragment::FT_Data: OS << "MCDataFragment"; break;
- case MCFragment::FT_CompactEncodedInst:
- OS << "MCCompactEncodedInstFragment"; break;
- case MCFragment::FT_Fill: OS << "MCFillFragment"; break;
- case MCFragment::FT_Relaxable: OS << "MCRelaxableFragment"; break;
- case MCFragment::FT_Org: OS << "MCOrgFragment"; break;
- case MCFragment::FT_Dwarf: OS << "MCDwarfFragment"; break;
- case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break;
- case MCFragment::FT_LEB: OS << "MCLEBFragment"; break;
- case MCFragment::FT_Padding: OS << "MCPaddingFragment"; break;
- case MCFragment::FT_SymbolId: OS << "MCSymbolIdFragment"; break;
- case MCFragment::FT_CVInlineLines: OS << "MCCVInlineLineTableFragment"; break;
- case MCFragment::FT_CVDefRange: OS << "MCCVDefRangeTableFragment"; break;
- case MCFragment::FT_Dummy: OS << "MCDummyFragment"; break;
- }
-
- OS << "<MCFragment " << (const void *)this << " LayoutOrder:" << LayoutOrder
- << " Offset:" << Offset << " HasInstructions:" << hasInstructions();
- if (const MCEncodedFragment *EF = dyn_cast<MCEncodedFragment>(this))
- OS << " BundlePadding:" << static_cast<unsigned>(EF->getBundlePadding());
- OS << ">";
-
- switch (getKind()) {
- case MCFragment::FT_Align: {
- const MCAlignFragment *AF = cast<MCAlignFragment>(this);
- if (AF->hasEmitNops())
- OS << " (emit nops)";
- OS << "\n ";
- OS << " Alignment:" << AF->getAlignment()
- << " Value:" << AF->getValue() << " ValueSize:" << AF->getValueSize()
- << " MaxBytesToEmit:" << AF->getMaxBytesToEmit() << ">";
- break;
- }
- case MCFragment::FT_Data: {
- const MCDataFragment *DF = cast<MCDataFragment>(this);
- OS << "\n ";
- OS << " Contents:[";
- const SmallVectorImpl<char> &Contents = DF->getContents();
- for (unsigned i = 0, e = Contents.size(); i != e; ++i) {
- if (i) OS << ",";
- OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF);
- }
- OS << "] (" << Contents.size() << " bytes)";
-
- if (DF->fixup_begin() != DF->fixup_end()) {
- OS << ",\n ";
- OS << " Fixups:[";
- for (MCDataFragment::const_fixup_iterator it = DF->fixup_begin(),
- ie = DF->fixup_end(); it != ie; ++it) {
- if (it != DF->fixup_begin()) OS << ",\n ";
- OS << *it;
- }
- OS << "]";
- }
- break;
- }
- case MCFragment::FT_CompactEncodedInst: {
- const MCCompactEncodedInstFragment *CEIF =
- cast<MCCompactEncodedInstFragment>(this);
- OS << "\n ";
- OS << " Contents:[";
- const SmallVectorImpl<char> &Contents = CEIF->getContents();
- for (unsigned i = 0, e = Contents.size(); i != e; ++i) {
- if (i) OS << ",";
- OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF);
- }
- OS << "] (" << Contents.size() << " bytes)";
- break;
- }
- case MCFragment::FT_Fill: {
- const MCFillFragment *FF = cast<MCFillFragment>(this);
- OS << " Value:" << static_cast<unsigned>(FF->getValue())
- << " ValueSize:" << static_cast<unsigned>(FF->getValueSize())
- << " NumValues:" << FF->getNumValues();
- break;
- }
- case MCFragment::FT_Relaxable: {
- const MCRelaxableFragment *F = cast<MCRelaxableFragment>(this);
- OS << "\n ";
- OS << " Inst:";
- F->getInst().dump_pretty(OS);
- break;
- }
- case MCFragment::FT_Org: {
- const MCOrgFragment *OF = cast<MCOrgFragment>(this);
- OS << "\n ";
- OS << " Offset:" << OF->getOffset()
- << " Value:" << static_cast<unsigned>(OF->getValue());
- break;
- }
- case MCFragment::FT_Dwarf: {
- const MCDwarfLineAddrFragment *OF = cast<MCDwarfLineAddrFragment>(this);
- OS << "\n ";
- OS << " AddrDelta:" << OF->getAddrDelta()
- << " LineDelta:" << OF->getLineDelta();
- break;
- }
- case MCFragment::FT_DwarfFrame: {
- const MCDwarfCallFrameFragment *CF = cast<MCDwarfCallFrameFragment>(this);
- OS << "\n ";
- OS << " AddrDelta:" << CF->getAddrDelta();
- break;
- }
- case MCFragment::FT_LEB: {
- const MCLEBFragment *LF = cast<MCLEBFragment>(this);
- OS << "\n ";
- OS << " Value:" << LF->getValue() << " Signed:" << LF->isSigned();
- break;
- }
- case MCFragment::FT_Padding: {
- const MCPaddingFragment *F = cast<MCPaddingFragment>(this);
- OS << "\n ";
- OS << " PaddingPoliciesMask:" << F->getPaddingPoliciesMask()
- << " IsInsertionPoint:" << F->isInsertionPoint()
- << " Size:" << F->getSize();
- OS << "\n ";
- OS << " Inst:";
- F->getInst().dump_pretty(OS);
- OS << " InstSize:" << F->getInstSize();
- OS << "\n ";
- break;
- }
- case MCFragment::FT_SymbolId: {
- const MCSymbolIdFragment *F = cast<MCSymbolIdFragment>(this);
- OS << "\n ";
- OS << " Sym:" << F->getSymbol();
- break;
- }
- case MCFragment::FT_CVInlineLines: {
- const auto *F = cast<MCCVInlineLineTableFragment>(this);
- OS << "\n ";
- OS << " Sym:" << *F->getFnStartSym();
- break;
- }
- case MCFragment::FT_CVDefRange: {
- const auto *F = cast<MCCVDefRangeFragment>(this);
- OS << "\n ";
- for (std::pair<const MCSymbol *, const MCSymbol *> RangeStartEnd :
- F->getRanges()) {
- OS << " RangeStart:" << RangeStartEnd.first;
- OS << " RangeEnd:" << RangeStartEnd.second;
- }
- break;
- }
- case MCFragment::FT_Dummy:
- break;
- }
- OS << ">";
-}
-#endif
diff --git a/contrib/llvm/lib/MC/MCInst.cpp b/contrib/llvm/lib/MC/MCInst.cpp
deleted file mode 100644
index f6f6edee5822..000000000000
--- a/contrib/llvm/lib/MC/MCInst.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-//===- lib/MC/MCInst.cpp - MCInst implementation --------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCInst.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCInstPrinter.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-void MCOperand::print(raw_ostream &OS) const {
- OS << "<MCOperand ";
- if (!isValid())
- OS << "INVALID";
- else if (isReg())
- OS << "Reg:" << getReg();
- else if (isImm())
- OS << "Imm:" << getImm();
- else if (isFPImm())
- OS << "FPImm:" << getFPImm();
- else if (isExpr()) {
- OS << "Expr:(" << *getExpr() << ")";
- } else if (isInst()) {
- OS << "Inst:(" << *getInst() << ")";
- } else
- OS << "UNDEFINED";
- OS << ">";
-}
-
-bool MCOperand::evaluateAsConstantImm(int64_t &Imm) const {
- if (isImm()) {
- Imm = getImm();
- return true;
- }
- return false;
-}
-
-bool MCOperand::isBareSymbolRef() const {
- assert(isExpr() &&
- "isBareSymbolRef expects only expressions");
- const MCExpr *Expr = getExpr();
- MCExpr::ExprKind Kind = getExpr()->getKind();
- return Kind == MCExpr::SymbolRef &&
- cast<MCSymbolRefExpr>(Expr)->getKind() == MCSymbolRefExpr::VK_None;
-}
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void MCOperand::dump() const {
- print(dbgs());
- dbgs() << "\n";
-}
-#endif
-
-void MCInst::print(raw_ostream &OS) const {
- OS << "<MCInst " << getOpcode();
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
- OS << " ";
- getOperand(i).print(OS);
- }
- OS << ">";
-}
-
-void MCInst::dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer,
- StringRef Separator) const {
- StringRef InstName = Printer ? Printer->getOpcodeName(getOpcode()) : "";
- dump_pretty(OS, InstName, Separator);
-}
-
-void MCInst::dump_pretty(raw_ostream &OS, StringRef Name,
- StringRef Separator) const {
- OS << "<MCInst #" << getOpcode();
-
- // Show the instruction opcode name if we have it.
- if (!Name.empty())
- OS << ' ' << Name;
-
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
- OS << Separator;
- getOperand(i).print(OS);
- }
- OS << ">";
-}
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void MCInst::dump() const {
- print(dbgs());
- dbgs() << "\n";
-}
-#endif
diff --git a/contrib/llvm/lib/MC/MCInstPrinter.cpp b/contrib/llvm/lib/MC/MCInstPrinter.cpp
deleted file mode 100644
index 159f4070fe9f..000000000000
--- a/contrib/llvm/lib/MC/MCInstPrinter.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-//===- MCInstPrinter.cpp - Convert an MCInst to target assembly syntax ----===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCInstPrinter.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCInstrInfo.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cinttypes>
-#include <cstdint>
-
-using namespace llvm;
-
-void llvm::dumpBytes(ArrayRef<uint8_t> bytes, raw_ostream &OS) {
- static const char hex_rep[] = "0123456789abcdef";
- bool First = true;
- for (char i: bytes) {
- if (First)
- First = false;
- else
- OS << ' ';
- OS << hex_rep[(i & 0xF0) >> 4];
- OS << hex_rep[i & 0xF];
- }
-}
-
-MCInstPrinter::~MCInstPrinter() = default;
-
-/// getOpcodeName - Return the name of the specified opcode enum (e.g.
-/// "MOV32ri") or empty if we can't resolve it.
-StringRef MCInstPrinter::getOpcodeName(unsigned Opcode) const {
- return MII.getName(Opcode);
-}
-
-void MCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
- llvm_unreachable("Target should implement this");
-}
-
-void MCInstPrinter::printAnnotation(raw_ostream &OS, StringRef Annot) {
- if (!Annot.empty()) {
- if (CommentStream) {
- (*CommentStream) << Annot;
- // By definition (see MCInstPrinter.h), CommentStream must end with
- // a newline after each comment.
- if (Annot.back() != '\n')
- (*CommentStream) << '\n';
- } else
- OS << " " << MAI.getCommentString() << " " << Annot;
- }
-}
-
-/// Utility functions to make adding mark ups simpler.
-StringRef MCInstPrinter::markup(StringRef s) const {
- if (getUseMarkup())
- return s;
- else
- return "";
-}
-StringRef MCInstPrinter::markup(StringRef a, StringRef b) const {
- if (getUseMarkup())
- return a;
- else
- return b;
-}
-
-// For asm-style hex (e.g. 0ffh) the first digit always has to be a number.
-static bool needsLeadingZero(uint64_t Value)
-{
- while (Value)
- {
- uint64_t digit = (Value >> 60) & 0xf;
- if (digit != 0)
- return (digit >= 0xa);
- Value <<= 4;
- }
- return false;
-}
-
-format_object<int64_t> MCInstPrinter::formatDec(int64_t Value) const {
- return format("%" PRId64, Value);
-}
-
-format_object<int64_t> MCInstPrinter::formatHex(int64_t Value) const {
- switch(PrintHexStyle) {
- case HexStyle::C:
- if (Value < 0)
- return format("-0x%" PRIx64, -Value);
- else
- return format("0x%" PRIx64, Value);
- case HexStyle::Asm:
- if (Value < 0) {
- if (needsLeadingZero((uint64_t)(-Value)))
- return format("-0%" PRIx64 "h", -Value);
- else
- return format("-%" PRIx64 "h", -Value);
- } else {
- if (needsLeadingZero((uint64_t)(Value)))
- return format("0%" PRIx64 "h", Value);
- else
- return format("%" PRIx64 "h", Value);
- }
- }
- llvm_unreachable("unsupported print style");
-}
-
-format_object<uint64_t> MCInstPrinter::formatHex(uint64_t Value) const {
- switch(PrintHexStyle) {
- case HexStyle::C:
- return format("0x%" PRIx64, Value);
- case HexStyle::Asm:
- if (needsLeadingZero(Value))
- return format("0%" PRIx64 "h", Value);
- else
- return format("%" PRIx64 "h", Value);
- }
- llvm_unreachable("unsupported print style");
-}
diff --git a/contrib/llvm/lib/MC/MCInstrAnalysis.cpp b/contrib/llvm/lib/MC/MCInstrAnalysis.cpp
deleted file mode 100644
index eca87f940bf5..000000000000
--- a/contrib/llvm/lib/MC/MCInstrAnalysis.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-//===- MCInstrAnalysis.cpp - InstrDesc target hooks -----------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCInstrAnalysis.h"
-
-#include "llvm/ADT/APInt.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCInstrDesc.h"
-#include "llvm/MC/MCInstrInfo.h"
-#include <cstdint>
-
-using namespace llvm;
-
-bool MCInstrAnalysis::clearsSuperRegisters(const MCRegisterInfo &MRI,
- const MCInst &Inst,
- APInt &Writes) const {
- Writes.clearAllBits();
- return false;
-}
-
-bool MCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr,
- uint64_t Size, uint64_t &Target) const {
- if (Inst.getNumOperands() == 0 ||
- Info->get(Inst.getOpcode()).OpInfo[0].OperandType != MCOI::OPERAND_PCREL)
- return false;
-
- int64_t Imm = Inst.getOperand(0).getImm();
- Target = Addr+Size+Imm;
- return true;
-}
diff --git a/contrib/llvm/lib/MC/MCInstrDesc.cpp b/contrib/llvm/lib/MC/MCInstrDesc.cpp
deleted file mode 100644
index d54aeba89edc..000000000000
--- a/contrib/llvm/lib/MC/MCInstrDesc.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-//===------ llvm/MC/MCInstrDesc.cpp- Instruction Descriptors --------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines methods on the MCOperandInfo and MCInstrDesc classes, which
-// are used to describe target instructions and their operands.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCInstrDesc.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCSubtargetInfo.h"
-
-using namespace llvm;
-
-bool MCInstrDesc::getDeprecatedInfo(MCInst &MI, const MCSubtargetInfo &STI,
- std::string &Info) const {
- if (ComplexDeprecationInfo)
- return ComplexDeprecationInfo(MI, STI, Info);
- if (DeprecatedFeature != -1 && STI.getFeatureBits()[DeprecatedFeature]) {
- // FIXME: it would be nice to include the subtarget feature here.
- Info = "deprecated";
- return true;
- }
- return false;
-}
-bool MCInstrDesc::mayAffectControlFlow(const MCInst &MI,
- const MCRegisterInfo &RI) const {
- if (isBranch() || isCall() || isReturn() || isIndirectBranch())
- return true;
- unsigned PC = RI.getProgramCounter();
- if (PC == 0)
- return false;
- if (hasDefOfPhysReg(MI, PC, RI))
- return true;
- return false;
-}
-
-bool MCInstrDesc::hasImplicitDefOfPhysReg(unsigned Reg,
- const MCRegisterInfo *MRI) const {
- if (const MCPhysReg *ImpDefs = ImplicitDefs)
- for (; *ImpDefs; ++ImpDefs)
- if (*ImpDefs == Reg || (MRI && MRI->isSubRegister(Reg, *ImpDefs)))
- return true;
- return false;
-}
-
-bool MCInstrDesc::hasDefOfPhysReg(const MCInst &MI, unsigned Reg,
- const MCRegisterInfo &RI) const {
- for (int i = 0, e = NumDefs; i != e; ++i)
- if (MI.getOperand(i).isReg() &&
- RI.isSubRegisterEq(Reg, MI.getOperand(i).getReg()))
- return true;
- if (variadicOpsAreDefs())
- for (int i = NumOperands - 1, e = MI.getNumOperands(); i != e; ++i)
- if (MI.getOperand(i).isReg() &&
- RI.isSubRegisterEq(Reg, MI.getOperand(i).getReg()))
- return true;
- return hasImplicitDefOfPhysReg(Reg, &RI);
-}
diff --git a/contrib/llvm/lib/MC/MCLabel.cpp b/contrib/llvm/lib/MC/MCLabel.cpp
deleted file mode 100644
index 66ee73c5bbb3..000000000000
--- a/contrib/llvm/lib/MC/MCLabel.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-//===- lib/MC/MCLabel.cpp - MCLabel implementation ------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCLabel.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-void MCLabel::print(raw_ostream &OS) const {
- OS << '"' << getInstance() << '"';
-}
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void MCLabel::dump() const {
- print(dbgs());
-}
-#endif
diff --git a/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp b/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp
deleted file mode 100644
index 9ab321872b11..000000000000
--- a/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-//===- llvm/MC/MCLinkerOptimizationHint.cpp ----- LOH handling ------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCLinkerOptimizationHint.h"
-#include "llvm/MC/MCAsmLayout.h"
-#include "llvm/MC/MCMachObjectWriter.h"
-#include "llvm/Support/LEB128.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cstddef>
-#include <cstdint>
-
-using namespace llvm;
-
-// Each LOH is composed by, in this order (each field is encoded using ULEB128):
-// - Its kind.
-// - Its number of arguments (let say N).
-// - Its arg1.
-// - ...
-// - Its argN.
-// <arg1> to <argN> are absolute addresses in the object file, i.e.,
-// relative addresses from the beginning of the object file.
-void MCLOHDirective::emit_impl(raw_ostream &OutStream,
- const MachObjectWriter &ObjWriter,
- const MCAsmLayout &Layout) const {
- encodeULEB128(Kind, OutStream);
- encodeULEB128(Args.size(), OutStream);
- for (const MCSymbol *Arg : Args)
- encodeULEB128(ObjWriter.getSymbolAddress(*Arg, Layout), OutStream);
-}
-
-void MCLOHDirective::emit(MachObjectWriter &ObjWriter,
- const MCAsmLayout &Layout) const {
- raw_ostream &OutStream = ObjWriter.W.OS;
- emit_impl(OutStream, ObjWriter, Layout);
-}
-
-uint64_t MCLOHDirective::getEmitSize(const MachObjectWriter &ObjWriter,
- const MCAsmLayout &Layout) const {
- class raw_counting_ostream : public raw_ostream {
- uint64_t Count = 0;
-
- void write_impl(const char *, size_t size) override { Count += size; }
-
- uint64_t current_pos() const override { return Count; }
-
- public:
- raw_counting_ostream() = default;
- ~raw_counting_ostream() override { flush(); }
- };
-
- raw_counting_ostream OutStream;
- emit_impl(OutStream, ObjWriter, Layout);
- return OutStream.tell();
-}
diff --git a/contrib/llvm/lib/MC/MCMachOStreamer.cpp b/contrib/llvm/lib/MC/MCMachOStreamer.cpp
deleted file mode 100644
index 613f255a4ea4..000000000000
--- a/contrib/llvm/lib/MC/MCMachOStreamer.cpp
+++ /dev/null
@@ -1,519 +0,0 @@
-//===- MCMachOStreamer.cpp - MachO Streamer -------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCCodeEmitter.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDirectives.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCFixup.h"
-#include "llvm/MC/MCFragment.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCLinkerOptimizationHint.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCObjectStreamer.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCSectionMachO.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCSymbolMachO.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/TargetRegistry.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <vector>
-
-using namespace llvm;
-
-namespace {
-
-class MCMachOStreamer : public MCObjectStreamer {
-private:
- /// LabelSections - true if each section change should emit a linker local
- /// label for use in relocations for assembler local references. Obviates the
- /// need for local relocations. False by default.
- bool LabelSections;
-
- bool DWARFMustBeAtTheEnd;
- bool CreatedADWARFSection;
-
- /// HasSectionLabel - map of which sections have already had a non-local
- /// label emitted to them. Used so we don't emit extraneous linker local
- /// labels in the middle of the section.
- DenseMap<const MCSection*, bool> HasSectionLabel;
-
- void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) override;
-
- void EmitDataRegion(DataRegionData::KindTy Kind);
- void EmitDataRegionEnd();
-
-public:
- MCMachOStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
- std::unique_ptr<MCObjectWriter> OW,
- std::unique_ptr<MCCodeEmitter> Emitter,
- bool DWARFMustBeAtTheEnd, bool label)
- : MCObjectStreamer(Context, std::move(MAB), std::move(OW),
- std::move(Emitter)),
- LabelSections(label), DWARFMustBeAtTheEnd(DWARFMustBeAtTheEnd),
- CreatedADWARFSection(false) {}
-
- /// state management
- void reset() override {
- CreatedADWARFSection = false;
- HasSectionLabel.clear();
- MCObjectStreamer::reset();
- }
-
- /// @name MCStreamer Interface
- /// @{
-
- void ChangeSection(MCSection *Sect, const MCExpr *Subsect) override;
- void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
- void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
- void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) override;
- void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
- void EmitLinkerOptions(ArrayRef<std::string> Options) override;
- void EmitDataRegion(MCDataRegionType Kind) override;
- void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
- unsigned Update, VersionTuple SDKVersion) override;
- void EmitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
- unsigned Update, VersionTuple SDKVersion) override;
- void EmitThumbFunc(MCSymbol *Func) override;
- bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
- void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
- void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
- unsigned ByteAlignment) override;
-
- void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
- unsigned ByteAlignment) override;
- void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
- uint64_t Size = 0, unsigned ByteAlignment = 0,
- SMLoc Loc = SMLoc()) override;
- void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
- unsigned ByteAlignment = 0) override;
-
- void EmitIdent(StringRef IdentString) override {
- llvm_unreachable("macho doesn't support this directive");
- }
-
- void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override {
- getAssembler().getLOHContainer().addDirective(Kind, Args);
- }
-
- void FinishImpl() override;
-};
-
-} // end anonymous namespace.
-
-static bool canGoAfterDWARF(const MCSectionMachO &MSec) {
- // These sections are created by the assembler itself after the end of
- // the .s file.
- StringRef SegName = MSec.getSegmentName();
- StringRef SecName = MSec.getSectionName();
-
- if (SegName == "__LD" && SecName == "__compact_unwind")
- return true;
-
- if (SegName == "__IMPORT") {
- if (SecName == "__jump_table")
- return true;
-
- if (SecName == "__pointers")
- return true;
- }
-
- if (SegName == "__TEXT" && SecName == "__eh_frame")
- return true;
-
- if (SegName == "__DATA" && (SecName == "__nl_symbol_ptr" ||
- SecName == "__thread_ptr"))
- return true;
-
- return false;
-}
-
-void MCMachOStreamer::ChangeSection(MCSection *Section,
- const MCExpr *Subsection) {
- // Change the section normally.
- bool Created = changeSectionImpl(Section, Subsection);
- const MCSectionMachO &MSec = *cast<MCSectionMachO>(Section);
- StringRef SegName = MSec.getSegmentName();
- if (SegName == "__DWARF")
- CreatedADWARFSection = true;
- else if (Created && DWARFMustBeAtTheEnd && !canGoAfterDWARF(MSec))
- assert(!CreatedADWARFSection && "Creating regular section after DWARF");
-
- // Output a linker-local symbol so we don't need section-relative local
- // relocations. The linker hates us when we do that.
- if (LabelSections && !HasSectionLabel[Section] &&
- !Section->getBeginSymbol()) {
- MCSymbol *Label = getContext().createLinkerPrivateTempSymbol();
- Section->setBeginSymbol(Label);
- HasSectionLabel[Section] = true;
- }
-}
-
-void MCMachOStreamer::EmitEHSymAttributes(const MCSymbol *Symbol,
- MCSymbol *EHSymbol) {
- getAssembler().registerSymbol(*Symbol);
- if (Symbol->isExternal())
- EmitSymbolAttribute(EHSymbol, MCSA_Global);
- if (cast<MCSymbolMachO>(Symbol)->isWeakDefinition())
- EmitSymbolAttribute(EHSymbol, MCSA_WeakDefinition);
- if (Symbol->isPrivateExtern())
- EmitSymbolAttribute(EHSymbol, MCSA_PrivateExtern);
-}
-
-void MCMachOStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
- // We have to create a new fragment if this is an atom defining symbol,
- // fragments cannot span atoms.
- if (getAssembler().isSymbolLinkerVisible(*Symbol))
- insert(new MCDataFragment());
-
- MCObjectStreamer::EmitLabel(Symbol, Loc);
-
- // This causes the reference type flag to be cleared. Darwin 'as' was "trying"
- // to clear the weak reference and weak definition bits too, but the
- // implementation was buggy. For now we just try to match 'as', for
- // diffability.
- //
- // FIXME: Cleanup this code, these bits should be emitted based on semantic
- // properties, not on the order of definition, etc.
- cast<MCSymbolMachO>(Symbol)->clearReferenceType();
-}
-
-void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
- MCValue Res;
-
- if (Value->evaluateAsRelocatable(Res, nullptr, nullptr)) {
- if (const MCSymbolRefExpr *SymAExpr = Res.getSymA()) {
- const MCSymbol &SymA = SymAExpr->getSymbol();
- if (!Res.getSymB() && (SymA.getName() == "" || Res.getConstant() != 0))
- cast<MCSymbolMachO>(Symbol)->setAltEntry();
- }
- }
- MCObjectStreamer::EmitAssignment(Symbol, Value);
-}
-
-void MCMachOStreamer::EmitDataRegion(DataRegionData::KindTy Kind) {
- // Create a temporary label to mark the start of the data region.
- MCSymbol *Start = getContext().createTempSymbol();
- EmitLabel(Start);
- // Record the region for the object writer to use.
- DataRegionData Data = { Kind, Start, nullptr };
- std::vector<DataRegionData> &Regions = getAssembler().getDataRegions();
- Regions.push_back(Data);
-}
-
-void MCMachOStreamer::EmitDataRegionEnd() {
- std::vector<DataRegionData> &Regions = getAssembler().getDataRegions();
- assert(!Regions.empty() && "Mismatched .end_data_region!");
- DataRegionData &Data = Regions.back();
- assert(!Data.End && "Mismatched .end_data_region!");
- // Create a temporary label to mark the end of the data region.
- Data.End = getContext().createTempSymbol();
- EmitLabel(Data.End);
-}
-
-void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
- // Let the target do whatever target specific stuff it needs to do.
- getAssembler().getBackend().handleAssemblerFlag(Flag);
- // Do any generic stuff we need to do.
- switch (Flag) {
- case MCAF_SyntaxUnified: return; // no-op here.
- case MCAF_Code16: return; // Change parsing mode; no-op here.
- case MCAF_Code32: return; // Change parsing mode; no-op here.
- case MCAF_Code64: return; // Change parsing mode; no-op here.
- case MCAF_SubsectionsViaSymbols:
- getAssembler().setSubsectionsViaSymbols(true);
- return;
- }
-}
-
-void MCMachOStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) {
- getAssembler().getLinkerOptions().push_back(Options);
-}
-
-void MCMachOStreamer::EmitDataRegion(MCDataRegionType Kind) {
- switch (Kind) {
- case MCDR_DataRegion:
- EmitDataRegion(DataRegionData::Data);
- return;
- case MCDR_DataRegionJT8:
- EmitDataRegion(DataRegionData::JumpTable8);
- return;
- case MCDR_DataRegionJT16:
- EmitDataRegion(DataRegionData::JumpTable16);
- return;
- case MCDR_DataRegionJT32:
- EmitDataRegion(DataRegionData::JumpTable32);
- return;
- case MCDR_DataRegionEnd:
- EmitDataRegionEnd();
- return;
- }
-}
-
-void MCMachOStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major,
- unsigned Minor, unsigned Update,
- VersionTuple SDKVersion) {
- getAssembler().setVersionMin(Kind, Major, Minor, Update, SDKVersion);
-}
-
-void MCMachOStreamer::EmitBuildVersion(unsigned Platform, unsigned Major,
- unsigned Minor, unsigned Update,
- VersionTuple SDKVersion) {
- getAssembler().setBuildVersion((MachO::PlatformType)Platform, Major, Minor,
- Update, SDKVersion);
-}
-
-void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) {
- // Remember that the function is a thumb function. Fixup and relocation
- // values will need adjusted.
- getAssembler().setIsThumbFunc(Symbol);
- cast<MCSymbolMachO>(Symbol)->setThumbFunc();
-}
-
-bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Sym,
- MCSymbolAttr Attribute) {
- MCSymbolMachO *Symbol = cast<MCSymbolMachO>(Sym);
-
- // Indirect symbols are handled differently, to match how 'as' handles
- // them. This makes writing matching .o files easier.
- if (Attribute == MCSA_IndirectSymbol) {
- // Note that we intentionally cannot use the symbol data here; this is
- // important for matching the string table that 'as' generates.
- IndirectSymbolData ISD;
- ISD.Symbol = Symbol;
- ISD.Section = getCurrentSectionOnly();
- getAssembler().getIndirectSymbols().push_back(ISD);
- return true;
- }
-
- // Adding a symbol attribute always introduces the symbol, note that an
- // important side effect of calling registerSymbol here is to register
- // the symbol with the assembler.
- getAssembler().registerSymbol(*Symbol);
-
- // The implementation of symbol attributes is designed to match 'as', but it
- // leaves much to desired. It doesn't really make sense to arbitrarily add and
- // remove flags, but 'as' allows this (in particular, see .desc).
- //
- // In the future it might be worth trying to make these operations more well
- // defined.
- switch (Attribute) {
- case MCSA_Invalid:
- case MCSA_ELF_TypeFunction:
- case MCSA_ELF_TypeIndFunction:
- case MCSA_ELF_TypeObject:
- case MCSA_ELF_TypeTLS:
- case MCSA_ELF_TypeCommon:
- case MCSA_ELF_TypeNoType:
- case MCSA_ELF_TypeGnuUniqueObject:
- case MCSA_Hidden:
- case MCSA_IndirectSymbol:
- case MCSA_Internal:
- case MCSA_Protected:
- case MCSA_Weak:
- case MCSA_Local:
- return false;
-
- case MCSA_Global:
- Symbol->setExternal(true);
- // This effectively clears the undefined lazy bit, in Darwin 'as', although
- // it isn't very consistent because it implements this as part of symbol
- // lookup.
- //
- // FIXME: Cleanup this code, these bits should be emitted based on semantic
- // properties, not on the order of definition, etc.
- Symbol->setReferenceTypeUndefinedLazy(false);
- break;
-
- case MCSA_LazyReference:
- // FIXME: This requires -dynamic.
- Symbol->setNoDeadStrip();
- if (Symbol->isUndefined())
- Symbol->setReferenceTypeUndefinedLazy(true);
- break;
-
- // Since .reference sets the no dead strip bit, it is equivalent to
- // .no_dead_strip in practice.
- case MCSA_Reference:
- case MCSA_NoDeadStrip:
- Symbol->setNoDeadStrip();
- break;
-
- case MCSA_SymbolResolver:
- Symbol->setSymbolResolver();
- break;
-
- case MCSA_AltEntry:
- Symbol->setAltEntry();
- break;
-
- case MCSA_PrivateExtern:
- Symbol->setExternal(true);
- Symbol->setPrivateExtern(true);
- break;
-
- case MCSA_WeakReference:
- // FIXME: This requires -dynamic.
- if (Symbol->isUndefined())
- Symbol->setWeakReference();
- break;
-
- case MCSA_WeakDefinition:
- // FIXME: 'as' enforces that this is defined and global. The manual claims
- // it has to be in a coalesced section, but this isn't enforced.
- Symbol->setWeakDefinition();
- break;
-
- case MCSA_WeakDefAutoPrivate:
- Symbol->setWeakDefinition();
- Symbol->setWeakReference();
- break;
-
- case MCSA_Cold:
- Symbol->setCold();
- break;
- }
-
- return true;
-}
-
-void MCMachOStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
- // Encode the 'desc' value into the lowest implementation defined bits.
- getAssembler().registerSymbol(*Symbol);
- cast<MCSymbolMachO>(Symbol)->setDesc(DescValue);
-}
-
-void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
- unsigned ByteAlignment) {
- // FIXME: Darwin 'as' does appear to allow redef of a .comm by itself.
- assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
-
- getAssembler().registerSymbol(*Symbol);
- Symbol->setExternal(true);
- Symbol->setCommon(Size, ByteAlignment);
-}
-
-void MCMachOStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
- unsigned ByteAlignment) {
- // '.lcomm' is equivalent to '.zerofill'.
- return EmitZerofill(getContext().getObjectFileInfo()->getDataBSSSection(),
- Symbol, Size, ByteAlignment);
-}
-
-void MCMachOStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment,
- SMLoc Loc) {
- // On darwin all virtual sections have zerofill type. Disallow the usage of
- // .zerofill in non-virtual functions. If something similar is needed, use
- // .space or .zero.
- if (!Section->isVirtualSection()) {
- getContext().reportError(
- Loc, "The usage of .zerofill is restricted to sections of "
- "ZEROFILL type. Use .zero or .space instead.");
- return; // Early returning here shouldn't harm. EmitZeros should work on any
- // section.
- }
-
- PushSection();
- SwitchSection(Section);
-
- // The symbol may not be present, which only creates the section.
- if (Symbol) {
- EmitValueToAlignment(ByteAlignment, 0, 1, 0);
- EmitLabel(Symbol);
- EmitZeros(Size);
- }
- PopSection();
-}
-
-// This should always be called with the thread local bss section. Like the
-// .zerofill directive this doesn't actually switch sections on us.
-void MCMachOStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment) {
- EmitZerofill(Section, Symbol, Size, ByteAlignment);
-}
-
-void MCMachOStreamer::EmitInstToData(const MCInst &Inst,
- const MCSubtargetInfo &STI) {
- MCDataFragment *DF = getOrCreateDataFragment();
-
- SmallVector<MCFixup, 4> Fixups;
- SmallString<256> Code;
- raw_svector_ostream VecOS(Code);
- getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
-
- // Add the fixups and data.
- for (MCFixup &Fixup : Fixups) {
- Fixup.setOffset(Fixup.getOffset() + DF->getContents().size());
- DF->getFixups().push_back(Fixup);
- }
- DF->setHasInstructions(STI);
- DF->getContents().append(Code.begin(), Code.end());
-}
-
-void MCMachOStreamer::FinishImpl() {
- EmitFrames(&getAssembler().getBackend());
-
- // We have to set the fragment atom associations so we can relax properly for
- // Mach-O.
-
- // First, scan the symbol table to build a lookup table from fragments to
- // defining symbols.
- DenseMap<const MCFragment *, const MCSymbol *> DefiningSymbolMap;
- for (const MCSymbol &Symbol : getAssembler().symbols()) {
- if (getAssembler().isSymbolLinkerVisible(Symbol) && Symbol.isInSection() &&
- !Symbol.isVariable()) {
- // An atom defining symbol should never be internal to a fragment.
- assert(Symbol.getOffset() == 0 &&
- "Invalid offset in atom defining symbol!");
- DefiningSymbolMap[Symbol.getFragment()] = &Symbol;
- }
- }
-
- // Set the fragment atom associations by tracking the last seen atom defining
- // symbol.
- for (MCSection &Sec : getAssembler()) {
- const MCSymbol *CurrentAtom = nullptr;
- for (MCFragment &Frag : Sec) {
- if (const MCSymbol *Symbol = DefiningSymbolMap.lookup(&Frag))
- CurrentAtom = Symbol;
- Frag.setAtom(CurrentAtom);
- }
- }
-
- this->MCObjectStreamer::FinishImpl();
-}
-
-MCStreamer *llvm::createMachOStreamer(MCContext &Context,
- std::unique_ptr<MCAsmBackend> &&MAB,
- std::unique_ptr<MCObjectWriter> &&OW,
- std::unique_ptr<MCCodeEmitter> &&CE,
- bool RelaxAll, bool DWARFMustBeAtTheEnd,
- bool LabelSections) {
- MCMachOStreamer *S =
- new MCMachOStreamer(Context, std::move(MAB), std::move(OW), std::move(CE),
- DWARFMustBeAtTheEnd, LabelSections);
- const Triple &Target = Context.getObjectFileInfo()->getTargetTriple();
- S->EmitVersionForTarget(Target, Context.getObjectFileInfo()->getSDKVersion());
- if (RelaxAll)
- S->getAssembler().setRelaxAll(true);
- return S;
-}
diff --git a/contrib/llvm/lib/MC/MCMachObjectTargetWriter.cpp b/contrib/llvm/lib/MC/MCMachObjectTargetWriter.cpp
deleted file mode 100644
index a57b8a7ac0ff..000000000000
--- a/contrib/llvm/lib/MC/MCMachObjectTargetWriter.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-//===- MCMachObjectTargetWriter.cpp - Mach-O Target Writer Subclass -------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCMachObjectWriter.h"
-
-using namespace llvm;
-
-MCMachObjectTargetWriter::MCMachObjectTargetWriter(bool Is64Bit_,
- uint32_t CPUType_,
- uint32_t CPUSubtype_)
- : Is64Bit(Is64Bit_), CPUType(CPUType_), CPUSubtype(CPUSubtype_) {}
-
-MCMachObjectTargetWriter::~MCMachObjectTargetWriter() = default;
diff --git a/contrib/llvm/lib/MC/MCNullStreamer.cpp b/contrib/llvm/lib/MC/MCNullStreamer.cpp
deleted file mode 100644
index 8452317c8c6b..000000000000
--- a/contrib/llvm/lib/MC/MCNullStreamer.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-//===- lib/MC/MCNullStreamer.cpp - Dummy Streamer Implementation ----------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbol.h"
-
-using namespace llvm;
-
-namespace {
-
- class MCNullStreamer : public MCStreamer {
- public:
- MCNullStreamer(MCContext &Context) : MCStreamer(Context) {}
-
- /// @name MCStreamer Interface
- /// @{
-
- bool hasRawTextSupport() const override { return true; }
- void EmitRawTextImpl(StringRef String) override {}
-
- bool EmitSymbolAttribute(MCSymbol *Symbol,
- MCSymbolAttr Attribute) override {
- return true;
- }
-
- void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
- unsigned ByteAlignment) override {}
- void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
- uint64_t Size = 0, unsigned ByteAlignment = 0,
- SMLoc Loc = SMLoc()) override {}
- void EmitGPRel32Value(const MCExpr *Value) override {}
- void BeginCOFFSymbolDef(const MCSymbol *Symbol) override {}
- void EmitCOFFSymbolStorageClass(int StorageClass) override {}
- void EmitCOFFSymbolType(int Type) override {}
- void EndCOFFSymbolDef() override {}
- };
-
-}
-
-MCStreamer *llvm::createNullStreamer(MCContext &Context) {
- return new MCNullStreamer(Context);
-}
diff --git a/contrib/llvm/lib/MC/MCObjectFileInfo.cpp b/contrib/llvm/lib/MC/MCObjectFileInfo.cpp
deleted file mode 100644
index 9f555abe1404..000000000000
--- a/contrib/llvm/lib/MC/MCObjectFileInfo.cpp
+++ /dev/null
@@ -1,867 +0,0 @@
-//===-- MCObjectFileInfo.cpp - Object File Information --------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/BinaryFormat/COFF.h"
-#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCSectionCOFF.h"
-#include "llvm/MC/MCSectionELF.h"
-#include "llvm/MC/MCSectionMachO.h"
-#include "llvm/MC/MCSectionWasm.h"
-#include "llvm/MC/MCSectionXCOFF.h"
-
-using namespace llvm;
-
-static bool useCompactUnwind(const Triple &T) {
- // Only on darwin.
- if (!T.isOSDarwin())
- return false;
-
- // aarch64 always has it.
- if (T.getArch() == Triple::aarch64)
- return true;
-
- // armv7k always has it.
- if (T.isWatchABI())
- return true;
-
- // Use it on newer version of OS X.
- if (T.isMacOSX() && !T.isMacOSXVersionLT(10, 6))
- return true;
-
- // And the iOS simulator.
- if (T.isiOS() &&
- (T.getArch() == Triple::x86_64 || T.getArch() == Triple::x86))
- return true;
-
- return false;
-}
-
-void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
- // MachO
- SupportsWeakOmittedEHFrame = false;
-
- EHFrameSection = Ctx->getMachOSection(
- "__TEXT", "__eh_frame",
- MachO::S_COALESCED | MachO::S_ATTR_NO_TOC |
- MachO::S_ATTR_STRIP_STATIC_SYMS | MachO::S_ATTR_LIVE_SUPPORT,
- SectionKind::getReadOnly());
-
- if (T.isOSDarwin() && T.getArch() == Triple::aarch64)
- SupportsCompactUnwindWithoutEHFrame = true;
-
- if (T.isWatchABI())
- OmitDwarfIfHaveCompactUnwind = true;
-
- FDECFIEncoding = dwarf::DW_EH_PE_pcrel;
-
- // .comm doesn't support alignment before Leopard.
- if (T.isMacOSX() && T.isMacOSXVersionLT(10, 5))
- CommDirectiveSupportsAlignment = false;
-
- TextSection // .text
- = Ctx->getMachOSection("__TEXT", "__text",
- MachO::S_ATTR_PURE_INSTRUCTIONS,
- SectionKind::getText());
- DataSection // .data
- = Ctx->getMachOSection("__DATA", "__data", 0, SectionKind::getData());
-
- // BSSSection might not be expected initialized on msvc.
- BSSSection = nullptr;
-
- TLSDataSection // .tdata
- = Ctx->getMachOSection("__DATA", "__thread_data",
- MachO::S_THREAD_LOCAL_REGULAR,
- SectionKind::getData());
- TLSBSSSection // .tbss
- = Ctx->getMachOSection("__DATA", "__thread_bss",
- MachO::S_THREAD_LOCAL_ZEROFILL,
- SectionKind::getThreadBSS());
-
- // TODO: Verify datarel below.
- TLSTLVSection // .tlv
- = Ctx->getMachOSection("__DATA", "__thread_vars",
- MachO::S_THREAD_LOCAL_VARIABLES,
- SectionKind::getData());
-
- TLSThreadInitSection = Ctx->getMachOSection(
- "__DATA", "__thread_init", MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS,
- SectionKind::getData());
-
- CStringSection // .cstring
- = Ctx->getMachOSection("__TEXT", "__cstring",
- MachO::S_CSTRING_LITERALS,
- SectionKind::getMergeable1ByteCString());
- UStringSection
- = Ctx->getMachOSection("__TEXT","__ustring", 0,
- SectionKind::getMergeable2ByteCString());
- FourByteConstantSection // .literal4
- = Ctx->getMachOSection("__TEXT", "__literal4",
- MachO::S_4BYTE_LITERALS,
- SectionKind::getMergeableConst4());
- EightByteConstantSection // .literal8
- = Ctx->getMachOSection("__TEXT", "__literal8",
- MachO::S_8BYTE_LITERALS,
- SectionKind::getMergeableConst8());
-
- SixteenByteConstantSection // .literal16
- = Ctx->getMachOSection("__TEXT", "__literal16",
- MachO::S_16BYTE_LITERALS,
- SectionKind::getMergeableConst16());
-
- ReadOnlySection // .const
- = Ctx->getMachOSection("__TEXT", "__const", 0,
- SectionKind::getReadOnly());
-
- // If the target is not powerpc, map the coal sections to the non-coal
- // sections.
- //
- // "__TEXT/__textcoal_nt" => section "__TEXT/__text"
- // "__TEXT/__const_coal" => section "__TEXT/__const"
- // "__DATA/__datacoal_nt" => section "__DATA/__data"
- Triple::ArchType ArchTy = T.getArch();
-
- ConstDataSection // .const_data
- = Ctx->getMachOSection("__DATA", "__const", 0,
- SectionKind::getReadOnlyWithRel());
-
- if (ArchTy == Triple::ppc || ArchTy == Triple::ppc64) {
- TextCoalSection
- = Ctx->getMachOSection("__TEXT", "__textcoal_nt",
- MachO::S_COALESCED |
- MachO::S_ATTR_PURE_INSTRUCTIONS,
- SectionKind::getText());
- ConstTextCoalSection
- = Ctx->getMachOSection("__TEXT", "__const_coal",
- MachO::S_COALESCED,
- SectionKind::getReadOnly());
- DataCoalSection = Ctx->getMachOSection(
- "__DATA", "__datacoal_nt", MachO::S_COALESCED, SectionKind::getData());
- ConstDataCoalSection = DataCoalSection;
- } else {
- TextCoalSection = TextSection;
- ConstTextCoalSection = ReadOnlySection;
- DataCoalSection = DataSection;
- ConstDataCoalSection = ConstDataSection;
- }
-
- DataCommonSection
- = Ctx->getMachOSection("__DATA","__common",
- MachO::S_ZEROFILL,
- SectionKind::getBSS());
- DataBSSSection
- = Ctx->getMachOSection("__DATA","__bss", MachO::S_ZEROFILL,
- SectionKind::getBSS());
-
-
- LazySymbolPointerSection
- = Ctx->getMachOSection("__DATA", "__la_symbol_ptr",
- MachO::S_LAZY_SYMBOL_POINTERS,
- SectionKind::getMetadata());
- NonLazySymbolPointerSection
- = Ctx->getMachOSection("__DATA", "__nl_symbol_ptr",
- MachO::S_NON_LAZY_SYMBOL_POINTERS,
- SectionKind::getMetadata());
-
- ThreadLocalPointerSection
- = Ctx->getMachOSection("__DATA", "__thread_ptr",
- MachO::S_THREAD_LOCAL_VARIABLE_POINTERS,
- SectionKind::getMetadata());
-
- // Exception Handling.
- LSDASection = Ctx->getMachOSection("__TEXT", "__gcc_except_tab", 0,
- SectionKind::getReadOnlyWithRel());
-
- COFFDebugSymbolsSection = nullptr;
- COFFDebugTypesSection = nullptr;
- COFFGlobalTypeHashesSection = nullptr;
-
- if (useCompactUnwind(T)) {
- CompactUnwindSection =
- Ctx->getMachOSection("__LD", "__compact_unwind", MachO::S_ATTR_DEBUG,
- SectionKind::getReadOnly());
-
- if (T.getArch() == Triple::x86_64 || T.getArch() == Triple::x86)
- CompactUnwindDwarfEHFrameOnly = 0x04000000; // UNWIND_X86_64_MODE_DWARF
- else if (T.getArch() == Triple::aarch64)
- CompactUnwindDwarfEHFrameOnly = 0x03000000; // UNWIND_ARM64_MODE_DWARF
- else if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
- CompactUnwindDwarfEHFrameOnly = 0x04000000; // UNWIND_ARM_MODE_DWARF
- }
-
- // Debug Information.
- DwarfDebugNamesSection =
- Ctx->getMachOSection("__DWARF", "__debug_names", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata(), "debug_names_begin");
- DwarfAccelNamesSection =
- Ctx->getMachOSection("__DWARF", "__apple_names", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata(), "names_begin");
- DwarfAccelObjCSection =
- Ctx->getMachOSection("__DWARF", "__apple_objc", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata(), "objc_begin");
- // 16 character section limit...
- DwarfAccelNamespaceSection =
- Ctx->getMachOSection("__DWARF", "__apple_namespac", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata(), "namespac_begin");
- DwarfAccelTypesSection =
- Ctx->getMachOSection("__DWARF", "__apple_types", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata(), "types_begin");
-
- DwarfSwiftASTSection =
- Ctx->getMachOSection("__DWARF", "__swift_ast", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata());
-
- DwarfAbbrevSection =
- Ctx->getMachOSection("__DWARF", "__debug_abbrev", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata(), "section_abbrev");
- DwarfInfoSection =
- Ctx->getMachOSection("__DWARF", "__debug_info", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata(), "section_info");
- DwarfLineSection =
- Ctx->getMachOSection("__DWARF", "__debug_line", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata(), "section_line");
- DwarfLineStrSection =
- Ctx->getMachOSection("__DWARF", "__debug_line_str", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata(), "section_line_str");
- DwarfFrameSection =
- Ctx->getMachOSection("__DWARF", "__debug_frame", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata());
- DwarfPubNamesSection =
- Ctx->getMachOSection("__DWARF", "__debug_pubnames", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata());
- DwarfPubTypesSection =
- Ctx->getMachOSection("__DWARF", "__debug_pubtypes", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata());
- DwarfGnuPubNamesSection =
- Ctx->getMachOSection("__DWARF", "__debug_gnu_pubn", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata());
- DwarfGnuPubTypesSection =
- Ctx->getMachOSection("__DWARF", "__debug_gnu_pubt", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata());
- DwarfStrSection =
- Ctx->getMachOSection("__DWARF", "__debug_str", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata(), "info_string");
- DwarfStrOffSection =
- Ctx->getMachOSection("__DWARF", "__debug_str_offs", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata(), "section_str_off");
- DwarfAddrSection =
- Ctx->getMachOSection("__DWARF", "__debug_addr", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata(), "section_info");
- DwarfLocSection =
- Ctx->getMachOSection("__DWARF", "__debug_loc", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata(), "section_debug_loc");
- DwarfLoclistsSection =
- Ctx->getMachOSection("__DWARF", "__debug_loclists", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata(), "section_debug_loc");
-
- DwarfARangesSection =
- Ctx->getMachOSection("__DWARF", "__debug_aranges", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata());
- DwarfRangesSection =
- Ctx->getMachOSection("__DWARF", "__debug_ranges", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata(), "debug_range");
- DwarfRnglistsSection =
- Ctx->getMachOSection("__DWARF", "__debug_rnglists", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata(), "debug_range");
- DwarfMacinfoSection =
- Ctx->getMachOSection("__DWARF", "__debug_macinfo", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata(), "debug_macinfo");
- DwarfDebugInlineSection =
- Ctx->getMachOSection("__DWARF", "__debug_inlined", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata());
- DwarfCUIndexSection =
- Ctx->getMachOSection("__DWARF", "__debug_cu_index", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata());
- DwarfTUIndexSection =
- Ctx->getMachOSection("__DWARF", "__debug_tu_index", MachO::S_ATTR_DEBUG,
- SectionKind::getMetadata());
- StackMapSection = Ctx->getMachOSection("__LLVM_STACKMAPS", "__llvm_stackmaps",
- 0, SectionKind::getMetadata());
-
- FaultMapSection = Ctx->getMachOSection("__LLVM_FAULTMAPS", "__llvm_faultmaps",
- 0, SectionKind::getMetadata());
-
- RemarksSection = Ctx->getMachOSection(
- "__LLVM", "__remarks", MachO::S_ATTR_DEBUG, SectionKind::getMetadata());
-
- TLSExtraDataSection = TLSTLVSection;
-}
-
-void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
- switch (T.getArch()) {
- case Triple::mips:
- case Triple::mipsel:
- case Triple::mips64:
- case Triple::mips64el:
- FDECFIEncoding = Ctx->getAsmInfo()->getCodePointerSize() == 4
- ? dwarf::DW_EH_PE_sdata4
- : dwarf::DW_EH_PE_sdata8;
- break;
- case Triple::ppc64:
- case Triple::ppc64le:
- case Triple::x86_64:
- FDECFIEncoding = dwarf::DW_EH_PE_pcrel |
- (Large ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4);
- break;
- case Triple::bpfel:
- case Triple::bpfeb:
- FDECFIEncoding = dwarf::DW_EH_PE_sdata8;
- break;
- case Triple::hexagon:
- FDECFIEncoding =
- PositionIndependent ? dwarf::DW_EH_PE_pcrel : dwarf::DW_EH_PE_absptr;
- break;
- default:
- FDECFIEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
- break;
- }
-
- unsigned EHSectionType = T.getArch() == Triple::x86_64
- ? ELF::SHT_X86_64_UNWIND
- : ELF::SHT_PROGBITS;
-
- // Solaris requires different flags for .eh_frame to seemingly every other
- // platform.
- unsigned EHSectionFlags = ELF::SHF_ALLOC;
- if (T.isOSSolaris() && T.getArch() != Triple::x86_64)
- EHSectionFlags |= ELF::SHF_WRITE;
-
- // ELF
- BSSSection = Ctx->getELFSection(".bss", ELF::SHT_NOBITS,
- ELF::SHF_WRITE | ELF::SHF_ALLOC);
-
- TextSection = Ctx->getELFSection(".text", ELF::SHT_PROGBITS,
- ELF::SHF_EXECINSTR | ELF::SHF_ALLOC);
-
- DataSection = Ctx->getELFSection(".data", ELF::SHT_PROGBITS,
- ELF::SHF_WRITE | ELF::SHF_ALLOC);
-
- ReadOnlySection =
- Ctx->getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
-
- TLSDataSection =
- Ctx->getELFSection(".tdata", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC | ELF::SHF_TLS | ELF::SHF_WRITE);
-
- TLSBSSSection = Ctx->getELFSection(
- ".tbss", ELF::SHT_NOBITS, ELF::SHF_ALLOC | ELF::SHF_TLS | ELF::SHF_WRITE);
-
- DataRelROSection = Ctx->getELFSection(".data.rel.ro", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC | ELF::SHF_WRITE);
-
- MergeableConst4Section =
- Ctx->getELFSection(".rodata.cst4", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC | ELF::SHF_MERGE, 4, "");
-
- MergeableConst8Section =
- Ctx->getELFSection(".rodata.cst8", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC | ELF::SHF_MERGE, 8, "");
-
- MergeableConst16Section =
- Ctx->getELFSection(".rodata.cst16", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC | ELF::SHF_MERGE, 16, "");
-
- MergeableConst32Section =
- Ctx->getELFSection(".rodata.cst32", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC | ELF::SHF_MERGE, 32, "");
-
- // Exception Handling Sections.
-
- // FIXME: We're emitting LSDA info into a readonly section on ELF, even though
- // it contains relocatable pointers. In PIC mode, this is probably a big
- // runtime hit for C++ apps. Either the contents of the LSDA need to be
- // adjusted or this should be a data section.
- LSDASection = Ctx->getELFSection(".gcc_except_table", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC);
-
- COFFDebugSymbolsSection = nullptr;
- COFFDebugTypesSection = nullptr;
-
- unsigned DebugSecType = ELF::SHT_PROGBITS;
-
- // MIPS .debug_* sections should have SHT_MIPS_DWARF section type
- // to distinguish among sections contain DWARF and ECOFF debug formats.
- // Sections with ECOFF debug format are obsoleted and marked by SHT_PROGBITS.
- if (T.isMIPS())
- DebugSecType = ELF::SHT_MIPS_DWARF;
-
- // Debug Info Sections.
- DwarfAbbrevSection =
- Ctx->getELFSection(".debug_abbrev", DebugSecType, 0);
- DwarfInfoSection = Ctx->getELFSection(".debug_info", DebugSecType, 0);
- DwarfLineSection = Ctx->getELFSection(".debug_line", DebugSecType, 0);
- DwarfLineStrSection =
- Ctx->getELFSection(".debug_line_str", DebugSecType,
- ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, "");
- DwarfFrameSection = Ctx->getELFSection(".debug_frame", DebugSecType, 0);
- DwarfPubNamesSection =
- Ctx->getELFSection(".debug_pubnames", DebugSecType, 0);
- DwarfPubTypesSection =
- Ctx->getELFSection(".debug_pubtypes", DebugSecType, 0);
- DwarfGnuPubNamesSection =
- Ctx->getELFSection(".debug_gnu_pubnames", DebugSecType, 0);
- DwarfGnuPubTypesSection =
- Ctx->getELFSection(".debug_gnu_pubtypes", DebugSecType, 0);
- DwarfStrSection =
- Ctx->getELFSection(".debug_str", DebugSecType,
- ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, "");
- DwarfLocSection = Ctx->getELFSection(".debug_loc", DebugSecType, 0);
- DwarfARangesSection =
- Ctx->getELFSection(".debug_aranges", DebugSecType, 0);
- DwarfRangesSection =
- Ctx->getELFSection(".debug_ranges", DebugSecType, 0);
- DwarfMacinfoSection =
- Ctx->getELFSection(".debug_macinfo", DebugSecType, 0);
-
- // DWARF5 Experimental Debug Info
-
- // Accelerator Tables
- DwarfDebugNamesSection =
- Ctx->getELFSection(".debug_names", ELF::SHT_PROGBITS, 0);
- DwarfAccelNamesSection =
- Ctx->getELFSection(".apple_names", ELF::SHT_PROGBITS, 0);
- DwarfAccelObjCSection =
- Ctx->getELFSection(".apple_objc", ELF::SHT_PROGBITS, 0);
- DwarfAccelNamespaceSection =
- Ctx->getELFSection(".apple_namespaces", ELF::SHT_PROGBITS, 0);
- DwarfAccelTypesSection =
- Ctx->getELFSection(".apple_types", ELF::SHT_PROGBITS, 0);
-
- // String Offset and Address Sections
- DwarfStrOffSection =
- Ctx->getELFSection(".debug_str_offsets", DebugSecType, 0);
- DwarfAddrSection = Ctx->getELFSection(".debug_addr", DebugSecType, 0);
- DwarfRnglistsSection = Ctx->getELFSection(".debug_rnglists", DebugSecType, 0);
- DwarfLoclistsSection = Ctx->getELFSection(".debug_loclists", DebugSecType, 0);
-
- // Fission Sections
- DwarfInfoDWOSection =
- Ctx->getELFSection(".debug_info.dwo", DebugSecType, ELF::SHF_EXCLUDE);
- DwarfTypesDWOSection =
- Ctx->getELFSection(".debug_types.dwo", DebugSecType, ELF::SHF_EXCLUDE);
- DwarfAbbrevDWOSection =
- Ctx->getELFSection(".debug_abbrev.dwo", DebugSecType, ELF::SHF_EXCLUDE);
- DwarfStrDWOSection = Ctx->getELFSection(
- ".debug_str.dwo", DebugSecType,
- ELF::SHF_MERGE | ELF::SHF_STRINGS | ELF::SHF_EXCLUDE, 1, "");
- DwarfLineDWOSection =
- Ctx->getELFSection(".debug_line.dwo", DebugSecType, ELF::SHF_EXCLUDE);
- DwarfLocDWOSection =
- Ctx->getELFSection(".debug_loc.dwo", DebugSecType, ELF::SHF_EXCLUDE);
- DwarfStrOffDWOSection = Ctx->getELFSection(".debug_str_offsets.dwo",
- DebugSecType, ELF::SHF_EXCLUDE);
- DwarfRnglistsDWOSection =
- Ctx->getELFSection(".debug_rnglists.dwo", DebugSecType, ELF::SHF_EXCLUDE);
-
- // DWP Sections
- DwarfCUIndexSection =
- Ctx->getELFSection(".debug_cu_index", DebugSecType, 0);
- DwarfTUIndexSection =
- Ctx->getELFSection(".debug_tu_index", DebugSecType, 0);
-
- StackMapSection =
- Ctx->getELFSection(".llvm_stackmaps", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
-
- FaultMapSection =
- Ctx->getELFSection(".llvm_faultmaps", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
-
- EHFrameSection =
- Ctx->getELFSection(".eh_frame", EHSectionType, EHSectionFlags);
-
- StackSizesSection = Ctx->getELFSection(".stack_sizes", ELF::SHT_PROGBITS, 0);
-
- RemarksSection =
- Ctx->getELFSection(".remarks", ELF::SHT_PROGBITS, ELF::SHF_EXCLUDE);
-}
-
-void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
- EHFrameSection =
- Ctx->getCOFFSection(".eh_frame", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getData());
-
- // Set the `IMAGE_SCN_MEM_16BIT` flag when compiling for thumb mode. This is
- // used to indicate to the linker that the text segment contains thumb instructions
- // and to set the ISA selection bit for calls accordingly.
- const bool IsThumb = T.getArch() == Triple::thumb;
-
- CommDirectiveSupportsAlignment = true;
-
- // COFF
- BSSSection = Ctx->getCOFFSection(
- ".bss", COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE,
- SectionKind::getBSS());
- TextSection = Ctx->getCOFFSection(
- ".text",
- (IsThumb ? COFF::IMAGE_SCN_MEM_16BIT : (COFF::SectionCharacteristics)0) |
- COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getText());
- DataSection = Ctx->getCOFFSection(
- ".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ |
- COFF::IMAGE_SCN_MEM_WRITE,
- SectionKind::getData());
- ReadOnlySection = Ctx->getCOFFSection(
- ".rdata", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getReadOnly());
-
- if (T.getArch() == Triple::x86_64 || T.getArch() == Triple::aarch64) {
- // On Windows 64 with SEH, the LSDA is emitted into the .xdata section
- LSDASection = nullptr;
- } else {
- LSDASection = Ctx->getCOFFSection(".gcc_except_table",
- COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getReadOnly());
- }
-
- // Debug info.
- COFFDebugSymbolsSection =
- Ctx->getCOFFSection(".debug$S", (COFF::IMAGE_SCN_MEM_DISCARDABLE |
- COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ),
- SectionKind::getMetadata());
- COFFDebugTypesSection =
- Ctx->getCOFFSection(".debug$T", (COFF::IMAGE_SCN_MEM_DISCARDABLE |
- COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ),
- SectionKind::getMetadata());
- COFFGlobalTypeHashesSection = Ctx->getCOFFSection(
- ".debug$H",
- (COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ),
- SectionKind::getMetadata());
-
- DwarfAbbrevSection = Ctx->getCOFFSection(
- ".debug_abbrev",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "section_abbrev");
- DwarfInfoSection = Ctx->getCOFFSection(
- ".debug_info",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "section_info");
- DwarfLineSection = Ctx->getCOFFSection(
- ".debug_line",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "section_line");
- DwarfLineStrSection = Ctx->getCOFFSection(
- ".debug_line_str",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "section_line_str");
- DwarfFrameSection = Ctx->getCOFFSection(
- ".debug_frame",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata());
- DwarfPubNamesSection = Ctx->getCOFFSection(
- ".debug_pubnames",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata());
- DwarfPubTypesSection = Ctx->getCOFFSection(
- ".debug_pubtypes",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata());
- DwarfGnuPubNamesSection = Ctx->getCOFFSection(
- ".debug_gnu_pubnames",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata());
- DwarfGnuPubTypesSection = Ctx->getCOFFSection(
- ".debug_gnu_pubtypes",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata());
- DwarfStrSection = Ctx->getCOFFSection(
- ".debug_str",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "info_string");
- DwarfStrOffSection = Ctx->getCOFFSection(
- ".debug_str_offsets",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "section_str_off");
- DwarfLocSection = Ctx->getCOFFSection(
- ".debug_loc",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "section_debug_loc");
- DwarfARangesSection = Ctx->getCOFFSection(
- ".debug_aranges",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata());
- DwarfRangesSection = Ctx->getCOFFSection(
- ".debug_ranges",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "debug_range");
- DwarfMacinfoSection = Ctx->getCOFFSection(
- ".debug_macinfo",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "debug_macinfo");
- DwarfInfoDWOSection = Ctx->getCOFFSection(
- ".debug_info.dwo",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "section_info_dwo");
- DwarfTypesDWOSection = Ctx->getCOFFSection(
- ".debug_types.dwo",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "section_types_dwo");
- DwarfAbbrevDWOSection = Ctx->getCOFFSection(
- ".debug_abbrev.dwo",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "section_abbrev_dwo");
- DwarfStrDWOSection = Ctx->getCOFFSection(
- ".debug_str.dwo",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "skel_string");
- DwarfLineDWOSection = Ctx->getCOFFSection(
- ".debug_line.dwo",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata());
- DwarfLocDWOSection = Ctx->getCOFFSection(
- ".debug_loc.dwo",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "skel_loc");
- DwarfStrOffDWOSection = Ctx->getCOFFSection(
- ".debug_str_offsets.dwo",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "section_str_off_dwo");
- DwarfAddrSection = Ctx->getCOFFSection(
- ".debug_addr",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "addr_sec");
- DwarfCUIndexSection = Ctx->getCOFFSection(
- ".debug_cu_index",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata());
- DwarfTUIndexSection = Ctx->getCOFFSection(
- ".debug_tu_index",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata());
- DwarfDebugNamesSection = Ctx->getCOFFSection(
- ".debug_names",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "debug_names_begin");
- DwarfAccelNamesSection = Ctx->getCOFFSection(
- ".apple_names",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "names_begin");
- DwarfAccelNamespaceSection = Ctx->getCOFFSection(
- ".apple_namespaces",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "namespac_begin");
- DwarfAccelTypesSection = Ctx->getCOFFSection(
- ".apple_types",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "types_begin");
- DwarfAccelObjCSection = Ctx->getCOFFSection(
- ".apple_objc",
- COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata(), "objc_begin");
-
- DrectveSection = Ctx->getCOFFSection(
- ".drectve", COFF::IMAGE_SCN_LNK_INFO | COFF::IMAGE_SCN_LNK_REMOVE,
- SectionKind::getMetadata());
-
- PDataSection = Ctx->getCOFFSection(
- ".pdata", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getData());
-
- XDataSection = Ctx->getCOFFSection(
- ".xdata", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getData());
-
- SXDataSection = Ctx->getCOFFSection(".sxdata", COFF::IMAGE_SCN_LNK_INFO,
- SectionKind::getMetadata());
-
- GFIDsSection = Ctx->getCOFFSection(".gfids$y",
- COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getMetadata());
-
- TLSDataSection = Ctx->getCOFFSection(
- ".tls$", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ |
- COFF::IMAGE_SCN_MEM_WRITE,
- SectionKind::getData());
-
- StackMapSection = Ctx->getCOFFSection(".llvm_stackmaps",
- COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getReadOnly());
-}
-
-void MCObjectFileInfo::initWasmMCObjectFileInfo(const Triple &T) {
- TextSection = Ctx->getWasmSection(".text", SectionKind::getText());
- DataSection = Ctx->getWasmSection(".data", SectionKind::getData());
-
- DwarfLineSection =
- Ctx->getWasmSection(".debug_line", SectionKind::getMetadata());
- DwarfLineStrSection =
- Ctx->getWasmSection(".debug_line_str", SectionKind::getMetadata());
- DwarfStrSection =
- Ctx->getWasmSection(".debug_str", SectionKind::getMetadata());
- DwarfLocSection =
- Ctx->getWasmSection(".debug_loc", SectionKind::getMetadata());
- DwarfAbbrevSection =
- Ctx->getWasmSection(".debug_abbrev", SectionKind::getMetadata());
- DwarfARangesSection = Ctx->getWasmSection(".debug_aranges", SectionKind::getMetadata());
- DwarfRangesSection =
- Ctx->getWasmSection(".debug_ranges", SectionKind::getMetadata());
- DwarfMacinfoSection =
- Ctx->getWasmSection(".debug_macinfo", SectionKind::getMetadata());
- DwarfAddrSection = Ctx->getWasmSection(".debug_addr", SectionKind::getMetadata());
- DwarfCUIndexSection = Ctx->getWasmSection(".debug_cu_index", SectionKind::getMetadata());
- DwarfTUIndexSection = Ctx->getWasmSection(".debug_tu_index", SectionKind::getMetadata());
- DwarfInfoSection =
- Ctx->getWasmSection(".debug_info", SectionKind::getMetadata());
- DwarfFrameSection = Ctx->getWasmSection(".debug_frame", SectionKind::getMetadata());
- DwarfPubNamesSection = Ctx->getWasmSection(".debug_pubnames", SectionKind::getMetadata());
- DwarfPubTypesSection = Ctx->getWasmSection(".debug_pubtypes", SectionKind::getMetadata());
-
- // Wasm use data section for LSDA.
- // TODO Consider putting each function's exception table in a separate
- // section, as in -function-sections, to facilitate lld's --gc-section.
- LSDASection = Ctx->getWasmSection(".rodata.gcc_except_table",
- SectionKind::getReadOnlyWithRel());
-
- // TODO: Define more sections.
-}
-
-void MCObjectFileInfo::initXCOFFMCObjectFileInfo(const Triple &T) {
- // The default csect for program code. Functions without a specified section
- // get placed into this csect. The choice of csect name is not a property of
- // the ABI or object file format. For example, the XL compiler uses an unnamed
- // csect for program code.
- TextSection = Ctx->getXCOFFSection(
- ".text", XCOFF::StorageMappingClass::XMC_PR, SectionKind::getText());
-}
-
-void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC,
- MCContext &ctx,
- bool LargeCodeModel) {
- PositionIndependent = PIC;
- Ctx = &ctx;
-
- // Common.
- CommDirectiveSupportsAlignment = true;
- SupportsWeakOmittedEHFrame = true;
- SupportsCompactUnwindWithoutEHFrame = false;
- OmitDwarfIfHaveCompactUnwind = false;
-
- FDECFIEncoding = dwarf::DW_EH_PE_absptr;
-
- CompactUnwindDwarfEHFrameOnly = 0;
-
- EHFrameSection = nullptr; // Created on demand.
- CompactUnwindSection = nullptr; // Used only by selected targets.
- DwarfAccelNamesSection = nullptr; // Used only by selected targets.
- DwarfAccelObjCSection = nullptr; // Used only by selected targets.
- DwarfAccelNamespaceSection = nullptr; // Used only by selected targets.
- DwarfAccelTypesSection = nullptr; // Used only by selected targets.
-
- TT = TheTriple;
-
- switch (TT.getObjectFormat()) {
- case Triple::MachO:
- Env = IsMachO;
- initMachOMCObjectFileInfo(TT);
- break;
- case Triple::COFF:
- if (!TT.isOSWindows())
- report_fatal_error(
- "Cannot initialize MC for non-Windows COFF object files.");
-
- Env = IsCOFF;
- initCOFFMCObjectFileInfo(TT);
- break;
- case Triple::ELF:
- Env = IsELF;
- initELFMCObjectFileInfo(TT, LargeCodeModel);
- break;
- case Triple::Wasm:
- Env = IsWasm;
- initWasmMCObjectFileInfo(TT);
- break;
- case Triple::XCOFF:
- Env = IsXCOFF;
- initXCOFFMCObjectFileInfo(TT);
- break;
- case Triple::UnknownObjectFormat:
- report_fatal_error("Cannot initialize MC for unknown object file format.");
- break;
- }
-}
-
-MCSection *MCObjectFileInfo::getDwarfComdatSection(const char *Name,
- uint64_t Hash) const {
- switch (TT.getObjectFormat()) {
- case Triple::ELF:
- return Ctx->getELFSection(Name, ELF::SHT_PROGBITS, ELF::SHF_GROUP, 0,
- utostr(Hash));
- case Triple::MachO:
- case Triple::COFF:
- case Triple::Wasm:
- case Triple::XCOFF:
- case Triple::UnknownObjectFormat:
- report_fatal_error("Cannot get DWARF comdat section for this object file "
- "format: not implemented.");
- break;
- }
- llvm_unreachable("Unknown ObjectFormatType");
-}
-
-MCSection *
-MCObjectFileInfo::getStackSizesSection(const MCSection &TextSec) const {
- if (Env != IsELF)
- return StackSizesSection;
-
- const MCSectionELF &ElfSec = static_cast<const MCSectionELF &>(TextSec);
- unsigned Flags = ELF::SHF_LINK_ORDER;
- StringRef GroupName;
- if (const MCSymbol *Group = ElfSec.getGroup()) {
- GroupName = Group->getName();
- Flags |= ELF::SHF_GROUP;
- }
-
- const MCSymbol *Link = TextSec.getBeginSymbol();
- auto It = StackSizesUniquing.insert({Link, StackSizesUniquing.size()});
- unsigned UniqueID = It.first->second;
-
- return Ctx->getELFSection(".stack_sizes", ELF::SHT_PROGBITS, Flags, 0,
- GroupName, UniqueID, cast<MCSymbolELF>(Link));
-}
diff --git a/contrib/llvm/lib/MC/MCObjectStreamer.cpp b/contrib/llvm/lib/MC/MCObjectStreamer.cpp
deleted file mode 100644
index 1587d8498666..000000000000
--- a/contrib/llvm/lib/MC/MCObjectStreamer.cpp
+++ /dev/null
@@ -1,731 +0,0 @@
-//===- lib/MC/MCObjectStreamer.cpp - Object File MCStreamer Interface -----===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCObjectStreamer.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCCodeEmitter.h"
-#include "llvm/MC/MCCodeView.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDwarf.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/SourceMgr.h"
-using namespace llvm;
-
-MCObjectStreamer::MCObjectStreamer(MCContext &Context,
- std::unique_ptr<MCAsmBackend> TAB,
- std::unique_ptr<MCObjectWriter> OW,
- std::unique_ptr<MCCodeEmitter> Emitter)
- : MCStreamer(Context),
- Assembler(llvm::make_unique<MCAssembler>(
- Context, std::move(TAB), std::move(Emitter), std::move(OW))),
- EmitEHFrame(true), EmitDebugFrame(false) {}
-
-MCObjectStreamer::~MCObjectStreamer() {}
-
-// AssemblerPtr is used for evaluation of expressions and causes
-// difference between asm and object outputs. Return nullptr to in
-// inline asm mode to limit divergence to assembly inputs.
-MCAssembler *MCObjectStreamer::getAssemblerPtr() {
- if (getUseAssemblerInfoForParsing())
- return Assembler.get();
- return nullptr;
-}
-
-void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) {
- if (PendingLabels.empty())
- return;
- if (!F) {
- F = new MCDataFragment();
- MCSection *CurSection = getCurrentSectionOnly();
- CurSection->getFragmentList().insert(CurInsertionPoint, F);
- F->setParent(CurSection);
- }
- for (MCSymbol *Sym : PendingLabels) {
- Sym->setFragment(F);
- Sym->setOffset(FOffset);
- }
- PendingLabels.clear();
-}
-
-// When fixup's offset is a forward declared label, e.g.:
-//
-// .reloc 1f, R_MIPS_JALR, foo
-// 1: nop
-//
-// postpone adding it to Fixups vector until the label is defined and its offset
-// is known.
-void MCObjectStreamer::resolvePendingFixups() {
- for (PendingMCFixup &PendingFixup : PendingFixups) {
- if (!PendingFixup.Sym || PendingFixup.Sym->isUndefined ()) {
- getContext().reportError(PendingFixup.Fixup.getLoc(),
- "unresolved relocation offset");
- continue;
- }
- flushPendingLabels(PendingFixup.DF, PendingFixup.DF->getContents().size());
- PendingFixup.Fixup.setOffset(PendingFixup.Sym->getOffset());
- PendingFixup.DF->getFixups().push_back(PendingFixup.Fixup);
- }
- PendingFixups.clear();
-}
-
-// As a compile-time optimization, avoid allocating and evaluating an MCExpr
-// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment.
-static Optional<uint64_t>
-absoluteSymbolDiff(MCAssembler &Asm, const MCSymbol *Hi, const MCSymbol *Lo) {
- assert(Hi && Lo);
- if (Asm.getBackendPtr()->requiresDiffExpressionRelocations())
- return None;
-
- if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() ||
- Hi->isVariable() || Lo->isVariable())
- return None;
-
- return Hi->getOffset() - Lo->getOffset();
-}
-
-void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,
- const MCSymbol *Lo,
- unsigned Size) {
- if (Optional<uint64_t> Diff = absoluteSymbolDiff(getAssembler(), Hi, Lo)) {
- EmitIntValue(*Diff, Size);
- return;
- }
- MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size);
-}
-
-void MCObjectStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
- const MCSymbol *Lo) {
- if (Optional<uint64_t> Diff = absoluteSymbolDiff(getAssembler(), Hi, Lo)) {
- EmitULEB128IntValue(*Diff);
- return;
- }
- MCStreamer::emitAbsoluteSymbolDiffAsULEB128(Hi, Lo);
-}
-
-void MCObjectStreamer::reset() {
- if (Assembler)
- Assembler->reset();
- CurInsertionPoint = MCSection::iterator();
- EmitEHFrame = true;
- EmitDebugFrame = false;
- PendingLabels.clear();
- MCStreamer::reset();
-}
-
-void MCObjectStreamer::EmitFrames(MCAsmBackend *MAB) {
- if (!getNumFrameInfos())
- return;
-
- if (EmitEHFrame)
- MCDwarfFrameEmitter::Emit(*this, MAB, true);
-
- if (EmitDebugFrame)
- MCDwarfFrameEmitter::Emit(*this, MAB, false);
-}
-
-MCFragment *MCObjectStreamer::getCurrentFragment() const {
- assert(getCurrentSectionOnly() && "No current section!");
-
- if (CurInsertionPoint != getCurrentSectionOnly()->getFragmentList().begin())
- return &*std::prev(CurInsertionPoint);
-
- return nullptr;
-}
-
-static bool CanReuseDataFragment(const MCDataFragment &F,
- const MCAssembler &Assembler,
- const MCSubtargetInfo *STI) {
- if (!F.hasInstructions())
- return true;
- // When bundling is enabled, we don't want to add data to a fragment that
- // already has instructions (see MCELFStreamer::EmitInstToData for details)
- if (Assembler.isBundlingEnabled())
- return Assembler.getRelaxAll();
- // If the subtarget is changed mid fragment we start a new fragment to record
- // the new STI.
- return !STI || F.getSubtargetInfo() == STI;
-}
-
-MCDataFragment *
-MCObjectStreamer::getOrCreateDataFragment(const MCSubtargetInfo *STI) {
- MCDataFragment *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment());
- if (!F || !CanReuseDataFragment(*F, *Assembler, STI)) {
- F = new MCDataFragment();
- insert(F);
- }
- return F;
-}
-
-MCPaddingFragment *MCObjectStreamer::getOrCreatePaddingFragment() {
- MCPaddingFragment *F =
- dyn_cast_or_null<MCPaddingFragment>(getCurrentFragment());
- if (!F) {
- F = new MCPaddingFragment();
- insert(F);
- }
- return F;
-}
-
-void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) {
- Assembler->registerSymbol(Sym);
-}
-
-void MCObjectStreamer::EmitCFISections(bool EH, bool Debug) {
- MCStreamer::EmitCFISections(EH, Debug);
- EmitEHFrame = EH;
- EmitDebugFrame = Debug;
-}
-
-void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
- SMLoc Loc) {
- MCStreamer::EmitValueImpl(Value, Size, Loc);
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
-
- MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
-
- // Avoid fixups when possible.
- int64_t AbsValue;
- if (Value->evaluateAsAbsolute(AbsValue, getAssemblerPtr())) {
- if (!isUIntN(8 * Size, AbsValue) && !isIntN(8 * Size, AbsValue)) {
- getContext().reportError(
- Loc, "value evaluated as " + Twine(AbsValue) + " is out of range.");
- return;
- }
- EmitIntValue(AbsValue, Size);
- return;
- }
- DF->getFixups().push_back(
- MCFixup::create(DF->getContents().size(), Value,
- MCFixup::getKindForSize(Size, false), Loc));
- DF->getContents().resize(DF->getContents().size() + Size, 0);
-}
-
-MCSymbol *MCObjectStreamer::EmitCFILabel() {
- MCSymbol *Label = getContext().createTempSymbol("cfi", true);
- EmitLabel(Label);
- return Label;
-}
-
-void MCObjectStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
- // We need to create a local symbol to avoid relocations.
- Frame.Begin = getContext().createTempSymbol();
- EmitLabel(Frame.Begin);
-}
-
-void MCObjectStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
- Frame.End = getContext().createTempSymbol();
- EmitLabel(Frame.End);
-}
-
-void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
- MCStreamer::EmitLabel(Symbol, Loc);
-
- getAssembler().registerSymbol(*Symbol);
-
- // If there is a current fragment, mark the symbol as pointing into it.
- // Otherwise queue the label and set its fragment pointer when we emit the
- // next fragment.
- auto *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment());
- if (F && !(getAssembler().isBundlingEnabled() &&
- getAssembler().getRelaxAll())) {
- Symbol->setFragment(F);
- Symbol->setOffset(F->getContents().size());
- } else {
- PendingLabels.push_back(Symbol);
- }
-}
-
-void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F) {
- MCStreamer::EmitLabel(Symbol, Loc);
- getAssembler().registerSymbol(*Symbol);
- auto *DF = dyn_cast_or_null<MCDataFragment>(F);
- if (DF)
- Symbol->setFragment(F);
- else
- PendingLabels.push_back(Symbol);
-}
-
-void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) {
- int64_t IntValue;
- if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) {
- EmitULEB128IntValue(IntValue);
- return;
- }
- insert(new MCLEBFragment(*Value, false));
-}
-
-void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value) {
- int64_t IntValue;
- if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) {
- EmitSLEB128IntValue(IntValue);
- return;
- }
- insert(new MCLEBFragment(*Value, true));
-}
-
-void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias,
- const MCSymbol *Symbol) {
- report_fatal_error("This file format doesn't support weak aliases.");
-}
-
-void MCObjectStreamer::ChangeSection(MCSection *Section,
- const MCExpr *Subsection) {
- changeSectionImpl(Section, Subsection);
-}
-
-bool MCObjectStreamer::changeSectionImpl(MCSection *Section,
- const MCExpr *Subsection) {
- assert(Section && "Cannot switch to a null section!");
- flushPendingLabels(nullptr);
- getContext().clearDwarfLocSeen();
-
- bool Created = getAssembler().registerSection(*Section);
-
- int64_t IntSubsection = 0;
- if (Subsection &&
- !Subsection->evaluateAsAbsolute(IntSubsection, getAssemblerPtr()))
- report_fatal_error("Cannot evaluate subsection number");
- if (IntSubsection < 0 || IntSubsection > 8192)
- report_fatal_error("Subsection number out of range");
- CurInsertionPoint =
- Section->getSubsectionInsertionPoint(unsigned(IntSubsection));
- return Created;
-}
-
-void MCObjectStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
- getAssembler().registerSymbol(*Symbol);
- MCStreamer::EmitAssignment(Symbol, Value);
-}
-
-bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) const {
- return Sec.hasInstructions();
-}
-
-void MCObjectStreamer::EmitInstruction(const MCInst &Inst,
- const MCSubtargetInfo &STI) {
- getAssembler().getBackend().handleCodePaddingInstructionBegin(Inst);
- EmitInstructionImpl(Inst, STI);
- getAssembler().getBackend().handleCodePaddingInstructionEnd(Inst);
-}
-
-void MCObjectStreamer::EmitInstructionImpl(const MCInst &Inst,
- const MCSubtargetInfo &STI) {
- MCStreamer::EmitInstruction(Inst, STI);
-
- MCSection *Sec = getCurrentSectionOnly();
- Sec->setHasInstructions(true);
-
- // Now that a machine instruction has been assembled into this section, make
- // a line entry for any .loc directive that has been seen.
- MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
-
- // If this instruction doesn't need relaxation, just emit it as data.
- MCAssembler &Assembler = getAssembler();
- if (!Assembler.getBackend().mayNeedRelaxation(Inst, STI)) {
- EmitInstToData(Inst, STI);
- return;
- }
-
- // Otherwise, relax and emit it as data if either:
- // - The RelaxAll flag was passed
- // - Bundling is enabled and this instruction is inside a bundle-locked
- // group. We want to emit all such instructions into the same data
- // fragment.
- if (Assembler.getRelaxAll() ||
- (Assembler.isBundlingEnabled() && Sec->isBundleLocked())) {
- MCInst Relaxed;
- getAssembler().getBackend().relaxInstruction(Inst, STI, Relaxed);
- while (getAssembler().getBackend().mayNeedRelaxation(Relaxed, STI))
- getAssembler().getBackend().relaxInstruction(Relaxed, STI, Relaxed);
- EmitInstToData(Relaxed, STI);
- return;
- }
-
- // Otherwise emit to a separate fragment.
- EmitInstToFragment(Inst, STI);
-}
-
-void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst,
- const MCSubtargetInfo &STI) {
- if (getAssembler().getRelaxAll() && getAssembler().isBundlingEnabled())
- llvm_unreachable("All instructions should have already been relaxed");
-
- // Always create a new, separate fragment here, because its size can change
- // during relaxation.
- MCRelaxableFragment *IF = new MCRelaxableFragment(Inst, STI);
- insert(IF);
-
- SmallString<128> Code;
- raw_svector_ostream VecOS(Code);
- getAssembler().getEmitter().encodeInstruction(Inst, VecOS, IF->getFixups(),
- STI);
- IF->getContents().append(Code.begin(), Code.end());
-}
-
-#ifndef NDEBUG
-static const char *const BundlingNotImplementedMsg =
- "Aligned bundling is not implemented for this object format";
-#endif
-
-void MCObjectStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
- llvm_unreachable(BundlingNotImplementedMsg);
-}
-
-void MCObjectStreamer::EmitBundleLock(bool AlignToEnd) {
- llvm_unreachable(BundlingNotImplementedMsg);
-}
-
-void MCObjectStreamer::EmitBundleUnlock() {
- llvm_unreachable(BundlingNotImplementedMsg);
-}
-
-void MCObjectStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
- unsigned Column, unsigned Flags,
- unsigned Isa,
- unsigned Discriminator,
- StringRef FileName) {
- // In case we see two .loc directives in a row, make sure the
- // first one gets a line entry.
- MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
-
- this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags,
- Isa, Discriminator, FileName);
-}
-
-static const MCExpr *buildSymbolDiff(MCObjectStreamer &OS, const MCSymbol *A,
- const MCSymbol *B) {
- MCContext &Context = OS.getContext();
- MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
- const MCExpr *ARef = MCSymbolRefExpr::create(A, Variant, Context);
- const MCExpr *BRef = MCSymbolRefExpr::create(B, Variant, Context);
- const MCExpr *AddrDelta =
- MCBinaryExpr::create(MCBinaryExpr::Sub, ARef, BRef, Context);
- return AddrDelta;
-}
-
-static void emitDwarfSetLineAddr(MCObjectStreamer &OS,
- MCDwarfLineTableParams Params,
- int64_t LineDelta, const MCSymbol *Label,
- int PointerSize) {
- // emit the sequence to set the address
- OS.EmitIntValue(dwarf::DW_LNS_extended_op, 1);
- OS.EmitULEB128IntValue(PointerSize + 1);
- OS.EmitIntValue(dwarf::DW_LNE_set_address, 1);
- OS.EmitSymbolValue(Label, PointerSize);
-
- // emit the sequence for the LineDelta (from 1) and a zero address delta.
- MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
-}
-
-void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta,
- const MCSymbol *LastLabel,
- const MCSymbol *Label,
- unsigned PointerSize) {
- if (!LastLabel) {
- emitDwarfSetLineAddr(*this, Assembler->getDWARFLinetableParams(), LineDelta,
- Label, PointerSize);
- return;
- }
- const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel);
- int64_t Res;
- if (AddrDelta->evaluateAsAbsolute(Res, getAssemblerPtr())) {
- MCDwarfLineAddr::Emit(this, Assembler->getDWARFLinetableParams(), LineDelta,
- Res);
- return;
- }
- insert(new MCDwarfLineAddrFragment(LineDelta, *AddrDelta));
-}
-
-void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
- const MCSymbol *Label) {
- const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel);
- int64_t Res;
- if (AddrDelta->evaluateAsAbsolute(Res, getAssemblerPtr())) {
- MCDwarfFrameEmitter::EmitAdvanceLoc(*this, Res);
- return;
- }
- insert(new MCDwarfCallFrameFragment(*AddrDelta));
-}
-
-void MCObjectStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
- unsigned Line, unsigned Column,
- bool PrologueEnd, bool IsStmt,
- StringRef FileName, SMLoc Loc) {
- // Validate the directive.
- if (!checkCVLocSection(FunctionId, FileNo, Loc))
- return;
-
- // Emit a label at the current position and record it in the CodeViewContext.
- MCSymbol *LineSym = getContext().createTempSymbol();
- EmitLabel(LineSym);
- getContext().getCVContext().recordCVLoc(getContext(), LineSym, FunctionId,
- FileNo, Line, Column, PrologueEnd,
- IsStmt);
-}
-
-void MCObjectStreamer::EmitCVLinetableDirective(unsigned FunctionId,
- const MCSymbol *Begin,
- const MCSymbol *End) {
- getContext().getCVContext().emitLineTableForFunction(*this, FunctionId, Begin,
- End);
- this->MCStreamer::EmitCVLinetableDirective(FunctionId, Begin, End);
-}
-
-void MCObjectStreamer::EmitCVInlineLinetableDirective(
- unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
- const MCSymbol *FnStartSym, const MCSymbol *FnEndSym) {
- getContext().getCVContext().emitInlineLineTableForFunction(
- *this, PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym,
- FnEndSym);
- this->MCStreamer::EmitCVInlineLinetableDirective(
- PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
-}
-
-void MCObjectStreamer::EmitCVDefRangeDirective(
- ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
- StringRef FixedSizePortion) {
- MCFragment *Frag =
- getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion);
- // Attach labels that were pending before we created the defrange fragment to
- // the beginning of the new fragment.
- flushPendingLabels(Frag, 0);
- this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion);
-}
-
-void MCObjectStreamer::EmitCVStringTableDirective() {
- getContext().getCVContext().emitStringTable(*this);
-}
-void MCObjectStreamer::EmitCVFileChecksumsDirective() {
- getContext().getCVContext().emitFileChecksums(*this);
-}
-
-void MCObjectStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) {
- getContext().getCVContext().emitFileChecksumOffset(*this, FileNo);
-}
-
-void MCObjectStreamer::EmitBytes(StringRef Data) {
- MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
- DF->getContents().append(Data.begin(), Data.end());
-
- // EmitBytes might not cover all possible ways we emit data (or could be used
- // to emit executable code in some cases), but is the best method we have
- // right now for checking this.
- MCSection *Sec = getCurrentSectionOnly();
- Sec->setHasData(true);
-}
-
-void MCObjectStreamer::EmitValueToAlignment(unsigned ByteAlignment,
- int64_t Value,
- unsigned ValueSize,
- unsigned MaxBytesToEmit) {
- if (MaxBytesToEmit == 0)
- MaxBytesToEmit = ByteAlignment;
- insert(new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit));
-
- // Update the maximum alignment on the current section if necessary.
- MCSection *CurSec = getCurrentSectionOnly();
- if (ByteAlignment > CurSec->getAlignment())
- CurSec->setAlignment(ByteAlignment);
-}
-
-void MCObjectStreamer::EmitCodeAlignment(unsigned ByteAlignment,
- unsigned MaxBytesToEmit) {
- EmitValueToAlignment(ByteAlignment, 0, 1, MaxBytesToEmit);
- cast<MCAlignFragment>(getCurrentFragment())->setEmitNops(true);
-}
-
-void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,
- unsigned char Value,
- SMLoc Loc) {
- insert(new MCOrgFragment(*Offset, Value, Loc));
-}
-
-void MCObjectStreamer::EmitCodePaddingBasicBlockStart(
- const MCCodePaddingContext &Context) {
- getAssembler().getBackend().handleCodePaddingBasicBlockStart(this, Context);
-}
-
-void MCObjectStreamer::EmitCodePaddingBasicBlockEnd(
- const MCCodePaddingContext &Context) {
- getAssembler().getBackend().handleCodePaddingBasicBlockEnd(Context);
-}
-
-// Associate DTPRel32 fixup with data and resize data area
-void MCObjectStreamer::EmitDTPRel32Value(const MCExpr *Value) {
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
-
- DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
- Value, FK_DTPRel_4));
- DF->getContents().resize(DF->getContents().size() + 4, 0);
-}
-
-// Associate DTPRel64 fixup with data and resize data area
-void MCObjectStreamer::EmitDTPRel64Value(const MCExpr *Value) {
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
-
- DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
- Value, FK_DTPRel_8));
- DF->getContents().resize(DF->getContents().size() + 8, 0);
-}
-
-// Associate TPRel32 fixup with data and resize data area
-void MCObjectStreamer::EmitTPRel32Value(const MCExpr *Value) {
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
-
- DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
- Value, FK_TPRel_4));
- DF->getContents().resize(DF->getContents().size() + 4, 0);
-}
-
-// Associate TPRel64 fixup with data and resize data area
-void MCObjectStreamer::EmitTPRel64Value(const MCExpr *Value) {
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
-
- DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
- Value, FK_TPRel_8));
- DF->getContents().resize(DF->getContents().size() + 8, 0);
-}
-
-// Associate GPRel32 fixup with data and resize data area
-void MCObjectStreamer::EmitGPRel32Value(const MCExpr *Value) {
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
-
- DF->getFixups().push_back(
- MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4));
- DF->getContents().resize(DF->getContents().size() + 4, 0);
-}
-
-// Associate GPRel64 fixup with data and resize data area
-void MCObjectStreamer::EmitGPRel64Value(const MCExpr *Value) {
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
-
- DF->getFixups().push_back(
- MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4));
- DF->getContents().resize(DF->getContents().size() + 8, 0);
-}
-
-bool MCObjectStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name,
- const MCExpr *Expr, SMLoc Loc,
- const MCSubtargetInfo &STI) {
- Optional<MCFixupKind> MaybeKind = Assembler->getBackend().getFixupKind(Name);
- if (!MaybeKind.hasValue())
- return true;
-
- MCFixupKind Kind = *MaybeKind;
-
- if (Expr == nullptr)
- Expr =
- MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext());
-
- MCDataFragment *DF = getOrCreateDataFragment(&STI);
- flushPendingLabels(DF, DF->getContents().size());
-
- int64_t OffsetValue;
- if (Offset.evaluateAsAbsolute(OffsetValue)) {
- if (OffsetValue < 0)
- llvm_unreachable(".reloc offset is negative");
- DF->getFixups().push_back(MCFixup::create(OffsetValue, Expr, Kind, Loc));
- return false;
- }
-
- if (Offset.getKind() != llvm::MCExpr::SymbolRef)
- llvm_unreachable(".reloc offset is not absolute nor a label");
-
- const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(Offset);
- if (SRE.getSymbol().isDefined()) {
- DF->getFixups().push_back(MCFixup::create(SRE.getSymbol().getOffset(),
- Expr, Kind, Loc));
- return false;
- }
-
- PendingFixups.emplace_back(&SRE.getSymbol(), DF,
- MCFixup::create(-1, Expr, Kind, Loc));
- return false;
-}
-
-void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
- SMLoc Loc) {
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
-
- assert(getCurrentSectionOnly() && "need a section");
- insert(new MCFillFragment(FillValue, 1, NumBytes, Loc));
-}
-
-void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
- int64_t Expr, SMLoc Loc) {
- int64_t IntNumValues;
- // Do additional checking now if we can resolve the value.
- if (NumValues.evaluateAsAbsolute(IntNumValues, getAssemblerPtr())) {
- if (IntNumValues < 0) {
- getContext().getSourceManager()->PrintMessage(
- Loc, SourceMgr::DK_Warning,
- "'.fill' directive with negative repeat count has no effect");
- return;
- }
- // Emit now if we can for better errors.
- int64_t NonZeroSize = Size > 4 ? 4 : Size;
- Expr &= ~0ULL >> (64 - NonZeroSize * 8);
- for (uint64_t i = 0, e = IntNumValues; i != e; ++i) {
- EmitIntValue(Expr, NonZeroSize);
- if (NonZeroSize < Size)
- EmitIntValue(0, Size - NonZeroSize);
- }
- return;
- }
-
- // Otherwise emit as fragment.
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
-
- assert(getCurrentSectionOnly() && "need a section");
- insert(new MCFillFragment(Expr, Size, NumValues, Loc));
-}
-
-void MCObjectStreamer::EmitFileDirective(StringRef Filename) {
- getAssembler().addFileName(Filename);
-}
-
-void MCObjectStreamer::EmitAddrsig() {
- getAssembler().getWriter().emitAddrsigSection();
-}
-
-void MCObjectStreamer::EmitAddrsigSym(const MCSymbol *Sym) {
- getAssembler().registerSymbol(*Sym);
- getAssembler().getWriter().addAddrsigSymbol(Sym);
-}
-
-void MCObjectStreamer::FinishImpl() {
- getContext().RemapDebugPaths();
-
- // If we are generating dwarf for assembly source files dump out the sections.
- if (getContext().getGenDwarfForAssembly())
- MCGenDwarfInfo::Emit(this);
-
- // Dump out the dwarf file & directory tables and line tables.
- MCDwarfLineTable::Emit(this, getAssembler().getDWARFLinetableParams());
-
- flushPendingLabels();
- resolvePendingFixups();
- getAssembler().Finish();
-}
diff --git a/contrib/llvm/lib/MC/MCObjectWriter.cpp b/contrib/llvm/lib/MC/MCObjectWriter.cpp
deleted file mode 100644
index a058bbe0ba0b..000000000000
--- a/contrib/llvm/lib/MC/MCObjectWriter.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-//===- lib/MC/MCObjectWriter.cpp - MCObjectWriter implementation ----------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCFragment.h"
-#include "llvm/MC/MCSymbol.h"
-
-using namespace llvm;
-
-MCObjectWriter::~MCObjectWriter() = default;
-
-bool MCObjectWriter::isSymbolRefDifferenceFullyResolved(
- const MCAssembler &Asm, const MCSymbolRefExpr *A, const MCSymbolRefExpr *B,
- bool InSet) const {
- // Modified symbol references cannot be resolved.
- if (A->getKind() != MCSymbolRefExpr::VK_None ||
- B->getKind() != MCSymbolRefExpr::VK_None)
- return false;
-
- const MCSymbol &SA = A->getSymbol();
- const MCSymbol &SB = B->getSymbol();
- if (SA.isUndefined() || SB.isUndefined())
- return false;
-
- if (!SA.getFragment() || !SB.getFragment())
- return false;
-
- return isSymbolRefDifferenceFullyResolvedImpl(Asm, SA, SB, InSet);
-}
-
-bool MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
- const MCAssembler &Asm, const MCSymbol &A, const MCSymbol &B,
- bool InSet) const {
- return isSymbolRefDifferenceFullyResolvedImpl(Asm, A, *B.getFragment(), InSet,
- false);
-}
-
-bool MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
- const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB,
- bool InSet, bool IsPCRel) const {
- const MCSection &SecA = SymA.getSection();
- const MCSection &SecB = *FB.getParent();
- // On ELF and COFF A - B is absolute if A and B are in the same section.
- return &SecA == &SecB;
-}
diff --git a/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp b/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp
deleted file mode 100644
index 9155ae05d29d..000000000000
--- a/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp
+++ /dev/null
@@ -1,755 +0,0 @@
-//===- AsmLexer.cpp - Lexer for Assembly Files ----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This class implements the lexer for assembly files.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCParser/AsmLexer.h"
-#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCParser/MCAsmLexer.h"
-#include "llvm/Support/SMLoc.h"
-#include "llvm/Support/SaveAndRestore.h"
-#include <cassert>
-#include <cctype>
-#include <cstdio>
-#include <cstring>
-#include <string>
-#include <tuple>
-#include <utility>
-
-using namespace llvm;
-
-AsmLexer::AsmLexer(const MCAsmInfo &MAI) : MAI(MAI) {
- AllowAtInIdentifier = !StringRef(MAI.getCommentString()).startswith("@");
-}
-
-AsmLexer::~AsmLexer() = default;
-
-void AsmLexer::setBuffer(StringRef Buf, const char *ptr) {
- CurBuf = Buf;
-
- if (ptr)
- CurPtr = ptr;
- else
- CurPtr = CurBuf.begin();
-
- TokStart = nullptr;
-}
-
-/// ReturnError - Set the error to the specified string at the specified
-/// location. This is defined to always return AsmToken::Error.
-AsmToken AsmLexer::ReturnError(const char *Loc, const std::string &Msg) {
- SetError(SMLoc::getFromPointer(Loc), Msg);
-
- return AsmToken(AsmToken::Error, StringRef(Loc, CurPtr - Loc));
-}
-
-int AsmLexer::getNextChar() {
- if (CurPtr == CurBuf.end())
- return EOF;
- return (unsigned char)*CurPtr++;
-}
-
-/// The leading integral digit sequence and dot should have already been
-/// consumed, some or all of the fractional digit sequence *can* have been
-/// consumed.
-AsmToken AsmLexer::LexFloatLiteral() {
- // Skip the fractional digit sequence.
- while (isDigit(*CurPtr))
- ++CurPtr;
-
- if (*CurPtr == '-' || *CurPtr == '+')
- return ReturnError(CurPtr, "Invalid sign in float literal");
-
- // Check for exponent
- if ((*CurPtr == 'e' || *CurPtr == 'E')) {
- ++CurPtr;
-
- if (*CurPtr == '-' || *CurPtr == '+')
- ++CurPtr;
-
- while (isDigit(*CurPtr))
- ++CurPtr;
- }
-
- return AsmToken(AsmToken::Real,
- StringRef(TokStart, CurPtr - TokStart));
-}
-
-/// LexHexFloatLiteral matches essentially (.[0-9a-fA-F]*)?[pP][+-]?[0-9a-fA-F]+
-/// while making sure there are enough actual digits around for the constant to
-/// be valid.
-///
-/// The leading "0x[0-9a-fA-F]*" (i.e. integer part) has already been consumed
-/// before we get here.
-AsmToken AsmLexer::LexHexFloatLiteral(bool NoIntDigits) {
- assert((*CurPtr == 'p' || *CurPtr == 'P' || *CurPtr == '.') &&
- "unexpected parse state in floating hex");
- bool NoFracDigits = true;
-
- // Skip the fractional part if there is one
- if (*CurPtr == '.') {
- ++CurPtr;
-
- const char *FracStart = CurPtr;
- while (isHexDigit(*CurPtr))
- ++CurPtr;
-
- NoFracDigits = CurPtr == FracStart;
- }
-
- if (NoIntDigits && NoFracDigits)
- return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
- "expected at least one significand digit");
-
- // Make sure we do have some kind of proper exponent part
- if (*CurPtr != 'p' && *CurPtr != 'P')
- return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
- "expected exponent part 'p'");
- ++CurPtr;
-
- if (*CurPtr == '+' || *CurPtr == '-')
- ++CurPtr;
-
- // N.b. exponent digits are *not* hex
- const char *ExpStart = CurPtr;
- while (isDigit(*CurPtr))
- ++CurPtr;
-
- if (CurPtr == ExpStart)
- return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
- "expected at least one exponent digit");
-
- return AsmToken(AsmToken::Real, StringRef(TokStart, CurPtr - TokStart));
-}
-
-/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@?]*
-static bool IsIdentifierChar(char c, bool AllowAt) {
- return isAlnum(c) || c == '_' || c == '$' || c == '.' ||
- (c == '@' && AllowAt) || c == '?';
-}
-
-AsmToken AsmLexer::LexIdentifier() {
- // Check for floating point literals.
- if (CurPtr[-1] == '.' && isDigit(*CurPtr)) {
- // Disambiguate a .1243foo identifier from a floating literal.
- while (isDigit(*CurPtr))
- ++CurPtr;
-
- if (!IsIdentifierChar(*CurPtr, AllowAtInIdentifier) ||
- *CurPtr == 'e' || *CurPtr == 'E')
- return LexFloatLiteral();
- }
-
- while (IsIdentifierChar(*CurPtr, AllowAtInIdentifier))
- ++CurPtr;
-
- // Handle . as a special case.
- if (CurPtr == TokStart+1 && TokStart[0] == '.')
- return AsmToken(AsmToken::Dot, StringRef(TokStart, 1));
-
- return AsmToken(AsmToken::Identifier, StringRef(TokStart, CurPtr - TokStart));
-}
-
-/// LexSlash: Slash: /
-/// C-Style Comment: /* ... */
-AsmToken AsmLexer::LexSlash() {
- switch (*CurPtr) {
- case '*':
- IsAtStartOfStatement = false;
- break; // C style comment.
- case '/':
- ++CurPtr;
- return LexLineComment();
- default:
- IsAtStartOfStatement = false;
- return AsmToken(AsmToken::Slash, StringRef(TokStart, 1));
- }
-
- // C Style comment.
- ++CurPtr; // skip the star.
- const char *CommentTextStart = CurPtr;
- while (CurPtr != CurBuf.end()) {
- switch (*CurPtr++) {
- case '*':
- // End of the comment?
- if (*CurPtr != '/')
- break;
- // If we have a CommentConsumer, notify it about the comment.
- if (CommentConsumer) {
- CommentConsumer->HandleComment(
- SMLoc::getFromPointer(CommentTextStart),
- StringRef(CommentTextStart, CurPtr - 1 - CommentTextStart));
- }
- ++CurPtr; // End the */.
- return AsmToken(AsmToken::Comment,
- StringRef(TokStart, CurPtr - TokStart));
- }
- }
- return ReturnError(TokStart, "unterminated comment");
-}
-
-/// LexLineComment: Comment: #[^\n]*
-/// : //[^\n]*
-AsmToken AsmLexer::LexLineComment() {
- // Mark This as an end of statement with a body of the
- // comment. While it would be nicer to leave this two tokens,
- // backwards compatability with TargetParsers makes keeping this in this form
- // better.
- const char *CommentTextStart = CurPtr;
- int CurChar = getNextChar();
- while (CurChar != '\n' && CurChar != '\r' && CurChar != EOF)
- CurChar = getNextChar();
- if (CurChar == '\r' && CurPtr != CurBuf.end() && *CurPtr == '\n')
- ++CurPtr;
-
- // If we have a CommentConsumer, notify it about the comment.
- if (CommentConsumer) {
- CommentConsumer->HandleComment(
- SMLoc::getFromPointer(CommentTextStart),
- StringRef(CommentTextStart, CurPtr - 1 - CommentTextStart));
- }
-
- IsAtStartOfLine = true;
- // This is a whole line comment. leave newline
- if (IsAtStartOfStatement)
- return AsmToken(AsmToken::EndOfStatement,
- StringRef(TokStart, CurPtr - TokStart));
- IsAtStartOfStatement = true;
-
- return AsmToken(AsmToken::EndOfStatement,
- StringRef(TokStart, CurPtr - 1 - TokStart));
-}
-
-static void SkipIgnoredIntegerSuffix(const char *&CurPtr) {
- // Skip ULL, UL, U, L and LL suffices.
- if (CurPtr[0] == 'U')
- ++CurPtr;
- if (CurPtr[0] == 'L')
- ++CurPtr;
- if (CurPtr[0] == 'L')
- ++CurPtr;
-}
-
-// Look ahead to search for first non-hex digit, if it's [hH], then we treat the
-// integer as a hexadecimal, possibly with leading zeroes.
-static unsigned doHexLookAhead(const char *&CurPtr, unsigned DefaultRadix,
- bool LexHex) {
- const char *FirstNonDec = nullptr;
- const char *LookAhead = CurPtr;
- while (true) {
- if (isDigit(*LookAhead)) {
- ++LookAhead;
- } else {
- if (!FirstNonDec)
- FirstNonDec = LookAhead;
-
- // Keep going if we are looking for a 'h' suffix.
- if (LexHex && isHexDigit(*LookAhead))
- ++LookAhead;
- else
- break;
- }
- }
- bool isHex = LexHex && (*LookAhead == 'h' || *LookAhead == 'H');
- CurPtr = isHex || !FirstNonDec ? LookAhead : FirstNonDec;
- if (isHex)
- return 16;
- return DefaultRadix;
-}
-
-static AsmToken intToken(StringRef Ref, APInt &Value)
-{
- if (Value.isIntN(64))
- return AsmToken(AsmToken::Integer, Ref, Value);
- return AsmToken(AsmToken::BigNum, Ref, Value);
-}
-
-/// LexDigit: First character is [0-9].
-/// Local Label: [0-9][:]
-/// Forward/Backward Label: [0-9][fb]
-/// Binary integer: 0b[01]+
-/// Octal integer: 0[0-7]+
-/// Hex integer: 0x[0-9a-fA-F]+ or [0x]?[0-9][0-9a-fA-F]*[hH]
-/// Decimal integer: [1-9][0-9]*
-AsmToken AsmLexer::LexDigit() {
- // MASM-flavor binary integer: [01]+[bB]
- // MASM-flavor hexadecimal integer: [0-9][0-9a-fA-F]*[hH]
- if (LexMasmIntegers && isdigit(CurPtr[-1])) {
- const char *FirstNonBinary = (CurPtr[-1] != '0' && CurPtr[-1] != '1') ?
- CurPtr - 1 : nullptr;
- const char *OldCurPtr = CurPtr;
- while (isHexDigit(*CurPtr)) {
- if (*CurPtr != '0' && *CurPtr != '1' && !FirstNonBinary)
- FirstNonBinary = CurPtr;
- ++CurPtr;
- }
-
- unsigned Radix = 0;
- if (*CurPtr == 'h' || *CurPtr == 'H') {
- // hexadecimal number
- ++CurPtr;
- Radix = 16;
- } else if (FirstNonBinary && FirstNonBinary + 1 == CurPtr &&
- (*FirstNonBinary == 'b' || *FirstNonBinary == 'B'))
- Radix = 2;
-
- if (Radix == 2 || Radix == 16) {
- StringRef Result(TokStart, CurPtr - TokStart);
- APInt Value(128, 0, true);
-
- if (Result.drop_back().getAsInteger(Radix, Value))
- return ReturnError(TokStart, Radix == 2 ? "invalid binary number" :
- "invalid hexdecimal number");
-
- // MSVC accepts and ignores type suffices on integer literals.
- SkipIgnoredIntegerSuffix(CurPtr);
-
- return intToken(Result, Value);
- }
-
- // octal/decimal integers, or floating point numbers, fall through
- CurPtr = OldCurPtr;
- }
-
- // Decimal integer: [1-9][0-9]*
- if (CurPtr[-1] != '0' || CurPtr[0] == '.') {
- unsigned Radix = doHexLookAhead(CurPtr, 10, LexMasmIntegers);
- bool isHex = Radix == 16;
- // Check for floating point literals.
- if (!isHex && (*CurPtr == '.' || *CurPtr == 'e' || *CurPtr == 'E')) {
- if (*CurPtr == '.')
- ++CurPtr;
- return LexFloatLiteral();
- }
-
- StringRef Result(TokStart, CurPtr - TokStart);
-
- APInt Value(128, 0, true);
- if (Result.getAsInteger(Radix, Value))
- return ReturnError(TokStart, !isHex ? "invalid decimal number" :
- "invalid hexdecimal number");
-
- // Consume the [hH].
- if (LexMasmIntegers && Radix == 16)
- ++CurPtr;
-
- // The darwin/x86 (and x86-64) assembler accepts and ignores type
- // suffices on integer literals.
- SkipIgnoredIntegerSuffix(CurPtr);
-
- return intToken(Result, Value);
- }
-
- if (!LexMasmIntegers && ((*CurPtr == 'b') || (*CurPtr == 'B'))) {
- ++CurPtr;
- // See if we actually have "0b" as part of something like "jmp 0b\n"
- if (!isDigit(CurPtr[0])) {
- --CurPtr;
- StringRef Result(TokStart, CurPtr - TokStart);
- return AsmToken(AsmToken::Integer, Result, 0);
- }
- const char *NumStart = CurPtr;
- while (CurPtr[0] == '0' || CurPtr[0] == '1')
- ++CurPtr;
-
- // Requires at least one binary digit.
- if (CurPtr == NumStart)
- return ReturnError(TokStart, "invalid binary number");
-
- StringRef Result(TokStart, CurPtr - TokStart);
-
- APInt Value(128, 0, true);
- if (Result.substr(2).getAsInteger(2, Value))
- return ReturnError(TokStart, "invalid binary number");
-
- // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
- // suffixes on integer literals.
- SkipIgnoredIntegerSuffix(CurPtr);
-
- return intToken(Result, Value);
- }
-
- if ((*CurPtr == 'x') || (*CurPtr == 'X')) {
- ++CurPtr;
- const char *NumStart = CurPtr;
- while (isHexDigit(CurPtr[0]))
- ++CurPtr;
-
- // "0x.0p0" is valid, and "0x0p0" (but not "0xp0" for example, which will be
- // diagnosed by LexHexFloatLiteral).
- if (CurPtr[0] == '.' || CurPtr[0] == 'p' || CurPtr[0] == 'P')
- return LexHexFloatLiteral(NumStart == CurPtr);
-
- // Otherwise requires at least one hex digit.
- if (CurPtr == NumStart)
- return ReturnError(CurPtr-2, "invalid hexadecimal number");
-
- APInt Result(128, 0);
- if (StringRef(TokStart, CurPtr - TokStart).getAsInteger(0, Result))
- return ReturnError(TokStart, "invalid hexadecimal number");
-
- // Consume the optional [hH].
- if (LexMasmIntegers && (*CurPtr == 'h' || *CurPtr == 'H'))
- ++CurPtr;
-
- // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
- // suffixes on integer literals.
- SkipIgnoredIntegerSuffix(CurPtr);
-
- return intToken(StringRef(TokStart, CurPtr - TokStart), Result);
- }
-
- // Either octal or hexadecimal.
- APInt Value(128, 0, true);
- unsigned Radix = doHexLookAhead(CurPtr, 8, LexMasmIntegers);
- bool isHex = Radix == 16;
- StringRef Result(TokStart, CurPtr - TokStart);
- if (Result.getAsInteger(Radix, Value))
- return ReturnError(TokStart, !isHex ? "invalid octal number" :
- "invalid hexdecimal number");
-
- // Consume the [hH].
- if (Radix == 16)
- ++CurPtr;
-
- // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
- // suffixes on integer literals.
- SkipIgnoredIntegerSuffix(CurPtr);
-
- return intToken(Result, Value);
-}
-
-/// LexSingleQuote: Integer: 'b'
-AsmToken AsmLexer::LexSingleQuote() {
- int CurChar = getNextChar();
-
- if (CurChar == '\\')
- CurChar = getNextChar();
-
- if (CurChar == EOF)
- return ReturnError(TokStart, "unterminated single quote");
-
- CurChar = getNextChar();
-
- if (CurChar != '\'')
- return ReturnError(TokStart, "single quote way too long");
-
- // The idea here being that 'c' is basically just an integral
- // constant.
- StringRef Res = StringRef(TokStart,CurPtr - TokStart);
- long long Value;
-
- if (Res.startswith("\'\\")) {
- char theChar = Res[2];
- switch (theChar) {
- default: Value = theChar; break;
- case '\'': Value = '\''; break;
- case 't': Value = '\t'; break;
- case 'n': Value = '\n'; break;
- case 'b': Value = '\b'; break;
- }
- } else
- Value = TokStart[1];
-
- return AsmToken(AsmToken::Integer, Res, Value);
-}
-
-/// LexQuote: String: "..."
-AsmToken AsmLexer::LexQuote() {
- int CurChar = getNextChar();
- // TODO: does gas allow multiline string constants?
- while (CurChar != '"') {
- if (CurChar == '\\') {
- // Allow \", etc.
- CurChar = getNextChar();
- }
-
- if (CurChar == EOF)
- return ReturnError(TokStart, "unterminated string constant");
-
- CurChar = getNextChar();
- }
-
- return AsmToken(AsmToken::String, StringRef(TokStart, CurPtr - TokStart));
-}
-
-StringRef AsmLexer::LexUntilEndOfStatement() {
- TokStart = CurPtr;
-
- while (!isAtStartOfComment(CurPtr) && // Start of line comment.
- !isAtStatementSeparator(CurPtr) && // End of statement marker.
- *CurPtr != '\n' && *CurPtr != '\r' && CurPtr != CurBuf.end()) {
- ++CurPtr;
- }
- return StringRef(TokStart, CurPtr-TokStart);
-}
-
-StringRef AsmLexer::LexUntilEndOfLine() {
- TokStart = CurPtr;
-
- while (*CurPtr != '\n' && *CurPtr != '\r' && CurPtr != CurBuf.end()) {
- ++CurPtr;
- }
- return StringRef(TokStart, CurPtr-TokStart);
-}
-
-size_t AsmLexer::peekTokens(MutableArrayRef<AsmToken> Buf,
- bool ShouldSkipSpace) {
- SaveAndRestore<const char *> SavedTokenStart(TokStart);
- SaveAndRestore<const char *> SavedCurPtr(CurPtr);
- SaveAndRestore<bool> SavedAtStartOfLine(IsAtStartOfLine);
- SaveAndRestore<bool> SavedAtStartOfStatement(IsAtStartOfStatement);
- SaveAndRestore<bool> SavedSkipSpace(SkipSpace, ShouldSkipSpace);
- SaveAndRestore<bool> SavedIsPeeking(IsPeeking, true);
- std::string SavedErr = getErr();
- SMLoc SavedErrLoc = getErrLoc();
-
- size_t ReadCount;
- for (ReadCount = 0; ReadCount < Buf.size(); ++ReadCount) {
- AsmToken Token = LexToken();
-
- Buf[ReadCount] = Token;
-
- if (Token.is(AsmToken::Eof))
- break;
- }
-
- SetError(SavedErrLoc, SavedErr);
- return ReadCount;
-}
-
-bool AsmLexer::isAtStartOfComment(const char *Ptr) {
- StringRef CommentString = MAI.getCommentString();
-
- if (CommentString.size() == 1)
- return CommentString[0] == Ptr[0];
-
- // Allow # preprocessor commments also be counted as comments for "##" cases
- if (CommentString[1] == '#')
- return CommentString[0] == Ptr[0];
-
- return strncmp(Ptr, CommentString.data(), CommentString.size()) == 0;
-}
-
-bool AsmLexer::isAtStatementSeparator(const char *Ptr) {
- return strncmp(Ptr, MAI.getSeparatorString(),
- strlen(MAI.getSeparatorString())) == 0;
-}
-
-AsmToken AsmLexer::LexToken() {
- TokStart = CurPtr;
- // This always consumes at least one character.
- int CurChar = getNextChar();
-
- if (!IsPeeking && CurChar == '#' && IsAtStartOfStatement) {
- // If this starts with a '#', this may be a cpp
- // hash directive and otherwise a line comment.
- AsmToken TokenBuf[2];
- MutableArrayRef<AsmToken> Buf(TokenBuf, 2);
- size_t num = peekTokens(Buf, true);
- // There cannot be a space preceding this
- if (IsAtStartOfLine && num == 2 && TokenBuf[0].is(AsmToken::Integer) &&
- TokenBuf[1].is(AsmToken::String)) {
- CurPtr = TokStart; // reset curPtr;
- StringRef s = LexUntilEndOfLine();
- UnLex(TokenBuf[1]);
- UnLex(TokenBuf[0]);
- return AsmToken(AsmToken::HashDirective, s);
- }
- return LexLineComment();
- }
-
- if (isAtStartOfComment(TokStart))
- return LexLineComment();
-
- if (isAtStatementSeparator(TokStart)) {
- CurPtr += strlen(MAI.getSeparatorString()) - 1;
- IsAtStartOfLine = true;
- IsAtStartOfStatement = true;
- return AsmToken(AsmToken::EndOfStatement,
- StringRef(TokStart, strlen(MAI.getSeparatorString())));
- }
-
- // If we're missing a newline at EOF, make sure we still get an
- // EndOfStatement token before the Eof token.
- if (CurChar == EOF && !IsAtStartOfStatement) {
- IsAtStartOfLine = true;
- IsAtStartOfStatement = true;
- return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
- }
- IsAtStartOfLine = false;
- bool OldIsAtStartOfStatement = IsAtStartOfStatement;
- IsAtStartOfStatement = false;
- switch (CurChar) {
- default:
- // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
- if (isalpha(CurChar) || CurChar == '_' || CurChar == '.')
- return LexIdentifier();
-
- // Unknown character, emit an error.
- return ReturnError(TokStart, "invalid character in input");
- case EOF:
- IsAtStartOfLine = true;
- IsAtStartOfStatement = true;
- return AsmToken(AsmToken::Eof, StringRef(TokStart, 0));
- case 0:
- case ' ':
- case '\t':
- IsAtStartOfStatement = OldIsAtStartOfStatement;
- while (*CurPtr == ' ' || *CurPtr == '\t')
- CurPtr++;
- if (SkipSpace)
- return LexToken(); // Ignore whitespace.
- else
- return AsmToken(AsmToken::Space, StringRef(TokStart, CurPtr - TokStart));
- case '\r': {
- IsAtStartOfLine = true;
- IsAtStartOfStatement = true;
- // If this is a CR followed by LF, treat that as one token.
- if (CurPtr != CurBuf.end() && *CurPtr == '\n')
- ++CurPtr;
- return AsmToken(AsmToken::EndOfStatement,
- StringRef(TokStart, CurPtr - TokStart));
- }
- case '\n':
- IsAtStartOfLine = true;
- IsAtStartOfStatement = true;
- return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
- case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1));
- case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1));
- case '~': return AsmToken(AsmToken::Tilde, StringRef(TokStart, 1));
- case '(': return AsmToken(AsmToken::LParen, StringRef(TokStart, 1));
- case ')': return AsmToken(AsmToken::RParen, StringRef(TokStart, 1));
- case '[': return AsmToken(AsmToken::LBrac, StringRef(TokStart, 1));
- case ']': return AsmToken(AsmToken::RBrac, StringRef(TokStart, 1));
- case '{': return AsmToken(AsmToken::LCurly, StringRef(TokStart, 1));
- case '}': return AsmToken(AsmToken::RCurly, StringRef(TokStart, 1));
- case '*': return AsmToken(AsmToken::Star, StringRef(TokStart, 1));
- case ',': return AsmToken(AsmToken::Comma, StringRef(TokStart, 1));
- case '$': return AsmToken(AsmToken::Dollar, StringRef(TokStart, 1));
- case '@': return AsmToken(AsmToken::At, StringRef(TokStart, 1));
- case '\\': return AsmToken(AsmToken::BackSlash, StringRef(TokStart, 1));
- case '=':
- if (*CurPtr == '=') {
- ++CurPtr;
- return AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2));
- }
- return AsmToken(AsmToken::Equal, StringRef(TokStart, 1));
- case '-':
- if (*CurPtr == '>') {
- ++CurPtr;
- return AsmToken(AsmToken::MinusGreater, StringRef(TokStart, 2));
- }
- return AsmToken(AsmToken::Minus, StringRef(TokStart, 1));
- case '|':
- if (*CurPtr == '|') {
- ++CurPtr;
- return AsmToken(AsmToken::PipePipe, StringRef(TokStart, 2));
- }
- return AsmToken(AsmToken::Pipe, StringRef(TokStart, 1));
- case '^': return AsmToken(AsmToken::Caret, StringRef(TokStart, 1));
- case '&':
- if (*CurPtr == '&') {
- ++CurPtr;
- return AsmToken(AsmToken::AmpAmp, StringRef(TokStart, 2));
- }
- return AsmToken(AsmToken::Amp, StringRef(TokStart, 1));
- case '!':
- if (*CurPtr == '=') {
- ++CurPtr;
- return AsmToken(AsmToken::ExclaimEqual, StringRef(TokStart, 2));
- }
- return AsmToken(AsmToken::Exclaim, StringRef(TokStart, 1));
- case '%':
- if (MAI.hasMipsExpressions()) {
- AsmToken::TokenKind Operator;
- unsigned OperatorLength;
-
- std::tie(Operator, OperatorLength) =
- StringSwitch<std::pair<AsmToken::TokenKind, unsigned>>(
- StringRef(CurPtr))
- .StartsWith("call16", {AsmToken::PercentCall16, 7})
- .StartsWith("call_hi", {AsmToken::PercentCall_Hi, 8})
- .StartsWith("call_lo", {AsmToken::PercentCall_Lo, 8})
- .StartsWith("dtprel_hi", {AsmToken::PercentDtprel_Hi, 10})
- .StartsWith("dtprel_lo", {AsmToken::PercentDtprel_Lo, 10})
- .StartsWith("got_disp", {AsmToken::PercentGot_Disp, 9})
- .StartsWith("got_hi", {AsmToken::PercentGot_Hi, 7})
- .StartsWith("got_lo", {AsmToken::PercentGot_Lo, 7})
- .StartsWith("got_ofst", {AsmToken::PercentGot_Ofst, 9})
- .StartsWith("got_page", {AsmToken::PercentGot_Page, 9})
- .StartsWith("gottprel", {AsmToken::PercentGottprel, 9})
- .StartsWith("got", {AsmToken::PercentGot, 4})
- .StartsWith("gp_rel", {AsmToken::PercentGp_Rel, 7})
- .StartsWith("higher", {AsmToken::PercentHigher, 7})
- .StartsWith("highest", {AsmToken::PercentHighest, 8})
- .StartsWith("hi", {AsmToken::PercentHi, 3})
- .StartsWith("lo", {AsmToken::PercentLo, 3})
- .StartsWith("neg", {AsmToken::PercentNeg, 4})
- .StartsWith("pcrel_hi", {AsmToken::PercentPcrel_Hi, 9})
- .StartsWith("pcrel_lo", {AsmToken::PercentPcrel_Lo, 9})
- .StartsWith("tlsgd", {AsmToken::PercentTlsgd, 6})
- .StartsWith("tlsldm", {AsmToken::PercentTlsldm, 7})
- .StartsWith("tprel_hi", {AsmToken::PercentTprel_Hi, 9})
- .StartsWith("tprel_lo", {AsmToken::PercentTprel_Lo, 9})
- .Default({AsmToken::Percent, 1});
-
- if (Operator != AsmToken::Percent) {
- CurPtr += OperatorLength - 1;
- return AsmToken(Operator, StringRef(TokStart, OperatorLength));
- }
- }
- return AsmToken(AsmToken::Percent, StringRef(TokStart, 1));
- case '/':
- IsAtStartOfStatement = OldIsAtStartOfStatement;
- return LexSlash();
- case '#': return AsmToken(AsmToken::Hash, StringRef(TokStart, 1));
- case '\'': return LexSingleQuote();
- case '"': return LexQuote();
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- return LexDigit();
- case '<':
- switch (*CurPtr) {
- case '<':
- ++CurPtr;
- return AsmToken(AsmToken::LessLess, StringRef(TokStart, 2));
- case '=':
- ++CurPtr;
- return AsmToken(AsmToken::LessEqual, StringRef(TokStart, 2));
- case '>':
- ++CurPtr;
- return AsmToken(AsmToken::LessGreater, StringRef(TokStart, 2));
- default:
- return AsmToken(AsmToken::Less, StringRef(TokStart, 1));
- }
- case '>':
- switch (*CurPtr) {
- case '>':
- ++CurPtr;
- return AsmToken(AsmToken::GreaterGreater, StringRef(TokStart, 2));
- case '=':
- ++CurPtr;
- return AsmToken(AsmToken::GreaterEqual, StringRef(TokStart, 2));
- default:
- return AsmToken(AsmToken::Greater, StringRef(TokStart, 1));
- }
-
- // TODO: Quoted identifiers (objc methods etc)
- // local labels: [0-9][:]
- // Forward/backward labels: [0-9][fb]
- // Integers, fp constants, character constants.
- }
-}
diff --git a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp
deleted file mode 100644
index c2cbca2177be..000000000000
--- a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp
+++ /dev/null
@@ -1,5962 +0,0 @@
-//===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This class implements the parser for assembly files.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/None.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/Dwarf.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCCodeView.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDirectives.h"
-#include "llvm/MC/MCDwarf.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCInstPrinter.h"
-#include "llvm/MC/MCInstrDesc.h"
-#include "llvm/MC/MCInstrInfo.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCParser/AsmCond.h"
-#include "llvm/MC/MCParser/AsmLexer.h"
-#include "llvm/MC/MCParser/MCAsmLexer.h"
-#include "llvm/MC/MCParser/MCAsmParser.h"
-#include "llvm/MC/MCParser/MCAsmParserExtension.h"
-#include "llvm/MC/MCParser/MCAsmParserUtils.h"
-#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
-#include "llvm/MC/MCParser/MCTargetAsmParser.h"
-#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCTargetOptions.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MD5.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/SMLoc.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <cctype>
-#include <climits>
-#include <cstddef>
-#include <cstdint>
-#include <deque>
-#include <memory>
-#include <sstream>
-#include <string>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-using namespace llvm;
-
-MCAsmParserSemaCallback::~MCAsmParserSemaCallback() = default;
-
-static cl::opt<unsigned> AsmMacroMaxNestingDepth(
- "asm-macro-max-nesting-depth", cl::init(20), cl::Hidden,
- cl::desc("The maximum nesting depth allowed for assembly macros."));
-
-namespace {
-
-/// Helper types for tracking macro definitions.
-typedef std::vector<AsmToken> MCAsmMacroArgument;
-typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
-
-/// Helper class for storing information about an active macro
-/// instantiation.
-struct MacroInstantiation {
- /// The location of the instantiation.
- SMLoc InstantiationLoc;
-
- /// The buffer where parsing should resume upon instantiation completion.
- int ExitBuffer;
-
- /// The location where parsing should resume upon instantiation completion.
- SMLoc ExitLoc;
-
- /// The depth of TheCondStack at the start of the instantiation.
- size_t CondStackDepth;
-
-public:
- MacroInstantiation(SMLoc IL, int EB, SMLoc EL, size_t CondStackDepth);
-};
-
-struct ParseStatementInfo {
- /// The parsed operands from the last parsed statement.
- SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands;
-
- /// The opcode from the last parsed instruction.
- unsigned Opcode = ~0U;
-
- /// Was there an error parsing the inline assembly?
- bool ParseError = false;
-
- SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
-
- ParseStatementInfo() = delete;
- ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
- : AsmRewrites(rewrites) {}
-};
-
-/// The concrete assembly parser instance.
-class AsmParser : public MCAsmParser {
-private:
- AsmLexer Lexer;
- MCContext &Ctx;
- MCStreamer &Out;
- const MCAsmInfo &MAI;
- SourceMgr &SrcMgr;
- SourceMgr::DiagHandlerTy SavedDiagHandler;
- void *SavedDiagContext;
- std::unique_ptr<MCAsmParserExtension> PlatformParser;
-
- /// This is the current buffer index we're lexing from as managed by the
- /// SourceMgr object.
- unsigned CurBuffer;
-
- AsmCond TheCondState;
- std::vector<AsmCond> TheCondStack;
-
- /// maps directive names to handler methods in parser
- /// extensions. Extensions register themselves in this map by calling
- /// addDirectiveHandler.
- StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
-
- /// Stack of active macro instantiations.
- std::vector<MacroInstantiation*> ActiveMacros;
-
- /// List of bodies of anonymous macros.
- std::deque<MCAsmMacro> MacroLikeBodies;
-
- /// Boolean tracking whether macro substitution is enabled.
- unsigned MacrosEnabledFlag : 1;
-
- /// Keeps track of how many .macro's have been instantiated.
- unsigned NumOfMacroInstantiations;
-
- /// The values from the last parsed cpp hash file line comment if any.
- struct CppHashInfoTy {
- StringRef Filename;
- int64_t LineNumber;
- SMLoc Loc;
- unsigned Buf;
- CppHashInfoTy() : Filename(), LineNumber(0), Loc(), Buf(0) {}
- };
- CppHashInfoTy CppHashInfo;
-
- /// The filename from the first cpp hash file line comment, if any.
- StringRef FirstCppHashFilename;
-
- /// List of forward directional labels for diagnosis at the end.
- SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels;
-
- /// AssemblerDialect. ~OU means unset value and use value provided by MAI.
- unsigned AssemblerDialect = ~0U;
-
- /// is Darwin compatibility enabled?
- bool IsDarwin = false;
-
- /// Are we parsing ms-style inline assembly?
- bool ParsingInlineAsm = false;
-
- /// Did we already inform the user about inconsistent MD5 usage?
- bool ReportedInconsistentMD5 = false;
-
- // Is alt macro mode enabled.
- bool AltMacroMode = false;
-
-public:
- AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
- const MCAsmInfo &MAI, unsigned CB);
- AsmParser(const AsmParser &) = delete;
- AsmParser &operator=(const AsmParser &) = delete;
- ~AsmParser() override;
-
- bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;
-
- void addDirectiveHandler(StringRef Directive,
- ExtensionDirectiveHandler Handler) override {
- ExtensionDirectiveMap[Directive] = Handler;
- }
-
- void addAliasForDirective(StringRef Directive, StringRef Alias) override {
- DirectiveKindMap[Directive] = DirectiveKindMap[Alias];
- }
-
- /// @name MCAsmParser Interface
- /// {
-
- SourceMgr &getSourceManager() override { return SrcMgr; }
- MCAsmLexer &getLexer() override { return Lexer; }
- MCContext &getContext() override { return Ctx; }
- MCStreamer &getStreamer() override { return Out; }
-
- CodeViewContext &getCVContext() { return Ctx.getCVContext(); }
-
- unsigned getAssemblerDialect() override {
- if (AssemblerDialect == ~0U)
- return MAI.getAssemblerDialect();
- else
- return AssemblerDialect;
- }
- void setAssemblerDialect(unsigned i) override {
- AssemblerDialect = i;
- }
-
- void Note(SMLoc L, const Twine &Msg, SMRange Range = None) override;
- bool Warning(SMLoc L, const Twine &Msg, SMRange Range = None) override;
- bool printError(SMLoc L, const Twine &Msg, SMRange Range = None) override;
-
- const AsmToken &Lex() override;
-
- void setParsingInlineAsm(bool V) override {
- ParsingInlineAsm = V;
- // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and
- // hex integer literals.
- Lexer.setLexMasmIntegers(V);
- }
- bool isParsingInlineAsm() override { return ParsingInlineAsm; }
-
- bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
- unsigned &NumOutputs, unsigned &NumInputs,
- SmallVectorImpl<std::pair<void *,bool>> &OpDecls,
- SmallVectorImpl<std::string> &Constraints,
- SmallVectorImpl<std::string> &Clobbers,
- const MCInstrInfo *MII, const MCInstPrinter *IP,
- MCAsmParserSemaCallback &SI) override;
-
- bool parseExpression(const MCExpr *&Res);
- bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
- bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
- bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
- bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
- SMLoc &EndLoc) override;
- bool parseAbsoluteExpression(int64_t &Res) override;
-
- /// Parse a floating point expression using the float \p Semantics
- /// and set \p Res to the value.
- bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
-
- /// Parse an identifier or string (as a quoted identifier)
- /// and set \p Res to the identifier contents.
- bool parseIdentifier(StringRef &Res) override;
- void eatToEndOfStatement() override;
-
- bool checkForValidSection() override;
-
- /// }
-
-private:
- bool parseStatement(ParseStatementInfo &Info,
- MCAsmParserSemaCallback *SI);
- bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
- bool parseCppHashLineFilenameComment(SMLoc L);
-
- void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body,
- ArrayRef<MCAsmMacroParameter> Parameters);
- bool expandMacro(raw_svector_ostream &OS, StringRef Body,
- ArrayRef<MCAsmMacroParameter> Parameters,
- ArrayRef<MCAsmMacroArgument> A, bool EnableAtPseudoVariable,
- SMLoc L);
-
- /// Are macros enabled in the parser?
- bool areMacrosEnabled() {return MacrosEnabledFlag;}
-
- /// Control a flag in the parser that enables or disables macros.
- void setMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;}
-
- /// Are we inside a macro instantiation?
- bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
-
- /// Handle entry to macro instantiation.
- ///
- /// \param M The macro.
- /// \param NameLoc Instantiation location.
- bool handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc);
-
- /// Handle exit from macro instantiation.
- void handleMacroExit();
-
- /// Extract AsmTokens for a macro argument.
- bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg);
-
- /// Parse all macro arguments for a given macro.
- bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A);
-
- void printMacroInstantiations();
- void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
- SMRange Range = None) const {
- ArrayRef<SMRange> Ranges(Range);
- SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);
- }
- static void DiagHandler(const SMDiagnostic &Diag, void *Context);
-
- /// Should we emit DWARF describing this assembler source? (Returns false if
- /// the source has .file directives, which means we don't want to generate
- /// info describing the assembler source itself.)
- bool enabledGenDwarfForAssembly();
-
- /// Enter the specified file. This returns true on failure.
- bool enterIncludeFile(const std::string &Filename);
-
- /// Process the specified file for the .incbin directive.
- /// This returns true on failure.
- bool processIncbinFile(const std::string &Filename, int64_t Skip = 0,
- const MCExpr *Count = nullptr, SMLoc Loc = SMLoc());
-
- /// Reset the current lexer position to that given by \p Loc. The
- /// current token is not set; clients should ensure Lex() is called
- /// subsequently.
- ///
- /// \param InBuffer If not 0, should be the known buffer id that contains the
- /// location.
- void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0);
-
- /// Parse up to the end of statement and a return the contents from the
- /// current token until the end of the statement; the current token on exit
- /// will be either the EndOfStatement or EOF.
- StringRef parseStringToEndOfStatement() override;
-
- /// Parse until the end of a statement or a comma is encountered,
- /// return the contents from the current token up to the end or comma.
- StringRef parseStringToComma();
-
- bool parseAssignment(StringRef Name, bool allow_redef,
- bool NoDeadStrip = false);
-
- unsigned getBinOpPrecedence(AsmToken::TokenKind K,
- MCBinaryExpr::Opcode &Kind);
-
- bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
- bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
- bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);
-
- bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc);
-
- bool parseCVFunctionId(int64_t &FunctionId, StringRef DirectiveName);
- bool parseCVFileId(int64_t &FileId, StringRef DirectiveName);
-
- // Generic (target and platform independent) directive parsing.
- enum DirectiveKind {
- DK_NO_DIRECTIVE, // Placeholder
- DK_SET,
- DK_EQU,
- DK_EQUIV,
- DK_ASCII,
- DK_ASCIZ,
- DK_STRING,
- DK_BYTE,
- DK_SHORT,
- DK_RELOC,
- DK_VALUE,
- DK_2BYTE,
- DK_LONG,
- DK_INT,
- DK_4BYTE,
- DK_QUAD,
- DK_8BYTE,
- DK_OCTA,
- DK_DC,
- DK_DC_A,
- DK_DC_B,
- DK_DC_D,
- DK_DC_L,
- DK_DC_S,
- DK_DC_W,
- DK_DC_X,
- DK_DCB,
- DK_DCB_B,
- DK_DCB_D,
- DK_DCB_L,
- DK_DCB_S,
- DK_DCB_W,
- DK_DCB_X,
- DK_DS,
- DK_DS_B,
- DK_DS_D,
- DK_DS_L,
- DK_DS_P,
- DK_DS_S,
- DK_DS_W,
- DK_DS_X,
- DK_SINGLE,
- DK_FLOAT,
- DK_DOUBLE,
- DK_ALIGN,
- DK_ALIGN32,
- DK_BALIGN,
- DK_BALIGNW,
- DK_BALIGNL,
- DK_P2ALIGN,
- DK_P2ALIGNW,
- DK_P2ALIGNL,
- DK_ORG,
- DK_FILL,
- DK_ENDR,
- DK_BUNDLE_ALIGN_MODE,
- DK_BUNDLE_LOCK,
- DK_BUNDLE_UNLOCK,
- DK_ZERO,
- DK_EXTERN,
- DK_GLOBL,
- DK_GLOBAL,
- DK_LAZY_REFERENCE,
- DK_NO_DEAD_STRIP,
- DK_SYMBOL_RESOLVER,
- DK_PRIVATE_EXTERN,
- DK_REFERENCE,
- DK_WEAK_DEFINITION,
- DK_WEAK_REFERENCE,
- DK_WEAK_DEF_CAN_BE_HIDDEN,
- DK_COLD,
- DK_COMM,
- DK_COMMON,
- DK_LCOMM,
- DK_ABORT,
- DK_INCLUDE,
- DK_INCBIN,
- DK_CODE16,
- DK_CODE16GCC,
- DK_REPT,
- DK_IRP,
- DK_IRPC,
- DK_IF,
- DK_IFEQ,
- DK_IFGE,
- DK_IFGT,
- DK_IFLE,
- DK_IFLT,
- DK_IFNE,
- DK_IFB,
- DK_IFNB,
- DK_IFC,
- DK_IFEQS,
- DK_IFNC,
- DK_IFNES,
- DK_IFDEF,
- DK_IFNDEF,
- DK_IFNOTDEF,
- DK_ELSEIF,
- DK_ELSE,
- DK_ENDIF,
- DK_SPACE,
- DK_SKIP,
- DK_FILE,
- DK_LINE,
- DK_LOC,
- DK_STABS,
- DK_CV_FILE,
- DK_CV_FUNC_ID,
- DK_CV_INLINE_SITE_ID,
- DK_CV_LOC,
- DK_CV_LINETABLE,
- DK_CV_INLINE_LINETABLE,
- DK_CV_DEF_RANGE,
- DK_CV_STRINGTABLE,
- DK_CV_STRING,
- DK_CV_FILECHECKSUMS,
- DK_CV_FILECHECKSUM_OFFSET,
- DK_CV_FPO_DATA,
- DK_CFI_SECTIONS,
- DK_CFI_STARTPROC,
- DK_CFI_ENDPROC,
- DK_CFI_DEF_CFA,
- DK_CFI_DEF_CFA_OFFSET,
- DK_CFI_ADJUST_CFA_OFFSET,
- DK_CFI_DEF_CFA_REGISTER,
- DK_CFI_OFFSET,
- DK_CFI_REL_OFFSET,
- DK_CFI_PERSONALITY,
- DK_CFI_LSDA,
- DK_CFI_REMEMBER_STATE,
- DK_CFI_RESTORE_STATE,
- DK_CFI_SAME_VALUE,
- DK_CFI_RESTORE,
- DK_CFI_ESCAPE,
- DK_CFI_RETURN_COLUMN,
- DK_CFI_SIGNAL_FRAME,
- DK_CFI_UNDEFINED,
- DK_CFI_REGISTER,
- DK_CFI_WINDOW_SAVE,
- DK_CFI_B_KEY_FRAME,
- DK_MACROS_ON,
- DK_MACROS_OFF,
- DK_ALTMACRO,
- DK_NOALTMACRO,
- DK_MACRO,
- DK_EXITM,
- DK_ENDM,
- DK_ENDMACRO,
- DK_PURGEM,
- DK_SLEB128,
- DK_ULEB128,
- DK_ERR,
- DK_ERROR,
- DK_WARNING,
- DK_PRINT,
- DK_ADDRSIG,
- DK_ADDRSIG_SYM,
- DK_END
- };
-
- /// Maps directive name --> DirectiveKind enum, for
- /// directives parsed by this class.
- StringMap<DirectiveKind> DirectiveKindMap;
-
- // ".ascii", ".asciz", ".string"
- bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
- bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc"
- bool parseDirectiveValue(StringRef IDVal,
- unsigned Size); // ".byte", ".long", ...
- bool parseDirectiveOctaValue(StringRef IDVal); // ".octa", ...
- bool parseDirectiveRealValue(StringRef IDVal,
- const fltSemantics &); // ".single", ...
- bool parseDirectiveFill(); // ".fill"
- bool parseDirectiveZero(); // ".zero"
- // ".set", ".equ", ".equiv"
- bool parseDirectiveSet(StringRef IDVal, bool allow_redef);
- bool parseDirectiveOrg(); // ".org"
- // ".align{,32}", ".p2align{,w,l}"
- bool parseDirectiveAlign(bool IsPow2, unsigned ValueSize);
-
- // ".file", ".line", ".loc", ".stabs"
- bool parseDirectiveFile(SMLoc DirectiveLoc);
- bool parseDirectiveLine();
- bool parseDirectiveLoc();
- bool parseDirectiveStabs();
-
- // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",
- // ".cv_inline_linetable", ".cv_def_range", ".cv_string"
- bool parseDirectiveCVFile();
- bool parseDirectiveCVFuncId();
- bool parseDirectiveCVInlineSiteId();
- bool parseDirectiveCVLoc();
- bool parseDirectiveCVLinetable();
- bool parseDirectiveCVInlineLinetable();
- bool parseDirectiveCVDefRange();
- bool parseDirectiveCVString();
- bool parseDirectiveCVStringTable();
- bool parseDirectiveCVFileChecksums();
- bool parseDirectiveCVFileChecksumOffset();
- bool parseDirectiveCVFPOData();
-
- // .cfi directives
- bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
- bool parseDirectiveCFIWindowSave();
- bool parseDirectiveCFISections();
- bool parseDirectiveCFIStartProc();
- bool parseDirectiveCFIEndProc();
- bool parseDirectiveCFIDefCfaOffset();
- bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc);
- bool parseDirectiveCFIAdjustCfaOffset();
- bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);
- bool parseDirectiveCFIOffset(SMLoc DirectiveLoc);
- bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc);
- bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality);
- bool parseDirectiveCFIRememberState();
- bool parseDirectiveCFIRestoreState();
- bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);
- bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);
- bool parseDirectiveCFIEscape();
- bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);
- bool parseDirectiveCFISignalFrame();
- bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
-
- // macro directives
- bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
- bool parseDirectiveExitMacro(StringRef Directive);
- bool parseDirectiveEndMacro(StringRef Directive);
- bool parseDirectiveMacro(SMLoc DirectiveLoc);
- bool parseDirectiveMacrosOnOff(StringRef Directive);
- // alternate macro mode directives
- bool parseDirectiveAltmacro(StringRef Directive);
- // ".bundle_align_mode"
- bool parseDirectiveBundleAlignMode();
- // ".bundle_lock"
- bool parseDirectiveBundleLock();
- // ".bundle_unlock"
- bool parseDirectiveBundleUnlock();
-
- // ".space", ".skip"
- bool parseDirectiveSpace(StringRef IDVal);
-
- // ".dcb"
- bool parseDirectiveDCB(StringRef IDVal, unsigned Size);
- bool parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &);
- // ".ds"
- bool parseDirectiveDS(StringRef IDVal, unsigned Size);
-
- // .sleb128 (Signed=true) and .uleb128 (Signed=false)
- bool parseDirectiveLEB128(bool Signed);
-
- /// Parse a directive like ".globl" which
- /// accepts a single symbol (which should be a label or an external).
- bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
-
- bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
-
- bool parseDirectiveAbort(); // ".abort"
- bool parseDirectiveInclude(); // ".include"
- bool parseDirectiveIncbin(); // ".incbin"
-
- // ".if", ".ifeq", ".ifge", ".ifgt" , ".ifle", ".iflt" or ".ifne"
- bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
- // ".ifb" or ".ifnb", depending on ExpectBlank.
- bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
- // ".ifc" or ".ifnc", depending on ExpectEqual.
- bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual);
- // ".ifeqs" or ".ifnes", depending on ExpectEqual.
- bool parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual);
- // ".ifdef" or ".ifndef", depending on expect_defined
- bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
- bool parseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
- bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else"
- bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
- bool parseEscapedString(std::string &Data) override;
-
- const MCExpr *applyModifierToExpr(const MCExpr *E,
- MCSymbolRefExpr::VariantKind Variant);
-
- // Macro-like directives
- MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
- void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
- raw_svector_ostream &OS);
- bool parseDirectiveRept(SMLoc DirectiveLoc, StringRef Directive);
- bool parseDirectiveIrp(SMLoc DirectiveLoc); // ".irp"
- bool parseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"
- bool parseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
-
- // "_emit" or "__emit"
- bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
- size_t Len);
-
- // "align"
- bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
-
- // "end"
- bool parseDirectiveEnd(SMLoc DirectiveLoc);
-
- // ".err" or ".error"
- bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage);
-
- // ".warning"
- bool parseDirectiveWarning(SMLoc DirectiveLoc);
-
- // .print <double-quotes-string>
- bool parseDirectivePrint(SMLoc DirectiveLoc);
-
- // Directives to support address-significance tables.
- bool parseDirectiveAddrsig();
- bool parseDirectiveAddrsigSym();
-
- void initializeDirectiveKindMap();
-};
-
-} // end anonymous namespace
-
-namespace llvm {
-
-extern MCAsmParserExtension *createDarwinAsmParser();
-extern MCAsmParserExtension *createELFAsmParser();
-extern MCAsmParserExtension *createCOFFAsmParser();
-extern MCAsmParserExtension *createWasmAsmParser();
-
-} // end namespace llvm
-
-enum { DEFAULT_ADDRSPACE = 0 };
-
-AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
- const MCAsmInfo &MAI, unsigned CB = 0)
- : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),
- CurBuffer(CB ? CB : SM.getMainFileID()), MacrosEnabledFlag(true) {
- HadError = false;
- // Save the old handler.
- SavedDiagHandler = SrcMgr.getDiagHandler();
- SavedDiagContext = SrcMgr.getDiagContext();
- // Set our own handler which calls the saved handler.
- SrcMgr.setDiagHandler(DiagHandler, this);
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
-
- // Initialize the platform / file format parser.
- switch (Ctx.getObjectFileInfo()->getObjectFileType()) {
- case MCObjectFileInfo::IsCOFF:
- PlatformParser.reset(createCOFFAsmParser());
- break;
- case MCObjectFileInfo::IsMachO:
- PlatformParser.reset(createDarwinAsmParser());
- IsDarwin = true;
- break;
- case MCObjectFileInfo::IsELF:
- PlatformParser.reset(createELFAsmParser());
- break;
- case MCObjectFileInfo::IsWasm:
- PlatformParser.reset(createWasmAsmParser());
- break;
- case MCObjectFileInfo::IsXCOFF:
- // TODO: Need to implement createXCOFFAsmParser for XCOFF format.
- break;
- }
-
- PlatformParser->Initialize(*this);
- initializeDirectiveKindMap();
-
- NumOfMacroInstantiations = 0;
-}
-
-AsmParser::~AsmParser() {
- assert((HadError || ActiveMacros.empty()) &&
- "Unexpected active macro instantiation!");
-
- // Restore the saved diagnostics handler and context for use during
- // finalization.
- SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);
-}
-
-void AsmParser::printMacroInstantiations() {
- // Print the active macro instantiation stack.
- for (std::vector<MacroInstantiation *>::const_reverse_iterator
- it = ActiveMacros.rbegin(),
- ie = ActiveMacros.rend();
- it != ie; ++it)
- printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note,
- "while in macro instantiation");
-}
-
-void AsmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {
- printPendingErrors();
- printMessage(L, SourceMgr::DK_Note, Msg, Range);
- printMacroInstantiations();
-}
-
-bool AsmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
- if(getTargetParser().getTargetOptions().MCNoWarn)
- return false;
- if (getTargetParser().getTargetOptions().MCFatalWarnings)
- return Error(L, Msg, Range);
- printMessage(L, SourceMgr::DK_Warning, Msg, Range);
- printMacroInstantiations();
- return false;
-}
-
-bool AsmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
- HadError = true;
- printMessage(L, SourceMgr::DK_Error, Msg, Range);
- printMacroInstantiations();
- return true;
-}
-
-bool AsmParser::enterIncludeFile(const std::string &Filename) {
- std::string IncludedFile;
- unsigned NewBuf =
- SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
- if (!NewBuf)
- return true;
-
- CurBuffer = NewBuf;
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
- return false;
-}
-
-/// Process the specified .incbin file by searching for it in the include paths
-/// then just emitting the byte contents of the file to the streamer. This
-/// returns true on failure.
-bool AsmParser::processIncbinFile(const std::string &Filename, int64_t Skip,
- const MCExpr *Count, SMLoc Loc) {
- std::string IncludedFile;
- unsigned NewBuf =
- SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
- if (!NewBuf)
- return true;
-
- // Pick up the bytes from the file and emit them.
- StringRef Bytes = SrcMgr.getMemoryBuffer(NewBuf)->getBuffer();
- Bytes = Bytes.drop_front(Skip);
- if (Count) {
- int64_t Res;
- if (!Count->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
- return Error(Loc, "expected absolute expression");
- if (Res < 0)
- return Warning(Loc, "negative count has no effect");
- Bytes = Bytes.take_front(Res);
- }
- getStreamer().EmitBytes(Bytes);
- return false;
-}
-
-void AsmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) {
- CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),
- Loc.getPointer());
-}
-
-const AsmToken &AsmParser::Lex() {
- if (Lexer.getTok().is(AsmToken::Error))
- Error(Lexer.getErrLoc(), Lexer.getErr());
-
- // if it's a end of statement with a comment in it
- if (getTok().is(AsmToken::EndOfStatement)) {
- // if this is a line comment output it.
- if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&
- getTok().getString().front() != '\r' && MAI.preserveAsmComments())
- Out.addExplicitComment(Twine(getTok().getString()));
- }
-
- const AsmToken *tok = &Lexer.Lex();
-
- // Parse comments here to be deferred until end of next statement.
- while (tok->is(AsmToken::Comment)) {
- if (MAI.preserveAsmComments())
- Out.addExplicitComment(Twine(tok->getString()));
- tok = &Lexer.Lex();
- }
-
- if (tok->is(AsmToken::Eof)) {
- // If this is the end of an included file, pop the parent file off the
- // include stack.
- SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
- if (ParentIncludeLoc != SMLoc()) {
- jumpToLoc(ParentIncludeLoc);
- return Lex();
- }
- }
-
- return *tok;
-}
-
-bool AsmParser::enabledGenDwarfForAssembly() {
- // Check whether the user specified -g.
- if (!getContext().getGenDwarfForAssembly())
- return false;
- // If we haven't encountered any .file directives (which would imply that
- // the assembler source was produced with debug info already) then emit one
- // describing the assembler source file itself.
- if (getContext().getGenDwarfFileNumber() == 0) {
- // Use the first #line directive for this, if any. It's preprocessed, so
- // there is no checksum, and of course no source directive.
- if (!FirstCppHashFilename.empty())
- getContext().setMCLineTableRootFile(/*CUID=*/0,
- getContext().getCompilationDir(),
- FirstCppHashFilename,
- /*Cksum=*/None, /*Source=*/None);
- const MCDwarfFile &RootFile =
- getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile();
- getContext().setGenDwarfFileNumber(getStreamer().EmitDwarfFileDirective(
- /*CUID=*/0, getContext().getCompilationDir(), RootFile.Name,
- RootFile.Checksum, RootFile.Source));
- }
- return true;
-}
-
-bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
- // Create the initial section, if requested.
- if (!NoInitialTextSection)
- Out.InitSections(false);
-
- // Prime the lexer.
- Lex();
-
- HadError = false;
- AsmCond StartingCondState = TheCondState;
- SmallVector<AsmRewrite, 4> AsmStrRewrites;
-
- // If we are generating dwarf for assembly source files save the initial text
- // section. (Don't use enabledGenDwarfForAssembly() here, as we aren't
- // emitting any actual debug info yet and haven't had a chance to parse any
- // embedded .file directives.)
- if (getContext().getGenDwarfForAssembly()) {
- MCSection *Sec = getStreamer().getCurrentSectionOnly();
- if (!Sec->getBeginSymbol()) {
- MCSymbol *SectionStartSym = getContext().createTempSymbol();
- getStreamer().EmitLabel(SectionStartSym);
- Sec->setBeginSymbol(SectionStartSym);
- }
- bool InsertResult = getContext().addGenDwarfSection(Sec);
- assert(InsertResult && ".text section should not have debug info yet");
- (void)InsertResult;
- }
-
- // While we have input, parse each statement.
- while (Lexer.isNot(AsmToken::Eof)) {
- ParseStatementInfo Info(&AsmStrRewrites);
- if (!parseStatement(Info, nullptr))
- continue;
-
- // If we have a Lexer Error we are on an Error Token. Load in Lexer Error
- // for printing ErrMsg via Lex() only if no (presumably better) parser error
- // exists.
- if (!hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
- Lex();
- }
-
- // parseStatement returned true so may need to emit an error.
- printPendingErrors();
-
- // Skipping to the next line if needed.
- if (!getLexer().isAtStartOfStatement())
- eatToEndOfStatement();
- }
-
- getTargetParser().onEndOfFile();
- printPendingErrors();
-
- // All errors should have been emitted.
- assert(!hasPendingError() && "unexpected error from parseStatement");
-
- getTargetParser().flushPendingInstructions(getStreamer());
-
- if (TheCondState.TheCond != StartingCondState.TheCond ||
- TheCondState.Ignore != StartingCondState.Ignore)
- printError(getTok().getLoc(), "unmatched .ifs or .elses");
- // Check to see there are no empty DwarfFile slots.
- const auto &LineTables = getContext().getMCDwarfLineTables();
- if (!LineTables.empty()) {
- unsigned Index = 0;
- for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) {
- if (File.Name.empty() && Index != 0)
- printError(getTok().getLoc(), "unassigned file number: " +
- Twine(Index) +
- " for .file directives");
- ++Index;
- }
- }
-
- // Check to see that all assembler local symbols were actually defined.
- // Targets that don't do subsections via symbols may not want this, though,
- // so conservatively exclude them. Only do this if we're finalizing, though,
- // as otherwise we won't necessarilly have seen everything yet.
- if (!NoFinalize) {
- if (MAI.hasSubsectionsViaSymbols()) {
- for (const auto &TableEntry : getContext().getSymbols()) {
- MCSymbol *Sym = TableEntry.getValue();
- // Variable symbols may not be marked as defined, so check those
- // explicitly. If we know it's a variable, we have a definition for
- // the purposes of this check.
- if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined())
- // FIXME: We would really like to refer back to where the symbol was
- // first referenced for a source location. We need to add something
- // to track that. Currently, we just point to the end of the file.
- printError(getTok().getLoc(), "assembler local symbol '" +
- Sym->getName() + "' not defined");
- }
- }
-
- // Temporary symbols like the ones for directional jumps don't go in the
- // symbol table. They also need to be diagnosed in all (final) cases.
- for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
- if (std::get<2>(LocSym)->isUndefined()) {
- // Reset the state of any "# line file" directives we've seen to the
- // context as it was at the diagnostic site.
- CppHashInfo = std::get<1>(LocSym);
- printError(std::get<0>(LocSym), "directional label undefined");
- }
- }
- }
-
- // Finalize the output stream if there are no errors and if the client wants
- // us to.
- if (!HadError && !NoFinalize)
- Out.Finish();
-
- return HadError || getContext().hadError();
-}
-
-bool AsmParser::checkForValidSection() {
- if (!ParsingInlineAsm && !getStreamer().getCurrentSectionOnly()) {
- Out.InitSections(false);
- return Error(getTok().getLoc(),
- "expected section directive before assembly directive");
- }
- return false;
-}
-
-/// Throw away the rest of the line for testing purposes.
-void AsmParser::eatToEndOfStatement() {
- while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
- Lexer.Lex();
-
- // Eat EOL.
- if (Lexer.is(AsmToken::EndOfStatement))
- Lexer.Lex();
-}
-
-StringRef AsmParser::parseStringToEndOfStatement() {
- const char *Start = getTok().getLoc().getPointer();
-
- while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
- Lexer.Lex();
-
- const char *End = getTok().getLoc().getPointer();
- return StringRef(Start, End - Start);
-}
-
-StringRef AsmParser::parseStringToComma() {
- const char *Start = getTok().getLoc().getPointer();
-
- while (Lexer.isNot(AsmToken::EndOfStatement) &&
- Lexer.isNot(AsmToken::Comma) && Lexer.isNot(AsmToken::Eof))
- Lexer.Lex();
-
- const char *End = getTok().getLoc().getPointer();
- return StringRef(Start, End - Start);
-}
-
-/// Parse a paren expression and return it.
-/// NOTE: This assumes the leading '(' has already been consumed.
-///
-/// parenexpr ::= expr)
-///
-bool AsmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
- if (parseExpression(Res))
- return true;
- if (Lexer.isNot(AsmToken::RParen))
- return TokError("expected ')' in parentheses expression");
- EndLoc = Lexer.getTok().getEndLoc();
- Lex();
- return false;
-}
-
-/// Parse a bracket expression and return it.
-/// NOTE: This assumes the leading '[' has already been consumed.
-///
-/// bracketexpr ::= expr]
-///
-bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
- if (parseExpression(Res))
- return true;
- EndLoc = getTok().getEndLoc();
- if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))
- return true;
- return false;
-}
-
-/// Parse a primary expression and return it.
-/// primaryexpr ::= (parenexpr
-/// primaryexpr ::= symbol
-/// primaryexpr ::= number
-/// primaryexpr ::= '.'
-/// primaryexpr ::= ~,+,- primaryexpr
-bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
- SMLoc FirstTokenLoc = getLexer().getLoc();
- AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
- switch (FirstTokenKind) {
- default:
- return TokError("unknown token in expression");
- // If we have an error assume that we've already handled it.
- case AsmToken::Error:
- return true;
- case AsmToken::Exclaim:
- Lex(); // Eat the operator.
- if (parsePrimaryExpr(Res, EndLoc))
- return true;
- Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
- return false;
- case AsmToken::Dollar:
- case AsmToken::At:
- case AsmToken::String:
- case AsmToken::Identifier: {
- StringRef Identifier;
- if (parseIdentifier(Identifier)) {
- // We may have failed but $ may be a valid token.
- if (getTok().is(AsmToken::Dollar)) {
- if (Lexer.getMAI().getDollarIsPC()) {
- Lex();
- // This is a '$' reference, which references the current PC. Emit a
- // temporary label to the streamer and refer to it.
- MCSymbol *Sym = Ctx.createTempSymbol();
- Out.EmitLabel(Sym);
- Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
- getContext());
- EndLoc = FirstTokenLoc;
- return false;
- }
- return Error(FirstTokenLoc, "invalid token in expression");
- }
- }
- // Parse symbol variant
- std::pair<StringRef, StringRef> Split;
- if (!MAI.useParensForSymbolVariant()) {
- if (FirstTokenKind == AsmToken::String) {
- if (Lexer.is(AsmToken::At)) {
- Lex(); // eat @
- SMLoc AtLoc = getLexer().getLoc();
- StringRef VName;
- if (parseIdentifier(VName))
- return Error(AtLoc, "expected symbol variant after '@'");
-
- Split = std::make_pair(Identifier, VName);
- }
- } else {
- Split = Identifier.split('@');
- }
- } else if (Lexer.is(AsmToken::LParen)) {
- Lex(); // eat '('.
- StringRef VName;
- parseIdentifier(VName);
- // eat ')'.
- if (parseToken(AsmToken::RParen,
- "unexpected token in variant, expected ')'"))
- return true;
- Split = std::make_pair(Identifier, VName);
- }
-
- EndLoc = SMLoc::getFromPointer(Identifier.end());
-
- // This is a symbol reference.
- StringRef SymbolName = Identifier;
- if (SymbolName.empty())
- return Error(getLexer().getLoc(), "expected a symbol reference");
-
- MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
-
- // Lookup the symbol variant if used.
- if (!Split.second.empty()) {
- Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
- if (Variant != MCSymbolRefExpr::VK_Invalid) {
- SymbolName = Split.first;
- } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) {
- Variant = MCSymbolRefExpr::VK_None;
- } else {
- return Error(SMLoc::getFromPointer(Split.second.begin()),
- "invalid variant '" + Split.second + "'");
- }
- }
-
- MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);
- if (!Sym)
- Sym = getContext().getOrCreateSymbol(SymbolName);
-
- // If this is an absolute variable reference, substitute it now to preserve
- // semantics in the face of reassignment.
- if (Sym->isVariable()) {
- auto V = Sym->getVariableValue(/*SetUsed*/ false);
- bool DoInline = isa<MCConstantExpr>(V) && !Variant;
- if (auto TV = dyn_cast<MCTargetExpr>(V))
- DoInline = TV->inlineAssignedExpr();
- if (DoInline) {
- if (Variant)
- return Error(EndLoc, "unexpected modifier on variable reference");
- Res = Sym->getVariableValue(/*SetUsed*/ false);
- return false;
- }
- }
-
- // Otherwise create a symbol ref.
- Res = MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc);
- return false;
- }
- case AsmToken::BigNum:
- return TokError("literal value out of range for directive");
- case AsmToken::Integer: {
- SMLoc Loc = getTok().getLoc();
- int64_t IntVal = getTok().getIntVal();
- Res = MCConstantExpr::create(IntVal, getContext());
- EndLoc = Lexer.getTok().getEndLoc();
- Lex(); // Eat token.
- // Look for 'b' or 'f' following an Integer as a directional label
- if (Lexer.getKind() == AsmToken::Identifier) {
- StringRef IDVal = getTok().getString();
- // Lookup the symbol variant if used.
- std::pair<StringRef, StringRef> Split = IDVal.split('@');
- MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
- if (Split.first.size() != IDVal.size()) {
- Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
- if (Variant == MCSymbolRefExpr::VK_Invalid)
- return TokError("invalid variant '" + Split.second + "'");
- IDVal = Split.first;
- }
- if (IDVal == "f" || IDVal == "b") {
- MCSymbol *Sym =
- Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b");
- Res = MCSymbolRefExpr::create(Sym, Variant, getContext());
- if (IDVal == "b" && Sym->isUndefined())
- return Error(Loc, "directional label undefined");
- DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym));
- EndLoc = Lexer.getTok().getEndLoc();
- Lex(); // Eat identifier.
- }
- }
- return false;
- }
- case AsmToken::Real: {
- APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
- uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
- Res = MCConstantExpr::create(IntVal, getContext());
- EndLoc = Lexer.getTok().getEndLoc();
- Lex(); // Eat token.
- return false;
- }
- case AsmToken::Dot: {
- // This is a '.' reference, which references the current PC. Emit a
- // temporary label to the streamer and refer to it.
- MCSymbol *Sym = Ctx.createTempSymbol();
- Out.EmitLabel(Sym);
- Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
- EndLoc = Lexer.getTok().getEndLoc();
- Lex(); // Eat identifier.
- return false;
- }
- case AsmToken::LParen:
- Lex(); // Eat the '('.
- return parseParenExpr(Res, EndLoc);
- case AsmToken::LBrac:
- if (!PlatformParser->HasBracketExpressions())
- return TokError("brackets expression not supported on this target");
- Lex(); // Eat the '['.
- return parseBracketExpr(Res, EndLoc);
- case AsmToken::Minus:
- Lex(); // Eat the operator.
- if (parsePrimaryExpr(Res, EndLoc))
- return true;
- Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);
- return false;
- case AsmToken::Plus:
- Lex(); // Eat the operator.
- if (parsePrimaryExpr(Res, EndLoc))
- return true;
- Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);
- return false;
- case AsmToken::Tilde:
- Lex(); // Eat the operator.
- if (parsePrimaryExpr(Res, EndLoc))
- return true;
- Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
- return false;
- // MIPS unary expression operators. The lexer won't generate these tokens if
- // MCAsmInfo::HasMipsExpressions is false for the target.
- case AsmToken::PercentCall16:
- case AsmToken::PercentCall_Hi:
- case AsmToken::PercentCall_Lo:
- case AsmToken::PercentDtprel_Hi:
- case AsmToken::PercentDtprel_Lo:
- case AsmToken::PercentGot:
- case AsmToken::PercentGot_Disp:
- case AsmToken::PercentGot_Hi:
- case AsmToken::PercentGot_Lo:
- case AsmToken::PercentGot_Ofst:
- case AsmToken::PercentGot_Page:
- case AsmToken::PercentGottprel:
- case AsmToken::PercentGp_Rel:
- case AsmToken::PercentHi:
- case AsmToken::PercentHigher:
- case AsmToken::PercentHighest:
- case AsmToken::PercentLo:
- case AsmToken::PercentNeg:
- case AsmToken::PercentPcrel_Hi:
- case AsmToken::PercentPcrel_Lo:
- case AsmToken::PercentTlsgd:
- case AsmToken::PercentTlsldm:
- case AsmToken::PercentTprel_Hi:
- case AsmToken::PercentTprel_Lo:
- Lex(); // Eat the operator.
- if (Lexer.isNot(AsmToken::LParen))
- return TokError("expected '(' after operator");
- Lex(); // Eat the operator.
- if (parseExpression(Res, EndLoc))
- return true;
- if (Lexer.isNot(AsmToken::RParen))
- return TokError("expected ')'");
- Lex(); // Eat the operator.
- Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx);
- return !Res;
- }
-}
-
-bool AsmParser::parseExpression(const MCExpr *&Res) {
- SMLoc EndLoc;
- return parseExpression(Res, EndLoc);
-}
-
-const MCExpr *
-AsmParser::applyModifierToExpr(const MCExpr *E,
- MCSymbolRefExpr::VariantKind Variant) {
- // Ask the target implementation about this expression first.
- const MCExpr *NewE = getTargetParser().applyModifierToExpr(E, Variant, Ctx);
- if (NewE)
- return NewE;
- // Recurse over the given expression, rebuilding it to apply the given variant
- // if there is exactly one symbol.
- switch (E->getKind()) {
- case MCExpr::Target:
- case MCExpr::Constant:
- return nullptr;
-
- case MCExpr::SymbolRef: {
- const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
-
- if (SRE->getKind() != MCSymbolRefExpr::VK_None) {
- TokError("invalid variant on expression '" + getTok().getIdentifier() +
- "' (already modified)");
- return E;
- }
-
- return MCSymbolRefExpr::create(&SRE->getSymbol(), Variant, getContext());
- }
-
- case MCExpr::Unary: {
- const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
- const MCExpr *Sub = applyModifierToExpr(UE->getSubExpr(), Variant);
- if (!Sub)
- return nullptr;
- return MCUnaryExpr::create(UE->getOpcode(), Sub, getContext());
- }
-
- case MCExpr::Binary: {
- const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
- const MCExpr *LHS = applyModifierToExpr(BE->getLHS(), Variant);
- const MCExpr *RHS = applyModifierToExpr(BE->getRHS(), Variant);
-
- if (!LHS && !RHS)
- return nullptr;
-
- if (!LHS)
- LHS = BE->getLHS();
- if (!RHS)
- RHS = BE->getRHS();
-
- return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, getContext());
- }
- }
-
- llvm_unreachable("Invalid expression kind!");
-}
-
-/// This function checks if the next token is <string> type or arithmetic.
-/// string that begin with character '<' must end with character '>'.
-/// otherwise it is arithmetics.
-/// If the function returns a 'true' value,
-/// the End argument will be filled with the last location pointed to the '>'
-/// character.
-
-/// There is a gap between the AltMacro's documentation and the single quote
-/// implementation. GCC does not fully support this feature and so we will not
-/// support it.
-/// TODO: Adding single quote as a string.
-static bool isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc) {
- assert((StrLoc.getPointer() != nullptr) &&
- "Argument to the function cannot be a NULL value");
- const char *CharPtr = StrLoc.getPointer();
- while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
- (*CharPtr != '\0')) {
- if (*CharPtr == '!')
- CharPtr++;
- CharPtr++;
- }
- if (*CharPtr == '>') {
- EndLoc = StrLoc.getFromPointer(CharPtr + 1);
- return true;
- }
- return false;
-}
-
-/// creating a string without the escape characters '!'.
-static std::string altMacroString(StringRef AltMacroStr) {
- std::string Res;
- for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {
- if (AltMacroStr[Pos] == '!')
- Pos++;
- Res += AltMacroStr[Pos];
- }
- return Res;
-}
-
-/// Parse an expression and return it.
-///
-/// expr ::= expr &&,|| expr -> lowest.
-/// expr ::= expr |,^,&,! expr
-/// expr ::= expr ==,!=,<>,<,<=,>,>= expr
-/// expr ::= expr <<,>> expr
-/// expr ::= expr +,- expr
-/// expr ::= expr *,/,% expr -> highest.
-/// expr ::= primaryexpr
-///
-bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
- // Parse the expression.
- Res = nullptr;
- if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
- parseBinOpRHS(1, Res, EndLoc))
- return true;
-
- // As a special case, we support 'a op b @ modifier' by rewriting the
- // expression to include the modifier. This is inefficient, but in general we
- // expect users to use 'a@modifier op b'.
- if (Lexer.getKind() == AsmToken::At) {
- Lex();
-
- if (Lexer.isNot(AsmToken::Identifier))
- return TokError("unexpected symbol modifier following '@'");
-
- MCSymbolRefExpr::VariantKind Variant =
- MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier());
- if (Variant == MCSymbolRefExpr::VK_Invalid)
- return TokError("invalid variant '" + getTok().getIdentifier() + "'");
-
- const MCExpr *ModifiedRes = applyModifierToExpr(Res, Variant);
- if (!ModifiedRes) {
- return TokError("invalid modifier '" + getTok().getIdentifier() +
- "' (no symbols present)");
- }
-
- Res = ModifiedRes;
- Lex();
- }
-
- // Try to constant fold it up front, if possible. Do not exploit
- // assembler here.
- int64_t Value;
- if (Res->evaluateAsAbsolute(Value))
- Res = MCConstantExpr::create(Value, getContext());
-
- return false;
-}
-
-bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
- Res = nullptr;
- return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
-}
-
-bool AsmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
- SMLoc &EndLoc) {
- if (parseParenExpr(Res, EndLoc))
- return true;
-
- for (; ParenDepth > 0; --ParenDepth) {
- if (parseBinOpRHS(1, Res, EndLoc))
- return true;
-
- // We don't Lex() the last RParen.
- // This is the same behavior as parseParenExpression().
- if (ParenDepth - 1 > 0) {
- EndLoc = getTok().getEndLoc();
- if (parseToken(AsmToken::RParen,
- "expected ')' in parentheses expression"))
- return true;
- }
- }
- return false;
-}
-
-bool AsmParser::parseAbsoluteExpression(int64_t &Res) {
- const MCExpr *Expr;
-
- SMLoc StartLoc = Lexer.getLoc();
- if (parseExpression(Expr))
- return true;
-
- if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
- return Error(StartLoc, "expected absolute expression");
-
- return false;
-}
-
-static unsigned getDarwinBinOpPrecedence(AsmToken::TokenKind K,
- MCBinaryExpr::Opcode &Kind,
- bool ShouldUseLogicalShr) {
- switch (K) {
- default:
- return 0; // not a binop.
-
- // Lowest Precedence: &&, ||
- case AsmToken::AmpAmp:
- Kind = MCBinaryExpr::LAnd;
- return 1;
- case AsmToken::PipePipe:
- Kind = MCBinaryExpr::LOr;
- return 1;
-
- // Low Precedence: |, &, ^
- //
- // FIXME: gas seems to support '!' as an infix operator?
- case AsmToken::Pipe:
- Kind = MCBinaryExpr::Or;
- return 2;
- case AsmToken::Caret:
- Kind = MCBinaryExpr::Xor;
- return 2;
- case AsmToken::Amp:
- Kind = MCBinaryExpr::And;
- return 2;
-
- // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >=
- case AsmToken::EqualEqual:
- Kind = MCBinaryExpr::EQ;
- return 3;
- case AsmToken::ExclaimEqual:
- case AsmToken::LessGreater:
- Kind = MCBinaryExpr::NE;
- return 3;
- case AsmToken::Less:
- Kind = MCBinaryExpr::LT;
- return 3;
- case AsmToken::LessEqual:
- Kind = MCBinaryExpr::LTE;
- return 3;
- case AsmToken::Greater:
- Kind = MCBinaryExpr::GT;
- return 3;
- case AsmToken::GreaterEqual:
- Kind = MCBinaryExpr::GTE;
- return 3;
-
- // Intermediate Precedence: <<, >>
- case AsmToken::LessLess:
- Kind = MCBinaryExpr::Shl;
- return 4;
- case AsmToken::GreaterGreater:
- Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
- return 4;
-
- // High Intermediate Precedence: +, -
- case AsmToken::Plus:
- Kind = MCBinaryExpr::Add;
- return 5;
- case AsmToken::Minus:
- Kind = MCBinaryExpr::Sub;
- return 5;
-
- // Highest Precedence: *, /, %
- case AsmToken::Star:
- Kind = MCBinaryExpr::Mul;
- return 6;
- case AsmToken::Slash:
- Kind = MCBinaryExpr::Div;
- return 6;
- case AsmToken::Percent:
- Kind = MCBinaryExpr::Mod;
- return 6;
- }
-}
-
-static unsigned getGNUBinOpPrecedence(AsmToken::TokenKind K,
- MCBinaryExpr::Opcode &Kind,
- bool ShouldUseLogicalShr) {
- switch (K) {
- default:
- return 0; // not a binop.
-
- // Lowest Precedence: &&, ||
- case AsmToken::AmpAmp:
- Kind = MCBinaryExpr::LAnd;
- return 2;
- case AsmToken::PipePipe:
- Kind = MCBinaryExpr::LOr;
- return 1;
-
- // Low Precedence: ==, !=, <>, <, <=, >, >=
- case AsmToken::EqualEqual:
- Kind = MCBinaryExpr::EQ;
- return 3;
- case AsmToken::ExclaimEqual:
- case AsmToken::LessGreater:
- Kind = MCBinaryExpr::NE;
- return 3;
- case AsmToken::Less:
- Kind = MCBinaryExpr::LT;
- return 3;
- case AsmToken::LessEqual:
- Kind = MCBinaryExpr::LTE;
- return 3;
- case AsmToken::Greater:
- Kind = MCBinaryExpr::GT;
- return 3;
- case AsmToken::GreaterEqual:
- Kind = MCBinaryExpr::GTE;
- return 3;
-
- // Low Intermediate Precedence: +, -
- case AsmToken::Plus:
- Kind = MCBinaryExpr::Add;
- return 4;
- case AsmToken::Minus:
- Kind = MCBinaryExpr::Sub;
- return 4;
-
- // High Intermediate Precedence: |, &, ^
- //
- // FIXME: gas seems to support '!' as an infix operator?
- case AsmToken::Pipe:
- Kind = MCBinaryExpr::Or;
- return 5;
- case AsmToken::Caret:
- Kind = MCBinaryExpr::Xor;
- return 5;
- case AsmToken::Amp:
- Kind = MCBinaryExpr::And;
- return 5;
-
- // Highest Precedence: *, /, %, <<, >>
- case AsmToken::Star:
- Kind = MCBinaryExpr::Mul;
- return 6;
- case AsmToken::Slash:
- Kind = MCBinaryExpr::Div;
- return 6;
- case AsmToken::Percent:
- Kind = MCBinaryExpr::Mod;
- return 6;
- case AsmToken::LessLess:
- Kind = MCBinaryExpr::Shl;
- return 6;
- case AsmToken::GreaterGreater:
- Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
- return 6;
- }
-}
-
-unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K,
- MCBinaryExpr::Opcode &Kind) {
- bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();
- return IsDarwin ? getDarwinBinOpPrecedence(K, Kind, ShouldUseLogicalShr)
- : getGNUBinOpPrecedence(K, Kind, ShouldUseLogicalShr);
-}
-
-/// Parse all binary operators with precedence >= 'Precedence'.
-/// Res contains the LHS of the expression on input.
-bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
- SMLoc &EndLoc) {
- SMLoc StartLoc = Lexer.getLoc();
- while (true) {
- MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
- unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
-
- // If the next token is lower precedence than we are allowed to eat, return
- // successfully with what we ate already.
- if (TokPrec < Precedence)
- return false;
-
- Lex();
-
- // Eat the next primary expression.
- const MCExpr *RHS;
- if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))
- return true;
-
- // If BinOp binds less tightly with RHS than the operator after RHS, let
- // the pending operator take RHS as its LHS.
- MCBinaryExpr::Opcode Dummy;
- unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
- if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))
- return true;
-
- // Merge LHS and RHS according to operator.
- Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc);
- }
-}
-
-/// ParseStatement:
-/// ::= EndOfStatement
-/// ::= Label* Directive ...Operands... EndOfStatement
-/// ::= Label* Identifier OperandList* EndOfStatement
-bool AsmParser::parseStatement(ParseStatementInfo &Info,
- MCAsmParserSemaCallback *SI) {
- assert(!hasPendingError() && "parseStatement started with pending error");
- // Eat initial spaces and comments
- while (Lexer.is(AsmToken::Space))
- Lex();
- if (Lexer.is(AsmToken::EndOfStatement)) {
- // if this is a line comment we can drop it safely
- if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
- getTok().getString().front() == '\n')
- Out.AddBlankLine();
- Lex();
- return false;
- }
- // Statements always start with an identifier.
- AsmToken ID = getTok();
- SMLoc IDLoc = ID.getLoc();
- StringRef IDVal;
- int64_t LocalLabelVal = -1;
- if (Lexer.is(AsmToken::HashDirective))
- return parseCppHashLineFilenameComment(IDLoc);
- // Allow an integer followed by a ':' as a directional local label.
- if (Lexer.is(AsmToken::Integer)) {
- LocalLabelVal = getTok().getIntVal();
- if (LocalLabelVal < 0) {
- if (!TheCondState.Ignore) {
- Lex(); // always eat a token
- return Error(IDLoc, "unexpected token at start of statement");
- }
- IDVal = "";
- } else {
- IDVal = getTok().getString();
- Lex(); // Consume the integer token to be used as an identifier token.
- if (Lexer.getKind() != AsmToken::Colon) {
- if (!TheCondState.Ignore) {
- Lex(); // always eat a token
- return Error(IDLoc, "unexpected token at start of statement");
- }
- }
- }
- } else if (Lexer.is(AsmToken::Dot)) {
- // Treat '.' as a valid identifier in this context.
- Lex();
- IDVal = ".";
- } else if (Lexer.is(AsmToken::LCurly)) {
- // Treat '{' as a valid identifier in this context.
- Lex();
- IDVal = "{";
-
- } else if (Lexer.is(AsmToken::RCurly)) {
- // Treat '}' as a valid identifier in this context.
- Lex();
- IDVal = "}";
- } else if (Lexer.is(AsmToken::Star) &&
- getTargetParser().starIsStartOfStatement()) {
- // Accept '*' as a valid start of statement.
- Lex();
- IDVal = "*";
- } else if (parseIdentifier(IDVal)) {
- if (!TheCondState.Ignore) {
- Lex(); // always eat a token
- return Error(IDLoc, "unexpected token at start of statement");
- }
- IDVal = "";
- }
-
- // Handle conditional assembly here before checking for skipping. We
- // have to do this so that .endif isn't skipped in a ".if 0" block for
- // example.
- StringMap<DirectiveKind>::const_iterator DirKindIt =
- DirectiveKindMap.find(IDVal);
- DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
- ? DK_NO_DIRECTIVE
- : DirKindIt->getValue();
- switch (DirKind) {
- default:
- break;
- case DK_IF:
- case DK_IFEQ:
- case DK_IFGE:
- case DK_IFGT:
- case DK_IFLE:
- case DK_IFLT:
- case DK_IFNE:
- return parseDirectiveIf(IDLoc, DirKind);
- case DK_IFB:
- return parseDirectiveIfb(IDLoc, true);
- case DK_IFNB:
- return parseDirectiveIfb(IDLoc, false);
- case DK_IFC:
- return parseDirectiveIfc(IDLoc, true);
- case DK_IFEQS:
- return parseDirectiveIfeqs(IDLoc, true);
- case DK_IFNC:
- return parseDirectiveIfc(IDLoc, false);
- case DK_IFNES:
- return parseDirectiveIfeqs(IDLoc, false);
- case DK_IFDEF:
- return parseDirectiveIfdef(IDLoc, true);
- case DK_IFNDEF:
- case DK_IFNOTDEF:
- return parseDirectiveIfdef(IDLoc, false);
- case DK_ELSEIF:
- return parseDirectiveElseIf(IDLoc);
- case DK_ELSE:
- return parseDirectiveElse(IDLoc);
- case DK_ENDIF:
- return parseDirectiveEndIf(IDLoc);
- }
-
- // Ignore the statement if in the middle of inactive conditional
- // (e.g. ".if 0").
- if (TheCondState.Ignore) {
- eatToEndOfStatement();
- return false;
- }
-
- // FIXME: Recurse on local labels?
-
- // See what kind of statement we have.
- switch (Lexer.getKind()) {
- case AsmToken::Colon: {
- if (!getTargetParser().isLabel(ID))
- break;
- if (checkForValidSection())
- return true;
-
- // identifier ':' -> Label.
- Lex();
-
- // Diagnose attempt to use '.' as a label.
- if (IDVal == ".")
- return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");
-
- // Diagnose attempt to use a variable as a label.
- //
- // FIXME: Diagnostics. Note the location of the definition as a label.
- // FIXME: This doesn't diagnose assignment to a symbol which has been
- // implicitly marked as external.
- MCSymbol *Sym;
- if (LocalLabelVal == -1) {
- if (ParsingInlineAsm && SI) {
- StringRef RewrittenLabel =
- SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
- assert(!RewrittenLabel.empty() &&
- "We should have an internal name here.");
- Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(),
- RewrittenLabel);
- IDVal = RewrittenLabel;
- }
- Sym = getContext().getOrCreateSymbol(IDVal);
- } else
- Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal);
- // End of Labels should be treated as end of line for lexing
- // purposes but that information is not available to the Lexer who
- // does not understand Labels. This may cause us to see a Hash
- // here instead of a preprocessor line comment.
- if (getTok().is(AsmToken::Hash)) {
- StringRef CommentStr = parseStringToEndOfStatement();
- Lexer.Lex();
- Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
- }
-
- // Consume any end of statement token, if present, to avoid spurious
- // AddBlankLine calls().
- if (getTok().is(AsmToken::EndOfStatement)) {
- Lex();
- }
-
- getTargetParser().doBeforeLabelEmit(Sym);
-
- // Emit the label.
- if (!getTargetParser().isParsingInlineAsm())
- Out.EmitLabel(Sym, IDLoc);
-
- // If we are generating dwarf for assembly source files then gather the
- // info to make a dwarf label entry for this label if needed.
- if (enabledGenDwarfForAssembly())
- MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
- IDLoc);
-
- getTargetParser().onLabelParsed(Sym);
-
- return false;
- }
-
- case AsmToken::Equal:
- if (!getTargetParser().equalIsAsmAssignment())
- break;
- // identifier '=' ... -> assignment statement
- Lex();
-
- return parseAssignment(IDVal, true);
-
- default: // Normal instruction or directive.
- break;
- }
-
- // If macros are enabled, check to see if this is a macro instantiation.
- if (areMacrosEnabled())
- if (const MCAsmMacro *M = getContext().lookupMacro(IDVal)) {
- return handleMacroEntry(M, IDLoc);
- }
-
- // Otherwise, we have a normal instruction or directive.
-
- // Directives start with "."
- if (IDVal.startswith(".") && IDVal != ".") {
- // There are several entities interested in parsing directives:
- //
- // 1. The target-specific assembly parser. Some directives are target
- // specific or may potentially behave differently on certain targets.
- // 2. Asm parser extensions. For example, platform-specific parsers
- // (like the ELF parser) register themselves as extensions.
- // 3. The generic directive parser implemented by this class. These are
- // all the directives that behave in a target and platform independent
- // manner, or at least have a default behavior that's shared between
- // all targets and platforms.
-
- getTargetParser().flushPendingInstructions(getStreamer());
-
- SMLoc StartTokLoc = getTok().getLoc();
- bool TPDirectiveReturn = getTargetParser().ParseDirective(ID);
-
- if (hasPendingError())
- return true;
- // Currently the return value should be true if we are
- // uninterested but as this is at odds with the standard parsing
- // convention (return true = error) we have instances of a parsed
- // directive that fails returning true as an error. Catch these
- // cases as best as possible errors here.
- if (TPDirectiveReturn && StartTokLoc != getTok().getLoc())
- return true;
- // Return if we did some parsing or believe we succeeded.
- if (!TPDirectiveReturn || StartTokLoc != getTok().getLoc())
- return false;
-
- // Next, check the extension directive map to see if any extension has
- // registered itself to parse this directive.
- std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
- ExtensionDirectiveMap.lookup(IDVal);
- if (Handler.first)
- return (*Handler.second)(Handler.first, IDVal, IDLoc);
-
- // Finally, if no one else is interested in this directive, it must be
- // generic and familiar to this class.
- switch (DirKind) {
- default:
- break;
- case DK_SET:
- case DK_EQU:
- return parseDirectiveSet(IDVal, true);
- case DK_EQUIV:
- return parseDirectiveSet(IDVal, false);
- case DK_ASCII:
- return parseDirectiveAscii(IDVal, false);
- case DK_ASCIZ:
- case DK_STRING:
- return parseDirectiveAscii(IDVal, true);
- case DK_BYTE:
- case DK_DC_B:
- return parseDirectiveValue(IDVal, 1);
- case DK_DC:
- case DK_DC_W:
- case DK_SHORT:
- case DK_VALUE:
- case DK_2BYTE:
- return parseDirectiveValue(IDVal, 2);
- case DK_LONG:
- case DK_INT:
- case DK_4BYTE:
- case DK_DC_L:
- return parseDirectiveValue(IDVal, 4);
- case DK_QUAD:
- case DK_8BYTE:
- return parseDirectiveValue(IDVal, 8);
- case DK_DC_A:
- return parseDirectiveValue(
- IDVal, getContext().getAsmInfo()->getCodePointerSize());
- case DK_OCTA:
- return parseDirectiveOctaValue(IDVal);
- case DK_SINGLE:
- case DK_FLOAT:
- case DK_DC_S:
- return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle());
- case DK_DOUBLE:
- case DK_DC_D:
- return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble());
- case DK_ALIGN: {
- bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
- return parseDirectiveAlign(IsPow2, /*ExprSize=*/1);
- }
- case DK_ALIGN32: {
- bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
- return parseDirectiveAlign(IsPow2, /*ExprSize=*/4);
- }
- case DK_BALIGN:
- return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
- case DK_BALIGNW:
- return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
- case DK_BALIGNL:
- return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
- case DK_P2ALIGN:
- return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
- case DK_P2ALIGNW:
- return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
- case DK_P2ALIGNL:
- return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
- case DK_ORG:
- return parseDirectiveOrg();
- case DK_FILL:
- return parseDirectiveFill();
- case DK_ZERO:
- return parseDirectiveZero();
- case DK_EXTERN:
- eatToEndOfStatement(); // .extern is the default, ignore it.
- return false;
- case DK_GLOBL:
- case DK_GLOBAL:
- return parseDirectiveSymbolAttribute(MCSA_Global);
- case DK_LAZY_REFERENCE:
- return parseDirectiveSymbolAttribute(MCSA_LazyReference);
- case DK_NO_DEAD_STRIP:
- return parseDirectiveSymbolAttribute(MCSA_NoDeadStrip);
- case DK_SYMBOL_RESOLVER:
- return parseDirectiveSymbolAttribute(MCSA_SymbolResolver);
- case DK_PRIVATE_EXTERN:
- return parseDirectiveSymbolAttribute(MCSA_PrivateExtern);
- case DK_REFERENCE:
- return parseDirectiveSymbolAttribute(MCSA_Reference);
- case DK_WEAK_DEFINITION:
- return parseDirectiveSymbolAttribute(MCSA_WeakDefinition);
- case DK_WEAK_REFERENCE:
- return parseDirectiveSymbolAttribute(MCSA_WeakReference);
- case DK_WEAK_DEF_CAN_BE_HIDDEN:
- return parseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate);
- case DK_COLD:
- return parseDirectiveSymbolAttribute(MCSA_Cold);
- case DK_COMM:
- case DK_COMMON:
- return parseDirectiveComm(/*IsLocal=*/false);
- case DK_LCOMM:
- return parseDirectiveComm(/*IsLocal=*/true);
- case DK_ABORT:
- return parseDirectiveAbort();
- case DK_INCLUDE:
- return parseDirectiveInclude();
- case DK_INCBIN:
- return parseDirectiveIncbin();
- case DK_CODE16:
- case DK_CODE16GCC:
- return TokError(Twine(IDVal) +
- " not currently supported for this target");
- case DK_REPT:
- return parseDirectiveRept(IDLoc, IDVal);
- case DK_IRP:
- return parseDirectiveIrp(IDLoc);
- case DK_IRPC:
- return parseDirectiveIrpc(IDLoc);
- case DK_ENDR:
- return parseDirectiveEndr(IDLoc);
- case DK_BUNDLE_ALIGN_MODE:
- return parseDirectiveBundleAlignMode();
- case DK_BUNDLE_LOCK:
- return parseDirectiveBundleLock();
- case DK_BUNDLE_UNLOCK:
- return parseDirectiveBundleUnlock();
- case DK_SLEB128:
- return parseDirectiveLEB128(true);
- case DK_ULEB128:
- return parseDirectiveLEB128(false);
- case DK_SPACE:
- case DK_SKIP:
- return parseDirectiveSpace(IDVal);
- case DK_FILE:
- return parseDirectiveFile(IDLoc);
- case DK_LINE:
- return parseDirectiveLine();
- case DK_LOC:
- return parseDirectiveLoc();
- case DK_STABS:
- return parseDirectiveStabs();
- case DK_CV_FILE:
- return parseDirectiveCVFile();
- case DK_CV_FUNC_ID:
- return parseDirectiveCVFuncId();
- case DK_CV_INLINE_SITE_ID:
- return parseDirectiveCVInlineSiteId();
- case DK_CV_LOC:
- return parseDirectiveCVLoc();
- case DK_CV_LINETABLE:
- return parseDirectiveCVLinetable();
- case DK_CV_INLINE_LINETABLE:
- return parseDirectiveCVInlineLinetable();
- case DK_CV_DEF_RANGE:
- return parseDirectiveCVDefRange();
- case DK_CV_STRING:
- return parseDirectiveCVString();
- case DK_CV_STRINGTABLE:
- return parseDirectiveCVStringTable();
- case DK_CV_FILECHECKSUMS:
- return parseDirectiveCVFileChecksums();
- case DK_CV_FILECHECKSUM_OFFSET:
- return parseDirectiveCVFileChecksumOffset();
- case DK_CV_FPO_DATA:
- return parseDirectiveCVFPOData();
- case DK_CFI_SECTIONS:
- return parseDirectiveCFISections();
- case DK_CFI_STARTPROC:
- return parseDirectiveCFIStartProc();
- case DK_CFI_ENDPROC:
- return parseDirectiveCFIEndProc();
- case DK_CFI_DEF_CFA:
- return parseDirectiveCFIDefCfa(IDLoc);
- case DK_CFI_DEF_CFA_OFFSET:
- return parseDirectiveCFIDefCfaOffset();
- case DK_CFI_ADJUST_CFA_OFFSET:
- return parseDirectiveCFIAdjustCfaOffset();
- case DK_CFI_DEF_CFA_REGISTER:
- return parseDirectiveCFIDefCfaRegister(IDLoc);
- case DK_CFI_OFFSET:
- return parseDirectiveCFIOffset(IDLoc);
- case DK_CFI_REL_OFFSET:
- return parseDirectiveCFIRelOffset(IDLoc);
- case DK_CFI_PERSONALITY:
- return parseDirectiveCFIPersonalityOrLsda(true);
- case DK_CFI_LSDA:
- return parseDirectiveCFIPersonalityOrLsda(false);
- case DK_CFI_REMEMBER_STATE:
- return parseDirectiveCFIRememberState();
- case DK_CFI_RESTORE_STATE:
- return parseDirectiveCFIRestoreState();
- case DK_CFI_SAME_VALUE:
- return parseDirectiveCFISameValue(IDLoc);
- case DK_CFI_RESTORE:
- return parseDirectiveCFIRestore(IDLoc);
- case DK_CFI_ESCAPE:
- return parseDirectiveCFIEscape();
- case DK_CFI_RETURN_COLUMN:
- return parseDirectiveCFIReturnColumn(IDLoc);
- case DK_CFI_SIGNAL_FRAME:
- return parseDirectiveCFISignalFrame();
- case DK_CFI_UNDEFINED:
- return parseDirectiveCFIUndefined(IDLoc);
- case DK_CFI_REGISTER:
- return parseDirectiveCFIRegister(IDLoc);
- case DK_CFI_WINDOW_SAVE:
- return parseDirectiveCFIWindowSave();
- case DK_MACROS_ON:
- case DK_MACROS_OFF:
- return parseDirectiveMacrosOnOff(IDVal);
- case DK_MACRO:
- return parseDirectiveMacro(IDLoc);
- case DK_ALTMACRO:
- case DK_NOALTMACRO:
- return parseDirectiveAltmacro(IDVal);
- case DK_EXITM:
- return parseDirectiveExitMacro(IDVal);
- case DK_ENDM:
- case DK_ENDMACRO:
- return parseDirectiveEndMacro(IDVal);
- case DK_PURGEM:
- return parseDirectivePurgeMacro(IDLoc);
- case DK_END:
- return parseDirectiveEnd(IDLoc);
- case DK_ERR:
- return parseDirectiveError(IDLoc, false);
- case DK_ERROR:
- return parseDirectiveError(IDLoc, true);
- case DK_WARNING:
- return parseDirectiveWarning(IDLoc);
- case DK_RELOC:
- return parseDirectiveReloc(IDLoc);
- case DK_DCB:
- case DK_DCB_W:
- return parseDirectiveDCB(IDVal, 2);
- case DK_DCB_B:
- return parseDirectiveDCB(IDVal, 1);
- case DK_DCB_D:
- return parseDirectiveRealDCB(IDVal, APFloat::IEEEdouble());
- case DK_DCB_L:
- return parseDirectiveDCB(IDVal, 4);
- case DK_DCB_S:
- return parseDirectiveRealDCB(IDVal, APFloat::IEEEsingle());
- case DK_DC_X:
- case DK_DCB_X:
- return TokError(Twine(IDVal) +
- " not currently supported for this target");
- case DK_DS:
- case DK_DS_W:
- return parseDirectiveDS(IDVal, 2);
- case DK_DS_B:
- return parseDirectiveDS(IDVal, 1);
- case DK_DS_D:
- return parseDirectiveDS(IDVal, 8);
- case DK_DS_L:
- case DK_DS_S:
- return parseDirectiveDS(IDVal, 4);
- case DK_DS_P:
- case DK_DS_X:
- return parseDirectiveDS(IDVal, 12);
- case DK_PRINT:
- return parseDirectivePrint(IDLoc);
- case DK_ADDRSIG:
- return parseDirectiveAddrsig();
- case DK_ADDRSIG_SYM:
- return parseDirectiveAddrsigSym();
- }
-
- return Error(IDLoc, "unknown directive");
- }
-
- // __asm _emit or __asm __emit
- if (ParsingInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
- IDVal == "_EMIT" || IDVal == "__EMIT"))
- return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
-
- // __asm align
- if (ParsingInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
- return parseDirectiveMSAlign(IDLoc, Info);
-
- if (ParsingInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
- Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
- if (checkForValidSection())
- return true;
-
- // Canonicalize the opcode to lower case.
- std::string OpcodeStr = IDVal.lower();
- ParseInstructionInfo IInfo(Info.AsmRewrites);
- bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID,
- Info.ParsedOperands);
- Info.ParseError = ParseHadError;
-
- // Dump the parsed representation, if requested.
- if (getShowParsedOperands()) {
- SmallString<256> Str;
- raw_svector_ostream OS(Str);
- OS << "parsed instruction: [";
- for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {
- if (i != 0)
- OS << ", ";
- Info.ParsedOperands[i]->print(OS);
- }
- OS << "]";
-
- printMessage(IDLoc, SourceMgr::DK_Note, OS.str());
- }
-
- // Fail even if ParseInstruction erroneously returns false.
- if (hasPendingError() || ParseHadError)
- return true;
-
- // If we are generating dwarf for the current section then generate a .loc
- // directive for the instruction.
- if (!ParseHadError && enabledGenDwarfForAssembly() &&
- getContext().getGenDwarfSectionSyms().count(
- getStreamer().getCurrentSectionOnly())) {
- unsigned Line;
- if (ActiveMacros.empty())
- Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
- else
- Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
- ActiveMacros.front()->ExitBuffer);
-
- // If we previously parsed a cpp hash file line comment then make sure the
- // current Dwarf File is for the CppHashFilename if not then emit the
- // Dwarf File table for it and adjust the line number for the .loc.
- if (!CppHashInfo.Filename.empty()) {
- unsigned FileNumber = getStreamer().EmitDwarfFileDirective(
- 0, StringRef(), CppHashInfo.Filename);
- getContext().setGenDwarfFileNumber(FileNumber);
-
- unsigned CppHashLocLineNo =
- SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
- Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);
- }
-
- getStreamer().EmitDwarfLocDirective(
- getContext().getGenDwarfFileNumber(), Line, 0,
- DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0,
- StringRef());
- }
-
- // If parsing succeeded, match the instruction.
- if (!ParseHadError) {
- uint64_t ErrorInfo;
- if (getTargetParser().MatchAndEmitInstruction(
- IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
- getTargetParser().isParsingInlineAsm()))
- return true;
- }
- return false;
-}
-
-// Parse and erase curly braces marking block start/end
-bool
-AsmParser::parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
- // Identify curly brace marking block start/end
- if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
- return false;
-
- SMLoc StartLoc = Lexer.getLoc();
- Lex(); // Eat the brace
- if (Lexer.is(AsmToken::EndOfStatement))
- Lex(); // Eat EndOfStatement following the brace
-
- // Erase the block start/end brace from the output asm string
- AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -
- StartLoc.getPointer());
- return true;
-}
-
-/// parseCppHashLineFilenameComment as this:
-/// ::= # number "filename"
-bool AsmParser::parseCppHashLineFilenameComment(SMLoc L) {
- Lex(); // Eat the hash token.
- // Lexer only ever emits HashDirective if it fully formed if it's
- // done the checking already so this is an internal error.
- assert(getTok().is(AsmToken::Integer) &&
- "Lexing Cpp line comment: Expected Integer");
- int64_t LineNumber = getTok().getIntVal();
- Lex();
- assert(getTok().is(AsmToken::String) &&
- "Lexing Cpp line comment: Expected String");
- StringRef Filename = getTok().getString();
- Lex();
-
- // Get rid of the enclosing quotes.
- Filename = Filename.substr(1, Filename.size() - 2);
-
- // Save the SMLoc, Filename and LineNumber for later use by diagnostics
- // and possibly DWARF file info.
- CppHashInfo.Loc = L;
- CppHashInfo.Filename = Filename;
- CppHashInfo.LineNumber = LineNumber;
- CppHashInfo.Buf = CurBuffer;
- if (FirstCppHashFilename.empty())
- FirstCppHashFilename = Filename;
- return false;
-}
-
-/// will use the last parsed cpp hash line filename comment
-/// for the Filename and LineNo if any in the diagnostic.
-void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
- const AsmParser *Parser = static_cast<const AsmParser *>(Context);
- raw_ostream &OS = errs();
-
- const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
- SMLoc DiagLoc = Diag.getLoc();
- unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
- unsigned CppHashBuf =
- Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
-
- // Like SourceMgr::printMessage() we need to print the include stack if any
- // before printing the message.
- unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
- if (!Parser->SavedDiagHandler && DiagCurBuffer &&
- DiagCurBuffer != DiagSrcMgr.getMainFileID()) {
- SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
- DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
- }
-
- // If we have not parsed a cpp hash line filename comment or the source
- // manager changed or buffer changed (like in a nested include) then just
- // print the normal diagnostic using its Filename and LineNo.
- if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
- DiagBuf != CppHashBuf) {
- if (Parser->SavedDiagHandler)
- Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
- else
- Diag.print(nullptr, OS);
- return;
- }
-
- // Use the CppHashFilename and calculate a line number based on the
- // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc
- // for the diagnostic.
- const std::string &Filename = Parser->CppHashInfo.Filename;
-
- int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
- int CppHashLocLineNo =
- Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
- int LineNo =
- Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
-
- SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
- Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
- Diag.getLineContents(), Diag.getRanges());
-
- if (Parser->SavedDiagHandler)
- Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
- else
- NewDiag.print(nullptr, OS);
-}
-
-// FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The
-// difference being that that function accepts '@' as part of identifiers and
-// we can't do that. AsmLexer.cpp should probably be changed to handle
-// '@' as a special case when needed.
-static bool isIdentifierChar(char c) {
- return isalnum(static_cast<unsigned char>(c)) || c == '_' || c == '$' ||
- c == '.';
-}
-
-bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
- ArrayRef<MCAsmMacroParameter> Parameters,
- ArrayRef<MCAsmMacroArgument> A,
- bool EnableAtPseudoVariable, SMLoc L) {
- unsigned NParameters = Parameters.size();
- bool HasVararg = NParameters ? Parameters.back().Vararg : false;
- if ((!IsDarwin || NParameters != 0) && NParameters != A.size())
- return Error(L, "Wrong number of arguments");
-
- // A macro without parameters is handled differently on Darwin:
- // gas accepts no arguments and does no substitutions
- while (!Body.empty()) {
- // Scan for the next substitution.
- std::size_t End = Body.size(), Pos = 0;
- for (; Pos != End; ++Pos) {
- // Check for a substitution or escape.
- if (IsDarwin && !NParameters) {
- // This macro has no parameters, look for $0, $1, etc.
- if (Body[Pos] != '$' || Pos + 1 == End)
- continue;
-
- char Next = Body[Pos + 1];
- if (Next == '$' || Next == 'n' ||
- isdigit(static_cast<unsigned char>(Next)))
- break;
- } else {
- // This macro has parameters, look for \foo, \bar, etc.
- if (Body[Pos] == '\\' && Pos + 1 != End)
- break;
- }
- }
-
- // Add the prefix.
- OS << Body.slice(0, Pos);
-
- // Check if we reached the end.
- if (Pos == End)
- break;
-
- if (IsDarwin && !NParameters) {
- switch (Body[Pos + 1]) {
- // $$ => $
- case '$':
- OS << '$';
- break;
-
- // $n => number of arguments
- case 'n':
- OS << A.size();
- break;
-
- // $[0-9] => argument
- default: {
- // Missing arguments are ignored.
- unsigned Index = Body[Pos + 1] - '0';
- if (Index >= A.size())
- break;
-
- // Otherwise substitute with the token values, with spaces eliminated.
- for (const AsmToken &Token : A[Index])
- OS << Token.getString();
- break;
- }
- }
- Pos += 2;
- } else {
- unsigned I = Pos + 1;
-
- // Check for the \@ pseudo-variable.
- if (EnableAtPseudoVariable && Body[I] == '@' && I + 1 != End)
- ++I;
- else
- while (isIdentifierChar(Body[I]) && I + 1 != End)
- ++I;
-
- const char *Begin = Body.data() + Pos + 1;
- StringRef Argument(Begin, I - (Pos + 1));
- unsigned Index = 0;
-
- if (Argument == "@") {
- OS << NumOfMacroInstantiations;
- Pos += 2;
- } else {
- for (; Index < NParameters; ++Index)
- if (Parameters[Index].Name == Argument)
- break;
-
- if (Index == NParameters) {
- if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
- Pos += 3;
- else {
- OS << '\\' << Argument;
- Pos = I;
- }
- } else {
- bool VarargParameter = HasVararg && Index == (NParameters - 1);
- for (const AsmToken &Token : A[Index])
- // For altmacro mode, you can write '%expr'.
- // The prefix '%' evaluates the expression 'expr'
- // and uses the result as a string (e.g. replace %(1+2) with the
- // string "3").
- // Here, we identify the integer token which is the result of the
- // absolute expression evaluation and replace it with its string
- // representation.
- if (AltMacroMode && Token.getString().front() == '%' &&
- Token.is(AsmToken::Integer))
- // Emit an integer value to the buffer.
- OS << Token.getIntVal();
- // Only Token that was validated as a string and begins with '<'
- // is considered altMacroString!!!
- else if (AltMacroMode && Token.getString().front() == '<' &&
- Token.is(AsmToken::String)) {
- OS << altMacroString(Token.getStringContents());
- }
- // We expect no quotes around the string's contents when
- // parsing for varargs.
- else if (Token.isNot(AsmToken::String) || VarargParameter)
- OS << Token.getString();
- else
- OS << Token.getStringContents();
-
- Pos += 1 + Argument.size();
- }
- }
- }
- // Update the scan point.
- Body = Body.substr(Pos);
- }
-
- return false;
-}
-
-MacroInstantiation::MacroInstantiation(SMLoc IL, int EB, SMLoc EL,
- size_t CondStackDepth)
- : InstantiationLoc(IL), ExitBuffer(EB), ExitLoc(EL),
- CondStackDepth(CondStackDepth) {}
-
-static bool isOperator(AsmToken::TokenKind kind) {
- switch (kind) {
- default:
- return false;
- case AsmToken::Plus:
- case AsmToken::Minus:
- case AsmToken::Tilde:
- case AsmToken::Slash:
- case AsmToken::Star:
- case AsmToken::Dot:
- case AsmToken::Equal:
- case AsmToken::EqualEqual:
- case AsmToken::Pipe:
- case AsmToken::PipePipe:
- case AsmToken::Caret:
- case AsmToken::Amp:
- case AsmToken::AmpAmp:
- case AsmToken::Exclaim:
- case AsmToken::ExclaimEqual:
- case AsmToken::Less:
- case AsmToken::LessEqual:
- case AsmToken::LessLess:
- case AsmToken::LessGreater:
- case AsmToken::Greater:
- case AsmToken::GreaterEqual:
- case AsmToken::GreaterGreater:
- return true;
- }
-}
-
-namespace {
-
-class AsmLexerSkipSpaceRAII {
-public:
- AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {
- Lexer.setSkipSpace(SkipSpace);
- }
-
- ~AsmLexerSkipSpaceRAII() {
- Lexer.setSkipSpace(true);
- }
-
-private:
- AsmLexer &Lexer;
-};
-
-} // end anonymous namespace
-
-bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) {
-
- if (Vararg) {
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- StringRef Str = parseStringToEndOfStatement();
- MA.emplace_back(AsmToken::String, Str);
- }
- return false;
- }
-
- unsigned ParenLevel = 0;
-
- // Darwin doesn't use spaces to delmit arguments.
- AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin);
-
- bool SpaceEaten;
-
- while (true) {
- SpaceEaten = false;
- if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
- return TokError("unexpected token in macro instantiation");
-
- if (ParenLevel == 0) {
-
- if (Lexer.is(AsmToken::Comma))
- break;
-
- if (Lexer.is(AsmToken::Space)) {
- SpaceEaten = true;
- Lexer.Lex(); // Eat spaces
- }
-
- // Spaces can delimit parameters, but could also be part an expression.
- // If the token after a space is an operator, add the token and the next
- // one into this argument
- if (!IsDarwin) {
- if (isOperator(Lexer.getKind())) {
- MA.push_back(getTok());
- Lexer.Lex();
-
- // Whitespace after an operator can be ignored.
- if (Lexer.is(AsmToken::Space))
- Lexer.Lex();
-
- continue;
- }
- }
- if (SpaceEaten)
- break;
- }
-
- // handleMacroEntry relies on not advancing the lexer here
- // to be able to fill in the remaining default parameter values
- if (Lexer.is(AsmToken::EndOfStatement))
- break;
-
- // Adjust the current parentheses level.
- if (Lexer.is(AsmToken::LParen))
- ++ParenLevel;
- else if (Lexer.is(AsmToken::RParen) && ParenLevel)
- --ParenLevel;
-
- // Append the token to the current argument list.
- MA.push_back(getTok());
- Lexer.Lex();
- }
-
- if (ParenLevel != 0)
- return TokError("unbalanced parentheses in macro argument");
- return false;
-}
-
-// Parse the macro instantiation arguments.
-bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
- MCAsmMacroArguments &A) {
- const unsigned NParameters = M ? M->Parameters.size() : 0;
- bool NamedParametersFound = false;
- SmallVector<SMLoc, 4> FALocs;
-
- A.resize(NParameters);
- FALocs.resize(NParameters);
-
- // Parse two kinds of macro invocations:
- // - macros defined without any parameters accept an arbitrary number of them
- // - macros defined with parameters accept at most that many of them
- bool HasVararg = NParameters ? M->Parameters.back().Vararg : false;
- for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
- ++Parameter) {
- SMLoc IDLoc = Lexer.getLoc();
- MCAsmMacroParameter FA;
-
- if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) {
- if (parseIdentifier(FA.Name))
- return Error(IDLoc, "invalid argument identifier for formal argument");
-
- if (Lexer.isNot(AsmToken::Equal))
- return TokError("expected '=' after formal parameter identifier");
-
- Lex();
-
- NamedParametersFound = true;
- }
- bool Vararg = HasVararg && Parameter == (NParameters - 1);
-
- if (NamedParametersFound && FA.Name.empty())
- return Error(IDLoc, "cannot mix positional and keyword arguments");
-
- SMLoc StrLoc = Lexer.getLoc();
- SMLoc EndLoc;
- if (AltMacroMode && Lexer.is(AsmToken::Percent)) {
- const MCExpr *AbsoluteExp;
- int64_t Value;
- /// Eat '%'
- Lex();
- if (parseExpression(AbsoluteExp, EndLoc))
- return false;
- if (!AbsoluteExp->evaluateAsAbsolute(Value,
- getStreamer().getAssemblerPtr()))
- return Error(StrLoc, "expected absolute expression");
- const char *StrChar = StrLoc.getPointer();
- const char *EndChar = EndLoc.getPointer();
- AsmToken newToken(AsmToken::Integer,
- StringRef(StrChar, EndChar - StrChar), Value);
- FA.Value.push_back(newToken);
- } else if (AltMacroMode && Lexer.is(AsmToken::Less) &&
- isAltmacroString(StrLoc, EndLoc)) {
- const char *StrChar = StrLoc.getPointer();
- const char *EndChar = EndLoc.getPointer();
- jumpToLoc(EndLoc, CurBuffer);
- /// Eat from '<' to '>'
- Lex();
- AsmToken newToken(AsmToken::String,
- StringRef(StrChar, EndChar - StrChar));
- FA.Value.push_back(newToken);
- } else if(parseMacroArgument(FA.Value, Vararg))
- return true;
-
- unsigned PI = Parameter;
- if (!FA.Name.empty()) {
- unsigned FAI = 0;
- for (FAI = 0; FAI < NParameters; ++FAI)
- if (M->Parameters[FAI].Name == FA.Name)
- break;
-
- if (FAI >= NParameters) {
- assert(M && "expected macro to be defined");
- return Error(IDLoc, "parameter named '" + FA.Name +
- "' does not exist for macro '" + M->Name + "'");
- }
- PI = FAI;
- }
-
- if (!FA.Value.empty()) {
- if (A.size() <= PI)
- A.resize(PI + 1);
- A[PI] = FA.Value;
-
- if (FALocs.size() <= PI)
- FALocs.resize(PI + 1);
-
- FALocs[PI] = Lexer.getLoc();
- }
-
- // At the end of the statement, fill in remaining arguments that have
- // default values. If there aren't any, then the next argument is
- // required but missing
- if (Lexer.is(AsmToken::EndOfStatement)) {
- bool Failure = false;
- for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
- if (A[FAI].empty()) {
- if (M->Parameters[FAI].Required) {
- Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
- "missing value for required parameter "
- "'" + M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");
- Failure = true;
- }
-
- if (!M->Parameters[FAI].Value.empty())
- A[FAI] = M->Parameters[FAI].Value;
- }
- }
- return Failure;
- }
-
- if (Lexer.is(AsmToken::Comma))
- Lex();
- }
-
- return TokError("too many positional arguments");
-}
-
-bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
- // Arbitrarily limit macro nesting depth (default matches 'as'). We can
- // eliminate this, although we should protect against infinite loops.
- unsigned MaxNestingDepth = AsmMacroMaxNestingDepth;
- if (ActiveMacros.size() == MaxNestingDepth) {
- std::ostringstream MaxNestingDepthError;
- MaxNestingDepthError << "macros cannot be nested more than "
- << MaxNestingDepth << " levels deep."
- << " Use -asm-macro-max-nesting-depth to increase "
- "this limit.";
- return TokError(MaxNestingDepthError.str());
- }
-
- MCAsmMacroArguments A;
- if (parseMacroArguments(M, A))
- return true;
-
- // Macro instantiation is lexical, unfortunately. We construct a new buffer
- // to hold the macro body with substitutions.
- SmallString<256> Buf;
- StringRef Body = M->Body;
- raw_svector_ostream OS(Buf);
-
- if (expandMacro(OS, Body, M->Parameters, A, true, getTok().getLoc()))
- return true;
-
- // We include the .endmacro in the buffer as our cue to exit the macro
- // instantiation.
- OS << ".endmacro\n";
-
- std::unique_ptr<MemoryBuffer> Instantiation =
- MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
-
- // Create the macro instantiation object and add to the current macro
- // instantiation stack.
- MacroInstantiation *MI = new MacroInstantiation(
- NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size());
- ActiveMacros.push_back(MI);
-
- ++NumOfMacroInstantiations;
-
- // Jump to the macro instantiation and prime the lexer.
- CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
- Lex();
-
- return false;
-}
-
-void AsmParser::handleMacroExit() {
- // Jump to the EndOfStatement we should return to, and consume it.
- jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer);
- Lex();
-
- // Pop the instantiation entry.
- delete ActiveMacros.back();
- ActiveMacros.pop_back();
-}
-
-bool AsmParser::parseAssignment(StringRef Name, bool allow_redef,
- bool NoDeadStrip) {
- MCSymbol *Sym;
- const MCExpr *Value;
- if (MCParserUtils::parseAssignmentExpression(Name, allow_redef, *this, Sym,
- Value))
- return true;
-
- if (!Sym) {
- // In the case where we parse an expression starting with a '.', we will
- // not generate an error, nor will we create a symbol. In this case we
- // should just return out.
- return false;
- }
-
- // Do the assignment.
- Out.EmitAssignment(Sym, Value);
- if (NoDeadStrip)
- Out.EmitSymbolAttribute(Sym, MCSA_NoDeadStrip);
-
- return false;
-}
-
-/// parseIdentifier:
-/// ::= identifier
-/// ::= string
-bool AsmParser::parseIdentifier(StringRef &Res) {
- // The assembler has relaxed rules for accepting identifiers, in particular we
- // allow things like '.globl $foo' and '.def @feat.00', which would normally be
- // separate tokens. At this level, we have already lexed so we cannot (currently)
- // handle this as a context dependent token, instead we detect adjacent tokens
- // and return the combined identifier.
- if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
- SMLoc PrefixLoc = getLexer().getLoc();
-
- // Consume the prefix character, and check for a following identifier.
-
- AsmToken Buf[1];
- Lexer.peekTokens(Buf, false);
-
- if (Buf[0].isNot(AsmToken::Identifier))
- return true;
-
- // We have a '$' or '@' followed by an identifier, make sure they are adjacent.
- if (PrefixLoc.getPointer() + 1 != Buf[0].getLoc().getPointer())
- return true;
-
- // eat $ or @
- Lexer.Lex(); // Lexer's Lex guarantees consecutive token.
- // Construct the joined identifier and consume the token.
- Res =
- StringRef(PrefixLoc.getPointer(), getTok().getIdentifier().size() + 1);
- Lex(); // Parser Lex to maintain invariants.
- return false;
- }
-
- if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
- return true;
-
- Res = getTok().getIdentifier();
-
- Lex(); // Consume the identifier token.
-
- return false;
-}
-
-/// parseDirectiveSet:
-/// ::= .equ identifier ',' expression
-/// ::= .equiv identifier ',' expression
-/// ::= .set identifier ',' expression
-bool AsmParser::parseDirectiveSet(StringRef IDVal, bool allow_redef) {
- StringRef Name;
- if (check(parseIdentifier(Name), "expected identifier") ||
- parseToken(AsmToken::Comma) || parseAssignment(Name, allow_redef, true))
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
- return false;
-}
-
-bool AsmParser::parseEscapedString(std::string &Data) {
- if (check(getTok().isNot(AsmToken::String), "expected string"))
- return true;
-
- Data = "";
- StringRef Str = getTok().getStringContents();
- for (unsigned i = 0, e = Str.size(); i != e; ++i) {
- if (Str[i] != '\\') {
- Data += Str[i];
- continue;
- }
-
- // Recognize escaped characters. Note that this escape semantics currently
- // loosely follows Darwin 'as'. Notably, it doesn't support hex escapes.
- ++i;
- if (i == e)
- return TokError("unexpected backslash at end of string");
-
- // Recognize octal sequences.
- if ((unsigned)(Str[i] - '0') <= 7) {
- // Consume up to three octal characters.
- unsigned Value = Str[i] - '0';
-
- if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
- ++i;
- Value = Value * 8 + (Str[i] - '0');
-
- if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {
- ++i;
- Value = Value * 8 + (Str[i] - '0');
- }
- }
-
- if (Value > 255)
- return TokError("invalid octal escape sequence (out of range)");
-
- Data += (unsigned char)Value;
- continue;
- }
-
- // Otherwise recognize individual escapes.
- switch (Str[i]) {
- default:
- // Just reject invalid escape sequences for now.
- return TokError("invalid escape sequence (unrecognized character)");
-
- case 'b': Data += '\b'; break;
- case 'f': Data += '\f'; break;
- case 'n': Data += '\n'; break;
- case 'r': Data += '\r'; break;
- case 't': Data += '\t'; break;
- case '"': Data += '"'; break;
- case '\\': Data += '\\'; break;
- }
- }
-
- Lex();
- return false;
-}
-
-/// parseDirectiveAscii:
-/// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ]
-bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
- auto parseOp = [&]() -> bool {
- std::string Data;
- if (checkForValidSection() || parseEscapedString(Data))
- return true;
- getStreamer().EmitBytes(Data);
- if (ZeroTerminated)
- getStreamer().EmitBytes(StringRef("\0", 1));
- return false;
- };
-
- if (parseMany(parseOp))
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
- return false;
-}
-
-/// parseDirectiveReloc
-/// ::= .reloc expression , identifier [ , expression ]
-bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
- const MCExpr *Offset;
- const MCExpr *Expr = nullptr;
- int64_t OffsetValue;
- SMLoc OffsetLoc = Lexer.getTok().getLoc();
-
- if (parseExpression(Offset))
- return true;
-
- if ((Offset->evaluateAsAbsolute(OffsetValue,
- getStreamer().getAssemblerPtr()) &&
- check(OffsetValue < 0, OffsetLoc, "expression is negative")) ||
- (check(Offset->getKind() != llvm::MCExpr::Constant &&
- Offset->getKind() != llvm::MCExpr::SymbolRef,
- OffsetLoc, "expected non-negative number or a label")) ||
- (parseToken(AsmToken::Comma, "expected comma") ||
- check(getTok().isNot(AsmToken::Identifier), "expected relocation name")))
- return true;
-
- SMLoc NameLoc = Lexer.getTok().getLoc();
- StringRef Name = Lexer.getTok().getIdentifier();
- Lex();
-
- if (Lexer.is(AsmToken::Comma)) {
- Lex();
- SMLoc ExprLoc = Lexer.getLoc();
- if (parseExpression(Expr))
- return true;
-
- MCValue Value;
- if (!Expr->evaluateAsRelocatable(Value, nullptr, nullptr))
- return Error(ExprLoc, "expression must be relocatable");
- }
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in .reloc directive"))
- return true;
-
- const MCTargetAsmParser &MCT = getTargetParser();
- const MCSubtargetInfo &STI = MCT.getSTI();
- if (getStreamer().EmitRelocDirective(*Offset, Name, Expr, DirectiveLoc, STI))
- return Error(NameLoc, "unknown relocation name");
-
- return false;
-}
-
-/// parseDirectiveValue
-/// ::= (.byte | .short | ... ) [ expression (, expression)* ]
-bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
- auto parseOp = [&]() -> bool {
- const MCExpr *Value;
- SMLoc ExprLoc = getLexer().getLoc();
- if (checkForValidSection() || parseExpression(Value))
- return true;
- // Special case constant expressions to match code generator.
- if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
- assert(Size <= 8 && "Invalid size");
- uint64_t IntValue = MCE->getValue();
- if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
- return Error(ExprLoc, "out of range literal value");
- getStreamer().EmitIntValue(IntValue, Size);
- } else
- getStreamer().EmitValue(Value, Size, ExprLoc);
- return false;
- };
-
- if (parseMany(parseOp))
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
- return false;
-}
-
-static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo) {
- if (Asm.getTok().isNot(AsmToken::Integer) &&
- Asm.getTok().isNot(AsmToken::BigNum))
- return Asm.TokError("unknown token in expression");
- SMLoc ExprLoc = Asm.getTok().getLoc();
- APInt IntValue = Asm.getTok().getAPIntVal();
- Asm.Lex();
- if (!IntValue.isIntN(128))
- return Asm.Error(ExprLoc, "out of range literal value");
- if (!IntValue.isIntN(64)) {
- hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue();
- lo = IntValue.getLoBits(64).getZExtValue();
- } else {
- hi = 0;
- lo = IntValue.getZExtValue();
- }
- return false;
-}
-
-/// ParseDirectiveOctaValue
-/// ::= .octa [ hexconstant (, hexconstant)* ]
-
-bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) {
- auto parseOp = [&]() -> bool {
- if (checkForValidSection())
- return true;
- uint64_t hi, lo;
- if (parseHexOcta(*this, hi, lo))
- return true;
- if (MAI.isLittleEndian()) {
- getStreamer().EmitIntValue(lo, 8);
- getStreamer().EmitIntValue(hi, 8);
- } else {
- getStreamer().EmitIntValue(hi, 8);
- getStreamer().EmitIntValue(lo, 8);
- }
- return false;
- };
-
- if (parseMany(parseOp))
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
- return false;
-}
-
-bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
- // We don't truly support arithmetic on floating point expressions, so we
- // have to manually parse unary prefixes.
- bool IsNeg = false;
- if (getLexer().is(AsmToken::Minus)) {
- Lexer.Lex();
- IsNeg = true;
- } else if (getLexer().is(AsmToken::Plus))
- Lexer.Lex();
-
- if (Lexer.is(AsmToken::Error))
- return TokError(Lexer.getErr());
- if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&
- Lexer.isNot(AsmToken::Identifier))
- return TokError("unexpected token in directive");
-
- // Convert to an APFloat.
- APFloat Value(Semantics);
- StringRef IDVal = getTok().getString();
- if (getLexer().is(AsmToken::Identifier)) {
- if (!IDVal.compare_lower("infinity") || !IDVal.compare_lower("inf"))
- Value = APFloat::getInf(Semantics);
- else if (!IDVal.compare_lower("nan"))
- Value = APFloat::getNaN(Semantics, false, ~0);
- else
- return TokError("invalid floating point literal");
- } else if (Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) ==
- APFloat::opInvalidOp)
- return TokError("invalid floating point literal");
- if (IsNeg)
- Value.changeSign();
-
- // Consume the numeric token.
- Lex();
-
- Res = Value.bitcastToAPInt();
-
- return false;
-}
-
-/// parseDirectiveRealValue
-/// ::= (.single | .double) [ expression (, expression)* ]
-bool AsmParser::parseDirectiveRealValue(StringRef IDVal,
- const fltSemantics &Semantics) {
- auto parseOp = [&]() -> bool {
- APInt AsInt;
- if (checkForValidSection() || parseRealValue(Semantics, AsInt))
- return true;
- getStreamer().EmitIntValue(AsInt.getLimitedValue(),
- AsInt.getBitWidth() / 8);
- return false;
- };
-
- if (parseMany(parseOp))
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
- return false;
-}
-
-/// parseDirectiveZero
-/// ::= .zero expression
-bool AsmParser::parseDirectiveZero() {
- SMLoc NumBytesLoc = Lexer.getLoc();
- const MCExpr *NumBytes;
- if (checkForValidSection() || parseExpression(NumBytes))
- return true;
-
- int64_t Val = 0;
- if (getLexer().is(AsmToken::Comma)) {
- Lex();
- if (parseAbsoluteExpression(Val))
- return true;
- }
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.zero' directive"))
- return true;
- getStreamer().emitFill(*NumBytes, Val, NumBytesLoc);
-
- return false;
-}
-
-/// parseDirectiveFill
-/// ::= .fill expression [ , expression [ , expression ] ]
-bool AsmParser::parseDirectiveFill() {
- SMLoc NumValuesLoc = Lexer.getLoc();
- const MCExpr *NumValues;
- if (checkForValidSection() || parseExpression(NumValues))
- return true;
-
- int64_t FillSize = 1;
- int64_t FillExpr = 0;
-
- SMLoc SizeLoc, ExprLoc;
-
- if (parseOptionalToken(AsmToken::Comma)) {
- SizeLoc = getTok().getLoc();
- if (parseAbsoluteExpression(FillSize))
- return true;
- if (parseOptionalToken(AsmToken::Comma)) {
- ExprLoc = getTok().getLoc();
- if (parseAbsoluteExpression(FillExpr))
- return true;
- }
- }
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.fill' directive"))
- return true;
-
- if (FillSize < 0) {
- Warning(SizeLoc, "'.fill' directive with negative size has no effect");
- return false;
- }
- if (FillSize > 8) {
- Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8");
- FillSize = 8;
- }
-
- if (!isUInt<32>(FillExpr) && FillSize > 4)
- Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits");
-
- getStreamer().emitFill(*NumValues, FillSize, FillExpr, NumValuesLoc);
-
- return false;
-}
-
-/// parseDirectiveOrg
-/// ::= .org expression [ , expression ]
-bool AsmParser::parseDirectiveOrg() {
- const MCExpr *Offset;
- SMLoc OffsetLoc = Lexer.getLoc();
- if (checkForValidSection() || parseExpression(Offset))
- return true;
-
- // Parse optional fill expression.
- int64_t FillExpr = 0;
- if (parseOptionalToken(AsmToken::Comma))
- if (parseAbsoluteExpression(FillExpr))
- return addErrorSuffix(" in '.org' directive");
- if (parseToken(AsmToken::EndOfStatement))
- return addErrorSuffix(" in '.org' directive");
-
- getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc);
- return false;
-}
-
-/// parseDirectiveAlign
-/// ::= {.align, ...} expression [ , expression [ , expression ]]
-bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
- SMLoc AlignmentLoc = getLexer().getLoc();
- int64_t Alignment;
- SMLoc MaxBytesLoc;
- bool HasFillExpr = false;
- int64_t FillExpr = 0;
- int64_t MaxBytesToFill = 0;
-
- auto parseAlign = [&]() -> bool {
- if (parseAbsoluteExpression(Alignment))
- return true;
- if (parseOptionalToken(AsmToken::Comma)) {
- // The fill expression can be omitted while specifying a maximum number of
- // alignment bytes, e.g:
- // .align 3,,4
- if (getTok().isNot(AsmToken::Comma)) {
- HasFillExpr = true;
- if (parseAbsoluteExpression(FillExpr))
- return true;
- }
- if (parseOptionalToken(AsmToken::Comma))
- if (parseTokenLoc(MaxBytesLoc) ||
- parseAbsoluteExpression(MaxBytesToFill))
- return true;
- }
- return parseToken(AsmToken::EndOfStatement);
- };
-
- if (checkForValidSection())
- return addErrorSuffix(" in directive");
- // Ignore empty '.p2align' directives for GNU-as compatibility
- if (IsPow2 && (ValueSize == 1) && getTok().is(AsmToken::EndOfStatement)) {
- Warning(AlignmentLoc, "p2align directive with no operand(s) is ignored");
- return parseToken(AsmToken::EndOfStatement);
- }
- if (parseAlign())
- return addErrorSuffix(" in directive");
-
- // Always emit an alignment here even if we thrown an error.
- bool ReturnVal = false;
-
- // Compute alignment in bytes.
- if (IsPow2) {
- // FIXME: Diagnose overflow.
- if (Alignment >= 32) {
- ReturnVal |= Error(AlignmentLoc, "invalid alignment value");
- Alignment = 31;
- }
-
- Alignment = 1ULL << Alignment;
- } else {
- // Reject alignments that aren't either a power of two or zero,
- // for gas compatibility. Alignment of zero is silently rounded
- // up to one.
- if (Alignment == 0)
- Alignment = 1;
- if (!isPowerOf2_64(Alignment))
- ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");
- }
-
- // Diagnose non-sensical max bytes to align.
- if (MaxBytesLoc.isValid()) {
- if (MaxBytesToFill < 1) {
- ReturnVal |= Error(MaxBytesLoc,
- "alignment directive can never be satisfied in this "
- "many bytes, ignoring maximum bytes expression");
- MaxBytesToFill = 0;
- }
-
- if (MaxBytesToFill >= Alignment) {
- Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
- "has no effect");
- MaxBytesToFill = 0;
- }
- }
-
- // Check whether we should use optimal code alignment for this .align
- // directive.
- const MCSection *Section = getStreamer().getCurrentSectionOnly();
- assert(Section && "must have section to emit alignment");
- bool UseCodeAlign = Section->UseCodeAlign();
- if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
- ValueSize == 1 && UseCodeAlign) {
- getStreamer().EmitCodeAlignment(Alignment, MaxBytesToFill);
- } else {
- // FIXME: Target specific behavior about how the "extra" bytes are filled.
- getStreamer().EmitValueToAlignment(Alignment, FillExpr, ValueSize,
- MaxBytesToFill);
- }
-
- return ReturnVal;
-}
-
-/// parseDirectiveFile
-/// ::= .file filename
-/// ::= .file number [directory] filename [md5 checksum] [source source-text]
-bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
- // FIXME: I'm not sure what this is.
- int64_t FileNumber = -1;
- if (getLexer().is(AsmToken::Integer)) {
- FileNumber = getTok().getIntVal();
- Lex();
-
- if (FileNumber < 0)
- return TokError("negative file number");
- }
-
- std::string Path;
-
- // Usually the directory and filename together, otherwise just the directory.
- // Allow the strings to have escaped octal character sequence.
- if (check(getTok().isNot(AsmToken::String),
- "unexpected token in '.file' directive") ||
- parseEscapedString(Path))
- return true;
-
- StringRef Directory;
- StringRef Filename;
- std::string FilenameData;
- if (getLexer().is(AsmToken::String)) {
- if (check(FileNumber == -1,
- "explicit path specified, but no file number") ||
- parseEscapedString(FilenameData))
- return true;
- Filename = FilenameData;
- Directory = Path;
- } else {
- Filename = Path;
- }
-
- uint64_t MD5Hi, MD5Lo;
- bool HasMD5 = false;
-
- Optional<StringRef> Source;
- bool HasSource = false;
- std::string SourceString;
-
- while (!parseOptionalToken(AsmToken::EndOfStatement)) {
- StringRef Keyword;
- if (check(getTok().isNot(AsmToken::Identifier),
- "unexpected token in '.file' directive") ||
- parseIdentifier(Keyword))
- return true;
- if (Keyword == "md5") {
- HasMD5 = true;
- if (check(FileNumber == -1,
- "MD5 checksum specified, but no file number") ||
- parseHexOcta(*this, MD5Hi, MD5Lo))
- return true;
- } else if (Keyword == "source") {
- HasSource = true;
- if (check(FileNumber == -1,
- "source specified, but no file number") ||
- check(getTok().isNot(AsmToken::String),
- "unexpected token in '.file' directive") ||
- parseEscapedString(SourceString))
- return true;
- } else {
- return TokError("unexpected token in '.file' directive");
- }
- }
-
- if (FileNumber == -1) {
- // Ignore the directive if there is no number and the target doesn't support
- // numberless .file directives. This allows some portability of assembler
- // between different object file formats.
- if (getContext().getAsmInfo()->hasSingleParameterDotFile())
- getStreamer().EmitFileDirective(Filename);
- } else {
- // In case there is a -g option as well as debug info from directive .file,
- // we turn off the -g option, directly use the existing debug info instead.
- // Throw away any implicit file table for the assembler source.
- if (Ctx.getGenDwarfForAssembly()) {
- Ctx.getMCDwarfLineTable(0).resetFileTable();
- Ctx.setGenDwarfForAssembly(false);
- }
-
- Optional<MD5::MD5Result> CKMem;
- if (HasMD5) {
- MD5::MD5Result Sum;
- for (unsigned i = 0; i != 8; ++i) {
- Sum.Bytes[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
- Sum.Bytes[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
- }
- CKMem = Sum;
- }
- if (HasSource) {
- char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
- memcpy(SourceBuf, SourceString.data(), SourceString.size());
- Source = StringRef(SourceBuf, SourceString.size());
- }
- if (FileNumber == 0) {
- if (Ctx.getDwarfVersion() < 5)
- return Warning(DirectiveLoc, "file 0 not supported prior to DWARF-5");
- getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);
- } else {
- Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
- FileNumber, Directory, Filename, CKMem, Source);
- if (!FileNumOrErr)
- return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
- }
- // Alert the user if there are some .file directives with MD5 and some not.
- // But only do that once.
- if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
- ReportedInconsistentMD5 = true;
- return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
- }
- }
-
- return false;
-}
-
-/// parseDirectiveLine
-/// ::= .line [number]
-bool AsmParser::parseDirectiveLine() {
- int64_t LineNumber;
- if (getLexer().is(AsmToken::Integer)) {
- if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))
- return true;
- (void)LineNumber;
- // FIXME: Do something with the .line.
- }
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.line' directive"))
- return true;
-
- return false;
-}
-
-/// parseDirectiveLoc
-/// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]
-/// [epilogue_begin] [is_stmt VALUE] [isa VALUE]
-/// The first number is a file number, must have been previously assigned with
-/// a .file directive, the second number is the line number and optionally the
-/// third number is a column position (zero if not specified). The remaining
-/// optional items are .loc sub-directives.
-bool AsmParser::parseDirectiveLoc() {
- int64_t FileNumber = 0, LineNumber = 0;
- SMLoc Loc = getTok().getLoc();
- if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||
- check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,
- "file number less than one in '.loc' directive") ||
- check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,
- "unassigned file number in '.loc' directive"))
- return true;
-
- // optional
- if (getLexer().is(AsmToken::Integer)) {
- LineNumber = getTok().getIntVal();
- if (LineNumber < 0)
- return TokError("line number less than zero in '.loc' directive");
- Lex();
- }
-
- int64_t ColumnPos = 0;
- if (getLexer().is(AsmToken::Integer)) {
- ColumnPos = getTok().getIntVal();
- if (ColumnPos < 0)
- return TokError("column position less than zero in '.loc' directive");
- Lex();
- }
-
- unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
- unsigned Isa = 0;
- int64_t Discriminator = 0;
-
- auto parseLocOp = [&]() -> bool {
- StringRef Name;
- SMLoc Loc = getTok().getLoc();
- if (parseIdentifier(Name))
- return TokError("unexpected token in '.loc' directive");
-
- if (Name == "basic_block")
- Flags |= DWARF2_FLAG_BASIC_BLOCK;
- else if (Name == "prologue_end")
- Flags |= DWARF2_FLAG_PROLOGUE_END;
- else if (Name == "epilogue_begin")
- Flags |= DWARF2_FLAG_EPILOGUE_BEGIN;
- else if (Name == "is_stmt") {
- Loc = getTok().getLoc();
- const MCExpr *Value;
- if (parseExpression(Value))
- return true;
- // The expression must be the constant 0 or 1.
- if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
- int Value = MCE->getValue();
- if (Value == 0)
- Flags &= ~DWARF2_FLAG_IS_STMT;
- else if (Value == 1)
- Flags |= DWARF2_FLAG_IS_STMT;
- else
- return Error(Loc, "is_stmt value not 0 or 1");
- } else {
- return Error(Loc, "is_stmt value not the constant value of 0 or 1");
- }
- } else if (Name == "isa") {
- Loc = getTok().getLoc();
- const MCExpr *Value;
- if (parseExpression(Value))
- return true;
- // The expression must be a constant greater or equal to 0.
- if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
- int Value = MCE->getValue();
- if (Value < 0)
- return Error(Loc, "isa number less than zero");
- Isa = Value;
- } else {
- return Error(Loc, "isa number not a constant value");
- }
- } else if (Name == "discriminator") {
- if (parseAbsoluteExpression(Discriminator))
- return true;
- } else {
- return Error(Loc, "unknown sub-directive in '.loc' directive");
- }
- return false;
- };
-
- if (parseMany(parseLocOp, false /*hasComma*/))
- return true;
-
- getStreamer().EmitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
- Isa, Discriminator, StringRef());
-
- return false;
-}
-
-/// parseDirectiveStabs
-/// ::= .stabs string, number, number, number
-bool AsmParser::parseDirectiveStabs() {
- return TokError("unsupported directive '.stabs'");
-}
-
-/// parseDirectiveCVFile
-/// ::= .cv_file number filename [checksum] [checksumkind]
-bool AsmParser::parseDirectiveCVFile() {
- SMLoc FileNumberLoc = getTok().getLoc();
- int64_t FileNumber;
- std::string Filename;
- std::string Checksum;
- int64_t ChecksumKind = 0;
-
- if (parseIntToken(FileNumber,
- "expected file number in '.cv_file' directive") ||
- check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
- check(getTok().isNot(AsmToken::String),
- "unexpected token in '.cv_file' directive") ||
- parseEscapedString(Filename))
- return true;
- if (!parseOptionalToken(AsmToken::EndOfStatement)) {
- if (check(getTok().isNot(AsmToken::String),
- "unexpected token in '.cv_file' directive") ||
- parseEscapedString(Checksum) ||
- parseIntToken(ChecksumKind,
- "expected checksum kind in '.cv_file' directive") ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.cv_file' directive"))
- return true;
- }
-
- Checksum = fromHex(Checksum);
- void *CKMem = Ctx.allocate(Checksum.size(), 1);
- memcpy(CKMem, Checksum.data(), Checksum.size());
- ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
- Checksum.size());
-
- if (!getStreamer().EmitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
- static_cast<uint8_t>(ChecksumKind)))
- return Error(FileNumberLoc, "file number already allocated");
-
- return false;
-}
-
-bool AsmParser::parseCVFunctionId(int64_t &FunctionId,
- StringRef DirectiveName) {
- SMLoc Loc;
- return parseTokenLoc(Loc) ||
- parseIntToken(FunctionId, "expected function id in '" + DirectiveName +
- "' directive") ||
- check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc,
- "expected function id within range [0, UINT_MAX)");
-}
-
-bool AsmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {
- SMLoc Loc;
- return parseTokenLoc(Loc) ||
- parseIntToken(FileNumber, "expected integer in '" + DirectiveName +
- "' directive") ||
- check(FileNumber < 1, Loc, "file number less than one in '" +
- DirectiveName + "' directive") ||
- check(!getCVContext().isValidFileNumber(FileNumber), Loc,
- "unassigned file number in '" + DirectiveName + "' directive");
-}
-
-/// parseDirectiveCVFuncId
-/// ::= .cv_func_id FunctionId
-///
-/// Introduces a function ID that can be used with .cv_loc.
-bool AsmParser::parseDirectiveCVFuncId() {
- SMLoc FunctionIdLoc = getTok().getLoc();
- int64_t FunctionId;
-
- if (parseCVFunctionId(FunctionId, ".cv_func_id") ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.cv_func_id' directive"))
- return true;
-
- if (!getStreamer().EmitCVFuncIdDirective(FunctionId))
- return Error(FunctionIdLoc, "function id already allocated");
-
- return false;
-}
-
-/// parseDirectiveCVInlineSiteId
-/// ::= .cv_inline_site_id FunctionId
-/// "within" IAFunc
-/// "inlined_at" IAFile IALine [IACol]
-///
-/// Introduces a function ID that can be used with .cv_loc. Includes "inlined
-/// at" source location information for use in the line table of the caller,
-/// whether the caller is a real function or another inlined call site.
-bool AsmParser::parseDirectiveCVInlineSiteId() {
- SMLoc FunctionIdLoc = getTok().getLoc();
- int64_t FunctionId;
- int64_t IAFunc;
- int64_t IAFile;
- int64_t IALine;
- int64_t IACol = 0;
-
- // FunctionId
- if (parseCVFunctionId(FunctionId, ".cv_inline_site_id"))
- return true;
-
- // "within"
- if (check((getLexer().isNot(AsmToken::Identifier) ||
- getTok().getIdentifier() != "within"),
- "expected 'within' identifier in '.cv_inline_site_id' directive"))
- return true;
- Lex();
-
- // IAFunc
- if (parseCVFunctionId(IAFunc, ".cv_inline_site_id"))
- return true;
-
- // "inlined_at"
- if (check((getLexer().isNot(AsmToken::Identifier) ||
- getTok().getIdentifier() != "inlined_at"),
- "expected 'inlined_at' identifier in '.cv_inline_site_id' "
- "directive") )
- return true;
- Lex();
-
- // IAFile IALine
- if (parseCVFileId(IAFile, ".cv_inline_site_id") ||
- parseIntToken(IALine, "expected line number after 'inlined_at'"))
- return true;
-
- // [IACol]
- if (getLexer().is(AsmToken::Integer)) {
- IACol = getTok().getIntVal();
- Lex();
- }
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.cv_inline_site_id' directive"))
- return true;
-
- if (!getStreamer().EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
- IALine, IACol, FunctionIdLoc))
- return Error(FunctionIdLoc, "function id already allocated");
-
- return false;
-}
-
-/// parseDirectiveCVLoc
-/// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
-/// [is_stmt VALUE]
-/// The first number is a file number, must have been previously assigned with
-/// a .file directive, the second number is the line number and optionally the
-/// third number is a column position (zero if not specified). The remaining
-/// optional items are .loc sub-directives.
-bool AsmParser::parseDirectiveCVLoc() {
- SMLoc DirectiveLoc = getTok().getLoc();
- int64_t FunctionId, FileNumber;
- if (parseCVFunctionId(FunctionId, ".cv_loc") ||
- parseCVFileId(FileNumber, ".cv_loc"))
- return true;
-
- int64_t LineNumber = 0;
- if (getLexer().is(AsmToken::Integer)) {
- LineNumber = getTok().getIntVal();
- if (LineNumber < 0)
- return TokError("line number less than zero in '.cv_loc' directive");
- Lex();
- }
-
- int64_t ColumnPos = 0;
- if (getLexer().is(AsmToken::Integer)) {
- ColumnPos = getTok().getIntVal();
- if (ColumnPos < 0)
- return TokError("column position less than zero in '.cv_loc' directive");
- Lex();
- }
-
- bool PrologueEnd = false;
- uint64_t IsStmt = 0;
-
- auto parseOp = [&]() -> bool {
- StringRef Name;
- SMLoc Loc = getTok().getLoc();
- if (parseIdentifier(Name))
- return TokError("unexpected token in '.cv_loc' directive");
- if (Name == "prologue_end")
- PrologueEnd = true;
- else if (Name == "is_stmt") {
- Loc = getTok().getLoc();
- const MCExpr *Value;
- if (parseExpression(Value))
- return true;
- // The expression must be the constant 0 or 1.
- IsStmt = ~0ULL;
- if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
- IsStmt = MCE->getValue();
-
- if (IsStmt > 1)
- return Error(Loc, "is_stmt value not 0 or 1");
- } else {
- return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
- }
- return false;
- };
-
- if (parseMany(parseOp, false /*hasComma*/))
- return true;
-
- getStreamer().EmitCVLocDirective(FunctionId, FileNumber, LineNumber,
- ColumnPos, PrologueEnd, IsStmt, StringRef(),
- DirectiveLoc);
- return false;
-}
-
-/// parseDirectiveCVLinetable
-/// ::= .cv_linetable FunctionId, FnStart, FnEnd
-bool AsmParser::parseDirectiveCVLinetable() {
- int64_t FunctionId;
- StringRef FnStartName, FnEndName;
- SMLoc Loc = getTok().getLoc();
- if (parseCVFunctionId(FunctionId, ".cv_linetable") ||
- parseToken(AsmToken::Comma,
- "unexpected token in '.cv_linetable' directive") ||
- parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
- "expected identifier in directive") ||
- parseToken(AsmToken::Comma,
- "unexpected token in '.cv_linetable' directive") ||
- parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
- "expected identifier in directive"))
- return true;
-
- MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
- MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
-
- getStreamer().EmitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
- return false;
-}
-
-/// parseDirectiveCVInlineLinetable
-/// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
-bool AsmParser::parseDirectiveCVInlineLinetable() {
- int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
- StringRef FnStartName, FnEndName;
- SMLoc Loc = getTok().getLoc();
- if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") ||
- parseTokenLoc(Loc) ||
- parseIntToken(
- SourceFileId,
- "expected SourceField in '.cv_inline_linetable' directive") ||
- check(SourceFileId <= 0, Loc,
- "File id less than zero in '.cv_inline_linetable' directive") ||
- parseTokenLoc(Loc) ||
- parseIntToken(
- SourceLineNum,
- "expected SourceLineNum in '.cv_inline_linetable' directive") ||
- check(SourceLineNum < 0, Loc,
- "Line number less than zero in '.cv_inline_linetable' directive") ||
- parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
- "expected identifier in directive") ||
- parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
- "expected identifier in directive"))
- return true;
-
- if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
- return true;
-
- MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
- MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
- getStreamer().EmitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
- SourceLineNum, FnStartSym,
- FnEndSym);
- return false;
-}
-
-/// parseDirectiveCVDefRange
-/// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
-bool AsmParser::parseDirectiveCVDefRange() {
- SMLoc Loc;
- std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
- while (getLexer().is(AsmToken::Identifier)) {
- Loc = getLexer().getLoc();
- StringRef GapStartName;
- if (parseIdentifier(GapStartName))
- return Error(Loc, "expected identifier in directive");
- MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);
-
- Loc = getLexer().getLoc();
- StringRef GapEndName;
- if (parseIdentifier(GapEndName))
- return Error(Loc, "expected identifier in directive");
- MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);
-
- Ranges.push_back({GapStartSym, GapEndSym});
- }
-
- std::string FixedSizePortion;
- if (parseToken(AsmToken::Comma, "unexpected token in directive") ||
- parseEscapedString(FixedSizePortion))
- return true;
-
- getStreamer().EmitCVDefRangeDirective(Ranges, FixedSizePortion);
- return false;
-}
-
-/// parseDirectiveCVString
-/// ::= .cv_stringtable "string"
-bool AsmParser::parseDirectiveCVString() {
- std::string Data;
- if (checkForValidSection() || parseEscapedString(Data))
- return addErrorSuffix(" in '.cv_string' directive");
-
- // Put the string in the table and emit the offset.
- std::pair<StringRef, unsigned> Insertion =
- getCVContext().addToStringTable(Data);
- getStreamer().EmitIntValue(Insertion.second, 4);
- return false;
-}
-
-/// parseDirectiveCVStringTable
-/// ::= .cv_stringtable
-bool AsmParser::parseDirectiveCVStringTable() {
- getStreamer().EmitCVStringTableDirective();
- return false;
-}
-
-/// parseDirectiveCVFileChecksums
-/// ::= .cv_filechecksums
-bool AsmParser::parseDirectiveCVFileChecksums() {
- getStreamer().EmitCVFileChecksumsDirective();
- return false;
-}
-
-/// parseDirectiveCVFileChecksumOffset
-/// ::= .cv_filechecksumoffset fileno
-bool AsmParser::parseDirectiveCVFileChecksumOffset() {
- int64_t FileNo;
- if (parseIntToken(FileNo, "expected identifier in directive"))
- return true;
- if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
- return true;
- getStreamer().EmitCVFileChecksumOffsetDirective(FileNo);
- return false;
-}
-
-/// parseDirectiveCVFPOData
-/// ::= .cv_fpo_data procsym
-bool AsmParser::parseDirectiveCVFPOData() {
- SMLoc DirLoc = getLexer().getLoc();
- StringRef ProcName;
- if (parseIdentifier(ProcName))
- return TokError("expected symbol name");
- if (parseEOL("unexpected tokens"))
- return addErrorSuffix(" in '.cv_fpo_data' directive");
- MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
- getStreamer().EmitCVFPOData(ProcSym, DirLoc);
- return false;
-}
-
-/// parseDirectiveCFISections
-/// ::= .cfi_sections section [, section]
-bool AsmParser::parseDirectiveCFISections() {
- StringRef Name;
- bool EH = false;
- bool Debug = false;
-
- if (parseIdentifier(Name))
- return TokError("Expected an identifier");
-
- if (Name == ".eh_frame")
- EH = true;
- else if (Name == ".debug_frame")
- Debug = true;
-
- if (getLexer().is(AsmToken::Comma)) {
- Lex();
-
- if (parseIdentifier(Name))
- return TokError("Expected an identifier");
-
- if (Name == ".eh_frame")
- EH = true;
- else if (Name == ".debug_frame")
- Debug = true;
- }
-
- getStreamer().EmitCFISections(EH, Debug);
- return false;
-}
-
-/// parseDirectiveCFIStartProc
-/// ::= .cfi_startproc [simple]
-bool AsmParser::parseDirectiveCFIStartProc() {
- StringRef Simple;
- if (!parseOptionalToken(AsmToken::EndOfStatement)) {
- if (check(parseIdentifier(Simple) || Simple != "simple",
- "unexpected token") ||
- parseToken(AsmToken::EndOfStatement))
- return addErrorSuffix(" in '.cfi_startproc' directive");
- }
-
- // TODO(kristina): Deal with a corner case of incorrect diagnostic context
- // being produced if this directive is emitted as part of preprocessor macro
- // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
- // Tools like llvm-mc on the other hand are not affected by it, and report
- // correct context information.
- getStreamer().EmitCFIStartProc(!Simple.empty(), Lexer.getLoc());
- return false;
-}
-
-/// parseDirectiveCFIEndProc
-/// ::= .cfi_endproc
-bool AsmParser::parseDirectiveCFIEndProc() {
- getStreamer().EmitCFIEndProc();
- return false;
-}
-
-/// parse register name or number.
-bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register,
- SMLoc DirectiveLoc) {
- unsigned RegNo;
-
- if (getLexer().isNot(AsmToken::Integer)) {
- if (getTargetParser().ParseRegister(RegNo, DirectiveLoc, DirectiveLoc))
- return true;
- Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
- } else
- return parseAbsoluteExpression(Register);
-
- return false;
-}
-
-/// parseDirectiveCFIDefCfa
-/// ::= .cfi_def_cfa register, offset
-bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
- int64_t Register = 0, Offset = 0;
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
- parseToken(AsmToken::Comma, "unexpected token in directive") ||
- parseAbsoluteExpression(Offset))
- return true;
-
- getStreamer().EmitCFIDefCfa(Register, Offset);
- return false;
-}
-
-/// parseDirectiveCFIDefCfaOffset
-/// ::= .cfi_def_cfa_offset offset
-bool AsmParser::parseDirectiveCFIDefCfaOffset() {
- int64_t Offset = 0;
- if (parseAbsoluteExpression(Offset))
- return true;
-
- getStreamer().EmitCFIDefCfaOffset(Offset);
- return false;
-}
-
-/// parseDirectiveCFIRegister
-/// ::= .cfi_register register, register
-bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
- int64_t Register1 = 0, Register2 = 0;
- if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) ||
- parseToken(AsmToken::Comma, "unexpected token in directive") ||
- parseRegisterOrRegisterNumber(Register2, DirectiveLoc))
- return true;
-
- getStreamer().EmitCFIRegister(Register1, Register2);
- return false;
-}
-
-/// parseDirectiveCFIWindowSave
-/// ::= .cfi_window_save
-bool AsmParser::parseDirectiveCFIWindowSave() {
- getStreamer().EmitCFIWindowSave();
- return false;
-}
-
-/// parseDirectiveCFIAdjustCfaOffset
-/// ::= .cfi_adjust_cfa_offset adjustment
-bool AsmParser::parseDirectiveCFIAdjustCfaOffset() {
- int64_t Adjustment = 0;
- if (parseAbsoluteExpression(Adjustment))
- return true;
-
- getStreamer().EmitCFIAdjustCfaOffset(Adjustment);
- return false;
-}
-
-/// parseDirectiveCFIDefCfaRegister
-/// ::= .cfi_def_cfa_register register
-bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
- int64_t Register = 0;
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
- return true;
-
- getStreamer().EmitCFIDefCfaRegister(Register);
- return false;
-}
-
-/// parseDirectiveCFIOffset
-/// ::= .cfi_offset register, offset
-bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
- int64_t Register = 0;
- int64_t Offset = 0;
-
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
- parseToken(AsmToken::Comma, "unexpected token in directive") ||
- parseAbsoluteExpression(Offset))
- return true;
-
- getStreamer().EmitCFIOffset(Register, Offset);
- return false;
-}
-
-/// parseDirectiveCFIRelOffset
-/// ::= .cfi_rel_offset register, offset
-bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
- int64_t Register = 0, Offset = 0;
-
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
- parseToken(AsmToken::Comma, "unexpected token in directive") ||
- parseAbsoluteExpression(Offset))
- return true;
-
- getStreamer().EmitCFIRelOffset(Register, Offset);
- return false;
-}
-
-static bool isValidEncoding(int64_t Encoding) {
- if (Encoding & ~0xff)
- return false;
-
- if (Encoding == dwarf::DW_EH_PE_omit)
- return true;
-
- const unsigned Format = Encoding & 0xf;
- if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
- Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
- Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
- Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
- return false;
-
- const unsigned Application = Encoding & 0x70;
- if (Application != dwarf::DW_EH_PE_absptr &&
- Application != dwarf::DW_EH_PE_pcrel)
- return false;
-
- return true;
-}
-
-/// parseDirectiveCFIPersonalityOrLsda
-/// IsPersonality true for cfi_personality, false for cfi_lsda
-/// ::= .cfi_personality encoding, [symbol_name]
-/// ::= .cfi_lsda encoding, [symbol_name]
-bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
- int64_t Encoding = 0;
- if (parseAbsoluteExpression(Encoding))
- return true;
- if (Encoding == dwarf::DW_EH_PE_omit)
- return false;
-
- StringRef Name;
- if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||
- parseToken(AsmToken::Comma, "unexpected token in directive") ||
- check(parseIdentifier(Name), "expected identifier in directive"))
- return true;
-
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- if (IsPersonality)
- getStreamer().EmitCFIPersonality(Sym, Encoding);
- else
- getStreamer().EmitCFILsda(Sym, Encoding);
- return false;
-}
-
-/// parseDirectiveCFIRememberState
-/// ::= .cfi_remember_state
-bool AsmParser::parseDirectiveCFIRememberState() {
- getStreamer().EmitCFIRememberState();
- return false;
-}
-
-/// parseDirectiveCFIRestoreState
-/// ::= .cfi_remember_state
-bool AsmParser::parseDirectiveCFIRestoreState() {
- getStreamer().EmitCFIRestoreState();
- return false;
-}
-
-/// parseDirectiveCFISameValue
-/// ::= .cfi_same_value register
-bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
- int64_t Register = 0;
-
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
- return true;
-
- getStreamer().EmitCFISameValue(Register);
- return false;
-}
-
-/// parseDirectiveCFIRestore
-/// ::= .cfi_restore register
-bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
- int64_t Register = 0;
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
- return true;
-
- getStreamer().EmitCFIRestore(Register);
- return false;
-}
-
-/// parseDirectiveCFIEscape
-/// ::= .cfi_escape expression[,...]
-bool AsmParser::parseDirectiveCFIEscape() {
- std::string Values;
- int64_t CurrValue;
- if (parseAbsoluteExpression(CurrValue))
- return true;
-
- Values.push_back((uint8_t)CurrValue);
-
- while (getLexer().is(AsmToken::Comma)) {
- Lex();
-
- if (parseAbsoluteExpression(CurrValue))
- return true;
-
- Values.push_back((uint8_t)CurrValue);
- }
-
- getStreamer().EmitCFIEscape(Values);
- return false;
-}
-
-/// parseDirectiveCFIReturnColumn
-/// ::= .cfi_return_column register
-bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
- int64_t Register = 0;
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
- return true;
- getStreamer().EmitCFIReturnColumn(Register);
- return false;
-}
-
-/// parseDirectiveCFISignalFrame
-/// ::= .cfi_signal_frame
-bool AsmParser::parseDirectiveCFISignalFrame() {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.cfi_signal_frame'"))
- return true;
-
- getStreamer().EmitCFISignalFrame();
- return false;
-}
-
-/// parseDirectiveCFIUndefined
-/// ::= .cfi_undefined register
-bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
- int64_t Register = 0;
-
- if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
- return true;
-
- getStreamer().EmitCFIUndefined(Register);
- return false;
-}
-
-/// parseDirectiveAltmacro
-/// ::= .altmacro
-/// ::= .noaltmacro
-bool AsmParser::parseDirectiveAltmacro(StringRef Directive) {
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '" + Directive + "' directive");
- AltMacroMode = (Directive == ".altmacro");
- return false;
-}
-
-/// parseDirectiveMacrosOnOff
-/// ::= .macros_on
-/// ::= .macros_off
-bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '" + Directive + "' directive"))
- return true;
-
- setMacrosEnabled(Directive == ".macros_on");
- return false;
-}
-
-/// parseDirectiveMacro
-/// ::= .macro name[,] [parameters]
-bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
- StringRef Name;
- if (parseIdentifier(Name))
- return TokError("expected identifier in '.macro' directive");
-
- if (getLexer().is(AsmToken::Comma))
- Lex();
-
- MCAsmMacroParameters Parameters;
- while (getLexer().isNot(AsmToken::EndOfStatement)) {
-
- if (!Parameters.empty() && Parameters.back().Vararg)
- return Error(Lexer.getLoc(),
- "Vararg parameter '" + Parameters.back().Name +
- "' should be last one in the list of parameters.");
-
- MCAsmMacroParameter Parameter;
- if (parseIdentifier(Parameter.Name))
- return TokError("expected identifier in '.macro' directive");
-
- // Emit an error if two (or more) named parameters share the same name
- for (const MCAsmMacroParameter& CurrParam : Parameters)
- if (CurrParam.Name.equals(Parameter.Name))
- return TokError("macro '" + Name + "' has multiple parameters"
- " named '" + Parameter.Name + "'");
-
- if (Lexer.is(AsmToken::Colon)) {
- Lex(); // consume ':'
-
- SMLoc QualLoc;
- StringRef Qualifier;
-
- QualLoc = Lexer.getLoc();
- if (parseIdentifier(Qualifier))
- return Error(QualLoc, "missing parameter qualifier for "
- "'" + Parameter.Name + "' in macro '" + Name + "'");
-
- if (Qualifier == "req")
- Parameter.Required = true;
- else if (Qualifier == "vararg")
- Parameter.Vararg = true;
- else
- return Error(QualLoc, Qualifier + " is not a valid parameter qualifier "
- "for '" + Parameter.Name + "' in macro '" + Name + "'");
- }
-
- if (getLexer().is(AsmToken::Equal)) {
- Lex();
-
- SMLoc ParamLoc;
-
- ParamLoc = Lexer.getLoc();
- if (parseMacroArgument(Parameter.Value, /*Vararg=*/false ))
- return true;
-
- if (Parameter.Required)
- Warning(ParamLoc, "pointless default value for required parameter "
- "'" + Parameter.Name + "' in macro '" + Name + "'");
- }
-
- Parameters.push_back(std::move(Parameter));
-
- if (getLexer().is(AsmToken::Comma))
- Lex();
- }
-
- // Eat just the end of statement.
- Lexer.Lex();
-
- // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors
- AsmToken EndToken, StartToken = getTok();
- unsigned MacroDepth = 0;
- // Lex the macro definition.
- while (true) {
- // Ignore Lexing errors in macros.
- while (Lexer.is(AsmToken::Error)) {
- Lexer.Lex();
- }
-
- // Check whether we have reached the end of the file.
- if (getLexer().is(AsmToken::Eof))
- return Error(DirectiveLoc, "no matching '.endmacro' in definition");
-
- // Otherwise, check whether we have reach the .endmacro.
- if (getLexer().is(AsmToken::Identifier)) {
- if (getTok().getIdentifier() == ".endm" ||
- getTok().getIdentifier() == ".endmacro") {
- if (MacroDepth == 0) { // Outermost macro.
- EndToken = getTok();
- Lexer.Lex();
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '" + EndToken.getIdentifier() +
- "' directive");
- break;
- } else {
- // Otherwise we just found the end of an inner macro.
- --MacroDepth;
- }
- } else if (getTok().getIdentifier() == ".macro") {
- // We allow nested macros. Those aren't instantiated until the outermost
- // macro is expanded so just ignore them for now.
- ++MacroDepth;
- }
- }
-
- // Otherwise, scan til the end of the statement.
- eatToEndOfStatement();
- }
-
- if (getContext().lookupMacro(Name)) {
- return Error(DirectiveLoc, "macro '" + Name + "' is already defined");
- }
-
- const char *BodyStart = StartToken.getLoc().getPointer();
- const char *BodyEnd = EndToken.getLoc().getPointer();
- StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
- checkForBadMacro(DirectiveLoc, Name, Body, Parameters);
- MCAsmMacro Macro(Name, Body, std::move(Parameters));
- DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
- Macro.dump());
- getContext().defineMacro(Name, std::move(Macro));
- return false;
-}
-
-/// checkForBadMacro
-///
-/// With the support added for named parameters there may be code out there that
-/// is transitioning from positional parameters. In versions of gas that did
-/// not support named parameters they would be ignored on the macro definition.
-/// But to support both styles of parameters this is not possible so if a macro
-/// definition has named parameters but does not use them and has what appears
-/// to be positional parameters, strings like $1, $2, ... and $n, then issue a
-/// warning that the positional parameter found in body which have no effect.
-/// Hoping the developer will either remove the named parameters from the macro
-/// definition so the positional parameters get used if that was what was
-/// intended or change the macro to use the named parameters. It is possible
-/// this warning will trigger when the none of the named parameters are used
-/// and the strings like $1 are infact to simply to be passed trough unchanged.
-void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name,
- StringRef Body,
- ArrayRef<MCAsmMacroParameter> Parameters) {
- // If this macro is not defined with named parameters the warning we are
- // checking for here doesn't apply.
- unsigned NParameters = Parameters.size();
- if (NParameters == 0)
- return;
-
- bool NamedParametersFound = false;
- bool PositionalParametersFound = false;
-
- // Look at the body of the macro for use of both the named parameters and what
- // are likely to be positional parameters. This is what expandMacro() is
- // doing when it finds the parameters in the body.
- while (!Body.empty()) {
- // Scan for the next possible parameter.
- std::size_t End = Body.size(), Pos = 0;
- for (; Pos != End; ++Pos) {
- // Check for a substitution or escape.
- // This macro is defined with parameters, look for \foo, \bar, etc.
- if (Body[Pos] == '\\' && Pos + 1 != End)
- break;
-
- // This macro should have parameters, but look for $0, $1, ..., $n too.
- if (Body[Pos] != '$' || Pos + 1 == End)
- continue;
- char Next = Body[Pos + 1];
- if (Next == '$' || Next == 'n' ||
- isdigit(static_cast<unsigned char>(Next)))
- break;
- }
-
- // Check if we reached the end.
- if (Pos == End)
- break;
-
- if (Body[Pos] == '$') {
- switch (Body[Pos + 1]) {
- // $$ => $
- case '$':
- break;
-
- // $n => number of arguments
- case 'n':
- PositionalParametersFound = true;
- break;
-
- // $[0-9] => argument
- default: {
- PositionalParametersFound = true;
- break;
- }
- }
- Pos += 2;
- } else {
- unsigned I = Pos + 1;
- while (isIdentifierChar(Body[I]) && I + 1 != End)
- ++I;
-
- const char *Begin = Body.data() + Pos + 1;
- StringRef Argument(Begin, I - (Pos + 1));
- unsigned Index = 0;
- for (; Index < NParameters; ++Index)
- if (Parameters[Index].Name == Argument)
- break;
-
- if (Index == NParameters) {
- if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')
- Pos += 3;
- else {
- Pos = I;
- }
- } else {
- NamedParametersFound = true;
- Pos += 1 + Argument.size();
- }
- }
- // Update the scan point.
- Body = Body.substr(Pos);
- }
-
- if (!NamedParametersFound && PositionalParametersFound)
- Warning(DirectiveLoc, "macro defined with named parameters which are not "
- "used in macro body, possible positional parameter "
- "found in body which will have no effect");
-}
-
-/// parseDirectiveExitMacro
-/// ::= .exitm
-bool AsmParser::parseDirectiveExitMacro(StringRef Directive) {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '" + Directive + "' directive"))
- return true;
-
- if (!isInsideMacroInstantiation())
- return TokError("unexpected '" + Directive + "' in file, "
- "no current macro definition");
-
- // Exit all conditionals that are active in the current macro.
- while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
- TheCondState = TheCondStack.back();
- TheCondStack.pop_back();
- }
-
- handleMacroExit();
- return false;
-}
-
-/// parseDirectiveEndMacro
-/// ::= .endm
-/// ::= .endmacro
-bool AsmParser::parseDirectiveEndMacro(StringRef Directive) {
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '" + Directive + "' directive");
-
- // If we are inside a macro instantiation, terminate the current
- // instantiation.
- if (isInsideMacroInstantiation()) {
- handleMacroExit();
- return false;
- }
-
- // Otherwise, this .endmacro is a stray entry in the file; well formed
- // .endmacro directives are handled during the macro definition parsing.
- return TokError("unexpected '" + Directive + "' in file, "
- "no current macro definition");
-}
-
-/// parseDirectivePurgeMacro
-/// ::= .purgem
-bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
- StringRef Name;
- SMLoc Loc;
- if (parseTokenLoc(Loc) ||
- check(parseIdentifier(Name), Loc,
- "expected identifier in '.purgem' directive") ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.purgem' directive"))
- return true;
-
- if (!getContext().lookupMacro(Name))
- return Error(DirectiveLoc, "macro '" + Name + "' is not defined");
-
- getContext().undefineMacro(Name);
- DEBUG_WITH_TYPE("asm-macros", dbgs()
- << "Un-defining macro: " << Name << "\n");
- return false;
-}
-
-/// parseDirectiveBundleAlignMode
-/// ::= {.bundle_align_mode} expression
-bool AsmParser::parseDirectiveBundleAlignMode() {
- // Expect a single argument: an expression that evaluates to a constant
- // in the inclusive range 0-30.
- SMLoc ExprLoc = getLexer().getLoc();
- int64_t AlignSizePow2;
- if (checkForValidSection() || parseAbsoluteExpression(AlignSizePow2) ||
- parseToken(AsmToken::EndOfStatement, "unexpected token after expression "
- "in '.bundle_align_mode' "
- "directive") ||
- check(AlignSizePow2 < 0 || AlignSizePow2 > 30, ExprLoc,
- "invalid bundle alignment size (expected between 0 and 30)"))
- return true;
-
- // Because of AlignSizePow2's verified range we can safely truncate it to
- // unsigned.
- getStreamer().EmitBundleAlignMode(static_cast<unsigned>(AlignSizePow2));
- return false;
-}
-
-/// parseDirectiveBundleLock
-/// ::= {.bundle_lock} [align_to_end]
-bool AsmParser::parseDirectiveBundleLock() {
- if (checkForValidSection())
- return true;
- bool AlignToEnd = false;
-
- StringRef Option;
- SMLoc Loc = getTok().getLoc();
- const char *kInvalidOptionError =
- "invalid option for '.bundle_lock' directive";
-
- if (!parseOptionalToken(AsmToken::EndOfStatement)) {
- if (check(parseIdentifier(Option), Loc, kInvalidOptionError) ||
- check(Option != "align_to_end", Loc, kInvalidOptionError) ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token after '.bundle_lock' directive option"))
- return true;
- AlignToEnd = true;
- }
-
- getStreamer().EmitBundleLock(AlignToEnd);
- return false;
-}
-
-/// parseDirectiveBundleLock
-/// ::= {.bundle_lock}
-bool AsmParser::parseDirectiveBundleUnlock() {
- if (checkForValidSection() ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.bundle_unlock' directive"))
- return true;
-
- getStreamer().EmitBundleUnlock();
- return false;
-}
-
-/// parseDirectiveSpace
-/// ::= (.skip | .space) expression [ , expression ]
-bool AsmParser::parseDirectiveSpace(StringRef IDVal) {
- SMLoc NumBytesLoc = Lexer.getLoc();
- const MCExpr *NumBytes;
- if (checkForValidSection() || parseExpression(NumBytes))
- return true;
-
- int64_t FillExpr = 0;
- if (parseOptionalToken(AsmToken::Comma))
- if (parseAbsoluteExpression(FillExpr))
- return addErrorSuffix("in '" + Twine(IDVal) + "' directive");
- if (parseToken(AsmToken::EndOfStatement))
- return addErrorSuffix("in '" + Twine(IDVal) + "' directive");
-
- // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
- getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc);
-
- return false;
-}
-
-/// parseDirectiveDCB
-/// ::= .dcb.{b, l, w} expression, expression
-bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) {
- SMLoc NumValuesLoc = Lexer.getLoc();
- int64_t NumValues;
- if (checkForValidSection() || parseAbsoluteExpression(NumValues))
- return true;
-
- if (NumValues < 0) {
- Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
- return false;
- }
-
- if (parseToken(AsmToken::Comma,
- "unexpected token in '" + Twine(IDVal) + "' directive"))
- return true;
-
- const MCExpr *Value;
- SMLoc ExprLoc = getLexer().getLoc();
- if (parseExpression(Value))
- return true;
-
- // Special case constant expressions to match code generator.
- if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
- assert(Size <= 8 && "Invalid size");
- uint64_t IntValue = MCE->getValue();
- if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
- return Error(ExprLoc, "literal value out of range for directive");
- for (uint64_t i = 0, e = NumValues; i != e; ++i)
- getStreamer().EmitIntValue(IntValue, Size);
- } else {
- for (uint64_t i = 0, e = NumValues; i != e; ++i)
- getStreamer().EmitValue(Value, Size, ExprLoc);
- }
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '" + Twine(IDVal) + "' directive"))
- return true;
-
- return false;
-}
-
-/// parseDirectiveRealDCB
-/// ::= .dcb.{d, s} expression, expression
-bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Semantics) {
- SMLoc NumValuesLoc = Lexer.getLoc();
- int64_t NumValues;
- if (checkForValidSection() || parseAbsoluteExpression(NumValues))
- return true;
-
- if (NumValues < 0) {
- Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
- return false;
- }
-
- if (parseToken(AsmToken::Comma,
- "unexpected token in '" + Twine(IDVal) + "' directive"))
- return true;
-
- APInt AsInt;
- if (parseRealValue(Semantics, AsInt))
- return true;
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '" + Twine(IDVal) + "' directive"))
- return true;
-
- for (uint64_t i = 0, e = NumValues; i != e; ++i)
- getStreamer().EmitIntValue(AsInt.getLimitedValue(),
- AsInt.getBitWidth() / 8);
-
- return false;
-}
-
-/// parseDirectiveDS
-/// ::= .ds.{b, d, l, p, s, w, x} expression
-bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) {
- SMLoc NumValuesLoc = Lexer.getLoc();
- int64_t NumValues;
- if (checkForValidSection() || parseAbsoluteExpression(NumValues))
- return true;
-
- if (NumValues < 0) {
- Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
- return false;
- }
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '" + Twine(IDVal) + "' directive"))
- return true;
-
- for (uint64_t i = 0, e = NumValues; i != e; ++i)
- getStreamer().emitFill(Size, 0);
-
- return false;
-}
-
-/// parseDirectiveLEB128
-/// ::= (.sleb128 | .uleb128) [ expression (, expression)* ]
-bool AsmParser::parseDirectiveLEB128(bool Signed) {
- if (checkForValidSection())
- return true;
-
- auto parseOp = [&]() -> bool {
- const MCExpr *Value;
- if (parseExpression(Value))
- return true;
- if (Signed)
- getStreamer().EmitSLEB128Value(Value);
- else
- getStreamer().EmitULEB128Value(Value);
- return false;
- };
-
- if (parseMany(parseOp))
- return addErrorSuffix(" in directive");
-
- return false;
-}
-
-/// parseDirectiveSymbolAttribute
-/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
-bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
- auto parseOp = [&]() -> bool {
- StringRef Name;
- SMLoc Loc = getTok().getLoc();
- if (parseIdentifier(Name))
- return Error(Loc, "expected identifier");
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- // Assembler local symbols don't make any sense here. Complain loudly.
- if (Sym->isTemporary())
- return Error(Loc, "non-local symbol required");
-
- if (!getStreamer().EmitSymbolAttribute(Sym, Attr))
- return Error(Loc, "unable to emit symbol attribute");
- return false;
- };
-
- if (parseMany(parseOp))
- return addErrorSuffix(" in directive");
- return false;
-}
-
-/// parseDirectiveComm
-/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
-bool AsmParser::parseDirectiveComm(bool IsLocal) {
- if (checkForValidSection())
- return true;
-
- SMLoc IDLoc = getLexer().getLoc();
- StringRef Name;
- if (parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- // Handle the identifier as the key symbol.
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- int64_t Size;
- SMLoc SizeLoc = getLexer().getLoc();
- if (parseAbsoluteExpression(Size))
- return true;
-
- int64_t Pow2Alignment = 0;
- SMLoc Pow2AlignmentLoc;
- if (getLexer().is(AsmToken::Comma)) {
- Lex();
- Pow2AlignmentLoc = getLexer().getLoc();
- if (parseAbsoluteExpression(Pow2Alignment))
- return true;
-
- LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
- if (IsLocal && LCOMM == LCOMM::NoAlignment)
- return Error(Pow2AlignmentLoc, "alignment not supported on this target");
-
- // If this target takes alignments in bytes (not log) validate and convert.
- if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
- (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
- if (!isPowerOf2_64(Pow2Alignment))
- return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
- Pow2Alignment = Log2_64(Pow2Alignment);
- }
- }
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.comm' or '.lcomm' directive"))
- return true;
-
- // NOTE: a size of zero for a .comm should create a undefined symbol
- // but a size of .lcomm creates a bss symbol of size zero.
- if (Size < 0)
- return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
- "be less than zero");
-
- // NOTE: The alignment in the directive is a power of 2 value, the assembler
- // may internally end up wanting an alignment in bytes.
- // FIXME: Diagnose overflow.
- if (Pow2Alignment < 0)
- return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
- "alignment, can't be less than zero");
-
- Sym->redefineIfPossible();
- if (!Sym->isUndefined())
- return Error(IDLoc, "invalid symbol redefinition");
-
- // Create the Symbol as a common or local common with Size and Pow2Alignment
- if (IsLocal) {
- getStreamer().EmitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment);
- return false;
- }
-
- getStreamer().EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment);
- return false;
-}
-
-/// parseDirectiveAbort
-/// ::= .abort [... message ...]
-bool AsmParser::parseDirectiveAbort() {
- // FIXME: Use loc from directive.
- SMLoc Loc = getLexer().getLoc();
-
- StringRef Str = parseStringToEndOfStatement();
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.abort' directive"))
- return true;
-
- if (Str.empty())
- return Error(Loc, ".abort detected. Assembly stopping.");
- else
- return Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
- // FIXME: Actually abort assembly here.
-
- return false;
-}
-
-/// parseDirectiveInclude
-/// ::= .include "filename"
-bool AsmParser::parseDirectiveInclude() {
- // Allow the strings to have escaped octal character sequence.
- std::string Filename;
- SMLoc IncludeLoc = getTok().getLoc();
-
- if (check(getTok().isNot(AsmToken::String),
- "expected string in '.include' directive") ||
- parseEscapedString(Filename) ||
- check(getTok().isNot(AsmToken::EndOfStatement),
- "unexpected token in '.include' directive") ||
- // Attempt to switch the lexer to the included file before consuming the
- // end of statement to avoid losing it when we switch.
- check(enterIncludeFile(Filename), IncludeLoc,
- "Could not find include file '" + Filename + "'"))
- return true;
-
- return false;
-}
-
-/// parseDirectiveIncbin
-/// ::= .incbin "filename" [ , skip [ , count ] ]
-bool AsmParser::parseDirectiveIncbin() {
- // Allow the strings to have escaped octal character sequence.
- std::string Filename;
- SMLoc IncbinLoc = getTok().getLoc();
- if (check(getTok().isNot(AsmToken::String),
- "expected string in '.incbin' directive") ||
- parseEscapedString(Filename))
- return true;
-
- int64_t Skip = 0;
- const MCExpr *Count = nullptr;
- SMLoc SkipLoc, CountLoc;
- if (parseOptionalToken(AsmToken::Comma)) {
- // The skip expression can be omitted while specifying the count, e.g:
- // .incbin "filename",,4
- if (getTok().isNot(AsmToken::Comma)) {
- if (parseTokenLoc(SkipLoc) || parseAbsoluteExpression(Skip))
- return true;
- }
- if (parseOptionalToken(AsmToken::Comma)) {
- CountLoc = getTok().getLoc();
- if (parseExpression(Count))
- return true;
- }
- }
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.incbin' directive"))
- return true;
-
- if (check(Skip < 0, SkipLoc, "skip is negative"))
- return true;
-
- // Attempt to process the included file.
- if (processIncbinFile(Filename, Skip, Count, CountLoc))
- return Error(IncbinLoc, "Could not find incbin file '" + Filename + "'");
- return false;
-}
-
-/// parseDirectiveIf
-/// ::= .if{,eq,ge,gt,le,lt,ne} expression
-bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
- TheCondStack.push_back(TheCondState);
- TheCondState.TheCond = AsmCond::IfCond;
- if (TheCondState.Ignore) {
- eatToEndOfStatement();
- } else {
- int64_t ExprValue;
- if (parseAbsoluteExpression(ExprValue) ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.if' directive"))
- return true;
-
- switch (DirKind) {
- default:
- llvm_unreachable("unsupported directive");
- case DK_IF:
- case DK_IFNE:
- break;
- case DK_IFEQ:
- ExprValue = ExprValue == 0;
- break;
- case DK_IFGE:
- ExprValue = ExprValue >= 0;
- break;
- case DK_IFGT:
- ExprValue = ExprValue > 0;
- break;
- case DK_IFLE:
- ExprValue = ExprValue <= 0;
- break;
- case DK_IFLT:
- ExprValue = ExprValue < 0;
- break;
- }
-
- TheCondState.CondMet = ExprValue;
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// parseDirectiveIfb
-/// ::= .ifb string
-bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
- TheCondStack.push_back(TheCondState);
- TheCondState.TheCond = AsmCond::IfCond;
-
- if (TheCondState.Ignore) {
- eatToEndOfStatement();
- } else {
- StringRef Str = parseStringToEndOfStatement();
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.ifb' directive"))
- return true;
-
- TheCondState.CondMet = ExpectBlank == Str.empty();
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// parseDirectiveIfc
-/// ::= .ifc string1, string2
-/// ::= .ifnc string1, string2
-bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
- TheCondStack.push_back(TheCondState);
- TheCondState.TheCond = AsmCond::IfCond;
-
- if (TheCondState.Ignore) {
- eatToEndOfStatement();
- } else {
- StringRef Str1 = parseStringToComma();
-
- if (parseToken(AsmToken::Comma, "unexpected token in '.ifc' directive"))
- return true;
-
- StringRef Str2 = parseStringToEndOfStatement();
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.ifc' directive"))
- return true;
-
- TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim());
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// parseDirectiveIfeqs
-/// ::= .ifeqs string1, string2
-bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {
- if (Lexer.isNot(AsmToken::String)) {
- if (ExpectEqual)
- return TokError("expected string parameter for '.ifeqs' directive");
- return TokError("expected string parameter for '.ifnes' directive");
- }
-
- StringRef String1 = getTok().getStringContents();
- Lex();
-
- if (Lexer.isNot(AsmToken::Comma)) {
- if (ExpectEqual)
- return TokError(
- "expected comma after first string for '.ifeqs' directive");
- return TokError("expected comma after first string for '.ifnes' directive");
- }
-
- Lex();
-
- if (Lexer.isNot(AsmToken::String)) {
- if (ExpectEqual)
- return TokError("expected string parameter for '.ifeqs' directive");
- return TokError("expected string parameter for '.ifnes' directive");
- }
-
- StringRef String2 = getTok().getStringContents();
- Lex();
-
- TheCondStack.push_back(TheCondState);
- TheCondState.TheCond = AsmCond::IfCond;
- TheCondState.CondMet = ExpectEqual == (String1 == String2);
- TheCondState.Ignore = !TheCondState.CondMet;
-
- return false;
-}
-
-/// parseDirectiveIfdef
-/// ::= .ifdef symbol
-bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
- StringRef Name;
- TheCondStack.push_back(TheCondState);
- TheCondState.TheCond = AsmCond::IfCond;
-
- if (TheCondState.Ignore) {
- eatToEndOfStatement();
- } else {
- if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") ||
- parseToken(AsmToken::EndOfStatement, "unexpected token in '.ifdef'"))
- return true;
-
- MCSymbol *Sym = getContext().lookupSymbol(Name);
-
- if (expect_defined)
- TheCondState.CondMet = (Sym && !Sym->isUndefined(false));
- else
- TheCondState.CondMet = (!Sym || Sym->isUndefined(false));
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// parseDirectiveElseIf
-/// ::= .elseif expression
-bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) {
- if (TheCondState.TheCond != AsmCond::IfCond &&
- TheCondState.TheCond != AsmCond::ElseIfCond)
- return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
- " .if or an .elseif");
- TheCondState.TheCond = AsmCond::ElseIfCond;
-
- bool LastIgnoreState = false;
- if (!TheCondStack.empty())
- LastIgnoreState = TheCondStack.back().Ignore;
- if (LastIgnoreState || TheCondState.CondMet) {
- TheCondState.Ignore = true;
- eatToEndOfStatement();
- } else {
- int64_t ExprValue;
- if (parseAbsoluteExpression(ExprValue))
- return true;
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.elseif' directive"))
- return true;
-
- TheCondState.CondMet = ExprValue;
- TheCondState.Ignore = !TheCondState.CondMet;
- }
-
- return false;
-}
-
-/// parseDirectiveElse
-/// ::= .else
-bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.else' directive"))
- return true;
-
- if (TheCondState.TheCond != AsmCond::IfCond &&
- TheCondState.TheCond != AsmCond::ElseIfCond)
- return Error(DirectiveLoc, "Encountered a .else that doesn't follow "
- " an .if or an .elseif");
- TheCondState.TheCond = AsmCond::ElseCond;
- bool LastIgnoreState = false;
- if (!TheCondStack.empty())
- LastIgnoreState = TheCondStack.back().Ignore;
- if (LastIgnoreState || TheCondState.CondMet)
- TheCondState.Ignore = true;
- else
- TheCondState.Ignore = false;
-
- return false;
-}
-
-/// parseDirectiveEnd
-/// ::= .end
-bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.end' directive"))
- return true;
-
- while (Lexer.isNot(AsmToken::Eof))
- Lexer.Lex();
-
- return false;
-}
-
-/// parseDirectiveError
-/// ::= .err
-/// ::= .error [string]
-bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) {
- if (!TheCondStack.empty()) {
- if (TheCondStack.back().Ignore) {
- eatToEndOfStatement();
- return false;
- }
- }
-
- if (!WithMessage)
- return Error(L, ".err encountered");
-
- StringRef Message = ".error directive invoked in source file";
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- if (Lexer.isNot(AsmToken::String))
- return TokError(".error argument must be a string");
-
- Message = getTok().getStringContents();
- Lex();
- }
-
- return Error(L, Message);
-}
-
-/// parseDirectiveWarning
-/// ::= .warning [string]
-bool AsmParser::parseDirectiveWarning(SMLoc L) {
- if (!TheCondStack.empty()) {
- if (TheCondStack.back().Ignore) {
- eatToEndOfStatement();
- return false;
- }
- }
-
- StringRef Message = ".warning directive invoked in source file";
-
- if (!parseOptionalToken(AsmToken::EndOfStatement)) {
- if (Lexer.isNot(AsmToken::String))
- return TokError(".warning argument must be a string");
-
- Message = getTok().getStringContents();
- Lex();
- if (parseToken(AsmToken::EndOfStatement,
- "expected end of statement in '.warning' directive"))
- return true;
- }
-
- return Warning(L, Message);
-}
-
-/// parseDirectiveEndIf
-/// ::= .endif
-bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.endif' directive"))
- return true;
-
- if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
- return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
- "an .if or .else");
- if (!TheCondStack.empty()) {
- TheCondState = TheCondStack.back();
- TheCondStack.pop_back();
- }
-
- return false;
-}
-
-void AsmParser::initializeDirectiveKindMap() {
- DirectiveKindMap[".set"] = DK_SET;
- DirectiveKindMap[".equ"] = DK_EQU;
- DirectiveKindMap[".equiv"] = DK_EQUIV;
- DirectiveKindMap[".ascii"] = DK_ASCII;
- DirectiveKindMap[".asciz"] = DK_ASCIZ;
- DirectiveKindMap[".string"] = DK_STRING;
- DirectiveKindMap[".byte"] = DK_BYTE;
- DirectiveKindMap[".short"] = DK_SHORT;
- DirectiveKindMap[".value"] = DK_VALUE;
- DirectiveKindMap[".2byte"] = DK_2BYTE;
- DirectiveKindMap[".long"] = DK_LONG;
- DirectiveKindMap[".int"] = DK_INT;
- DirectiveKindMap[".4byte"] = DK_4BYTE;
- DirectiveKindMap[".quad"] = DK_QUAD;
- DirectiveKindMap[".8byte"] = DK_8BYTE;
- DirectiveKindMap[".octa"] = DK_OCTA;
- DirectiveKindMap[".single"] = DK_SINGLE;
- DirectiveKindMap[".float"] = DK_FLOAT;
- DirectiveKindMap[".double"] = DK_DOUBLE;
- DirectiveKindMap[".align"] = DK_ALIGN;
- DirectiveKindMap[".align32"] = DK_ALIGN32;
- DirectiveKindMap[".balign"] = DK_BALIGN;
- DirectiveKindMap[".balignw"] = DK_BALIGNW;
- DirectiveKindMap[".balignl"] = DK_BALIGNL;
- DirectiveKindMap[".p2align"] = DK_P2ALIGN;
- DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW;
- DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL;
- DirectiveKindMap[".org"] = DK_ORG;
- DirectiveKindMap[".fill"] = DK_FILL;
- DirectiveKindMap[".zero"] = DK_ZERO;
- DirectiveKindMap[".extern"] = DK_EXTERN;
- DirectiveKindMap[".globl"] = DK_GLOBL;
- DirectiveKindMap[".global"] = DK_GLOBAL;
- DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE;
- DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP;
- DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER;
- DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN;
- DirectiveKindMap[".reference"] = DK_REFERENCE;
- DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION;
- DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE;
- DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN;
- DirectiveKindMap[".cold"] = DK_COLD;
- DirectiveKindMap[".comm"] = DK_COMM;
- DirectiveKindMap[".common"] = DK_COMMON;
- DirectiveKindMap[".lcomm"] = DK_LCOMM;
- DirectiveKindMap[".abort"] = DK_ABORT;
- DirectiveKindMap[".include"] = DK_INCLUDE;
- DirectiveKindMap[".incbin"] = DK_INCBIN;
- DirectiveKindMap[".code16"] = DK_CODE16;
- DirectiveKindMap[".code16gcc"] = DK_CODE16GCC;
- DirectiveKindMap[".rept"] = DK_REPT;
- DirectiveKindMap[".rep"] = DK_REPT;
- DirectiveKindMap[".irp"] = DK_IRP;
- DirectiveKindMap[".irpc"] = DK_IRPC;
- DirectiveKindMap[".endr"] = DK_ENDR;
- DirectiveKindMap[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE;
- DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK;
- DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK;
- DirectiveKindMap[".if"] = DK_IF;
- DirectiveKindMap[".ifeq"] = DK_IFEQ;
- DirectiveKindMap[".ifge"] = DK_IFGE;
- DirectiveKindMap[".ifgt"] = DK_IFGT;
- DirectiveKindMap[".ifle"] = DK_IFLE;
- DirectiveKindMap[".iflt"] = DK_IFLT;
- DirectiveKindMap[".ifne"] = DK_IFNE;
- DirectiveKindMap[".ifb"] = DK_IFB;
- DirectiveKindMap[".ifnb"] = DK_IFNB;
- DirectiveKindMap[".ifc"] = DK_IFC;
- DirectiveKindMap[".ifeqs"] = DK_IFEQS;
- DirectiveKindMap[".ifnc"] = DK_IFNC;
- DirectiveKindMap[".ifnes"] = DK_IFNES;
- DirectiveKindMap[".ifdef"] = DK_IFDEF;
- DirectiveKindMap[".ifndef"] = DK_IFNDEF;
- DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF;
- DirectiveKindMap[".elseif"] = DK_ELSEIF;
- DirectiveKindMap[".else"] = DK_ELSE;
- DirectiveKindMap[".end"] = DK_END;
- DirectiveKindMap[".endif"] = DK_ENDIF;
- DirectiveKindMap[".skip"] = DK_SKIP;
- DirectiveKindMap[".space"] = DK_SPACE;
- DirectiveKindMap[".file"] = DK_FILE;
- DirectiveKindMap[".line"] = DK_LINE;
- DirectiveKindMap[".loc"] = DK_LOC;
- DirectiveKindMap[".stabs"] = DK_STABS;
- DirectiveKindMap[".cv_file"] = DK_CV_FILE;
- DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
- DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
- DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
- DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
- DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
- DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
- DirectiveKindMap[".cv_string"] = DK_CV_STRING;
- DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
- DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
- DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
- DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
- DirectiveKindMap[".sleb128"] = DK_SLEB128;
- DirectiveKindMap[".uleb128"] = DK_ULEB128;
- DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
- DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
- DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
- DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
- DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
- DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
- DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
- DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
- DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
- DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
- DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
- DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
- DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
- DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
- DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
- DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
- DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
- DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
- DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
- DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
- DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
- DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
- DirectiveKindMap[".macros_on"] = DK_MACROS_ON;
- DirectiveKindMap[".macros_off"] = DK_MACROS_OFF;
- DirectiveKindMap[".macro"] = DK_MACRO;
- DirectiveKindMap[".exitm"] = DK_EXITM;
- DirectiveKindMap[".endm"] = DK_ENDM;
- DirectiveKindMap[".endmacro"] = DK_ENDMACRO;
- DirectiveKindMap[".purgem"] = DK_PURGEM;
- DirectiveKindMap[".err"] = DK_ERR;
- DirectiveKindMap[".error"] = DK_ERROR;
- DirectiveKindMap[".warning"] = DK_WARNING;
- DirectiveKindMap[".altmacro"] = DK_ALTMACRO;
- DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;
- DirectiveKindMap[".reloc"] = DK_RELOC;
- DirectiveKindMap[".dc"] = DK_DC;
- DirectiveKindMap[".dc.a"] = DK_DC_A;
- DirectiveKindMap[".dc.b"] = DK_DC_B;
- DirectiveKindMap[".dc.d"] = DK_DC_D;
- DirectiveKindMap[".dc.l"] = DK_DC_L;
- DirectiveKindMap[".dc.s"] = DK_DC_S;
- DirectiveKindMap[".dc.w"] = DK_DC_W;
- DirectiveKindMap[".dc.x"] = DK_DC_X;
- DirectiveKindMap[".dcb"] = DK_DCB;
- DirectiveKindMap[".dcb.b"] = DK_DCB_B;
- DirectiveKindMap[".dcb.d"] = DK_DCB_D;
- DirectiveKindMap[".dcb.l"] = DK_DCB_L;
- DirectiveKindMap[".dcb.s"] = DK_DCB_S;
- DirectiveKindMap[".dcb.w"] = DK_DCB_W;
- DirectiveKindMap[".dcb.x"] = DK_DCB_X;
- DirectiveKindMap[".ds"] = DK_DS;
- DirectiveKindMap[".ds.b"] = DK_DS_B;
- DirectiveKindMap[".ds.d"] = DK_DS_D;
- DirectiveKindMap[".ds.l"] = DK_DS_L;
- DirectiveKindMap[".ds.p"] = DK_DS_P;
- DirectiveKindMap[".ds.s"] = DK_DS_S;
- DirectiveKindMap[".ds.w"] = DK_DS_W;
- DirectiveKindMap[".ds.x"] = DK_DS_X;
- DirectiveKindMap[".print"] = DK_PRINT;
- DirectiveKindMap[".addrsig"] = DK_ADDRSIG;
- DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM;
-}
-
-MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
- AsmToken EndToken, StartToken = getTok();
-
- unsigned NestLevel = 0;
- while (true) {
- // Check whether we have reached the end of the file.
- if (getLexer().is(AsmToken::Eof)) {
- printError(DirectiveLoc, "no matching '.endr' in definition");
- return nullptr;
- }
-
- if (Lexer.is(AsmToken::Identifier) &&
- (getTok().getIdentifier() == ".rep" ||
- getTok().getIdentifier() == ".rept" ||
- getTok().getIdentifier() == ".irp" ||
- getTok().getIdentifier() == ".irpc")) {
- ++NestLevel;
- }
-
- // Otherwise, check whether we have reached the .endr.
- if (Lexer.is(AsmToken::Identifier) && getTok().getIdentifier() == ".endr") {
- if (NestLevel == 0) {
- EndToken = getTok();
- Lex();
- if (Lexer.isNot(AsmToken::EndOfStatement)) {
- printError(getTok().getLoc(),
- "unexpected token in '.endr' directive");
- return nullptr;
- }
- break;
- }
- --NestLevel;
- }
-
- // Otherwise, scan till the end of the statement.
- eatToEndOfStatement();
- }
-
- const char *BodyStart = StartToken.getLoc().getPointer();
- const char *BodyEnd = EndToken.getLoc().getPointer();
- StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
-
- // We Are Anonymous.
- MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
- return &MacroLikeBodies.back();
-}
-
-void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
- raw_svector_ostream &OS) {
- OS << ".endr\n";
-
- std::unique_ptr<MemoryBuffer> Instantiation =
- MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
-
- // Create the macro instantiation object and add to the current macro
- // instantiation stack.
- MacroInstantiation *MI = new MacroInstantiation(
- DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size());
- ActiveMacros.push_back(MI);
-
- // Jump to the macro instantiation and prime the lexer.
- CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
- Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
- Lex();
-}
-
-/// parseDirectiveRept
-/// ::= .rep | .rept count
-bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {
- const MCExpr *CountExpr;
- SMLoc CountLoc = getTok().getLoc();
- if (parseExpression(CountExpr))
- return true;
-
- int64_t Count;
- if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
- return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
- }
-
- if (check(Count < 0, CountLoc, "Count is negative") ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '" + Dir + "' directive"))
- return true;
-
- // Lex the rept definition.
- MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
- if (!M)
- return true;
-
- // Macro instantiation is lexical, unfortunately. We construct a new buffer
- // to hold the macro body with substitutions.
- SmallString<256> Buf;
- raw_svector_ostream OS(Buf);
- while (Count--) {
- // Note that the AtPseudoVariable is disabled for instantiations of .rep(t).
- if (expandMacro(OS, M->Body, None, None, false, getTok().getLoc()))
- return true;
- }
- instantiateMacroLikeBody(M, DirectiveLoc, OS);
-
- return false;
-}
-
-/// parseDirectiveIrp
-/// ::= .irp symbol,values
-bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) {
- MCAsmMacroParameter Parameter;
- MCAsmMacroArguments A;
- if (check(parseIdentifier(Parameter.Name),
- "expected identifier in '.irp' directive") ||
- parseToken(AsmToken::Comma, "expected comma in '.irp' directive") ||
- parseMacroArguments(nullptr, A) ||
- parseToken(AsmToken::EndOfStatement, "expected End of Statement"))
- return true;
-
- // Lex the irp definition.
- MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
- if (!M)
- return true;
-
- // Macro instantiation is lexical, unfortunately. We construct a new buffer
- // to hold the macro body with substitutions.
- SmallString<256> Buf;
- raw_svector_ostream OS(Buf);
-
- for (const MCAsmMacroArgument &Arg : A) {
- // Note that the AtPseudoVariable is enabled for instantiations of .irp.
- // This is undocumented, but GAS seems to support it.
- if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc()))
- return true;
- }
-
- instantiateMacroLikeBody(M, DirectiveLoc, OS);
-
- return false;
-}
-
-/// parseDirectiveIrpc
-/// ::= .irpc symbol,values
-bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) {
- MCAsmMacroParameter Parameter;
- MCAsmMacroArguments A;
-
- if (check(parseIdentifier(Parameter.Name),
- "expected identifier in '.irpc' directive") ||
- parseToken(AsmToken::Comma, "expected comma in '.irpc' directive") ||
- parseMacroArguments(nullptr, A))
- return true;
-
- if (A.size() != 1 || A.front().size() != 1)
- return TokError("unexpected token in '.irpc' directive");
-
- // Eat the end of statement.
- if (parseToken(AsmToken::EndOfStatement, "expected end of statement"))
- return true;
-
- // Lex the irpc definition.
- MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
- if (!M)
- return true;
-
- // Macro instantiation is lexical, unfortunately. We construct a new buffer
- // to hold the macro body with substitutions.
- SmallString<256> Buf;
- raw_svector_ostream OS(Buf);
-
- StringRef Values = A.front().front().getString();
- for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
- MCAsmMacroArgument Arg;
- Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1));
-
- // Note that the AtPseudoVariable is enabled for instantiations of .irpc.
- // This is undocumented, but GAS seems to support it.
- if (expandMacro(OS, M->Body, Parameter, Arg, true, getTok().getLoc()))
- return true;
- }
-
- instantiateMacroLikeBody(M, DirectiveLoc, OS);
-
- return false;
-}
-
-bool AsmParser::parseDirectiveEndr(SMLoc DirectiveLoc) {
- if (ActiveMacros.empty())
- return TokError("unmatched '.endr' directive");
-
- // The only .repl that should get here are the ones created by
- // instantiateMacroLikeBody.
- assert(getLexer().is(AsmToken::EndOfStatement));
-
- handleMacroExit();
- return false;
-}
-
-bool AsmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
- size_t Len) {
- const MCExpr *Value;
- SMLoc ExprLoc = getLexer().getLoc();
- if (parseExpression(Value))
- return true;
- const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
- if (!MCE)
- return Error(ExprLoc, "unexpected expression in _emit");
- uint64_t IntValue = MCE->getValue();
- if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
- return Error(ExprLoc, "literal value out of range for directive");
-
- Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
- return false;
-}
-
-bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
- const MCExpr *Value;
- SMLoc ExprLoc = getLexer().getLoc();
- if (parseExpression(Value))
- return true;
- const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
- if (!MCE)
- return Error(ExprLoc, "unexpected expression in align");
- uint64_t IntValue = MCE->getValue();
- if (!isPowerOf2_64(IntValue))
- return Error(ExprLoc, "literal value not a power of two greater then zero");
-
- Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
- return false;
-}
-
-bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) {
- const AsmToken StrTok = getTok();
- Lex();
- if (StrTok.isNot(AsmToken::String) || StrTok.getString().front() != '"')
- return Error(DirectiveLoc, "expected double quoted string after .print");
- if (parseToken(AsmToken::EndOfStatement, "expected end of statement"))
- return true;
- llvm::outs() << StrTok.getStringContents() << '\n';
- return false;
-}
-
-bool AsmParser::parseDirectiveAddrsig() {
- getStreamer().EmitAddrsig();
- return false;
-}
-
-bool AsmParser::parseDirectiveAddrsigSym() {
- StringRef Name;
- if (check(parseIdentifier(Name),
- "expected identifier in '.addrsig_sym' directive"))
- return true;
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- getStreamer().EmitAddrsigSym(Sym);
- return false;
-}
-
-// We are comparing pointers, but the pointers are relative to a single string.
-// Thus, this should always be deterministic.
-static int rewritesSort(const AsmRewrite *AsmRewriteA,
- const AsmRewrite *AsmRewriteB) {
- if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
- return -1;
- if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
- return 1;
-
- // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
- // rewrite to the same location. Make sure the SizeDirective rewrite is
- // performed first, then the Imm/ImmPrefix and finally the Input/Output. This
- // ensures the sort algorithm is stable.
- if (AsmRewritePrecedence[AsmRewriteA->Kind] >
- AsmRewritePrecedence[AsmRewriteB->Kind])
- return -1;
-
- if (AsmRewritePrecedence[AsmRewriteA->Kind] <
- AsmRewritePrecedence[AsmRewriteB->Kind])
- return 1;
- llvm_unreachable("Unstable rewrite sort.");
-}
-
-bool AsmParser::parseMSInlineAsm(
- void *AsmLoc, std::string &AsmString, unsigned &NumOutputs,
- unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
- SmallVectorImpl<std::string> &Constraints,
- SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
- const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
- SmallVector<void *, 4> InputDecls;
- SmallVector<void *, 4> OutputDecls;
- SmallVector<bool, 4> InputDeclsAddressOf;
- SmallVector<bool, 4> OutputDeclsAddressOf;
- SmallVector<std::string, 4> InputConstraints;
- SmallVector<std::string, 4> OutputConstraints;
- SmallVector<unsigned, 4> ClobberRegs;
-
- SmallVector<AsmRewrite, 4> AsmStrRewrites;
-
- // Prime the lexer.
- Lex();
-
- // While we have input, parse each statement.
- unsigned InputIdx = 0;
- unsigned OutputIdx = 0;
- while (getLexer().isNot(AsmToken::Eof)) {
- // Parse curly braces marking block start/end
- if (parseCurlyBlockScope(AsmStrRewrites))
- continue;
-
- ParseStatementInfo Info(&AsmStrRewrites);
- bool StatementErr = parseStatement(Info, &SI);
-
- if (StatementErr || Info.ParseError) {
- // Emit pending errors if any exist.
- printPendingErrors();
- return true;
- }
-
- // No pending error should exist here.
- assert(!hasPendingError() && "unexpected error from parseStatement");
-
- if (Info.Opcode == ~0U)
- continue;
-
- const MCInstrDesc &Desc = MII->get(Info.Opcode);
-
- // Build the list of clobbers, outputs and inputs.
- for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
- MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
-
- // Immediate.
- if (Operand.isImm())
- continue;
-
- // Register operand.
- if (Operand.isReg() && !Operand.needAddressOf() &&
- !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) {
- unsigned NumDefs = Desc.getNumDefs();
- // Clobber.
- if (NumDefs && Operand.getMCOperandNum() < NumDefs)
- ClobberRegs.push_back(Operand.getReg());
- continue;
- }
-
- // Expr/Input or Output.
- StringRef SymName = Operand.getSymName();
- if (SymName.empty())
- continue;
-
- void *OpDecl = Operand.getOpDecl();
- if (!OpDecl)
- continue;
-
- bool isOutput = (i == 1) && Desc.mayStore();
- SMLoc Start = SMLoc::getFromPointer(SymName.data());
- if (isOutput) {
- ++InputIdx;
- OutputDecls.push_back(OpDecl);
- OutputDeclsAddressOf.push_back(Operand.needAddressOf());
- OutputConstraints.push_back(("=" + Operand.getConstraint()).str());
- AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size());
- } else {
- InputDecls.push_back(OpDecl);
- InputDeclsAddressOf.push_back(Operand.needAddressOf());
- InputConstraints.push_back(Operand.getConstraint().str());
- AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size());
- }
- }
-
- // Consider implicit defs to be clobbers. Think of cpuid and push.
- ArrayRef<MCPhysReg> ImpDefs(Desc.getImplicitDefs(),
- Desc.getNumImplicitDefs());
- ClobberRegs.insert(ClobberRegs.end(), ImpDefs.begin(), ImpDefs.end());
- }
-
- // Set the number of Outputs and Inputs.
- NumOutputs = OutputDecls.size();
- NumInputs = InputDecls.size();
-
- // Set the unique clobbers.
- array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
- ClobberRegs.erase(std::unique(ClobberRegs.begin(), ClobberRegs.end()),
- ClobberRegs.end());
- Clobbers.assign(ClobberRegs.size(), std::string());
- for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
- raw_string_ostream OS(Clobbers[I]);
- IP->printRegName(OS, ClobberRegs[I]);
- }
-
- // Merge the various outputs and inputs. Output are expected first.
- if (NumOutputs || NumInputs) {
- unsigned NumExprs = NumOutputs + NumInputs;
- OpDecls.resize(NumExprs);
- Constraints.resize(NumExprs);
- for (unsigned i = 0; i < NumOutputs; ++i) {
- OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
- Constraints[i] = OutputConstraints[i];
- }
- for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
- OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
- Constraints[j] = InputConstraints[i];
- }
- }
-
- // Build the IR assembly string.
- std::string AsmStringIR;
- raw_string_ostream OS(AsmStringIR);
- StringRef ASMString =
- SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer();
- const char *AsmStart = ASMString.begin();
- const char *AsmEnd = ASMString.end();
- array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
- for (const AsmRewrite &AR : AsmStrRewrites) {
- AsmRewriteKind Kind = AR.Kind;
-
- const char *Loc = AR.Loc.getPointer();
- assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
-
- // Emit everything up to the immediate/expression.
- if (unsigned Len = Loc - AsmStart)
- OS << StringRef(AsmStart, Len);
-
- // Skip the original expression.
- if (Kind == AOK_Skip) {
- AsmStart = Loc + AR.Len;
- continue;
- }
-
- unsigned AdditionalSkip = 0;
- // Rewrite expressions in $N notation.
- switch (Kind) {
- default:
- break;
- case AOK_IntelExpr:
- assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
- if (AR.IntelExp.NeedBracs)
- OS << "[";
- if (AR.IntelExp.hasBaseReg())
- OS << AR.IntelExp.BaseReg;
- if (AR.IntelExp.hasIndexReg())
- OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
- << AR.IntelExp.IndexReg;
- if (AR.IntelExp.Scale > 1)
- OS << " * $$" << AR.IntelExp.Scale;
- if (AR.IntelExp.Imm || !AR.IntelExp.hasRegs())
- OS << (AR.IntelExp.hasRegs() ? " + $$" : "$$") << AR.IntelExp.Imm;
- if (AR.IntelExp.NeedBracs)
- OS << "]";
- break;
- case AOK_Label:
- OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
- break;
- case AOK_Input:
- OS << '$' << InputIdx++;
- break;
- case AOK_Output:
- OS << '$' << OutputIdx++;
- break;
- case AOK_SizeDirective:
- switch (AR.Val) {
- default: break;
- case 8: OS << "byte ptr "; break;
- case 16: OS << "word ptr "; break;
- case 32: OS << "dword ptr "; break;
- case 64: OS << "qword ptr "; break;
- case 80: OS << "xword ptr "; break;
- case 128: OS << "xmmword ptr "; break;
- case 256: OS << "ymmword ptr "; break;
- }
- break;
- case AOK_Emit:
- OS << ".byte";
- break;
- case AOK_Align: {
- // MS alignment directives are measured in bytes. If the native assembler
- // measures alignment in bytes, we can pass it straight through.
- OS << ".align";
- if (getContext().getAsmInfo()->getAlignmentIsInBytes())
- break;
-
- // Alignment is in log2 form, so print that instead and skip the original
- // immediate.
- unsigned Val = AR.Val;
- OS << ' ' << Val;
- assert(Val < 10 && "Expected alignment less then 2^10.");
- AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
- break;
- }
- case AOK_EVEN:
- OS << ".even";
- break;
- case AOK_EndOfStatement:
- OS << "\n\t";
- break;
- }
-
- // Skip the original expression.
- AsmStart = Loc + AR.Len + AdditionalSkip;
- }
-
- // Emit the remainder of the asm string.
- if (AsmStart != AsmEnd)
- OS << StringRef(AsmStart, AsmEnd - AsmStart);
-
- AsmString = OS.str();
- return false;
-}
-
-namespace llvm {
-namespace MCParserUtils {
-
-/// Returns whether the given symbol is used anywhere in the given expression,
-/// or subexpressions.
-static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *Value) {
- switch (Value->getKind()) {
- case MCExpr::Binary: {
- const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Value);
- return isSymbolUsedInExpression(Sym, BE->getLHS()) ||
- isSymbolUsedInExpression(Sym, BE->getRHS());
- }
- case MCExpr::Target:
- case MCExpr::Constant:
- return false;
- case MCExpr::SymbolRef: {
- const MCSymbol &S =
- static_cast<const MCSymbolRefExpr *>(Value)->getSymbol();
- if (S.isVariable())
- return isSymbolUsedInExpression(Sym, S.getVariableValue());
- return &S == Sym;
- }
- case MCExpr::Unary:
- return isSymbolUsedInExpression(
- Sym, static_cast<const MCUnaryExpr *>(Value)->getSubExpr());
- }
-
- llvm_unreachable("Unknown expr kind!");
-}
-
-bool parseAssignmentExpression(StringRef Name, bool allow_redef,
- MCAsmParser &Parser, MCSymbol *&Sym,
- const MCExpr *&Value) {
-
- // FIXME: Use better location, we should use proper tokens.
- SMLoc EqualLoc = Parser.getTok().getLoc();
- if (Parser.parseExpression(Value))
- return Parser.TokError("missing expression");
-
- // Note: we don't count b as used in "a = b". This is to allow
- // a = b
- // b = c
-
- if (Parser.parseToken(AsmToken::EndOfStatement))
- return true;
-
- // Validate that the LHS is allowed to be a variable (either it has not been
- // used as a symbol, or it is an absolute symbol).
- Sym = Parser.getContext().lookupSymbol(Name);
- if (Sym) {
- // Diagnose assignment to a label.
- //
- // FIXME: Diagnostics. Note the location of the definition as a label.
- // FIXME: Diagnose assignment to protected identifier (e.g., register name).
- if (isSymbolUsedInExpression(Sym, Value))
- return Parser.Error(EqualLoc, "Recursive use of '" + Name + "'");
- else if (Sym->isUndefined(/*SetUsed*/ false) && !Sym->isUsed() &&
- !Sym->isVariable())
- ; // Allow redefinitions of undefined symbols only used in directives.
- else if (Sym->isVariable() && !Sym->isUsed() && allow_redef)
- ; // Allow redefinitions of variables that haven't yet been used.
- else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef))
- return Parser.Error(EqualLoc, "redefinition of '" + Name + "'");
- else if (!Sym->isVariable())
- return Parser.Error(EqualLoc, "invalid assignment to '" + Name + "'");
- else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
- return Parser.Error(EqualLoc,
- "invalid reassignment of non-absolute variable '" +
- Name + "'");
- } else if (Name == ".") {
- Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc);
- return false;
- } else
- Sym = Parser.getContext().getOrCreateSymbol(Name);
-
- Sym->setRedefinable(allow_redef);
-
- return false;
-}
-
-} // end namespace MCParserUtils
-} // end namespace llvm
-
-/// Create an MCAsmParser instance.
-MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C,
- MCStreamer &Out, const MCAsmInfo &MAI,
- unsigned CB) {
- return new AsmParser(SM, C, Out, MAI, CB);
-}
diff --git a/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp
deleted file mode 100644
index 1217ea99e465..000000000000
--- a/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp
+++ /dev/null
@@ -1,865 +0,0 @@
-//===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/COFF.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDirectives.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCParser/MCAsmLexer.h"
-#include "llvm/MC/MCParser/MCAsmParserExtension.h"
-#include "llvm/MC/MCParser/MCTargetAsmParser.h"
-#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCSectionCOFF.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/SectionKind.h"
-#include "llvm/Support/SMLoc.h"
-#include <cassert>
-#include <cstdint>
-#include <limits>
-#include <utility>
-
-using namespace llvm;
-
-namespace {
-
-class COFFAsmParser : public MCAsmParserExtension {
- template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
- void addDirectiveHandler(StringRef Directive) {
- MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
- this, HandleDirective<COFFAsmParser, HandlerMethod>);
- getParser().addDirectiveHandler(Directive, Handler);
- }
-
- bool ParseSectionSwitch(StringRef Section,
- unsigned Characteristics,
- SectionKind Kind);
-
- bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
- SectionKind Kind, StringRef COMDATSymName,
- COFF::COMDATType Type);
-
- bool ParseSectionName(StringRef &SectionName);
- bool ParseSectionFlags(StringRef SectionName, StringRef FlagsString,
- unsigned *Flags);
-
- void Initialize(MCAsmParser &Parser) override {
- // Call the base implementation.
- MCAsmParserExtension::Initialize(Parser);
-
- addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
- addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
- addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymIdx>(".symidx");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva");
-
- // Win64 EH directives.
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
- ".seh_proc");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
- ".seh_endproc");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
- ".seh_startchained");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
- ".seh_endchained");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
- ".seh_handler");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
- ".seh_handlerdata");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
- ".seh_pushreg");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
- ".seh_setframe");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
- ".seh_stackalloc");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
- ".seh_savereg");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
- ".seh_savexmm");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
- ".seh_pushframe");
- addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
- ".seh_endprologue");
- addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
- }
-
- bool ParseSectionDirectiveText(StringRef, SMLoc) {
- return ParseSectionSwitch(".text",
- COFF::IMAGE_SCN_CNT_CODE
- | COFF::IMAGE_SCN_MEM_EXECUTE
- | COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getText());
- }
-
- bool ParseSectionDirectiveData(StringRef, SMLoc) {
- return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ |
- COFF::IMAGE_SCN_MEM_WRITE,
- SectionKind::getData());
- }
-
- bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
- return ParseSectionSwitch(".bss",
- COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
- | COFF::IMAGE_SCN_MEM_READ
- | COFF::IMAGE_SCN_MEM_WRITE,
- SectionKind::getBSS());
- }
-
- bool ParseDirectiveSection(StringRef, SMLoc);
- bool ParseDirectiveDef(StringRef, SMLoc);
- bool ParseDirectiveScl(StringRef, SMLoc);
- bool ParseDirectiveType(StringRef, SMLoc);
- bool ParseDirectiveEndef(StringRef, SMLoc);
- bool ParseDirectiveSecRel32(StringRef, SMLoc);
- bool ParseDirectiveSecIdx(StringRef, SMLoc);
- bool ParseDirectiveSafeSEH(StringRef, SMLoc);
- bool ParseDirectiveSymIdx(StringRef, SMLoc);
- bool parseCOMDATType(COFF::COMDATType &Type);
- bool ParseDirectiveLinkOnce(StringRef, SMLoc);
- bool ParseDirectiveRVA(StringRef, SMLoc);
-
- // Win64 EH directives.
- bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
- bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
- bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
- bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
- bool ParseSEHDirectiveHandler(StringRef, SMLoc);
- bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
- bool ParseSEHDirectivePushReg(StringRef, SMLoc);
- bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
- bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
- bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
- bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
- bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
- bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
-
- bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
- bool ParseSEHRegisterNumber(unsigned &RegNo);
- bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
-
-public:
- COFFAsmParser() = default;
-};
-
-} // end annonomous namespace.
-
-static SectionKind computeSectionKind(unsigned Flags) {
- if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
- return SectionKind::getText();
- if (Flags & COFF::IMAGE_SCN_MEM_READ &&
- (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
- return SectionKind::getReadOnly();
- return SectionKind::getData();
-}
-
-bool COFFAsmParser::ParseSectionFlags(StringRef SectionName,
- StringRef FlagsString, unsigned *Flags) {
- enum {
- None = 0,
- Alloc = 1 << 0,
- Code = 1 << 1,
- Load = 1 << 2,
- InitData = 1 << 3,
- Shared = 1 << 4,
- NoLoad = 1 << 5,
- NoRead = 1 << 6,
- NoWrite = 1 << 7,
- Discardable = 1 << 8,
- };
-
- bool ReadOnlyRemoved = false;
- unsigned SecFlags = None;
-
- for (char FlagChar : FlagsString) {
- switch (FlagChar) {
- case 'a':
- // Ignored.
- break;
-
- case 'b': // bss section
- SecFlags |= Alloc;
- if (SecFlags & InitData)
- return TokError("conflicting section flags 'b' and 'd'.");
- SecFlags &= ~Load;
- break;
-
- case 'd': // data section
- SecFlags |= InitData;
- if (SecFlags & Alloc)
- return TokError("conflicting section flags 'b' and 'd'.");
- SecFlags &= ~NoWrite;
- if ((SecFlags & NoLoad) == 0)
- SecFlags |= Load;
- break;
-
- case 'n': // section is not loaded
- SecFlags |= NoLoad;
- SecFlags &= ~Load;
- break;
-
- case 'D': // discardable
- SecFlags |= Discardable;
- break;
-
- case 'r': // read-only
- ReadOnlyRemoved = false;
- SecFlags |= NoWrite;
- if ((SecFlags & Code) == 0)
- SecFlags |= InitData;
- if ((SecFlags & NoLoad) == 0)
- SecFlags |= Load;
- break;
-
- case 's': // shared section
- SecFlags |= Shared | InitData;
- SecFlags &= ~NoWrite;
- if ((SecFlags & NoLoad) == 0)
- SecFlags |= Load;
- break;
-
- case 'w': // writable
- SecFlags &= ~NoWrite;
- ReadOnlyRemoved = true;
- break;
-
- case 'x': // executable section
- SecFlags |= Code;
- if ((SecFlags & NoLoad) == 0)
- SecFlags |= Load;
- if (!ReadOnlyRemoved)
- SecFlags |= NoWrite;
- break;
-
- case 'y': // not readable
- SecFlags |= NoRead | NoWrite;
- break;
-
- default:
- return TokError("unknown flag");
- }
- }
-
- *Flags = 0;
-
- if (SecFlags == None)
- SecFlags = InitData;
-
- if (SecFlags & Code)
- *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
- if (SecFlags & InitData)
- *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
- if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
- *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
- if (SecFlags & NoLoad)
- *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
- if ((SecFlags & Discardable) ||
- MCSectionCOFF::isImplicitlyDiscardable(SectionName))
- *Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE;
- if ((SecFlags & NoRead) == 0)
- *Flags |= COFF::IMAGE_SCN_MEM_READ;
- if ((SecFlags & NoWrite) == 0)
- *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
- if (SecFlags & Shared)
- *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
-
- return false;
-}
-
-/// ParseDirectiveSymbolAttribute
-/// ::= { ".weak", ... } [ identifier ( , identifier )* ]
-bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
- MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
- .Case(".weak", MCSA_Weak)
- .Default(MCSA_Invalid);
- assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- while (true) {
- StringRef Name;
-
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- getStreamer().EmitSymbolAttribute(Sym, Attr);
-
- if (getLexer().is(AsmToken::EndOfStatement))
- break;
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
- }
- }
-
- Lex();
- return false;
-}
-
-bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
- unsigned Characteristics,
- SectionKind Kind) {
- return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
-}
-
-bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
- unsigned Characteristics,
- SectionKind Kind,
- StringRef COMDATSymName,
- COFF::COMDATType Type) {
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in section switching directive");
- Lex();
-
- getStreamer().SwitchSection(getContext().getCOFFSection(
- Section, Characteristics, Kind, COMDATSymName, Type));
-
- return false;
-}
-
-bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
- if (!getLexer().is(AsmToken::Identifier))
- return true;
-
- SectionName = getTok().getIdentifier();
- Lex();
- return false;
-}
-
-// .section name [, "flags"] [, identifier [ identifier ], identifier]
-//
-// Supported flags:
-// a: Ignored.
-// b: BSS section (uninitialized data)
-// d: data section (initialized data)
-// n: "noload" section (removed by linker)
-// D: Discardable section
-// r: Readable section
-// s: Shared section
-// w: Writable section
-// x: Executable section
-// y: Not-readable section (clears 'r')
-//
-// Subsections are not supported.
-bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
- StringRef SectionName;
-
- if (ParseSectionName(SectionName))
- return TokError("expected identifier in directive");
-
- unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ |
- COFF::IMAGE_SCN_MEM_WRITE;
-
- if (getLexer().is(AsmToken::Comma)) {
- Lex();
-
- if (getLexer().isNot(AsmToken::String))
- return TokError("expected string in directive");
-
- StringRef FlagsStr = getTok().getStringContents();
- Lex();
-
- if (ParseSectionFlags(SectionName, FlagsStr, &Flags))
- return true;
- }
-
- COFF::COMDATType Type = (COFF::COMDATType)0;
- StringRef COMDATSymName;
- if (getLexer().is(AsmToken::Comma)) {
- Type = COFF::IMAGE_COMDAT_SELECT_ANY;
- Lex();
-
- Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
-
- if (!getLexer().is(AsmToken::Identifier))
- return TokError("expected comdat type such as 'discard' or 'largest' "
- "after protection bits");
-
- if (parseCOMDATType(Type))
- return true;
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("expected comma in directive");
- Lex();
-
- if (getParser().parseIdentifier(COMDATSymName))
- return TokError("expected identifier in directive");
- }
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- SectionKind Kind = computeSectionKind(Flags);
- if (Kind.isText()) {
- const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
- if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
- Flags |= COFF::IMAGE_SCN_MEM_16BIT;
- }
- ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
- StringRef SymbolName;
-
- if (getParser().parseIdentifier(SymbolName))
- return TokError("expected identifier in directive");
-
- MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
-
- getStreamer().BeginCOFFSymbolDef(Sym);
-
- Lex();
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
- int64_t SymbolStorageClass;
- if (getParser().parseAbsoluteExpression(SymbolStorageClass))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- Lex();
- getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
- int64_t Type;
- if (getParser().parseAbsoluteExpression(Type))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- Lex();
- getStreamer().EmitCOFFSymbolType(Type);
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
- Lex();
- getStreamer().EndCOFFSymbolDef();
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
- StringRef SymbolID;
- if (getParser().parseIdentifier(SymbolID))
- return TokError("expected identifier in directive");
-
- int64_t Offset = 0;
- SMLoc OffsetLoc;
- if (getLexer().is(AsmToken::Plus)) {
- OffsetLoc = getLexer().getLoc();
- if (getParser().parseAbsoluteExpression(Offset))
- return true;
- }
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- if (Offset < 0 || Offset > std::numeric_limits<uint32_t>::max())
- return Error(
- OffsetLoc,
- "invalid '.secrel32' directive offset, can't be less "
- "than zero or greater than std::numeric_limits<uint32_t>::max()");
-
- MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
-
- Lex();
- getStreamer().EmitCOFFSecRel32(Symbol, Offset);
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveRVA(StringRef, SMLoc) {
- auto parseOp = [&]() -> bool {
- StringRef SymbolID;
- if (getParser().parseIdentifier(SymbolID))
- return TokError("expected identifier in directive");
-
- int64_t Offset = 0;
- SMLoc OffsetLoc;
- if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) {
- OffsetLoc = getLexer().getLoc();
- if (getParser().parseAbsoluteExpression(Offset))
- return true;
- }
-
- if (Offset < std::numeric_limits<int32_t>::min() ||
- Offset > std::numeric_limits<int32_t>::max())
- return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less "
- "than -2147483648 or greater than "
- "2147483647");
-
- MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
-
- getStreamer().EmitCOFFImgRel32(Symbol, Offset);
- return false;
- };
-
- if (getParser().parseMany(parseOp))
- return addErrorSuffix(" in directive");
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
- StringRef SymbolID;
- if (getParser().parseIdentifier(SymbolID))
- return TokError("expected identifier in directive");
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
-
- Lex();
- getStreamer().EmitCOFFSafeSEH(Symbol);
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
- StringRef SymbolID;
- if (getParser().parseIdentifier(SymbolID))
- return TokError("expected identifier in directive");
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
-
- Lex();
- getStreamer().EmitCOFFSectionIndex(Symbol);
- return false;
-}
-
-bool COFFAsmParser::ParseDirectiveSymIdx(StringRef, SMLoc) {
- StringRef SymbolID;
- if (getParser().parseIdentifier(SymbolID))
- return TokError("expected identifier in directive");
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
-
- Lex();
- getStreamer().EmitCOFFSymbolIndex(Symbol);
- return false;
-}
-
-/// ::= [ identifier ]
-bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
- StringRef TypeId = getTok().getIdentifier();
-
- Type = StringSwitch<COFF::COMDATType>(TypeId)
- .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
- .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
- .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
- .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
- .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
- .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
- .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
- .Default((COFF::COMDATType)0);
-
- if (Type == 0)
- return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
-
- Lex();
-
- return false;
-}
-
-/// ParseDirectiveLinkOnce
-/// ::= .linkonce [ identifier ]
-bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
- COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
- if (getLexer().is(AsmToken::Identifier))
- if (parseCOMDATType(Type))
- return true;
-
- const MCSectionCOFF *Current =
- static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly());
-
- if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
- return Error(Loc, "cannot make section associative with .linkonce");
-
- if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
- return Error(Loc, Twine("section '") + Current->getSectionName() +
- "' is already linkonce");
-
- Current->setSelection(Type);
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc Loc) {
- StringRef SymbolID;
- if (getParser().parseIdentifier(SymbolID))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
-
- Lex();
- getStreamer().EmitWinCFIStartProc(Symbol, Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc Loc) {
- Lex();
- getStreamer().EmitWinCFIEndProc(Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc Loc) {
- Lex();
- getStreamer().EmitWinCFIStartChained(Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc Loc) {
- Lex();
- getStreamer().EmitWinCFIEndChained(Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc Loc) {
- StringRef SymbolID;
- if (getParser().parseIdentifier(SymbolID))
- return true;
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("you must specify one or both of @unwind or @except");
- Lex();
- bool unwind = false, except = false;
- if (ParseAtUnwindOrAtExcept(unwind, except))
- return true;
- if (getLexer().is(AsmToken::Comma)) {
- Lex();
- if (ParseAtUnwindOrAtExcept(unwind, except))
- return true;
- }
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
-
- Lex();
- getStreamer().EmitWinEHHandler(handler, unwind, except, Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) {
- Lex();
- getStreamer().EmitWinEHHandlerData();
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc Loc) {
- unsigned Reg = 0;
- if (ParseSEHRegisterNumber(Reg))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- Lex();
- getStreamer().EmitWinCFIPushReg(Reg, Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc Loc) {
- unsigned Reg = 0;
- int64_t Off;
- if (ParseSEHRegisterNumber(Reg))
- return true;
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("you must specify a stack pointer offset");
-
- Lex();
- if (getParser().parseAbsoluteExpression(Off))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- Lex();
- getStreamer().EmitWinCFISetFrame(Reg, Off, Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) {
- int64_t Size;
- if (getParser().parseAbsoluteExpression(Size))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- Lex();
- getStreamer().EmitWinCFIAllocStack(Size, Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc Loc) {
- unsigned Reg = 0;
- int64_t Off;
- if (ParseSEHRegisterNumber(Reg))
- return true;
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("you must specify an offset on the stack");
-
- Lex();
- if (getParser().parseAbsoluteExpression(Off))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- Lex();
- // FIXME: Err on %xmm* registers
- getStreamer().EmitWinCFISaveReg(Reg, Off, Loc);
- return false;
-}
-
-// FIXME: This method is inherently x86-specific. It should really be in the
-// x86 backend.
-bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc Loc) {
- unsigned Reg = 0;
- int64_t Off;
- if (ParseSEHRegisterNumber(Reg))
- return true;
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("you must specify an offset on the stack");
-
- Lex();
- if (getParser().parseAbsoluteExpression(Off))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- Lex();
- // FIXME: Err on non-%xmm* registers
- getStreamer().EmitWinCFISaveXMM(Reg, Off, Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc Loc) {
- bool Code = false;
- StringRef CodeID;
- if (getLexer().is(AsmToken::At)) {
- SMLoc startLoc = getLexer().getLoc();
- Lex();
- if (!getParser().parseIdentifier(CodeID)) {
- if (CodeID != "code")
- return Error(startLoc, "expected @code");
- Code = true;
- }
- }
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- Lex();
- getStreamer().EmitWinCFIPushFrame(Code, Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) {
- Lex();
- getStreamer().EmitWinCFIEndProlog(Loc);
- return false;
-}
-
-bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
- StringRef identifier;
- if (getLexer().isNot(AsmToken::At))
- return TokError("a handler attribute must begin with '@'");
- SMLoc startLoc = getLexer().getLoc();
- Lex();
- if (getParser().parseIdentifier(identifier))
- return Error(startLoc, "expected @unwind or @except");
- if (identifier == "unwind")
- unwind = true;
- else if (identifier == "except")
- except = true;
- else
- return Error(startLoc, "expected @unwind or @except");
- return false;
-}
-
-bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
- SMLoc startLoc = getLexer().getLoc();
- if (getLexer().is(AsmToken::Percent)) {
- const MCRegisterInfo *MRI = getContext().getRegisterInfo();
- SMLoc endLoc;
- unsigned LLVMRegNo;
- if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
- return true;
-
-#if 0
- // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
- // violation so this validation code is disabled.
-
- // Check that this is a non-volatile register.
- const unsigned *NVRegs = TAI.getCalleeSavedRegs();
- unsigned i;
- for (i = 0; NVRegs[i] != 0; ++i)
- if (NVRegs[i] == LLVMRegNo)
- break;
- if (NVRegs[i] == 0)
- return Error(startLoc, "expected non-volatile register");
-#endif
-
- int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
- if (SEHRegNo < 0)
- return Error(startLoc,"register can't be represented in SEH unwind info");
- RegNo = SEHRegNo;
- }
- else {
- int64_t n;
- if (getParser().parseAbsoluteExpression(n))
- return true;
- if (n > 15)
- return Error(startLoc, "register number is too high");
- RegNo = n;
- }
-
- return false;
-}
-
-namespace llvm {
-
-MCAsmParserExtension *createCOFFAsmParser() {
- return new COFFAsmParser;
-}
-
-} // end namespace llvm
diff --git a/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp
deleted file mode 100644
index 1160934dc62c..000000000000
--- a/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp
+++ /dev/null
@@ -1,1208 +0,0 @@
-//===- DarwinAsmParser.cpp - Darwin (Mach-O) Assembly Parser --------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDirectives.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCParser/MCAsmLexer.h"
-#include "llvm/MC/MCParser/MCAsmParser.h"
-#include "llvm/MC/MCParser/MCAsmParserExtension.h"
-#include "llvm/MC/MCSectionMachO.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/SectionKind.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/SMLoc.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cstddef>
-#include <cstdint>
-#include <string>
-#include <system_error>
-#include <utility>
-
-using namespace llvm;
-
-namespace {
-
-/// Implementation of directive handling which is shared across all
-/// Darwin targets.
-class DarwinAsmParser : public MCAsmParserExtension {
- template<bool (DarwinAsmParser::*HandlerMethod)(StringRef, SMLoc)>
- void addDirectiveHandler(StringRef Directive) {
- MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
- this, HandleDirective<DarwinAsmParser, HandlerMethod>);
- getParser().addDirectiveHandler(Directive, Handler);
- }
-
- bool parseSectionSwitch(StringRef Segment, StringRef Section,
- unsigned TAA = 0, unsigned ImplicitAlign = 0,
- unsigned StubSize = 0);
-
- SMLoc LastVersionDirective;
-
-public:
- DarwinAsmParser() = default;
-
- void Initialize(MCAsmParser &Parser) override {
- // Call the base implementation.
- this->MCAsmParserExtension::Initialize(Parser);
-
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveAltEntry>(".alt_entry");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveDesc>(".desc");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveIndirectSymbol>(
- ".indirect_symbol");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveLsym>(".lsym");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveSubsectionsViaSymbols>(
- ".subsections_via_symbols");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(".dump");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(".load");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveSection>(".section");
- addDirectiveHandler<&DarwinAsmParser::parseDirectivePushSection>(
- ".pushsection");
- addDirectiveHandler<&DarwinAsmParser::parseDirectivePopSection>(
- ".popsection");
- addDirectiveHandler<&DarwinAsmParser::parseDirectivePrevious>(".previous");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogUnique>(
- ".secure_log_unique");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogReset>(
- ".secure_log_reset");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveTBSS>(".tbss");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveZerofill>(".zerofill");
-
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegion>(
- ".data_region");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegionEnd>(
- ".end_data_region");
-
- // Special section directives.
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveBss>(".bss");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConst>(".const");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstData>(
- ".const_data");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstructor>(
- ".constructor");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveCString>(
- ".cstring");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveData>(".data");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDestructor>(
- ".destructor");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDyld>(".dyld");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit0>(
- ".fvmlib_init0");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit1>(
- ".fvmlib_init1");
- addDirectiveHandler<
- &DarwinAsmParser::parseSectionDirectiveLazySymbolPointers>(
- ".lazy_symbol_pointer");
- addDirectiveHandler<&DarwinAsmParser::parseDirectiveLinkerOption>(
- ".linker_option");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral16>(
- ".literal16");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral4>(
- ".literal4");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral8>(
- ".literal8");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModInitFunc>(
- ".mod_init_func");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModTermFunc>(
- ".mod_term_func");
- addDirectiveHandler<
- &DarwinAsmParser::parseSectionDirectiveNonLazySymbolPointers>(
- ".non_lazy_symbol_pointer");
- addDirectiveHandler<
- &DarwinAsmParser::parseSectionDirectiveThreadLocalVariablePointers>(
- ".thread_local_variable_pointer");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatClsMeth>(
- ".objc_cat_cls_meth");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatInstMeth>(
- ".objc_cat_inst_meth");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCategory>(
- ".objc_category");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClass>(
- ".objc_class");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassNames>(
- ".objc_class_names");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassVars>(
- ".objc_class_vars");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsMeth>(
- ".objc_cls_meth");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsRefs>(
- ".objc_cls_refs");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCInstMeth>(
- ".objc_inst_meth");
- addDirectiveHandler<
- &DarwinAsmParser::parseSectionDirectiveObjCInstanceVars>(
- ".objc_instance_vars");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMessageRefs>(
- ".objc_message_refs");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMetaClass>(
- ".objc_meta_class");
- addDirectiveHandler<
- &DarwinAsmParser::parseSectionDirectiveObjCMethVarNames>(
- ".objc_meth_var_names");
- addDirectiveHandler<
- &DarwinAsmParser::parseSectionDirectiveObjCMethVarTypes>(
- ".objc_meth_var_types");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCModuleInfo>(
- ".objc_module_info");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCProtocol>(
- ".objc_protocol");
- addDirectiveHandler<
- &DarwinAsmParser::parseSectionDirectiveObjCSelectorStrs>(
- ".objc_selector_strs");
- addDirectiveHandler<
- &DarwinAsmParser::parseSectionDirectiveObjCStringObject>(
- ".objc_string_object");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCSymbols>(
- ".objc_symbols");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectivePICSymbolStub>(
- ".picsymbol_stub");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticConst>(
- ".static_const");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticData>(
- ".static_data");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveSymbolStub>(
- ".symbol_stub");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTData>(".tdata");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveText>(".text");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveThreadInitFunc>(
- ".thread_init_func");
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTLV>(".tlv");
-
- addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveIdent>(".ident");
- addDirectiveHandler<&DarwinAsmParser::parseWatchOSVersionMin>(
- ".watchos_version_min");
- addDirectiveHandler<&DarwinAsmParser::parseTvOSVersionMin>(
- ".tvos_version_min");
- addDirectiveHandler<&DarwinAsmParser::parseIOSVersionMin>(
- ".ios_version_min");
- addDirectiveHandler<&DarwinAsmParser::parseMacOSXVersionMin>(
- ".macosx_version_min");
- addDirectiveHandler<&DarwinAsmParser::parseBuildVersion>(".build_version");
-
- LastVersionDirective = SMLoc();
- }
-
- bool parseDirectiveAltEntry(StringRef, SMLoc);
- bool parseDirectiveDesc(StringRef, SMLoc);
- bool parseDirectiveIndirectSymbol(StringRef, SMLoc);
- bool parseDirectiveDumpOrLoad(StringRef, SMLoc);
- bool parseDirectiveLsym(StringRef, SMLoc);
- bool parseDirectiveLinkerOption(StringRef, SMLoc);
- bool parseDirectiveSection(StringRef, SMLoc);
- bool parseDirectivePushSection(StringRef, SMLoc);
- bool parseDirectivePopSection(StringRef, SMLoc);
- bool parseDirectivePrevious(StringRef, SMLoc);
- bool parseDirectiveSecureLogReset(StringRef, SMLoc);
- bool parseDirectiveSecureLogUnique(StringRef, SMLoc);
- bool parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc);
- bool parseDirectiveTBSS(StringRef, SMLoc);
- bool parseDirectiveZerofill(StringRef, SMLoc);
- bool parseDirectiveDataRegion(StringRef, SMLoc);
- bool parseDirectiveDataRegionEnd(StringRef, SMLoc);
-
- // Named Section Directive
- bool parseSectionDirectiveBss(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__bss");
- }
-
- bool parseSectionDirectiveConst(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT", "__const");
- }
-
- bool parseSectionDirectiveStaticConst(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT", "__static_const");
- }
-
- bool parseSectionDirectiveCString(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT","__cstring",
- MachO::S_CSTRING_LITERALS);
- }
-
- bool parseSectionDirectiveLiteral4(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT", "__literal4",
- MachO::S_4BYTE_LITERALS, 4);
- }
-
- bool parseSectionDirectiveLiteral8(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT", "__literal8",
- MachO::S_8BYTE_LITERALS, 8);
- }
-
- bool parseSectionDirectiveLiteral16(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT","__literal16",
- MachO::S_16BYTE_LITERALS, 16);
- }
-
- bool parseSectionDirectiveConstructor(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT","__constructor");
- }
-
- bool parseSectionDirectiveDestructor(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT","__destructor");
- }
-
- bool parseSectionDirectiveFVMLibInit0(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT","__fvmlib_init0");
- }
-
- bool parseSectionDirectiveFVMLibInit1(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT","__fvmlib_init1");
- }
-
- bool parseSectionDirectiveSymbolStub(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT","__symbol_stub",
- MachO::S_SYMBOL_STUBS |
- MachO::S_ATTR_PURE_INSTRUCTIONS,
- // FIXME: Different on PPC and ARM.
- 0, 16);
- }
-
- bool parseSectionDirectivePICSymbolStub(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT","__picsymbol_stub",
- MachO::S_SYMBOL_STUBS |
- MachO::S_ATTR_PURE_INSTRUCTIONS, 0, 26);
- }
-
- bool parseSectionDirectiveData(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__data");
- }
-
- bool parseSectionDirectiveStaticData(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__static_data");
- }
-
- bool parseSectionDirectiveNonLazySymbolPointers(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__nl_symbol_ptr",
- MachO::S_NON_LAZY_SYMBOL_POINTERS, 4);
- }
-
- bool parseSectionDirectiveLazySymbolPointers(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__la_symbol_ptr",
- MachO::S_LAZY_SYMBOL_POINTERS, 4);
- }
-
- bool parseSectionDirectiveThreadLocalVariablePointers(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__thread_ptr",
- MachO::S_THREAD_LOCAL_VARIABLE_POINTERS, 4);
- }
-
- bool parseSectionDirectiveDyld(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__dyld");
- }
-
- bool parseSectionDirectiveModInitFunc(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__mod_init_func",
- MachO::S_MOD_INIT_FUNC_POINTERS, 4);
- }
-
- bool parseSectionDirectiveModTermFunc(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__mod_term_func",
- MachO::S_MOD_TERM_FUNC_POINTERS, 4);
- }
-
- bool parseSectionDirectiveConstData(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__const");
- }
-
- bool parseSectionDirectiveObjCClass(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__class",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCMetaClass(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__meta_class",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCCatClsMeth(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__cat_cls_meth",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCCatInstMeth(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__cat_inst_meth",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCProtocol(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__protocol",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCStringObject(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__string_object",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCClsMeth(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__cls_meth",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCInstMeth(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__inst_meth",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCClsRefs(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__cls_refs",
- MachO::S_ATTR_NO_DEAD_STRIP |
- MachO::S_LITERAL_POINTERS, 4);
- }
-
- bool parseSectionDirectiveObjCMessageRefs(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__message_refs",
- MachO::S_ATTR_NO_DEAD_STRIP |
- MachO::S_LITERAL_POINTERS, 4);
- }
-
- bool parseSectionDirectiveObjCSymbols(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__symbols",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCCategory(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__category",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCClassVars(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__class_vars",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCInstanceVars(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__instance_vars",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCModuleInfo(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__module_info",
- MachO::S_ATTR_NO_DEAD_STRIP);
- }
-
- bool parseSectionDirectiveObjCClassNames(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT", "__cstring",
- MachO::S_CSTRING_LITERALS);
- }
-
- bool parseSectionDirectiveObjCMethVarTypes(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT", "__cstring",
- MachO::S_CSTRING_LITERALS);
- }
-
- bool parseSectionDirectiveObjCMethVarNames(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT", "__cstring",
- MachO::S_CSTRING_LITERALS);
- }
-
- bool parseSectionDirectiveObjCSelectorStrs(StringRef, SMLoc) {
- return parseSectionSwitch("__OBJC", "__selector_strs",
- MachO::S_CSTRING_LITERALS);
- }
-
- bool parseSectionDirectiveTData(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__thread_data",
- MachO::S_THREAD_LOCAL_REGULAR);
- }
-
- bool parseSectionDirectiveText(StringRef, SMLoc) {
- return parseSectionSwitch("__TEXT", "__text",
- MachO::S_ATTR_PURE_INSTRUCTIONS);
- }
-
- bool parseSectionDirectiveTLV(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__thread_vars",
- MachO::S_THREAD_LOCAL_VARIABLES);
- }
-
- bool parseSectionDirectiveIdent(StringRef, SMLoc) {
- // Darwin silently ignores the .ident directive.
- getParser().eatToEndOfStatement();
- return false;
- }
-
- bool parseSectionDirectiveThreadInitFunc(StringRef, SMLoc) {
- return parseSectionSwitch("__DATA", "__thread_init",
- MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS);
- }
-
- bool parseWatchOSVersionMin(StringRef Directive, SMLoc Loc) {
- return parseVersionMin(Directive, Loc, MCVM_WatchOSVersionMin);
- }
- bool parseTvOSVersionMin(StringRef Directive, SMLoc Loc) {
- return parseVersionMin(Directive, Loc, MCVM_TvOSVersionMin);
- }
- bool parseIOSVersionMin(StringRef Directive, SMLoc Loc) {
- return parseVersionMin(Directive, Loc, MCVM_IOSVersionMin);
- }
- bool parseMacOSXVersionMin(StringRef Directive, SMLoc Loc) {
- return parseVersionMin(Directive, Loc, MCVM_OSXVersionMin);
- }
-
- bool parseBuildVersion(StringRef Directive, SMLoc Loc);
- bool parseVersionMin(StringRef Directive, SMLoc Loc, MCVersionMinType Type);
- bool parseMajorMinorVersionComponent(unsigned *Major, unsigned *Minor,
- const char *VersionName);
- bool parseOptionalTrailingVersionComponent(unsigned *Component,
- const char *ComponentName);
- bool parseVersion(unsigned *Major, unsigned *Minor, unsigned *Update);
- bool parseSDKVersion(VersionTuple &SDKVersion);
- void checkVersion(StringRef Directive, StringRef Arg, SMLoc Loc,
- Triple::OSType ExpectedOS);
-};
-
-} // end anonymous namespace
-
-bool DarwinAsmParser::parseSectionSwitch(StringRef Segment, StringRef Section,
- unsigned TAA, unsigned Align,
- unsigned StubSize) {
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in section switching directive");
- Lex();
-
- // FIXME: Arch specific.
- bool isText = TAA & MachO::S_ATTR_PURE_INSTRUCTIONS;
- getStreamer().SwitchSection(getContext().getMachOSection(
- Segment, Section, TAA, StubSize,
- isText ? SectionKind::getText() : SectionKind::getData()));
-
- // Set the implicit alignment, if any.
- //
- // FIXME: This isn't really what 'as' does; I think it just uses the implicit
- // alignment on the section (e.g., if one manually inserts bytes into the
- // section, then just issuing the section switch directive will not realign
- // the section. However, this is arguably more reasonable behavior, and there
- // is no good reason for someone to intentionally emit incorrectly sized
- // values into the implicitly aligned sections.
- if (Align)
- getStreamer().EmitValueToAlignment(Align);
-
- return false;
-}
-
-/// parseDirectiveAltEntry
-/// ::= .alt_entry identifier
-bool DarwinAsmParser::parseDirectiveAltEntry(StringRef, SMLoc) {
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- // Look up symbol.
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- if (Sym->isDefined())
- return TokError(".alt_entry must preceed symbol definition");
-
- if (!getStreamer().EmitSymbolAttribute(Sym, MCSA_AltEntry))
- return TokError("unable to emit symbol attribute");
-
- Lex();
- return false;
-}
-
-/// parseDirectiveDesc
-/// ::= .desc identifier , expression
-bool DarwinAsmParser::parseDirectiveDesc(StringRef, SMLoc) {
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- // Handle the identifier as the key symbol.
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in '.desc' directive");
- Lex();
-
- int64_t DescValue;
- if (getParser().parseAbsoluteExpression(DescValue))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.desc' directive");
-
- Lex();
-
- // Set the n_desc field of this Symbol to this DescValue
- getStreamer().EmitSymbolDesc(Sym, DescValue);
-
- return false;
-}
-
-/// parseDirectiveIndirectSymbol
-/// ::= .indirect_symbol identifier
-bool DarwinAsmParser::parseDirectiveIndirectSymbol(StringRef, SMLoc Loc) {
- const MCSectionMachO *Current = static_cast<const MCSectionMachO *>(
- getStreamer().getCurrentSectionOnly());
- MachO::SectionType SectionType = Current->getType();
- if (SectionType != MachO::S_NON_LAZY_SYMBOL_POINTERS &&
- SectionType != MachO::S_LAZY_SYMBOL_POINTERS &&
- SectionType != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS &&
- SectionType != MachO::S_SYMBOL_STUBS)
- return Error(Loc, "indirect symbol not in a symbol pointer or stub "
- "section");
-
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in .indirect_symbol directive");
-
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- // Assembler local symbols don't make any sense here. Complain loudly.
- if (Sym->isTemporary())
- return TokError("non-local symbol required in directive");
-
- if (!getStreamer().EmitSymbolAttribute(Sym, MCSA_IndirectSymbol))
- return TokError("unable to emit indirect symbol attribute for: " + Name);
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.indirect_symbol' directive");
-
- Lex();
-
- return false;
-}
-
-/// parseDirectiveDumpOrLoad
-/// ::= ( .dump | .load ) "filename"
-bool DarwinAsmParser::parseDirectiveDumpOrLoad(StringRef Directive,
- SMLoc IDLoc) {
- bool IsDump = Directive == ".dump";
- if (getLexer().isNot(AsmToken::String))
- return TokError("expected string in '.dump' or '.load' directive");
-
- Lex();
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.dump' or '.load' directive");
-
- Lex();
-
- // FIXME: If/when .dump and .load are implemented they will be done in the
- // the assembly parser and not have any need for an MCStreamer API.
- if (IsDump)
- return Warning(IDLoc, "ignoring directive .dump for now");
- else
- return Warning(IDLoc, "ignoring directive .load for now");
-}
-
-/// ParseDirectiveLinkerOption
-/// ::= .linker_option "string" ( , "string" )*
-bool DarwinAsmParser::parseDirectiveLinkerOption(StringRef IDVal, SMLoc) {
- SmallVector<std::string, 4> Args;
- while (true) {
- if (getLexer().isNot(AsmToken::String))
- return TokError("expected string in '" + Twine(IDVal) + "' directive");
-
- std::string Data;
- if (getParser().parseEscapedString(Data))
- return true;
-
- Args.push_back(Data);
-
- if (getLexer().is(AsmToken::EndOfStatement))
- break;
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in '" + Twine(IDVal) + "' directive");
- Lex();
- }
-
- getStreamer().EmitLinkerOptions(Args);
- return false;
-}
-
-/// parseDirectiveLsym
-/// ::= .lsym identifier , expression
-bool DarwinAsmParser::parseDirectiveLsym(StringRef, SMLoc) {
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- // Handle the identifier as the key symbol.
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in '.lsym' directive");
- Lex();
-
- const MCExpr *Value;
- if (getParser().parseExpression(Value))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.lsym' directive");
-
- Lex();
-
- // We don't currently support this directive.
- //
- // FIXME: Diagnostic location!
- (void) Sym;
- return TokError("directive '.lsym' is unsupported");
-}
-
-/// parseDirectiveSection:
-/// ::= .section identifier (',' identifier)*
-bool DarwinAsmParser::parseDirectiveSection(StringRef, SMLoc) {
- SMLoc Loc = getLexer().getLoc();
-
- StringRef SectionName;
- if (getParser().parseIdentifier(SectionName))
- return Error(Loc, "expected identifier after '.section' directive");
-
- // Verify there is a following comma.
- if (!getLexer().is(AsmToken::Comma))
- return TokError("unexpected token in '.section' directive");
-
- std::string SectionSpec = SectionName;
- SectionSpec += ",";
-
- // Add all the tokens until the end of the line, ParseSectionSpecifier will
- // handle this.
- StringRef EOL = getLexer().LexUntilEndOfStatement();
- SectionSpec.append(EOL.begin(), EOL.end());
-
- Lex();
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.section' directive");
- Lex();
-
- StringRef Segment, Section;
- unsigned StubSize;
- unsigned TAA;
- bool TAAParsed;
- std::string ErrorStr =
- MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section,
- TAA, TAAParsed, StubSize);
-
- if (!ErrorStr.empty())
- return Error(Loc, ErrorStr);
-
- // Issue a warning if the target is not powerpc and Section is a *coal* section.
- Triple TT = getParser().getContext().getObjectFileInfo()->getTargetTriple();
- Triple::ArchType ArchTy = TT.getArch();
-
- if (ArchTy != Triple::ppc && ArchTy != Triple::ppc64) {
- StringRef NonCoalSection = StringSwitch<StringRef>(Section)
- .Case("__textcoal_nt", "__text")
- .Case("__const_coal", "__const")
- .Case("__datacoal_nt", "__data")
- .Default(Section);
-
- if (!Section.equals(NonCoalSection)) {
- StringRef SectionVal(Loc.getPointer());
- size_t B = SectionVal.find(',') + 1, E = SectionVal.find(',', B);
- SMLoc BLoc = SMLoc::getFromPointer(SectionVal.data() + B);
- SMLoc ELoc = SMLoc::getFromPointer(SectionVal.data() + E);
- getParser().Warning(Loc, "section \"" + Section + "\" is deprecated",
- SMRange(BLoc, ELoc));
- getParser().Note(Loc, "change section name to \"" + NonCoalSection +
- "\"", SMRange(BLoc, ELoc));
- }
- }
-
- // FIXME: Arch specific.
- bool isText = Segment == "__TEXT"; // FIXME: Hack.
- getStreamer().SwitchSection(getContext().getMachOSection(
- Segment, Section, TAA, StubSize,
- isText ? SectionKind::getText() : SectionKind::getData()));
- return false;
-}
-
-/// ParseDirectivePushSection:
-/// ::= .pushsection identifier (',' identifier)*
-bool DarwinAsmParser::parseDirectivePushSection(StringRef S, SMLoc Loc) {
- getStreamer().PushSection();
-
- if (parseDirectiveSection(S, Loc)) {
- getStreamer().PopSection();
- return true;
- }
-
- return false;
-}
-
-/// ParseDirectivePopSection:
-/// ::= .popsection
-bool DarwinAsmParser::parseDirectivePopSection(StringRef, SMLoc) {
- if (!getStreamer().PopSection())
- return TokError(".popsection without corresponding .pushsection");
- return false;
-}
-
-/// ParseDirectivePrevious:
-/// ::= .previous
-bool DarwinAsmParser::parseDirectivePrevious(StringRef DirName, SMLoc) {
- MCSectionSubPair PreviousSection = getStreamer().getPreviousSection();
- if (!PreviousSection.first)
- return TokError(".previous without corresponding .section");
- getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second);
- return false;
-}
-
-/// ParseDirectiveSecureLogUnique
-/// ::= .secure_log_unique ... message ...
-bool DarwinAsmParser::parseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) {
- StringRef LogMessage = getParser().parseStringToEndOfStatement();
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.secure_log_unique' directive");
-
- if (getContext().getSecureLogUsed())
- return Error(IDLoc, ".secure_log_unique specified multiple times");
-
- // Get the secure log path.
- const char *SecureLogFile = getContext().getSecureLogFile();
- if (!SecureLogFile)
- return Error(IDLoc, ".secure_log_unique used but AS_SECURE_LOG_FILE "
- "environment variable unset.");
-
- // Open the secure log file if we haven't already.
- raw_fd_ostream *OS = getContext().getSecureLog();
- if (!OS) {
- std::error_code EC;
- auto NewOS = llvm::make_unique<raw_fd_ostream>(
- StringRef(SecureLogFile), EC, sys::fs::F_Append | sys::fs::F_Text);
- if (EC)
- return Error(IDLoc, Twine("can't open secure log file: ") +
- SecureLogFile + " (" + EC.message() + ")");
- OS = NewOS.get();
- getContext().setSecureLog(std::move(NewOS));
- }
-
- // Write the message.
- unsigned CurBuf = getSourceManager().FindBufferContainingLoc(IDLoc);
- *OS << getSourceManager().getBufferInfo(CurBuf).Buffer->getBufferIdentifier()
- << ":" << getSourceManager().FindLineNumber(IDLoc, CurBuf) << ":"
- << LogMessage + "\n";
-
- getContext().setSecureLogUsed(true);
-
- return false;
-}
-
-/// ParseDirectiveSecureLogReset
-/// ::= .secure_log_reset
-bool DarwinAsmParser::parseDirectiveSecureLogReset(StringRef, SMLoc IDLoc) {
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.secure_log_reset' directive");
-
- Lex();
-
- getContext().setSecureLogUsed(false);
-
- return false;
-}
-
-/// parseDirectiveSubsectionsViaSymbols
-/// ::= .subsections_via_symbols
-bool DarwinAsmParser::parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) {
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.subsections_via_symbols' directive");
-
- Lex();
-
- getStreamer().EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
-
- return false;
-}
-
-/// ParseDirectiveTBSS
-/// ::= .tbss identifier, size, align
-bool DarwinAsmParser::parseDirectiveTBSS(StringRef, SMLoc) {
- SMLoc IDLoc = getLexer().getLoc();
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- // Handle the identifier as the key symbol.
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- int64_t Size;
- SMLoc SizeLoc = getLexer().getLoc();
- if (getParser().parseAbsoluteExpression(Size))
- return true;
-
- int64_t Pow2Alignment = 0;
- SMLoc Pow2AlignmentLoc;
- if (getLexer().is(AsmToken::Comma)) {
- Lex();
- Pow2AlignmentLoc = getLexer().getLoc();
- if (getParser().parseAbsoluteExpression(Pow2Alignment))
- return true;
- }
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.tbss' directive");
-
- Lex();
-
- if (Size < 0)
- return Error(SizeLoc, "invalid '.tbss' directive size, can't be less than"
- "zero");
-
- // FIXME: Diagnose overflow.
- if (Pow2Alignment < 0)
- return Error(Pow2AlignmentLoc, "invalid '.tbss' alignment, can't be less"
- "than zero");
-
- if (!Sym->isUndefined())
- return Error(IDLoc, "invalid symbol redefinition");
-
- getStreamer().EmitTBSSSymbol(getContext().getMachOSection(
- "__DATA", "__thread_bss",
- MachO::S_THREAD_LOCAL_ZEROFILL,
- 0, SectionKind::getThreadBSS()),
- Sym, Size, 1 << Pow2Alignment);
-
- return false;
-}
-
-/// ParseDirectiveZerofill
-/// ::= .zerofill segname , sectname [, identifier , size_expression [
-/// , align_expression ]]
-bool DarwinAsmParser::parseDirectiveZerofill(StringRef, SMLoc) {
- StringRef Segment;
- if (getParser().parseIdentifier(Segment))
- return TokError("expected segment name after '.zerofill' directive");
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- StringRef Section;
- SMLoc SectionLoc = getLexer().getLoc();
- if (getParser().parseIdentifier(Section))
- return TokError("expected section name after comma in '.zerofill' "
- "directive");
-
- // If this is the end of the line all that was wanted was to create the
- // the section but with no symbol.
- if (getLexer().is(AsmToken::EndOfStatement)) {
- // Create the zerofill section but no symbol
- getStreamer().EmitZerofill(
- getContext().getMachOSection(Segment, Section, MachO::S_ZEROFILL, 0,
- SectionKind::getBSS()),
- /*Symbol=*/nullptr, /*Size=*/0, /*ByteAlignment=*/0, SectionLoc);
- return false;
- }
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- SMLoc IDLoc = getLexer().getLoc();
- StringRef IDStr;
- if (getParser().parseIdentifier(IDStr))
- return TokError("expected identifier in directive");
-
- // handle the identifier as the key symbol.
- MCSymbol *Sym = getContext().getOrCreateSymbol(IDStr);
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- int64_t Size;
- SMLoc SizeLoc = getLexer().getLoc();
- if (getParser().parseAbsoluteExpression(Size))
- return true;
-
- int64_t Pow2Alignment = 0;
- SMLoc Pow2AlignmentLoc;
- if (getLexer().is(AsmToken::Comma)) {
- Lex();
- Pow2AlignmentLoc = getLexer().getLoc();
- if (getParser().parseAbsoluteExpression(Pow2Alignment))
- return true;
- }
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.zerofill' directive");
-
- Lex();
-
- if (Size < 0)
- return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less "
- "than zero");
-
- // NOTE: The alignment in the directive is a power of 2 value, the assembler
- // may internally end up wanting an alignment in bytes.
- // FIXME: Diagnose overflow.
- if (Pow2Alignment < 0)
- return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, "
- "can't be less than zero");
-
- if (!Sym->isUndefined())
- return Error(IDLoc, "invalid symbol redefinition");
-
- // Create the zerofill Symbol with Size and Pow2Alignment
- //
- // FIXME: Arch specific.
- getStreamer().EmitZerofill(getContext().getMachOSection(
- Segment, Section, MachO::S_ZEROFILL,
- 0, SectionKind::getBSS()),
- Sym, Size, 1 << Pow2Alignment, SectionLoc);
-
- return false;
-}
-
-/// ParseDirectiveDataRegion
-/// ::= .data_region [ ( jt8 | jt16 | jt32 ) ]
-bool DarwinAsmParser::parseDirectiveDataRegion(StringRef, SMLoc) {
- if (getLexer().is(AsmToken::EndOfStatement)) {
- Lex();
- getStreamer().EmitDataRegion(MCDR_DataRegion);
- return false;
- }
- StringRef RegionType;
- SMLoc Loc = getParser().getTok().getLoc();
- if (getParser().parseIdentifier(RegionType))
- return TokError("expected region type after '.data_region' directive");
- int Kind = StringSwitch<int>(RegionType)
- .Case("jt8", MCDR_DataRegionJT8)
- .Case("jt16", MCDR_DataRegionJT16)
- .Case("jt32", MCDR_DataRegionJT32)
- .Default(-1);
- if (Kind == -1)
- return Error(Loc, "unknown region type in '.data_region' directive");
- Lex();
-
- getStreamer().EmitDataRegion((MCDataRegionType)Kind);
- return false;
-}
-
-/// ParseDirectiveDataRegionEnd
-/// ::= .end_data_region
-bool DarwinAsmParser::parseDirectiveDataRegionEnd(StringRef, SMLoc) {
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.end_data_region' directive");
-
- Lex();
- getStreamer().EmitDataRegion(MCDR_DataRegionEnd);
- return false;
-}
-
-static bool isSDKVersionToken(const AsmToken &Tok) {
- return Tok.is(AsmToken::Identifier) && Tok.getIdentifier() == "sdk_version";
-}
-
-/// parseMajorMinorVersionComponent ::= major, minor
-bool DarwinAsmParser::parseMajorMinorVersionComponent(unsigned *Major,
- unsigned *Minor,
- const char *VersionName) {
- // Get the major version number.
- if (getLexer().isNot(AsmToken::Integer))
- return TokError(Twine("invalid ") + VersionName +
- " major version number, integer expected");
- int64_t MajorVal = getLexer().getTok().getIntVal();
- if (MajorVal > 65535 || MajorVal <= 0)
- return TokError(Twine("invalid ") + VersionName + " major version number");
- *Major = (unsigned)MajorVal;
- Lex();
- if (getLexer().isNot(AsmToken::Comma))
- return TokError(Twine(VersionName) +
- " minor version number required, comma expected");
- Lex();
- // Get the minor version number.
- if (getLexer().isNot(AsmToken::Integer))
- return TokError(Twine("invalid ") + VersionName +
- " minor version number, integer expected");
- int64_t MinorVal = getLexer().getTok().getIntVal();
- if (MinorVal > 255 || MinorVal < 0)
- return TokError(Twine("invalid ") + VersionName + " minor version number");
- *Minor = MinorVal;
- Lex();
- return false;
-}
-
-/// parseOptionalTrailingVersionComponent ::= , version_number
-bool DarwinAsmParser::parseOptionalTrailingVersionComponent(
- unsigned *Component, const char *ComponentName) {
- assert(getLexer().is(AsmToken::Comma) && "comma expected");
- Lex();
- if (getLexer().isNot(AsmToken::Integer))
- return TokError(Twine("invalid ") + ComponentName +
- " version number, integer expected");
- int64_t Val = getLexer().getTok().getIntVal();
- if (Val > 255 || Val < 0)
- return TokError(Twine("invalid ") + ComponentName + " version number");
- *Component = Val;
- Lex();
- return false;
-}
-
-/// parseVersion ::= parseMajorMinorVersionComponent
-/// parseOptionalTrailingVersionComponent
-bool DarwinAsmParser::parseVersion(unsigned *Major, unsigned *Minor,
- unsigned *Update) {
- if (parseMajorMinorVersionComponent(Major, Minor, "OS"))
- return true;
-
- // Get the update level, if specified
- *Update = 0;
- if (getLexer().is(AsmToken::EndOfStatement) ||
- isSDKVersionToken(getLexer().getTok()))
- return false;
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("invalid OS update specifier, comma expected");
- if (parseOptionalTrailingVersionComponent(Update, "OS update"))
- return true;
- return false;
-}
-
-bool DarwinAsmParser::parseSDKVersion(VersionTuple &SDKVersion) {
- assert(isSDKVersionToken(getLexer().getTok()) && "expected sdk_version");
- Lex();
- unsigned Major, Minor;
- if (parseMajorMinorVersionComponent(&Major, &Minor, "SDK"))
- return true;
- SDKVersion = VersionTuple(Major, Minor);
-
- // Get the subminor version, if specified.
- if (getLexer().is(AsmToken::Comma)) {
- unsigned Subminor;
- if (parseOptionalTrailingVersionComponent(&Subminor, "SDK subminor"))
- return true;
- SDKVersion = VersionTuple(Major, Minor, Subminor);
- }
- return false;
-}
-
-void DarwinAsmParser::checkVersion(StringRef Directive, StringRef Arg,
- SMLoc Loc, Triple::OSType ExpectedOS) {
- const Triple &Target = getContext().getObjectFileInfo()->getTargetTriple();
- if (Target.getOS() != ExpectedOS)
- Warning(Loc, Twine(Directive) +
- (Arg.empty() ? Twine() : Twine(' ') + Arg) +
- " used while targeting " + Target.getOSName());
-
- if (LastVersionDirective.isValid()) {
- Warning(Loc, "overriding previous version directive");
- Note(LastVersionDirective, "previous definition is here");
- }
- LastVersionDirective = Loc;
-}
-
-static Triple::OSType getOSTypeFromMCVM(MCVersionMinType Type) {
- switch (Type) {
- case MCVM_WatchOSVersionMin: return Triple::WatchOS;
- case MCVM_TvOSVersionMin: return Triple::TvOS;
- case MCVM_IOSVersionMin: return Triple::IOS;
- case MCVM_OSXVersionMin: return Triple::MacOSX;
- }
- llvm_unreachable("Invalid mc version min type");
-}
-
-/// parseVersionMin
-/// ::= .ios_version_min parseVersion parseSDKVersion
-/// | .macosx_version_min parseVersion parseSDKVersion
-/// | .tvos_version_min parseVersion parseSDKVersion
-/// | .watchos_version_min parseVersion parseSDKVersion
-bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc,
- MCVersionMinType Type) {
- unsigned Major;
- unsigned Minor;
- unsigned Update;
- if (parseVersion(&Major, &Minor, &Update))
- return true;
-
- VersionTuple SDKVersion;
- if (isSDKVersionToken(getLexer().getTok()) && parseSDKVersion(SDKVersion))
- return true;
-
- if (parseToken(AsmToken::EndOfStatement))
- return addErrorSuffix(Twine(" in '") + Directive + "' directive");
-
- Triple::OSType ExpectedOS = getOSTypeFromMCVM(Type);
- checkVersion(Directive, StringRef(), Loc, ExpectedOS);
- getStreamer().EmitVersionMin(Type, Major, Minor, Update, SDKVersion);
- return false;
-}
-
-static Triple::OSType getOSTypeFromPlatform(MachO::PlatformType Type) {
- switch (Type) {
- case MachO::PLATFORM_MACOS: return Triple::MacOSX;
- case MachO::PLATFORM_IOS: return Triple::IOS;
- case MachO::PLATFORM_TVOS: return Triple::TvOS;
- case MachO::PLATFORM_WATCHOS: return Triple::WatchOS;
- case MachO::PLATFORM_BRIDGEOS: /* silence warning */ break;
- case MachO::PLATFORM_MACCATALYST: return Triple::IOS;
- case MachO::PLATFORM_IOSSIMULATOR: /* silence warning */ break;
- case MachO::PLATFORM_TVOSSIMULATOR: /* silence warning */ break;
- case MachO::PLATFORM_WATCHOSSIMULATOR: /* silence warning */ break;
- }
- llvm_unreachable("Invalid mach-o platform type");
-}
-
-/// parseBuildVersion
-/// ::= .build_version (macos|ios|tvos|watchos), parseVersion parseSDKVersion
-bool DarwinAsmParser::parseBuildVersion(StringRef Directive, SMLoc Loc) {
- StringRef PlatformName;
- SMLoc PlatformLoc = getTok().getLoc();
- if (getParser().parseIdentifier(PlatformName))
- return TokError("platform name expected");
-
- unsigned Platform = StringSwitch<unsigned>(PlatformName)
- .Case("macos", MachO::PLATFORM_MACOS)
- .Case("ios", MachO::PLATFORM_IOS)
- .Case("tvos", MachO::PLATFORM_TVOS)
- .Case("watchos", MachO::PLATFORM_WATCHOS)
- .Case("macCatalyst", MachO::PLATFORM_MACCATALYST)
- .Default(0);
- if (Platform == 0)
- return Error(PlatformLoc, "unknown platform name");
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("version number required, comma expected");
- Lex();
-
- unsigned Major;
- unsigned Minor;
- unsigned Update;
- if (parseVersion(&Major, &Minor, &Update))
- return true;
-
- VersionTuple SDKVersion;
- if (isSDKVersionToken(getLexer().getTok()) && parseSDKVersion(SDKVersion))
- return true;
-
- if (parseToken(AsmToken::EndOfStatement))
- return addErrorSuffix(" in '.build_version' directive");
-
- Triple::OSType ExpectedOS
- = getOSTypeFromPlatform((MachO::PlatformType)Platform);
- checkVersion(Directive, PlatformName, Loc, ExpectedOS);
- getStreamer().EmitBuildVersion(Platform, Major, Minor, Update, SDKVersion);
- return false;
-}
-
-
-namespace llvm {
-
-MCAsmParserExtension *createDarwinAsmParser() {
- return new DarwinAsmParser;
-}
-
-} // end llvm namespace
diff --git a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp
deleted file mode 100644
index a55bdd5364cb..000000000000
--- a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp
+++ /dev/null
@@ -1,899 +0,0 @@
-//===- ELFAsmParser.cpp - ELF Assembly Parser -----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDirectives.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCParser/MCAsmLexer.h"
-#include "llvm/MC/MCParser/MCAsmParser.h"
-#include "llvm/MC/MCParser/MCAsmParserExtension.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCSectionELF.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCSymbolELF.h"
-#include "llvm/MC/SectionKind.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/SMLoc.h"
-#include <cassert>
-#include <cstdint>
-#include <utility>
-
-using namespace llvm;
-
-namespace {
-
-class ELFAsmParser : public MCAsmParserExtension {
- template<bool (ELFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
- void addDirectiveHandler(StringRef Directive) {
- MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
- this, HandleDirective<ELFAsmParser, HandlerMethod>);
-
- getParser().addDirectiveHandler(Directive, Handler);
- }
-
- bool ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags,
- SectionKind Kind);
-
-public:
- ELFAsmParser() { BracketExpressionsSupported = true; }
-
- void Initialize(MCAsmParser &Parser) override {
- // Call the base implementation.
- this->MCAsmParserExtension::Initialize(Parser);
-
- addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data");
- addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text");
- addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss");
- addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata");
- addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata");
- addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss");
- addDirectiveHandler<
- &ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel");
- addDirectiveHandler<
- &ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro");
- addDirectiveHandler<
- &ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section");
- addDirectiveHandler<
- &ELFAsmParser::ParseDirectivePushSection>(".pushsection");
- addDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size");
- addDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveVersion>(".version");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".local");
- addDirectiveHandler<
- &ELFAsmParser::ParseDirectiveSymbolAttribute>(".protected");
- addDirectiveHandler<
- &ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal");
- addDirectiveHandler<
- &ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveSubsection>(".subsection");
- addDirectiveHandler<&ELFAsmParser::ParseDirectiveCGProfile>(".cg_profile");
- }
-
- // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is
- // the best way for us to get access to it?
- bool ParseSectionDirectiveData(StringRef, SMLoc) {
- return ParseSectionSwitch(".data", ELF::SHT_PROGBITS,
- ELF::SHF_WRITE | ELF::SHF_ALLOC,
- SectionKind::getData());
- }
- bool ParseSectionDirectiveText(StringRef, SMLoc) {
- return ParseSectionSwitch(".text", ELF::SHT_PROGBITS,
- ELF::SHF_EXECINSTR |
- ELF::SHF_ALLOC, SectionKind::getText());
- }
- bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
- return ParseSectionSwitch(".bss", ELF::SHT_NOBITS,
- ELF::SHF_WRITE |
- ELF::SHF_ALLOC, SectionKind::getBSS());
- }
- bool ParseSectionDirectiveRoData(StringRef, SMLoc) {
- return ParseSectionSwitch(".rodata", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC,
- SectionKind::getReadOnly());
- }
- bool ParseSectionDirectiveTData(StringRef, SMLoc) {
- return ParseSectionSwitch(".tdata", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC |
- ELF::SHF_TLS | ELF::SHF_WRITE,
- SectionKind::getThreadData());
- }
- bool ParseSectionDirectiveTBSS(StringRef, SMLoc) {
- return ParseSectionSwitch(".tbss", ELF::SHT_NOBITS,
- ELF::SHF_ALLOC |
- ELF::SHF_TLS | ELF::SHF_WRITE,
- SectionKind::getThreadBSS());
- }
- bool ParseSectionDirectiveDataRel(StringRef, SMLoc) {
- return ParseSectionSwitch(".data.rel", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC | ELF::SHF_WRITE,
- SectionKind::getData());
- }
- bool ParseSectionDirectiveDataRelRo(StringRef, SMLoc) {
- return ParseSectionSwitch(".data.rel.ro", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC |
- ELF::SHF_WRITE,
- SectionKind::getReadOnlyWithRel());
- }
- bool ParseSectionDirectiveEhFrame(StringRef, SMLoc) {
- return ParseSectionSwitch(".eh_frame", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC | ELF::SHF_WRITE,
- SectionKind::getData());
- }
- bool ParseDirectivePushSection(StringRef, SMLoc);
- bool ParseDirectivePopSection(StringRef, SMLoc);
- bool ParseDirectiveSection(StringRef, SMLoc);
- bool ParseDirectiveSize(StringRef, SMLoc);
- bool ParseDirectivePrevious(StringRef, SMLoc);
- bool ParseDirectiveType(StringRef, SMLoc);
- bool ParseDirectiveIdent(StringRef, SMLoc);
- bool ParseDirectiveSymver(StringRef, SMLoc);
- bool ParseDirectiveVersion(StringRef, SMLoc);
- bool ParseDirectiveWeakref(StringRef, SMLoc);
- bool ParseDirectiveSymbolAttribute(StringRef, SMLoc);
- bool ParseDirectiveSubsection(StringRef, SMLoc);
- bool ParseDirectiveCGProfile(StringRef, SMLoc);
-
-private:
- bool ParseSectionName(StringRef &SectionName);
- bool ParseSectionArguments(bool IsPush, SMLoc loc);
- unsigned parseSunStyleSectionFlags();
- bool maybeParseSectionType(StringRef &TypeName);
- bool parseMergeSize(int64_t &Size);
- bool parseGroup(StringRef &GroupName);
- bool parseMetadataSym(MCSymbolELF *&Associated);
- bool maybeParseUniqueID(int64_t &UniqueID);
-};
-
-} // end anonymous namespace
-
-/// ParseDirectiveSymbolAttribute
-/// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ]
-bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
- MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
- .Case(".weak", MCSA_Weak)
- .Case(".local", MCSA_Local)
- .Case(".hidden", MCSA_Hidden)
- .Case(".internal", MCSA_Internal)
- .Case(".protected", MCSA_Protected)
- .Default(MCSA_Invalid);
- assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- while (true) {
- StringRef Name;
-
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- getStreamer().EmitSymbolAttribute(Sym, Attr);
-
- if (getLexer().is(AsmToken::EndOfStatement))
- break;
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
- }
- }
-
- Lex();
- return false;
-}
-
-bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type,
- unsigned Flags, SectionKind Kind) {
- const MCExpr *Subsection = nullptr;
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- if (getParser().parseExpression(Subsection))
- return true;
- }
- Lex();
-
- getStreamer().SwitchSection(getContext().getELFSection(Section, Type, Flags),
- Subsection);
-
- return false;
-}
-
-bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) {
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
- MCSymbolELF *Sym = cast<MCSymbolELF>(getContext().getOrCreateSymbol(Name));
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
-
- const MCExpr *Expr;
- if (getParser().parseExpression(Expr))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
- Lex();
-
- getStreamer().emitELFSize(Sym, Expr);
- return false;
-}
-
-bool ELFAsmParser::ParseSectionName(StringRef &SectionName) {
- // A section name can contain -, so we cannot just use
- // parseIdentifier.
- SMLoc FirstLoc = getLexer().getLoc();
- unsigned Size = 0;
-
- if (getLexer().is(AsmToken::String)) {
- SectionName = getTok().getIdentifier();
- Lex();
- return false;
- }
-
- while (!getParser().hasPendingError()) {
- SMLoc PrevLoc = getLexer().getLoc();
- if (getLexer().is(AsmToken::Comma) ||
- getLexer().is(AsmToken::EndOfStatement))
- break;
-
- unsigned CurSize;
- if (getLexer().is(AsmToken::String)) {
- CurSize = getTok().getIdentifier().size() + 2;
- Lex();
- } else if (getLexer().is(AsmToken::Identifier)) {
- CurSize = getTok().getIdentifier().size();
- Lex();
- } else {
- CurSize = getTok().getString().size();
- Lex();
- }
- Size += CurSize;
- SectionName = StringRef(FirstLoc.getPointer(), Size);
-
- // Make sure the following token is adjacent.
- if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer())
- break;
- }
- if (Size == 0)
- return true;
-
- return false;
-}
-
-static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) {
- unsigned flags = 0;
-
- // If a valid numerical value is set for the section flag, use it verbatim
- if (!flagsStr.getAsInteger(0, flags))
- return flags;
-
- for (char i : flagsStr) {
- switch (i) {
- case 'a':
- flags |= ELF::SHF_ALLOC;
- break;
- case 'e':
- flags |= ELF::SHF_EXCLUDE;
- break;
- case 'x':
- flags |= ELF::SHF_EXECINSTR;
- break;
- case 'w':
- flags |= ELF::SHF_WRITE;
- break;
- case 'o':
- flags |= ELF::SHF_LINK_ORDER;
- break;
- case 'M':
- flags |= ELF::SHF_MERGE;
- break;
- case 'S':
- flags |= ELF::SHF_STRINGS;
- break;
- case 'T':
- flags |= ELF::SHF_TLS;
- break;
- case 'c':
- flags |= ELF::XCORE_SHF_CP_SECTION;
- break;
- case 'd':
- flags |= ELF::XCORE_SHF_DP_SECTION;
- break;
- case 'y':
- flags |= ELF::SHF_ARM_PURECODE;
- break;
- case 's':
- flags |= ELF::SHF_HEX_GPREL;
- break;
- case 'G':
- flags |= ELF::SHF_GROUP;
- break;
- case '?':
- *UseLastGroup = true;
- break;
- default:
- return -1U;
- }
- }
-
- return flags;
-}
-
-unsigned ELFAsmParser::parseSunStyleSectionFlags() {
- unsigned flags = 0;
- while (getLexer().is(AsmToken::Hash)) {
- Lex(); // Eat the #.
-
- if (!getLexer().is(AsmToken::Identifier))
- return -1U;
-
- StringRef flagId = getTok().getIdentifier();
- if (flagId == "alloc")
- flags |= ELF::SHF_ALLOC;
- else if (flagId == "execinstr")
- flags |= ELF::SHF_EXECINSTR;
- else if (flagId == "write")
- flags |= ELF::SHF_WRITE;
- else if (flagId == "tls")
- flags |= ELF::SHF_TLS;
- else
- return -1U;
-
- Lex(); // Eat the flag.
-
- if (!getLexer().is(AsmToken::Comma))
- break;
- Lex(); // Eat the comma.
- }
- return flags;
-}
-
-
-bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) {
- getStreamer().PushSection();
-
- if (ParseSectionArguments(/*IsPush=*/true, loc)) {
- getStreamer().PopSection();
- return true;
- }
-
- return false;
-}
-
-bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) {
- if (!getStreamer().PopSection())
- return TokError(".popsection without corresponding .pushsection");
- return false;
-}
-
-bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) {
- return ParseSectionArguments(/*IsPush=*/false, loc);
-}
-
-bool ELFAsmParser::maybeParseSectionType(StringRef &TypeName) {
- MCAsmLexer &L = getLexer();
- if (L.isNot(AsmToken::Comma))
- return false;
- Lex();
- if (L.isNot(AsmToken::At) && L.isNot(AsmToken::Percent) &&
- L.isNot(AsmToken::String)) {
- if (L.getAllowAtInIdentifier())
- return TokError("expected '@<type>', '%<type>' or \"<type>\"");
- else
- return TokError("expected '%<type>' or \"<type>\"");
- }
- if (!L.is(AsmToken::String))
- Lex();
- if (L.is(AsmToken::Integer)) {
- TypeName = getTok().getString();
- Lex();
- } else if (getParser().parseIdentifier(TypeName))
- return TokError("expected identifier in directive");
- return false;
-}
-
-bool ELFAsmParser::parseMergeSize(int64_t &Size) {
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("expected the entry size");
- Lex();
- if (getParser().parseAbsoluteExpression(Size))
- return true;
- if (Size <= 0)
- return TokError("entry size must be positive");
- return false;
-}
-
-bool ELFAsmParser::parseGroup(StringRef &GroupName) {
- MCAsmLexer &L = getLexer();
- if (L.isNot(AsmToken::Comma))
- return TokError("expected group name");
- Lex();
- if (L.is(AsmToken::Integer)) {
- GroupName = getTok().getString();
- Lex();
- } else if (getParser().parseIdentifier(GroupName)) {
- return TokError("invalid group name");
- }
- if (L.is(AsmToken::Comma)) {
- Lex();
- StringRef Linkage;
- if (getParser().parseIdentifier(Linkage))
- return TokError("invalid linkage");
- if (Linkage != "comdat")
- return TokError("Linkage must be 'comdat'");
- }
- return false;
-}
-
-bool ELFAsmParser::parseMetadataSym(MCSymbolELF *&Associated) {
- MCAsmLexer &L = getLexer();
- if (L.isNot(AsmToken::Comma))
- return TokError("expected metadata symbol");
- Lex();
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("invalid metadata symbol");
- Associated = dyn_cast_or_null<MCSymbolELF>(getContext().lookupSymbol(Name));
- if (!Associated || !Associated->isInSection())
- return TokError("symbol is not in a section: " + Name);
- return false;
-}
-
-bool ELFAsmParser::maybeParseUniqueID(int64_t &UniqueID) {
- MCAsmLexer &L = getLexer();
- if (L.isNot(AsmToken::Comma))
- return false;
- Lex();
- StringRef UniqueStr;
- if (getParser().parseIdentifier(UniqueStr))
- return TokError("expected identifier in directive");
- if (UniqueStr != "unique")
- return TokError("expected 'unique'");
- if (L.isNot(AsmToken::Comma))
- return TokError("expected commma");
- Lex();
- if (getParser().parseAbsoluteExpression(UniqueID))
- return true;
- if (UniqueID < 0)
- return TokError("unique id must be positive");
- if (!isUInt<32>(UniqueID) || UniqueID == ~0U)
- return TokError("unique id is too large");
- return false;
-}
-
-static bool hasPrefix(StringRef SectionName, StringRef Prefix) {
- return SectionName.startswith(Prefix) || SectionName == Prefix.drop_back();
-}
-
-bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
- StringRef SectionName;
-
- if (ParseSectionName(SectionName))
- return TokError("expected identifier in directive");
-
- StringRef TypeName;
- int64_t Size = 0;
- StringRef GroupName;
- unsigned Flags = 0;
- const MCExpr *Subsection = nullptr;
- bool UseLastGroup = false;
- MCSymbolELF *Associated = nullptr;
- int64_t UniqueID = ~0;
-
- // Set the defaults first.
- if (hasPrefix(SectionName, ".rodata.") || SectionName == ".rodata1")
- Flags |= ELF::SHF_ALLOC;
- else if (SectionName == ".fini" || SectionName == ".init" ||
- hasPrefix(SectionName, ".text."))
- Flags |= ELF::SHF_ALLOC | ELF::SHF_EXECINSTR;
- else if (hasPrefix(SectionName, ".data.") || SectionName == ".data1" ||
- hasPrefix(SectionName, ".bss.") ||
- hasPrefix(SectionName, ".init_array.") ||
- hasPrefix(SectionName, ".fini_array.") ||
- hasPrefix(SectionName, ".preinit_array."))
- Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE;
- else if (hasPrefix(SectionName, ".tdata.") ||
- hasPrefix(SectionName, ".tbss."))
- Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_TLS;
-
- if (getLexer().is(AsmToken::Comma)) {
- Lex();
-
- if (IsPush && getLexer().isNot(AsmToken::String)) {
- if (getParser().parseExpression(Subsection))
- return true;
- if (getLexer().isNot(AsmToken::Comma))
- goto EndStmt;
- Lex();
- }
-
- unsigned extraFlags;
-
- if (getLexer().isNot(AsmToken::String)) {
- if (!getContext().getAsmInfo()->usesSunStyleELFSectionSwitchSyntax()
- || getLexer().isNot(AsmToken::Hash))
- return TokError("expected string in directive");
- extraFlags = parseSunStyleSectionFlags();
- } else {
- StringRef FlagsStr = getTok().getStringContents();
- Lex();
- extraFlags = parseSectionFlags(FlagsStr, &UseLastGroup);
- }
-
- if (extraFlags == -1U)
- return TokError("unknown flag");
- Flags |= extraFlags;
-
- bool Mergeable = Flags & ELF::SHF_MERGE;
- bool Group = Flags & ELF::SHF_GROUP;
- if (Group && UseLastGroup)
- return TokError("Section cannot specifiy a group name while also acting "
- "as a member of the last group");
-
- if (maybeParseSectionType(TypeName))
- return true;
-
- MCAsmLexer &L = getLexer();
- if (TypeName.empty()) {
- if (Mergeable)
- return TokError("Mergeable section must specify the type");
- if (Group)
- return TokError("Group section must specify the type");
- if (L.isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
- }
-
- if (Mergeable)
- if (parseMergeSize(Size))
- return true;
- if (Group)
- if (parseGroup(GroupName))
- return true;
- if (Flags & ELF::SHF_LINK_ORDER)
- if (parseMetadataSym(Associated))
- return true;
- if (maybeParseUniqueID(UniqueID))
- return true;
- }
-
-EndStmt:
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
- Lex();
-
- unsigned Type = ELF::SHT_PROGBITS;
-
- if (TypeName.empty()) {
- if (SectionName.startswith(".note"))
- Type = ELF::SHT_NOTE;
- else if (hasPrefix(SectionName, ".init_array."))
- Type = ELF::SHT_INIT_ARRAY;
- else if (hasPrefix(SectionName, ".bss."))
- Type = ELF::SHT_NOBITS;
- else if (hasPrefix(SectionName, ".tbss."))
- Type = ELF::SHT_NOBITS;
- else if (hasPrefix(SectionName, ".fini_array."))
- Type = ELF::SHT_FINI_ARRAY;
- else if (hasPrefix(SectionName, ".preinit_array."))
- Type = ELF::SHT_PREINIT_ARRAY;
- } else {
- if (TypeName == "init_array")
- Type = ELF::SHT_INIT_ARRAY;
- else if (TypeName == "fini_array")
- Type = ELF::SHT_FINI_ARRAY;
- else if (TypeName == "preinit_array")
- Type = ELF::SHT_PREINIT_ARRAY;
- else if (TypeName == "nobits")
- Type = ELF::SHT_NOBITS;
- else if (TypeName == "progbits")
- Type = ELF::SHT_PROGBITS;
- else if (TypeName == "note")
- Type = ELF::SHT_NOTE;
- else if (TypeName == "unwind")
- Type = ELF::SHT_X86_64_UNWIND;
- else if (TypeName == "llvm_odrtab")
- Type = ELF::SHT_LLVM_ODRTAB;
- else if (TypeName == "llvm_linker_options")
- Type = ELF::SHT_LLVM_LINKER_OPTIONS;
- else if (TypeName == "llvm_call_graph_profile")
- Type = ELF::SHT_LLVM_CALL_GRAPH_PROFILE;
- else if (TypeName == "llvm_dependent_libraries")
- Type = ELF::SHT_LLVM_DEPENDENT_LIBRARIES;
- else if (TypeName == "llvm_sympart")
- Type = ELF::SHT_LLVM_SYMPART;
- else if (TypeName.getAsInteger(0, Type))
- return TokError("unknown section type");
- }
-
- if (UseLastGroup) {
- MCSectionSubPair CurrentSection = getStreamer().getCurrentSection();
- if (const MCSectionELF *Section =
- cast_or_null<MCSectionELF>(CurrentSection.first))
- if (const MCSymbol *Group = Section->getGroup()) {
- GroupName = Group->getName();
- Flags |= ELF::SHF_GROUP;
- }
- }
-
- MCSection *ELFSection =
- getContext().getELFSection(SectionName, Type, Flags, Size, GroupName,
- UniqueID, Associated);
- getStreamer().SwitchSection(ELFSection, Subsection);
-
- if (getContext().getGenDwarfForAssembly()) {
- bool InsertResult = getContext().addGenDwarfSection(ELFSection);
- if (InsertResult) {
- if (getContext().getDwarfVersion() <= 2)
- Warning(loc, "DWARF2 only supports one section per compilation unit");
-
- if (!ELFSection->getBeginSymbol()) {
- MCSymbol *SectionStartSymbol = getContext().createTempSymbol();
- getStreamer().EmitLabel(SectionStartSymbol);
- ELFSection->setBeginSymbol(SectionStartSymbol);
- }
- }
- }
-
- return false;
-}
-
-bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) {
- MCSectionSubPair PreviousSection = getStreamer().getPreviousSection();
- if (PreviousSection.first == nullptr)
- return TokError(".previous without corresponding .section");
- getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second);
-
- return false;
-}
-
-static MCSymbolAttr MCAttrForString(StringRef Type) {
- return StringSwitch<MCSymbolAttr>(Type)
- .Cases("STT_FUNC", "function", MCSA_ELF_TypeFunction)
- .Cases("STT_OBJECT", "object", MCSA_ELF_TypeObject)
- .Cases("STT_TLS", "tls_object", MCSA_ELF_TypeTLS)
- .Cases("STT_COMMON", "common", MCSA_ELF_TypeCommon)
- .Cases("STT_NOTYPE", "notype", MCSA_ELF_TypeNoType)
- .Cases("STT_GNU_IFUNC", "gnu_indirect_function",
- MCSA_ELF_TypeIndFunction)
- .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject)
- .Default(MCSA_Invalid);
-}
-
-/// ParseDirectiveELFType
-/// ::= .type identifier , STT_<TYPE_IN_UPPER_CASE>
-/// ::= .type identifier , #attribute
-/// ::= .type identifier , @attribute
-/// ::= .type identifier , %attribute
-/// ::= .type identifier , "attribute"
-bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- // Handle the identifier as the key symbol.
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- // NOTE the comma is optional in all cases. It is only documented as being
- // optional in the first case, however, GAS will silently treat the comma as
- // optional in all cases. Furthermore, although the documentation states that
- // the first form only accepts STT_<TYPE_IN_UPPER_CASE>, in reality, GAS
- // accepts both the upper case name as well as the lower case aliases.
- if (getLexer().is(AsmToken::Comma))
- Lex();
-
- if (getLexer().isNot(AsmToken::Identifier) &&
- getLexer().isNot(AsmToken::Hash) &&
- getLexer().isNot(AsmToken::Percent) &&
- getLexer().isNot(AsmToken::String)) {
- if (!getLexer().getAllowAtInIdentifier())
- return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', "
- "'%<type>' or \"<type>\"");
- else if (getLexer().isNot(AsmToken::At))
- return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', "
- "'%<type>' or \"<type>\"");
- }
-
- if (getLexer().isNot(AsmToken::String) &&
- getLexer().isNot(AsmToken::Identifier))
- Lex();
-
- SMLoc TypeLoc = getLexer().getLoc();
-
- StringRef Type;
- if (getParser().parseIdentifier(Type))
- return TokError("expected symbol type in directive");
-
- MCSymbolAttr Attr = MCAttrForString(Type);
- if (Attr == MCSA_Invalid)
- return Error(TypeLoc, "unsupported attribute in '.type' directive");
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.type' directive");
- Lex();
-
- getStreamer().EmitSymbolAttribute(Sym, Attr);
-
- return false;
-}
-
-/// ParseDirectiveIdent
-/// ::= .ident string
-bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) {
- if (getLexer().isNot(AsmToken::String))
- return TokError("unexpected token in '.ident' directive");
-
- StringRef Data = getTok().getIdentifier();
-
- Lex();
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.ident' directive");
- Lex();
-
- getStreamer().EmitIdent(Data);
- return false;
-}
-
-/// ParseDirectiveSymver
-/// ::= .symver foo, bar2@zed
-bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) {
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("expected a comma");
-
- // ARM assembly uses @ for a comment...
- // except when parsing the second parameter of the .symver directive.
- // Force the next symbol to allow @ in the identifier, which is
- // required for this directive and then reset it to its initial state.
- const bool AllowAtInIdentifier = getLexer().getAllowAtInIdentifier();
- getLexer().setAllowAtInIdentifier(true);
- Lex();
- getLexer().setAllowAtInIdentifier(AllowAtInIdentifier);
-
- StringRef AliasName;
- if (getParser().parseIdentifier(AliasName))
- return TokError("expected identifier in directive");
-
- if (AliasName.find('@') == StringRef::npos)
- return TokError("expected a '@' in the name");
-
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- getStreamer().emitELFSymverDirective(AliasName, Sym);
- return false;
-}
-
-/// ParseDirectiveVersion
-/// ::= .version string
-bool ELFAsmParser::ParseDirectiveVersion(StringRef, SMLoc) {
- if (getLexer().isNot(AsmToken::String))
- return TokError("unexpected token in '.version' directive");
-
- StringRef Data = getTok().getIdentifier();
-
- Lex();
-
- MCSection *Note = getContext().getELFSection(".note", ELF::SHT_NOTE, 0);
-
- getStreamer().PushSection();
- getStreamer().SwitchSection(Note);
- getStreamer().EmitIntValue(Data.size()+1, 4); // namesz.
- getStreamer().EmitIntValue(0, 4); // descsz = 0 (no description).
- getStreamer().EmitIntValue(1, 4); // type = NT_VERSION.
- getStreamer().EmitBytes(Data); // name.
- getStreamer().EmitIntValue(0, 1); // terminate the string.
- getStreamer().EmitValueToAlignment(4); // ensure 4 byte alignment.
- getStreamer().PopSection();
- return false;
-}
-
-/// ParseDirectiveWeakref
-/// ::= .weakref foo, bar
-bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) {
- // FIXME: Share code with the other alias building directives.
-
- StringRef AliasName;
- if (getParser().parseIdentifier(AliasName))
- return TokError("expected identifier in directive");
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("expected a comma");
-
- Lex();
-
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);
-
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
- getStreamer().EmitWeakReference(Alias, Sym);
- return false;
-}
-
-bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) {
- const MCExpr *Subsection = nullptr;
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- if (getParser().parseExpression(Subsection))
- return true;
- }
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- Lex();
-
- getStreamer().SubSection(Subsection);
- return false;
-}
-
-/// ParseDirectiveCGProfile
-/// ::= .cg_profile identifier, identifier, <number>
-bool ELFAsmParser::ParseDirectiveCGProfile(StringRef, SMLoc) {
- StringRef From;
- SMLoc FromLoc = getLexer().getLoc();
- if (getParser().parseIdentifier(From))
- return TokError("expected identifier in directive");
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("expected a comma");
- Lex();
-
- StringRef To;
- SMLoc ToLoc = getLexer().getLoc();
- if (getParser().parseIdentifier(To))
- return TokError("expected identifier in directive");
-
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("expected a comma");
- Lex();
-
- int64_t Count;
- if (getParser().parseIntToken(
- Count, "expected integer count in '.cg_profile' directive"))
- return true;
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
-
- MCSymbol *FromSym = getContext().getOrCreateSymbol(From);
- MCSymbol *ToSym = getContext().getOrCreateSymbol(To);
-
- getStreamer().emitCGProfileEntry(
- MCSymbolRefExpr::create(FromSym, MCSymbolRefExpr::VK_None, getContext(),
- FromLoc),
- MCSymbolRefExpr::create(ToSym, MCSymbolRefExpr::VK_None, getContext(),
- ToLoc),
- Count);
- return false;
-}
-
-namespace llvm {
-
-MCAsmParserExtension *createELFAsmParser() {
- return new ELFAsmParser;
-}
-
-} // end namespace llvm
diff --git a/contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp b/contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp
deleted file mode 100644
index 497055bc1760..000000000000
--- a/contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-//===- MCAsmLexer.cpp - Abstract Asm Lexer Interface ----------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCParser/MCAsmLexer.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/SMLoc.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-MCAsmLexer::MCAsmLexer() {
- CurTok.emplace_back(AsmToken::Space, StringRef());
-}
-
-MCAsmLexer::~MCAsmLexer() = default;
-
-SMLoc MCAsmLexer::getLoc() const {
- return SMLoc::getFromPointer(TokStart);
-}
-
-SMLoc AsmToken::getLoc() const {
- return SMLoc::getFromPointer(Str.data());
-}
-
-SMLoc AsmToken::getEndLoc() const {
- return SMLoc::getFromPointer(Str.data() + Str.size());
-}
-
-SMRange AsmToken::getLocRange() const {
- return SMRange(getLoc(), getEndLoc());
-}
-
-void AsmToken::dump(raw_ostream &OS) const {
- switch (Kind) {
- case AsmToken::Error:
- OS << "error";
- break;
- case AsmToken::Identifier:
- OS << "identifier: " << getString();
- break;
- case AsmToken::Integer:
- OS << "int: " << getString();
- break;
- case AsmToken::Real:
- OS << "real: " << getString();
- break;
- case AsmToken::String:
- OS << "string: " << getString();
- break;
-
- case AsmToken::Amp: OS << "Amp"; break;
- case AsmToken::AmpAmp: OS << "AmpAmp"; break;
- case AsmToken::At: OS << "At"; break;
- case AsmToken::BackSlash: OS << "BackSlash"; break;
- case AsmToken::BigNum: OS << "BigNum"; break;
- case AsmToken::Caret: OS << "Caret"; break;
- case AsmToken::Colon: OS << "Colon"; break;
- case AsmToken::Comma: OS << "Comma"; break;
- case AsmToken::Comment: OS << "Comment"; break;
- case AsmToken::Dollar: OS << "Dollar"; break;
- case AsmToken::Dot: OS << "Dot"; break;
- case AsmToken::EndOfStatement: OS << "EndOfStatement"; break;
- case AsmToken::Eof: OS << "Eof"; break;
- case AsmToken::Equal: OS << "Equal"; break;
- case AsmToken::EqualEqual: OS << "EqualEqual"; break;
- case AsmToken::Exclaim: OS << "Exclaim"; break;
- case AsmToken::ExclaimEqual: OS << "ExclaimEqual"; break;
- case AsmToken::Greater: OS << "Greater"; break;
- case AsmToken::GreaterEqual: OS << "GreaterEqual"; break;
- case AsmToken::GreaterGreater: OS << "GreaterGreater"; break;
- case AsmToken::Hash: OS << "Hash"; break;
- case AsmToken::HashDirective: OS << "HashDirective"; break;
- case AsmToken::LBrac: OS << "LBrac"; break;
- case AsmToken::LCurly: OS << "LCurly"; break;
- case AsmToken::LParen: OS << "LParen"; break;
- case AsmToken::Less: OS << "Less"; break;
- case AsmToken::LessEqual: OS << "LessEqual"; break;
- case AsmToken::LessGreater: OS << "LessGreater"; break;
- case AsmToken::LessLess: OS << "LessLess"; break;
- case AsmToken::Minus: OS << "Minus"; break;
- case AsmToken::MinusGreater: OS << "MinusGreater"; break;
- case AsmToken::Percent: OS << "Percent"; break;
- case AsmToken::Pipe: OS << "Pipe"; break;
- case AsmToken::PipePipe: OS << "PipePipe"; break;
- case AsmToken::Plus: OS << "Plus"; break;
- case AsmToken::RBrac: OS << "RBrac"; break;
- case AsmToken::RCurly: OS << "RCurly"; break;
- case AsmToken::RParen: OS << "RParen"; break;
- case AsmToken::Slash: OS << "Slash"; break;
- case AsmToken::Space: OS << "Space"; break;
- case AsmToken::Star: OS << "Star"; break;
- case AsmToken::Tilde: OS << "Tilde"; break;
- case AsmToken::PercentCall16: OS << "PercentCall16"; break;
- case AsmToken::PercentCall_Hi: OS << "PercentCall_Hi"; break;
- case AsmToken::PercentCall_Lo: OS << "PercentCall_Lo"; break;
- case AsmToken::PercentDtprel_Hi: OS << "PercentDtprel_Hi"; break;
- case AsmToken::PercentDtprel_Lo: OS << "PercentDtprel_Lo"; break;
- case AsmToken::PercentGot: OS << "PercentGot"; break;
- case AsmToken::PercentGot_Disp: OS << "PercentGot_Disp"; break;
- case AsmToken::PercentGot_Hi: OS << "PercentGot_Hi"; break;
- case AsmToken::PercentGot_Lo: OS << "PercentGot_Lo"; break;
- case AsmToken::PercentGot_Ofst: OS << "PercentGot_Ofst"; break;
- case AsmToken::PercentGot_Page: OS << "PercentGot_Page"; break;
- case AsmToken::PercentGottprel: OS << "PercentGottprel"; break;
- case AsmToken::PercentGp_Rel: OS << "PercentGp_Rel"; break;
- case AsmToken::PercentHi: OS << "PercentHi"; break;
- case AsmToken::PercentHigher: OS << "PercentHigher"; break;
- case AsmToken::PercentHighest: OS << "PercentHighest"; break;
- case AsmToken::PercentLo: OS << "PercentLo"; break;
- case AsmToken::PercentNeg: OS << "PercentNeg"; break;
- case AsmToken::PercentPcrel_Hi: OS << "PercentPcrel_Hi"; break;
- case AsmToken::PercentPcrel_Lo: OS << "PercentPcrel_Lo"; break;
- case AsmToken::PercentTlsgd: OS << "PercentTlsgd"; break;
- case AsmToken::PercentTlsldm: OS << "PercentTlsldm"; break;
- case AsmToken::PercentTprel_Hi: OS << "PercentTprel_Hi"; break;
- case AsmToken::PercentTprel_Lo: OS << "PercentTprel_Lo"; break;
- }
-
- // Print the token string.
- OS << " (\"";
- OS.write_escaped(getString());
- OS << "\")";
-}
diff --git a/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp
deleted file mode 100644
index 41a1ee555d6f..000000000000
--- a/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-//===-- MCAsmParser.cpp - Abstract Asm Parser Interface -------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCParser/MCAsmParser.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/MC/MCParser/MCAsmLexer.h"
-#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
-#include "llvm/MC/MCParser/MCTargetAsmParser.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/SMLoc.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-
-using namespace llvm;
-
-MCAsmParser::MCAsmParser() {}
-
-MCAsmParser::~MCAsmParser() = default;
-
-void MCAsmParser::setTargetParser(MCTargetAsmParser &P) {
- assert(!TargetParser && "Target parser is already initialized!");
- TargetParser = &P;
- TargetParser->Initialize(*this);
-}
-
-const AsmToken &MCAsmParser::getTok() const {
- return getLexer().getTok();
-}
-
-bool MCAsmParser::parseTokenLoc(SMLoc &Loc) {
- Loc = getTok().getLoc();
- return false;
-}
-
-bool MCAsmParser::parseEOL(const Twine &Msg) {
- if (getTok().getKind() != AsmToken::EndOfStatement)
- return Error(getTok().getLoc(), Msg);
- Lex();
- return false;
-}
-
-bool MCAsmParser::parseToken(AsmToken::TokenKind T, const Twine &Msg) {
- if (T == AsmToken::EndOfStatement)
- return parseEOL(Msg);
- if (getTok().getKind() != T)
- return Error(getTok().getLoc(), Msg);
- Lex();
- return false;
-}
-
-bool MCAsmParser::parseIntToken(int64_t &V, const Twine &Msg) {
- if (getTok().getKind() != AsmToken::Integer)
- return TokError(Msg);
- V = getTok().getIntVal();
- Lex();
- return false;
-}
-
-bool MCAsmParser::parseOptionalToken(AsmToken::TokenKind T) {
- bool Present = (getTok().getKind() == T);
- if (Present)
- parseToken(T);
- return Present;
-}
-
-bool MCAsmParser::check(bool P, const Twine &Msg) {
- return check(P, getTok().getLoc(), Msg);
-}
-
-bool MCAsmParser::check(bool P, SMLoc Loc, const Twine &Msg) {
- if (P)
- return Error(Loc, Msg);
- return false;
-}
-
-bool MCAsmParser::TokError(const Twine &Msg, SMRange Range) {
- return Error(getLexer().getLoc(), Msg, Range);
-}
-
-bool MCAsmParser::Error(SMLoc L, const Twine &Msg, SMRange Range) {
-
- MCPendingError PErr;
- PErr.Loc = L;
- Msg.toVector(PErr.Msg);
- PErr.Range = Range;
- PendingErrors.push_back(PErr);
-
- // If we threw this parsing error after a lexing error, this should
- // supercede the lexing error and so we remove it from the Lexer
- // before it can propagate
- if (getTok().is(AsmToken::Error))
- getLexer().Lex();
- return true;
-}
-
-bool MCAsmParser::addErrorSuffix(const Twine &Suffix) {
- // Make sure lexing errors have propagated to the parser.
- if (getTok().is(AsmToken::Error))
- Lex();
- for (auto &PErr : PendingErrors)
- Suffix.toVector(PErr.Msg);
- return true;
-}
-
-bool MCAsmParser::parseMany(function_ref<bool()> parseOne, bool hasComma) {
- if (parseOptionalToken(AsmToken::EndOfStatement))
- return false;
- while (true) {
- if (parseOne())
- return true;
- if (parseOptionalToken(AsmToken::EndOfStatement))
- return false;
- if (hasComma && parseToken(AsmToken::Comma))
- return true;
- }
- return false;
-}
-
-bool MCAsmParser::parseExpression(const MCExpr *&Res) {
- SMLoc L;
- return parseExpression(Res, L);
-}
-
-void MCParsedAsmOperand::dump() const {
- // Cannot completely remove virtual function even in release mode.
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
- dbgs() << " " << *this;
-#endif
-}
diff --git a/contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp b/contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp
deleted file mode 100644
index 18d18f0cf6ed..000000000000
--- a/contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-//===- MCAsmParserExtension.cpp - Asm Parser Hooks ------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCParser/MCAsmParserExtension.h"
-
-using namespace llvm;
-
-MCAsmParserExtension::MCAsmParserExtension() = default;
-
-MCAsmParserExtension::~MCAsmParserExtension() = default;
-
-void MCAsmParserExtension::Initialize(MCAsmParser &Parser) {
- this->Parser = &Parser;
-}
diff --git a/contrib/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp
deleted file mode 100644
index 940f26d4750b..000000000000
--- a/contrib/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-//===-- MCTargetAsmParser.cpp - Target Assembly Parser --------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCParser/MCTargetAsmParser.h"
-#include "llvm/MC/MCContext.h"
-
-using namespace llvm;
-
-MCTargetAsmParser::MCTargetAsmParser(MCTargetOptions const &MCOptions,
- const MCSubtargetInfo &STI,
- const MCInstrInfo &MII)
- : MCOptions(MCOptions), STI(&STI), MII(MII) {}
-
-MCTargetAsmParser::~MCTargetAsmParser() = default;
-
-MCSubtargetInfo &MCTargetAsmParser::copySTI() {
- MCSubtargetInfo &STICopy = getContext().getSubtargetCopy(getSTI());
- STI = &STICopy;
- return STICopy;
-}
-
-const MCSubtargetInfo &MCTargetAsmParser::getSTI() const {
- return *STI;
-}
diff --git a/contrib/llvm/lib/MC/MCParser/WasmAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/WasmAsmParser.cpp
deleted file mode 100644
index 28d4459fecd4..000000000000
--- a/contrib/llvm/lib/MC/MCParser/WasmAsmParser.cpp
+++ /dev/null
@@ -1,255 +0,0 @@
-//===- WasmAsmParser.cpp - Wasm Assembly Parser -----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// --
-//
-// Note, this is for wasm, the binary format (analogous to ELF), not wasm,
-// the instruction set (analogous to x86), for which parsing code lives in
-// WebAssemblyAsmParser.
-//
-// This file contains processing for generic directives implemented using
-// MCTargetStreamer, the ones that depend on WebAssemblyTargetStreamer are in
-// WebAssemblyAsmParser.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/BinaryFormat/Wasm.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCParser/MCAsmLexer.h"
-#include "llvm/MC/MCParser/MCAsmParser.h"
-#include "llvm/MC/MCParser/MCAsmParserExtension.h"
-#include "llvm/MC/MCSectionWasm.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCSymbolWasm.h"
-#include "llvm/Support/MachineValueType.h"
-
-using namespace llvm;
-
-namespace {
-
-class WasmAsmParser : public MCAsmParserExtension {
- MCAsmParser *Parser = nullptr;
- MCAsmLexer *Lexer = nullptr;
-
- template<bool (WasmAsmParser::*HandlerMethod)(StringRef, SMLoc)>
- void addDirectiveHandler(StringRef Directive) {
- MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
- this, HandleDirective<WasmAsmParser, HandlerMethod>);
-
- getParser().addDirectiveHandler(Directive, Handler);
- }
-
-public:
- WasmAsmParser() { BracketExpressionsSupported = true; }
-
- void Initialize(MCAsmParser &P) override {
- Parser = &P;
- Lexer = &Parser->getLexer();
- // Call the base implementation.
- this->MCAsmParserExtension::Initialize(*Parser);
-
- addDirectiveHandler<&WasmAsmParser::parseSectionDirectiveText>(".text");
- addDirectiveHandler<&WasmAsmParser::parseSectionDirective>(".section");
- addDirectiveHandler<&WasmAsmParser::parseDirectiveSize>(".size");
- addDirectiveHandler<&WasmAsmParser::parseDirectiveType>(".type");
- addDirectiveHandler<&WasmAsmParser::ParseDirectiveIdent>(".ident");
- addDirectiveHandler<
- &WasmAsmParser::ParseDirectiveSymbolAttribute>(".weak");
- addDirectiveHandler<
- &WasmAsmParser::ParseDirectiveSymbolAttribute>(".local");
- addDirectiveHandler<
- &WasmAsmParser::ParseDirectiveSymbolAttribute>(".internal");
- addDirectiveHandler<
- &WasmAsmParser::ParseDirectiveSymbolAttribute>(".hidden");
- }
-
- bool error(const StringRef &Msg, const AsmToken &Tok) {
- return Parser->Error(Tok.getLoc(), Msg + Tok.getString());
- }
-
- bool isNext(AsmToken::TokenKind Kind) {
- auto Ok = Lexer->is(Kind);
- if (Ok)
- Lex();
- return Ok;
- }
-
- bool expect(AsmToken::TokenKind Kind, const char *KindName) {
- if (!isNext(Kind))
- return error(std::string("Expected ") + KindName + ", instead got: ",
- Lexer->getTok());
- return false;
- }
-
- bool parseSectionDirectiveText(StringRef, SMLoc) {
- // FIXME: .text currently no-op.
- return false;
- }
-
- bool parseSectionFlags(StringRef FlagStr, bool &Passive) {
- SmallVector<StringRef, 2> Flags;
- // If there are no flags, keep Flags empty
- FlagStr.split(Flags, ",", -1, false);
- for (auto &Flag : Flags) {
- if (Flag == "passive")
- Passive = true;
- else
- return error("Expected section flags, instead got: ", Lexer->getTok());
- }
- return false;
- }
-
- bool parseSectionDirective(StringRef, SMLoc) {
- StringRef Name;
- if (Parser->parseIdentifier(Name))
- return TokError("expected identifier in directive");
-
- if (expect(AsmToken::Comma, ","))
- return true;
-
- if (Lexer->isNot(AsmToken::String))
- return error("expected string in directive, instead got: ", Lexer->getTok());
-
- auto Kind = StringSwitch<Optional<SectionKind>>(Name)
- .StartsWith(".data", SectionKind::getData())
- .StartsWith(".rodata", SectionKind::getReadOnly())
- .StartsWith(".text", SectionKind::getText())
- .StartsWith(".custom_section", SectionKind::getMetadata())
- .StartsWith(".bss", SectionKind::getBSS())
- // See use of .init_array in WasmObjectWriter and
- // TargetLoweringObjectFileWasm
- .StartsWith(".init_array", SectionKind::getData())
- .Default(Optional<SectionKind>());
- if (!Kind.hasValue())
- return Parser->Error(Lexer->getLoc(), "unknown section kind: " + Name);
-
- MCSectionWasm *Section = getContext().getWasmSection(Name, Kind.getValue());
-
- // Update section flags if present in this .section directive
- bool Passive = false;
- if (parseSectionFlags(getTok().getStringContents(), Passive))
- return true;
-
- if (Passive) {
- if (!Section->isWasmData())
- return Parser->Error(getTok().getLoc(),
- "Only data sections can be passive");
- Section->setPassive();
- }
-
- Lex();
-
- if (expect(AsmToken::Comma, ",") || expect(AsmToken::At, "@") ||
- expect(AsmToken::EndOfStatement, "eol"))
- return true;
-
- auto WS = getContext().getWasmSection(Name, Kind.getValue());
- getStreamer().SwitchSection(WS);
- return false;
- }
-
- // TODO: This function is almost the same as ELFAsmParser::ParseDirectiveSize
- // so maybe could be shared somehow.
- bool parseDirectiveSize(StringRef, SMLoc) {
- StringRef Name;
- if (Parser->parseIdentifier(Name))
- return TokError("expected identifier in directive");
- auto Sym = getContext().getOrCreateSymbol(Name);
- if (expect(AsmToken::Comma, ","))
- return true;
- const MCExpr *Expr;
- if (Parser->parseExpression(Expr))
- return true;
- if (expect(AsmToken::EndOfStatement, "eol"))
- return true;
- // This is done automatically by the assembler for functions currently,
- // so this is only currently needed for data sections:
- getStreamer().emitELFSize(Sym, Expr);
- return false;
- }
-
- bool parseDirectiveType(StringRef, SMLoc) {
- // This could be the start of a function, check if followed by
- // "label,@function"
- if (!Lexer->is(AsmToken::Identifier))
- return error("Expected label after .type directive, got: ",
- Lexer->getTok());
- auto WasmSym = cast<MCSymbolWasm>(
- getStreamer().getContext().getOrCreateSymbol(
- Lexer->getTok().getString()));
- Lex();
- if (!(isNext(AsmToken::Comma) && isNext(AsmToken::At) &&
- Lexer->is(AsmToken::Identifier)))
- return error("Expected label,@type declaration, got: ", Lexer->getTok());
- auto TypeName = Lexer->getTok().getString();
- if (TypeName == "function")
- WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
- else if (TypeName == "global")
- WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
- else if (TypeName == "object")
- WasmSym->setType(wasm::WASM_SYMBOL_TYPE_DATA);
- else
- return error("Unknown WASM symbol type: ", Lexer->getTok());
- Lex();
- return expect(AsmToken::EndOfStatement, "EOL");
- }
-
- // FIXME: Shared with ELF.
- /// ParseDirectiveIdent
- /// ::= .ident string
- bool ParseDirectiveIdent(StringRef, SMLoc) {
- if (getLexer().isNot(AsmToken::String))
- return TokError("unexpected token in '.ident' directive");
- StringRef Data = getTok().getIdentifier();
- Lex();
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in '.ident' directive");
- Lex();
- getStreamer().EmitIdent(Data);
- return false;
- }
-
- // FIXME: Shared with ELF.
- /// ParseDirectiveSymbolAttribute
- /// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ]
- bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
- MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
- .Case(".weak", MCSA_Weak)
- .Case(".local", MCSA_Local)
- .Case(".hidden", MCSA_Hidden)
- .Case(".internal", MCSA_Internal)
- .Case(".protected", MCSA_Protected)
- .Default(MCSA_Invalid);
- assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- while (true) {
- StringRef Name;
- if (getParser().parseIdentifier(Name))
- return TokError("expected identifier in directive");
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- getStreamer().EmitSymbolAttribute(Sym, Attr);
- if (getLexer().is(AsmToken::EndOfStatement))
- break;
- if (getLexer().isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
- }
- }
- Lex();
- return false;
- }
-};
-
-} // end anonymous namespace
-
-namespace llvm {
-
-MCAsmParserExtension *createWasmAsmParser() {
- return new WasmAsmParser;
-}
-
-} // end namespace llvm
diff --git a/contrib/llvm/lib/MC/MCRegisterInfo.cpp b/contrib/llvm/lib/MC/MCRegisterInfo.cpp
deleted file mode 100644
index 4273b876b7bb..000000000000
--- a/contrib/llvm/lib/MC/MCRegisterInfo.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-//===- MC/MCRegisterInfo.cpp - Target Register Description ----------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements MCRegisterInfo functions.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <algorithm>
-#include <cassert>
-#include <cstdint>
-
-using namespace llvm;
-
-unsigned MCRegisterInfo::getMatchingSuperReg(unsigned Reg, unsigned SubIdx,
- const MCRegisterClass *RC) const {
- for (MCSuperRegIterator Supers(Reg, this); Supers.isValid(); ++Supers)
- if (RC->contains(*Supers) && Reg == getSubReg(*Supers, SubIdx))
- return *Supers;
- return 0;
-}
-
-unsigned MCRegisterInfo::getSubReg(unsigned Reg, unsigned Idx) const {
- assert(Idx && Idx < getNumSubRegIndices() &&
- "This is not a subregister index");
- // Get a pointer to the corresponding SubRegIndices list. This list has the
- // name of each sub-register in the same order as MCSubRegIterator.
- const uint16_t *SRI = SubRegIndices + get(Reg).SubRegIndices;
- for (MCSubRegIterator Subs(Reg, this); Subs.isValid(); ++Subs, ++SRI)
- if (*SRI == Idx)
- return *Subs;
- return 0;
-}
-
-unsigned MCRegisterInfo::getSubRegIndex(unsigned Reg, unsigned SubReg) const {
- assert(SubReg && SubReg < getNumRegs() && "This is not a register");
- // Get a pointer to the corresponding SubRegIndices list. This list has the
- // name of each sub-register in the same order as MCSubRegIterator.
- const uint16_t *SRI = SubRegIndices + get(Reg).SubRegIndices;
- for (MCSubRegIterator Subs(Reg, this); Subs.isValid(); ++Subs, ++SRI)
- if (*Subs == SubReg)
- return *SRI;
- return 0;
-}
-
-unsigned MCRegisterInfo::getSubRegIdxSize(unsigned Idx) const {
- assert(Idx && Idx < getNumSubRegIndices() &&
- "This is not a subregister index");
- return SubRegIdxRanges[Idx].Size;
-}
-
-unsigned MCRegisterInfo::getSubRegIdxOffset(unsigned Idx) const {
- assert(Idx && Idx < getNumSubRegIndices() &&
- "This is not a subregister index");
- return SubRegIdxRanges[Idx].Offset;
-}
-
-int MCRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
- const DwarfLLVMRegPair *M = isEH ? EHL2DwarfRegs : L2DwarfRegs;
- unsigned Size = isEH ? EHL2DwarfRegsSize : L2DwarfRegsSize;
-
- if (!M)
- return -1;
- DwarfLLVMRegPair Key = { RegNum, 0 };
- const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, Key);
- if (I == M+Size || I->FromReg != RegNum)
- return -1;
- return I->ToReg;
-}
-
-int MCRegisterInfo::getLLVMRegNum(unsigned RegNum, bool isEH) const {
- const DwarfLLVMRegPair *M = isEH ? EHDwarf2LRegs : Dwarf2LRegs;
- unsigned Size = isEH ? EHDwarf2LRegsSize : Dwarf2LRegsSize;
-
- if (!M)
- return -1;
- DwarfLLVMRegPair Key = { RegNum, 0 };
- const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, Key);
- assert(I != M+Size && I->FromReg == RegNum && "Invalid RegNum");
- return I->ToReg;
-}
-
-int MCRegisterInfo::getLLVMRegNumFromEH(unsigned RegNum) const {
- const DwarfLLVMRegPair *M = EHDwarf2LRegs;
- unsigned Size = EHDwarf2LRegsSize;
-
- if (!M)
- return -1;
- DwarfLLVMRegPair Key = { RegNum, 0 };
- const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, Key);
- if (I == M+Size || I->FromReg != RegNum)
- return -1;
- return I->ToReg;
-}
-
-int MCRegisterInfo::getDwarfRegNumFromDwarfEHRegNum(unsigned RegNum) const {
- // On ELF platforms, DWARF EH register numbers are the same as DWARF
- // other register numbers. On Darwin x86, they differ and so need to be
- // mapped. The .cfi_* directives accept integer literals as well as
- // register names and should generate exactly what the assembly code
- // asked for, so there might be DWARF/EH register numbers that don't have
- // a corresponding LLVM register number at all. So if we can't map the
- // EH register number to an LLVM register number, assume it's just a
- // valid DWARF register number as is.
- int LRegNum = getLLVMRegNumFromEH(RegNum);
- if (LRegNum != -1)
- return getDwarfRegNum(LRegNum, false);
- return RegNum;
-}
-
-int MCRegisterInfo::getSEHRegNum(unsigned RegNum) const {
- const DenseMap<unsigned, int>::const_iterator I = L2SEHRegs.find(RegNum);
- if (I == L2SEHRegs.end()) return (int)RegNum;
- return I->second;
-}
-
-int MCRegisterInfo::getCodeViewRegNum(unsigned RegNum) const {
- if (L2CVRegs.empty())
- report_fatal_error("target does not implement codeview register mapping");
- const DenseMap<unsigned, int>::const_iterator I = L2CVRegs.find(RegNum);
- if (I == L2CVRegs.end())
- report_fatal_error("unknown codeview register " + (RegNum < getNumRegs()
- ? getName(RegNum)
- : Twine(RegNum)));
- return I->second;
-}
diff --git a/contrib/llvm/lib/MC/MCSchedule.cpp b/contrib/llvm/lib/MC/MCSchedule.cpp
deleted file mode 100644
index 1fc5ec5e975f..000000000000
--- a/contrib/llvm/lib/MC/MCSchedule.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-//===- MCSchedule.cpp - Scheduling ------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the default scheduling model.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCSchedule.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCInstrDesc.h"
-#include "llvm/MC/MCInstrInfo.h"
-#include "llvm/MC/MCSubtargetInfo.h"
-#include <type_traits>
-
-using namespace llvm;
-
-static_assert(std::is_pod<MCSchedModel>::value,
- "We shouldn't have a static constructor here");
-const MCSchedModel MCSchedModel::Default = {DefaultIssueWidth,
- DefaultMicroOpBufferSize,
- DefaultLoopMicroOpBufferSize,
- DefaultLoadLatency,
- DefaultHighLatency,
- DefaultMispredictPenalty,
- false,
- true,
- 0,
- nullptr,
- nullptr,
- 0,
- 0,
- nullptr,
- nullptr};
-
-int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
- const MCSchedClassDesc &SCDesc) {
- int Latency = 0;
- for (unsigned DefIdx = 0, DefEnd = SCDesc.NumWriteLatencyEntries;
- DefIdx != DefEnd; ++DefIdx) {
- // Lookup the definition's write latency in SubtargetInfo.
- const MCWriteLatencyEntry *WLEntry =
- STI.getWriteLatencyEntry(&SCDesc, DefIdx);
- // Early exit if we found an invalid latency.
- if (WLEntry->Cycles < 0)
- return WLEntry->Cycles;
- Latency = std::max(Latency, static_cast<int>(WLEntry->Cycles));
- }
- return Latency;
-}
-
-int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
- unsigned SchedClass) const {
- const MCSchedClassDesc &SCDesc = *getSchedClassDesc(SchedClass);
- if (!SCDesc.isValid())
- return 0;
- if (!SCDesc.isVariant())
- return MCSchedModel::computeInstrLatency(STI, SCDesc);
-
- llvm_unreachable("unsupported variant scheduling class");
-}
-
-int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
- const MCInstrInfo &MCII,
- const MCInst &Inst) const {
- unsigned SchedClass = MCII.get(Inst.getOpcode()).getSchedClass();
- const MCSchedClassDesc *SCDesc = getSchedClassDesc(SchedClass);
- if (!SCDesc->isValid())
- return 0;
-
- unsigned CPUID = getProcessorID();
- while (SCDesc->isVariant()) {
- SchedClass = STI.resolveVariantSchedClass(SchedClass, &Inst, CPUID);
- SCDesc = getSchedClassDesc(SchedClass);
- }
-
- if (SchedClass)
- return MCSchedModel::computeInstrLatency(STI, *SCDesc);
-
- llvm_unreachable("unsupported variant scheduling class");
-}
-
-double
-MCSchedModel::getReciprocalThroughput(const MCSubtargetInfo &STI,
- const MCSchedClassDesc &SCDesc) {
- Optional<double> Throughput;
- const MCSchedModel &SM = STI.getSchedModel();
- const MCWriteProcResEntry *I = STI.getWriteProcResBegin(&SCDesc);
- const MCWriteProcResEntry *E = STI.getWriteProcResEnd(&SCDesc);
- for (; I != E; ++I) {
- if (!I->Cycles)
- continue;
- unsigned NumUnits = SM.getProcResource(I->ProcResourceIdx)->NumUnits;
- double Temp = NumUnits * 1.0 / I->Cycles;
- Throughput = Throughput ? std::min(Throughput.getValue(), Temp) : Temp;
- }
- if (Throughput.hasValue())
- return 1.0 / Throughput.getValue();
-
- // If no throughput value was calculated, assume that we can execute at the
- // maximum issue width scaled by number of micro-ops for the schedule class.
- return ((double)SCDesc.NumMicroOps) / SM.IssueWidth;
-}
-
-double
-MCSchedModel::getReciprocalThroughput(const MCSubtargetInfo &STI,
- const MCInstrInfo &MCII,
- const MCInst &Inst) const {
- unsigned SchedClass = MCII.get(Inst.getOpcode()).getSchedClass();
- const MCSchedClassDesc *SCDesc = getSchedClassDesc(SchedClass);
-
- // If there's no valid class, assume that the instruction executes/completes
- // at the maximum issue width.
- if (!SCDesc->isValid())
- return 1.0 / IssueWidth;
-
- unsigned CPUID = getProcessorID();
- while (SCDesc->isVariant()) {
- SchedClass = STI.resolveVariantSchedClass(SchedClass, &Inst, CPUID);
- SCDesc = getSchedClassDesc(SchedClass);
- }
-
- if (SchedClass)
- return MCSchedModel::getReciprocalThroughput(STI, *SCDesc);
-
- llvm_unreachable("unsupported variant scheduling class");
-}
-
-double
-MCSchedModel::getReciprocalThroughput(unsigned SchedClass,
- const InstrItineraryData &IID) {
- Optional<double> Throughput;
- const InstrStage *I = IID.beginStage(SchedClass);
- const InstrStage *E = IID.endStage(SchedClass);
- for (; I != E; ++I) {
- if (!I->getCycles())
- continue;
- double Temp = countPopulation(I->getUnits()) * 1.0 / I->getCycles();
- Throughput = Throughput ? std::min(Throughput.getValue(), Temp) : Temp;
- }
- if (Throughput.hasValue())
- return 1.0 / Throughput.getValue();
-
- // If there are no execution resources specified for this class, then assume
- // that it can execute at the maximum default issue width.
- return 1.0 / DefaultIssueWidth;
-}
-
-unsigned
-MCSchedModel::getForwardingDelayCycles(ArrayRef<MCReadAdvanceEntry> Entries,
- unsigned WriteResourceID) {
- if (Entries.empty())
- return 0;
-
- int DelayCycles = 0;
- for (const MCReadAdvanceEntry &E : Entries) {
- if (E.WriteResourceID != WriteResourceID)
- continue;
- DelayCycles = std::min(DelayCycles, E.Cycles);
- }
-
- return std::abs(DelayCycles);
-}
diff --git a/contrib/llvm/lib/MC/MCSection.cpp b/contrib/llvm/lib/MC/MCSection.cpp
deleted file mode 100644
index 2c892ab81608..000000000000
--- a/contrib/llvm/lib/MC/MCSection.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-//===- lib/MC/MCSection.cpp - Machine Code Section Representation ---------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCSection.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCFragment.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <utility>
-
-using namespace llvm;
-
-MCSection::MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin)
- : Begin(Begin), BundleGroupBeforeFirstInst(false), HasInstructions(false),
- HasData(false), IsRegistered(false), DummyFragment(this), Variant(V),
- Kind(K) {}
-
-MCSymbol *MCSection::getEndSymbol(MCContext &Ctx) {
- if (!End)
- End = Ctx.createTempSymbol("sec_end", true);
- return End;
-}
-
-bool MCSection::hasEnded() const { return End && End->isInSection(); }
-
-MCSection::~MCSection() = default;
-
-void MCSection::setBundleLockState(BundleLockStateType NewState) {
- if (NewState == NotBundleLocked) {
- if (BundleLockNestingDepth == 0) {
- report_fatal_error("Mismatched bundle_lock/unlock directives");
- }
- if (--BundleLockNestingDepth == 0) {
- BundleLockState = NotBundleLocked;
- }
- return;
- }
-
- // If any of the directives is an align_to_end directive, the whole nested
- // group is align_to_end. So don't downgrade from align_to_end to just locked.
- if (BundleLockState != BundleLockedAlignToEnd) {
- BundleLockState = NewState;
- }
- ++BundleLockNestingDepth;
-}
-
-MCSection::iterator
-MCSection::getSubsectionInsertionPoint(unsigned Subsection) {
- if (Subsection == 0 && SubsectionFragmentMap.empty())
- return end();
-
- SmallVectorImpl<std::pair<unsigned, MCFragment *>>::iterator MI =
- std::lower_bound(SubsectionFragmentMap.begin(),
- SubsectionFragmentMap.end(),
- std::make_pair(Subsection, (MCFragment *)nullptr));
- bool ExactMatch = false;
- if (MI != SubsectionFragmentMap.end()) {
- ExactMatch = MI->first == Subsection;
- if (ExactMatch)
- ++MI;
- }
- iterator IP;
- if (MI == SubsectionFragmentMap.end())
- IP = end();
- else
- IP = MI->second->getIterator();
- if (!ExactMatch && Subsection != 0) {
- // The GNU as documentation claims that subsections have an alignment of 4,
- // although this appears not to be the case.
- MCFragment *F = new MCDataFragment();
- SubsectionFragmentMap.insert(MI, std::make_pair(Subsection, F));
- getFragmentList().insert(IP, F);
- F->setParent(this);
- }
-
- return IP;
-}
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void MCSection::dump() const {
- raw_ostream &OS = errs();
-
- OS << "<MCSection";
- OS << " Fragments:[\n ";
- for (auto it = begin(), ie = end(); it != ie; ++it) {
- if (it != begin())
- OS << ",\n ";
- it->dump();
- }
- OS << "]>";
-}
-#endif
diff --git a/contrib/llvm/lib/MC/MCSectionCOFF.cpp b/contrib/llvm/lib/MC/MCSectionCOFF.cpp
deleted file mode 100644
index f0c06f70bd73..000000000000
--- a/contrib/llvm/lib/MC/MCSectionCOFF.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-//===- lib/MC/MCSectionCOFF.cpp - COFF Code Section Representation --------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCSectionCOFF.h"
-#include "llvm/BinaryFormat/COFF.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-
-using namespace llvm;
-
-// ShouldOmitSectionDirective - Decides whether a '.section' directive
-// should be printed before the section name
-bool MCSectionCOFF::ShouldOmitSectionDirective(StringRef Name,
- const MCAsmInfo &MAI) const {
- if (COMDATSymbol)
- return false;
-
- // FIXME: Does .section .bss/.data/.text work everywhere??
- if (Name == ".text" || Name == ".data" || Name == ".bss")
- return true;
-
- return false;
-}
-
-void MCSectionCOFF::setSelection(int Selection) const {
- assert(Selection != 0 && "invalid COMDAT selection type");
- this->Selection = Selection;
- Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
-}
-
-void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
- raw_ostream &OS,
- const MCExpr *Subsection) const {
- // standard sections don't require the '.section'
- if (ShouldOmitSectionDirective(SectionName, MAI)) {
- OS << '\t' << getSectionName() << '\n';
- return;
- }
-
- OS << "\t.section\t" << getSectionName() << ",\"";
- if (getCharacteristics() & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
- OS << 'd';
- if (getCharacteristics() & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
- OS << 'b';
- if (getCharacteristics() & COFF::IMAGE_SCN_MEM_EXECUTE)
- OS << 'x';
- if (getCharacteristics() & COFF::IMAGE_SCN_MEM_WRITE)
- OS << 'w';
- else if (getCharacteristics() & COFF::IMAGE_SCN_MEM_READ)
- OS << 'r';
- else
- OS << 'y';
- if (getCharacteristics() & COFF::IMAGE_SCN_LNK_REMOVE)
- OS << 'n';
- if (getCharacteristics() & COFF::IMAGE_SCN_MEM_SHARED)
- OS << 's';
- if ((getCharacteristics() & COFF::IMAGE_SCN_MEM_DISCARDABLE) &&
- !isImplicitlyDiscardable(SectionName))
- OS << 'D';
- OS << '"';
-
- if (getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) {
- if (COMDATSymbol)
- OS << ",";
- else
- OS << "\n\t.linkonce\t";
- switch (Selection) {
- case COFF::IMAGE_COMDAT_SELECT_NODUPLICATES:
- OS << "one_only";
- break;
- case COFF::IMAGE_COMDAT_SELECT_ANY:
- OS << "discard";
- break;
- case COFF::IMAGE_COMDAT_SELECT_SAME_SIZE:
- OS << "same_size";
- break;
- case COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH:
- OS << "same_contents";
- break;
- case COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE:
- OS << "associative";
- break;
- case COFF::IMAGE_COMDAT_SELECT_LARGEST:
- OS << "largest";
- break;
- case COFF::IMAGE_COMDAT_SELECT_NEWEST:
- OS << "newest";
- break;
- default:
- assert(false && "unsupported COFF selection type");
- break;
- }
- if (COMDATSymbol) {
- OS << ",";
- COMDATSymbol->print(OS, &MAI);
- }
- }
- OS << '\n';
-}
-
-bool MCSectionCOFF::UseCodeAlign() const {
- return getKind().isText();
-}
-
-bool MCSectionCOFF::isVirtualSection() const {
- return getCharacteristics() & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
-}
diff --git a/contrib/llvm/lib/MC/MCSectionELF.cpp b/contrib/llvm/lib/MC/MCSectionELF.cpp
deleted file mode 100644
index efe504b2024c..000000000000
--- a/contrib/llvm/lib/MC/MCSectionELF.cpp
+++ /dev/null
@@ -1,198 +0,0 @@
-//===- lib/MC/MCSectionELF.cpp - ELF Code Section Representation ----------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCSectionELF.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-
-using namespace llvm;
-
-// Decides whether a '.section' directive
-// should be printed before the section name.
-bool MCSectionELF::ShouldOmitSectionDirective(StringRef Name,
- const MCAsmInfo &MAI) const {
- if (isUnique())
- return false;
-
- return MAI.shouldOmitSectionDirective(Name);
-}
-
-static void printName(raw_ostream &OS, StringRef Name) {
- if (Name.find_first_not_of("0123456789_."
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == Name.npos) {
- OS << Name;
- return;
- }
- OS << '"';
- for (const char *B = Name.begin(), *E = Name.end(); B < E; ++B) {
- if (*B == '"') // Unquoted "
- OS << "\\\"";
- else if (*B != '\\') // Neither " or backslash
- OS << *B;
- else if (B + 1 == E) // Trailing backslash
- OS << "\\\\";
- else {
- OS << B[0] << B[1]; // Quoted character
- ++B;
- }
- }
- OS << '"';
-}
-
-void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
- raw_ostream &OS,
- const MCExpr *Subsection) const {
- if (ShouldOmitSectionDirective(SectionName, MAI)) {
- OS << '\t' << getSectionName();
- if (Subsection) {
- OS << '\t';
- Subsection->print(OS, &MAI);
- }
- OS << '\n';
- return;
- }
-
- OS << "\t.section\t";
- printName(OS, getSectionName());
-
- // Handle the weird solaris syntax if desired.
- if (MAI.usesSunStyleELFSectionSwitchSyntax() &&
- !(Flags & ELF::SHF_MERGE)) {
- if (Flags & ELF::SHF_ALLOC)
- OS << ",#alloc";
- if (Flags & ELF::SHF_EXECINSTR)
- OS << ",#execinstr";
- if (Flags & ELF::SHF_WRITE)
- OS << ",#write";
- if (Flags & ELF::SHF_EXCLUDE)
- OS << ",#exclude";
- if (Flags & ELF::SHF_TLS)
- OS << ",#tls";
- OS << '\n';
- return;
- }
-
- OS << ",\"";
- if (Flags & ELF::SHF_ALLOC)
- OS << 'a';
- if (Flags & ELF::SHF_EXCLUDE)
- OS << 'e';
- if (Flags & ELF::SHF_EXECINSTR)
- OS << 'x';
- if (Flags & ELF::SHF_GROUP)
- OS << 'G';
- if (Flags & ELF::SHF_WRITE)
- OS << 'w';
- if (Flags & ELF::SHF_MERGE)
- OS << 'M';
- if (Flags & ELF::SHF_STRINGS)
- OS << 'S';
- if (Flags & ELF::SHF_TLS)
- OS << 'T';
- if (Flags & ELF::SHF_LINK_ORDER)
- OS << 'o';
-
- // If there are target-specific flags, print them.
- Triple::ArchType Arch = T.getArch();
- if (Arch == Triple::xcore) {
- if (Flags & ELF::XCORE_SHF_CP_SECTION)
- OS << 'c';
- if (Flags & ELF::XCORE_SHF_DP_SECTION)
- OS << 'd';
- } else if (T.isARM() || T.isThumb()) {
- if (Flags & ELF::SHF_ARM_PURECODE)
- OS << 'y';
- } else if (Arch == Triple::hexagon) {
- if (Flags & ELF::SHF_HEX_GPREL)
- OS << 's';
- }
-
- OS << '"';
-
- OS << ',';
-
- // If comment string is '@', e.g. as on ARM - use '%' instead
- if (MAI.getCommentString()[0] == '@')
- OS << '%';
- else
- OS << '@';
-
- if (Type == ELF::SHT_INIT_ARRAY)
- OS << "init_array";
- else if (Type == ELF::SHT_FINI_ARRAY)
- OS << "fini_array";
- else if (Type == ELF::SHT_PREINIT_ARRAY)
- OS << "preinit_array";
- else if (Type == ELF::SHT_NOBITS)
- OS << "nobits";
- else if (Type == ELF::SHT_NOTE)
- OS << "note";
- else if (Type == ELF::SHT_PROGBITS)
- OS << "progbits";
- else if (Type == ELF::SHT_X86_64_UNWIND)
- OS << "unwind";
- else if (Type == ELF::SHT_MIPS_DWARF)
- // Print hex value of the flag while we do not have
- // any standard symbolic representation of the flag.
- OS << "0x7000001e";
- else if (Type == ELF::SHT_LLVM_ODRTAB)
- OS << "llvm_odrtab";
- else if (Type == ELF::SHT_LLVM_LINKER_OPTIONS)
- OS << "llvm_linker_options";
- else if (Type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE)
- OS << "llvm_call_graph_profile";
- else if (Type == ELF::SHT_LLVM_DEPENDENT_LIBRARIES)
- OS << "llvm_dependent_libraries";
- else if (Type == ELF::SHT_LLVM_SYMPART)
- OS << "llvm_sympart";
- else
- report_fatal_error("unsupported type 0x" + Twine::utohexstr(Type) +
- " for section " + getSectionName());
-
- if (EntrySize) {
- assert(Flags & ELF::SHF_MERGE);
- OS << "," << EntrySize;
- }
-
- if (Flags & ELF::SHF_GROUP) {
- OS << ",";
- printName(OS, Group->getName());
- OS << ",comdat";
- }
-
- if (Flags & ELF::SHF_LINK_ORDER) {
- assert(AssociatedSymbol);
- OS << ",";
- printName(OS, AssociatedSymbol->getName());
- }
-
- if (isUnique())
- OS << ",unique," << UniqueID;
-
- OS << '\n';
-
- if (Subsection) {
- OS << "\t.subsection\t";
- Subsection->print(OS, &MAI);
- OS << '\n';
- }
-}
-
-bool MCSectionELF::UseCodeAlign() const {
- return getFlags() & ELF::SHF_EXECINSTR;
-}
-
-bool MCSectionELF::isVirtualSection() const {
- return getType() == ELF::SHT_NOBITS;
-}
diff --git a/contrib/llvm/lib/MC/MCSectionMachO.cpp b/contrib/llvm/lib/MC/MCSectionMachO.cpp
deleted file mode 100644
index 0fd89dcbe5fa..000000000000
--- a/contrib/llvm/lib/MC/MCSectionMachO.cpp
+++ /dev/null
@@ -1,281 +0,0 @@
-//===- lib/MC/MCSectionMachO.cpp - MachO Code Section Representation ------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCSectionMachO.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cctype>
-using namespace llvm;
-
-/// SectionTypeDescriptors - These are strings that describe the various section
-/// types. This *must* be kept in order with and stay synchronized with the
-/// section type list.
-static constexpr struct {
- StringLiteral AssemblerName, EnumName;
-} SectionTypeDescriptors[MachO::LAST_KNOWN_SECTION_TYPE + 1] = {
- {StringLiteral("regular"), StringLiteral("S_REGULAR")}, // 0x00
- {StringLiteral(""), StringLiteral("S_ZEROFILL")}, // 0x01
- {StringLiteral("cstring_literals"),
- StringLiteral("S_CSTRING_LITERALS")}, // 0x02
- {StringLiteral("4byte_literals"),
- StringLiteral("S_4BYTE_LITERALS")}, // 0x03
- {StringLiteral("8byte_literals"),
- StringLiteral("S_8BYTE_LITERALS")}, // 0x04
- {StringLiteral("literal_pointers"),
- StringLiteral("S_LITERAL_POINTERS")}, // 0x05
- {StringLiteral("non_lazy_symbol_pointers"),
- StringLiteral("S_NON_LAZY_SYMBOL_POINTERS")}, // 0x06
- {StringLiteral("lazy_symbol_pointers"),
- StringLiteral("S_LAZY_SYMBOL_POINTERS")}, // 0x07
- {StringLiteral("symbol_stubs"), StringLiteral("S_SYMBOL_STUBS")}, // 0x08
- {StringLiteral("mod_init_funcs"),
- StringLiteral("S_MOD_INIT_FUNC_POINTERS")}, // 0x09
- {StringLiteral("mod_term_funcs"),
- StringLiteral("S_MOD_TERM_FUNC_POINTERS")}, // 0x0A
- {StringLiteral("coalesced"), StringLiteral("S_COALESCED")}, // 0x0B
- {StringLiteral("") /*FIXME??*/, StringLiteral("S_GB_ZEROFILL")}, // 0x0C
- {StringLiteral("interposing"), StringLiteral("S_INTERPOSING")}, // 0x0D
- {StringLiteral("16byte_literals"),
- StringLiteral("S_16BYTE_LITERALS")}, // 0x0E
- {StringLiteral("") /*FIXME??*/, StringLiteral("S_DTRACE_DOF")}, // 0x0F
- {StringLiteral("") /*FIXME??*/,
- StringLiteral("S_LAZY_DYLIB_SYMBOL_POINTERS")}, // 0x10
- {StringLiteral("thread_local_regular"),
- StringLiteral("S_THREAD_LOCAL_REGULAR")}, // 0x11
- {StringLiteral("thread_local_zerofill"),
- StringLiteral("S_THREAD_LOCAL_ZEROFILL")}, // 0x12
- {StringLiteral("thread_local_variables"),
- StringLiteral("S_THREAD_LOCAL_VARIABLES")}, // 0x13
- {StringLiteral("thread_local_variable_pointers"),
- StringLiteral("S_THREAD_LOCAL_VARIABLE_POINTERS")}, // 0x14
- {StringLiteral("thread_local_init_function_pointers"),
- StringLiteral("S_THREAD_LOCAL_INIT_FUNCTION_POINTERS")}, // 0x15
-};
-
-/// SectionAttrDescriptors - This is an array of descriptors for section
-/// attributes. Unlike the SectionTypeDescriptors, this is not directly indexed
-/// by attribute, instead it is searched.
-static constexpr struct {
- unsigned AttrFlag;
- StringLiteral AssemblerName, EnumName;
-} SectionAttrDescriptors[] = {
-#define ENTRY(ASMNAME, ENUM) \
- { MachO::ENUM, StringLiteral(ASMNAME), StringLiteral(#ENUM) },
-ENTRY("pure_instructions", S_ATTR_PURE_INSTRUCTIONS)
-ENTRY("no_toc", S_ATTR_NO_TOC)
-ENTRY("strip_static_syms", S_ATTR_STRIP_STATIC_SYMS)
-ENTRY("no_dead_strip", S_ATTR_NO_DEAD_STRIP)
-ENTRY("live_support", S_ATTR_LIVE_SUPPORT)
-ENTRY("self_modifying_code", S_ATTR_SELF_MODIFYING_CODE)
-ENTRY("debug", S_ATTR_DEBUG)
-ENTRY("" /*FIXME*/, S_ATTR_SOME_INSTRUCTIONS)
-ENTRY("" /*FIXME*/, S_ATTR_EXT_RELOC)
-ENTRY("" /*FIXME*/, S_ATTR_LOC_RELOC)
-#undef ENTRY
- { 0, StringLiteral("none"), StringLiteral("") }, // used if section has no attributes but has a stub size
-};
-
-MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section,
- unsigned TAA, unsigned reserved2, SectionKind K,
- MCSymbol *Begin)
- : MCSection(SV_MachO, K, Begin), TypeAndAttributes(TAA),
- Reserved2(reserved2) {
- assert(Segment.size() <= 16 && Section.size() <= 16 &&
- "Segment or section string too long");
- for (unsigned i = 0; i != 16; ++i) {
- if (i < Segment.size())
- SegmentName[i] = Segment[i];
- else
- SegmentName[i] = 0;
-
- if (i < Section.size())
- SectionName[i] = Section[i];
- else
- SectionName[i] = 0;
- }
-}
-
-void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
- raw_ostream &OS,
- const MCExpr *Subsection) const {
- OS << "\t.section\t" << getSegmentName() << ',' << getSectionName();
-
- // Get the section type and attributes.
- unsigned TAA = getTypeAndAttributes();
- if (TAA == 0) {
- OS << '\n';
- return;
- }
-
- MachO::SectionType SectionType = getType();
- assert(SectionType <= MachO::LAST_KNOWN_SECTION_TYPE &&
- "Invalid SectionType specified!");
-
- if (!SectionTypeDescriptors[SectionType].AssemblerName.empty()) {
- OS << ',';
- OS << SectionTypeDescriptors[SectionType].AssemblerName;
- } else {
- // If we have no name for the attribute, stop here.
- OS << '\n';
- return;
- }
-
- // If we don't have any attributes, we're done.
- unsigned SectionAttrs = TAA & MachO::SECTION_ATTRIBUTES;
- if (SectionAttrs == 0) {
- // If we have a S_SYMBOL_STUBS size specified, print it along with 'none' as
- // the attribute specifier.
- if (Reserved2 != 0)
- OS << ",none," << Reserved2;
- OS << '\n';
- return;
- }
-
- // Check each attribute to see if we have it.
- char Separator = ',';
- for (unsigned i = 0;
- SectionAttrs != 0 && SectionAttrDescriptors[i].AttrFlag;
- ++i) {
- // Check to see if we have this attribute.
- if ((SectionAttrDescriptors[i].AttrFlag & SectionAttrs) == 0)
- continue;
-
- // Yep, clear it and print it.
- SectionAttrs &= ~SectionAttrDescriptors[i].AttrFlag;
-
- OS << Separator;
- if (!SectionAttrDescriptors[i].AssemblerName.empty())
- OS << SectionAttrDescriptors[i].AssemblerName;
- else
- OS << "<<" << SectionAttrDescriptors[i].EnumName << ">>";
- Separator = '+';
- }
-
- assert(SectionAttrs == 0 && "Unknown section attributes!");
-
- // If we have a S_SYMBOL_STUBS size specified, print it.
- if (Reserved2 != 0)
- OS << ',' << Reserved2;
- OS << '\n';
-}
-
-bool MCSectionMachO::UseCodeAlign() const {
- return hasAttribute(MachO::S_ATTR_PURE_INSTRUCTIONS);
-}
-
-bool MCSectionMachO::isVirtualSection() const {
- return (getType() == MachO::S_ZEROFILL ||
- getType() == MachO::S_GB_ZEROFILL ||
- getType() == MachO::S_THREAD_LOCAL_ZEROFILL);
-}
-
-/// ParseSectionSpecifier - Parse the section specifier indicated by "Spec".
-/// This is a string that can appear after a .section directive in a mach-o
-/// flavored .s file. If successful, this fills in the specified Out
-/// parameters and returns an empty string. When an invalid section
-/// specifier is present, this returns a string indicating the problem.
-std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
- StringRef &Segment, // Out.
- StringRef &Section, // Out.
- unsigned &TAA, // Out.
- bool &TAAParsed, // Out.
- unsigned &StubSize) { // Out.
- TAAParsed = false;
-
- SmallVector<StringRef, 5> SplitSpec;
- Spec.split(SplitSpec, ',');
- // Remove leading and trailing whitespace.
- auto GetEmptyOrTrim = [&SplitSpec](size_t Idx) -> StringRef {
- return SplitSpec.size() > Idx ? SplitSpec[Idx].trim() : StringRef();
- };
- Segment = GetEmptyOrTrim(0);
- Section = GetEmptyOrTrim(1);
- StringRef SectionType = GetEmptyOrTrim(2);
- StringRef Attrs = GetEmptyOrTrim(3);
- StringRef StubSizeStr = GetEmptyOrTrim(4);
-
- // Verify that the segment is present and not too long.
- if (Segment.empty() || Segment.size() > 16)
- return "mach-o section specifier requires a segment whose length is "
- "between 1 and 16 characters";
-
- // Verify that the section is present and not too long.
- if (Section.empty())
- return "mach-o section specifier requires a segment and section "
- "separated by a comma";
-
- if (Section.size() > 16)
- return "mach-o section specifier requires a section whose length is "
- "between 1 and 16 characters";
-
- // If there is no comma after the section, we're done.
- TAA = 0;
- StubSize = 0;
- if (SectionType.empty())
- return "";
-
- // Figure out which section type it is.
- auto TypeDescriptor = std::find_if(
- std::begin(SectionTypeDescriptors), std::end(SectionTypeDescriptors),
- [&](decltype(*SectionTypeDescriptors) &Descriptor) {
- return SectionType == Descriptor.AssemblerName;
- });
-
- // If we didn't find the section type, reject it.
- if (TypeDescriptor == std::end(SectionTypeDescriptors))
- return "mach-o section specifier uses an unknown section type";
-
- // Remember the TypeID.
- TAA = TypeDescriptor - std::begin(SectionTypeDescriptors);
- TAAParsed = true;
-
- // If we have no comma after the section type, there are no attributes.
- if (Attrs.empty()) {
- // S_SYMBOL_STUBS always require a symbol stub size specifier.
- if (TAA == MachO::S_SYMBOL_STUBS)
- return "mach-o section specifier of type 'symbol_stubs' requires a size "
- "specifier";
- return "";
- }
-
- // The attribute list is a '+' separated list of attributes.
- SmallVector<StringRef, 1> SectionAttrs;
- Attrs.split(SectionAttrs, '+', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
-
- for (StringRef &SectionAttr : SectionAttrs) {
- auto AttrDescriptorI = std::find_if(
- std::begin(SectionAttrDescriptors), std::end(SectionAttrDescriptors),
- [&](decltype(*SectionAttrDescriptors) &Descriptor) {
- return SectionAttr.trim() == Descriptor.AssemblerName;
- });
- if (AttrDescriptorI == std::end(SectionAttrDescriptors))
- return "mach-o section specifier has invalid attribute";
-
- TAA |= AttrDescriptorI->AttrFlag;
- }
-
- // Okay, we've parsed the section attributes, see if we have a stub size spec.
- if (StubSizeStr.empty()) {
- // S_SYMBOL_STUBS always require a symbol stub size specifier.
- if (TAA == MachO::S_SYMBOL_STUBS)
- return "mach-o section specifier of type 'symbol_stubs' requires a size "
- "specifier";
- return "";
- }
-
- // If we have a stub size spec, we must have a sectiontype of S_SYMBOL_STUBS.
- if ((TAA & MachO::SECTION_TYPE) != MachO::S_SYMBOL_STUBS)
- return "mach-o section specifier cannot have a stub size specified because "
- "it does not have type 'symbol_stubs'";
-
- // Convert the stub size from a string to an integer.
- if (StubSizeStr.getAsInteger(0, StubSize))
- return "mach-o section specifier has a malformed stub size";
-
- return "";
-}
diff --git a/contrib/llvm/lib/MC/MCSectionWasm.cpp b/contrib/llvm/lib/MC/MCSectionWasm.cpp
deleted file mode 100644
index 8633c10a73fd..000000000000
--- a/contrib/llvm/lib/MC/MCSectionWasm.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-//===- lib/MC/MCSectionWasm.cpp - Wasm Code Section Representation --------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCSectionWasm.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-// Decides whether a '.section' directive
-// should be printed before the section name.
-bool MCSectionWasm::shouldOmitSectionDirective(StringRef Name,
- const MCAsmInfo &MAI) const {
- return MAI.shouldOmitSectionDirective(Name);
-}
-
-static void printName(raw_ostream &OS, StringRef Name) {
- if (Name.find_first_not_of("0123456789_."
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == Name.npos) {
- OS << Name;
- return;
- }
- OS << '"';
- for (const char *B = Name.begin(), *E = Name.end(); B < E; ++B) {
- if (*B == '"') // Unquoted "
- OS << "\\\"";
- else if (*B != '\\') // Neither " or backslash
- OS << *B;
- else if (B + 1 == E) // Trailing backslash
- OS << "\\\\";
- else {
- OS << B[0] << B[1]; // Quoted character
- ++B;
- }
- }
- OS << '"';
-}
-
-void MCSectionWasm::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
- raw_ostream &OS,
- const MCExpr *Subsection) const {
-
- if (shouldOmitSectionDirective(SectionName, MAI)) {
- OS << '\t' << getSectionName();
- if (Subsection) {
- OS << '\t';
- Subsection->print(OS, &MAI);
- }
- OS << '\n';
- return;
- }
-
- OS << "\t.section\t";
- printName(OS, getSectionName());
- OS << ",\"";
-
- if (IsPassive)
- OS << "passive";
-
- OS << '"';
-
- OS << ',';
-
- // If comment string is '@', e.g. as on ARM - use '%' instead
- if (MAI.getCommentString()[0] == '@')
- OS << '%';
- else
- OS << '@';
-
- // TODO: Print section type.
-
- if (isUnique())
- OS << ",unique," << UniqueID;
-
- OS << '\n';
-
- if (Subsection) {
- OS << "\t.subsection\t";
- Subsection->print(OS, &MAI);
- OS << '\n';
- }
-}
-
-bool MCSectionWasm::UseCodeAlign() const { return false; }
-
-bool MCSectionWasm::isVirtualSection() const { return false; }
diff --git a/contrib/llvm/lib/MC/MCSectionXCOFF.cpp b/contrib/llvm/lib/MC/MCSectionXCOFF.cpp
deleted file mode 100644
index d1a637345024..000000000000
--- a/contrib/llvm/lib/MC/MCSectionXCOFF.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-//===- lib/MC/MCSectionXCOFF.cpp - XCOFF Code Section Representation ------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCSectionXCOFF.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-MCSectionXCOFF::~MCSectionXCOFF() = default;
-
-void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
- raw_ostream &OS,
- const MCExpr *Subsection) const {
- if (getKind().isText()) {
- OS << "\t.csect " << getSectionName() << "["
- << "PR"
- << "]" << '\n';
- return;
- }
-
- report_fatal_error("Printing for this SectionKind is unimplemented.");
-}
-
-bool MCSectionXCOFF::UseCodeAlign() const { return getKind().isText(); }
-
-bool MCSectionXCOFF::isVirtualSection() const { return !getKind().isCommon(); }
diff --git a/contrib/llvm/lib/MC/MCStreamer.cpp b/contrib/llvm/lib/MC/MCStreamer.cpp
deleted file mode 100644
index decbb96817e3..000000000000
--- a/contrib/llvm/lib/MC/MCStreamer.cpp
+++ /dev/null
@@ -1,1106 +0,0 @@
-//===- lib/MC/MCStreamer.cpp - Streaming Machine Code Output --------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/COFF.h"
-#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCCodeView.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDwarf.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCInstPrinter.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCSectionCOFF.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCWin64EH.h"
-#include "llvm/MC/MCWinEH.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/LEB128.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <cstdint>
-#include <cstdlib>
-#include <utility>
-
-using namespace llvm;
-
-MCTargetStreamer::MCTargetStreamer(MCStreamer &S) : Streamer(S) {
- S.setTargetStreamer(this);
-}
-
-// Pin the vtables to this file.
-MCTargetStreamer::~MCTargetStreamer() = default;
-
-void MCTargetStreamer::emitLabel(MCSymbol *Symbol) {}
-
-void MCTargetStreamer::finish() {}
-
-void MCTargetStreamer::changeSection(const MCSection *CurSection,
- MCSection *Section,
- const MCExpr *Subsection,
- raw_ostream &OS) {
- Section->PrintSwitchToSection(
- *Streamer.getContext().getAsmInfo(),
- Streamer.getContext().getObjectFileInfo()->getTargetTriple(), OS,
- Subsection);
-}
-
-void MCTargetStreamer::emitDwarfFileDirective(StringRef Directive) {
- Streamer.EmitRawText(Directive);
-}
-
-void MCTargetStreamer::emitValue(const MCExpr *Value) {
- SmallString<128> Str;
- raw_svector_ostream OS(Str);
-
- Value->print(OS, Streamer.getContext().getAsmInfo());
- Streamer.EmitRawText(OS.str());
-}
-
-void MCTargetStreamer::emitRawBytes(StringRef Data) {
- const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();
- const char *Directive = MAI->getData8bitsDirective();
- for (const unsigned char C : Data.bytes()) {
- SmallString<128> Str;
- raw_svector_ostream OS(Str);
-
- OS << Directive << (unsigned)C;
- Streamer.EmitRawText(OS.str());
- }
-}
-
-void MCTargetStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {}
-
-MCStreamer::MCStreamer(MCContext &Ctx)
- : Context(Ctx), CurrentWinFrameInfo(nullptr),
- UseAssemblerInfoForParsing(false) {
- SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>());
-}
-
-MCStreamer::~MCStreamer() {}
-
-void MCStreamer::reset() {
- DwarfFrameInfos.clear();
- CurrentWinFrameInfo = nullptr;
- WinFrameInfos.clear();
- SymbolOrdering.clear();
- SectionStack.clear();
- SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>());
-}
-
-raw_ostream &MCStreamer::GetCommentOS() {
- // By default, discard comments.
- return nulls();
-}
-
-unsigned MCStreamer::getNumFrameInfos() { return DwarfFrameInfos.size(); }
-ArrayRef<MCDwarfFrameInfo> MCStreamer::getDwarfFrameInfos() const {
- return DwarfFrameInfos;
-}
-
-void MCStreamer::emitRawComment(const Twine &T, bool TabPrefix) {}
-
-void MCStreamer::addExplicitComment(const Twine &T) {}
-void MCStreamer::emitExplicitComments() {}
-
-void MCStreamer::generateCompactUnwindEncodings(MCAsmBackend *MAB) {
- for (auto &FI : DwarfFrameInfos)
- FI.CompactUnwindEncoding =
- (MAB ? MAB->generateCompactUnwindEncoding(FI.Instructions) : 0);
-}
-
-/// EmitIntValue - Special case of EmitValue that avoids the client having to
-/// pass in a MCExpr for constant integers.
-void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size) {
- assert(1 <= Size && Size <= 8 && "Invalid size");
- assert((isUIntN(8 * Size, Value) || isIntN(8 * Size, Value)) &&
- "Invalid size");
- char buf[8];
- const bool isLittleEndian = Context.getAsmInfo()->isLittleEndian();
- for (unsigned i = 0; i != Size; ++i) {
- unsigned index = isLittleEndian ? i : (Size - i - 1);
- buf[i] = uint8_t(Value >> (index * 8));
- }
- EmitBytes(StringRef(buf, Size));
-}
-
-/// EmitULEB128IntValue - Special case of EmitULEB128Value that avoids the
-/// client having to pass in a MCExpr for constant integers.
-void MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned PadTo) {
- SmallString<128> Tmp;
- raw_svector_ostream OSE(Tmp);
- encodeULEB128(Value, OSE, PadTo);
- EmitBytes(OSE.str());
-}
-
-/// EmitSLEB128IntValue - Special case of EmitSLEB128Value that avoids the
-/// client having to pass in a MCExpr for constant integers.
-void MCStreamer::EmitSLEB128IntValue(int64_t Value) {
- SmallString<128> Tmp;
- raw_svector_ostream OSE(Tmp);
- encodeSLEB128(Value, OSE);
- EmitBytes(OSE.str());
-}
-
-void MCStreamer::EmitValue(const MCExpr *Value, unsigned Size, SMLoc Loc) {
- EmitValueImpl(Value, Size, Loc);
-}
-
-void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
- bool IsSectionRelative) {
- assert((!IsSectionRelative || Size == 4) &&
- "SectionRelative value requires 4-bytes");
-
- if (!IsSectionRelative)
- EmitValueImpl(MCSymbolRefExpr::create(Sym, getContext()), Size);
- else
- EmitCOFFSecRel32(Sym, /*Offset=*/0);
-}
-
-void MCStreamer::EmitDTPRel64Value(const MCExpr *Value) {
- report_fatal_error("unsupported directive in streamer");
-}
-
-void MCStreamer::EmitDTPRel32Value(const MCExpr *Value) {
- report_fatal_error("unsupported directive in streamer");
-}
-
-void MCStreamer::EmitTPRel64Value(const MCExpr *Value) {
- report_fatal_error("unsupported directive in streamer");
-}
-
-void MCStreamer::EmitTPRel32Value(const MCExpr *Value) {
- report_fatal_error("unsupported directive in streamer");
-}
-
-void MCStreamer::EmitGPRel64Value(const MCExpr *Value) {
- report_fatal_error("unsupported directive in streamer");
-}
-
-void MCStreamer::EmitGPRel32Value(const MCExpr *Value) {
- report_fatal_error("unsupported directive in streamer");
-}
-
-/// Emit NumBytes bytes worth of the value specified by FillValue.
-/// This implements directives such as '.space'.
-void MCStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) {
- emitFill(*MCConstantExpr::create(NumBytes, getContext()), FillValue);
-}
-
-/// The implementation in this class just redirects to emitFill.
-void MCStreamer::EmitZeros(uint64_t NumBytes) {
- emitFill(NumBytes, 0);
-}
-
-Expected<unsigned>
-MCStreamer::tryEmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
- StringRef Filename,
- Optional<MD5::MD5Result> Checksum,
- Optional<StringRef> Source,
- unsigned CUID) {
- return getContext().getDwarfFile(Directory, Filename, FileNo, Checksum,
- Source, CUID);
-}
-
-void MCStreamer::emitDwarfFile0Directive(StringRef Directory,
- StringRef Filename,
- Optional<MD5::MD5Result> Checksum,
- Optional<StringRef> Source,
- unsigned CUID) {
- getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum,
- Source);
-}
-
-void MCStreamer::EmitCFIBKeyFrame() {
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->IsBKeyFrame = true;
-}
-
-void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
- unsigned Column, unsigned Flags,
- unsigned Isa,
- unsigned Discriminator,
- StringRef FileName) {
- getContext().setCurrentDwarfLoc(FileNo, Line, Column, Flags, Isa,
- Discriminator);
-}
-
-MCSymbol *MCStreamer::getDwarfLineTableSymbol(unsigned CUID) {
- MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
- if (!Table.getLabel()) {
- StringRef Prefix = Context.getAsmInfo()->getPrivateGlobalPrefix();
- Table.setLabel(
- Context.getOrCreateSymbol(Prefix + "line_table_start" + Twine(CUID)));
- }
- return Table.getLabel();
-}
-
-bool MCStreamer::hasUnfinishedDwarfFrameInfo() {
- return !DwarfFrameInfos.empty() && !DwarfFrameInfos.back().End;
-}
-
-MCDwarfFrameInfo *MCStreamer::getCurrentDwarfFrameInfo() {
- if (!hasUnfinishedDwarfFrameInfo()) {
- getContext().reportError(SMLoc(), "this directive must appear between "
- ".cfi_startproc and .cfi_endproc "
- "directives");
- return nullptr;
- }
- return &DwarfFrameInfos.back();
-}
-
-bool MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename,
- ArrayRef<uint8_t> Checksum,
- unsigned ChecksumKind) {
- return getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
- ChecksumKind);
-}
-
-bool MCStreamer::EmitCVFuncIdDirective(unsigned FunctionId) {
- return getContext().getCVContext().recordFunctionId(FunctionId);
-}
-
-bool MCStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId,
- unsigned IAFunc, unsigned IAFile,
- unsigned IALine, unsigned IACol,
- SMLoc Loc) {
- if (getContext().getCVContext().getCVFunctionInfo(IAFunc) == nullptr) {
- getContext().reportError(Loc, "parent function id not introduced by "
- ".cv_func_id or .cv_inline_site_id");
- return true;
- }
-
- return getContext().getCVContext().recordInlinedCallSiteId(
- FunctionId, IAFunc, IAFile, IALine, IACol);
-}
-
-void MCStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
- unsigned Line, unsigned Column,
- bool PrologueEnd, bool IsStmt,
- StringRef FileName, SMLoc Loc) {}
-
-bool MCStreamer::checkCVLocSection(unsigned FuncId, unsigned FileNo,
- SMLoc Loc) {
- CodeViewContext &CVC = getContext().getCVContext();
- MCCVFunctionInfo *FI = CVC.getCVFunctionInfo(FuncId);
- if (!FI) {
- getContext().reportError(
- Loc, "function id not introduced by .cv_func_id or .cv_inline_site_id");
- return false;
- }
-
- // Track the section
- if (FI->Section == nullptr)
- FI->Section = getCurrentSectionOnly();
- else if (FI->Section != getCurrentSectionOnly()) {
- getContext().reportError(
- Loc,
- "all .cv_loc directives for a function must be in the same section");
- return false;
- }
- return true;
-}
-
-void MCStreamer::EmitCVLinetableDirective(unsigned FunctionId,
- const MCSymbol *Begin,
- const MCSymbol *End) {}
-
-void MCStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
- unsigned SourceFileId,
- unsigned SourceLineNum,
- const MCSymbol *FnStartSym,
- const MCSymbol *FnEndSym) {}
-
-void MCStreamer::EmitCVDefRangeDirective(
- ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
- StringRef FixedSizePortion) {}
-
-void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol,
- MCSymbol *EHSymbol) {
-}
-
-void MCStreamer::InitSections(bool NoExecStack) {
- SwitchSection(getContext().getObjectFileInfo()->getTextSection());
-}
-
-void MCStreamer::AssignFragment(MCSymbol *Symbol, MCFragment *Fragment) {
- assert(Fragment);
- Symbol->setFragment(Fragment);
-
- // As we emit symbols into a section, track the order so that they can
- // be sorted upon later. Zero is reserved to mean 'unemitted'.
- SymbolOrdering[Symbol] = 1 + SymbolOrdering.size();
-}
-
-void MCStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
- Symbol->redefineIfPossible();
-
- if (!Symbol->isUndefined() || Symbol->isVariable())
- return getContext().reportError(Loc, "invalid symbol redefinition");
-
- assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
- assert(getCurrentSectionOnly() && "Cannot emit before setting section!");
- assert(!Symbol->getFragment() && "Unexpected fragment on symbol data!");
- assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
-
- Symbol->setFragment(&getCurrentSectionOnly()->getDummyFragment());
-
- MCTargetStreamer *TS = getTargetStreamer();
- if (TS)
- TS->emitLabel(Symbol);
-}
-
-void MCStreamer::EmitCFISections(bool EH, bool Debug) {
- assert(EH || Debug);
-}
-
-void MCStreamer::EmitCFIStartProc(bool IsSimple, SMLoc Loc) {
- if (hasUnfinishedDwarfFrameInfo())
- return getContext().reportError(
- Loc, "starting new .cfi frame before finishing the previous one");
-
- MCDwarfFrameInfo Frame;
- Frame.IsSimple = IsSimple;
- EmitCFIStartProcImpl(Frame);
-
- const MCAsmInfo* MAI = Context.getAsmInfo();
- if (MAI) {
- for (const MCCFIInstruction& Inst : MAI->getInitialFrameState()) {
- if (Inst.getOperation() == MCCFIInstruction::OpDefCfa ||
- Inst.getOperation() == MCCFIInstruction::OpDefCfaRegister) {
- Frame.CurrentCfaRegister = Inst.getRegister();
- }
- }
- }
-
- DwarfFrameInfos.push_back(Frame);
-}
-
-void MCStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
-}
-
-void MCStreamer::EmitCFIEndProc() {
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- EmitCFIEndProcImpl(*CurFrame);
-}
-
-void MCStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
- // Put a dummy non-null value in Frame.End to mark that this frame has been
- // closed.
- Frame.End = (MCSymbol *)1;
-}
-
-MCSymbol *MCStreamer::EmitCFILabel() {
- // Return a dummy non-null value so that label fields appear filled in when
- // generating textual assembly.
- return (MCSymbol *)1;
-}
-
-void MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) {
- MCSymbol *Label = EmitCFILabel();
- MCCFIInstruction Instruction =
- MCCFIInstruction::createDefCfa(Label, Register, Offset);
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->Instructions.push_back(Instruction);
- CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register);
-}
-
-void MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) {
- MCSymbol *Label = EmitCFILabel();
- MCCFIInstruction Instruction =
- MCCFIInstruction::createDefCfaOffset(Label, Offset);
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->Instructions.push_back(Instruction);
-}
-
-void MCStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) {
- MCSymbol *Label = EmitCFILabel();
- MCCFIInstruction Instruction =
- MCCFIInstruction::createAdjustCfaOffset(Label, Adjustment);
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->Instructions.push_back(Instruction);
-}
-
-void MCStreamer::EmitCFIDefCfaRegister(int64_t Register) {
- MCSymbol *Label = EmitCFILabel();
- MCCFIInstruction Instruction =
- MCCFIInstruction::createDefCfaRegister(Label, Register);
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->Instructions.push_back(Instruction);
- CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register);
-}
-
-void MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) {
- MCSymbol *Label = EmitCFILabel();
- MCCFIInstruction Instruction =
- MCCFIInstruction::createOffset(Label, Register, Offset);
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->Instructions.push_back(Instruction);
-}
-
-void MCStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) {
- MCSymbol *Label = EmitCFILabel();
- MCCFIInstruction Instruction =
- MCCFIInstruction::createRelOffset(Label, Register, Offset);
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->Instructions.push_back(Instruction);
-}
-
-void MCStreamer::EmitCFIPersonality(const MCSymbol *Sym,
- unsigned Encoding) {
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->Personality = Sym;
- CurFrame->PersonalityEncoding = Encoding;
-}
-
-void MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->Lsda = Sym;
- CurFrame->LsdaEncoding = Encoding;
-}
-
-void MCStreamer::EmitCFIRememberState() {
- MCSymbol *Label = EmitCFILabel();
- MCCFIInstruction Instruction = MCCFIInstruction::createRememberState(Label);
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->Instructions.push_back(Instruction);
-}
-
-void MCStreamer::EmitCFIRestoreState() {
- // FIXME: Error if there is no matching cfi_remember_state.
- MCSymbol *Label = EmitCFILabel();
- MCCFIInstruction Instruction = MCCFIInstruction::createRestoreState(Label);
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->Instructions.push_back(Instruction);
-}
-
-void MCStreamer::EmitCFISameValue(int64_t Register) {
- MCSymbol *Label = EmitCFILabel();
- MCCFIInstruction Instruction =
- MCCFIInstruction::createSameValue(Label, Register);
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->Instructions.push_back(Instruction);
-}
-
-void MCStreamer::EmitCFIRestore(int64_t Register) {
- MCSymbol *Label = EmitCFILabel();
- MCCFIInstruction Instruction =
- MCCFIInstruction::createRestore(Label, Register);
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->Instructions.push_back(Instruction);
-}
-
-void MCStreamer::EmitCFIEscape(StringRef Values) {
- MCSymbol *Label = EmitCFILabel();
- MCCFIInstruction Instruction = MCCFIInstruction::createEscape(Label, Values);
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->Instructions.push_back(Instruction);
-}
-
-void MCStreamer::EmitCFIGnuArgsSize(int64_t Size) {
- MCSymbol *Label = EmitCFILabel();
- MCCFIInstruction Instruction =
- MCCFIInstruction::createGnuArgsSize(Label, Size);
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->Instructions.push_back(Instruction);
-}
-
-void MCStreamer::EmitCFISignalFrame() {
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->IsSignalFrame = true;
-}
-
-void MCStreamer::EmitCFIUndefined(int64_t Register) {
- MCSymbol *Label = EmitCFILabel();
- MCCFIInstruction Instruction =
- MCCFIInstruction::createUndefined(Label, Register);
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->Instructions.push_back(Instruction);
-}
-
-void MCStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) {
- MCSymbol *Label = EmitCFILabel();
- MCCFIInstruction Instruction =
- MCCFIInstruction::createRegister(Label, Register1, Register2);
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->Instructions.push_back(Instruction);
-}
-
-void MCStreamer::EmitCFIWindowSave() {
- MCSymbol *Label = EmitCFILabel();
- MCCFIInstruction Instruction =
- MCCFIInstruction::createWindowSave(Label);
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->Instructions.push_back(Instruction);
-}
-
-void MCStreamer::EmitCFINegateRAState() {
- MCSymbol *Label = EmitCFILabel();
- MCCFIInstruction Instruction = MCCFIInstruction::createNegateRAState(Label);
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->Instructions.push_back(Instruction);
-}
-
-void MCStreamer::EmitCFIReturnColumn(int64_t Register) {
- MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
- if (!CurFrame)
- return;
- CurFrame->RAReg = Register;
-}
-
-WinEH::FrameInfo *MCStreamer::EnsureValidWinFrameInfo(SMLoc Loc) {
- const MCAsmInfo *MAI = Context.getAsmInfo();
- if (!MAI->usesWindowsCFI()) {
- getContext().reportError(
- Loc, ".seh_* directives are not supported on this target");
- return nullptr;
- }
- if (!CurrentWinFrameInfo || CurrentWinFrameInfo->End) {
- getContext().reportError(
- Loc, ".seh_ directive must appear within an active frame");
- return nullptr;
- }
- return CurrentWinFrameInfo;
-}
-
-void MCStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
- const MCAsmInfo *MAI = Context.getAsmInfo();
- if (!MAI->usesWindowsCFI())
- return getContext().reportError(
- Loc, ".seh_* directives are not supported on this target");
- if (CurrentWinFrameInfo && !CurrentWinFrameInfo->End)
- getContext().reportError(
- Loc, "Starting a function before ending the previous one!");
-
- MCSymbol *StartProc = EmitCFILabel();
-
- WinFrameInfos.emplace_back(
- llvm::make_unique<WinEH::FrameInfo>(Symbol, StartProc));
- CurrentWinFrameInfo = WinFrameInfos.back().get();
- CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
-}
-
-void MCStreamer::EmitWinCFIEndProc(SMLoc Loc) {
- WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
- if (!CurFrame)
- return;
- if (CurFrame->ChainedParent)
- getContext().reportError(Loc, "Not all chained regions terminated!");
-
- MCSymbol *Label = EmitCFILabel();
- CurFrame->End = Label;
-}
-
-void MCStreamer::EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) {
- WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
- if (!CurFrame)
- return;
- if (CurFrame->ChainedParent)
- getContext().reportError(Loc, "Not all chained regions terminated!");
-
- MCSymbol *Label = EmitCFILabel();
- CurFrame->FuncletOrFuncEnd = Label;
-}
-
-void MCStreamer::EmitWinCFIStartChained(SMLoc Loc) {
- WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
- if (!CurFrame)
- return;
-
- MCSymbol *StartProc = EmitCFILabel();
-
- WinFrameInfos.emplace_back(llvm::make_unique<WinEH::FrameInfo>(
- CurFrame->Function, StartProc, CurFrame));
- CurrentWinFrameInfo = WinFrameInfos.back().get();
- CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
-}
-
-void MCStreamer::EmitWinCFIEndChained(SMLoc Loc) {
- WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
- if (!CurFrame)
- return;
- if (!CurFrame->ChainedParent)
- return getContext().reportError(
- Loc, "End of a chained region outside a chained region!");
-
- MCSymbol *Label = EmitCFILabel();
-
- CurFrame->End = Label;
- CurrentWinFrameInfo = const_cast<WinEH::FrameInfo *>(CurFrame->ChainedParent);
-}
-
-void MCStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
- SMLoc Loc) {
- WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
- if (!CurFrame)
- return;
- if (CurFrame->ChainedParent)
- return getContext().reportError(
- Loc, "Chained unwind areas can't have handlers!");
- CurFrame->ExceptionHandler = Sym;
- if (!Except && !Unwind)
- getContext().reportError(Loc, "Don't know what kind of handler this is!");
- if (Unwind)
- CurFrame->HandlesUnwind = true;
- if (Except)
- CurFrame->HandlesExceptions = true;
-}
-
-void MCStreamer::EmitWinEHHandlerData(SMLoc Loc) {
- WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
- if (!CurFrame)
- return;
- if (CurFrame->ChainedParent)
- getContext().reportError(Loc, "Chained unwind areas can't have handlers!");
-}
-
-void MCStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
- const MCSymbolRefExpr *To, uint64_t Count) {
-}
-
-static MCSection *getWinCFISection(MCContext &Context, unsigned *NextWinCFIID,
- MCSection *MainCFISec,
- const MCSection *TextSec) {
- // If this is the main .text section, use the main unwind info section.
- if (TextSec == Context.getObjectFileInfo()->getTextSection())
- return MainCFISec;
-
- const auto *TextSecCOFF = cast<MCSectionCOFF>(TextSec);
- auto *MainCFISecCOFF = cast<MCSectionCOFF>(MainCFISec);
- unsigned UniqueID = TextSecCOFF->getOrAssignWinCFISectionID(NextWinCFIID);
-
- // If this section is COMDAT, this unwind section should be COMDAT associative
- // with its group.
- const MCSymbol *KeySym = nullptr;
- if (TextSecCOFF->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) {
- KeySym = TextSecCOFF->getCOMDATSymbol();
-
- // In a GNU environment, we can't use associative comdats. Instead, do what
- // GCC does, which is to make plain comdat selectany section named like
- // ".[px]data$_Z3foov".
- if (!Context.getAsmInfo()->hasCOFFAssociativeComdats()) {
- std::string SectionName =
- (MainCFISecCOFF->getSectionName() + "$" +
- TextSecCOFF->getSectionName().split('$').second)
- .str();
- return Context.getCOFFSection(
- SectionName,
- MainCFISecCOFF->getCharacteristics() | COFF::IMAGE_SCN_LNK_COMDAT,
- MainCFISecCOFF->getKind(), "", COFF::IMAGE_COMDAT_SELECT_ANY);
- }
- }
-
- return Context.getAssociativeCOFFSection(MainCFISecCOFF, KeySym, UniqueID);
-}
-
-MCSection *MCStreamer::getAssociatedPDataSection(const MCSection *TextSec) {
- return getWinCFISection(getContext(), &NextWinCFIID,
- getContext().getObjectFileInfo()->getPDataSection(),
- TextSec);
-}
-
-MCSection *MCStreamer::getAssociatedXDataSection(const MCSection *TextSec) {
- return getWinCFISection(getContext(), &NextWinCFIID,
- getContext().getObjectFileInfo()->getXDataSection(),
- TextSec);
-}
-
-void MCStreamer::EmitSyntaxDirective() {}
-
-void MCStreamer::EmitWinCFIPushReg(unsigned Register, SMLoc Loc) {
- WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
- if (!CurFrame)
- return;
-
- MCSymbol *Label = EmitCFILabel();
-
- WinEH::Instruction Inst = Win64EH::Instruction::PushNonVol(Label, Register);
- CurFrame->Instructions.push_back(Inst);
-}
-
-void MCStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset,
- SMLoc Loc) {
- WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
- if (!CurFrame)
- return;
- if (CurFrame->LastFrameInst >= 0)
- return getContext().reportError(
- Loc, "frame register and offset can be set at most once");
- if (Offset & 0x0F)
- return getContext().reportError(Loc, "offset is not a multiple of 16");
- if (Offset > 240)
- return getContext().reportError(
- Loc, "frame offset must be less than or equal to 240");
-
- MCSymbol *Label = EmitCFILabel();
-
- WinEH::Instruction Inst =
- Win64EH::Instruction::SetFPReg(Label, Register, Offset);
- CurFrame->LastFrameInst = CurFrame->Instructions.size();
- CurFrame->Instructions.push_back(Inst);
-}
-
-void MCStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
- WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
- if (!CurFrame)
- return;
- if (Size == 0)
- return getContext().reportError(Loc,
- "stack allocation size must be non-zero");
- if (Size & 7)
- return getContext().reportError(
- Loc, "stack allocation size is not a multiple of 8");
-
- MCSymbol *Label = EmitCFILabel();
-
- WinEH::Instruction Inst = Win64EH::Instruction::Alloc(Label, Size);
- CurFrame->Instructions.push_back(Inst);
-}
-
-void MCStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset,
- SMLoc Loc) {
- WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
- if (!CurFrame)
- return;
-
- if (Offset & 7)
- return getContext().reportError(
- Loc, "register save offset is not 8 byte aligned");
-
- MCSymbol *Label = EmitCFILabel();
-
- WinEH::Instruction Inst =
- Win64EH::Instruction::SaveNonVol(Label, Register, Offset);
- CurFrame->Instructions.push_back(Inst);
-}
-
-void MCStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset,
- SMLoc Loc) {
- WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
- if (!CurFrame)
- return;
- if (Offset & 0x0F)
- return getContext().reportError(Loc, "offset is not a multiple of 16");
-
- MCSymbol *Label = EmitCFILabel();
-
- WinEH::Instruction Inst =
- Win64EH::Instruction::SaveXMM(Label, Register, Offset);
- CurFrame->Instructions.push_back(Inst);
-}
-
-void MCStreamer::EmitWinCFIPushFrame(bool Code, SMLoc Loc) {
- WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
- if (!CurFrame)
- return;
- if (!CurFrame->Instructions.empty())
- return getContext().reportError(
- Loc, "If present, PushMachFrame must be the first UOP");
-
- MCSymbol *Label = EmitCFILabel();
-
- WinEH::Instruction Inst = Win64EH::Instruction::PushMachFrame(Label, Code);
- CurFrame->Instructions.push_back(Inst);
-}
-
-void MCStreamer::EmitWinCFIEndProlog(SMLoc Loc) {
- WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
- if (!CurFrame)
- return;
-
- MCSymbol *Label = EmitCFILabel();
-
- CurFrame->PrologEnd = Label;
-}
-
-void MCStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {}
-
-void MCStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {}
-
-void MCStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {}
-
-void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {}
-
-void MCStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {}
-
-/// EmitRawText - If this file is backed by an assembly streamer, this dumps
-/// the specified string in the output .s file. This capability is
-/// indicated by the hasRawTextSupport() predicate.
-void MCStreamer::EmitRawTextImpl(StringRef String) {
- // This is not llvm_unreachable for the sake of out of tree backend
- // developers who may not have assembly streamers and should serve as a
- // reminder to not accidentally call EmitRawText in the absence of such.
- report_fatal_error("EmitRawText called on an MCStreamer that doesn't support "
- "it (target backend is likely missing an AsmStreamer "
- "implementation)");
-}
-
-void MCStreamer::EmitRawText(const Twine &T) {
- SmallString<128> Str;
- EmitRawTextImpl(T.toStringRef(Str));
-}
-
-void MCStreamer::EmitWindowsUnwindTables() {
-}
-
-void MCStreamer::Finish() {
- if ((!DwarfFrameInfos.empty() && !DwarfFrameInfos.back().End) ||
- (!WinFrameInfos.empty() && !WinFrameInfos.back()->End)) {
- getContext().reportError(SMLoc(), "Unfinished frame!");
- return;
- }
-
- MCTargetStreamer *TS = getTargetStreamer();
- if (TS)
- TS->finish();
-
- FinishImpl();
-}
-
-void MCStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
- visitUsedExpr(*Value);
- Symbol->setVariableValue(Value);
-
- MCTargetStreamer *TS = getTargetStreamer();
- if (TS)
- TS->emitAssignment(Symbol, Value);
-}
-
-void MCTargetStreamer::prettyPrintAsm(MCInstPrinter &InstPrinter,
- raw_ostream &OS, const MCInst &Inst,
- const MCSubtargetInfo &STI) {
- InstPrinter.printInst(&Inst, OS, "", STI);
-}
-
-void MCStreamer::visitUsedSymbol(const MCSymbol &Sym) {
-}
-
-void MCStreamer::visitUsedExpr(const MCExpr &Expr) {
- switch (Expr.getKind()) {
- case MCExpr::Target:
- cast<MCTargetExpr>(Expr).visitUsedExpr(*this);
- break;
-
- case MCExpr::Constant:
- break;
-
- case MCExpr::Binary: {
- const MCBinaryExpr &BE = cast<MCBinaryExpr>(Expr);
- visitUsedExpr(*BE.getLHS());
- visitUsedExpr(*BE.getRHS());
- break;
- }
-
- case MCExpr::SymbolRef:
- visitUsedSymbol(cast<MCSymbolRefExpr>(Expr).getSymbol());
- break;
-
- case MCExpr::Unary:
- visitUsedExpr(*cast<MCUnaryExpr>(Expr).getSubExpr());
- break;
- }
-}
-
-void MCStreamer::EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &) {
- // Scan for values.
- for (unsigned i = Inst.getNumOperands(); i--;)
- if (Inst.getOperand(i).isExpr())
- visitUsedExpr(*Inst.getOperand(i).getExpr());
-}
-
-void MCStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
- unsigned Size) {
- // Get the Hi-Lo expression.
- const MCExpr *Diff =
- MCBinaryExpr::createSub(MCSymbolRefExpr::create(Hi, Context),
- MCSymbolRefExpr::create(Lo, Context), Context);
-
- const MCAsmInfo *MAI = Context.getAsmInfo();
- if (!MAI->doesSetDirectiveSuppressReloc()) {
- EmitValue(Diff, Size);
- return;
- }
-
- // Otherwise, emit with .set (aka assignment).
- MCSymbol *SetLabel = Context.createTempSymbol("set", true);
- EmitAssignment(SetLabel, Diff);
- EmitSymbolValue(SetLabel, Size);
-}
-
-void MCStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
- const MCSymbol *Lo) {
- // Get the Hi-Lo expression.
- const MCExpr *Diff =
- MCBinaryExpr::createSub(MCSymbolRefExpr::create(Hi, Context),
- MCSymbolRefExpr::create(Lo, Context), Context);
-
- EmitULEB128Value(Diff);
-}
-
-void MCStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {}
-void MCStreamer::EmitThumbFunc(MCSymbol *Func) {}
-void MCStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {}
-void MCStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) {
- llvm_unreachable("this directive only supported on COFF targets");
-}
-void MCStreamer::EndCOFFSymbolDef() {
- llvm_unreachable("this directive only supported on COFF targets");
-}
-void MCStreamer::EmitFileDirective(StringRef Filename) {}
-void MCStreamer::EmitCOFFSymbolStorageClass(int StorageClass) {
- llvm_unreachable("this directive only supported on COFF targets");
-}
-void MCStreamer::EmitCOFFSymbolType(int Type) {
- llvm_unreachable("this directive only supported on COFF targets");
-}
-void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
-void MCStreamer::emitELFSymverDirective(StringRef AliasName,
- const MCSymbol *Aliasee) {}
-void MCStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
- unsigned ByteAlignment) {}
-void MCStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment) {}
-void MCStreamer::ChangeSection(MCSection *, const MCExpr *) {}
-void MCStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {}
-void MCStreamer::EmitBytes(StringRef Data) {}
-void MCStreamer::EmitBinaryData(StringRef Data) { EmitBytes(Data); }
-void MCStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) {
- visitUsedExpr(*Value);
-}
-void MCStreamer::EmitULEB128Value(const MCExpr *Value) {}
-void MCStreamer::EmitSLEB128Value(const MCExpr *Value) {}
-void MCStreamer::emitFill(const MCExpr &NumBytes, uint64_t Value, SMLoc Loc) {}
-void MCStreamer::emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
- SMLoc Loc) {}
-void MCStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
- unsigned ValueSize,
- unsigned MaxBytesToEmit) {}
-void MCStreamer::EmitCodeAlignment(unsigned ByteAlignment,
- unsigned MaxBytesToEmit) {}
-void MCStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value,
- SMLoc Loc) {}
-void MCStreamer::EmitBundleAlignMode(unsigned AlignPow2) {}
-void MCStreamer::EmitBundleLock(bool AlignToEnd) {}
-void MCStreamer::FinishImpl() {}
-void MCStreamer::EmitBundleUnlock() {}
-
-void MCStreamer::SwitchSection(MCSection *Section, const MCExpr *Subsection) {
- assert(Section && "Cannot switch to a null section!");
- MCSectionSubPair curSection = SectionStack.back().first;
- SectionStack.back().second = curSection;
- if (MCSectionSubPair(Section, Subsection) != curSection) {
- ChangeSection(Section, Subsection);
- SectionStack.back().first = MCSectionSubPair(Section, Subsection);
- assert(!Section->hasEnded() && "Section already ended");
- MCSymbol *Sym = Section->getBeginSymbol();
- if (Sym && !Sym->isInSection())
- EmitLabel(Sym);
- }
-}
-
-MCSymbol *MCStreamer::endSection(MCSection *Section) {
- // TODO: keep track of the last subsection so that this symbol appears in the
- // correct place.
- MCSymbol *Sym = Section->getEndSymbol(Context);
- if (Sym->isInSection())
- return Sym;
-
- SwitchSection(Section);
- EmitLabel(Sym);
- return Sym;
-}
-
-void MCStreamer::EmitVersionForTarget(const Triple &Target,
- const VersionTuple &SDKVersion) {
- if (!Target.isOSBinFormatMachO() || !Target.isOSDarwin())
- return;
- // Do we even know the version?
- if (Target.getOSMajorVersion() == 0)
- return;
-
- unsigned Major;
- unsigned Minor;
- unsigned Update;
- if (Target.isMacCatalystEnvironment()) {
- // Mac Catalyst always uses the build version load command.
- Target.getiOSVersion(Major, Minor, Update);
- assert(Major && "A non-zero major version is expected");
- EmitBuildVersion(MachO::PLATFORM_MACCATALYST, Major, Minor, Update,
- SDKVersion);
- return;
- }
-
- MCVersionMinType VersionType;
- if (Target.isWatchOS()) {
- VersionType = MCVM_WatchOSVersionMin;
- Target.getWatchOSVersion(Major, Minor, Update);
- } else if (Target.isTvOS()) {
- VersionType = MCVM_TvOSVersionMin;
- Target.getiOSVersion(Major, Minor, Update);
- } else if (Target.isMacOSX()) {
- VersionType = MCVM_OSXVersionMin;
- if (!Target.getMacOSXVersion(Major, Minor, Update))
- Major = 0;
- } else {
- VersionType = MCVM_IOSVersionMin;
- Target.getiOSVersion(Major, Minor, Update);
- }
- if (Major != 0)
- EmitVersionMin(VersionType, Major, Minor, Update, SDKVersion);
-}
diff --git a/contrib/llvm/lib/MC/MCSubtargetInfo.cpp b/contrib/llvm/lib/MC/MCSubtargetInfo.cpp
deleted file mode 100644
index 5fd48d9e1010..000000000000
--- a/contrib/llvm/lib/MC/MCSubtargetInfo.cpp
+++ /dev/null
@@ -1,317 +0,0 @@
-//===- MCSubtargetInfo.cpp - Subtarget Information ------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/MC/MCInstrItineraries.h"
-#include "llvm/MC/MCSchedule.h"
-#include "llvm/MC/SubtargetFeature.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <cstring>
-
-using namespace llvm;
-
-/// Find KV in array using binary search.
-template <typename T>
-static const T *Find(StringRef S, ArrayRef<T> A) {
- // Binary search the array
- auto F = llvm::lower_bound(A, S);
- // If not found then return NULL
- if (F == A.end() || StringRef(F->Key) != S) return nullptr;
- // Return the found array item
- return F;
-}
-
-/// For each feature that is (transitively) implied by this feature, set it.
-static
-void SetImpliedBits(FeatureBitset &Bits, const FeatureBitset &Implies,
- ArrayRef<SubtargetFeatureKV> FeatureTable) {
- // OR the Implies bits in outside the loop. This allows the Implies for CPUs
- // which might imply features not in FeatureTable to use this.
- Bits |= Implies;
- for (const SubtargetFeatureKV &FE : FeatureTable)
- if (Implies.test(FE.Value))
- SetImpliedBits(Bits, FE.Implies.getAsBitset(), FeatureTable);
-}
-
-/// For each feature that (transitively) implies this feature, clear it.
-static
-void ClearImpliedBits(FeatureBitset &Bits, unsigned Value,
- ArrayRef<SubtargetFeatureKV> FeatureTable) {
- for (const SubtargetFeatureKV &FE : FeatureTable) {
- if (FE.Implies.getAsBitset().test(Value)) {
- Bits.reset(FE.Value);
- ClearImpliedBits(Bits, FE.Value, FeatureTable);
- }
- }
-}
-
-static void ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature,
- ArrayRef<SubtargetFeatureKV> FeatureTable) {
- assert(SubtargetFeatures::hasFlag(Feature) &&
- "Feature flags should start with '+' or '-'");
-
- // Find feature in table.
- const SubtargetFeatureKV *FeatureEntry =
- Find(SubtargetFeatures::StripFlag(Feature), FeatureTable);
- // If there is a match
- if (FeatureEntry) {
- // Enable/disable feature in bits
- if (SubtargetFeatures::isEnabled(Feature)) {
- Bits.set(FeatureEntry->Value);
-
- // For each feature that this implies, set it.
- SetImpliedBits(Bits, FeatureEntry->Implies.getAsBitset(), FeatureTable);
- } else {
- Bits.reset(FeatureEntry->Value);
-
- // For each feature that implies this, clear it.
- ClearImpliedBits(Bits, FeatureEntry->Value, FeatureTable);
- }
- } else {
- errs() << "'" << Feature << "' is not a recognized feature for this target"
- << " (ignoring feature)\n";
- }
-}
-
-/// Return the length of the longest entry in the table.
-template <typename T>
-static size_t getLongestEntryLength(ArrayRef<T> Table) {
- size_t MaxLen = 0;
- for (auto &I : Table)
- MaxLen = std::max(MaxLen, std::strlen(I.Key));
- return MaxLen;
-}
-
-/// Display help for feature and mcpu choices.
-static void Help(ArrayRef<SubtargetSubTypeKV> CPUTable,
- ArrayRef<SubtargetFeatureKV> FeatTable) {
- // the static variable ensures that the help information only gets
- // printed once even though a target machine creates multiple subtargets
- static bool PrintOnce = false;
- if (PrintOnce) {
- return;
- }
-
- // Determine the length of the longest CPU and Feature entries.
- unsigned MaxCPULen = getLongestEntryLength(CPUTable);
- unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
-
- // Print the CPU table.
- errs() << "Available CPUs for this target:\n\n";
- for (auto &CPU : CPUTable)
- errs() << format(" %-*s - Select the %s processor.\n", MaxCPULen, CPU.Key,
- CPU.Key);
- errs() << '\n';
-
- // Print the Feature table.
- errs() << "Available features for this target:\n\n";
- for (auto &Feature : FeatTable)
- errs() << format(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
- errs() << '\n';
-
- errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
- "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
-
- PrintOnce = true;
-}
-
-/// Display help for mcpu choices only
-static void cpuHelp(ArrayRef<SubtargetSubTypeKV> CPUTable) {
- // the static variable ensures that the help information only gets
- // printed once even though a target machine creates multiple subtargets
- static bool PrintOnce = false;
- if (PrintOnce) {
- return;
- }
-
- // Print the CPU table.
- errs() << "Available CPUs for this target:\n\n";
- for (auto &CPU : CPUTable)
- errs() << "\t" << CPU.Key << "\n";
- errs() << '\n';
-
- errs() << "Use -mcpu or -mtune to specify the target's processor.\n"
- "For example, clang --target=aarch64-unknown-linux-gui "
- "-mcpu=cortex-a35\n";
-
- PrintOnce = true;
-}
-
-static FeatureBitset getFeatures(StringRef CPU, StringRef FS,
- ArrayRef<SubtargetSubTypeKV> ProcDesc,
- ArrayRef<SubtargetFeatureKV> ProcFeatures) {
- SubtargetFeatures Features(FS);
-
- if (ProcDesc.empty() || ProcFeatures.empty())
- return FeatureBitset();
-
- assert(std::is_sorted(std::begin(ProcDesc), std::end(ProcDesc)) &&
- "CPU table is not sorted");
- assert(std::is_sorted(std::begin(ProcFeatures), std::end(ProcFeatures)) &&
- "CPU features table is not sorted");
- // Resulting bits
- FeatureBitset Bits;
-
- // Check if help is needed
- if (CPU == "help")
- Help(ProcDesc, ProcFeatures);
-
- // Find CPU entry if CPU name is specified.
- else if (!CPU.empty()) {
- const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);
-
- // If there is a match
- if (CPUEntry) {
- // Set the features implied by this CPU feature, if any.
- SetImpliedBits(Bits, CPUEntry->Implies.getAsBitset(), ProcFeatures);
- } else {
- errs() << "'" << CPU << "' is not a recognized processor for this target"
- << " (ignoring processor)\n";
- }
- }
-
- // Iterate through each feature
- for (const std::string &Feature : Features.getFeatures()) {
- // Check for help
- if (Feature == "+help")
- Help(ProcDesc, ProcFeatures);
- else if (Feature == "+cpuHelp")
- cpuHelp(ProcDesc);
- else
- ApplyFeatureFlag(Bits, Feature, ProcFeatures);
- }
-
- return Bits;
-}
-
-void MCSubtargetInfo::InitMCProcessorInfo(StringRef CPU, StringRef FS) {
- FeatureBits = getFeatures(CPU, FS, ProcDesc, ProcFeatures);
- if (!CPU.empty())
- CPUSchedModel = &getSchedModelForCPU(CPU);
- else
- CPUSchedModel = &MCSchedModel::GetDefaultSchedModel();
-}
-
-void MCSubtargetInfo::setDefaultFeatures(StringRef CPU, StringRef FS) {
- FeatureBits = getFeatures(CPU, FS, ProcDesc, ProcFeatures);
-}
-
-MCSubtargetInfo::MCSubtargetInfo(
- const Triple &TT, StringRef C, StringRef FS,
- ArrayRef<SubtargetFeatureKV> PF, ArrayRef<SubtargetSubTypeKV> PD,
- const MCWriteProcResEntry *WPR,
- const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA,
- const InstrStage *IS, const unsigned *OC, const unsigned *FP)
- : TargetTriple(TT), CPU(C), ProcFeatures(PF), ProcDesc(PD),
- WriteProcResTable(WPR), WriteLatencyTable(WL),
- ReadAdvanceTable(RA), Stages(IS), OperandCycles(OC), ForwardingPaths(FP) {
- InitMCProcessorInfo(CPU, FS);
-}
-
-FeatureBitset MCSubtargetInfo::ToggleFeature(uint64_t FB) {
- FeatureBits.flip(FB);
- return FeatureBits;
-}
-
-FeatureBitset MCSubtargetInfo::ToggleFeature(const FeatureBitset &FB) {
- FeatureBits ^= FB;
- return FeatureBits;
-}
-
-FeatureBitset MCSubtargetInfo::SetFeatureBitsTransitively(
- const FeatureBitset &FB) {
- SetImpliedBits(FeatureBits, FB, ProcFeatures);
- return FeatureBits;
-}
-
-FeatureBitset MCSubtargetInfo::ClearFeatureBitsTransitively(
- const FeatureBitset &FB) {
- for (unsigned I = 0, E = FB.size(); I < E; I++) {
- if (FB[I]) {
- FeatureBits.reset(I);
- ClearImpliedBits(FeatureBits, I, ProcFeatures);
- }
- }
- return FeatureBits;
-}
-
-FeatureBitset MCSubtargetInfo::ToggleFeature(StringRef Feature) {
- // Find feature in table.
- const SubtargetFeatureKV *FeatureEntry =
- Find(SubtargetFeatures::StripFlag(Feature), ProcFeatures);
- // If there is a match
- if (FeatureEntry) {
- if (FeatureBits.test(FeatureEntry->Value)) {
- FeatureBits.reset(FeatureEntry->Value);
- // For each feature that implies this, clear it.
- ClearImpliedBits(FeatureBits, FeatureEntry->Value, ProcFeatures);
- } else {
- FeatureBits.set(FeatureEntry->Value);
-
- // For each feature that this implies, set it.
- SetImpliedBits(FeatureBits, FeatureEntry->Implies.getAsBitset(),
- ProcFeatures);
- }
- } else {
- errs() << "'" << Feature << "' is not a recognized feature for this target"
- << " (ignoring feature)\n";
- }
-
- return FeatureBits;
-}
-
-FeatureBitset MCSubtargetInfo::ApplyFeatureFlag(StringRef FS) {
- ::ApplyFeatureFlag(FeatureBits, FS, ProcFeatures);
- return FeatureBits;
-}
-
-bool MCSubtargetInfo::checkFeatures(StringRef FS) const {
- SubtargetFeatures T(FS);
- FeatureBitset Set, All;
- for (std::string F : T.getFeatures()) {
- ::ApplyFeatureFlag(Set, F, ProcFeatures);
- if (F[0] == '-')
- F[0] = '+';
- ::ApplyFeatureFlag(All, F, ProcFeatures);
- }
- return (FeatureBits & All) == Set;
-}
-
-const MCSchedModel &MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const {
- assert(std::is_sorted(ProcDesc.begin(), ProcDesc.end()) &&
- "Processor machine model table is not sorted");
-
- // Find entry
- const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);
-
- if (!CPUEntry) {
- if (CPU != "help") // Don't error if the user asked for help.
- errs() << "'" << CPU
- << "' is not a recognized processor for this target"
- << " (ignoring processor)\n";
- return MCSchedModel::GetDefaultSchedModel();
- }
- assert(CPUEntry->SchedModel && "Missing processor SchedModel value");
- return *CPUEntry->SchedModel;
-}
-
-InstrItineraryData
-MCSubtargetInfo::getInstrItineraryForCPU(StringRef CPU) const {
- const MCSchedModel &SchedModel = getSchedModelForCPU(CPU);
- return InstrItineraryData(SchedModel, Stages, OperandCycles, ForwardingPaths);
-}
-
-void MCSubtargetInfo::initInstrItins(InstrItineraryData &InstrItins) const {
- InstrItins = InstrItineraryData(getSchedModel(), Stages, OperandCycles,
- ForwardingPaths);
-}
diff --git a/contrib/llvm/lib/MC/MCSymbol.cpp b/contrib/llvm/lib/MC/MCSymbol.cpp
deleted file mode 100644
index 67cab9a92722..000000000000
--- a/contrib/llvm/lib/MC/MCSymbol.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-//===- lib/MC/MCSymbol.cpp - MCSymbol implementation ----------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCFragment.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <cstddef>
-
-using namespace llvm;
-
-// Only the address of this fragment is ever actually used.
-static MCDummyFragment SentinelFragment(nullptr);
-
-// Sentinel value for the absolute pseudo fragment.
-MCFragment *MCSymbol::AbsolutePseudoFragment = &SentinelFragment;
-
-void *MCSymbol::operator new(size_t s, const StringMapEntry<bool> *Name,
- MCContext &Ctx) {
- // We may need more space for a Name to account for alignment. So allocate
- // space for the storage type and not the name pointer.
- size_t Size = s + (Name ? sizeof(NameEntryStorageTy) : 0);
-
- // For safety, ensure that the alignment of a pointer is enough for an
- // MCSymbol. This also ensures we don't need padding between the name and
- // symbol.
- static_assert((unsigned)alignof(MCSymbol) <= alignof(NameEntryStorageTy),
- "Bad alignment of MCSymbol");
- void *Storage = Ctx.allocate(Size, alignof(NameEntryStorageTy));
- NameEntryStorageTy *Start = static_cast<NameEntryStorageTy*>(Storage);
- NameEntryStorageTy *End = Start + (Name ? 1 : 0);
- return End;
-}
-
-void MCSymbol::setVariableValue(const MCExpr *Value) {
- assert(!IsUsed && "Cannot set a variable that has already been used.");
- assert(Value && "Invalid variable value!");
- assert((SymbolContents == SymContentsUnset ||
- SymbolContents == SymContentsVariable) &&
- "Cannot give common/offset symbol a variable value");
- this->Value = Value;
- SymbolContents = SymContentsVariable;
- setUndefined();
-}
-
-void MCSymbol::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
- // The name for this MCSymbol is required to be a valid target name. However,
- // some targets support quoting names with funny characters. If the name
- // contains a funny character, then print it quoted.
- StringRef Name = getName();
- if (!MAI || MAI->isValidUnquotedName(Name)) {
- OS << Name;
- return;
- }
-
- if (MAI && !MAI->supportsNameQuoting())
- report_fatal_error("Symbol name with unsupported characters");
-
- OS << '"';
- for (char C : Name) {
- if (C == '\n')
- OS << "\\n";
- else if (C == '"')
- OS << "\\\"";
- else
- OS << C;
- }
- OS << '"';
-}
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void MCSymbol::dump() const {
- dbgs() << *this;
-}
-#endif
diff --git a/contrib/llvm/lib/MC/MCSymbolELF.cpp b/contrib/llvm/lib/MC/MCSymbolELF.cpp
deleted file mode 100644
index a07c56c64f84..000000000000
--- a/contrib/llvm/lib/MC/MCSymbolELF.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-//===- lib/MC/MCSymbolELF.cpp ---------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCSymbolELF.h"
-#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/MC/MCFixupKindInfo.h"
-
-namespace llvm {
-
-namespace {
-enum {
- // Shift value for STT_* flags. 7 possible values. 3 bits.
- ELF_STT_Shift = 0,
-
- // Shift value for STB_* flags. 4 possible values, 2 bits.
- ELF_STB_Shift = 3,
-
- // Shift value for STV_* flags. 4 possible values, 2 bits.
- ELF_STV_Shift = 5,
-
- // Shift value for STO_* flags. 3 bits. All the values are between 0x20 and
- // 0xe0, so we shift right by 5 before storing.
- ELF_STO_Shift = 7,
-
- // One bit.
- ELF_IsSignature_Shift = 10,
-
- // One bit.
- ELF_WeakrefUsedInReloc_Shift = 11,
-
- // One bit.
- ELF_BindingSet_Shift = 12
-};
-}
-
-void MCSymbolELF::setBinding(unsigned Binding) const {
- setIsBindingSet();
- if (getType() == ELF::STT_SECTION && Binding != ELF::STB_LOCAL)
- setType(ELF::STT_NOTYPE);
- unsigned Val;
- switch (Binding) {
- default:
- llvm_unreachable("Unsupported Binding");
- case ELF::STB_LOCAL:
- Val = 0;
- break;
- case ELF::STB_GLOBAL:
- Val = 1;
- break;
- case ELF::STB_WEAK:
- Val = 2;
- break;
- case ELF::STB_GNU_UNIQUE:
- Val = 3;
- break;
- }
- uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STB_Shift);
- setFlags(OtherFlags | (Val << ELF_STB_Shift));
-}
-
-unsigned MCSymbolELF::getBinding() const {
- if (isBindingSet()) {
- uint32_t Val = (Flags >> ELF_STB_Shift) & 3;
- switch (Val) {
- default:
- llvm_unreachable("Invalid value");
- case 0:
- return ELF::STB_LOCAL;
- case 1:
- return ELF::STB_GLOBAL;
- case 2:
- return ELF::STB_WEAK;
- case 3:
- return ELF::STB_GNU_UNIQUE;
- }
- }
-
- if (isDefined())
- return ELF::STB_LOCAL;
- if (isUsedInReloc())
- return ELF::STB_GLOBAL;
- if (isWeakrefUsedInReloc())
- return ELF::STB_WEAK;
- if (isSignature())
- return ELF::STB_LOCAL;
- return ELF::STB_GLOBAL;
-}
-
-void MCSymbolELF::setType(unsigned Type) const {
- unsigned Val;
- if (Type == ELF::STT_SECTION && getBinding() != ELF::STB_LOCAL)
- return;
- switch (Type) {
- default:
- llvm_unreachable("Unsupported Binding");
- case ELF::STT_NOTYPE:
- Val = 0;
- break;
- case ELF::STT_OBJECT:
- Val = 1;
- break;
- case ELF::STT_FUNC:
- Val = 2;
- break;
- case ELF::STT_SECTION:
- Val = 3;
- break;
- case ELF::STT_COMMON:
- Val = 4;
- break;
- case ELF::STT_TLS:
- Val = 5;
- break;
- case ELF::STT_GNU_IFUNC:
- Val = 6;
- break;
- }
- uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STT_Shift);
- setFlags(OtherFlags | (Val << ELF_STT_Shift));
-}
-
-unsigned MCSymbolELF::getType() const {
- uint32_t Val = (Flags >> ELF_STT_Shift) & 7;
- switch (Val) {
- default:
- llvm_unreachable("Invalid value");
- case 0:
- return ELF::STT_NOTYPE;
- case 1:
- return ELF::STT_OBJECT;
- case 2:
- return ELF::STT_FUNC;
- case 3:
- return ELF::STT_SECTION;
- case 4:
- return ELF::STT_COMMON;
- case 5:
- return ELF::STT_TLS;
- case 6:
- return ELF::STT_GNU_IFUNC;
- }
-}
-
-void MCSymbolELF::setVisibility(unsigned Visibility) {
- assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL ||
- Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED);
-
- uint32_t OtherFlags = getFlags() & ~(0x3 << ELF_STV_Shift);
- setFlags(OtherFlags | (Visibility << ELF_STV_Shift));
-}
-
-unsigned MCSymbolELF::getVisibility() const {
- unsigned Visibility = (Flags >> ELF_STV_Shift) & 3;
- return Visibility;
-}
-
-void MCSymbolELF::setOther(unsigned Other) {
- assert((Other & 0x1f) == 0);
- Other >>= 5;
- assert(Other <= 0x7);
- uint32_t OtherFlags = getFlags() & ~(0x7 << ELF_STO_Shift);
- setFlags(OtherFlags | (Other << ELF_STO_Shift));
-}
-
-unsigned MCSymbolELF::getOther() const {
- unsigned Other = (Flags >> ELF_STO_Shift) & 7;
- return Other << 5;
-}
-
-void MCSymbolELF::setIsWeakrefUsedInReloc() const {
- uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_WeakrefUsedInReloc_Shift);
- setFlags(OtherFlags | (1 << ELF_WeakrefUsedInReloc_Shift));
-}
-
-bool MCSymbolELF::isWeakrefUsedInReloc() const {
- return getFlags() & (0x1 << ELF_WeakrefUsedInReloc_Shift);
-}
-
-void MCSymbolELF::setIsSignature() const {
- uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_IsSignature_Shift);
- setFlags(OtherFlags | (1 << ELF_IsSignature_Shift));
-}
-
-bool MCSymbolELF::isSignature() const {
- return getFlags() & (0x1 << ELF_IsSignature_Shift);
-}
-
-void MCSymbolELF::setIsBindingSet() const {
- uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_BindingSet_Shift);
- setFlags(OtherFlags | (1 << ELF_BindingSet_Shift));
-}
-
-bool MCSymbolELF::isBindingSet() const {
- return getFlags() & (0x1 << ELF_BindingSet_Shift);
-}
-}
diff --git a/contrib/llvm/lib/MC/MCTargetOptions.cpp b/contrib/llvm/lib/MC/MCTargetOptions.cpp
deleted file mode 100644
index 96bb094134fe..000000000000
--- a/contrib/llvm/lib/MC/MCTargetOptions.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-//===- lib/MC/MCTargetOptions.cpp - MC Target Options ---------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCTargetOptions.h"
-#include "llvm/ADT/StringRef.h"
-
-using namespace llvm;
-
-MCTargetOptions::MCTargetOptions()
- : MCRelaxAll(false), MCNoExecStack(false), MCFatalWarnings(false),
- MCNoWarn(false), MCNoDeprecatedWarn(false), MCSaveTempLabels(false),
- MCUseDwarfDirectory(false), MCIncrementalLinkerCompatible(false),
- MCPIECopyRelocations(false), ShowMCEncoding(false), ShowMCInst(false),
- AsmVerbose(false), PreserveAsmComments(true) {}
-
-StringRef MCTargetOptions::getABIName() const {
- return ABIName;
-}
diff --git a/contrib/llvm/lib/MC/MCValue.cpp b/contrib/llvm/lib/MC/MCValue.cpp
deleted file mode 100644
index 81da47b2eced..000000000000
--- a/contrib/llvm/lib/MC/MCValue.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-//===- lib/MC/MCValue.cpp - MCValue implementation ------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCValue.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-void MCValue::print(raw_ostream &OS) const {
- if (isAbsolute()) {
- OS << getConstant();
- return;
- }
-
- // FIXME: prints as a number, which isn't ideal. But the meaning will be
- // target-specific anyway.
- if (getRefKind())
- OS << ':' << getRefKind() << ':';
-
- OS << *getSymA();
-
- if (getSymB()) {
- OS << " - ";
- OS << *getSymB();
- }
-
- if (getConstant())
- OS << " + " << getConstant();
-}
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void MCValue::dump() const {
- print(dbgs());
-}
-#endif
-
-MCSymbolRefExpr::VariantKind MCValue::getAccessVariant() const {
- const MCSymbolRefExpr *B = getSymB();
- if (B) {
- if (B->getKind() != MCSymbolRefExpr::VK_None)
- llvm_unreachable("unsupported");
- }
-
- const MCSymbolRefExpr *A = getSymA();
- if (!A)
- return MCSymbolRefExpr::VK_None;
-
- MCSymbolRefExpr::VariantKind Kind = A->getKind();
- if (Kind == MCSymbolRefExpr::VK_WEAKREF)
- return MCSymbolRefExpr::VK_None;
- return Kind;
-}
diff --git a/contrib/llvm/lib/MC/MCWasmObjectTargetWriter.cpp b/contrib/llvm/lib/MC/MCWasmObjectTargetWriter.cpp
deleted file mode 100644
index e46257823e34..000000000000
--- a/contrib/llvm/lib/MC/MCWasmObjectTargetWriter.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-//===-- MCWasmObjectTargetWriter.cpp - Wasm Target Writer Subclass --------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCWasmObjectWriter.h"
-
-using namespace llvm;
-
-MCWasmObjectTargetWriter::MCWasmObjectTargetWriter(bool Is64Bit)
- : Is64Bit(Is64Bit) {}
-
-// Pin the vtable to this object file
-MCWasmObjectTargetWriter::~MCWasmObjectTargetWriter() = default;
diff --git a/contrib/llvm/lib/MC/MCWasmStreamer.cpp b/contrib/llvm/lib/MC/MCWasmStreamer.cpp
deleted file mode 100644
index 86fa72197855..000000000000
--- a/contrib/llvm/lib/MC/MCWasmStreamer.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-//===- lib/MC/MCWasmStreamer.cpp - Wasm Object Output ---------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file assembles .s files and emits Wasm .o object files.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCWasmStreamer.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/MC/MCAsmLayout.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCCodeEmitter.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCObjectStreamer.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCSectionWasm.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCSymbolWasm.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/TargetRegistry.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-MCWasmStreamer::~MCWasmStreamer() = default; // anchor.
-
-void MCWasmStreamer::mergeFragment(MCDataFragment *DF, MCDataFragment *EF) {
- flushPendingLabels(DF, DF->getContents().size());
-
- for (unsigned I = 0, E = EF->getFixups().size(); I != E; ++I) {
- EF->getFixups()[I].setOffset(EF->getFixups()[I].getOffset() +
- DF->getContents().size());
- DF->getFixups().push_back(EF->getFixups()[I]);
- }
- if (DF->getSubtargetInfo() == nullptr && EF->getSubtargetInfo())
- DF->setHasInstructions(*EF->getSubtargetInfo());
- DF->getContents().append(EF->getContents().begin(), EF->getContents().end());
-}
-
-void MCWasmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
- // Let the target do whatever target specific stuff it needs to do.
- getAssembler().getBackend().handleAssemblerFlag(Flag);
-
- // Do any generic stuff we need to do.
- llvm_unreachable("invalid assembler flag!");
-}
-
-void MCWasmStreamer::ChangeSection(MCSection *Section,
- const MCExpr *Subsection) {
- MCAssembler &Asm = getAssembler();
- auto *SectionWasm = cast<MCSectionWasm>(Section);
- const MCSymbol *Grp = SectionWasm->getGroup();
- if (Grp)
- Asm.registerSymbol(*Grp);
-
- this->MCObjectStreamer::ChangeSection(Section, Subsection);
- Asm.registerSymbol(*Section->getBeginSymbol());
-}
-
-void MCWasmStreamer::EmitWeakReference(MCSymbol *Alias,
- const MCSymbol *Symbol) {
- getAssembler().registerSymbol(*Symbol);
- const MCExpr *Value = MCSymbolRefExpr::create(
- Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext());
- Alias->setVariableValue(Value);
-}
-
-bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
- assert(Attribute != MCSA_IndirectSymbol && "indirect symbols not supported");
-
- auto *Symbol = cast<MCSymbolWasm>(S);
-
- // Adding a symbol attribute always introduces the symbol; note that an
- // important side effect of calling registerSymbol here is to register the
- // symbol with the assembler.
- getAssembler().registerSymbol(*Symbol);
-
- switch (Attribute) {
- case MCSA_LazyReference:
- case MCSA_Reference:
- case MCSA_SymbolResolver:
- case MCSA_PrivateExtern:
- case MCSA_WeakDefinition:
- case MCSA_WeakDefAutoPrivate:
- case MCSA_Invalid:
- case MCSA_IndirectSymbol:
- case MCSA_Protected:
- return false;
-
- case MCSA_Hidden:
- Symbol->setHidden(true);
- break;
-
- case MCSA_Weak:
- case MCSA_WeakReference:
- Symbol->setWeak(true);
- Symbol->setExternal(true);
- break;
-
- case MCSA_Global:
- Symbol->setExternal(true);
- break;
-
- case MCSA_ELF_TypeFunction:
- Symbol->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
- break;
-
- case MCSA_ELF_TypeObject:
- case MCSA_Cold:
- break;
-
- case MCSA_NoDeadStrip:
- Symbol->setExported();
- break;
-
- default:
- // unrecognized directive
- llvm_unreachable("unexpected MCSymbolAttr");
- return false;
- }
-
- return true;
-}
-
-void MCWasmStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
- unsigned ByteAlignment) {
- llvm_unreachable("Common symbols are not yet implemented for Wasm");
-}
-
-void MCWasmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
- cast<MCSymbolWasm>(Symbol)->setSize(Value);
-}
-
-void MCWasmStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
- unsigned ByteAlignment) {
- llvm_unreachable("Local common symbols are not yet implemented for Wasm");
-}
-
-void MCWasmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
- SMLoc Loc) {
- MCObjectStreamer::EmitValueImpl(Value, Size, Loc);
-}
-
-void MCWasmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
- unsigned ValueSize,
- unsigned MaxBytesToEmit) {
- MCObjectStreamer::EmitValueToAlignment(ByteAlignment, Value, ValueSize,
- MaxBytesToEmit);
-}
-
-void MCWasmStreamer::EmitIdent(StringRef IdentString) {
- // TODO(sbc): Add the ident section once we support mergable strings
- // sections in the object format
-}
-
-void MCWasmStreamer::EmitInstToFragment(const MCInst &Inst,
- const MCSubtargetInfo &STI) {
- this->MCObjectStreamer::EmitInstToFragment(Inst, STI);
-}
-
-void MCWasmStreamer::EmitInstToData(const MCInst &Inst,
- const MCSubtargetInfo &STI) {
- MCAssembler &Assembler = getAssembler();
- SmallVector<MCFixup, 4> Fixups;
- SmallString<256> Code;
- raw_svector_ostream VecOS(Code);
- Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
-
- // Append the encoded instruction to the current data fragment (or create a
- // new such fragment if the current fragment is not a data fragment).
- MCDataFragment *DF = getOrCreateDataFragment();
-
- // Add the fixups and data.
- for (unsigned I = 0, E = Fixups.size(); I != E; ++I) {
- Fixups[I].setOffset(Fixups[I].getOffset() + DF->getContents().size());
- DF->getFixups().push_back(Fixups[I]);
- }
- DF->setHasInstructions(STI);
- DF->getContents().append(Code.begin(), Code.end());
-}
-
-void MCWasmStreamer::FinishImpl() {
- EmitFrames(nullptr);
-
- this->MCObjectStreamer::FinishImpl();
-}
-
-MCStreamer *llvm::createWasmStreamer(MCContext &Context,
- std::unique_ptr<MCAsmBackend> &&MAB,
- std::unique_ptr<MCObjectWriter> &&OW,
- std::unique_ptr<MCCodeEmitter> &&CE,
- bool RelaxAll) {
- MCWasmStreamer *S =
- new MCWasmStreamer(Context, std::move(MAB), std::move(OW), std::move(CE));
- if (RelaxAll)
- S->getAssembler().setRelaxAll(true);
- return S;
-}
-
-void MCWasmStreamer::EmitThumbFunc(MCSymbol *Func) {
- llvm_unreachable("Generic Wasm doesn't support this directive");
-}
-
-void MCWasmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
- llvm_unreachable("Wasm doesn't support this directive");
-}
-
-void MCWasmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment,
- SMLoc Loc) {
- llvm_unreachable("Wasm doesn't support this directive");
-}
-
-void MCWasmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment) {
- llvm_unreachable("Wasm doesn't support this directive");
-}
diff --git a/contrib/llvm/lib/MC/MCWin64EH.cpp b/contrib/llvm/lib/MC/MCWin64EH.cpp
deleted file mode 100644
index 4e9a29667097..000000000000
--- a/contrib/llvm/lib/MC/MCWin64EH.cpp
+++ /dev/null
@@ -1,680 +0,0 @@
-//===- lib/MC/MCWin64EH.cpp - MCWin64EH implementation --------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCWin64EH.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCObjectStreamer.h"
-#include "llvm/MC/MCSectionCOFF.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/Support/Win64EH.h"
-
-using namespace llvm;
-
-// NOTE: All relocations generated here are 4-byte image-relative.
-
-static uint8_t CountOfUnwindCodes(std::vector<WinEH::Instruction> &Insns) {
- uint8_t Count = 0;
- for (const auto &I : Insns) {
- switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
- default:
- llvm_unreachable("Unsupported unwind code");
- case Win64EH::UOP_PushNonVol:
- case Win64EH::UOP_AllocSmall:
- case Win64EH::UOP_SetFPReg:
- case Win64EH::UOP_PushMachFrame:
- Count += 1;
- break;
- case Win64EH::UOP_SaveNonVol:
- case Win64EH::UOP_SaveXMM128:
- Count += 2;
- break;
- case Win64EH::UOP_SaveNonVolBig:
- case Win64EH::UOP_SaveXMM128Big:
- Count += 3;
- break;
- case Win64EH::UOP_AllocLarge:
- Count += (I.Offset > 512 * 1024 - 8) ? 3 : 2;
- break;
- }
- }
- return Count;
-}
-
-static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
- const MCSymbol *RHS) {
- MCContext &Context = Streamer.getContext();
- const MCExpr *Diff =
- MCBinaryExpr::createSub(MCSymbolRefExpr::create(LHS, Context),
- MCSymbolRefExpr::create(RHS, Context), Context);
- Streamer.EmitValue(Diff, 1);
-}
-
-static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
- WinEH::Instruction &inst) {
- uint8_t b2;
- uint16_t w;
- b2 = (inst.Operation & 0x0F);
- switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
- default:
- llvm_unreachable("Unsupported unwind code");
- case Win64EH::UOP_PushNonVol:
- EmitAbsDifference(streamer, inst.Label, begin);
- b2 |= (inst.Register & 0x0F) << 4;
- streamer.EmitIntValue(b2, 1);
- break;
- case Win64EH::UOP_AllocLarge:
- EmitAbsDifference(streamer, inst.Label, begin);
- if (inst.Offset > 512 * 1024 - 8) {
- b2 |= 0x10;
- streamer.EmitIntValue(b2, 1);
- w = inst.Offset & 0xFFF8;
- streamer.EmitIntValue(w, 2);
- w = inst.Offset >> 16;
- } else {
- streamer.EmitIntValue(b2, 1);
- w = inst.Offset >> 3;
- }
- streamer.EmitIntValue(w, 2);
- break;
- case Win64EH::UOP_AllocSmall:
- b2 |= (((inst.Offset - 8) >> 3) & 0x0F) << 4;
- EmitAbsDifference(streamer, inst.Label, begin);
- streamer.EmitIntValue(b2, 1);
- break;
- case Win64EH::UOP_SetFPReg:
- EmitAbsDifference(streamer, inst.Label, begin);
- streamer.EmitIntValue(b2, 1);
- break;
- case Win64EH::UOP_SaveNonVol:
- case Win64EH::UOP_SaveXMM128:
- b2 |= (inst.Register & 0x0F) << 4;
- EmitAbsDifference(streamer, inst.Label, begin);
- streamer.EmitIntValue(b2, 1);
- w = inst.Offset >> 3;
- if (inst.Operation == Win64EH::UOP_SaveXMM128)
- w >>= 1;
- streamer.EmitIntValue(w, 2);
- break;
- case Win64EH::UOP_SaveNonVolBig:
- case Win64EH::UOP_SaveXMM128Big:
- b2 |= (inst.Register & 0x0F) << 4;
- EmitAbsDifference(streamer, inst.Label, begin);
- streamer.EmitIntValue(b2, 1);
- if (inst.Operation == Win64EH::UOP_SaveXMM128Big)
- w = inst.Offset & 0xFFF0;
- else
- w = inst.Offset & 0xFFF8;
- streamer.EmitIntValue(w, 2);
- w = inst.Offset >> 16;
- streamer.EmitIntValue(w, 2);
- break;
- case Win64EH::UOP_PushMachFrame:
- if (inst.Offset == 1)
- b2 |= 0x10;
- EmitAbsDifference(streamer, inst.Label, begin);
- streamer.EmitIntValue(b2, 1);
- break;
- }
-}
-
-static void EmitSymbolRefWithOfs(MCStreamer &streamer,
- const MCSymbol *Base,
- const MCSymbol *Other) {
- MCContext &Context = streamer.getContext();
- const MCSymbolRefExpr *BaseRef = MCSymbolRefExpr::create(Base, Context);
- const MCSymbolRefExpr *OtherRef = MCSymbolRefExpr::create(Other, Context);
- const MCExpr *Ofs = MCBinaryExpr::createSub(OtherRef, BaseRef, Context);
- const MCSymbolRefExpr *BaseRefRel = MCSymbolRefExpr::create(Base,
- MCSymbolRefExpr::VK_COFF_IMGREL32,
- Context);
- streamer.EmitValue(MCBinaryExpr::createAdd(BaseRefRel, Ofs, Context), 4);
-}
-
-static void EmitRuntimeFunction(MCStreamer &streamer,
- const WinEH::FrameInfo *info) {
- MCContext &context = streamer.getContext();
-
- streamer.EmitValueToAlignment(4);
- EmitSymbolRefWithOfs(streamer, info->Function, info->Begin);
- EmitSymbolRefWithOfs(streamer, info->Function, info->End);
- streamer.EmitValue(MCSymbolRefExpr::create(info->Symbol,
- MCSymbolRefExpr::VK_COFF_IMGREL32,
- context), 4);
-}
-
-static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
- // If this UNWIND_INFO already has a symbol, it's already been emitted.
- if (info->Symbol)
- return;
-
- MCContext &context = streamer.getContext();
- MCSymbol *Label = context.createTempSymbol();
-
- streamer.EmitValueToAlignment(4);
- streamer.EmitLabel(Label);
- info->Symbol = Label;
-
- // Upper 3 bits are the version number (currently 1).
- uint8_t flags = 0x01;
- if (info->ChainedParent)
- flags |= Win64EH::UNW_ChainInfo << 3;
- else {
- if (info->HandlesUnwind)
- flags |= Win64EH::UNW_TerminateHandler << 3;
- if (info->HandlesExceptions)
- flags |= Win64EH::UNW_ExceptionHandler << 3;
- }
- streamer.EmitIntValue(flags, 1);
-
- if (info->PrologEnd)
- EmitAbsDifference(streamer, info->PrologEnd, info->Begin);
- else
- streamer.EmitIntValue(0, 1);
-
- uint8_t numCodes = CountOfUnwindCodes(info->Instructions);
- streamer.EmitIntValue(numCodes, 1);
-
- uint8_t frame = 0;
- if (info->LastFrameInst >= 0) {
- WinEH::Instruction &frameInst = info->Instructions[info->LastFrameInst];
- assert(frameInst.Operation == Win64EH::UOP_SetFPReg);
- frame = (frameInst.Register & 0x0F) | (frameInst.Offset & 0xF0);
- }
- streamer.EmitIntValue(frame, 1);
-
- // Emit unwind instructions (in reverse order).
- uint8_t numInst = info->Instructions.size();
- for (uint8_t c = 0; c < numInst; ++c) {
- WinEH::Instruction inst = info->Instructions.back();
- info->Instructions.pop_back();
- EmitUnwindCode(streamer, info->Begin, inst);
- }
-
- // For alignment purposes, the instruction array will always have an even
- // number of entries, with the final entry potentially unused (in which case
- // the array will be one longer than indicated by the count of unwind codes
- // field).
- if (numCodes & 1) {
- streamer.EmitIntValue(0, 2);
- }
-
- if (flags & (Win64EH::UNW_ChainInfo << 3))
- EmitRuntimeFunction(streamer, info->ChainedParent);
- else if (flags &
- ((Win64EH::UNW_TerminateHandler|Win64EH::UNW_ExceptionHandler) << 3))
- streamer.EmitValue(MCSymbolRefExpr::create(info->ExceptionHandler,
- MCSymbolRefExpr::VK_COFF_IMGREL32,
- context), 4);
- else if (numCodes == 0) {
- // The minimum size of an UNWIND_INFO struct is 8 bytes. If we're not
- // a chained unwind info, if there is no handler, and if there are fewer
- // than 2 slots used in the unwind code array, we have to pad to 8 bytes.
- streamer.EmitIntValue(0, 4);
- }
-}
-
-void llvm::Win64EH::UnwindEmitter::Emit(MCStreamer &Streamer) const {
- // Emit the unwind info structs first.
- for (const auto &CFI : Streamer.getWinFrameInfos()) {
- MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
- Streamer.SwitchSection(XData);
- ::EmitUnwindInfo(Streamer, CFI.get());
- }
-
- // Now emit RUNTIME_FUNCTION entries.
- for (const auto &CFI : Streamer.getWinFrameInfos()) {
- MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
- Streamer.SwitchSection(PData);
- EmitRuntimeFunction(Streamer, CFI.get());
- }
-}
-
-void llvm::Win64EH::UnwindEmitter::EmitUnwindInfo(
- MCStreamer &Streamer, WinEH::FrameInfo *info) const {
- // Switch sections (the static function above is meant to be called from
- // here and from Emit().
- MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
- Streamer.SwitchSection(XData);
-
- ::EmitUnwindInfo(Streamer, info);
-}
-
-static int64_t GetAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
- const MCSymbol *RHS) {
- MCContext &Context = Streamer.getContext();
- const MCExpr *Diff =
- MCBinaryExpr::createSub(MCSymbolRefExpr::create(LHS, Context),
- MCSymbolRefExpr::create(RHS, Context), Context);
- MCObjectStreamer *OS = (MCObjectStreamer *)(&Streamer);
- // It should normally be possible to calculate the length of a function
- // at this point, but it might not be possible in the presence of certain
- // unusual constructs, like an inline asm with an alignment directive.
- int64_t value;
- if (!Diff->evaluateAsAbsolute(value, OS->getAssembler()))
- report_fatal_error("Failed to evaluate function length in SEH unwind info");
- return value;
-}
-
-static uint32_t
-ARM64CountOfUnwindCodes(const std::vector<WinEH::Instruction> &Insns) {
- uint32_t Count = 0;
- for (const auto &I : Insns) {
- switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
- default:
- llvm_unreachable("Unsupported ARM64 unwind code");
- case Win64EH::UOP_AllocSmall:
- Count += 1;
- break;
- case Win64EH::UOP_AllocMedium:
- Count += 2;
- break;
- case Win64EH::UOP_AllocLarge:
- Count += 4;
- break;
- case Win64EH::UOP_SaveFPLRX:
- Count += 1;
- break;
- case Win64EH::UOP_SaveFPLR:
- Count += 1;
- break;
- case Win64EH::UOP_SaveReg:
- Count += 2;
- break;
- case Win64EH::UOP_SaveRegP:
- Count += 2;
- break;
- case Win64EH::UOP_SaveRegPX:
- Count += 2;
- break;
- case Win64EH::UOP_SaveRegX:
- Count += 2;
- break;
- case Win64EH::UOP_SaveFReg:
- Count += 2;
- break;
- case Win64EH::UOP_SaveFRegP:
- Count += 2;
- break;
- case Win64EH::UOP_SaveFRegX:
- Count += 2;
- break;
- case Win64EH::UOP_SaveFRegPX:
- Count += 2;
- break;
- case Win64EH::UOP_SetFP:
- Count += 1;
- break;
- case Win64EH::UOP_AddFP:
- Count += 2;
- break;
- case Win64EH::UOP_Nop:
- Count += 1;
- break;
- case Win64EH::UOP_End:
- Count += 1;
- break;
- }
- }
- return Count;
-}
-
-// Unwind opcode encodings and restrictions are documented at
-// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
-static void ARM64EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
- WinEH::Instruction &inst) {
- uint8_t b, reg;
- switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
- default:
- llvm_unreachable("Unsupported ARM64 unwind code");
- case Win64EH::UOP_AllocSmall:
- b = (inst.Offset >> 4) & 0x1F;
- streamer.EmitIntValue(b, 1);
- break;
- case Win64EH::UOP_AllocMedium: {
- uint16_t hw = (inst.Offset >> 4) & 0x7FF;
- b = 0xC0;
- b |= (hw >> 8);
- streamer.EmitIntValue(b, 1);
- b = hw & 0xFF;
- streamer.EmitIntValue(b, 1);
- break;
- }
- case Win64EH::UOP_AllocLarge: {
- uint32_t w;
- b = 0xE0;
- streamer.EmitIntValue(b, 1);
- w = inst.Offset >> 4;
- b = (w & 0x00FF0000) >> 16;
- streamer.EmitIntValue(b, 1);
- b = (w & 0x0000FF00) >> 8;
- streamer.EmitIntValue(b, 1);
- b = w & 0x000000FF;
- streamer.EmitIntValue(b, 1);
- break;
- }
- case Win64EH::UOP_SetFP:
- b = 0xE1;
- streamer.EmitIntValue(b, 1);
- break;
- case Win64EH::UOP_AddFP:
- b = 0xE2;
- streamer.EmitIntValue(b, 1);
- b = (inst.Offset >> 3);
- streamer.EmitIntValue(b, 1);
- break;
- case Win64EH::UOP_Nop:
- b = 0xE3;
- streamer.EmitIntValue(b, 1);
- break;
- case Win64EH::UOP_SaveFPLRX:
- b = 0x80;
- b |= ((inst.Offset - 1) >> 3) & 0x3F;
- streamer.EmitIntValue(b, 1);
- break;
- case Win64EH::UOP_SaveFPLR:
- b = 0x40;
- b |= (inst.Offset >> 3) & 0x3F;
- streamer.EmitIntValue(b, 1);
- break;
- case Win64EH::UOP_SaveReg:
- assert(inst.Register >= 19 && "Saved reg must be >= 19");
- reg = inst.Register - 19;
- b = 0xD0 | ((reg & 0xC) >> 2);
- streamer.EmitIntValue(b, 1);
- b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
- streamer.EmitIntValue(b, 1);
- break;
- case Win64EH::UOP_SaveRegX:
- assert(inst.Register >= 19 && "Saved reg must be >= 19");
- reg = inst.Register - 19;
- b = 0xD4 | ((reg & 0x8) >> 3);
- streamer.EmitIntValue(b, 1);
- b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
- streamer.EmitIntValue(b, 1);
- break;
- case Win64EH::UOP_SaveRegP:
- assert(inst.Register >= 19 && "Saved registers must be >= 19");
- reg = inst.Register - 19;
- b = 0xC8 | ((reg & 0xC) >> 2);
- streamer.EmitIntValue(b, 1);
- b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
- streamer.EmitIntValue(b, 1);
- break;
- case Win64EH::UOP_SaveRegPX:
- assert(inst.Register >= 19 && "Saved registers must be >= 19");
- reg = inst.Register - 19;
- b = 0xCC | ((reg & 0xC) >> 2);
- streamer.EmitIntValue(b, 1);
- b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
- streamer.EmitIntValue(b, 1);
- break;
- case Win64EH::UOP_SaveFReg:
- assert(inst.Register >= 8 && "Saved dreg must be >= 8");
- reg = inst.Register - 8;
- b = 0xDC | ((reg & 0x4) >> 2);
- streamer.EmitIntValue(b, 1);
- b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
- streamer.EmitIntValue(b, 1);
- break;
- case Win64EH::UOP_SaveFRegX:
- assert(inst.Register >= 8 && "Saved dreg must be >= 8");
- reg = inst.Register - 8;
- b = 0xDE;
- streamer.EmitIntValue(b, 1);
- b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
- streamer.EmitIntValue(b, 1);
- break;
- case Win64EH::UOP_SaveFRegP:
- assert(inst.Register >= 8 && "Saved dregs must be >= 8");
- reg = inst.Register - 8;
- b = 0xD8 | ((reg & 0x4) >> 2);
- streamer.EmitIntValue(b, 1);
- b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
- streamer.EmitIntValue(b, 1);
- break;
- case Win64EH::UOP_SaveFRegPX:
- assert(inst.Register >= 8 && "Saved dregs must be >= 8");
- reg = inst.Register - 8;
- b = 0xDA | ((reg & 0x4) >> 2);
- streamer.EmitIntValue(b, 1);
- b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
- streamer.EmitIntValue(b, 1);
- break;
- case Win64EH::UOP_End:
- b = 0xE4;
- streamer.EmitIntValue(b, 1);
- break;
- }
-}
-
-// Returns the epilog symbol of an epilog with the exact same unwind code
-// sequence, if it exists. Otherwise, returns nulltpr.
-// EpilogInstrs - Unwind codes for the current epilog.
-// Epilogs - Epilogs that potentialy match the current epilog.
-static MCSymbol*
-FindMatchingEpilog(const std::vector<WinEH::Instruction>& EpilogInstrs,
- const std::vector<MCSymbol *>& Epilogs,
- const WinEH::FrameInfo *info) {
- for (auto *EpilogStart : Epilogs) {
- auto InstrsIter = info->EpilogMap.find(EpilogStart);
- assert(InstrsIter != info->EpilogMap.end() &&
- "Epilog not found in EpilogMap");
- const auto &Instrs = InstrsIter->second;
-
- if (Instrs.size() != EpilogInstrs.size())
- continue;
-
- bool Match = true;
- for (unsigned i = 0; i < Instrs.size(); ++i)
- if (Instrs[i].Operation != EpilogInstrs[i].Operation ||
- Instrs[i].Offset != EpilogInstrs[i].Offset ||
- Instrs[i].Register != EpilogInstrs[i].Register) {
- Match = false;
- break;
- }
-
- if (Match)
- return EpilogStart;
- }
- return nullptr;
-}
-
-// Populate the .xdata section. The format of .xdata on ARM64 is documented at
-// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
-static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
- // If this UNWIND_INFO already has a symbol, it's already been emitted.
- if (info->Symbol)
- return;
-
- MCContext &context = streamer.getContext();
- MCSymbol *Label = context.createTempSymbol();
-
- streamer.EmitValueToAlignment(4);
- streamer.EmitLabel(Label);
- info->Symbol = Label;
-
- int64_t RawFuncLength;
- if (!info->FuncletOrFuncEnd) {
- // FIXME: This is very wrong; we emit SEH data which covers zero bytes
- // of code. But otherwise test/MC/AArch64/seh.s crashes.
- RawFuncLength = 0;
- } else {
- // FIXME: GetAbsDifference tries to compute the length of the function
- // immediately, before the whole file is emitted, but in general
- // that's impossible: the size in bytes of certain assembler directives
- // like .align and .fill is not known until the whole file is parsed and
- // relaxations are applied. Currently, GetAbsDifference fails with a fatal
- // error in that case. (We mostly don't hit this because inline assembly
- // specifying those directives is rare, and we don't normally try to
- // align loops on AArch64.)
- //
- // There are two potential approaches to delaying the computation. One,
- // we could emit something like ".word (endfunc-beginfunc)/4+0x10800000",
- // as long as we have some conservative estimate we could use to prove
- // that we don't need to split the unwind data. Emitting the constant
- // is straightforward, but there's no existing code for estimating the
- // size of the function.
- //
- // The other approach would be to use a dedicated, relaxable fragment,
- // which could grow to accommodate splitting the unwind data if
- // necessary. This is more straightforward, since it automatically works
- // without any new infrastructure, and it's consistent with how we handle
- // relaxation in other contexts. But it would require some refactoring
- // to move parts of the pdata/xdata emission into the implementation of
- // a fragment. We could probably continue to encode the unwind codes
- // here, but we'd have to emit the pdata, the xdata header, and the
- // epilogue scopes later, since they depend on whether the we need to
- // split the unwind data.
- RawFuncLength = GetAbsDifference(streamer, info->FuncletOrFuncEnd,
- info->Begin);
- }
- if (RawFuncLength > 0xFFFFF)
- report_fatal_error("SEH unwind data splitting not yet implemented");
- uint32_t FuncLength = (uint32_t)RawFuncLength / 4;
- uint32_t PrologCodeBytes = ARM64CountOfUnwindCodes(info->Instructions);
- uint32_t TotalCodeBytes = PrologCodeBytes;
-
- // Process epilogs.
- MapVector<MCSymbol *, uint32_t> EpilogInfo;
- // Epilogs processed so far.
- std::vector<MCSymbol *> AddedEpilogs;
-
- for (auto &I : info->EpilogMap) {
- MCSymbol *EpilogStart = I.first;
- auto &EpilogInstrs = I.second;
- uint32_t CodeBytes = ARM64CountOfUnwindCodes(EpilogInstrs);
-
- MCSymbol* MatchingEpilog =
- FindMatchingEpilog(EpilogInstrs, AddedEpilogs, info);
- if (MatchingEpilog) {
- assert(EpilogInfo.find(MatchingEpilog) != EpilogInfo.end() &&
- "Duplicate epilog not found");
- EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
- // Clear the unwind codes in the EpilogMap, so that they don't get output
- // in the logic below.
- EpilogInstrs.clear();
- } else {
- EpilogInfo[EpilogStart] = TotalCodeBytes;
- TotalCodeBytes += CodeBytes;
- AddedEpilogs.push_back(EpilogStart);
- }
- }
-
- // Code Words, Epilog count, E, X, Vers, Function Length
- uint32_t row1 = 0x0;
- uint32_t CodeWords = TotalCodeBytes / 4;
- uint32_t CodeWordsMod = TotalCodeBytes % 4;
- if (CodeWordsMod)
- CodeWords++;
- uint32_t EpilogCount = info->EpilogMap.size();
- bool ExtensionWord = EpilogCount > 31 || TotalCodeBytes > 124;
- if (!ExtensionWord) {
- row1 |= (EpilogCount & 0x1F) << 22;
- row1 |= (CodeWords & 0x1F) << 27;
- }
- // E is always 0 right now, TODO: packed epilog setup
- if (info->HandlesExceptions) // X
- row1 |= 1 << 20;
- row1 |= FuncLength & 0x3FFFF;
- streamer.EmitIntValue(row1, 4);
-
- // Extended Code Words, Extended Epilog Count
- if (ExtensionWord) {
- // FIXME: We should be able to split unwind info into multiple sections.
- // FIXME: We should share epilog codes across epilogs, where possible,
- // which would make this issue show up less frequently.
- if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
- report_fatal_error("SEH unwind data splitting not yet implemented");
- uint32_t row2 = 0x0;
- row2 |= (CodeWords & 0xFF) << 16;
- row2 |= (EpilogCount & 0xFFFF);
- streamer.EmitIntValue(row2, 4);
- }
-
- // Epilog Start Index, Epilog Start Offset
- for (auto &I : EpilogInfo) {
- MCSymbol *EpilogStart = I.first;
- uint32_t EpilogIndex = I.second;
- uint32_t EpilogOffset =
- (uint32_t)GetAbsDifference(streamer, EpilogStart, info->Begin);
- if (EpilogOffset)
- EpilogOffset /= 4;
- uint32_t row3 = EpilogOffset;
- row3 |= (EpilogIndex & 0x3FF) << 22;
- streamer.EmitIntValue(row3, 4);
- }
-
- // Emit prolog unwind instructions (in reverse order).
- uint8_t numInst = info->Instructions.size();
- for (uint8_t c = 0; c < numInst; ++c) {
- WinEH::Instruction inst = info->Instructions.back();
- info->Instructions.pop_back();
- ARM64EmitUnwindCode(streamer, info->Begin, inst);
- }
-
- // Emit epilog unwind instructions
- for (auto &I : info->EpilogMap) {
- auto &EpilogInstrs = I.second;
- for (uint32_t i = 0; i < EpilogInstrs.size(); i++) {
- WinEH::Instruction inst = EpilogInstrs[i];
- ARM64EmitUnwindCode(streamer, info->Begin, inst);
- }
- }
-
- int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
- assert(BytesMod >= 0);
- for (int i = 0; i < BytesMod; i++)
- streamer.EmitIntValue(0xE3, 1);
-
- if (info->HandlesExceptions)
- streamer.EmitValue(
- MCSymbolRefExpr::create(info->ExceptionHandler,
- MCSymbolRefExpr::VK_COFF_IMGREL32, context),
- 4);
-}
-
-static void ARM64EmitRuntimeFunction(MCStreamer &streamer,
- const WinEH::FrameInfo *info) {
- MCContext &context = streamer.getContext();
-
- streamer.EmitValueToAlignment(4);
- EmitSymbolRefWithOfs(streamer, info->Function, info->Begin);
- streamer.EmitValue(MCSymbolRefExpr::create(info->Symbol,
- MCSymbolRefExpr::VK_COFF_IMGREL32,
- context),
- 4);
-}
-
-void llvm::Win64EH::ARM64UnwindEmitter::Emit(MCStreamer &Streamer) const {
- // Emit the unwind info structs first.
- for (const auto &CFI : Streamer.getWinFrameInfos()) {
- MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
- Streamer.SwitchSection(XData);
- ARM64EmitUnwindInfo(Streamer, CFI.get());
- }
-
- // Now emit RUNTIME_FUNCTION entries.
- for (const auto &CFI : Streamer.getWinFrameInfos()) {
- MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
- Streamer.SwitchSection(PData);
- ARM64EmitRuntimeFunction(Streamer, CFI.get());
- }
-}
-
-void llvm::Win64EH::ARM64UnwindEmitter::EmitUnwindInfo(
- MCStreamer &Streamer, WinEH::FrameInfo *info) const {
- // Switch sections (the static function above is meant to be called from
- // here and from Emit().
- MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
- Streamer.SwitchSection(XData);
- ARM64EmitUnwindInfo(Streamer, info);
-}
diff --git a/contrib/llvm/lib/MC/MCWinCOFFStreamer.cpp b/contrib/llvm/lib/MC/MCWinCOFFStreamer.cpp
deleted file mode 100644
index 04d5f100a2ff..000000000000
--- a/contrib/llvm/lib/MC/MCWinCOFFStreamer.cpp
+++ /dev/null
@@ -1,325 +0,0 @@
-//===- llvm/MC/MCWinCOFFStreamer.cpp --------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains an implementation of a Windows COFF object file streamer.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/COFF.h"
-#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCCodeEmitter.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCFixup.h"
-#include "llvm/MC/MCFragment.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCObjectStreamer.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCSymbolCOFF.h"
-#include "llvm/MC/MCWinCOFFStreamer.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/SMLoc.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <cstdint>
-
-using namespace llvm;
-
-#define DEBUG_TYPE "WinCOFFStreamer"
-
-MCWinCOFFStreamer::MCWinCOFFStreamer(MCContext &Context,
- std::unique_ptr<MCAsmBackend> MAB,
- std::unique_ptr<MCCodeEmitter> CE,
- std::unique_ptr<MCObjectWriter> OW)
- : MCObjectStreamer(Context, std::move(MAB), std::move(OW), std::move(CE)),
- CurSymbol(nullptr) {}
-
-void MCWinCOFFStreamer::EmitInstToData(const MCInst &Inst,
- const MCSubtargetInfo &STI) {
- MCDataFragment *DF = getOrCreateDataFragment();
-
- SmallVector<MCFixup, 4> Fixups;
- SmallString<256> Code;
- raw_svector_ostream VecOS(Code);
- getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
-
- // Add the fixups and data.
- for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
- Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
- DF->getFixups().push_back(Fixups[i]);
- }
- DF->setHasInstructions(STI);
- DF->getContents().append(Code.begin(), Code.end());
-}
-
-void MCWinCOFFStreamer::InitSections(bool NoExecStack) {
- // FIXME: this is identical to the ELF one.
- // This emulates the same behavior of GNU as. This makes it easier
- // to compare the output as the major sections are in the same order.
- SwitchSection(getContext().getObjectFileInfo()->getTextSection());
- EmitCodeAlignment(4);
-
- SwitchSection(getContext().getObjectFileInfo()->getDataSection());
- EmitCodeAlignment(4);
-
- SwitchSection(getContext().getObjectFileInfo()->getBSSSection());
- EmitCodeAlignment(4);
-
- SwitchSection(getContext().getObjectFileInfo()->getTextSection());
-}
-
-void MCWinCOFFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) {
- auto *Symbol = cast<MCSymbolCOFF>(S);
- MCObjectStreamer::EmitLabel(Symbol, Loc);
-}
-
-void MCWinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
- llvm_unreachable("not implemented");
-}
-
-void MCWinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) {
- llvm_unreachable("not implemented");
-}
-
-bool MCWinCOFFStreamer::EmitSymbolAttribute(MCSymbol *S,
- MCSymbolAttr Attribute) {
- auto *Symbol = cast<MCSymbolCOFF>(S);
- getAssembler().registerSymbol(*Symbol);
-
- switch (Attribute) {
- default: return false;
- case MCSA_WeakReference:
- case MCSA_Weak:
- Symbol->setIsWeakExternal();
- Symbol->setExternal(true);
- break;
- case MCSA_Global:
- Symbol->setExternal(true);
- break;
- case MCSA_AltEntry:
- llvm_unreachable("COFF doesn't support the .alt_entry attribute");
- }
-
- return true;
-}
-
-void MCWinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
- llvm_unreachable("not implemented");
-}
-
-void MCWinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *S) {
- auto *Symbol = cast<MCSymbolCOFF>(S);
- if (CurSymbol)
- Error("starting a new symbol definition without completing the "
- "previous one");
- CurSymbol = Symbol;
-}
-
-void MCWinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) {
- if (!CurSymbol) {
- Error("storage class specified outside of symbol definition");
- return;
- }
-
- if (StorageClass & ~COFF::SSC_Invalid) {
- Error("storage class value '" + Twine(StorageClass) +
- "' out of range");
- return;
- }
-
- getAssembler().registerSymbol(*CurSymbol);
- cast<MCSymbolCOFF>(CurSymbol)->setClass((uint16_t)StorageClass);
-}
-
-void MCWinCOFFStreamer::EmitCOFFSymbolType(int Type) {
- if (!CurSymbol) {
- Error("symbol type specified outside of a symbol definition");
- return;
- }
-
- if (Type & ~0xffff) {
- Error("type value '" + Twine(Type) + "' out of range");
- return;
- }
-
- getAssembler().registerSymbol(*CurSymbol);
- cast<MCSymbolCOFF>(CurSymbol)->setType((uint16_t)Type);
-}
-
-void MCWinCOFFStreamer::EndCOFFSymbolDef() {
- if (!CurSymbol)
- Error("ending symbol definition without starting one");
- CurSymbol = nullptr;
-}
-
-void MCWinCOFFStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
- // SafeSEH is a feature specific to 32-bit x86. It does not exist (and is
- // unnecessary) on all platforms which use table-based exception dispatch.
- if (getContext().getObjectFileInfo()->getTargetTriple().getArch() !=
- Triple::x86)
- return;
-
- const MCSymbolCOFF *CSymbol = cast<MCSymbolCOFF>(Symbol);
- if (CSymbol->isSafeSEH())
- return;
-
- MCSection *SXData = getContext().getObjectFileInfo()->getSXDataSection();
- getAssembler().registerSection(*SXData);
- if (SXData->getAlignment() < 4)
- SXData->setAlignment(4);
-
- new MCSymbolIdFragment(Symbol, SXData);
-
- getAssembler().registerSymbol(*Symbol);
- CSymbol->setIsSafeSEH();
-
- // The Microsoft linker requires that the symbol type of a handler be
- // function. Go ahead and oblige it here.
- CSymbol->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION
- << COFF::SCT_COMPLEX_TYPE_SHIFT);
-}
-
-void MCWinCOFFStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {
- MCSection *Sec = getCurrentSectionOnly();
- getAssembler().registerSection(*Sec);
- if (Sec->getAlignment() < 4)
- Sec->setAlignment(4);
-
- new MCSymbolIdFragment(Symbol, getCurrentSectionOnly());
-
- getAssembler().registerSymbol(*Symbol);
-}
-
-void MCWinCOFFStreamer::EmitCOFFSectionIndex(const MCSymbol *Symbol) {
- visitUsedSymbol(*Symbol);
- MCDataFragment *DF = getOrCreateDataFragment();
- const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext());
- MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, FK_SecRel_2);
- DF->getFixups().push_back(Fixup);
- DF->getContents().resize(DF->getContents().size() + 2, 0);
-}
-
-void MCWinCOFFStreamer::EmitCOFFSecRel32(const MCSymbol *Symbol,
- uint64_t Offset) {
- visitUsedSymbol(*Symbol);
- MCDataFragment *DF = getOrCreateDataFragment();
- // Create Symbol A for the relocation relative reference.
- const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext());
- // Add the constant offset, if given.
- if (Offset)
- MCE = MCBinaryExpr::createAdd(
- MCE, MCConstantExpr::create(Offset, getContext()), getContext());
- // Build the secrel32 relocation.
- MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_SecRel_4);
- // Record the relocation.
- DF->getFixups().push_back(Fixup);
- // Emit 4 bytes (zeros) to the object file.
- DF->getContents().resize(DF->getContents().size() + 4, 0);
-}
-
-void MCWinCOFFStreamer::EmitCOFFImgRel32(const MCSymbol *Symbol,
- int64_t Offset) {
- visitUsedSymbol(*Symbol);
- MCDataFragment *DF = getOrCreateDataFragment();
- // Create Symbol A for the relocation relative reference.
- const MCExpr *MCE = MCSymbolRefExpr::create(
- Symbol, MCSymbolRefExpr::VK_COFF_IMGREL32, getContext());
- // Add the constant offset, if given.
- if (Offset)
- MCE = MCBinaryExpr::createAdd(
- MCE, MCConstantExpr::create(Offset, getContext()), getContext());
- // Build the imgrel relocation.
- MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_Data_4);
- // Record the relocation.
- DF->getFixups().push_back(Fixup);
- // Emit 4 bytes (zeros) to the object file.
- DF->getContents().resize(DF->getContents().size() + 4, 0);
-}
-
-void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
- unsigned ByteAlignment) {
- auto *Symbol = cast<MCSymbolCOFF>(S);
-
- const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
- if (T.isWindowsMSVCEnvironment()) {
- if (ByteAlignment > 32)
- report_fatal_error("alignment is limited to 32-bytes");
-
- // Round size up to alignment so that we will honor the alignment request.
- Size = std::max(Size, static_cast<uint64_t>(ByteAlignment));
- }
-
- getAssembler().registerSymbol(*Symbol);
- Symbol->setExternal(true);
- Symbol->setCommon(Size, ByteAlignment);
-
- if (!T.isWindowsMSVCEnvironment() && ByteAlignment > 1) {
- SmallString<128> Directive;
- raw_svector_ostream OS(Directive);
- const MCObjectFileInfo *MFI = getContext().getObjectFileInfo();
-
- OS << " -aligncomm:\"" << Symbol->getName() << "\","
- << Log2_32_Ceil(ByteAlignment);
-
- PushSection();
- SwitchSection(MFI->getDrectveSection());
- EmitBytes(Directive);
- PopSection();
- }
-}
-
-void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
- unsigned ByteAlignment) {
- auto *Symbol = cast<MCSymbolCOFF>(S);
-
- MCSection *Section = getContext().getObjectFileInfo()->getBSSSection();
- PushSection();
- SwitchSection(Section);
- EmitValueToAlignment(ByteAlignment, 0, 1, 0);
- EmitLabel(Symbol);
- Symbol->setExternal(false);
- EmitZeros(Size);
- PopSection();
-}
-
-void MCWinCOFFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment,
- SMLoc Loc) {
- llvm_unreachable("not implemented");
-}
-
-void MCWinCOFFStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment) {
- llvm_unreachable("not implemented");
-}
-
-// TODO: Implement this if you want to emit .comment section in COFF obj files.
-void MCWinCOFFStreamer::EmitIdent(StringRef IdentString) {
- llvm_unreachable("not implemented");
-}
-
-void MCWinCOFFStreamer::EmitWinEHHandlerData(SMLoc Loc) {
- llvm_unreachable("not implemented");
-}
-
-void MCWinCOFFStreamer::FinishImpl() {
- MCObjectStreamer::FinishImpl();
-}
-
-void MCWinCOFFStreamer::Error(const Twine &Msg) const {
- getContext().reportError(SMLoc(), Msg);
-}
diff --git a/contrib/llvm/lib/MC/MCWinEH.cpp b/contrib/llvm/lib/MC/MCWinEH.cpp
deleted file mode 100644
index e58a0b2cf654..000000000000
--- a/contrib/llvm/lib/MC/MCWinEH.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-//===- lib/MC/MCWinEH.cpp - Windows EH implementation ---------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCWinEH.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/BinaryFormat/COFF.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCSectionCOFF.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbol.h"
-
-namespace llvm {
-namespace WinEH {
-
-UnwindEmitter::~UnwindEmitter() {}
-
-}
-}
-
diff --git a/contrib/llvm/lib/MC/MCXCOFFObjectTargetWriter.cpp b/contrib/llvm/lib/MC/MCXCOFFObjectTargetWriter.cpp
deleted file mode 100644
index 504e333cb2d4..000000000000
--- a/contrib/llvm/lib/MC/MCXCOFFObjectTargetWriter.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-//===- MCXCOFFObjectTargetWriter.cpp - XCOFF Target Writer Subclass -------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCXCOFFObjectWriter.h"
-
-using namespace llvm;
-
-MCXCOFFObjectTargetWriter::MCXCOFFObjectTargetWriter(bool Is64Bit)
- : Is64Bit(Is64Bit) {}
-
-MCXCOFFObjectTargetWriter::~MCXCOFFObjectTargetWriter() = default;
diff --git a/contrib/llvm/lib/MC/MCXCOFFStreamer.cpp b/contrib/llvm/lib/MC/MCXCOFFStreamer.cpp
deleted file mode 100644
index 071de024a3fa..000000000000
--- a/contrib/llvm/lib/MC/MCXCOFFStreamer.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-//===- lib/MC/MCXCOFFStreamer.cpp - XCOFF Object Output -------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file assembles .s files and emits XCOFF .o object files.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCXCOFFStreamer.h"
-#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/MC/MCCodeEmitter.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/Support/TargetRegistry.h"
-
-using namespace llvm;
-
-MCXCOFFStreamer::MCXCOFFStreamer(MCContext &Context,
- std::unique_ptr<MCAsmBackend> MAB,
- std::unique_ptr<MCObjectWriter> OW,
- std::unique_ptr<MCCodeEmitter> Emitter)
- : MCObjectStreamer(Context, std::move(MAB), std::move(OW),
- std::move(Emitter)) {}
-
-bool MCXCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
- MCSymbolAttr Attribute) {
- report_fatal_error("Symbol attributes not implemented for XCOFF.");
-}
-
-void MCXCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
- unsigned ByteAlignment) {
- report_fatal_error("Emiting common symbols not implemented for XCOFF.");
-}
-
-void MCXCOFFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
- uint64_t Size, unsigned ByteAlignment,
- SMLoc Loc) {
- report_fatal_error("Zero fill not implemented for XCOFF.");
-}
-
-void MCXCOFFStreamer::EmitInstToData(const MCInst &Inst,
- const MCSubtargetInfo &) {
- report_fatal_error("Instruction emission not implemented for XCOFF.");
-}
-
-MCStreamer *llvm::createXCOFFStreamer(MCContext &Context,
- std::unique_ptr<MCAsmBackend> &&MAB,
- std::unique_ptr<MCObjectWriter> &&OW,
- std::unique_ptr<MCCodeEmitter> &&CE,
- bool RelaxAll) {
- MCXCOFFStreamer *S = new MCXCOFFStreamer(Context, std::move(MAB),
- std::move(OW), std::move(CE));
- if (RelaxAll)
- S->getAssembler().setRelaxAll(true);
- return S;
-}
diff --git a/contrib/llvm/lib/MC/MachObjectWriter.cpp b/contrib/llvm/lib/MC/MachObjectWriter.cpp
deleted file mode 100644
index f0ceb86b25af..000000000000
--- a/contrib/llvm/lib/MC/MachObjectWriter.cpp
+++ /dev/null
@@ -1,1048 +0,0 @@
-//===- lib/MC/MachObjectWriter.cpp - Mach-O File Writer -------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/MC/MCAsmLayout.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDirectives.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCFixupKindInfo.h"
-#include "llvm/MC/MCFragment.h"
-#include "llvm/MC/MCMachObjectWriter.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCSectionMachO.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCSymbolMachO.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <cstdint>
-#include <string>
-#include <utility>
-#include <vector>
-
-using namespace llvm;
-
-#define DEBUG_TYPE "mc"
-
-void MachObjectWriter::reset() {
- Relocations.clear();
- IndirectSymBase.clear();
- StringTable.clear();
- LocalSymbolData.clear();
- ExternalSymbolData.clear();
- UndefinedSymbolData.clear();
- MCObjectWriter::reset();
-}
-
-bool MachObjectWriter::doesSymbolRequireExternRelocation(const MCSymbol &S) {
- // Undefined symbols are always extern.
- if (S.isUndefined())
- return true;
-
- // References to weak definitions require external relocation entries; the
- // definition may not always be the one in the same object file.
- if (cast<MCSymbolMachO>(S).isWeakDefinition())
- return true;
-
- // Otherwise, we can use an internal relocation.
- return false;
-}
-
-bool MachObjectWriter::
-MachSymbolData::operator<(const MachSymbolData &RHS) const {
- return Symbol->getName() < RHS.Symbol->getName();
-}
-
-bool MachObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) {
- const MCFixupKindInfo &FKI = Asm.getBackend().getFixupKindInfo(
- (MCFixupKind) Kind);
-
- return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel;
-}
-
-uint64_t MachObjectWriter::getFragmentAddress(const MCFragment *Fragment,
- const MCAsmLayout &Layout) const {
- return getSectionAddress(Fragment->getParent()) +
- Layout.getFragmentOffset(Fragment);
-}
-
-uint64_t MachObjectWriter::getSymbolAddress(const MCSymbol &S,
- const MCAsmLayout &Layout) const {
- // If this is a variable, then recursively evaluate now.
- if (S.isVariable()) {
- if (const MCConstantExpr *C =
- dyn_cast<const MCConstantExpr>(S.getVariableValue()))
- return C->getValue();
-
- MCValue Target;
- if (!S.getVariableValue()->evaluateAsRelocatable(Target, &Layout, nullptr))
- report_fatal_error("unable to evaluate offset for variable '" +
- S.getName() + "'");
-
- // Verify that any used symbols are defined.
- if (Target.getSymA() && Target.getSymA()->getSymbol().isUndefined())
- report_fatal_error("unable to evaluate offset to undefined symbol '" +
- Target.getSymA()->getSymbol().getName() + "'");
- if (Target.getSymB() && Target.getSymB()->getSymbol().isUndefined())
- report_fatal_error("unable to evaluate offset to undefined symbol '" +
- Target.getSymB()->getSymbol().getName() + "'");
-
- uint64_t Address = Target.getConstant();
- if (Target.getSymA())
- Address += getSymbolAddress(Target.getSymA()->getSymbol(), Layout);
- if (Target.getSymB())
- Address += getSymbolAddress(Target.getSymB()->getSymbol(), Layout);
- return Address;
- }
-
- return getSectionAddress(S.getFragment()->getParent()) +
- Layout.getSymbolOffset(S);
-}
-
-uint64_t MachObjectWriter::getPaddingSize(const MCSection *Sec,
- const MCAsmLayout &Layout) const {
- uint64_t EndAddr = getSectionAddress(Sec) + Layout.getSectionAddressSize(Sec);
- unsigned Next = Sec->getLayoutOrder() + 1;
- if (Next >= Layout.getSectionOrder().size())
- return 0;
-
- const MCSection &NextSec = *Layout.getSectionOrder()[Next];
- if (NextSec.isVirtualSection())
- return 0;
- return OffsetToAlignment(EndAddr, NextSec.getAlignment());
-}
-
-void MachObjectWriter::writeHeader(MachO::HeaderFileType Type,
- unsigned NumLoadCommands,
- unsigned LoadCommandsSize,
- bool SubsectionsViaSymbols) {
- uint32_t Flags = 0;
-
- if (SubsectionsViaSymbols)
- Flags |= MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
-
- // struct mach_header (28 bytes) or
- // struct mach_header_64 (32 bytes)
-
- uint64_t Start = W.OS.tell();
- (void) Start;
-
- W.write<uint32_t>(is64Bit() ? MachO::MH_MAGIC_64 : MachO::MH_MAGIC);
-
- W.write<uint32_t>(TargetObjectWriter->getCPUType());
- W.write<uint32_t>(TargetObjectWriter->getCPUSubtype());
-
- W.write<uint32_t>(Type);
- W.write<uint32_t>(NumLoadCommands);
- W.write<uint32_t>(LoadCommandsSize);
- W.write<uint32_t>(Flags);
- if (is64Bit())
- W.write<uint32_t>(0); // reserved
-
- assert(W.OS.tell() - Start == (is64Bit() ? sizeof(MachO::mach_header_64)
- : sizeof(MachO::mach_header)));
-}
-
-void MachObjectWriter::writeWithPadding(StringRef Str, uint64_t Size) {
- assert(Size >= Str.size());
- W.OS << Str;
- W.OS.write_zeros(Size - Str.size());
-}
-
-/// writeSegmentLoadCommand - Write a segment load command.
-///
-/// \param NumSections The number of sections in this segment.
-/// \param SectionDataSize The total size of the sections.
-void MachObjectWriter::writeSegmentLoadCommand(
- StringRef Name, unsigned NumSections, uint64_t VMAddr, uint64_t VMSize,
- uint64_t SectionDataStartOffset, uint64_t SectionDataSize, uint32_t MaxProt,
- uint32_t InitProt) {
- // struct segment_command (56 bytes) or
- // struct segment_command_64 (72 bytes)
-
- uint64_t Start = W.OS.tell();
- (void) Start;
-
- unsigned SegmentLoadCommandSize =
- is64Bit() ? sizeof(MachO::segment_command_64):
- sizeof(MachO::segment_command);
- W.write<uint32_t>(is64Bit() ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT);
- W.write<uint32_t>(SegmentLoadCommandSize +
- NumSections * (is64Bit() ? sizeof(MachO::section_64) :
- sizeof(MachO::section)));
-
- writeWithPadding(Name, 16);
- if (is64Bit()) {
- W.write<uint64_t>(VMAddr); // vmaddr
- W.write<uint64_t>(VMSize); // vmsize
- W.write<uint64_t>(SectionDataStartOffset); // file offset
- W.write<uint64_t>(SectionDataSize); // file size
- } else {
- W.write<uint32_t>(VMAddr); // vmaddr
- W.write<uint32_t>(VMSize); // vmsize
- W.write<uint32_t>(SectionDataStartOffset); // file offset
- W.write<uint32_t>(SectionDataSize); // file size
- }
- // maxprot
- W.write<uint32_t>(MaxProt);
- // initprot
- W.write<uint32_t>(InitProt);
- W.write<uint32_t>(NumSections);
- W.write<uint32_t>(0); // flags
-
- assert(W.OS.tell() - Start == SegmentLoadCommandSize);
-}
-
-void MachObjectWriter::writeSection(const MCAsmLayout &Layout,
- const MCSection &Sec, uint64_t VMAddr,
- uint64_t FileOffset, unsigned Flags,
- uint64_t RelocationsStart,
- unsigned NumRelocations) {
- uint64_t SectionSize = Layout.getSectionAddressSize(&Sec);
- const MCSectionMachO &Section = cast<MCSectionMachO>(Sec);
-
- // The offset is unused for virtual sections.
- if (Section.isVirtualSection()) {
- assert(Layout.getSectionFileSize(&Sec) == 0 && "Invalid file size!");
- FileOffset = 0;
- }
-
- // struct section (68 bytes) or
- // struct section_64 (80 bytes)
-
- uint64_t Start = W.OS.tell();
- (void) Start;
-
- writeWithPadding(Section.getSectionName(), 16);
- writeWithPadding(Section.getSegmentName(), 16);
- if (is64Bit()) {
- W.write<uint64_t>(VMAddr); // address
- W.write<uint64_t>(SectionSize); // size
- } else {
- W.write<uint32_t>(VMAddr); // address
- W.write<uint32_t>(SectionSize); // size
- }
- W.write<uint32_t>(FileOffset);
-
- assert(isPowerOf2_32(Section.getAlignment()) && "Invalid alignment!");
- W.write<uint32_t>(Log2_32(Section.getAlignment()));
- W.write<uint32_t>(NumRelocations ? RelocationsStart : 0);
- W.write<uint32_t>(NumRelocations);
- W.write<uint32_t>(Flags);
- W.write<uint32_t>(IndirectSymBase.lookup(&Sec)); // reserved1
- W.write<uint32_t>(Section.getStubSize()); // reserved2
- if (is64Bit())
- W.write<uint32_t>(0); // reserved3
-
- assert(W.OS.tell() - Start ==
- (is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section)));
-}
-
-void MachObjectWriter::writeSymtabLoadCommand(uint32_t SymbolOffset,
- uint32_t NumSymbols,
- uint32_t StringTableOffset,
- uint32_t StringTableSize) {
- // struct symtab_command (24 bytes)
-
- uint64_t Start = W.OS.tell();
- (void) Start;
-
- W.write<uint32_t>(MachO::LC_SYMTAB);
- W.write<uint32_t>(sizeof(MachO::symtab_command));
- W.write<uint32_t>(SymbolOffset);
- W.write<uint32_t>(NumSymbols);
- W.write<uint32_t>(StringTableOffset);
- W.write<uint32_t>(StringTableSize);
-
- assert(W.OS.tell() - Start == sizeof(MachO::symtab_command));
-}
-
-void MachObjectWriter::writeDysymtabLoadCommand(uint32_t FirstLocalSymbol,
- uint32_t NumLocalSymbols,
- uint32_t FirstExternalSymbol,
- uint32_t NumExternalSymbols,
- uint32_t FirstUndefinedSymbol,
- uint32_t NumUndefinedSymbols,
- uint32_t IndirectSymbolOffset,
- uint32_t NumIndirectSymbols) {
- // struct dysymtab_command (80 bytes)
-
- uint64_t Start = W.OS.tell();
- (void) Start;
-
- W.write<uint32_t>(MachO::LC_DYSYMTAB);
- W.write<uint32_t>(sizeof(MachO::dysymtab_command));
- W.write<uint32_t>(FirstLocalSymbol);
- W.write<uint32_t>(NumLocalSymbols);
- W.write<uint32_t>(FirstExternalSymbol);
- W.write<uint32_t>(NumExternalSymbols);
- W.write<uint32_t>(FirstUndefinedSymbol);
- W.write<uint32_t>(NumUndefinedSymbols);
- W.write<uint32_t>(0); // tocoff
- W.write<uint32_t>(0); // ntoc
- W.write<uint32_t>(0); // modtaboff
- W.write<uint32_t>(0); // nmodtab
- W.write<uint32_t>(0); // extrefsymoff
- W.write<uint32_t>(0); // nextrefsyms
- W.write<uint32_t>(IndirectSymbolOffset);
- W.write<uint32_t>(NumIndirectSymbols);
- W.write<uint32_t>(0); // extreloff
- W.write<uint32_t>(0); // nextrel
- W.write<uint32_t>(0); // locreloff
- W.write<uint32_t>(0); // nlocrel
-
- assert(W.OS.tell() - Start == sizeof(MachO::dysymtab_command));
-}
-
-MachObjectWriter::MachSymbolData *
-MachObjectWriter::findSymbolData(const MCSymbol &Sym) {
- for (auto *SymbolData :
- {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData})
- for (MachSymbolData &Entry : *SymbolData)
- if (Entry.Symbol == &Sym)
- return &Entry;
-
- return nullptr;
-}
-
-const MCSymbol &MachObjectWriter::findAliasedSymbol(const MCSymbol &Sym) const {
- const MCSymbol *S = &Sym;
- while (S->isVariable()) {
- const MCExpr *Value = S->getVariableValue();
- const auto *Ref = dyn_cast<MCSymbolRefExpr>(Value);
- if (!Ref)
- return *S;
- S = &Ref->getSymbol();
- }
- return *S;
-}
-
-void MachObjectWriter::writeNlist(MachSymbolData &MSD,
- const MCAsmLayout &Layout) {
- const MCSymbol *Symbol = MSD.Symbol;
- const MCSymbol &Data = *Symbol;
- const MCSymbol *AliasedSymbol = &findAliasedSymbol(*Symbol);
- uint8_t SectionIndex = MSD.SectionIndex;
- uint8_t Type = 0;
- uint64_t Address = 0;
- bool IsAlias = Symbol != AliasedSymbol;
-
- const MCSymbol &OrigSymbol = *Symbol;
- MachSymbolData *AliaseeInfo;
- if (IsAlias) {
- AliaseeInfo = findSymbolData(*AliasedSymbol);
- if (AliaseeInfo)
- SectionIndex = AliaseeInfo->SectionIndex;
- Symbol = AliasedSymbol;
- // FIXME: Should this update Data as well?
- }
-
- // Set the N_TYPE bits. See <mach-o/nlist.h>.
- //
- // FIXME: Are the prebound or indirect fields possible here?
- if (IsAlias && Symbol->isUndefined())
- Type = MachO::N_INDR;
- else if (Symbol->isUndefined())
- Type = MachO::N_UNDF;
- else if (Symbol->isAbsolute())
- Type = MachO::N_ABS;
- else
- Type = MachO::N_SECT;
-
- // FIXME: Set STAB bits.
-
- if (Data.isPrivateExtern())
- Type |= MachO::N_PEXT;
-
- // Set external bit.
- if (Data.isExternal() || (!IsAlias && Symbol->isUndefined()))
- Type |= MachO::N_EXT;
-
- // Compute the symbol address.
- if (IsAlias && Symbol->isUndefined())
- Address = AliaseeInfo->StringIndex;
- else if (Symbol->isDefined())
- Address = getSymbolAddress(OrigSymbol, Layout);
- else if (Symbol->isCommon()) {
- // Common symbols are encoded with the size in the address
- // field, and their alignment in the flags.
- Address = Symbol->getCommonSize();
- }
-
- // struct nlist (12 bytes)
-
- W.write<uint32_t>(MSD.StringIndex);
- W.OS << char(Type);
- W.OS << char(SectionIndex);
-
- // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
- // value.
- bool EncodeAsAltEntry =
- IsAlias && cast<MCSymbolMachO>(OrigSymbol).isAltEntry();
- W.write<uint16_t>(cast<MCSymbolMachO>(Symbol)->getEncodedFlags(EncodeAsAltEntry));
- if (is64Bit())
- W.write<uint64_t>(Address);
- else
- W.write<uint32_t>(Address);
-}
-
-void MachObjectWriter::writeLinkeditLoadCommand(uint32_t Type,
- uint32_t DataOffset,
- uint32_t DataSize) {
- uint64_t Start = W.OS.tell();
- (void) Start;
-
- W.write<uint32_t>(Type);
- W.write<uint32_t>(sizeof(MachO::linkedit_data_command));
- W.write<uint32_t>(DataOffset);
- W.write<uint32_t>(DataSize);
-
- assert(W.OS.tell() - Start == sizeof(MachO::linkedit_data_command));
-}
-
-static unsigned ComputeLinkerOptionsLoadCommandSize(
- const std::vector<std::string> &Options, bool is64Bit)
-{
- unsigned Size = sizeof(MachO::linker_option_command);
- for (const std::string &Option : Options)
- Size += Option.size() + 1;
- return alignTo(Size, is64Bit ? 8 : 4);
-}
-
-void MachObjectWriter::writeLinkerOptionsLoadCommand(
- const std::vector<std::string> &Options)
-{
- unsigned Size = ComputeLinkerOptionsLoadCommandSize(Options, is64Bit());
- uint64_t Start = W.OS.tell();
- (void) Start;
-
- W.write<uint32_t>(MachO::LC_LINKER_OPTION);
- W.write<uint32_t>(Size);
- W.write<uint32_t>(Options.size());
- uint64_t BytesWritten = sizeof(MachO::linker_option_command);
- for (const std::string &Option : Options) {
- // Write each string, including the null byte.
- W.OS << Option << '\0';
- BytesWritten += Option.size() + 1;
- }
-
- // Pad to a multiple of the pointer size.
- W.OS.write_zeros(OffsetToAlignment(BytesWritten, is64Bit() ? 8 : 4));
-
- assert(W.OS.tell() - Start == Size);
-}
-
-static bool isFixupTargetValid(const MCValue &Target) {
- // Target is (LHS - RHS + cst).
- // We don't support the form where LHS is null: -RHS + cst
- if (!Target.getSymA() && Target.getSymB())
- return false;
- return true;
-}
-
-void MachObjectWriter::recordRelocation(MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup, MCValue Target,
- uint64_t &FixedValue) {
- if (!isFixupTargetValid(Target)) {
- Asm.getContext().reportError(Fixup.getLoc(),
- "unsupported relocation expression");
- return;
- }
-
- TargetObjectWriter->recordRelocation(this, Asm, Layout, Fragment, Fixup,
- Target, FixedValue);
-}
-
-void MachObjectWriter::bindIndirectSymbols(MCAssembler &Asm) {
- // This is the point where 'as' creates actual symbols for indirect symbols
- // (in the following two passes). It would be easier for us to do this sooner
- // when we see the attribute, but that makes getting the order in the symbol
- // table much more complicated than it is worth.
- //
- // FIXME: Revisit this when the dust settles.
-
- // Report errors for use of .indirect_symbol not in a symbol pointer section
- // or stub section.
- for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
- ie = Asm.indirect_symbol_end(); it != ie; ++it) {
- const MCSectionMachO &Section = cast<MCSectionMachO>(*it->Section);
-
- if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS &&
- Section.getType() != MachO::S_LAZY_SYMBOL_POINTERS &&
- Section.getType() != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS &&
- Section.getType() != MachO::S_SYMBOL_STUBS) {
- MCSymbol &Symbol = *it->Symbol;
- report_fatal_error("indirect symbol '" + Symbol.getName() +
- "' not in a symbol pointer or stub section");
- }
- }
-
- // Bind non-lazy symbol pointers first.
- unsigned IndirectIndex = 0;
- for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
- ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) {
- const MCSectionMachO &Section = cast<MCSectionMachO>(*it->Section);
-
- if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS &&
- Section.getType() != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
- continue;
-
- // Initialize the section indirect symbol base, if necessary.
- IndirectSymBase.insert(std::make_pair(it->Section, IndirectIndex));
-
- Asm.registerSymbol(*it->Symbol);
- }
-
- // Then lazy symbol pointers and symbol stubs.
- IndirectIndex = 0;
- for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
- ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) {
- const MCSectionMachO &Section = cast<MCSectionMachO>(*it->Section);
-
- if (Section.getType() != MachO::S_LAZY_SYMBOL_POINTERS &&
- Section.getType() != MachO::S_SYMBOL_STUBS)
- continue;
-
- // Initialize the section indirect symbol base, if necessary.
- IndirectSymBase.insert(std::make_pair(it->Section, IndirectIndex));
-
- // Set the symbol type to undefined lazy, but only on construction.
- //
- // FIXME: Do not hardcode.
- bool Created;
- Asm.registerSymbol(*it->Symbol, &Created);
- if (Created)
- cast<MCSymbolMachO>(it->Symbol)->setReferenceTypeUndefinedLazy(true);
- }
-}
-
-/// computeSymbolTable - Compute the symbol table data
-void MachObjectWriter::computeSymbolTable(
- MCAssembler &Asm, std::vector<MachSymbolData> &LocalSymbolData,
- std::vector<MachSymbolData> &ExternalSymbolData,
- std::vector<MachSymbolData> &UndefinedSymbolData) {
- // Build section lookup table.
- DenseMap<const MCSection*, uint8_t> SectionIndexMap;
- unsigned Index = 1;
- for (MCAssembler::iterator it = Asm.begin(),
- ie = Asm.end(); it != ie; ++it, ++Index)
- SectionIndexMap[&*it] = Index;
- assert(Index <= 256 && "Too many sections!");
-
- // Build the string table.
- for (const MCSymbol &Symbol : Asm.symbols()) {
- if (!Asm.isSymbolLinkerVisible(Symbol))
- continue;
-
- StringTable.add(Symbol.getName());
- }
- StringTable.finalize();
-
- // Build the symbol arrays but only for non-local symbols.
- //
- // The particular order that we collect and then sort the symbols is chosen to
- // match 'as'. Even though it doesn't matter for correctness, this is
- // important for letting us diff .o files.
- for (const MCSymbol &Symbol : Asm.symbols()) {
- // Ignore non-linker visible symbols.
- if (!Asm.isSymbolLinkerVisible(Symbol))
- continue;
-
- if (!Symbol.isExternal() && !Symbol.isUndefined())
- continue;
-
- MachSymbolData MSD;
- MSD.Symbol = &Symbol;
- MSD.StringIndex = StringTable.getOffset(Symbol.getName());
-
- if (Symbol.isUndefined()) {
- MSD.SectionIndex = 0;
- UndefinedSymbolData.push_back(MSD);
- } else if (Symbol.isAbsolute()) {
- MSD.SectionIndex = 0;
- ExternalSymbolData.push_back(MSD);
- } else {
- MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
- assert(MSD.SectionIndex && "Invalid section index!");
- ExternalSymbolData.push_back(MSD);
- }
- }
-
- // Now add the data for local symbols.
- for (const MCSymbol &Symbol : Asm.symbols()) {
- // Ignore non-linker visible symbols.
- if (!Asm.isSymbolLinkerVisible(Symbol))
- continue;
-
- if (Symbol.isExternal() || Symbol.isUndefined())
- continue;
-
- MachSymbolData MSD;
- MSD.Symbol = &Symbol;
- MSD.StringIndex = StringTable.getOffset(Symbol.getName());
-
- if (Symbol.isAbsolute()) {
- MSD.SectionIndex = 0;
- LocalSymbolData.push_back(MSD);
- } else {
- MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
- assert(MSD.SectionIndex && "Invalid section index!");
- LocalSymbolData.push_back(MSD);
- }
- }
-
- // External and undefined symbols are required to be in lexicographic order.
- llvm::sort(ExternalSymbolData);
- llvm::sort(UndefinedSymbolData);
-
- // Set the symbol indices.
- Index = 0;
- for (auto *SymbolData :
- {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData})
- for (MachSymbolData &Entry : *SymbolData)
- Entry.Symbol->setIndex(Index++);
-
- for (const MCSection &Section : Asm) {
- for (RelAndSymbol &Rel : Relocations[&Section]) {
- if (!Rel.Sym)
- continue;
-
- // Set the Index and the IsExtern bit.
- unsigned Index = Rel.Sym->getIndex();
- assert(isInt<24>(Index));
- if (W.Endian == support::little)
- Rel.MRE.r_word1 = (Rel.MRE.r_word1 & (~0U << 24)) | Index | (1 << 27);
- else
- Rel.MRE.r_word1 = (Rel.MRE.r_word1 & 0xff) | Index << 8 | (1 << 4);
- }
- }
-}
-
-void MachObjectWriter::computeSectionAddresses(const MCAssembler &Asm,
- const MCAsmLayout &Layout) {
- uint64_t StartAddress = 0;
- for (const MCSection *Sec : Layout.getSectionOrder()) {
- StartAddress = alignTo(StartAddress, Sec->getAlignment());
- SectionAddress[Sec] = StartAddress;
- StartAddress += Layout.getSectionAddressSize(Sec);
-
- // Explicitly pad the section to match the alignment requirements of the
- // following one. This is for 'gas' compatibility, it shouldn't
- /// strictly be necessary.
- StartAddress += getPaddingSize(Sec, Layout);
- }
-}
-
-void MachObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
- const MCAsmLayout &Layout) {
- computeSectionAddresses(Asm, Layout);
-
- // Create symbol data for any indirect symbols.
- bindIndirectSymbols(Asm);
-}
-
-bool MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
- const MCAssembler &Asm, const MCSymbol &A, const MCSymbol &B,
- bool InSet) const {
- // FIXME: We don't handle things like
- // foo = .
- // creating atoms.
- if (A.isVariable() || B.isVariable())
- return false;
- return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, A, B,
- InSet);
-}
-
-bool MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
- const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB,
- bool InSet, bool IsPCRel) const {
- if (InSet)
- return true;
-
- // The effective address is
- // addr(atom(A)) + offset(A)
- // - addr(atom(B)) - offset(B)
- // and the offsets are not relocatable, so the fixup is fully resolved when
- // addr(atom(A)) - addr(atom(B)) == 0.
- const MCSymbol &SA = findAliasedSymbol(SymA);
- const MCSection &SecA = SA.getSection();
- const MCSection &SecB = *FB.getParent();
-
- if (IsPCRel) {
- // The simple (Darwin, except on x86_64) way of dealing with this was to
- // assume that any reference to a temporary symbol *must* be a temporary
- // symbol in the same atom, unless the sections differ. Therefore, any PCrel
- // relocation to a temporary symbol (in the same section) is fully
- // resolved. This also works in conjunction with absolutized .set, which
- // requires the compiler to use .set to absolutize the differences between
- // symbols which the compiler knows to be assembly time constants, so we
- // don't need to worry about considering symbol differences fully resolved.
- //
- // If the file isn't using sub-sections-via-symbols, we can make the
- // same assumptions about any symbol that we normally make about
- // assembler locals.
-
- bool hasReliableSymbolDifference = isX86_64();
- if (!hasReliableSymbolDifference) {
- if (!SA.isInSection() || &SecA != &SecB ||
- (!SA.isTemporary() && FB.getAtom() != SA.getFragment()->getAtom() &&
- Asm.getSubsectionsViaSymbols()))
- return false;
- return true;
- }
- // For Darwin x86_64, there is one special case when the reference IsPCRel.
- // If the fragment with the reference does not have a base symbol but meets
- // the simple way of dealing with this, in that it is a temporary symbol in
- // the same atom then it is assumed to be fully resolved. This is needed so
- // a relocation entry is not created and so the static linker does not
- // mess up the reference later.
- else if(!FB.getAtom() &&
- SA.isTemporary() && SA.isInSection() && &SecA == &SecB){
- return true;
- }
- }
-
- // If they are not in the same section, we can't compute the diff.
- if (&SecA != &SecB)
- return false;
-
- const MCFragment *FA = SA.getFragment();
-
- // Bail if the symbol has no fragment.
- if (!FA)
- return false;
-
- // If the atoms are the same, they are guaranteed to have the same address.
- if (FA->getAtom() == FB.getAtom())
- return true;
-
- // Otherwise, we can't prove this is fully resolved.
- return false;
-}
-
-static MachO::LoadCommandType getLCFromMCVM(MCVersionMinType Type) {
- switch (Type) {
- case MCVM_OSXVersionMin: return MachO::LC_VERSION_MIN_MACOSX;
- case MCVM_IOSVersionMin: return MachO::LC_VERSION_MIN_IPHONEOS;
- case MCVM_TvOSVersionMin: return MachO::LC_VERSION_MIN_TVOS;
- case MCVM_WatchOSVersionMin: return MachO::LC_VERSION_MIN_WATCHOS;
- }
- llvm_unreachable("Invalid mc version min type");
-}
-
-uint64_t MachObjectWriter::writeObject(MCAssembler &Asm,
- const MCAsmLayout &Layout) {
- uint64_t StartOffset = W.OS.tell();
-
- // Compute symbol table information and bind symbol indices.
- computeSymbolTable(Asm, LocalSymbolData, ExternalSymbolData,
- UndefinedSymbolData);
-
- unsigned NumSections = Asm.size();
- const MCAssembler::VersionInfoType &VersionInfo =
- Layout.getAssembler().getVersionInfo();
-
- // The section data starts after the header, the segment load command (and
- // section headers) and the symbol table.
- unsigned NumLoadCommands = 1;
- uint64_t LoadCommandsSize = is64Bit() ?
- sizeof(MachO::segment_command_64) + NumSections * sizeof(MachO::section_64):
- sizeof(MachO::segment_command) + NumSections * sizeof(MachO::section);
-
- // Add the deployment target version info load command size, if used.
- if (VersionInfo.Major != 0) {
- ++NumLoadCommands;
- if (VersionInfo.EmitBuildVersion)
- LoadCommandsSize += sizeof(MachO::build_version_command);
- else
- LoadCommandsSize += sizeof(MachO::version_min_command);
- }
-
- // Add the data-in-code load command size, if used.
- unsigned NumDataRegions = Asm.getDataRegions().size();
- if (NumDataRegions) {
- ++NumLoadCommands;
- LoadCommandsSize += sizeof(MachO::linkedit_data_command);
- }
-
- // Add the loh load command size, if used.
- uint64_t LOHRawSize = Asm.getLOHContainer().getEmitSize(*this, Layout);
- uint64_t LOHSize = alignTo(LOHRawSize, is64Bit() ? 8 : 4);
- if (LOHSize) {
- ++NumLoadCommands;
- LoadCommandsSize += sizeof(MachO::linkedit_data_command);
- }
-
- // Add the symbol table load command sizes, if used.
- unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() +
- UndefinedSymbolData.size();
- if (NumSymbols) {
- NumLoadCommands += 2;
- LoadCommandsSize += (sizeof(MachO::symtab_command) +
- sizeof(MachO::dysymtab_command));
- }
-
- // Add the linker option load commands sizes.
- for (const auto &Option : Asm.getLinkerOptions()) {
- ++NumLoadCommands;
- LoadCommandsSize += ComputeLinkerOptionsLoadCommandSize(Option, is64Bit());
- }
-
- // Compute the total size of the section data, as well as its file size and vm
- // size.
- uint64_t SectionDataStart = (is64Bit() ? sizeof(MachO::mach_header_64) :
- sizeof(MachO::mach_header)) + LoadCommandsSize;
- uint64_t SectionDataSize = 0;
- uint64_t SectionDataFileSize = 0;
- uint64_t VMSize = 0;
- for (const MCSection &Sec : Asm) {
- uint64_t Address = getSectionAddress(&Sec);
- uint64_t Size = Layout.getSectionAddressSize(&Sec);
- uint64_t FileSize = Layout.getSectionFileSize(&Sec);
- FileSize += getPaddingSize(&Sec, Layout);
-
- VMSize = std::max(VMSize, Address + Size);
-
- if (Sec.isVirtualSection())
- continue;
-
- SectionDataSize = std::max(SectionDataSize, Address + Size);
- SectionDataFileSize = std::max(SectionDataFileSize, Address + FileSize);
- }
-
- // The section data is padded to 4 bytes.
- //
- // FIXME: Is this machine dependent?
- unsigned SectionDataPadding = OffsetToAlignment(SectionDataFileSize, 4);
- SectionDataFileSize += SectionDataPadding;
-
- // Write the prolog, starting with the header and load command...
- writeHeader(MachO::MH_OBJECT, NumLoadCommands, LoadCommandsSize,
- Asm.getSubsectionsViaSymbols());
- uint32_t Prot =
- MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE;
- writeSegmentLoadCommand("", NumSections, 0, VMSize, SectionDataStart,
- SectionDataSize, Prot, Prot);
-
- // ... and then the section headers.
- uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;
- for (const MCSection &Section : Asm) {
- const auto &Sec = cast<MCSectionMachO>(Section);
- std::vector<RelAndSymbol> &Relocs = Relocations[&Sec];
- unsigned NumRelocs = Relocs.size();
- uint64_t SectionStart = SectionDataStart + getSectionAddress(&Sec);
- unsigned Flags = Sec.getTypeAndAttributes();
- if (Sec.hasInstructions())
- Flags |= MachO::S_ATTR_SOME_INSTRUCTIONS;
- writeSection(Layout, Sec, getSectionAddress(&Sec), SectionStart, Flags,
- RelocTableEnd, NumRelocs);
- RelocTableEnd += NumRelocs * sizeof(MachO::any_relocation_info);
- }
-
- // Write out the deployment target information, if it's available.
- if (VersionInfo.Major != 0) {
- auto EncodeVersion = [](VersionTuple V) -> uint32_t {
- assert(!V.empty() && "empty version");
- unsigned Update = V.getSubminor() ? *V.getSubminor() : 0;
- unsigned Minor = V.getMinor() ? *V.getMinor() : 0;
- assert(Update < 256 && "unencodable update target version");
- assert(Minor < 256 && "unencodable minor target version");
- assert(V.getMajor() < 65536 && "unencodable major target version");
- return Update | (Minor << 8) | (V.getMajor() << 16);
- };
- uint32_t EncodedVersion = EncodeVersion(
- VersionTuple(VersionInfo.Major, VersionInfo.Minor, VersionInfo.Update));
- uint32_t SDKVersion = !VersionInfo.SDKVersion.empty()
- ? EncodeVersion(VersionInfo.SDKVersion)
- : 0;
- if (VersionInfo.EmitBuildVersion) {
- // FIXME: Currently empty tools. Add clang version in the future.
- W.write<uint32_t>(MachO::LC_BUILD_VERSION);
- W.write<uint32_t>(sizeof(MachO::build_version_command));
- W.write<uint32_t>(VersionInfo.TypeOrPlatform.Platform);
- W.write<uint32_t>(EncodedVersion);
- W.write<uint32_t>(SDKVersion);
- W.write<uint32_t>(0); // Empty tools list.
- } else {
- MachO::LoadCommandType LCType
- = getLCFromMCVM(VersionInfo.TypeOrPlatform.Type);
- W.write<uint32_t>(LCType);
- W.write<uint32_t>(sizeof(MachO::version_min_command));
- W.write<uint32_t>(EncodedVersion);
- W.write<uint32_t>(SDKVersion);
- }
- }
-
- // Write the data-in-code load command, if used.
- uint64_t DataInCodeTableEnd = RelocTableEnd + NumDataRegions * 8;
- if (NumDataRegions) {
- uint64_t DataRegionsOffset = RelocTableEnd;
- uint64_t DataRegionsSize = NumDataRegions * 8;
- writeLinkeditLoadCommand(MachO::LC_DATA_IN_CODE, DataRegionsOffset,
- DataRegionsSize);
- }
-
- // Write the loh load command, if used.
- uint64_t LOHTableEnd = DataInCodeTableEnd + LOHSize;
- if (LOHSize)
- writeLinkeditLoadCommand(MachO::LC_LINKER_OPTIMIZATION_HINT,
- DataInCodeTableEnd, LOHSize);
-
- // Write the symbol table load command, if used.
- if (NumSymbols) {
- unsigned FirstLocalSymbol = 0;
- unsigned NumLocalSymbols = LocalSymbolData.size();
- unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols;
- unsigned NumExternalSymbols = ExternalSymbolData.size();
- unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols;
- unsigned NumUndefinedSymbols = UndefinedSymbolData.size();
- unsigned NumIndirectSymbols = Asm.indirect_symbol_size();
- unsigned NumSymTabSymbols =
- NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols;
- uint64_t IndirectSymbolSize = NumIndirectSymbols * 4;
- uint64_t IndirectSymbolOffset = 0;
-
- // If used, the indirect symbols are written after the section data.
- if (NumIndirectSymbols)
- IndirectSymbolOffset = LOHTableEnd;
-
- // The symbol table is written after the indirect symbol data.
- uint64_t SymbolTableOffset = LOHTableEnd + IndirectSymbolSize;
-
- // The string table is written after symbol table.
- uint64_t StringTableOffset =
- SymbolTableOffset + NumSymTabSymbols * (is64Bit() ?
- sizeof(MachO::nlist_64) :
- sizeof(MachO::nlist));
- writeSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols,
- StringTableOffset, StringTable.getSize());
-
- writeDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols,
- FirstExternalSymbol, NumExternalSymbols,
- FirstUndefinedSymbol, NumUndefinedSymbols,
- IndirectSymbolOffset, NumIndirectSymbols);
- }
-
- // Write the linker options load commands.
- for (const auto &Option : Asm.getLinkerOptions())
- writeLinkerOptionsLoadCommand(Option);
-
- // Write the actual section data.
- for (const MCSection &Sec : Asm) {
- Asm.writeSectionData(W.OS, &Sec, Layout);
-
- uint64_t Pad = getPaddingSize(&Sec, Layout);
- W.OS.write_zeros(Pad);
- }
-
- // Write the extra padding.
- W.OS.write_zeros(SectionDataPadding);
-
- // Write the relocation entries.
- for (const MCSection &Sec : Asm) {
- // Write the section relocation entries, in reverse order to match 'as'
- // (approximately, the exact algorithm is more complicated than this).
- std::vector<RelAndSymbol> &Relocs = Relocations[&Sec];
- for (const RelAndSymbol &Rel : make_range(Relocs.rbegin(), Relocs.rend())) {
- W.write<uint32_t>(Rel.MRE.r_word0);
- W.write<uint32_t>(Rel.MRE.r_word1);
- }
- }
-
- // Write out the data-in-code region payload, if there is one.
- for (MCAssembler::const_data_region_iterator
- it = Asm.data_region_begin(), ie = Asm.data_region_end();
- it != ie; ++it) {
- const DataRegionData *Data = &(*it);
- uint64_t Start = getSymbolAddress(*Data->Start, Layout);
- uint64_t End;
- if (Data->End)
- End = getSymbolAddress(*Data->End, Layout);
- else
- report_fatal_error("Data region not terminated");
-
- LLVM_DEBUG(dbgs() << "data in code region-- kind: " << Data->Kind
- << " start: " << Start << "(" << Data->Start->getName()
- << ")"
- << " end: " << End << "(" << Data->End->getName() << ")"
- << " size: " << End - Start << "\n");
- W.write<uint32_t>(Start);
- W.write<uint16_t>(End - Start);
- W.write<uint16_t>(Data->Kind);
- }
-
- // Write out the loh commands, if there is one.
- if (LOHSize) {
-#ifndef NDEBUG
- unsigned Start = W.OS.tell();
-#endif
- Asm.getLOHContainer().emit(*this, Layout);
- // Pad to a multiple of the pointer size.
- W.OS.write_zeros(OffsetToAlignment(LOHRawSize, is64Bit() ? 8 : 4));
- assert(W.OS.tell() - Start == LOHSize);
- }
-
- // Write the symbol table data, if used.
- if (NumSymbols) {
- // Write the indirect symbol entries.
- for (MCAssembler::const_indirect_symbol_iterator
- it = Asm.indirect_symbol_begin(),
- ie = Asm.indirect_symbol_end(); it != ie; ++it) {
- // Indirect symbols in the non-lazy symbol pointer section have some
- // special handling.
- const MCSectionMachO &Section =
- static_cast<const MCSectionMachO &>(*it->Section);
- if (Section.getType() == MachO::S_NON_LAZY_SYMBOL_POINTERS) {
- // If this symbol is defined and internal, mark it as such.
- if (it->Symbol->isDefined() && !it->Symbol->isExternal()) {
- uint32_t Flags = MachO::INDIRECT_SYMBOL_LOCAL;
- if (it->Symbol->isAbsolute())
- Flags |= MachO::INDIRECT_SYMBOL_ABS;
- W.write<uint32_t>(Flags);
- continue;
- }
- }
-
- W.write<uint32_t>(it->Symbol->getIndex());
- }
-
- // FIXME: Check that offsets match computed ones.
-
- // Write the symbol table entries.
- for (auto *SymbolData :
- {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData})
- for (MachSymbolData &Entry : *SymbolData)
- writeNlist(Entry, Layout);
-
- // Write the string table.
- StringTable.write(W.OS);
- }
-
- return W.OS.tell() - StartOffset;
-}
-
-std::unique_ptr<MCObjectWriter>
-llvm::createMachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW,
- raw_pwrite_stream &OS, bool IsLittleEndian) {
- return llvm::make_unique<MachObjectWriter>(std::move(MOTW), OS,
- IsLittleEndian);
-}
diff --git a/contrib/llvm/lib/MC/StringTableBuilder.cpp b/contrib/llvm/lib/MC/StringTableBuilder.cpp
deleted file mode 100644
index cb3db8e2268c..000000000000
--- a/contrib/llvm/lib/MC/StringTableBuilder.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-//===- StringTableBuilder.cpp - String table building utility -------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/StringTableBuilder.h"
-#include "llvm/ADT/CachedHashString.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/BinaryFormat/COFF.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-#include <cstring>
-#include <utility>
-#include <vector>
-
-using namespace llvm;
-
-StringTableBuilder::~StringTableBuilder() = default;
-
-void StringTableBuilder::initSize() {
- // Account for leading bytes in table so that offsets returned from add are
- // correct.
- switch (K) {
- case RAW:
- case DWARF:
- Size = 0;
- break;
- case MachO:
- case ELF:
- // Start the table with a NUL byte.
- Size = 1;
- break;
- case WinCOFF:
- // Make room to write the table size later.
- Size = 4;
- break;
- }
-}
-
-StringTableBuilder::StringTableBuilder(Kind K, unsigned Alignment)
- : K(K), Alignment(Alignment) {
- initSize();
-}
-
-void StringTableBuilder::write(raw_ostream &OS) const {
- assert(isFinalized());
- SmallString<0> Data;
- Data.resize(getSize());
- write((uint8_t *)Data.data());
- OS << Data;
-}
-
-using StringPair = std::pair<CachedHashStringRef, size_t>;
-
-void StringTableBuilder::write(uint8_t *Buf) const {
- assert(isFinalized());
- for (const StringPair &P : StringIndexMap) {
- StringRef Data = P.first.val();
- if (!Data.empty())
- memcpy(Buf + P.second, Data.data(), Data.size());
- }
- if (K != WinCOFF)
- return;
- support::endian::write32le(Buf, Size);
-}
-
-// Returns the character at Pos from end of a string.
-static int charTailAt(StringPair *P, size_t Pos) {
- StringRef S = P->first.val();
- if (Pos >= S.size())
- return -1;
- return (unsigned char)S[S.size() - Pos - 1];
-}
-
-// Three-way radix quicksort. This is much faster than std::sort with strcmp
-// because it does not compare characters that we already know the same.
-static void multikeySort(MutableArrayRef<StringPair *> Vec, int Pos) {
-tailcall:
- if (Vec.size() <= 1)
- return;
-
- // Partition items so that items in [0, I) are greater than the pivot,
- // [I, J) are the same as the pivot, and [J, Vec.size()) are less than
- // the pivot.
- int Pivot = charTailAt(Vec[0], Pos);
- size_t I = 0;
- size_t J = Vec.size();
- for (size_t K = 1; K < J;) {
- int C = charTailAt(Vec[K], Pos);
- if (C > Pivot)
- std::swap(Vec[I++], Vec[K++]);
- else if (C < Pivot)
- std::swap(Vec[--J], Vec[K]);
- else
- K++;
- }
-
- multikeySort(Vec.slice(0, I), Pos);
- multikeySort(Vec.slice(J), Pos);
-
- // multikeySort(Vec.slice(I, J - I), Pos + 1), but with
- // tail call optimization.
- if (Pivot != -1) {
- Vec = Vec.slice(I, J - I);
- ++Pos;
- goto tailcall;
- }
-}
-
-void StringTableBuilder::finalize() {
- assert(K != DWARF);
- finalizeStringTable(/*Optimize=*/true);
-}
-
-void StringTableBuilder::finalizeInOrder() {
- finalizeStringTable(/*Optimize=*/false);
-}
-
-void StringTableBuilder::finalizeStringTable(bool Optimize) {
- Finalized = true;
-
- if (Optimize) {
- std::vector<StringPair *> Strings;
- Strings.reserve(StringIndexMap.size());
- for (StringPair &P : StringIndexMap)
- Strings.push_back(&P);
-
- multikeySort(Strings, 0);
- initSize();
-
- StringRef Previous;
- for (StringPair *P : Strings) {
- StringRef S = P->first.val();
- if (Previous.endswith(S)) {
- size_t Pos = Size - S.size() - (K != RAW);
- if (!(Pos & (Alignment - 1))) {
- P->second = Pos;
- continue;
- }
- }
-
- Size = alignTo(Size, Alignment);
- P->second = Size;
-
- Size += S.size();
- if (K != RAW)
- ++Size;
- Previous = S;
- }
- }
-
- if (K == MachO)
- Size = alignTo(Size, 4); // Pad to multiple of 4.
-
- // The first byte in an ELF string table must be null, according to the ELF
- // specification. In 'initSize()' we reserved the first byte to hold null for
- // this purpose and here we actually add the string to allow 'getOffset()' to
- // be called on an empty string.
- if (K == ELF)
- StringIndexMap[CachedHashStringRef("")] = 0;
-}
-
-void StringTableBuilder::clear() {
- Finalized = false;
- StringIndexMap.clear();
-}
-
-size_t StringTableBuilder::getOffset(CachedHashStringRef S) const {
- assert(isFinalized());
- auto I = StringIndexMap.find(S);
- assert(I != StringIndexMap.end() && "String is not in table!");
- return I->second;
-}
-
-size_t StringTableBuilder::add(CachedHashStringRef S) {
- if (K == WinCOFF)
- assert(S.size() > COFF::NameSize && "Short string in COFF string table!");
-
- assert(!isFinalized());
- auto P = StringIndexMap.insert(std::make_pair(S, 0));
- if (P.second) {
- size_t Start = alignTo(Size, Alignment);
- P.first->second = Start;
- Size = Start + S.size() + (K != RAW);
- }
- return P.first->second;
-}
diff --git a/contrib/llvm/lib/MC/SubtargetFeature.cpp b/contrib/llvm/lib/MC/SubtargetFeature.cpp
deleted file mode 100644
index c4dd77359b24..000000000000
--- a/contrib/llvm/lib/MC/SubtargetFeature.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-//===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-/// \file Implements the SubtargetFeature interface.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/SubtargetFeature.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <cstring>
-#include <iterator>
-#include <string>
-#include <vector>
-
-using namespace llvm;
-
-/// Splits a string of comma separated items in to a vector of strings.
-void SubtargetFeatures::Split(std::vector<std::string> &V, StringRef S) {
- SmallVector<StringRef, 3> Tmp;
- S.split(Tmp, ',', -1, false /* KeepEmpty */);
- V.assign(Tmp.begin(), Tmp.end());
-}
-
-void SubtargetFeatures::AddFeature(StringRef String, bool Enable) {
- // Don't add empty features.
- if (!String.empty())
- // Convert to lowercase, prepend flag if we don't already have a flag.
- Features.push_back(hasFlag(String) ? String.lower()
- : (Enable ? "+" : "-") + String.lower());
-}
-
-SubtargetFeatures::SubtargetFeatures(StringRef Initial) {
- // Break up string into separate features
- Split(Features, Initial);
-}
-
-std::string SubtargetFeatures::getString() const {
- return join(Features.begin(), Features.end(), ",");
-}
-
-void SubtargetFeatures::print(raw_ostream &OS) const {
- for (auto &F : Features)
- OS << F << " ";
- OS << "\n";
-}
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void SubtargetFeatures::dump() const {
- print(dbgs());
-}
-#endif
-
-void SubtargetFeatures::getDefaultSubtargetFeatures(const Triple& Triple) {
- // FIXME: This is an inelegant way of specifying the features of a
- // subtarget. It would be better if we could encode this information
- // into the IR. See <rdar://5972456>.
- if (Triple.getVendor() == Triple::Apple) {
- if (Triple.getArch() == Triple::ppc) {
- // powerpc-apple-*
- AddFeature("altivec");
- } else if (Triple.getArch() == Triple::ppc64) {
- // powerpc64-apple-*
- AddFeature("64bit");
- AddFeature("altivec");
- }
- }
-}
diff --git a/contrib/llvm/lib/MC/WasmObjectWriter.cpp b/contrib/llvm/lib/MC/WasmObjectWriter.cpp
deleted file mode 100644
index 098343cd0107..000000000000
--- a/contrib/llvm/lib/MC/WasmObjectWriter.cpp
+++ /dev/null
@@ -1,1622 +0,0 @@
-//===- lib/MC/WasmObjectWriter.cpp - Wasm File Writer ---------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements Wasm object file writer information.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/BinaryFormat/Wasm.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/MC/MCAsmLayout.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCFixupKindInfo.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCSectionWasm.h"
-#include "llvm/MC/MCSymbolWasm.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/MC/MCWasmObjectWriter.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/LEB128.h"
-#include "llvm/Support/StringSaver.h"
-#include <vector>
-
-using namespace llvm;
-
-#define DEBUG_TYPE "mc"
-
-namespace {
-
-// Went we ceate the indirect function table we start at 1, so that there is
-// and emtpy slot at 0 and therefore calling a null function pointer will trap.
-static const uint32_t InitialTableOffset = 1;
-
-// For patching purposes, we need to remember where each section starts, both
-// for patching up the section size field, and for patching up references to
-// locations within the section.
-struct SectionBookkeeping {
- // Where the size of the section is written.
- uint64_t SizeOffset;
- // Where the section header ends (without custom section name).
- uint64_t PayloadOffset;
- // Where the contents of the section starts.
- uint64_t ContentsOffset;
- uint32_t Index;
-};
-
-// The signature of a wasm function or event, in a struct capable of being used
-// as a DenseMap key.
-// TODO: Consider using wasm::WasmSignature directly instead.
-struct WasmSignature {
- // Support empty and tombstone instances, needed by DenseMap.
- enum { Plain, Empty, Tombstone } State = Plain;
-
- // The return types of the function.
- SmallVector<wasm::ValType, 1> Returns;
-
- // The parameter types of the function.
- SmallVector<wasm::ValType, 4> Params;
-
- bool operator==(const WasmSignature &Other) const {
- return State == Other.State && Returns == Other.Returns &&
- Params == Other.Params;
- }
-};
-
-// Traits for using WasmSignature in a DenseMap.
-struct WasmSignatureDenseMapInfo {
- static WasmSignature getEmptyKey() {
- WasmSignature Sig;
- Sig.State = WasmSignature::Empty;
- return Sig;
- }
- static WasmSignature getTombstoneKey() {
- WasmSignature Sig;
- Sig.State = WasmSignature::Tombstone;
- return Sig;
- }
- static unsigned getHashValue(const WasmSignature &Sig) {
- uintptr_t Value = Sig.State;
- for (wasm::ValType Ret : Sig.Returns)
- Value += DenseMapInfo<uint32_t>::getHashValue(uint32_t(Ret));
- for (wasm::ValType Param : Sig.Params)
- Value += DenseMapInfo<uint32_t>::getHashValue(uint32_t(Param));
- return Value;
- }
- static bool isEqual(const WasmSignature &LHS, const WasmSignature &RHS) {
- return LHS == RHS;
- }
-};
-
-// A wasm data segment. A wasm binary contains only a single data section
-// but that can contain many segments, each with their own virtual location
-// in memory. Each MCSection data created by llvm is modeled as its own
-// wasm data segment.
-struct WasmDataSegment {
- MCSectionWasm *Section;
- StringRef Name;
- uint32_t InitFlags;
- uint32_t Offset;
- uint32_t Alignment;
- uint32_t LinkerFlags;
- SmallVector<char, 4> Data;
-};
-
-// A wasm function to be written into the function section.
-struct WasmFunction {
- uint32_t SigIndex;
- const MCSymbolWasm *Sym;
-};
-
-// A wasm global to be written into the global section.
-struct WasmGlobal {
- wasm::WasmGlobalType Type;
- uint64_t InitialValue;
-};
-
-// Information about a single item which is part of a COMDAT. For each data
-// segment or function which is in the COMDAT, there is a corresponding
-// WasmComdatEntry.
-struct WasmComdatEntry {
- unsigned Kind;
- uint32_t Index;
-};
-
-// Information about a single relocation.
-struct WasmRelocationEntry {
- uint64_t Offset; // Where is the relocation.
- const MCSymbolWasm *Symbol; // The symbol to relocate with.
- int64_t Addend; // A value to add to the symbol.
- unsigned Type; // The type of the relocation.
- const MCSectionWasm *FixupSection; // The section the relocation is targeting.
-
- WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol,
- int64_t Addend, unsigned Type,
- const MCSectionWasm *FixupSection)
- : Offset(Offset), Symbol(Symbol), Addend(Addend), Type(Type),
- FixupSection(FixupSection) {}
-
- bool hasAddend() const { return wasm::relocTypeHasAddend(Type); }
-
- void print(raw_ostream &Out) const {
- Out << wasm::relocTypetoString(Type) << " Off=" << Offset
- << ", Sym=" << *Symbol << ", Addend=" << Addend
- << ", FixupSection=" << FixupSection->getSectionName();
- }
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
- LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
-#endif
-};
-
-static const uint32_t InvalidIndex = -1;
-
-struct WasmCustomSection {
-
- StringRef Name;
- MCSectionWasm *Section;
-
- uint32_t OutputContentsOffset;
- uint32_t OutputIndex;
-
- WasmCustomSection(StringRef Name, MCSectionWasm *Section)
- : Name(Name), Section(Section), OutputContentsOffset(0),
- OutputIndex(InvalidIndex) {}
-};
-
-#if !defined(NDEBUG)
-raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) {
- Rel.print(OS);
- return OS;
-}
-#endif
-
-// Write X as an (unsigned) LEB value at offset Offset in Stream, padded
-// to allow patching.
-static void writePatchableLEB(raw_pwrite_stream &Stream, uint32_t X,
- uint64_t Offset) {
- uint8_t Buffer[5];
- unsigned SizeLen = encodeULEB128(X, Buffer, 5);
- assert(SizeLen == 5);
- Stream.pwrite((char *)Buffer, SizeLen, Offset);
-}
-
-// Write X as an signed LEB value at offset Offset in Stream, padded
-// to allow patching.
-static void writePatchableSLEB(raw_pwrite_stream &Stream, int32_t X,
- uint64_t Offset) {
- uint8_t Buffer[5];
- unsigned SizeLen = encodeSLEB128(X, Buffer, 5);
- assert(SizeLen == 5);
- Stream.pwrite((char *)Buffer, SizeLen, Offset);
-}
-
-// Write X as a plain integer value at offset Offset in Stream.
-static void writeI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
- uint8_t Buffer[4];
- support::endian::write32le(Buffer, X);
- Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
-}
-
-class WasmObjectWriter : public MCObjectWriter {
- support::endian::Writer W;
-
- /// The target specific Wasm writer instance.
- std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter;
-
- // Relocations for fixing up references in the code section.
- std::vector<WasmRelocationEntry> CodeRelocations;
- uint32_t CodeSectionIndex;
-
- // Relocations for fixing up references in the data section.
- std::vector<WasmRelocationEntry> DataRelocations;
- uint32_t DataSectionIndex;
-
- // Index values to use for fixing up call_indirect type indices.
- // Maps function symbols to the index of the type of the function
- DenseMap<const MCSymbolWasm *, uint32_t> TypeIndices;
- // Maps function symbols to the table element index space. Used
- // for TABLE_INDEX relocation types (i.e. address taken functions).
- DenseMap<const MCSymbolWasm *, uint32_t> TableIndices;
- // Maps function/global symbols to the function/global/event/section index
- // space.
- DenseMap<const MCSymbolWasm *, uint32_t> WasmIndices;
- DenseMap<const MCSymbolWasm *, uint32_t> GOTIndices;
- // Maps data symbols to the Wasm segment and offset/size with the segment.
- DenseMap<const MCSymbolWasm *, wasm::WasmDataReference> DataLocations;
-
- // Stores output data (index, relocations, content offset) for custom
- // section.
- std::vector<WasmCustomSection> CustomSections;
- std::unique_ptr<WasmCustomSection> ProducersSection;
- std::unique_ptr<WasmCustomSection> TargetFeaturesSection;
- // Relocations for fixing up references in the custom sections.
- DenseMap<const MCSectionWasm *, std::vector<WasmRelocationEntry>>
- CustomSectionsRelocations;
-
- // Map from section to defining function symbol.
- DenseMap<const MCSection *, const MCSymbol *> SectionFunctions;
-
- DenseMap<WasmSignature, uint32_t, WasmSignatureDenseMapInfo> SignatureIndices;
- SmallVector<WasmSignature, 4> Signatures;
- SmallVector<WasmDataSegment, 4> DataSegments;
- unsigned NumFunctionImports = 0;
- unsigned NumGlobalImports = 0;
- unsigned NumEventImports = 0;
- uint32_t SectionCount = 0;
-
- // TargetObjectWriter wrappers.
- bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
-
- void startSection(SectionBookkeeping &Section, unsigned SectionId);
- void startCustomSection(SectionBookkeeping &Section, StringRef Name);
- void endSection(SectionBookkeeping &Section);
-
-public:
- WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
- raw_pwrite_stream &OS)
- : W(OS, support::little), TargetObjectWriter(std::move(MOTW)) {}
-
-private:
- void reset() override {
- CodeRelocations.clear();
- DataRelocations.clear();
- TypeIndices.clear();
- WasmIndices.clear();
- GOTIndices.clear();
- TableIndices.clear();
- DataLocations.clear();
- CustomSections.clear();
- ProducersSection.reset();
- TargetFeaturesSection.reset();
- CustomSectionsRelocations.clear();
- SignatureIndices.clear();
- Signatures.clear();
- DataSegments.clear();
- SectionFunctions.clear();
- NumFunctionImports = 0;
- NumGlobalImports = 0;
- MCObjectWriter::reset();
- }
-
- void writeHeader(const MCAssembler &Asm);
-
- void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
- const MCFragment *Fragment, const MCFixup &Fixup,
- MCValue Target, uint64_t &FixedValue) override;
-
- void executePostLayoutBinding(MCAssembler &Asm,
- const MCAsmLayout &Layout) override;
-
- uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
-
- void writeString(const StringRef Str) {
- encodeULEB128(Str.size(), W.OS);
- W.OS << Str;
- }
-
- void writeValueType(wasm::ValType Ty) { W.OS << static_cast<char>(Ty); }
-
- void writeTypeSection(ArrayRef<WasmSignature> Signatures);
- void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint32_t DataSize,
- uint32_t NumElements);
- void writeFunctionSection(ArrayRef<WasmFunction> Functions);
- void writeExportSection(ArrayRef<wasm::WasmExport> Exports);
- void writeElemSection(ArrayRef<uint32_t> TableElems);
- void writeDataCountSection();
- void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
- ArrayRef<WasmFunction> Functions);
- void writeDataSection();
- void writeEventSection(ArrayRef<wasm::WasmEventType> Events);
- void writeRelocSection(uint32_t SectionIndex, StringRef Name,
- std::vector<WasmRelocationEntry> &Relocations);
- void writeLinkingMetaDataSection(
- ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
- ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
- const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats);
- void writeCustomSection(WasmCustomSection &CustomSection,
- const MCAssembler &Asm, const MCAsmLayout &Layout);
- void writeCustomRelocSections();
- void
- updateCustomSectionRelocations(const SmallVector<WasmFunction, 4> &Functions,
- const MCAsmLayout &Layout);
-
- uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry);
- void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
- uint64_t ContentsOffset);
-
- uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry);
- uint32_t getFunctionType(const MCSymbolWasm &Symbol);
- uint32_t getEventType(const MCSymbolWasm &Symbol);
- void registerFunctionType(const MCSymbolWasm &Symbol);
- void registerEventType(const MCSymbolWasm &Symbol);
-};
-
-} // end anonymous namespace
-
-// Write out a section header and a patchable section size field.
-void WasmObjectWriter::startSection(SectionBookkeeping &Section,
- unsigned SectionId) {
- LLVM_DEBUG(dbgs() << "startSection " << SectionId << "\n");
- W.OS << char(SectionId);
-
- Section.SizeOffset = W.OS.tell();
-
- // The section size. We don't know the size yet, so reserve enough space
- // for any 32-bit value; we'll patch it later.
- encodeULEB128(0, W.OS, 5);
-
- // The position where the section starts, for measuring its size.
- Section.ContentsOffset = W.OS.tell();
- Section.PayloadOffset = W.OS.tell();
- Section.Index = SectionCount++;
-}
-
-void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section,
- StringRef Name) {
- LLVM_DEBUG(dbgs() << "startCustomSection " << Name << "\n");
- startSection(Section, wasm::WASM_SEC_CUSTOM);
-
- // The position where the section header ends, for measuring its size.
- Section.PayloadOffset = W.OS.tell();
-
- // Custom sections in wasm also have a string identifier.
- writeString(Name);
-
- // The position where the custom section starts.
- Section.ContentsOffset = W.OS.tell();
-}
-
-// Now that the section is complete and we know how big it is, patch up the
-// section size field at the start of the section.
-void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
- uint64_t Size = W.OS.tell();
- // /dev/null doesn't support seek/tell and can report offset of 0.
- // Simply skip this patching in that case.
- if (!Size)
- return;
-
- Size -= Section.PayloadOffset;
- if (uint32_t(Size) != Size)
- report_fatal_error("section size does not fit in a uint32_t");
-
- LLVM_DEBUG(dbgs() << "endSection size=" << Size << "\n");
-
- // Write the final section size to the payload_len field, which follows
- // the section id byte.
- writePatchableLEB(static_cast<raw_pwrite_stream &>(W.OS), Size,
- Section.SizeOffset);
-}
-
-// Emit the Wasm header.
-void WasmObjectWriter::writeHeader(const MCAssembler &Asm) {
- W.OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
- W.write<uint32_t>(wasm::WasmVersion);
-}
-
-void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
- const MCAsmLayout &Layout) {
- // Build a map of sections to the function that defines them, for use
- // in recordRelocation.
- for (const MCSymbol &S : Asm.symbols()) {
- const auto &WS = static_cast<const MCSymbolWasm &>(S);
- if (WS.isDefined() && WS.isFunction() && !WS.isVariable()) {
- const auto &Sec = static_cast<const MCSectionWasm &>(S.getSection());
- auto Pair = SectionFunctions.insert(std::make_pair(&Sec, &S));
- if (!Pair.second)
- report_fatal_error("section already has a defining function: " +
- Sec.getSectionName());
- }
- }
-}
-
-void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup, MCValue Target,
- uint64_t &FixedValue) {
- MCAsmBackend &Backend = Asm.getBackend();
- bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
- MCFixupKindInfo::FKF_IsPCRel;
- const auto &FixupSection = cast<MCSectionWasm>(*Fragment->getParent());
- uint64_t C = Target.getConstant();
- uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
- MCContext &Ctx = Asm.getContext();
-
- // The .init_array isn't translated as data, so don't do relocations in it.
- if (FixupSection.getSectionName().startswith(".init_array"))
- return;
-
- if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
- assert(RefB->getKind() == MCSymbolRefExpr::VK_None &&
- "Should not have constructed this");
-
- // Let A, B and C being the components of Target and R be the location of
- // the fixup. If the fixup is not pcrel, we want to compute (A - B + C).
- // If it is pcrel, we want to compute (A - B + C - R).
-
- // In general, Wasm has no relocations for -B. It can only represent (A + C)
- // or (A + C - R). If B = R + K and the relocation is not pcrel, we can
- // replace B to implement it: (A - R - K + C)
- if (IsPCRel) {
- Ctx.reportError(
- Fixup.getLoc(),
- "No relocation available to represent this relative expression");
- return;
- }
-
- const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol());
-
- if (SymB.isUndefined()) {
- Ctx.reportError(Fixup.getLoc(),
- Twine("symbol '") + SymB.getName() +
- "' can not be undefined in a subtraction expression");
- return;
- }
-
- assert(!SymB.isAbsolute() && "Should have been folded");
- const MCSection &SecB = SymB.getSection();
- if (&SecB != &FixupSection) {
- Ctx.reportError(Fixup.getLoc(),
- "Cannot represent a difference across sections");
- return;
- }
-
- uint64_t SymBOffset = Layout.getSymbolOffset(SymB);
- uint64_t K = SymBOffset - FixupOffset;
- IsPCRel = true;
- C -= K;
- }
-
- // We either rejected the fixup or folded B into C at this point.
- const MCSymbolRefExpr *RefA = Target.getSymA();
- const auto *SymA = RefA ? cast<MCSymbolWasm>(&RefA->getSymbol()) : nullptr;
-
- if (SymA && SymA->isVariable()) {
- const MCExpr *Expr = SymA->getVariableValue();
- const auto *Inner = cast<MCSymbolRefExpr>(Expr);
- if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
- llvm_unreachable("weakref used in reloc not yet implemented");
- }
-
- // Put any constant offset in an addend. Offsets can be negative, and
- // LLVM expects wrapping, in contrast to wasm's immediates which can't
- // be negative and don't wrap.
- FixedValue = 0;
-
- unsigned Type = TargetObjectWriter->getRelocType(Target, Fixup);
- assert(!IsPCRel);
- assert(SymA);
-
- // Absolute offset within a section or a function.
- // Currently only supported for for metadata sections.
- // See: test/MC/WebAssembly/blockaddress.ll
- if (Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
- Type == wasm::R_WASM_SECTION_OFFSET_I32) {
- if (!FixupSection.getKind().isMetadata())
- report_fatal_error("relocations for function or section offsets are "
- "only supported in metadata sections");
-
- const MCSymbol *SectionSymbol = nullptr;
- const MCSection &SecA = SymA->getSection();
- if (SecA.getKind().isText())
- SectionSymbol = SectionFunctions.find(&SecA)->second;
- else
- SectionSymbol = SecA.getBeginSymbol();
- if (!SectionSymbol)
- report_fatal_error("section symbol is required for relocation");
-
- C += Layout.getSymbolOffset(*SymA);
- SymA = cast<MCSymbolWasm>(SectionSymbol);
- }
-
- // Relocation other than R_WASM_TYPE_INDEX_LEB are required to be
- // against a named symbol.
- if (Type != wasm::R_WASM_TYPE_INDEX_LEB) {
- if (SymA->getName().empty())
- report_fatal_error("relocations against un-named temporaries are not yet "
- "supported by wasm");
-
- SymA->setUsedInReloc();
- }
-
- if (RefA->getKind() == MCSymbolRefExpr::VK_GOT)
- SymA->setUsedInGOT();
-
- WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
- LLVM_DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
-
- if (FixupSection.isWasmData()) {
- DataRelocations.push_back(Rec);
- } else if (FixupSection.getKind().isText()) {
- CodeRelocations.push_back(Rec);
- } else if (FixupSection.getKind().isMetadata()) {
- CustomSectionsRelocations[&FixupSection].push_back(Rec);
- } else {
- llvm_unreachable("unexpected section type");
- }
-}
-
-static const MCSymbolWasm *resolveSymbol(const MCSymbolWasm &Symbol) {
- const MCSymbolWasm* Ret = &Symbol;
- while (Ret->isVariable()) {
- const MCExpr *Expr = Ret->getVariableValue();
- auto *Inner = cast<MCSymbolRefExpr>(Expr);
- Ret = cast<MCSymbolWasm>(&Inner->getSymbol());
- }
- return Ret;
-}
-
-// Compute a value to write into the code at the location covered
-// by RelEntry. This value isn't used by the static linker; it just serves
-// to make the object format more readable and more likely to be directly
-// useable.
-uint32_t
-WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
- if (RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_LEB && !RelEntry.Symbol->isGlobal()) {
- assert(GOTIndices.count(RelEntry.Symbol) > 0 && "symbol not found in GOT index space");
- return GOTIndices[RelEntry.Symbol];
- }
-
- switch (RelEntry.Type) {
- case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
- case wasm::R_WASM_TABLE_INDEX_SLEB:
- case wasm::R_WASM_TABLE_INDEX_I32: {
- // Provisional value is table address of the resolved symbol itself
- const MCSymbolWasm *Sym = resolveSymbol(*RelEntry.Symbol);
- assert(Sym->isFunction());
- return TableIndices[Sym];
- }
- case wasm::R_WASM_TYPE_INDEX_LEB:
- // Provisional value is same as the index
- return getRelocationIndexValue(RelEntry);
- case wasm::R_WASM_FUNCTION_INDEX_LEB:
- case wasm::R_WASM_GLOBAL_INDEX_LEB:
- case wasm::R_WASM_EVENT_INDEX_LEB:
- // Provisional value is function/global/event Wasm index
- assert(WasmIndices.count(RelEntry.Symbol) > 0 && "symbol not found in wasm index space");
- return WasmIndices[RelEntry.Symbol];
- case wasm::R_WASM_FUNCTION_OFFSET_I32:
- case wasm::R_WASM_SECTION_OFFSET_I32: {
- const auto &Section =
- static_cast<const MCSectionWasm &>(RelEntry.Symbol->getSection());
- return Section.getSectionOffset() + RelEntry.Addend;
- }
- case wasm::R_WASM_MEMORY_ADDR_LEB:
- case wasm::R_WASM_MEMORY_ADDR_I32:
- case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
- case wasm::R_WASM_MEMORY_ADDR_SLEB: {
- // Provisional value is address of the global
- const MCSymbolWasm *Sym = resolveSymbol(*RelEntry.Symbol);
- // For undefined symbols, use zero
- if (!Sym->isDefined())
- return 0;
- const wasm::WasmDataReference &Ref = DataLocations[Sym];
- const WasmDataSegment &Segment = DataSegments[Ref.Segment];
- // Ignore overflow. LLVM allows address arithmetic to silently wrap.
- return Segment.Offset + Ref.Offset + RelEntry.Addend;
- }
- default:
- llvm_unreachable("invalid relocation type");
- }
-}
-
-static void addData(SmallVectorImpl<char> &DataBytes,
- MCSectionWasm &DataSection) {
- LLVM_DEBUG(errs() << "addData: " << DataSection.getSectionName() << "\n");
-
- DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
-
- for (const MCFragment &Frag : DataSection) {
- if (Frag.hasInstructions())
- report_fatal_error("only data supported in data sections");
-
- if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) {
- if (Align->getValueSize() != 1)
- report_fatal_error("only byte values supported for alignment");
- // If nops are requested, use zeros, as this is the data section.
- uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
- uint64_t Size =
- std::min<uint64_t>(alignTo(DataBytes.size(), Align->getAlignment()),
- DataBytes.size() + Align->getMaxBytesToEmit());
- DataBytes.resize(Size, Value);
- } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
- int64_t NumValues;
- if (!Fill->getNumValues().evaluateAsAbsolute(NumValues))
- llvm_unreachable("The fill should be an assembler constant");
- DataBytes.insert(DataBytes.end(), Fill->getValueSize() * NumValues,
- Fill->getValue());
- } else if (auto *LEB = dyn_cast<MCLEBFragment>(&Frag)) {
- const SmallVectorImpl<char> &Contents = LEB->getContents();
- DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
- } else {
- const auto &DataFrag = cast<MCDataFragment>(Frag);
- const SmallVectorImpl<char> &Contents = DataFrag.getContents();
- DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
- }
- }
-
- LLVM_DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n");
-}
-
-uint32_t
-WasmObjectWriter::getRelocationIndexValue(const WasmRelocationEntry &RelEntry) {
- if (RelEntry.Type == wasm::R_WASM_TYPE_INDEX_LEB) {
- if (!TypeIndices.count(RelEntry.Symbol))
- report_fatal_error("symbol not found in type index space: " +
- RelEntry.Symbol->getName());
- return TypeIndices[RelEntry.Symbol];
- }
-
- return RelEntry.Symbol->getIndex();
-}
-
-// Apply the portions of the relocation records that we can handle ourselves
-// directly.
-void WasmObjectWriter::applyRelocations(
- ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset) {
- auto &Stream = static_cast<raw_pwrite_stream &>(W.OS);
- for (const WasmRelocationEntry &RelEntry : Relocations) {
- uint64_t Offset = ContentsOffset +
- RelEntry.FixupSection->getSectionOffset() +
- RelEntry.Offset;
-
- LLVM_DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
- uint32_t Value = getProvisionalValue(RelEntry);
-
- switch (RelEntry.Type) {
- case wasm::R_WASM_FUNCTION_INDEX_LEB:
- case wasm::R_WASM_TYPE_INDEX_LEB:
- case wasm::R_WASM_GLOBAL_INDEX_LEB:
- case wasm::R_WASM_MEMORY_ADDR_LEB:
- case wasm::R_WASM_EVENT_INDEX_LEB:
- writePatchableLEB(Stream, Value, Offset);
- break;
- case wasm::R_WASM_TABLE_INDEX_I32:
- case wasm::R_WASM_MEMORY_ADDR_I32:
- case wasm::R_WASM_FUNCTION_OFFSET_I32:
- case wasm::R_WASM_SECTION_OFFSET_I32:
- writeI32(Stream, Value, Offset);
- break;
- case wasm::R_WASM_TABLE_INDEX_SLEB:
- case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
- case wasm::R_WASM_MEMORY_ADDR_SLEB:
- case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
- writePatchableSLEB(Stream, Value, Offset);
- break;
- default:
- llvm_unreachable("invalid relocation type");
- }
- }
-}
-
-void WasmObjectWriter::writeTypeSection(ArrayRef<WasmSignature> Signatures) {
- if (Signatures.empty())
- return;
-
- SectionBookkeeping Section;
- startSection(Section, wasm::WASM_SEC_TYPE);
-
- encodeULEB128(Signatures.size(), W.OS);
-
- for (const WasmSignature &Sig : Signatures) {
- W.OS << char(wasm::WASM_TYPE_FUNC);
- encodeULEB128(Sig.Params.size(), W.OS);
- for (wasm::ValType Ty : Sig.Params)
- writeValueType(Ty);
- encodeULEB128(Sig.Returns.size(), W.OS);
- for (wasm::ValType Ty : Sig.Returns)
- writeValueType(Ty);
- }
-
- endSection(Section);
-}
-
-void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports,
- uint32_t DataSize,
- uint32_t NumElements) {
- if (Imports.empty())
- return;
-
- uint32_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize;
-
- SectionBookkeeping Section;
- startSection(Section, wasm::WASM_SEC_IMPORT);
-
- encodeULEB128(Imports.size(), W.OS);
- for (const wasm::WasmImport &Import : Imports) {
- writeString(Import.Module);
- writeString(Import.Field);
- W.OS << char(Import.Kind);
-
- switch (Import.Kind) {
- case wasm::WASM_EXTERNAL_FUNCTION:
- encodeULEB128(Import.SigIndex, W.OS);
- break;
- case wasm::WASM_EXTERNAL_GLOBAL:
- W.OS << char(Import.Global.Type);
- W.OS << char(Import.Global.Mutable ? 1 : 0);
- break;
- case wasm::WASM_EXTERNAL_MEMORY:
- encodeULEB128(0, W.OS); // flags
- encodeULEB128(NumPages, W.OS); // initial
- break;
- case wasm::WASM_EXTERNAL_TABLE:
- W.OS << char(Import.Table.ElemType);
- encodeULEB128(0, W.OS); // flags
- encodeULEB128(NumElements, W.OS); // initial
- break;
- case wasm::WASM_EXTERNAL_EVENT:
- encodeULEB128(Import.Event.Attribute, W.OS);
- encodeULEB128(Import.Event.SigIndex, W.OS);
- break;
- default:
- llvm_unreachable("unsupported import kind");
- }
- }
-
- endSection(Section);
-}
-
-void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) {
- if (Functions.empty())
- return;
-
- SectionBookkeeping Section;
- startSection(Section, wasm::WASM_SEC_FUNCTION);
-
- encodeULEB128(Functions.size(), W.OS);
- for (const WasmFunction &Func : Functions)
- encodeULEB128(Func.SigIndex, W.OS);
-
- endSection(Section);
-}
-
-void WasmObjectWriter::writeEventSection(ArrayRef<wasm::WasmEventType> Events) {
- if (Events.empty())
- return;
-
- SectionBookkeeping Section;
- startSection(Section, wasm::WASM_SEC_EVENT);
-
- encodeULEB128(Events.size(), W.OS);
- for (const wasm::WasmEventType &Event : Events) {
- encodeULEB128(Event.Attribute, W.OS);
- encodeULEB128(Event.SigIndex, W.OS);
- }
-
- endSection(Section);
-}
-
-void WasmObjectWriter::writeExportSection(ArrayRef<wasm::WasmExport> Exports) {
- if (Exports.empty())
- return;
-
- SectionBookkeeping Section;
- startSection(Section, wasm::WASM_SEC_EXPORT);
-
- encodeULEB128(Exports.size(), W.OS);
- for (const wasm::WasmExport &Export : Exports) {
- writeString(Export.Name);
- W.OS << char(Export.Kind);
- encodeULEB128(Export.Index, W.OS);
- }
-
- endSection(Section);
-}
-
-void WasmObjectWriter::writeElemSection(ArrayRef<uint32_t> TableElems) {
- if (TableElems.empty())
- return;
-
- SectionBookkeeping Section;
- startSection(Section, wasm::WASM_SEC_ELEM);
-
- encodeULEB128(1, W.OS); // number of "segments"
- encodeULEB128(0, W.OS); // the table index
-
- // init expr for starting offset
- W.OS << char(wasm::WASM_OPCODE_I32_CONST);
- encodeSLEB128(InitialTableOffset, W.OS);
- W.OS << char(wasm::WASM_OPCODE_END);
-
- encodeULEB128(TableElems.size(), W.OS);
- for (uint32_t Elem : TableElems)
- encodeULEB128(Elem, W.OS);
-
- endSection(Section);
-}
-
-void WasmObjectWriter::writeDataCountSection() {
- if (DataSegments.empty())
- return;
-
- SectionBookkeeping Section;
- startSection(Section, wasm::WASM_SEC_DATACOUNT);
- encodeULEB128(DataSegments.size(), W.OS);
- endSection(Section);
-}
-
-void WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- ArrayRef<WasmFunction> Functions) {
- if (Functions.empty())
- return;
-
- SectionBookkeeping Section;
- startSection(Section, wasm::WASM_SEC_CODE);
- CodeSectionIndex = Section.Index;
-
- encodeULEB128(Functions.size(), W.OS);
-
- for (const WasmFunction &Func : Functions) {
- auto &FuncSection = static_cast<MCSectionWasm &>(Func.Sym->getSection());
-
- int64_t Size = 0;
- if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
- report_fatal_error(".size expression must be evaluatable");
-
- encodeULEB128(Size, W.OS);
- FuncSection.setSectionOffset(W.OS.tell() - Section.ContentsOffset);
- Asm.writeSectionData(W.OS, &FuncSection, Layout);
- }
-
- // Apply fixups.
- applyRelocations(CodeRelocations, Section.ContentsOffset);
-
- endSection(Section);
-}
-
-void WasmObjectWriter::writeDataSection() {
- if (DataSegments.empty())
- return;
-
- SectionBookkeeping Section;
- startSection(Section, wasm::WASM_SEC_DATA);
- DataSectionIndex = Section.Index;
-
- encodeULEB128(DataSegments.size(), W.OS); // count
-
- for (const WasmDataSegment &Segment : DataSegments) {
- encodeULEB128(Segment.InitFlags, W.OS); // flags
- if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX)
- encodeULEB128(0, W.OS); // memory index
- if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0) {
- W.OS << char(wasm::WASM_OPCODE_I32_CONST);
- encodeSLEB128(Segment.Offset, W.OS); // offset
- W.OS << char(wasm::WASM_OPCODE_END);
- }
- encodeULEB128(Segment.Data.size(), W.OS); // size
- Segment.Section->setSectionOffset(W.OS.tell() - Section.ContentsOffset);
- W.OS << Segment.Data; // data
- }
-
- // Apply fixups.
- applyRelocations(DataRelocations, Section.ContentsOffset);
-
- endSection(Section);
-}
-
-void WasmObjectWriter::writeRelocSection(
- uint32_t SectionIndex, StringRef Name,
- std::vector<WasmRelocationEntry> &Relocs) {
- // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
- // for descriptions of the reloc sections.
-
- if (Relocs.empty())
- return;
-
- // First, ensure the relocations are sorted in offset order. In general they
- // should already be sorted since `recordRelocation` is called in offset
- // order, but for the code section we combine many MC sections into single
- // wasm section, and this order is determined by the order of Asm.Symbols()
- // not the sections order.
- llvm::stable_sort(
- Relocs, [](const WasmRelocationEntry &A, const WasmRelocationEntry &B) {
- return (A.Offset + A.FixupSection->getSectionOffset()) <
- (B.Offset + B.FixupSection->getSectionOffset());
- });
-
- SectionBookkeeping Section;
- startCustomSection(Section, std::string("reloc.") + Name.str());
-
- encodeULEB128(SectionIndex, W.OS);
- encodeULEB128(Relocs.size(), W.OS);
- for (const WasmRelocationEntry &RelEntry : Relocs) {
- uint64_t Offset =
- RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
- uint32_t Index = getRelocationIndexValue(RelEntry);
-
- W.OS << char(RelEntry.Type);
- encodeULEB128(Offset, W.OS);
- encodeULEB128(Index, W.OS);
- if (RelEntry.hasAddend())
- encodeSLEB128(RelEntry.Addend, W.OS);
- }
-
- endSection(Section);
-}
-
-void WasmObjectWriter::writeCustomRelocSections() {
- for (const auto &Sec : CustomSections) {
- auto &Relocations = CustomSectionsRelocations[Sec.Section];
- writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
- }
-}
-
-void WasmObjectWriter::writeLinkingMetaDataSection(
- ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
- ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
- const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats) {
- SectionBookkeeping Section;
- startCustomSection(Section, "linking");
- encodeULEB128(wasm::WasmMetadataVersion, W.OS);
-
- SectionBookkeeping SubSection;
- if (SymbolInfos.size() != 0) {
- startSection(SubSection, wasm::WASM_SYMBOL_TABLE);
- encodeULEB128(SymbolInfos.size(), W.OS);
- for (const wasm::WasmSymbolInfo &Sym : SymbolInfos) {
- encodeULEB128(Sym.Kind, W.OS);
- encodeULEB128(Sym.Flags, W.OS);
- switch (Sym.Kind) {
- case wasm::WASM_SYMBOL_TYPE_FUNCTION:
- case wasm::WASM_SYMBOL_TYPE_GLOBAL:
- case wasm::WASM_SYMBOL_TYPE_EVENT:
- encodeULEB128(Sym.ElementIndex, W.OS);
- if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
- (Sym.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
- writeString(Sym.Name);
- break;
- case wasm::WASM_SYMBOL_TYPE_DATA:
- writeString(Sym.Name);
- if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
- encodeULEB128(Sym.DataRef.Segment, W.OS);
- encodeULEB128(Sym.DataRef.Offset, W.OS);
- encodeULEB128(Sym.DataRef.Size, W.OS);
- }
- break;
- case wasm::WASM_SYMBOL_TYPE_SECTION: {
- const uint32_t SectionIndex =
- CustomSections[Sym.ElementIndex].OutputIndex;
- encodeULEB128(SectionIndex, W.OS);
- break;
- }
- default:
- llvm_unreachable("unexpected kind");
- }
- }
- endSection(SubSection);
- }
-
- if (DataSegments.size()) {
- startSection(SubSection, wasm::WASM_SEGMENT_INFO);
- encodeULEB128(DataSegments.size(), W.OS);
- for (const WasmDataSegment &Segment : DataSegments) {
- writeString(Segment.Name);
- encodeULEB128(Segment.Alignment, W.OS);
- encodeULEB128(Segment.LinkerFlags, W.OS);
- }
- endSection(SubSection);
- }
-
- if (!InitFuncs.empty()) {
- startSection(SubSection, wasm::WASM_INIT_FUNCS);
- encodeULEB128(InitFuncs.size(), W.OS);
- for (auto &StartFunc : InitFuncs) {
- encodeULEB128(StartFunc.first, W.OS); // priority
- encodeULEB128(StartFunc.second, W.OS); // function index
- }
- endSection(SubSection);
- }
-
- if (Comdats.size()) {
- startSection(SubSection, wasm::WASM_COMDAT_INFO);
- encodeULEB128(Comdats.size(), W.OS);
- for (const auto &C : Comdats) {
- writeString(C.first);
- encodeULEB128(0, W.OS); // flags for future use
- encodeULEB128(C.second.size(), W.OS);
- for (const WasmComdatEntry &Entry : C.second) {
- encodeULEB128(Entry.Kind, W.OS);
- encodeULEB128(Entry.Index, W.OS);
- }
- }
- endSection(SubSection);
- }
-
- endSection(Section);
-}
-
-void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
- const MCAssembler &Asm,
- const MCAsmLayout &Layout) {
- SectionBookkeeping Section;
- auto *Sec = CustomSection.Section;
- startCustomSection(Section, CustomSection.Name);
-
- Sec->setSectionOffset(W.OS.tell() - Section.ContentsOffset);
- Asm.writeSectionData(W.OS, Sec, Layout);
-
- CustomSection.OutputContentsOffset = Section.ContentsOffset;
- CustomSection.OutputIndex = Section.Index;
-
- endSection(Section);
-
- // Apply fixups.
- auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
- applyRelocations(Relocations, CustomSection.OutputContentsOffset);
-}
-
-uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm &Symbol) {
- assert(Symbol.isFunction());
- assert(TypeIndices.count(&Symbol));
- return TypeIndices[&Symbol];
-}
-
-uint32_t WasmObjectWriter::getEventType(const MCSymbolWasm &Symbol) {
- assert(Symbol.isEvent());
- assert(TypeIndices.count(&Symbol));
- return TypeIndices[&Symbol];
-}
-
-void WasmObjectWriter::registerFunctionType(const MCSymbolWasm &Symbol) {
- assert(Symbol.isFunction());
-
- WasmSignature S;
- const MCSymbolWasm *ResolvedSym = resolveSymbol(Symbol);
- if (auto *Sig = ResolvedSym->getSignature()) {
- S.Returns = Sig->Returns;
- S.Params = Sig->Params;
- }
-
- auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));
- if (Pair.second)
- Signatures.push_back(S);
- TypeIndices[&Symbol] = Pair.first->second;
-
- LLVM_DEBUG(dbgs() << "registerFunctionType: " << Symbol
- << " new:" << Pair.second << "\n");
- LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");
-}
-
-void WasmObjectWriter::registerEventType(const MCSymbolWasm &Symbol) {
- assert(Symbol.isEvent());
-
- // TODO Currently we don't generate imported exceptions, but if we do, we
- // should have a way of infering types of imported exceptions.
- WasmSignature S;
- if (auto *Sig = Symbol.getSignature()) {
- S.Returns = Sig->Returns;
- S.Params = Sig->Params;
- }
-
- auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));
- if (Pair.second)
- Signatures.push_back(S);
- TypeIndices[&Symbol] = Pair.first->second;
-
- LLVM_DEBUG(dbgs() << "registerEventType: " << Symbol << " new:" << Pair.second
- << "\n");
- LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");
-}
-
-static bool isInSymtab(const MCSymbolWasm &Sym) {
- if (Sym.isUsedInReloc())
- return true;
-
- if (Sym.isComdat() && !Sym.isDefined())
- return false;
-
- if (Sym.isTemporary() && Sym.getName().empty())
- return false;
-
- if (Sym.isTemporary() && Sym.isData() && !Sym.getSize())
- return false;
-
- if (Sym.isSection())
- return false;
-
- return true;
-}
-
-uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
- const MCAsmLayout &Layout) {
- uint64_t StartOffset = W.OS.tell();
-
- LLVM_DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
-
- // Collect information from the available symbols.
- SmallVector<WasmFunction, 4> Functions;
- SmallVector<uint32_t, 4> TableElems;
- SmallVector<wasm::WasmImport, 4> Imports;
- SmallVector<wasm::WasmExport, 4> Exports;
- SmallVector<wasm::WasmEventType, 1> Events;
- SmallVector<wasm::WasmSymbolInfo, 4> SymbolInfos;
- SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs;
- std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
- uint32_t DataSize = 0;
-
- // For now, always emit the memory import, since loads and stores are not
- // valid without it. In the future, we could perhaps be more clever and omit
- // it if there are no loads or stores.
- wasm::WasmImport MemImport;
- MemImport.Module = "env";
- MemImport.Field = "__linear_memory";
- MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY;
- Imports.push_back(MemImport);
-
- // For now, always emit the table section, since indirect calls are not
- // valid without it. In the future, we could perhaps be more clever and omit
- // it if there are no indirect calls.
- wasm::WasmImport TableImport;
- TableImport.Module = "env";
- TableImport.Field = "__indirect_function_table";
- TableImport.Kind = wasm::WASM_EXTERNAL_TABLE;
- TableImport.Table.ElemType = wasm::WASM_TYPE_FUNCREF;
- Imports.push_back(TableImport);
-
- // Populate SignatureIndices, and Imports and WasmIndices for undefined
- // symbols. This must be done before populating WasmIndices for defined
- // symbols.
- for (const MCSymbol &S : Asm.symbols()) {
- const auto &WS = static_cast<const MCSymbolWasm &>(S);
-
- // Register types for all functions, including those with private linkage
- // (because wasm always needs a type signature).
- if (WS.isFunction())
- registerFunctionType(WS);
-
- if (WS.isEvent())
- registerEventType(WS);
-
- if (WS.isTemporary())
- continue;
-
- // If the symbol is not defined in this translation unit, import it.
- if (!WS.isDefined() && !WS.isComdat()) {
- if (WS.isFunction()) {
- wasm::WasmImport Import;
- Import.Module = WS.getImportModule();
- Import.Field = WS.getImportName();
- Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
- Import.SigIndex = getFunctionType(WS);
- Imports.push_back(Import);
- assert(WasmIndices.count(&WS) == 0);
- WasmIndices[&WS] = NumFunctionImports++;
- } else if (WS.isGlobal()) {
- if (WS.isWeak())
- report_fatal_error("undefined global symbol cannot be weak");
-
- wasm::WasmImport Import;
- Import.Field = WS.getImportName();
- Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
- Import.Module = WS.getImportModule();
- Import.Global = WS.getGlobalType();
- Imports.push_back(Import);
- assert(WasmIndices.count(&WS) == 0);
- WasmIndices[&WS] = NumGlobalImports++;
- } else if (WS.isEvent()) {
- if (WS.isWeak())
- report_fatal_error("undefined event symbol cannot be weak");
-
- wasm::WasmImport Import;
- Import.Module = WS.getImportModule();
- Import.Field = WS.getImportName();
- Import.Kind = wasm::WASM_EXTERNAL_EVENT;
- Import.Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION;
- Import.Event.SigIndex = getEventType(WS);
- Imports.push_back(Import);
- assert(WasmIndices.count(&WS) == 0);
- WasmIndices[&WS] = NumEventImports++;
- }
- }
- }
-
- // Add imports for GOT globals
- for (const MCSymbol &S : Asm.symbols()) {
- const auto &WS = static_cast<const MCSymbolWasm &>(S);
- if (WS.isUsedInGOT()) {
- wasm::WasmImport Import;
- if (WS.isFunction())
- Import.Module = "GOT.func";
- else
- Import.Module = "GOT.mem";
- Import.Field = WS.getName();
- Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
- Import.Global = {wasm::WASM_TYPE_I32, true};
- Imports.push_back(Import);
- assert(GOTIndices.count(&WS) == 0);
- GOTIndices[&WS] = NumGlobalImports++;
- }
- }
-
- // Populate DataSegments and CustomSections, which must be done before
- // populating DataLocations.
- for (MCSection &Sec : Asm) {
- auto &Section = static_cast<MCSectionWasm &>(Sec);
- StringRef SectionName = Section.getSectionName();
-
- // .init_array sections are handled specially elsewhere.
- if (SectionName.startswith(".init_array"))
- continue;
-
- // Code is handled separately
- if (Section.getKind().isText())
- continue;
-
- if (Section.isWasmData()) {
- uint32_t SegmentIndex = DataSegments.size();
- DataSize = alignTo(DataSize, Section.getAlignment());
- DataSegments.emplace_back();
- WasmDataSegment &Segment = DataSegments.back();
- Segment.Name = SectionName;
- Segment.InitFlags =
- Section.getPassive() ? (uint32_t)wasm::WASM_SEGMENT_IS_PASSIVE : 0;
- Segment.Offset = DataSize;
- Segment.Section = &Section;
- addData(Segment.Data, Section);
- Segment.Alignment = Log2_32(Section.getAlignment());
- Segment.LinkerFlags = 0;
- DataSize += Segment.Data.size();
- Section.setSegmentIndex(SegmentIndex);
-
- if (const MCSymbolWasm *C = Section.getGroup()) {
- Comdats[C->getName()].emplace_back(
- WasmComdatEntry{wasm::WASM_COMDAT_DATA, SegmentIndex});
- }
- } else {
- // Create custom sections
- assert(Sec.getKind().isMetadata());
-
- StringRef Name = SectionName;
-
- // For user-defined custom sections, strip the prefix
- if (Name.startswith(".custom_section."))
- Name = Name.substr(strlen(".custom_section."));
-
- MCSymbol *Begin = Sec.getBeginSymbol();
- if (Begin) {
- WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
- if (SectionName != Begin->getName())
- report_fatal_error("section name and begin symbol should match: " +
- Twine(SectionName));
- }
-
- // Separate out the producers and target features sections
- if (Name == "producers") {
- ProducersSection = llvm::make_unique<WasmCustomSection>(Name, &Section);
- continue;
- }
- if (Name == "target_features") {
- TargetFeaturesSection =
- llvm::make_unique<WasmCustomSection>(Name, &Section);
- continue;
- }
-
- CustomSections.emplace_back(Name, &Section);
- }
- }
-
- // Populate WasmIndices and DataLocations for defined symbols.
- for (const MCSymbol &S : Asm.symbols()) {
- // Ignore unnamed temporary symbols, which aren't ever exported, imported,
- // or used in relocations.
- if (S.isTemporary() && S.getName().empty())
- continue;
-
- const auto &WS = static_cast<const MCSymbolWasm &>(S);
- LLVM_DEBUG(
- dbgs() << "MCSymbol: " << toString(WS.getType()) << " '" << S << "'"
- << " isDefined=" << S.isDefined() << " isExternal="
- << S.isExternal() << " isTemporary=" << S.isTemporary()
- << " isWeak=" << WS.isWeak() << " isHidden=" << WS.isHidden()
- << " isVariable=" << WS.isVariable() << "\n");
-
- if (WS.isVariable())
- continue;
- if (WS.isComdat() && !WS.isDefined())
- continue;
-
- if (WS.isFunction()) {
- unsigned Index;
- if (WS.isDefined()) {
- if (WS.getOffset() != 0)
- report_fatal_error(
- "function sections must contain one function each");
-
- if (WS.getSize() == nullptr)
- report_fatal_error(
- "function symbols must have a size set with .size");
-
- // A definition. Write out the function body.
- Index = NumFunctionImports + Functions.size();
- WasmFunction Func;
- Func.SigIndex = getFunctionType(WS);
- Func.Sym = &WS;
- WasmIndices[&WS] = Index;
- Functions.push_back(Func);
-
- auto &Section = static_cast<MCSectionWasm &>(WS.getSection());
- if (const MCSymbolWasm *C = Section.getGroup()) {
- Comdats[C->getName()].emplace_back(
- WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, Index});
- }
- } else {
- // An import; the index was assigned above.
- Index = WasmIndices.find(&WS)->second;
- }
-
- LLVM_DEBUG(dbgs() << " -> function index: " << Index << "\n");
-
- } else if (WS.isData()) {
- if (!isInSymtab(WS))
- continue;
-
- if (!WS.isDefined()) {
- LLVM_DEBUG(dbgs() << " -> segment index: -1"
- << "\n");
- continue;
- }
-
- if (!WS.getSize())
- report_fatal_error("data symbols must have a size set with .size: " +
- WS.getName());
-
- int64_t Size = 0;
- if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
- report_fatal_error(".size expression must be evaluatable");
-
- auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
- assert(DataSection.isWasmData());
-
- // For each data symbol, export it in the symtab as a reference to the
- // corresponding Wasm data segment.
- wasm::WasmDataReference Ref = wasm::WasmDataReference{
- DataSection.getSegmentIndex(),
- static_cast<uint32_t>(Layout.getSymbolOffset(WS)),
- static_cast<uint32_t>(Size)};
- DataLocations[&WS] = Ref;
- LLVM_DEBUG(dbgs() << " -> segment index: " << Ref.Segment << "\n");
-
- } else if (WS.isGlobal()) {
- // A "true" Wasm global (currently just __stack_pointer)
- if (WS.isDefined())
- report_fatal_error("don't yet support defined globals");
-
- // An import; the index was assigned above
- LLVM_DEBUG(dbgs() << " -> global index: "
- << WasmIndices.find(&WS)->second << "\n");
-
- } else if (WS.isEvent()) {
- // C++ exception symbol (__cpp_exception)
- unsigned Index;
- if (WS.isDefined()) {
- Index = NumEventImports + Events.size();
- wasm::WasmEventType Event;
- Event.SigIndex = getEventType(WS);
- Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION;
- assert(WasmIndices.count(&WS) == 0);
- WasmIndices[&WS] = Index;
- Events.push_back(Event);
- } else {
- // An import; the index was assigned above.
- assert(WasmIndices.count(&WS) > 0);
- }
- LLVM_DEBUG(dbgs() << " -> event index: " << WasmIndices.find(&WS)->second
- << "\n");
-
- } else {
- assert(WS.isSection());
- }
- }
-
- // Populate WasmIndices and DataLocations for aliased symbols. We need to
- // process these in a separate pass because we need to have processed the
- // target of the alias before the alias itself and the symbols are not
- // necessarily ordered in this way.
- for (const MCSymbol &S : Asm.symbols()) {
- if (!S.isVariable())
- continue;
-
- assert(S.isDefined());
-
- // Find the target symbol of this weak alias and export that index
- const auto &WS = static_cast<const MCSymbolWasm &>(S);
- const MCSymbolWasm *ResolvedSym = resolveSymbol(WS);
- LLVM_DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *ResolvedSym
- << "'\n");
-
- if (ResolvedSym->isFunction()) {
- assert(WasmIndices.count(ResolvedSym) > 0);
- uint32_t WasmIndex = WasmIndices.find(ResolvedSym)->second;
- assert(WasmIndices.count(&WS) == 0);
- WasmIndices[&WS] = WasmIndex;
- LLVM_DEBUG(dbgs() << " -> index:" << WasmIndex << "\n");
- } else if (ResolvedSym->isData()) {
- assert(DataLocations.count(ResolvedSym) > 0);
- const wasm::WasmDataReference &Ref =
- DataLocations.find(ResolvedSym)->second;
- DataLocations[&WS] = Ref;
- LLVM_DEBUG(dbgs() << " -> index:" << Ref.Segment << "\n");
- } else {
- report_fatal_error("don't yet support global/event aliases");
- }
- }
-
- // Finally, populate the symbol table itself, in its "natural" order.
- for (const MCSymbol &S : Asm.symbols()) {
- const auto &WS = static_cast<const MCSymbolWasm &>(S);
- if (!isInSymtab(WS)) {
- WS.setIndex(InvalidIndex);
- continue;
- }
- LLVM_DEBUG(dbgs() << "adding to symtab: " << WS << "\n");
-
- uint32_t Flags = 0;
- if (WS.isWeak())
- Flags |= wasm::WASM_SYMBOL_BINDING_WEAK;
- if (WS.isHidden())
- Flags |= wasm::WASM_SYMBOL_VISIBILITY_HIDDEN;
- if (!WS.isExternal() && WS.isDefined())
- Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;
- if (WS.isUndefined())
- Flags |= wasm::WASM_SYMBOL_UNDEFINED;
- if (WS.isExported())
- Flags |= wasm::WASM_SYMBOL_EXPORTED;
- if (WS.getName() != WS.getImportName())
- Flags |= wasm::WASM_SYMBOL_EXPLICIT_NAME;
-
- wasm::WasmSymbolInfo Info;
- Info.Name = WS.getName();
- Info.Kind = WS.getType();
- Info.Flags = Flags;
- if (!WS.isData()) {
- assert(WasmIndices.count(&WS) > 0);
- Info.ElementIndex = WasmIndices.find(&WS)->second;
- } else if (WS.isDefined()) {
- assert(DataLocations.count(&WS) > 0);
- Info.DataRef = DataLocations.find(&WS)->second;
- }
- WS.setIndex(SymbolInfos.size());
- SymbolInfos.emplace_back(Info);
- }
-
- {
- auto HandleReloc = [&](const WasmRelocationEntry &Rel) {
- // Functions referenced by a relocation need to put in the table. This is
- // purely to make the object file's provisional values readable, and is
- // ignored by the linker, which re-calculates the relocations itself.
- if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
- Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB)
- return;
- assert(Rel.Symbol->isFunction());
- const MCSymbolWasm &WS = *resolveSymbol(*Rel.Symbol);
- uint32_t FunctionIndex = WasmIndices.find(&WS)->second;
- uint32_t TableIndex = TableElems.size() + InitialTableOffset;
- if (TableIndices.try_emplace(&WS, TableIndex).second) {
- LLVM_DEBUG(dbgs() << " -> adding " << WS.getName()
- << " to table: " << TableIndex << "\n");
- TableElems.push_back(FunctionIndex);
- registerFunctionType(WS);
- }
- };
-
- for (const WasmRelocationEntry &RelEntry : CodeRelocations)
- HandleReloc(RelEntry);
- for (const WasmRelocationEntry &RelEntry : DataRelocations)
- HandleReloc(RelEntry);
- }
-
- // Translate .init_array section contents into start functions.
- for (const MCSection &S : Asm) {
- const auto &WS = static_cast<const MCSectionWasm &>(S);
- if (WS.getSectionName().startswith(".fini_array"))
- report_fatal_error(".fini_array sections are unsupported");
- if (!WS.getSectionName().startswith(".init_array"))
- continue;
- if (WS.getFragmentList().empty())
- continue;
-
- // init_array is expected to contain a single non-empty data fragment
- if (WS.getFragmentList().size() != 3)
- report_fatal_error("only one .init_array section fragment supported");
-
- auto IT = WS.begin();
- const MCFragment &EmptyFrag = *IT;
- if (EmptyFrag.getKind() != MCFragment::FT_Data)
- report_fatal_error(".init_array section should be aligned");
-
- IT = std::next(IT);
- const MCFragment &AlignFrag = *IT;
- if (AlignFrag.getKind() != MCFragment::FT_Align)
- report_fatal_error(".init_array section should be aligned");
- if (cast<MCAlignFragment>(AlignFrag).getAlignment() != (is64Bit() ? 8 : 4))
- report_fatal_error(".init_array section should be aligned for pointers");
-
- const MCFragment &Frag = *std::next(IT);
- if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
- report_fatal_error("only data supported in .init_array section");
-
- uint16_t Priority = UINT16_MAX;
- unsigned PrefixLength = strlen(".init_array");
- if (WS.getSectionName().size() > PrefixLength) {
- if (WS.getSectionName()[PrefixLength] != '.')
- report_fatal_error(
- ".init_array section priority should start with '.'");
- if (WS.getSectionName()
- .substr(PrefixLength + 1)
- .getAsInteger(10, Priority))
- report_fatal_error("invalid .init_array section priority");
- }
- const auto &DataFrag = cast<MCDataFragment>(Frag);
- const SmallVectorImpl<char> &Contents = DataFrag.getContents();
- for (const uint8_t *
- P = (const uint8_t *)Contents.data(),
- *End = (const uint8_t *)Contents.data() + Contents.size();
- P != End; ++P) {
- if (*P != 0)
- report_fatal_error("non-symbolic data in .init_array section");
- }
- for (const MCFixup &Fixup : DataFrag.getFixups()) {
- assert(Fixup.getKind() ==
- MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
- const MCExpr *Expr = Fixup.getValue();
- auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
- if (!SymRef)
- report_fatal_error("fixups in .init_array should be symbol references");
- const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
- if (TargetSym.getIndex() == InvalidIndex)
- report_fatal_error("symbols in .init_array should exist in symbtab");
- if (!TargetSym.isFunction())
- report_fatal_error("symbols in .init_array should be for functions");
- InitFuncs.push_back(
- std::make_pair(Priority, TargetSym.getIndex()));
- }
- }
-
- // Write out the Wasm header.
- writeHeader(Asm);
-
- writeTypeSection(Signatures);
- writeImportSection(Imports, DataSize, TableElems.size());
- writeFunctionSection(Functions);
- // Skip the "table" section; we import the table instead.
- // Skip the "memory" section; we import the memory instead.
- writeEventSection(Events);
- writeExportSection(Exports);
- writeElemSection(TableElems);
- writeDataCountSection();
- writeCodeSection(Asm, Layout, Functions);
- writeDataSection();
- for (auto &CustomSection : CustomSections)
- writeCustomSection(CustomSection, Asm, Layout);
- writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
- writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations);
- writeRelocSection(DataSectionIndex, "DATA", DataRelocations);
- writeCustomRelocSections();
- if (ProducersSection)
- writeCustomSection(*ProducersSection, Asm, Layout);
- if (TargetFeaturesSection)
- writeCustomSection(*TargetFeaturesSection, Asm, Layout);
-
- // TODO: Translate the .comment section to the output.
- return W.OS.tell() - StartOffset;
-}
-
-std::unique_ptr<MCObjectWriter>
-llvm::createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
- raw_pwrite_stream &OS) {
- return llvm::make_unique<WasmObjectWriter>(std::move(MOTW), OS);
-}
diff --git a/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp b/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp
deleted file mode 100644
index 0e6c05bc726d..000000000000
--- a/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp
+++ /dev/null
@@ -1,1102 +0,0 @@
-//===- llvm/MC/WinCOFFObjectWriter.cpp ------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains an implementation of a Win32 COFF object file writer.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/COFF.h"
-#include "llvm/MC/MCAsmLayout.h"
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCFixup.h"
-#include "llvm/MC/MCFragment.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCSectionCOFF.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCSymbolCOFF.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/MC/MCWinCOFFObjectWriter.h"
-#include "llvm/MC/StringTableBuilder.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/JamCRC.h"
-#include "llvm/Support/LEB128.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-#include <cstring>
-#include <ctime>
-#include <memory>
-#include <string>
-#include <vector>
-
-using namespace llvm;
-using llvm::support::endian::write32le;
-
-#define DEBUG_TYPE "WinCOFFObjectWriter"
-
-namespace {
-
-using name = SmallString<COFF::NameSize>;
-
-enum AuxiliaryType {
- ATWeakExternal,
- ATFile,
- ATSectionDefinition
-};
-
-struct AuxSymbol {
- AuxiliaryType AuxType;
- COFF::Auxiliary Aux;
-};
-
-class COFFSection;
-
-class COFFSymbol {
-public:
- COFF::symbol Data = {};
-
- using AuxiliarySymbols = SmallVector<AuxSymbol, 1>;
-
- name Name;
- int Index;
- AuxiliarySymbols Aux;
- COFFSymbol *Other = nullptr;
- COFFSection *Section = nullptr;
- int Relocations = 0;
- const MCSymbol *MC = nullptr;
-
- COFFSymbol(StringRef Name) : Name(Name) {}
-
- void set_name_offset(uint32_t Offset);
-
- int64_t getIndex() const { return Index; }
- void setIndex(int Value) {
- Index = Value;
- if (MC)
- MC->setIndex(static_cast<uint32_t>(Value));
- }
-};
-
-// This class contains staging data for a COFF relocation entry.
-struct COFFRelocation {
- COFF::relocation Data;
- COFFSymbol *Symb = nullptr;
-
- COFFRelocation() = default;
-
- static size_t size() { return COFF::RelocationSize; }
-};
-
-using relocations = std::vector<COFFRelocation>;
-
-class COFFSection {
-public:
- COFF::section Header = {};
-
- std::string Name;
- int Number;
- MCSectionCOFF const *MCSection = nullptr;
- COFFSymbol *Symbol = nullptr;
- relocations Relocations;
-
- COFFSection(StringRef Name) : Name(Name) {}
-};
-
-class WinCOFFObjectWriter : public MCObjectWriter {
-public:
- support::endian::Writer W;
-
- using symbols = std::vector<std::unique_ptr<COFFSymbol>>;
- using sections = std::vector<std::unique_ptr<COFFSection>>;
-
- using symbol_map = DenseMap<MCSymbol const *, COFFSymbol *>;
- using section_map = DenseMap<MCSection const *, COFFSection *>;
-
- std::unique_ptr<MCWinCOFFObjectTargetWriter> TargetObjectWriter;
-
- // Root level file contents.
- COFF::header Header = {};
- sections Sections;
- symbols Symbols;
- StringTableBuilder Strings{StringTableBuilder::WinCOFF};
-
- // Maps used during object file creation.
- section_map SectionMap;
- symbol_map SymbolMap;
-
- bool UseBigObj;
-
- bool EmitAddrsigSection = false;
- MCSectionCOFF *AddrsigSection;
- std::vector<const MCSymbol *> AddrsigSyms;
-
- WinCOFFObjectWriter(std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW,
- raw_pwrite_stream &OS);
-
- void reset() override {
- memset(&Header, 0, sizeof(Header));
- Header.Machine = TargetObjectWriter->getMachine();
- Sections.clear();
- Symbols.clear();
- Strings.clear();
- SectionMap.clear();
- SymbolMap.clear();
- MCObjectWriter::reset();
- }
-
- COFFSymbol *createSymbol(StringRef Name);
- COFFSymbol *GetOrCreateCOFFSymbol(const MCSymbol *Symbol);
- COFFSection *createSection(StringRef Name);
-
- void defineSection(MCSectionCOFF const &Sec);
-
- COFFSymbol *getLinkedSymbol(const MCSymbol &Symbol);
- void DefineSymbol(const MCSymbol &Symbol, MCAssembler &Assembler,
- const MCAsmLayout &Layout);
-
- void SetSymbolName(COFFSymbol &S);
- void SetSectionName(COFFSection &S);
-
- bool IsPhysicalSection(COFFSection *S);
-
- // Entity writing methods.
-
- void WriteFileHeader(const COFF::header &Header);
- void WriteSymbol(const COFFSymbol &S);
- void WriteAuxiliarySymbols(const COFFSymbol::AuxiliarySymbols &S);
- void writeSectionHeaders();
- void WriteRelocation(const COFF::relocation &R);
- uint32_t writeSectionContents(MCAssembler &Asm, const MCAsmLayout &Layout,
- const MCSection &MCSec);
- void writeSection(MCAssembler &Asm, const MCAsmLayout &Layout,
- const COFFSection &Sec, const MCSection &MCSec);
-
- // MCObjectWriter interface implementation.
-
- void executePostLayoutBinding(MCAssembler &Asm,
- const MCAsmLayout &Layout) override;
-
- bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
- const MCSymbol &SymA,
- const MCFragment &FB, bool InSet,
- bool IsPCRel) const override;
-
- void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
- const MCFragment *Fragment, const MCFixup &Fixup,
- MCValue Target, uint64_t &FixedValue) override;
-
- void createFileSymbols(MCAssembler &Asm);
- void assignSectionNumbers();
- void assignFileOffsets(MCAssembler &Asm, const MCAsmLayout &Layout);
-
- void emitAddrsigSection() override { EmitAddrsigSection = true; }
- void addAddrsigSymbol(const MCSymbol *Sym) override {
- AddrsigSyms.push_back(Sym);
- }
-
- uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
-};
-
-} // end anonymous namespace
-
-//------------------------------------------------------------------------------
-// Symbol class implementation
-
-// In the case that the name does not fit within 8 bytes, the offset
-// into the string table is stored in the last 4 bytes instead, leaving
-// the first 4 bytes as 0.
-void COFFSymbol::set_name_offset(uint32_t Offset) {
- write32le(Data.Name + 0, 0);
- write32le(Data.Name + 4, Offset);
-}
-
-//------------------------------------------------------------------------------
-// WinCOFFObjectWriter class implementation
-
-WinCOFFObjectWriter::WinCOFFObjectWriter(
- std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
- : W(OS, support::little), TargetObjectWriter(std::move(MOTW)) {
- Header.Machine = TargetObjectWriter->getMachine();
-}
-
-COFFSymbol *WinCOFFObjectWriter::createSymbol(StringRef Name) {
- Symbols.push_back(make_unique<COFFSymbol>(Name));
- return Symbols.back().get();
-}
-
-COFFSymbol *WinCOFFObjectWriter::GetOrCreateCOFFSymbol(const MCSymbol *Symbol) {
- COFFSymbol *&Ret = SymbolMap[Symbol];
- if (!Ret)
- Ret = createSymbol(Symbol->getName());
- return Ret;
-}
-
-COFFSection *WinCOFFObjectWriter::createSection(StringRef Name) {
- Sections.emplace_back(make_unique<COFFSection>(Name));
- return Sections.back().get();
-}
-
-static uint32_t getAlignment(const MCSectionCOFF &Sec) {
- switch (Sec.getAlignment()) {
- case 1:
- return COFF::IMAGE_SCN_ALIGN_1BYTES;
- case 2:
- return COFF::IMAGE_SCN_ALIGN_2BYTES;
- case 4:
- return COFF::IMAGE_SCN_ALIGN_4BYTES;
- case 8:
- return COFF::IMAGE_SCN_ALIGN_8BYTES;
- case 16:
- return COFF::IMAGE_SCN_ALIGN_16BYTES;
- case 32:
- return COFF::IMAGE_SCN_ALIGN_32BYTES;
- case 64:
- return COFF::IMAGE_SCN_ALIGN_64BYTES;
- case 128:
- return COFF::IMAGE_SCN_ALIGN_128BYTES;
- case 256:
- return COFF::IMAGE_SCN_ALIGN_256BYTES;
- case 512:
- return COFF::IMAGE_SCN_ALIGN_512BYTES;
- case 1024:
- return COFF::IMAGE_SCN_ALIGN_1024BYTES;
- case 2048:
- return COFF::IMAGE_SCN_ALIGN_2048BYTES;
- case 4096:
- return COFF::IMAGE_SCN_ALIGN_4096BYTES;
- case 8192:
- return COFF::IMAGE_SCN_ALIGN_8192BYTES;
- }
- llvm_unreachable("unsupported section alignment");
-}
-
-/// This function takes a section data object from the assembler
-/// and creates the associated COFF section staging object.
-void WinCOFFObjectWriter::defineSection(const MCSectionCOFF &MCSec) {
- COFFSection *Section = createSection(MCSec.getSectionName());
- COFFSymbol *Symbol = createSymbol(MCSec.getSectionName());
- Section->Symbol = Symbol;
- Symbol->Section = Section;
- Symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_STATIC;
-
- // Create a COMDAT symbol if needed.
- if (MCSec.getSelection() != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
- if (const MCSymbol *S = MCSec.getCOMDATSymbol()) {
- COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(S);
- if (COMDATSymbol->Section)
- report_fatal_error("two sections have the same comdat");
- COMDATSymbol->Section = Section;
- }
- }
-
- // In this case the auxiliary symbol is a Section Definition.
- Symbol->Aux.resize(1);
- Symbol->Aux[0] = {};
- Symbol->Aux[0].AuxType = ATSectionDefinition;
- Symbol->Aux[0].Aux.SectionDefinition.Selection = MCSec.getSelection();
-
- // Set section alignment.
- Section->Header.Characteristics = MCSec.getCharacteristics();
- Section->Header.Characteristics |= getAlignment(MCSec);
-
- // Bind internal COFF section to MC section.
- Section->MCSection = &MCSec;
- SectionMap[&MCSec] = Section;
-}
-
-static uint64_t getSymbolValue(const MCSymbol &Symbol,
- const MCAsmLayout &Layout) {
- if (Symbol.isCommon() && Symbol.isExternal())
- return Symbol.getCommonSize();
-
- uint64_t Res;
- if (!Layout.getSymbolOffset(Symbol, Res))
- return 0;
-
- return Res;
-}
-
-COFFSymbol *WinCOFFObjectWriter::getLinkedSymbol(const MCSymbol &Symbol) {
- if (!Symbol.isVariable())
- return nullptr;
-
- const MCSymbolRefExpr *SymRef =
- dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue());
- if (!SymRef)
- return nullptr;
-
- const MCSymbol &Aliasee = SymRef->getSymbol();
- if (!Aliasee.isUndefined())
- return nullptr;
- return GetOrCreateCOFFSymbol(&Aliasee);
-}
-
-/// This function takes a symbol data object from the assembler
-/// and creates the associated COFF symbol staging object.
-void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &MCSym,
- MCAssembler &Assembler,
- const MCAsmLayout &Layout) {
- COFFSymbol *Sym = GetOrCreateCOFFSymbol(&MCSym);
- const MCSymbol *Base = Layout.getBaseSymbol(MCSym);
- COFFSection *Sec = nullptr;
- if (Base && Base->getFragment()) {
- Sec = SectionMap[Base->getFragment()->getParent()];
- if (Sym->Section && Sym->Section != Sec)
- report_fatal_error("conflicting sections for symbol");
- }
-
- COFFSymbol *Local = nullptr;
- if (cast<MCSymbolCOFF>(MCSym).isWeakExternal()) {
- Sym->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
-
- COFFSymbol *WeakDefault = getLinkedSymbol(MCSym);
- if (!WeakDefault) {
- std::string WeakName = (".weak." + MCSym.getName() + ".default").str();
- WeakDefault = createSymbol(WeakName);
- if (!Sec)
- WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
- else
- WeakDefault->Section = Sec;
- Local = WeakDefault;
- }
-
- Sym->Other = WeakDefault;
-
- // Setup the Weak External auxiliary symbol.
- Sym->Aux.resize(1);
- memset(&Sym->Aux[0], 0, sizeof(Sym->Aux[0]));
- Sym->Aux[0].AuxType = ATWeakExternal;
- Sym->Aux[0].Aux.WeakExternal.TagIndex = 0;
- Sym->Aux[0].Aux.WeakExternal.Characteristics =
- COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS;
- } else {
- if (!Base)
- Sym->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
- else
- Sym->Section = Sec;
- Local = Sym;
- }
-
- if (Local) {
- Local->Data.Value = getSymbolValue(MCSym, Layout);
-
- const MCSymbolCOFF &SymbolCOFF = cast<MCSymbolCOFF>(MCSym);
- Local->Data.Type = SymbolCOFF.getType();
- Local->Data.StorageClass = SymbolCOFF.getClass();
-
- // If no storage class was specified in the streamer, define it here.
- if (Local->Data.StorageClass == COFF::IMAGE_SYM_CLASS_NULL) {
- bool IsExternal = MCSym.isExternal() ||
- (!MCSym.getFragment() && !MCSym.isVariable());
-
- Local->Data.StorageClass = IsExternal ? COFF::IMAGE_SYM_CLASS_EXTERNAL
- : COFF::IMAGE_SYM_CLASS_STATIC;
- }
- }
-
- Sym->MC = &MCSym;
-}
-
-// Maximum offsets for different string table entry encodings.
-enum : unsigned { Max7DecimalOffset = 9999999U };
-enum : uint64_t { MaxBase64Offset = 0xFFFFFFFFFULL }; // 64^6, including 0
-
-// Encode a string table entry offset in base 64, padded to 6 chars, and
-// prefixed with a double slash: '//AAAAAA', '//AAAAAB', ...
-// Buffer must be at least 8 bytes large. No terminating null appended.
-static void encodeBase64StringEntry(char *Buffer, uint64_t Value) {
- assert(Value > Max7DecimalOffset && Value <= MaxBase64Offset &&
- "Illegal section name encoding for value");
-
- static const char Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789+/";
-
- Buffer[0] = '/';
- Buffer[1] = '/';
-
- char *Ptr = Buffer + 7;
- for (unsigned i = 0; i < 6; ++i) {
- unsigned Rem = Value % 64;
- Value /= 64;
- *(Ptr--) = Alphabet[Rem];
- }
-}
-
-void WinCOFFObjectWriter::SetSectionName(COFFSection &S) {
- if (S.Name.size() <= COFF::NameSize) {
- std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size());
- return;
- }
-
- uint64_t StringTableEntry = Strings.getOffset(S.Name);
- if (StringTableEntry <= Max7DecimalOffset) {
- SmallVector<char, COFF::NameSize> Buffer;
- Twine('/').concat(Twine(StringTableEntry)).toVector(Buffer);
- assert(Buffer.size() <= COFF::NameSize && Buffer.size() >= 2);
- std::memcpy(S.Header.Name, Buffer.data(), Buffer.size());
- return;
- }
- if (StringTableEntry <= MaxBase64Offset) {
- // Starting with 10,000,000, offsets are encoded as base64.
- encodeBase64StringEntry(S.Header.Name, StringTableEntry);
- return;
- }
- report_fatal_error("COFF string table is greater than 64 GB.");
-}
-
-void WinCOFFObjectWriter::SetSymbolName(COFFSymbol &S) {
- if (S.Name.size() > COFF::NameSize)
- S.set_name_offset(Strings.getOffset(S.Name));
- else
- std::memcpy(S.Data.Name, S.Name.c_str(), S.Name.size());
-}
-
-bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) {
- return (S->Header.Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) ==
- 0;
-}
-
-//------------------------------------------------------------------------------
-// entity writing methods
-
-void WinCOFFObjectWriter::WriteFileHeader(const COFF::header &Header) {
- if (UseBigObj) {
- W.write<uint16_t>(COFF::IMAGE_FILE_MACHINE_UNKNOWN);
- W.write<uint16_t>(0xFFFF);
- W.write<uint16_t>(COFF::BigObjHeader::MinBigObjectVersion);
- W.write<uint16_t>(Header.Machine);
- W.write<uint32_t>(Header.TimeDateStamp);
- W.OS.write(COFF::BigObjMagic, sizeof(COFF::BigObjMagic));
- W.write<uint32_t>(0);
- W.write<uint32_t>(0);
- W.write<uint32_t>(0);
- W.write<uint32_t>(0);
- W.write<uint32_t>(Header.NumberOfSections);
- W.write<uint32_t>(Header.PointerToSymbolTable);
- W.write<uint32_t>(Header.NumberOfSymbols);
- } else {
- W.write<uint16_t>(Header.Machine);
- W.write<uint16_t>(static_cast<int16_t>(Header.NumberOfSections));
- W.write<uint32_t>(Header.TimeDateStamp);
- W.write<uint32_t>(Header.PointerToSymbolTable);
- W.write<uint32_t>(Header.NumberOfSymbols);
- W.write<uint16_t>(Header.SizeOfOptionalHeader);
- W.write<uint16_t>(Header.Characteristics);
- }
-}
-
-void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol &S) {
- W.OS.write(S.Data.Name, COFF::NameSize);
- W.write<uint32_t>(S.Data.Value);
- if (UseBigObj)
- W.write<uint32_t>(S.Data.SectionNumber);
- else
- W.write<uint16_t>(static_cast<int16_t>(S.Data.SectionNumber));
- W.write<uint16_t>(S.Data.Type);
- W.OS << char(S.Data.StorageClass);
- W.OS << char(S.Data.NumberOfAuxSymbols);
- WriteAuxiliarySymbols(S.Aux);
-}
-
-void WinCOFFObjectWriter::WriteAuxiliarySymbols(
- const COFFSymbol::AuxiliarySymbols &S) {
- for (const AuxSymbol &i : S) {
- switch (i.AuxType) {
- case ATWeakExternal:
- W.write<uint32_t>(i.Aux.WeakExternal.TagIndex);
- W.write<uint32_t>(i.Aux.WeakExternal.Characteristics);
- W.OS.write_zeros(sizeof(i.Aux.WeakExternal.unused));
- if (UseBigObj)
- W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
- break;
- case ATFile:
- W.OS.write(reinterpret_cast<const char *>(&i.Aux),
- UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size);
- break;
- case ATSectionDefinition:
- W.write<uint32_t>(i.Aux.SectionDefinition.Length);
- W.write<uint16_t>(i.Aux.SectionDefinition.NumberOfRelocations);
- W.write<uint16_t>(i.Aux.SectionDefinition.NumberOfLinenumbers);
- W.write<uint32_t>(i.Aux.SectionDefinition.CheckSum);
- W.write<uint16_t>(static_cast<int16_t>(i.Aux.SectionDefinition.Number));
- W.OS << char(i.Aux.SectionDefinition.Selection);
- W.OS.write_zeros(sizeof(i.Aux.SectionDefinition.unused));
- W.write<uint16_t>(static_cast<int16_t>(i.Aux.SectionDefinition.Number >> 16));
- if (UseBigObj)
- W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
- break;
- }
- }
-}
-
-// Write the section header.
-void WinCOFFObjectWriter::writeSectionHeaders() {
- // Section numbers must be monotonically increasing in the section
- // header, but our Sections array is not sorted by section number,
- // so make a copy of Sections and sort it.
- std::vector<COFFSection *> Arr;
- for (auto &Section : Sections)
- Arr.push_back(Section.get());
- llvm::sort(Arr, [](const COFFSection *A, const COFFSection *B) {
- return A->Number < B->Number;
- });
-
- for (auto &Section : Arr) {
- if (Section->Number == -1)
- continue;
-
- COFF::section &S = Section->Header;
- if (Section->Relocations.size() >= 0xffff)
- S.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL;
- W.OS.write(S.Name, COFF::NameSize);
- W.write<uint32_t>(S.VirtualSize);
- W.write<uint32_t>(S.VirtualAddress);
- W.write<uint32_t>(S.SizeOfRawData);
- W.write<uint32_t>(S.PointerToRawData);
- W.write<uint32_t>(S.PointerToRelocations);
- W.write<uint32_t>(S.PointerToLineNumbers);
- W.write<uint16_t>(S.NumberOfRelocations);
- W.write<uint16_t>(S.NumberOfLineNumbers);
- W.write<uint32_t>(S.Characteristics);
- }
-}
-
-void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) {
- W.write<uint32_t>(R.VirtualAddress);
- W.write<uint32_t>(R.SymbolTableIndex);
- W.write<uint16_t>(R.Type);
-}
-
-// Write MCSec's contents. What this function does is essentially
-// "Asm.writeSectionData(&MCSec, Layout)", but it's a bit complicated
-// because it needs to compute a CRC.
-uint32_t WinCOFFObjectWriter::writeSectionContents(MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCSection &MCSec) {
- // Save the contents of the section to a temporary buffer, we need this
- // to CRC the data before we dump it into the object file.
- SmallVector<char, 128> Buf;
- raw_svector_ostream VecOS(Buf);
- Asm.writeSectionData(VecOS, &MCSec, Layout);
-
- // Write the section contents to the object file.
- W.OS << Buf;
-
- // Calculate our CRC with an initial value of '0', this is not how
- // JamCRC is specified but it aligns with the expected output.
- JamCRC JC(/*Init=*/0);
- JC.update(Buf);
- return JC.getCRC();
-}
-
-void WinCOFFObjectWriter::writeSection(MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const COFFSection &Sec,
- const MCSection &MCSec) {
- if (Sec.Number == -1)
- return;
-
- // Write the section contents.
- if (Sec.Header.PointerToRawData != 0) {
- assert(W.OS.tell() == Sec.Header.PointerToRawData &&
- "Section::PointerToRawData is insane!");
-
- uint32_t CRC = writeSectionContents(Asm, Layout, MCSec);
-
- // Update the section definition auxiliary symbol to record the CRC.
- COFFSection *Sec = SectionMap[&MCSec];
- COFFSymbol::AuxiliarySymbols &AuxSyms = Sec->Symbol->Aux;
- assert(AuxSyms.size() == 1 && AuxSyms[0].AuxType == ATSectionDefinition);
- AuxSymbol &SecDef = AuxSyms[0];
- SecDef.Aux.SectionDefinition.CheckSum = CRC;
- }
-
- // Write relocations for this section.
- if (Sec.Relocations.empty()) {
- assert(Sec.Header.PointerToRelocations == 0 &&
- "Section::PointerToRelocations is insane!");
- return;
- }
-
- assert(W.OS.tell() == Sec.Header.PointerToRelocations &&
- "Section::PointerToRelocations is insane!");
-
- if (Sec.Relocations.size() >= 0xffff) {
- // In case of overflow, write actual relocation count as first
- // relocation. Including the synthetic reloc itself (+ 1).
- COFF::relocation R;
- R.VirtualAddress = Sec.Relocations.size() + 1;
- R.SymbolTableIndex = 0;
- R.Type = 0;
- WriteRelocation(R);
- }
-
- for (const auto &Relocation : Sec.Relocations)
- WriteRelocation(Relocation.Data);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// MCObjectWriter interface implementations
-
-void WinCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
- const MCAsmLayout &Layout) {
- if (EmitAddrsigSection) {
- AddrsigSection = Asm.getContext().getCOFFSection(
- ".llvm_addrsig", COFF::IMAGE_SCN_LNK_REMOVE,
- SectionKind::getMetadata());
- Asm.registerSection(*AddrsigSection);
- }
-
- // "Define" each section & symbol. This creates section & symbol
- // entries in the staging area.
- for (const auto &Section : Asm)
- defineSection(static_cast<const MCSectionCOFF &>(Section));
-
- for (const MCSymbol &Symbol : Asm.symbols())
- if (!Symbol.isTemporary())
- DefineSymbol(Symbol, Asm, Layout);
-}
-
-bool WinCOFFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
- const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB,
- bool InSet, bool IsPCRel) const {
- // Don't drop relocations between functions, even if they are in the same text
- // section. Multiple Visual C++ linker features depend on having the
- // relocations present. The /INCREMENTAL flag will cause these relocations to
- // point to thunks, and the /GUARD:CF flag assumes that it can use relocations
- // to approximate the set of all address taken functions. LLD's implementation
- // of /GUARD:CF also relies on the existance of these relocations.
- uint16_t Type = cast<MCSymbolCOFF>(SymA).getType();
- if ((Type >> COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION)
- return false;
- return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
- InSet, IsPCRel);
-}
-
-void WinCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup, MCValue Target,
- uint64_t &FixedValue) {
- assert(Target.getSymA() && "Relocation must reference a symbol!");
-
- const MCSymbol &A = Target.getSymA()->getSymbol();
- if (!A.isRegistered()) {
- Asm.getContext().reportError(Fixup.getLoc(),
- Twine("symbol '") + A.getName() +
- "' can not be undefined");
- return;
- }
- if (A.isTemporary() && A.isUndefined()) {
- Asm.getContext().reportError(Fixup.getLoc(),
- Twine("assembler label '") + A.getName() +
- "' can not be undefined");
- return;
- }
-
- MCSection *MCSec = Fragment->getParent();
-
- // Mark this symbol as requiring an entry in the symbol table.
- assert(SectionMap.find(MCSec) != SectionMap.end() &&
- "Section must already have been defined in executePostLayoutBinding!");
-
- COFFSection *Sec = SectionMap[MCSec];
- const MCSymbolRefExpr *SymB = Target.getSymB();
-
- if (SymB) {
- const MCSymbol *B = &SymB->getSymbol();
- if (!B->getFragment()) {
- Asm.getContext().reportError(
- Fixup.getLoc(),
- Twine("symbol '") + B->getName() +
- "' can not be undefined in a subtraction expression");
- return;
- }
-
- // Offset of the symbol in the section
- int64_t OffsetOfB = Layout.getSymbolOffset(*B);
-
- // Offset of the relocation in the section
- int64_t OffsetOfRelocation =
- Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
-
- FixedValue = (OffsetOfRelocation - OffsetOfB) + Target.getConstant();
- } else {
- FixedValue = Target.getConstant();
- }
-
- COFFRelocation Reloc;
-
- Reloc.Data.SymbolTableIndex = 0;
- Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment);
-
- // Turn relocations for temporary symbols into section relocations.
- if (A.isTemporary()) {
- MCSection *TargetSection = &A.getSection();
- assert(
- SectionMap.find(TargetSection) != SectionMap.end() &&
- "Section must already have been defined in executePostLayoutBinding!");
- Reloc.Symb = SectionMap[TargetSection]->Symbol;
- FixedValue += Layout.getSymbolOffset(A);
- } else {
- assert(
- SymbolMap.find(&A) != SymbolMap.end() &&
- "Symbol must already have been defined in executePostLayoutBinding!");
- Reloc.Symb = SymbolMap[&A];
- }
-
- ++Reloc.Symb->Relocations;
-
- Reloc.Data.VirtualAddress += Fixup.getOffset();
- Reloc.Data.Type = TargetObjectWriter->getRelocType(
- Asm.getContext(), Target, Fixup, SymB, Asm.getBackend());
-
- // FIXME: Can anyone explain what this does other than adjust for the size
- // of the offset?
- if ((Header.Machine == COFF::IMAGE_FILE_MACHINE_AMD64 &&
- Reloc.Data.Type == COFF::IMAGE_REL_AMD64_REL32) ||
- (Header.Machine == COFF::IMAGE_FILE_MACHINE_I386 &&
- Reloc.Data.Type == COFF::IMAGE_REL_I386_REL32))
- FixedValue += 4;
-
- if (Header.Machine == COFF::IMAGE_FILE_MACHINE_ARMNT) {
- switch (Reloc.Data.Type) {
- case COFF::IMAGE_REL_ARM_ABSOLUTE:
- case COFF::IMAGE_REL_ARM_ADDR32:
- case COFF::IMAGE_REL_ARM_ADDR32NB:
- case COFF::IMAGE_REL_ARM_TOKEN:
- case COFF::IMAGE_REL_ARM_SECTION:
- case COFF::IMAGE_REL_ARM_SECREL:
- break;
- case COFF::IMAGE_REL_ARM_BRANCH11:
- case COFF::IMAGE_REL_ARM_BLX11:
- // IMAGE_REL_ARM_BRANCH11 and IMAGE_REL_ARM_BLX11 are only used for
- // pre-ARMv7, which implicitly rules it out of ARMNT (it would be valid
- // for Windows CE).
- case COFF::IMAGE_REL_ARM_BRANCH24:
- case COFF::IMAGE_REL_ARM_BLX24:
- case COFF::IMAGE_REL_ARM_MOV32A:
- // IMAGE_REL_ARM_BRANCH24, IMAGE_REL_ARM_BLX24, IMAGE_REL_ARM_MOV32A are
- // only used for ARM mode code, which is documented as being unsupported
- // by Windows on ARM. Empirical proof indicates that masm is able to
- // generate the relocations however the rest of the MSVC toolchain is
- // unable to handle it.
- llvm_unreachable("unsupported relocation");
- break;
- case COFF::IMAGE_REL_ARM_MOV32T:
- break;
- case COFF::IMAGE_REL_ARM_BRANCH20T:
- case COFF::IMAGE_REL_ARM_BRANCH24T:
- case COFF::IMAGE_REL_ARM_BLX23T:
- // IMAGE_REL_BRANCH20T, IMAGE_REL_ARM_BRANCH24T, IMAGE_REL_ARM_BLX23T all
- // perform a 4 byte adjustment to the relocation. Relative branches are
- // offset by 4 on ARM, however, because there is no RELA relocations, all
- // branches are offset by 4.
- FixedValue = FixedValue + 4;
- break;
- }
- }
-
- // The fixed value never makes sense for section indices, ignore it.
- if (Fixup.getKind() == FK_SecRel_2)
- FixedValue = 0;
-
- if (TargetObjectWriter->recordRelocation(Fixup))
- Sec->Relocations.push_back(Reloc);
-}
-
-static std::time_t getTime() {
- std::time_t Now = time(nullptr);
- if (Now < 0 || !isUInt<32>(Now))
- return UINT32_MAX;
- return Now;
-}
-
-// Create .file symbols.
-void WinCOFFObjectWriter::createFileSymbols(MCAssembler &Asm) {
- for (const std::string &Name : Asm.getFileNames()) {
- // round up to calculate the number of auxiliary symbols required
- unsigned SymbolSize = UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size;
- unsigned Count = (Name.size() + SymbolSize - 1) / SymbolSize;
-
- COFFSymbol *File = createSymbol(".file");
- File->Data.SectionNumber = COFF::IMAGE_SYM_DEBUG;
- File->Data.StorageClass = COFF::IMAGE_SYM_CLASS_FILE;
- File->Aux.resize(Count);
-
- unsigned Offset = 0;
- unsigned Length = Name.size();
- for (auto &Aux : File->Aux) {
- Aux.AuxType = ATFile;
-
- if (Length > SymbolSize) {
- memcpy(&Aux.Aux, Name.c_str() + Offset, SymbolSize);
- Length = Length - SymbolSize;
- } else {
- memcpy(&Aux.Aux, Name.c_str() + Offset, Length);
- memset((char *)&Aux.Aux + Length, 0, SymbolSize - Length);
- break;
- }
-
- Offset += SymbolSize;
- }
- }
-}
-
-static bool isAssociative(const COFFSection &Section) {
- return Section.Symbol->Aux[0].Aux.SectionDefinition.Selection ==
- COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE;
-}
-
-void WinCOFFObjectWriter::assignSectionNumbers() {
- size_t I = 1;
- auto Assign = [&](COFFSection &Section) {
- Section.Number = I;
- Section.Symbol->Data.SectionNumber = I;
- Section.Symbol->Aux[0].Aux.SectionDefinition.Number = I;
- ++I;
- };
-
- // Although it is not explicitly requested by the Microsoft COFF spec,
- // we should avoid emitting forward associative section references,
- // because MSVC link.exe as of 2017 cannot handle that.
- for (const std::unique_ptr<COFFSection> &Section : Sections)
- if (!isAssociative(*Section))
- Assign(*Section);
- for (const std::unique_ptr<COFFSection> &Section : Sections)
- if (isAssociative(*Section))
- Assign(*Section);
-}
-
-// Assign file offsets to COFF object file structures.
-void WinCOFFObjectWriter::assignFileOffsets(MCAssembler &Asm,
- const MCAsmLayout &Layout) {
- unsigned Offset = W.OS.tell();
-
- Offset += UseBigObj ? COFF::Header32Size : COFF::Header16Size;
- Offset += COFF::SectionSize * Header.NumberOfSections;
-
- for (const auto &Section : Asm) {
- COFFSection *Sec = SectionMap[&Section];
-
- if (Sec->Number == -1)
- continue;
-
- Sec->Header.SizeOfRawData = Layout.getSectionAddressSize(&Section);
-
- if (IsPhysicalSection(Sec)) {
- Sec->Header.PointerToRawData = Offset;
- Offset += Sec->Header.SizeOfRawData;
- }
-
- if (!Sec->Relocations.empty()) {
- bool RelocationsOverflow = Sec->Relocations.size() >= 0xffff;
-
- if (RelocationsOverflow) {
- // Signal overflow by setting NumberOfRelocations to max value. Actual
- // size is found in reloc #0. Microsoft tools understand this.
- Sec->Header.NumberOfRelocations = 0xffff;
- } else {
- Sec->Header.NumberOfRelocations = Sec->Relocations.size();
- }
- Sec->Header.PointerToRelocations = Offset;
-
- if (RelocationsOverflow) {
- // Reloc #0 will contain actual count, so make room for it.
- Offset += COFF::RelocationSize;
- }
-
- Offset += COFF::RelocationSize * Sec->Relocations.size();
-
- for (auto &Relocation : Sec->Relocations) {
- assert(Relocation.Symb->getIndex() != -1);
- Relocation.Data.SymbolTableIndex = Relocation.Symb->getIndex();
- }
- }
-
- assert(Sec->Symbol->Aux.size() == 1 &&
- "Section's symbol must have one aux!");
- AuxSymbol &Aux = Sec->Symbol->Aux[0];
- assert(Aux.AuxType == ATSectionDefinition &&
- "Section's symbol's aux symbol must be a Section Definition!");
- Aux.Aux.SectionDefinition.Length = Sec->Header.SizeOfRawData;
- Aux.Aux.SectionDefinition.NumberOfRelocations =
- Sec->Header.NumberOfRelocations;
- Aux.Aux.SectionDefinition.NumberOfLinenumbers =
- Sec->Header.NumberOfLineNumbers;
- }
-
- Header.PointerToSymbolTable = Offset;
-}
-
-uint64_t WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
- const MCAsmLayout &Layout) {
- uint64_t StartOffset = W.OS.tell();
-
- if (Sections.size() > INT32_MAX)
- report_fatal_error(
- "PE COFF object files can't have more than 2147483647 sections");
-
- UseBigObj = Sections.size() > COFF::MaxNumberOfSections16;
- Header.NumberOfSections = Sections.size();
- Header.NumberOfSymbols = 0;
-
- assignSectionNumbers();
- createFileSymbols(Asm);
-
- for (auto &Symbol : Symbols) {
- // Update section number & offset for symbols that have them.
- if (Symbol->Section)
- Symbol->Data.SectionNumber = Symbol->Section->Number;
- Symbol->setIndex(Header.NumberOfSymbols++);
- // Update auxiliary symbol info.
- Symbol->Data.NumberOfAuxSymbols = Symbol->Aux.size();
- Header.NumberOfSymbols += Symbol->Data.NumberOfAuxSymbols;
- }
-
- // Build string table.
- for (const auto &S : Sections)
- if (S->Name.size() > COFF::NameSize)
- Strings.add(S->Name);
- for (const auto &S : Symbols)
- if (S->Name.size() > COFF::NameSize)
- Strings.add(S->Name);
- Strings.finalize();
-
- // Set names.
- for (const auto &S : Sections)
- SetSectionName(*S);
- for (auto &S : Symbols)
- SetSymbolName(*S);
-
- // Fixup weak external references.
- for (auto &Symbol : Symbols) {
- if (Symbol->Other) {
- assert(Symbol->getIndex() != -1);
- assert(Symbol->Aux.size() == 1 && "Symbol must contain one aux symbol!");
- assert(Symbol->Aux[0].AuxType == ATWeakExternal &&
- "Symbol's aux symbol must be a Weak External!");
- Symbol->Aux[0].Aux.WeakExternal.TagIndex = Symbol->Other->getIndex();
- }
- }
-
- // Fixup associative COMDAT sections.
- for (auto &Section : Sections) {
- if (Section->Symbol->Aux[0].Aux.SectionDefinition.Selection !=
- COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
- continue;
-
- const MCSectionCOFF &MCSec = *Section->MCSection;
- const MCSymbol *AssocMCSym = MCSec.getCOMDATSymbol();
- assert(AssocMCSym);
-
- // It's an error to try to associate with an undefined symbol or a symbol
- // without a section.
- if (!AssocMCSym->isInSection()) {
- Asm.getContext().reportError(
- SMLoc(), Twine("cannot make section ") + MCSec.getSectionName() +
- Twine(" associative with sectionless symbol ") +
- AssocMCSym->getName());
- continue;
- }
-
- const auto *AssocMCSec = cast<MCSectionCOFF>(&AssocMCSym->getSection());
- assert(SectionMap.count(AssocMCSec));
- COFFSection *AssocSec = SectionMap[AssocMCSec];
-
- // Skip this section if the associated section is unused.
- if (AssocSec->Number == -1)
- continue;
-
- Section->Symbol->Aux[0].Aux.SectionDefinition.Number = AssocSec->Number;
- }
-
- // Create the contents of the .llvm_addrsig section.
- if (EmitAddrsigSection) {
- auto Frag = new MCDataFragment(AddrsigSection);
- Frag->setLayoutOrder(0);
- raw_svector_ostream OS(Frag->getContents());
- for (const MCSymbol *S : AddrsigSyms) {
- if (!S->isTemporary()) {
- encodeULEB128(S->getIndex(), OS);
- continue;
- }
-
- MCSection *TargetSection = &S->getSection();
- assert(SectionMap.find(TargetSection) != SectionMap.end() &&
- "Section must already have been defined in "
- "executePostLayoutBinding!");
- encodeULEB128(SectionMap[TargetSection]->Symbol->getIndex(), OS);
- }
- }
-
- assignFileOffsets(Asm, Layout);
-
- // MS LINK expects to be able to use this timestamp to implement their
- // /INCREMENTAL feature.
- if (Asm.isIncrementalLinkerCompatible()) {
- Header.TimeDateStamp = getTime();
- } else {
- // Have deterministic output if /INCREMENTAL isn't needed. Also matches GNU.
- Header.TimeDateStamp = 0;
- }
-
- // Write it all to disk...
- WriteFileHeader(Header);
- writeSectionHeaders();
-
- // Write section contents.
- sections::iterator I = Sections.begin();
- sections::iterator IE = Sections.end();
- MCAssembler::iterator J = Asm.begin();
- MCAssembler::iterator JE = Asm.end();
- for (; I != IE && J != JE; ++I, ++J)
- writeSection(Asm, Layout, **I, *J);
-
- assert(W.OS.tell() == Header.PointerToSymbolTable &&
- "Header::PointerToSymbolTable is insane!");
-
- // Write a symbol table.
- for (auto &Symbol : Symbols)
- if (Symbol->getIndex() != -1)
- WriteSymbol(*Symbol);
-
- // Write a string table, which completes the entire COFF file.
- Strings.write(W.OS);
-
- return W.OS.tell() - StartOffset;
-}
-
-MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_)
- : Machine(Machine_) {}
-
-// Pin the vtable to this file.
-void MCWinCOFFObjectTargetWriter::anchor() {}
-
-//------------------------------------------------------------------------------
-// WinCOFFObjectWriter factory function
-
-std::unique_ptr<MCObjectWriter> llvm::createWinCOFFObjectWriter(
- std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS) {
- return llvm::make_unique<WinCOFFObjectWriter>(std::move(MOTW), OS);
-}
diff --git a/contrib/llvm/lib/MC/XCOFFObjectWriter.cpp b/contrib/llvm/lib/MC/XCOFFObjectWriter.cpp
deleted file mode 100644
index 9b9a7b6c118c..000000000000
--- a/contrib/llvm/lib/MC/XCOFFObjectWriter.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-//===-- lib/MC/XCOFFObjectWriter.cpp - XCOFF file writer ------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements XCOFF object file writer information.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCAssembler.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/MC/MCXCOFFObjectWriter.h"
-
-using namespace llvm;
-
-namespace {
-
-class XCOFFObjectWriter : public MCObjectWriter {
- support::endian::Writer W;
- std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
-
- void executePostLayoutBinding(MCAssembler &, const MCAsmLayout &) override;
-
- void recordRelocation(MCAssembler &, const MCAsmLayout &, const MCFragment *,
- const MCFixup &, MCValue, uint64_t &) override;
-
- uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override;
-
-public:
- XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
- raw_pwrite_stream &OS);
-};
-
-XCOFFObjectWriter::XCOFFObjectWriter(
- std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
- : W(OS, support::big), TargetObjectWriter(std::move(MOTW)) {}
-
-void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &,
- const MCAsmLayout &) {
- // TODO Implement once we have sections and symbols to handle.
-}
-
-void XCOFFObjectWriter::recordRelocation(MCAssembler &, const MCAsmLayout &,
- const MCFragment *, const MCFixup &,
- MCValue, uint64_t &) {
- report_fatal_error("XCOFF relocations not supported.");
-}
-
-uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &) {
- // We always emit a timestamp of 0 for reproducibility, so ensure incremental
- // linking is not enabled, in case, like with Windows COFF, such a timestamp
- // is incompatible with incremental linking of XCOFF.
- if (Asm.isIncrementalLinkerCompatible())
- report_fatal_error("Incremental linking not supported for XCOFF.");
-
- if (TargetObjectWriter->is64Bit())
- report_fatal_error("64-bit XCOFF object files are not supported yet.");
-
- uint64_t StartOffset = W.OS.tell();
-
- // TODO FIXME Assign section numbers/finalize sections.
-
- // TODO FIXME Finalize symbols.
-
- // Magic.
- W.write<uint16_t>(0x01df);
- // Number of sections.
- W.write<uint16_t>(0);
- // Timestamp field. For reproducible output we write a 0, which represents no
- // timestamp.
- W.write<int32_t>(0);
- // Byte Offset to the start of the symbol table.
- W.write<uint32_t>(0);
- // Number of entries in the symbol table.
- W.write<int32_t>(0);
- // Size of the optional header.
- W.write<uint16_t>(0);
- // Flags.
- W.write<uint16_t>(0);
-
- return W.OS.tell() - StartOffset;
-}
-
-} // end anonymous namespace
-
-std::unique_ptr<MCObjectWriter>
-llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
- raw_pwrite_stream &OS) {
- return llvm::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS);
-}