diff options
Diffstat (limited to 'contrib/llvm/lib/MC')
63 files changed, 3444 insertions, 1280 deletions
diff --git a/contrib/llvm/lib/MC/ConstantPools.cpp b/contrib/llvm/lib/MC/ConstantPools.cpp index bf2c39e..ca54402 100644 --- a/contrib/llvm/lib/MC/ConstantPools.cpp +++ b/contrib/llvm/lib/MC/ConstantPools.cpp @@ -1,4 +1,4 @@ -//===- ConstantPools.cpp - ConstantPool class --*- C++ -*---------===// +//===- ConstantPools.cpp - ConstantPool class -----------------------------===// // // The LLVM Compiler Infrastructure // @@ -10,13 +10,16 @@ // This file implements the ConstantPool and AssemblerConstantPools classes. // //===----------------------------------------------------------------------===// -#include "llvm/ADT/MapVector.h" + #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 // diff --git a/contrib/llvm/lib/MC/ELFObjectWriter.cpp b/contrib/llvm/lib/MC/ELFObjectWriter.cpp index a8c88dd..c8dd630 100644 --- a/contrib/llvm/lib/MC/ELFObjectWriter.cpp +++ b/contrib/llvm/lib/MC/ELFObjectWriter.cpp @@ -11,29 +11,51 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringMap.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/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/Debug.h" -#include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/SMLoc.h" #include "llvm/Support/StringSaver.h" +#include "llvm/Support/SwapByteOrder.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <map> +#include <memory> +#include <string> +#include <utility> #include <vector> using namespace llvm; @@ -42,7 +64,8 @@ using namespace llvm; #define DEBUG_TYPE "reloc-info" namespace { -typedef DenseMap<const MCSectionELF *, uint32_t> SectionIndexMapTy; + +using SectionIndexMapTy = DenseMap<const MCSectionELF *, uint32_t>; class ELFObjectWriter; @@ -99,8 +122,7 @@ class ELFObjectWriter : public MCObjectWriter { DenseMap<const MCSymbolELF *, const MCSymbolELF *> Renames; - llvm::DenseMap<const MCSectionELF *, std::vector<ELFRelocationEntry>> - Relocations; + DenseMap<const MCSectionELF *, std::vector<ELFRelocationEntry>> Relocations; /// @} /// @name Symbol Table Data @@ -144,6 +166,8 @@ public: bool IsLittleEndian) : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {} + ~ELFObjectWriter() override = default; + void reset() override { Renames.clear(); Relocations.clear(); @@ -152,8 +176,6 @@ public: MCObjectWriter::reset(); } - ~ELFObjectWriter() override; - void WriteWord(uint64_t W) { if (is64Bit()) write64(W); @@ -174,8 +196,8 @@ public: ELFSymbolData &MSD, const MCAsmLayout &Layout); // Start and end offset of each section - typedef std::map<const MCSectionELF *, std::pair<uint64_t, uint64_t>> - SectionOffsetsTy; + using SectionOffsetsTy = + std::map<const MCSectionELF *, std::pair<uint64_t, uint64_t>>; bool shouldRelocateWithSymbol(const MCAssembler &Asm, const MCSymbolRefExpr *RefA, @@ -184,11 +206,10 @@ public: void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, - MCValue Target, bool &IsPCRel, - uint64_t &FixedValue) override; + MCValue Target, uint64_t &FixedValue) override; // Map from a signature symbol to the group section index - typedef DenseMap<const MCSymbol *, unsigned> RevGroupMapTy; + using RevGroupMapTy = DenseMap<const MCSymbol *, unsigned>; /// Compute the symbol table data /// @@ -222,18 +243,18 @@ public: void writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec); + using MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl; bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB, bool InSet, bool IsPCRel) const override; - bool isWeak(const MCSymbol &Sym) const override; - void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; void writeSection(const SectionIndexMapTy &SectionIndexMap, uint32_t GroupSymbolIndex, uint64_t Offset, uint64_t Size, const MCSectionELF &Section); }; + } // end anonymous namespace void ELFObjectWriter::align(unsigned Alignment) { @@ -297,9 +318,6 @@ void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value, ++NumWritten; } -ELFObjectWriter::~ELFObjectWriter() -{} - // Emit the ELF header. void ELFObjectWriter::writeHeader(const MCAssembler &Asm) { // ELF Header @@ -370,22 +388,6 @@ uint64_t ELFObjectWriter::SymbolValue(const MCSymbol &Sym, void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) { - // Section symbols are used as definitions for undefined symbols with matching - // names. If there are multiple sections with the same name, the first one is - // used. - for (const MCSection &Sec : Asm) { - const MCSymbol *Begin = Sec.getBeginSymbol(); - if (!Begin) - continue; - - const MCSymbol *Alias = Asm.getContext().lookupSymbol(Begin->getName()); - if (!Alias || !Alias->isUndefined()) - continue; - - Renames.insert( - std::make_pair(cast<MCSymbolELF>(Alias), cast<MCSymbolELF>(Begin))); - } - // The presence of symbol versions causes undefined symbols and // versions declared with @@@ to be renamed. for (const MCSymbol &A : Asm.symbols()) { @@ -625,16 +627,16 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, - bool &IsPCRel, uint64_t &FixedValue) { + 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()) { - 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). @@ -900,6 +902,8 @@ void ELFObjectWriter::computeSymbolTable( 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, @@ -1017,18 +1021,24 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec, 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 = - Asm.getContext().getAsmInfo()->compressDebugSections() != - DebugCompressionType::DCT_None; + MAI->compressDebugSections() != DebugCompressionType::None; if (!CompressionEnabled || !SectionName.startswith(".debug_") || SectionName == ".debug_frame") { Asm.writeSectionData(&Section, Layout); return; } + assert((MAI->compressDebugSections() == DebugCompressionType::Z || + MAI->compressDebugSections() == DebugCompressionType::GNU) && + "expected zlib or zlib-gnu style compression"); + SmallVector<char, 128> UncompressedData; raw_svector_ostream VecOS(UncompressedData); raw_pwrite_stream &OldStream = getStream(); @@ -1037,16 +1047,15 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec, setStream(OldStream); SmallVector<char, 128> CompressedContents; - zlib::Status Success = zlib::compress( - StringRef(UncompressedData.data(), UncompressedData.size()), - CompressedContents); - if (Success != zlib::StatusOK) { + if (Error E = zlib::compress( + StringRef(UncompressedData.data(), UncompressedData.size()), + CompressedContents)) { + consumeError(std::move(E)); getStream() << UncompressedData; return; } - bool ZlibStyle = Asm.getContext().getAsmInfo()->compressDebugSections() == - DebugCompressionType::DCT_Zlib; + bool ZlibStyle = MAI->compressDebugSections() == DebugCompressionType::Z; if (!maybeWriteCompression(UncompressedData.size(), CompressedContents, ZlibStyle, Sec.getAlignment())) { getStream() << UncompressedData; @@ -1058,8 +1067,7 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec, Section.setFlags(Section.getFlags() | ELF::SHF_COMPRESSED); else // Add "z" prefix to section name. This is zlib-gnu style. - Asm.getContext().renameELFSection(&Section, - (".z" + SectionName.drop_front(1)).str()); + MC.renameELFSection(&Section, (".z" + SectionName.drop_front(1)).str()); getStream() << CompressedContents; } @@ -1151,8 +1159,8 @@ void ELFObjectWriter::writeSection(const SectionIndexMapTy &SectionIndexMap, case ELF::SHT_RELA: { sh_link = SymbolTableIndex; assert(sh_link && ".symtab not found"); - const MCSectionELF *InfoSection = Section.getAssociatedSection(); - sh_info = SectionIndexMap.lookup(InfoSection); + const MCSection *InfoSection = Section.getAssociatedSection(); + sh_info = SectionIndexMap.lookup(cast<MCSectionELF>(InfoSection)); break; } @@ -1172,9 +1180,11 @@ void ELFObjectWriter::writeSection(const SectionIndexMapTy &SectionIndexMap, break; } - if (TargetObjectWriter->getEMachine() == ELF::EM_ARM && - Section.getType() == ELF::SHT_ARM_EXIDX) - sh_link = SectionIndexMap.lookup(Section.getAssociatedSection()); + 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, @@ -1298,7 +1308,8 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm, // Remember the offset into the file for this section. uint64_t SecStart = getStream().tell(); - writeRelocations(Asm, *RelSection->getAssociatedSection()); + writeRelocations(Asm, + cast<MCSectionELF>(*RelSection->getAssociatedSection())); uint64_t SecEnd = getStream().tell(); SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd); @@ -1351,34 +1362,13 @@ bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl( const auto &SymA = cast<MCSymbolELF>(SA); if (IsPCRel) { assert(!InSet); - if (::isWeak(SymA)) + if (isWeak(SymA)) return false; } return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB, InSet, IsPCRel); } -bool ELFObjectWriter::isWeak(const MCSymbol &S) const { - const auto &Sym = cast<MCSymbolELF>(S); - if (::isWeak(Sym)) - return true; - - // It is invalid to replace a reference to a global in a comdat - // with a reference to a local since out of comdat references - // to a local are forbidden. - // We could try to return false for more cases, like the reference - // being in the same comdat or Sym being an alias to another global, - // but it is not clear if it is worth the effort. - if (Sym.getBinding() != ELF::STB_GLOBAL) - return false; - - if (!Sym.isInSection()) - return false; - - const auto &Sec = cast<MCSectionELF>(Sym.getSection()); - return Sec.getGroup(); -} - MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_pwrite_stream &OS, bool IsLittleEndian) { diff --git a/contrib/llvm/lib/MC/MCAsmBackend.cpp b/contrib/llvm/lib/MC/MCAsmBackend.cpp index 570f764..3642f37 100644 --- a/contrib/llvm/lib/MC/MCAsmBackend.cpp +++ b/contrib/llvm/lib/MC/MCAsmBackend.cpp @@ -1,4 +1,4 @@ -//===-- MCAsmBackend.cpp - Target MC Assembly Backend ----------------------==// +//===- MCAsmBackend.cpp - Target MC Assembly Backend ----------------------===// // // The LLVM Compiler Infrastructure // @@ -8,13 +8,18 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCAsmBackend.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCFixupKindInfo.h" +#include <cassert> +#include <cstddef> +#include <cstdint> + using namespace llvm; -MCAsmBackend::MCAsmBackend() {} +MCAsmBackend::MCAsmBackend() = default; -MCAsmBackend::~MCAsmBackend() {} +MCAsmBackend::~MCAsmBackend() = default; Optional<MCFixupKind> MCAsmBackend::getFixupKind(StringRef Name) const { return None; diff --git a/contrib/llvm/lib/MC/MCAsmInfo.cpp b/contrib/llvm/lib/MC/MCAsmInfo.cpp index 3eb8f50..f059040 100644 --- a/contrib/llvm/lib/MC/MCAsmInfo.cpp +++ b/contrib/llvm/lib/MC/MCAsmInfo.cpp @@ -1,4 +1,4 @@ -//===-- MCAsmInfo.cpp - Asm Info -------------------------------------------==// +//===- MCAsmInfo.cpp - Asm Info -------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -13,32 +13,17 @@ //===----------------------------------------------------------------------===// #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/DataTypes.h" -#include "llvm/Support/Dwarf.h" -#include <cctype> -#include <cstring> + using namespace llvm; MCAsmInfo::MCAsmInfo() { - PointerSize = 4; - CalleeSaveStackSlotSize = 4; - - IsLittleEndian = true; - StackGrowsUp = false; - HasSubsectionsViaSymbols = false; - HasMachoZeroFillDirective = false; - HasMachoTBSSDirective = false; - MaxInstLength = 4; - MinInstAlignment = 1; - DollarIsPC = false; SeparatorString = ";"; CommentString = "#"; LabelSuffix = ":"; - UseAssignmentForEHBegin = false; - NeedsLocalForSize = false; PrivateGlobalPrefix = "L"; PrivateLabelPrefix = PrivateGlobalPrefix; LinkerPrivateGlobalPrefix = ""; @@ -47,10 +32,6 @@ MCAsmInfo::MCAsmInfo() { Code16Directive = ".code16"; Code32Directive = ".code32"; Code64Directive = ".code64"; - AssemblerDialect = 0; - AllowAtInName = false; - SupportsQuotedNames = true; - UseDataRegionDirectives = false; ZeroDirective = "\t.zero\t"; AsciiDirective = "\t.ascii\t"; AscizDirective = "\t.asciz\t"; @@ -58,40 +39,8 @@ MCAsmInfo::MCAsmInfo() { Data16bitsDirective = "\t.short\t"; Data32bitsDirective = "\t.long\t"; Data64bitsDirective = "\t.quad\t"; - SunStyleELFSectionSwitchSyntax = false; - UsesELFSectionDirectiveForBSS = false; - AlignmentIsInBytes = true; - TextAlignFillValue = 0; - GPRel64Directive = nullptr; - GPRel32Directive = nullptr; GlobalDirective = "\t.globl\t"; - SetDirectiveSuppressesReloc = false; - HasAggressiveSymbolFolding = true; - COMMDirectiveAlignmentIsInBytes = true; - LCOMMDirectiveAlignmentType = LCOMM::NoAlignment; - HasFunctionAlignment = true; - HasDotTypeDotSizeDirective = true; - HasSingleParameterDotFile = true; - HasIdentDirective = false; - HasNoDeadStrip = false; - HasAltEntry = false; WeakDirective = "\t.weak\t"; - WeakRefDirective = nullptr; - HasWeakDefDirective = false; - HasWeakDefCanBeHiddenDirective = false; - HasLinkOnceDirective = false; - HiddenVisibilityAttr = MCSA_Hidden; - HiddenDeclarationVisibilityAttr = MCSA_Hidden; - ProtectedVisibilityAttr = MCSA_Protected; - SupportsDebugInformation = false; - ExceptionsType = ExceptionHandling::None; - WinEHEncodingType = WinEH::EncodingType::Invalid; - DwarfUsesRelocationsAcrossSections = true; - DwarfFDESymbolsUseAbsDiff = false; - DwarfRegNumForCFI = false; - NeedsDwarfSectionOffsetDirective = false; - UseParensForSymbolVariant = false; - UseLogicalShr = true; // FIXME: Clang's logic should be synced with the logic used to initialize // this member and the two implementations should be merged. @@ -107,12 +56,9 @@ MCAsmInfo::MCAsmInfo() { // - The target subclasses for AArch64, ARM, and X86 handle these cases UseIntegratedAssembler = false; PreserveAsmComments = true; - - CompressDebugSections = DebugCompressionType::DCT_None; } -MCAsmInfo::~MCAsmInfo() { -} +MCAsmInfo::~MCAsmInfo() = default; bool MCAsmInfo::isSectionAtomizableBySymbols(const MCSection &Section) const { return false; diff --git a/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp b/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp index 5b9dd20..8510448 100644 --- a/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp +++ b/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp @@ -1,4 +1,4 @@ -//===-- MCAsmInfoCOFF.cpp - COFF asm properties -----------------*- C++ -*-===// +//===- MCAsmInfoCOFF.cpp - COFF asm properties ----------------------------===// // // The LLVM Compiler Infrastructure // @@ -13,9 +13,11 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCAsmInfoCOFF.h" +#include "llvm/MC/MCDirectives.h" + using namespace llvm; -void MCAsmInfoCOFF::anchor() { } +void MCAsmInfoCOFF::anchor() {} MCAsmInfoCOFF::MCAsmInfoCOFF() { // MingW 4.5 and later support .comm with log2 alignment, but .lcomm uses byte @@ -41,13 +43,10 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() { UseLogicalShr = false; } -void MCAsmInfoMicrosoft::anchor() { } - -MCAsmInfoMicrosoft::MCAsmInfoMicrosoft() { -} +void MCAsmInfoMicrosoft::anchor() {} -void MCAsmInfoGNUCOFF::anchor() { } +MCAsmInfoMicrosoft::MCAsmInfoMicrosoft() = default; -MCAsmInfoGNUCOFF::MCAsmInfoGNUCOFF() { +void MCAsmInfoGNUCOFF::anchor() {} -} +MCAsmInfoGNUCOFF::MCAsmInfoGNUCOFF() = default; diff --git a/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp b/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp index e95cf48..c748409 100644 --- a/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp +++ b/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp @@ -1,4 +1,4 @@ -//===-- MCAsmInfoDarwin.cpp - Darwin asm properties -------------*- C++ -*-===// +//===- MCAsmInfoDarwin.cpp - Darwin asm properties ------------------------===// // // The LLVM Compiler Infrastructure // @@ -13,9 +13,10 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCAsmInfoDarwin.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" +#include "llvm/BinaryFormat/MachO.h" +#include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCSectionMachO.h" + using namespace llvm; bool MCAsmInfoDarwin::isSectionAtomizableBySymbols( diff --git a/contrib/llvm/lib/MC/MCAsmInfoELF.cpp b/contrib/llvm/lib/MC/MCAsmInfoELF.cpp index 26e5608..b0dc43c 100644 --- a/contrib/llvm/lib/MC/MCAsmInfoELF.cpp +++ b/contrib/llvm/lib/MC/MCAsmInfoELF.cpp @@ -1,4 +1,4 @@ -//===-- MCAsmInfoELF.cpp - ELF asm properties -------------------*- C++ -*-===// +//===- MCAsmInfoELF.cpp - ELF asm properties ------------------------------===// // // The LLVM Compiler Infrastructure // @@ -13,12 +13,13 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCAsmInfoELF.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSectionELF.h" -#include "llvm/Support/ELF.h" + using namespace llvm; -void MCAsmInfoELF::anchor() { } +void MCAsmInfoELF::anchor() {} MCSection *MCAsmInfoELF::getNonexecutableStackSection(MCContext &Ctx) const { if (!UsesNonexecutableStackSection) @@ -31,5 +32,4 @@ MCAsmInfoELF::MCAsmInfoELF() { WeakRefDirective = "\t.weak\t"; PrivateGlobalPrefix = ".L"; PrivateLabelPrefix = ".L"; - UsesNonexecutableStackSection = true; } diff --git a/contrib/llvm/lib/MC/MCAsmInfoWasm.cpp b/contrib/llvm/lib/MC/MCAsmInfoWasm.cpp new file mode 100644 index 0000000..aa26616 --- /dev/null +++ b/contrib/llvm/lib/MC/MCAsmInfoWasm.cpp @@ -0,0 +1,27 @@ +//===-- MCAsmInfoWasm.cpp - Wasm asm properties -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines target asm properties related what form asm statements +// should take in general on Wasm-based targets +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCAsmInfoWasm.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSectionWasm.h" +using namespace llvm; + +void MCAsmInfoWasm::anchor() { } + +MCAsmInfoWasm::MCAsmInfoWasm() { + HasIdentDirective = true; + WeakRefDirective = "\t.weak\t"; + PrivateGlobalPrefix = ".L"; + PrivateLabelPrefix = ".L"; +} diff --git a/contrib/llvm/lib/MC/MCAsmStreamer.cpp b/contrib/llvm/lib/MC/MCAsmStreamer.cpp index 817009a..9e5553f 100644 --- a/contrib/llvm/lib/MC/MCAsmStreamer.cpp +++ b/contrib/llvm/lib/MC/MCAsmStreamer.cpp @@ -103,7 +103,10 @@ public: void AddComment(const Twine &T, bool EOL = true) override; /// AddEncodingComment - Add a comment showing the encoding of an instruction. - void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &); + /// If PrintSchedInfo - is true then the comment sched:[x:y] should + // be added to output if it's being supported by target + void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &, + bool PrintSchedInfo); /// GetCommentOS - Return a raw_ostream that comments can be written to. /// Unlike AddComment, you are required to terminate comments with \n if you @@ -130,7 +133,7 @@ public: void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override; - void EmitLabel(MCSymbol *Symbol) override; + void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitLinkerOptions(ArrayRef<std::string> Options) override; @@ -278,7 +281,8 @@ public: void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except) override; void EmitWinEHHandlerData() override; - void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; + void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, + bool PrintSchedInfo) override; void EmitBundleAlignMode(unsigned AlignPow2) override; void EmitBundleLock(bool AlignToEnd) override; @@ -392,12 +396,13 @@ void MCAsmStreamer::emitExplicitComments() { void MCAsmStreamer::ChangeSection(MCSection *Section, const MCExpr *Subsection) { assert(Section && "Cannot switch to a null section!"); - Section->PrintSwitchToSection(*MAI, OS, Subsection); + Section->PrintSwitchToSection( + *MAI, getContext().getObjectFileInfo()->getTargetTriple(), OS, + Subsection); } -void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) { - assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - MCStreamer::EmitLabel(Symbol); +void MCAsmStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) { + MCStreamer::EmitLabel(Symbol, Loc); Symbol->print(OS, MAI); OS << MAI->getLabelSuffix(); @@ -1503,7 +1508,8 @@ void MCAsmStreamer::EmitWinCFIEndProlog() { } void MCAsmStreamer::AddEncodingComment(const MCInst &Inst, - const MCSubtargetInfo &STI) { + const MCSubtargetInfo &STI, + bool PrintSchedInfo) { raw_ostream &OS = GetCommentOS(); SmallString<256> Code; SmallVector<MCFixup, 4> Fixups; @@ -1576,7 +1582,11 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst, } } } - OS << "]\n"; + OS << "]"; + // If we are not going to add fixup or schedul comments after this point then + // we have to end the current comment line with "\n". + if (Fixups.size() || !PrintSchedInfo) + OS << "\n"; for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { MCFixup &F = Fixups[i]; @@ -1587,16 +1597,19 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst, } void MCAsmStreamer::EmitInstruction(const MCInst &Inst, - const MCSubtargetInfo &STI) { + const MCSubtargetInfo &STI, + bool PrintSchedInfo) { assert(getCurrentSectionOnly() && "Cannot emit contents before setting section!"); // Show the encoding in a comment if we have a code emitter. if (Emitter) - AddEncodingComment(Inst, STI); + AddEncodingComment(Inst, STI, PrintSchedInfo); // Show the MCInst if enabled. if (ShowInst) { + if (PrintSchedInfo) + GetCommentOS() << "\n"; Inst.dump_pretty(GetCommentOS(), InstPrinter.get(), "\n "); GetCommentOS() << "\n"; } @@ -1606,6 +1619,16 @@ void MCAsmStreamer::EmitInstruction(const MCInst &Inst, else InstPrinter->printInst(&Inst, OS, "", STI); + if (PrintSchedInfo) { + std::string SI = STI.getSchedInfoStr(Inst); + if (!SI.empty()) + GetCommentOS() << SI; + } + + StringRef Comments = CommentToEmit; + if (Comments.size() && Comments.back() != '\n') + GetCommentOS() << "\n"; + EmitEOL(); } diff --git a/contrib/llvm/lib/MC/MCAssembler.cpp b/contrib/llvm/lib/MC/MCAssembler.cpp index 83fcec9..eaf6f19 100644 --- a/contrib/llvm/lib/MC/MCAssembler.cpp +++ b/contrib/llvm/lib/MC/MCAssembler.cpp @@ -8,8 +8,11 @@ //===----------------------------------------------------------------------===// #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/StringExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmInfo.h" @@ -19,24 +22,34 @@ #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/TargetRegistry.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"); @@ -55,8 +68,9 @@ STATISTIC(FragmentLayouts, "Number of fragment layouts"); STATISTIC(ObjectBytes, "Number of emitted object file bytes"); STATISTIC(RelaxationSteps, "Number of assembler layout and relaxation steps"); STATISTIC(RelaxedInstructions, "Number of relaxed instructions"); -} -} + +} // end namespace stats +} // end anonymous namespace // FIXME FIXME FIXME: There are number of places in this file where we convert // what is a 64-bit assembler value used for computation into a value in the @@ -73,8 +87,7 @@ MCAssembler::MCAssembler(MCContext &Context, MCAsmBackend &Backend, VersionMinInfo.Major = 0; // Major version == 0 for "none specified" } -MCAssembler::~MCAssembler() { -} +MCAssembler::~MCAssembler() = default; void MCAssembler::reset() { Sections.clear(); @@ -114,10 +127,16 @@ bool MCAssembler::isThumbFunc(const MCSymbol *Symbol) const { if (!Symbol->isVariable()) return false; - // FIXME: It looks like gas supports some cases of the form "foo + 2". It - // is not clear if that is a bug or a feature. const MCExpr *Expr = Symbol->getVariableValue(); - const MCSymbolRefExpr *Ref = dyn_cast<MCSymbolRefExpr>(Expr); + + 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; @@ -174,14 +193,23 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, // FIXME: This code has some duplication with recordRelocation. We should // probably merge the two into a single callback that tries to evaluate a // fixup and records a relocation if one is needed. + + // On error claim to have completely evaluated the fixup, to prevent any + // further processing from being done. const MCExpr *Expr = Fixup.getValue(); + MCContext &Ctx = getContext(); + Value = 0; if (!Expr->evaluateAsRelocatable(Target, &Layout, &Fixup)) { - getContext().reportError(Fixup.getLoc(), "expected relocatable expression"); - // Claim to have completely evaluated the fixup, to prevent any further - // processing from being done. - Value = 0; + Ctx.reportError(Fixup.getLoc(), "expected relocatable expression"); return true; } + if (const MCSymbolRefExpr *RefB = Target.getSymB()) { + if (RefB->getKind() != MCSymbolRefExpr::VK_None) { + Ctx.reportError(Fixup.getLoc(), + "unsupported subtraction of qualified symbol"); + return true; + } + } bool IsPCRel = Backend.getFixupKindInfo( Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel; @@ -219,7 +247,6 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, Value -= Layout.getSymbolOffset(Sym); } - bool ShouldAlignPC = Backend.getFixupKindInfo(Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsAlignedDownTo32Bits; assert((ShouldAlignPC ? IsPCRel : true) && @@ -234,10 +261,9 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, Value -= Offset; } - // Let the backend adjust the fixup value if necessary, including whether - // we need a relocation. - Backend.processFixupValue(*this, Layout, Fixup, DF, Target, Value, - IsResolved); + // Let the backend force a relocation if needed. + if (IsResolved && Backend.shouldForceRelocation(*this, Fixup, Target)) + IsResolved = false; return IsResolved; } @@ -621,27 +647,25 @@ void MCAssembler::writeSectionData(const MCSection *Sec, Layout.getSectionAddressSize(Sec)); } -std::pair<uint64_t, bool> MCAssembler::handleFixup(const MCAsmLayout &Layout, - MCFragment &F, - const MCFixup &Fixup) { +std::tuple<MCValue, uint64_t, bool> +MCAssembler::handleFixup(const MCAsmLayout &Layout, MCFragment &F, + const MCFixup &Fixup) { // Evaluate the fixup. MCValue Target; uint64_t FixedValue; - bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags & - MCFixupKindInfo::FKF_IsPCRel; - if (!evaluateFixup(Layout, Fixup, &F, Target, FixedValue)) { + bool IsResolved = evaluateFixup(Layout, Fixup, &F, Target, FixedValue); + 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. - getWriter().recordRelocation(*this, Layout, &F, Fixup, Target, IsPCRel, - FixedValue); + getWriter().recordRelocation(*this, Layout, &F, Fixup, Target, FixedValue); } - return std::make_pair(FixedValue, IsPCRel); + return std::make_tuple(Target, FixedValue, IsResolved); } void MCAssembler::layout(MCAsmLayout &Layout) { DEBUG_WITH_TYPE("mc-dump", { - llvm::errs() << "assembler backend - pre-layout\n--\n"; + errs() << "assembler backend - pre-layout\n--\n"; dump(); }); // Create dummy fragments and assign section ordinals. @@ -671,14 +695,14 @@ void MCAssembler::layout(MCAsmLayout &Layout) { return; DEBUG_WITH_TYPE("mc-dump", { - llvm::errs() << "assembler backend - post-relaxation\n--\n"; + errs() << "assembler backend - post-relaxation\n--\n"; dump(); }); // Finalize the layout, including fragment lowering. finishLayout(Layout); DEBUG_WITH_TYPE("mc-dump", { - llvm::errs() << "assembler backend - final-layout\n--\n"; + errs() << "assembler backend - final-layout\n--\n"; dump(); }); // Allow the object writer a chance to perform post-layout binding (for @@ -712,10 +736,12 @@ void MCAssembler::layout(MCAsmLayout &Layout) { llvm_unreachable("Unknown fragment with fixups!"); for (const MCFixup &Fixup : Fixups) { uint64_t FixedValue; - bool IsPCRel; - std::tie(FixedValue, IsPCRel) = handleFixup(Layout, Frag, Fixup); - getBackend().applyFixup(Fixup, Contents.data(), - Contents.size(), FixedValue, IsPCRel); + bool IsResolved; + MCValue Target; + std::tie(Target, FixedValue, IsResolved) = + handleFixup(Layout, Frag, Fixup); + getBackend().applyFixup(*this, Fixup, Target, Contents, FixedValue, + IsResolved); } } } @@ -741,6 +767,10 @@ bool MCAssembler::fixupNeedsRelaxation(const MCFixup &Fixup, MCValue Target; uint64_t Value; bool Resolved = evaluateFixup(Layout, Fixup, DF, Target, Value); + if (Target.getSymA() && + Target.getSymA()->getKind() == MCSymbolRefExpr::VK_X86_ABS8 && + Fixup.getKind() == FK_Data_1) + return false; return getBackend().fixupNeedsRelaxationAdvanced(Fixup, Resolved, Value, DF, Layout); } diff --git a/contrib/llvm/lib/MC/MCCodeEmitter.cpp b/contrib/llvm/lib/MC/MCCodeEmitter.cpp index c122763..ca69478 100644 --- a/contrib/llvm/lib/MC/MCCodeEmitter.cpp +++ b/contrib/llvm/lib/MC/MCCodeEmitter.cpp @@ -1,4 +1,4 @@ -//===-- MCCodeEmitter.cpp - Instruction Encoding --------------------------===// +//===- MCCodeEmitter.cpp - Instruction Encoding ---------------------------===// // // The LLVM Compiler Infrastructure // @@ -11,8 +11,6 @@ using namespace llvm; -MCCodeEmitter::MCCodeEmitter() { -} +MCCodeEmitter::MCCodeEmitter() = default; -MCCodeEmitter::~MCCodeEmitter() { -} +MCCodeEmitter::~MCCodeEmitter() = default; diff --git a/contrib/llvm/lib/MC/MCCodeView.cpp b/contrib/llvm/lib/MC/MCCodeView.cpp index 99a5c11..92b1e12 100644 --- a/contrib/llvm/lib/MC/MCCodeView.cpp +++ b/contrib/llvm/lib/MC/MCCodeView.cpp @@ -12,15 +12,15 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCCodeView.h" -#include "llvm/MC/MCAsmLayout.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/BinaryFormat/COFF.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/Line.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCValue.h" -#include "llvm/Support/COFF.h" #include "llvm/Support/EndianStream.h" using namespace llvm; @@ -145,7 +145,7 @@ void CodeViewContext::emitStringTable(MCObjectStreamer &OS) { MCSymbol *StringBegin = Ctx.createTempSymbol("strtab_begin", false), *StringEnd = Ctx.createTempSymbol("strtab_end", false); - OS.EmitIntValue(unsigned(ModuleSubstreamKind::StringTable), 4); + OS.EmitIntValue(unsigned(DebugSubsectionKind::StringTable), 4); OS.emitAbsoluteSymbolDiff(StringEnd, StringBegin, 4); OS.EmitLabel(StringBegin); @@ -172,7 +172,7 @@ void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) { MCSymbol *FileBegin = Ctx.createTempSymbol("filechecksums_begin", false), *FileEnd = Ctx.createTempSymbol("filechecksums_end", false); - OS.EmitIntValue(unsigned(ModuleSubstreamKind::FileChecksums), 4); + OS.EmitIntValue(unsigned(DebugSubsectionKind::FileChecksums), 4); OS.emitAbsoluteSymbolDiff(FileEnd, FileBegin, 4); OS.EmitLabel(FileBegin); @@ -197,7 +197,7 @@ void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS, MCSymbol *LineBegin = Ctx.createTempSymbol("linetable_begin", false), *LineEnd = Ctx.createTempSymbol("linetable_end", false); - OS.EmitIntValue(unsigned(ModuleSubstreamKind::Lines), 4); + OS.EmitIntValue(unsigned(DebugSubsectionKind::Lines), 4); OS.emitAbsoluteSymbolDiff(LineEnd, LineBegin, 4); OS.EmitLabel(LineBegin); OS.EmitCOFFSecRel32(FuncBegin, /*Offset=*/0); @@ -208,7 +208,7 @@ void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS, bool HaveColumns = any_of(Locs, [](const MCCVLineEntry &LineEntry) { return LineEntry.getColumn() != 0; }); - OS.EmitIntValue(HaveColumns ? int(LineFlags::HaveColumns) : 0, 2); + OS.EmitIntValue(HaveColumns ? int(LF_HaveColumns) : 0, 2); OS.emitAbsoluteSymbolDiff(FuncEnd, FuncBegin, 4); for (auto I = Locs.begin(), E = Locs.end(); I != E;) { diff --git a/contrib/llvm/lib/MC/MCContext.cpp b/contrib/llvm/lib/MC/MCContext.cpp index 9d2fac2..48ee84e 100644 --- a/contrib/llvm/lib/MC/MCContext.cpp +++ b/contrib/llvm/lib/MC/MCContext.cpp @@ -9,28 +9,41 @@ #include "llvm/MC/MCContext.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/BinaryFormat/COFF.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCAssembler.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/MCRegisterInfo.h" #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSectionWasm.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbolCOFF.h" #include "llvm/MC/MCSymbolELF.h" #include "llvm/MC/MCSymbolMachO.h" -#include "llvm/Support/COFF.h" +#include "llvm/MC/MCSymbolWasm.h" +#include "llvm/MC/SectionKind.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Signals.h" #include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstdlib> +#include <tuple> +#include <utility> using namespace llvm; @@ -40,19 +53,14 @@ AsSecureLogFileName("as-secure-log-file-name", "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), MAI(mai), MRI(mri), MOFI(mofi), Allocator(), + : SrcMgr(mgr), InlineSrcMgr(nullptr), MAI(mai), MRI(mri), MOFI(mofi), Symbols(Allocator), UsedNames(Allocator), - CurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0), DwarfLocSeen(false), - GenDwarfForAssembly(false), GenDwarfFileNumber(0), DwarfVersion(4), - AllowTemporaryLabels(true), DwarfCompileUnitID(0), - AutoReset(DoAutoReset), HadError(false) { + CurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0), + AutoReset(DoAutoReset) { SecureLogFile = AsSecureLogFileName; - SecureLog = nullptr; - SecureLogUsed = false; if (SrcMgr && SrcMgr->getNumBuffers()) MainFileName = @@ -80,7 +88,6 @@ void MCContext::reset() { MCSubtargetAllocator.DestroyAll(); UsedNames.clear(); Symbols.clear(); - SectionSymbols.clear(); Allocator.Reset(); Instances.clear(); CompilationDir.clear(); @@ -124,18 +131,6 @@ MCSymbol *MCContext::getOrCreateSymbol(const Twine &Name) { return Sym; } -MCSymbolELF *MCContext::getOrCreateSectionSymbol(const MCSectionELF &Section) { - MCSymbol *&Sym = SectionSymbols[&Section]; - if (Sym) - return cast<MCSymbolELF>(Sym); - - StringRef Name = Section.getSectionName(); - auto NameIter = UsedNames.insert(std::make_pair(Name, false)).first; - Sym = new (&*NameIter, *this) MCSymbolELF(&*NameIter, /*isTemporary*/ false); - - return cast<MCSymbolELF>(Sym); -} - MCSymbol *MCContext::getOrCreateFrameAllocSymbol(StringRef FuncName, unsigned Idx) { return getOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + FuncName + @@ -162,6 +157,8 @@ MCSymbol *MCContext::createSymbolImpl(const StringMapEntry<bool> *Name, return new (Name, *this) MCSymbolELF(Name, IsTemporary); case MCObjectFileInfo::IsMachO: return new (Name, *this) MCSymbolMachO(Name, IsTemporary); + case MCObjectFileInfo::IsWasm: + return new (Name, *this) MCSymbolWasm(Name, IsTemporary); } } return new (Name, *this) MCSymbol(MCSymbol::SymbolKindUnset, Name, @@ -182,7 +179,7 @@ MCSymbol *MCContext::createSymbol(StringRef Name, bool AlwaysAddSuffix, SmallString<128> NewName = Name; bool AddSuffix = AlwaysAddSuffix; unsigned &NextUniqueID = NextID[Name]; - for (;;) { + while (true) { if (AddSuffix) { NewName.resize(Name.size()); raw_svector_ostream(NewName) << NextUniqueID++; @@ -275,7 +272,6 @@ 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. @@ -316,18 +312,53 @@ void MCContext::renameELFSection(MCSectionELF *Section, StringRef Name) { 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 *Associated) { + const MCSectionELF *RelInfoSection) { StringMap<bool>::iterator I; bool Inserted; std::tie(I, Inserted) = - ELFRelSecNames.insert(std::make_pair(Name.str(), true)); + RelSecNames.insert(std::make_pair(Name.str(), true)); - return new (ELFAllocator.Allocate()) - MCSectionELF(I->getKey(), Type, Flags, SectionKind::getReadOnly(), - EntrySize, Group, true, nullptr, Associated); + return createELFSectionImpl( + I->getKey(), Type, Flags, SectionKind::getReadOnly(), EntrySize, Group, + true, cast<MCSymbolELF>(RelInfoSection->getBeginSymbol())); } MCSectionELF *MCContext::getELFNamedSection(const Twine &Prefix, @@ -340,21 +371,20 @@ MCSectionELF *MCContext::getELFNamedSection(const Twine &Prefix, MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type, unsigned Flags, unsigned EntrySize, const Twine &Group, unsigned UniqueID, - const char *BeginSymName) { + 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, - BeginSymName, nullptr); + Associated); } MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type, unsigned Flags, unsigned EntrySize, const MCSymbolELF *GroupSym, unsigned UniqueID, - const char *BeginSymName, - const MCSectionELF *Associated) { + const MCSymbolELF *Associated) { StringRef Group = ""; if (GroupSym) Group = GroupSym->getName(); @@ -375,22 +405,16 @@ MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type, else Kind = SectionKind::getReadOnly(); - MCSymbol *Begin = nullptr; - if (BeginSymName) - Begin = createTempSymbol(BeginSymName, false); - - MCSectionELF *Result = new (ELFAllocator.Allocate()) - MCSectionELF(CachedName, Type, Flags, Kind, EntrySize, GroupSym, UniqueID, - Begin, Associated); + MCSectionELF *Result = createELFSectionImpl( + CachedName, Type, Flags, Kind, EntrySize, GroupSym, UniqueID, Associated); Entry.second = Result; return Result; } MCSectionELF *MCContext::createELFGroupSection(const MCSymbolELF *Group) { - MCSectionELF *Result = new (ELFAllocator.Allocate()) - MCSectionELF(".group", ELF::SHT_GROUP, 0, SectionKind::getReadOnly(), 4, - Group, ~0, nullptr, nullptr); - return Result; + return createELFSectionImpl(".group", ELF::SHT_GROUP, 0, + SectionKind::getReadOnly(), 4, Group, ~0, + nullptr); } MCSectionCOFF *MCContext::getCOFFSection(StringRef Section, @@ -462,6 +486,80 @@ MCSectionCOFF *MCContext::getAssociativeCOFFSection(MCSectionCOFF *Sec, "", 0, UniqueID); } +void MCContext::renameWasmSection(MCSectionWasm *Section, StringRef Name) { + StringRef GroupName; + assert(!Section->getGroup() && "not yet implemented"); + + unsigned UniqueID = Section->getUniqueID(); + WasmUniquingMap.erase( + WasmSectionKey{Section->getSectionName(), GroupName, UniqueID}); + auto I = WasmUniquingMap.insert(std::make_pair( + WasmSectionKey{Name, GroupName, UniqueID}, + Section)) + .first; + StringRef CachedName = I->first.SectionName; + const_cast<MCSectionWasm *>(Section)->setSectionName(CachedName); +} + +MCSectionWasm *MCContext::createWasmRelSection(const Twine &Name, unsigned Type, + unsigned Flags, + const MCSymbolWasm *Group) { + StringMap<bool>::iterator I; + bool Inserted; + std::tie(I, Inserted) = + RelSecNames.insert(std::make_pair(Name.str(), true)); + + return new (WasmAllocator.Allocate()) + MCSectionWasm(I->getKey(), Type, Flags, SectionKind::getReadOnly(), + Group, ~0, nullptr); +} + +MCSectionWasm *MCContext::getWasmNamedSection(const Twine &Prefix, + const Twine &Suffix, unsigned Type, + unsigned Flags) { + return getWasmSection(Prefix + "." + Suffix, Type, Flags, Suffix); +} + +MCSectionWasm *MCContext::getWasmSection(const Twine &Section, unsigned Type, + unsigned Flags, + const Twine &Group, unsigned UniqueID, + const char *BeginSymName) { + MCSymbolWasm *GroupSym = nullptr; + if (!Group.isTriviallyEmpty() && !Group.str().empty()) + GroupSym = cast<MCSymbolWasm>(getOrCreateSymbol(Group)); + + return getWasmSection(Section, Type, Flags, GroupSym, UniqueID, BeginSymName); +} + +MCSectionWasm *MCContext::getWasmSection(const Twine &Section, unsigned Type, + unsigned Flags, + const MCSymbolWasm *GroupSym, + unsigned UniqueID, + const char *BeginSymName) { + StringRef Group = ""; + if (GroupSym) + Group = GroupSym->getName(); + // Do the lookup, if we have a hit, return it. + auto IterBool = WasmUniquingMap.insert( + std::make_pair(WasmSectionKey{Section.str(), Group, UniqueID}, nullptr)); + auto &Entry = *IterBool.first; + if (!IterBool.second) + return Entry.second; + + StringRef CachedName = Entry.first.SectionName; + + SectionKind Kind = SectionKind::getText(); + + MCSymbol *Begin = nullptr; + if (BeginSymName) + Begin = createTempSymbol(BeginSymName, false); + + MCSectionWasm *Result = new (WasmAllocator.Allocate()) + MCSectionWasm(CachedName, Type, Flags, Kind, GroupSym, UniqueID, Begin); + Entry.second = Result; + return Result; +} + MCSubtargetInfo &MCContext::getSubtargetCopy(const MCSubtargetInfo &STI) { return *new (MCSubtargetAllocator.Allocate()) MCSubtargetInfo(STI); } diff --git a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp index aa50727..ef1d833 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp +++ b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp @@ -27,8 +27,8 @@ #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" #include <cassert> #include <cstddef> #include <cstring> diff --git a/contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp b/contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp index 3a4f738..2f1275d 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp +++ b/contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp @@ -1,4 +1,4 @@ -//===-- MCDisassembler.cpp - Disassembler interface -----------------------===// +//===- MCDisassembler.cpp - Disassembler interface ------------------------===// // // The LLVM Compiler Infrastructure // @@ -8,13 +8,12 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCDisassembler/MCDisassembler.h" -#include "llvm/MC/MCDisassembler/MCExternalSymbolizer.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> using namespace llvm; -MCDisassembler::~MCDisassembler() { -} +MCDisassembler::~MCDisassembler() = default; bool MCDisassembler::tryAddingSymbolicOperand(MCInst &Inst, int64_t Value, uint64_t Address, bool IsBranch, diff --git a/contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp b/contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp index 1612562..8f932a3 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp +++ b/contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp @@ -1,4 +1,4 @@ -//==-- MCRelocationInfo.cpp ------------------------------------------------==// +//===-- MCRelocationInfo.cpp ----------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -13,12 +13,9 @@ using namespace llvm; -MCRelocationInfo::MCRelocationInfo(MCContext &Ctx) - : Ctx(Ctx) { -} +MCRelocationInfo::MCRelocationInfo(MCContext &Ctx) : Ctx(Ctx) {} -MCRelocationInfo::~MCRelocationInfo() { -} +MCRelocationInfo::~MCRelocationInfo() = default; const MCExpr * MCRelocationInfo::createExprForCAPIVariantKind(const MCExpr *SubExpr, diff --git a/contrib/llvm/lib/MC/MCDisassembler/MCSymbolizer.cpp b/contrib/llvm/lib/MC/MCDisassembler/MCSymbolizer.cpp index c0f707d..78e611e 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/MCSymbolizer.cpp +++ b/contrib/llvm/lib/MC/MCDisassembler/MCSymbolizer.cpp @@ -1,4 +1,4 @@ -//===-- llvm/MC/MCSymbolizer.cpp - MCSymbolizer class -----------*- C++ -*-===// +//===-- llvm/MC/MCSymbolizer.cpp - MCSymbolizer class ---------------------===// // // The LLVM Compiler Infrastructure // @@ -11,5 +11,4 @@ using namespace llvm; -MCSymbolizer::~MCSymbolizer() { -} +MCSymbolizer::~MCSymbolizer() = default; diff --git a/contrib/llvm/lib/MC/MCDwarf.cpp b/contrib/llvm/lib/MC/MCDwarf.cpp index a7551a3..a2beee3 100644 --- a/contrib/llvm/lib/MC/MCDwarf.cpp +++ b/contrib/llvm/lib/MC/MCDwarf.cpp @@ -8,10 +8,16 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCDwarf.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/BinaryFormat/Dwarf.h" #include "llvm/Config/config.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" @@ -20,14 +26,22 @@ #include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Support/Debug.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; @@ -154,7 +168,7 @@ EmitDwarfLineTable(MCObjectStreamer *MCOS, MCSection *Section, // and the current Label. const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo(); MCOS->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, - asmInfo->getPointerSize()); + asmInfo->getCodePointerSize()); Discriminator = 0; LastLine = LineEntry.getLine(); @@ -174,7 +188,7 @@ EmitDwarfLineTable(MCObjectStreamer *MCOS, MCSection *Section, const MCAsmInfo *AsmInfo = Ctx.getAsmInfo(); MCOS->EmitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd, - AsmInfo->getPointerSize()); + AsmInfo->getCodePointerSize()); } // @@ -580,7 +594,7 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS, // 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->getPointerSize(); + int AddrSize = asmInfo->getCodePointerSize(); int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1)); if (Pad == 2 * AddrSize) Pad = 0; @@ -592,7 +606,6 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS, // 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); @@ -661,7 +674,14 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS, // 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) @@ -669,11 +689,8 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS, else MCOS->EmitSymbolValue(AbbrevSectionSymbol, 4, AsmInfo.needsDwarfSectionOffsetDirective()); - - const MCAsmInfo *asmInfo = context.getAsmInfo(); - int AddrSize = asmInfo->getPointerSize(); - // The 1 byte size of an address. - MCOS->EmitIntValue(AddrSize, 1); + if (context.getDwarfVersion() <= 4) + MCOS->EmitIntValue(AddrSize, 1); // Second part: the compile_unit DIE. @@ -806,7 +823,7 @@ static void EmitGenDwarfRanges(MCStreamer *MCOS) { auto &Sections = context.getGenDwarfSectionSyms(); const MCAsmInfo *AsmInfo = context.getAsmInfo(); - int AddrSize = AsmInfo->getPointerSize(); + int AddrSize = AsmInfo->getCodePointerSize(); MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection()); @@ -885,7 +902,7 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) { } } - assert((RangesSectionSymbol != NULL) || !UseRangesSection); + assert((RangesSectionSymbol != nullptr) || !UseRangesSection); MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); @@ -964,7 +981,7 @@ static unsigned getSizeForEncoding(MCStreamer &streamer, default: llvm_unreachable("Unknown Encoding"); case dwarf::DW_EH_PE_absptr: case dwarf::DW_EH_PE_signed: - return context.getAsmInfo()->getPointerSize(); + return context.getAsmInfo()->getCodePointerSize(); case dwarf::DW_EH_PE_udata2: case dwarf::DW_EH_PE_sdata2: return 2; @@ -1003,6 +1020,7 @@ static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol, } namespace { + class FrameEmitterImpl { int CFAOffset = 0; int InitialCFAOffset = 0; @@ -1050,10 +1068,10 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) { Streamer.EmitULEB128IntValue(Reg2); return; } - case MCCFIInstruction::OpWindowSave: { + case MCCFIInstruction::OpWindowSave: Streamer.EmitIntValue(dwarf::DW_CFA_GNU_window_save, 1); return; - } + case MCCFIInstruction::OpUndefined: { unsigned Reg = Instr.getRegister(); Streamer.EmitIntValue(dwarf::DW_CFA_undefined, 1); @@ -1087,7 +1105,6 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) { return; } - case MCCFIInstruction::OpDefCfaRegister: { unsigned Reg = Instr.getRegister(); if (!IsEH) @@ -1097,7 +1114,6 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) { return; } - case MCCFIInstruction::OpOffset: case MCCFIInstruction::OpRelOffset: { const bool IsRelative = @@ -1145,11 +1161,11 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) { Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1); return; } - case MCCFIInstruction::OpGnuArgsSize: { + 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; @@ -1302,7 +1318,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCSymbol *personality, if (CIEVersion >= 4) { // Address Size - Streamer.EmitIntValue(context.getAsmInfo()->getPointerSize(), 1); + Streamer.EmitIntValue(context.getAsmInfo()->getCodePointerSize(), 1); // Segment Descriptor Size Streamer.EmitIntValue(0, 1); @@ -1368,7 +1384,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCSymbol *personality, InitialCFAOffset = CFAOffset; // Padding - Streamer.EmitValueToAlignment(IsEH ? 4 : MAI->getPointerSize()); + Streamer.EmitValueToAlignment(IsEH ? 4 : MAI->getCodePointerSize()); Streamer.EmitLabel(sectionEnd); return *sectionStart; @@ -1437,17 +1453,19 @@ void FrameEmitterImpl::EmitFDE(const MCSymbol &cieStart, // 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->getPointerSize() : PCSize; + unsigned Align = LastInSection ? asmInfo->getCodePointerSize() : PCSize; Streamer.EmitValueToAlignment(Align); Streamer.EmitLabel(fdeEnd); } namespace { + struct CIEKey { static const CIEKey getEmptyKey() { return CIEKey(nullptr, 0, -1, false, false); } + static const CIEKey getTombstoneKey() { return CIEKey(nullptr, -1, 0, false, false); } @@ -1457,23 +1475,28 @@ struct CIEKey { : Personality(Personality), PersonalityEncoding(PersonalityEncoding), LsdaEncoding(LsdaEncoding), IsSignalFrame(IsSignalFrame), IsSimple(IsSimple) {} + const MCSymbol *Personality; unsigned PersonalityEncoding; unsigned LsdaEncoding; bool IsSignalFrame; bool IsSimple; }; -} // anonymous namespace + +} // end anonymous namespace namespace llvm { + template <> struct DenseMapInfo<CIEKey> { static CIEKey getEmptyKey() { return CIEKey::getEmptyKey(); } static CIEKey getTombstoneKey() { return CIEKey::getTombstoneKey(); } + static unsigned getHashValue(const CIEKey &Key) { return static_cast<unsigned>( hash_combine(Key.Personality, Key.PersonalityEncoding, Key.LsdaEncoding, Key.IsSignalFrame, Key.IsSimple)); } + static bool isEqual(const CIEKey &LHS, const CIEKey &RHS) { return LHS.Personality == RHS.Personality && LHS.PersonalityEncoding == RHS.PersonalityEncoding && @@ -1482,7 +1505,8 @@ template <> struct DenseMapInfo<CIEKey> { LHS.IsSimple == RHS.IsSimple; } }; -} // namespace llvm + +} // end namespace llvm void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB, bool IsEH) { @@ -1490,6 +1514,7 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB, MCContext &Context = Streamer.getContext(); const MCObjectFileInfo *MOFI = Context.getObjectFileInfo(); + const MCAsmInfo *AsmInfo = Context.getAsmInfo(); FrameEmitterImpl Emitter(IsEH, Streamer); ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getDwarfFrameInfos(); @@ -1501,7 +1526,7 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB, if (Frame.CompactUnwindEncoding == 0) continue; if (!SectionEmitted) { Streamer.SwitchSection(MOFI->getCompactUnwindSection()); - Streamer.EmitValueToAlignment(Context.getAsmInfo()->getPointerSize()); + Streamer.EmitValueToAlignment(AsmInfo->getCodePointerSize()); SectionEmitted = true; } NeedsEHFrameSection |= diff --git a/contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp b/contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp index de645ca..68fb5e7 100644 --- a/contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp +++ b/contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp @@ -7,10 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCELFObjectWriter.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCValue.h" using namespace llvm; diff --git a/contrib/llvm/lib/MC/MCELFStreamer.cpp b/contrib/llvm/lib/MC/MCELFStreamer.cpp index 0ef1b2a..50c1f6e 100644 --- a/contrib/llvm/lib/MC/MCELFStreamer.cpp +++ b/contrib/llvm/lib/MC/MCELFStreamer.cpp @@ -12,29 +12,30 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCELFStreamer.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCAsmLayout.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/MCInst.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/MCSectionELF.h" -#include "llvm/MC/MCSymbolELF.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCValue.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ELF.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; @@ -42,9 +43,6 @@ bool MCELFStreamer::isBundleLocked() const { return getCurrentSectionOnly()->isBundleLocked(); } -MCELFStreamer::~MCELFStreamer() { -} - void MCELFStreamer::mergeFragment(MCDataFragment *DF, MCDataFragment *EF) { MCAssembler &Assembler = getAssembler(); @@ -95,11 +93,19 @@ void MCELFStreamer::InitSections(bool NoExecStack) { SwitchSection(Ctx.getAsmInfo()->getNonexecutableStackSection(Ctx)); } -void MCELFStreamer::EmitLabel(MCSymbol *S) { +void MCELFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) { auto *Symbol = cast<MCSymbolELF>(S); - assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); + MCObjectStreamer::EmitLabel(Symbol, Loc); + + const MCSectionELF &Section = + static_cast<const MCSectionELF &>(*getCurrentSectionOnly()); + if (Section.getFlags() & ELF::SHF_TLS) + Symbol->setType(ELF::STT_TLS); +} - MCObjectStreamer::EmitLabel(Symbol); +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()); @@ -147,17 +153,8 @@ void MCELFStreamer::ChangeSection(MCSection *Section, if (Grp) Asm.registerSymbol(*Grp); - this->MCObjectStreamer::ChangeSection(Section, Subsection); - MCContext &Ctx = getContext(); - auto *Begin = cast_or_null<MCSymbolELF>(Section->getBeginSymbol()); - if (!Begin) { - Begin = Ctx.getOrCreateSectionSymbol(*SectionELF); - Section->setBeginSymbol(Begin); - } - if (Begin->isUndefined()) { - Asm.registerSymbol(*Begin); - Begin->setType(ELF::STT_SECTION); - } + changeSectionImpl(Section, Subsection); + Asm.registerSymbol(*Section->getBeginSymbol()); } void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { @@ -361,13 +358,6 @@ void MCELFStreamer::EmitValueToAlignment(unsigned ByteAlignment, ValueSize, MaxBytesToEmit); } -// Add a symbol for the file name of this module. They start after the -// null symbol and don't count as normal symbol, i.e. a non-STT_FILE symbol -// with the same name may appear. -void MCELFStreamer::EmitFileDirective(StringRef Filename) { - getAssembler().addFileName(Filename); -} - void MCELFStreamer::EmitIdent(StringRef IdentString) { MCSection *Comment = getAssembler().getContext().getELFSection( ".comment", ELF::SHT_PROGBITS, ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, ""); @@ -630,15 +620,6 @@ void MCELFStreamer::FinishImpl() { this->MCObjectStreamer::FinishImpl(); } -MCStreamer *llvm::createELFStreamer(MCContext &Context, MCAsmBackend &MAB, - raw_pwrite_stream &OS, MCCodeEmitter *CE, - bool RelaxAll) { - MCELFStreamer *S = new MCELFStreamer(Context, MAB, OS, CE); - if (RelaxAll) - S->getAssembler().setRelaxAll(true); - return S; -} - void MCELFStreamer::EmitThumbFunc(MCSymbol *Func) { llvm_unreachable("Generic ELF doesn't support this directive"); } @@ -647,22 +628,6 @@ void MCELFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { llvm_unreachable("ELF doesn't support this directive"); } -void MCELFStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) { - llvm_unreachable("ELF doesn't support this directive"); -} - -void MCELFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { - llvm_unreachable("ELF doesn't support this directive"); -} - -void MCELFStreamer::EmitCOFFSymbolType(int Type) { - llvm_unreachable("ELF doesn't support this directive"); -} - -void MCELFStreamer::EndCOFFSymbolDef() { - llvm_unreachable("ELF doesn't support this directive"); -} - void MCELFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { llvm_unreachable("ELF doesn't support this directive"); @@ -672,3 +637,12 @@ void MCELFStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { llvm_unreachable("ELF doesn't support this directive"); } + +MCStreamer *llvm::createELFStreamer(MCContext &Context, MCAsmBackend &MAB, + raw_pwrite_stream &OS, MCCodeEmitter *CE, + bool RelaxAll) { + MCELFStreamer *S = new MCELFStreamer(Context, MAB, OS, CE); + if (RelaxAll) + S->getAssembler().setRelaxAll(true); + return S; +} diff --git a/contrib/llvm/lib/MC/MCExpr.cpp b/contrib/llvm/lib/MC/MCExpr.cpp index bcc43a5..38a8af4 100644 --- a/contrib/llvm/lib/MC/MCExpr.cpp +++ b/contrib/llvm/lib/MC/MCExpr.cpp @@ -17,18 +17,25 @@ #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()) { @@ -44,7 +51,7 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const { // Parenthesize names that start with $ so that they don't look like // absolute names. bool UseParens = - !InParens && Sym.getName().size() && Sym.getName()[0] == '$'; + !InParens && !Sym.getName().empty() && Sym.getName()[0] == '$'; if (UseParens) { OS << '('; Sym.print(OS, MAI); @@ -129,21 +136,24 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const { 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) { - return new (Ctx) MCBinaryExpr(Opc, LHS, RHS); + 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) { - return new (Ctx) MCUnaryExpr(Opc, Expr); + MCContext &Ctx, SMLoc Loc) { + return new (Ctx) MCUnaryExpr(Opc, Expr, Loc); } const MCConstantExpr *MCConstantExpr::create(int64_t Value, MCContext &Ctx) { @@ -153,8 +163,8 @@ const MCConstantExpr *MCConstantExpr::create(int64_t Value, MCContext &Ctx) { /* *** */ MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, - const MCAsmInfo *MAI) - : MCExpr(MCExpr::SymbolRef), Kind(Kind), + const MCAsmInfo *MAI, SMLoc Loc) + : MCExpr(MCExpr::SymbolRef, Loc), Kind(Kind), UseParensForSymbolVariant(MAI->useParensForSymbolVariant()), HasSubsectionsViaSymbols(MAI->hasSubsectionsViaSymbols()), Symbol(Symbol) { @@ -163,8 +173,8 @@ MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, const MCSymbolRefExpr *MCSymbolRefExpr::create(const MCSymbol *Sym, VariantKind Kind, - MCContext &Ctx) { - return new (Ctx) MCSymbolRefExpr(Sym, Kind, Ctx.getAsmInfo()); + MCContext &Ctx, SMLoc Loc) { + return new (Ctx) MCSymbolRefExpr(Sym, Kind, Ctx.getAsmInfo(), Loc); } const MCSymbolRefExpr *MCSymbolRefExpr::create(StringRef Name, VariantKind Kind, @@ -205,6 +215,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { 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"; @@ -275,6 +286,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_Hexagon_IE: return "IE"; case VK_Hexagon_IE_GOT: return "IEGOT"; case VK_WebAssembly_FUNCTION: return "FUNCTION"; + case VK_WebAssembly_TYPEINDEX: return "TYPEINDEX"; case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo"; case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi"; case VK_AMDGPU_REL32_LO: return "rel32@lo"; @@ -314,6 +326,7 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) { .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) @@ -642,8 +655,12 @@ bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, // 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; } } diff --git a/contrib/llvm/lib/MC/MCFragment.cpp b/contrib/llvm/lib/MC/MCFragment.cpp index 8ff8f8a..6e02493 100644 --- a/contrib/llvm/lib/MC/MCFragment.cpp +++ b/contrib/llvm/lib/MC/MCFragment.cpp @@ -8,29 +8,28 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCFragment.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" -#include "llvm/MC/MCAssembler.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/MCDwarf.h" #include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/MC/MCFixup.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/Compiler.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/LEB128.h" -#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstdint> +#include <utility> + using namespace llvm; -MCAsmLayout::MCAsmLayout(MCAssembler &Asm) - : Assembler(Asm), LastValidFragment() - { +MCAsmLayout::MCAsmLayout(MCAssembler &Asm) : Assembler(Asm) { // Compute the section layout order. Virtual sections must go last. for (MCSection &Sec : Asm) if (!Sec.isVirtualSection()) @@ -145,14 +144,14 @@ const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const { MCValue Value; if (!Expr->evaluateAsValue(Value, *this)) { Assembler.getContext().reportError( - SMLoc(), "expression could not be evaluated"); + Expr->getLoc(), "expression could not be evaluated"); return nullptr; } const MCSymbolRefExpr *RefB = Value.getSymB(); if (RefB) { Assembler.getContext().reportError( - SMLoc(), Twine("symbol '") + RefB->getSymbol().getName() + + Expr->getLoc(), Twine("symbol '") + RefB->getSymbol().getName() + "' could not be evaluated in a subtraction expression"); return nullptr; } @@ -164,8 +163,7 @@ const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const { const MCSymbol &ASym = A->getSymbol(); const MCAssembler &Asm = getAssembler(); if (ASym.isCommon()) { - // FIXME: we should probably add a SMLoc to MCExpr. - Asm.getContext().reportError(SMLoc(), + Asm.getContext().reportError(Expr->getLoc(), "Common symbol '" + ASym.getName() + "' cannot be used in assignment expr"); return nullptr; @@ -234,7 +232,7 @@ uint64_t llvm::computeBundlePadding(const MCAssembler &Assembler, void ilist_alloc_traits<MCFragment>::deleteNode(MCFragment *V) { V->destroy(); } -MCFragment::~MCFragment() { } +MCFragment::~MCFragment() = default; MCFragment::MCFragment(FragmentType Kind, bool HasInstructions, uint8_t BundlePadding, MCSection *Parent) @@ -295,8 +293,6 @@ void MCFragment::destroy() { } } -/* *** */ - // Debugging methods namespace llvm { @@ -308,10 +304,11 @@ raw_ostream &operator<<(raw_ostream &OS, const MCFixup &AF) { return OS; } -} +} // end namespace llvm -LLVM_DUMP_METHOD void MCFragment::dump() { - raw_ostream &OS = llvm::errs(); +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +LLVM_DUMP_METHOD void MCFragment::dump() const { + raw_ostream &OS = errs(); OS << "<"; switch (getKind()) { @@ -331,9 +328,9 @@ LLVM_DUMP_METHOD void MCFragment::dump() { case MCFragment::FT_Dummy: OS << "MCDummyFragment"; break; } - OS << "<MCFragment " << (void*) this << " LayoutOrder:" << LayoutOrder + OS << "<MCFragment " << (const void*) this << " LayoutOrder:" << LayoutOrder << " Offset:" << Offset - << " HasInstructions:" << hasInstructions() + << " HasInstructions:" << hasInstructions() << " BundlePadding:" << static_cast<unsigned>(getBundlePadding()) << ">"; switch (getKind()) { @@ -385,7 +382,8 @@ LLVM_DUMP_METHOD void MCFragment::dump() { } case MCFragment::FT_Fill: { const MCFillFragment *FF = cast<MCFillFragment>(this); - OS << " Value:" << FF->getValue() << " Size:" << FF->getSize(); + OS << " Value:" << static_cast<unsigned>(FF->getValue()) + << " Size:" << FF->getSize(); break; } case MCFragment::FT_Relaxable: { @@ -398,7 +396,8 @@ LLVM_DUMP_METHOD void MCFragment::dump() { case MCFragment::FT_Org: { const MCOrgFragment *OF = cast<MCOrgFragment>(this); OS << "\n "; - OS << " Offset:" << OF->getOffset() << " Value:" << OF->getValue(); + OS << " Offset:" << OF->getOffset() + << " Value:" << static_cast<unsigned>(OF->getValue()); break; } case MCFragment::FT_Dwarf: { @@ -448,19 +447,19 @@ LLVM_DUMP_METHOD void MCFragment::dump() { OS << ">"; } -LLVM_DUMP_METHOD void MCAssembler::dump() { - raw_ostream &OS = llvm::errs(); +LLVM_DUMP_METHOD void MCAssembler::dump() const{ + raw_ostream &OS = errs(); OS << "<MCAssembler\n"; OS << " Sections:[\n "; - for (iterator it = begin(), ie = end(); it != ie; ++it) { + for (const_iterator it = begin(), ie = end(); it != ie; ++it) { if (it != begin()) OS << ",\n "; it->dump(); } OS << "],\n"; OS << " Symbols:["; - for (symbol_iterator it = symbol_begin(), ie = symbol_end(); it != ie; ++it) { + for (const_symbol_iterator it = symbol_begin(), ie = symbol_end(); it != ie; ++it) { if (it != symbol_begin()) OS << ",\n "; OS << "("; it->dump(); @@ -469,3 +468,4 @@ LLVM_DUMP_METHOD void MCAssembler::dump() { } OS << "]>\n"; } +#endif diff --git a/contrib/llvm/lib/MC/MCInst.cpp b/contrib/llvm/lib/MC/MCInst.cpp index 2da8ecc..f6d1d3c 100644 --- a/contrib/llvm/lib/MC/MCInst.cpp +++ b/contrib/llvm/lib/MC/MCInst.cpp @@ -10,6 +10,7 @@ #include "llvm/MC/MCInst.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInstPrinter.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -34,10 +35,12 @@ void MCOperand::print(raw_ostream &OS) const { OS << ">"; } +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void MCOperand::dump() const { print(dbgs()); dbgs() << "\n"; } +#endif void MCInst::print(raw_ostream &OS) const { OS << "<MCInst " << getOpcode(); @@ -63,7 +66,9 @@ void MCInst::dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer, 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 index 23afe80..9296fce 100644 --- a/contrib/llvm/lib/MC/MCInstPrinter.cpp +++ b/contrib/llvm/lib/MC/MCInstPrinter.cpp @@ -1,4 +1,4 @@ -//===-- MCInstPrinter.cpp - Convert an MCInst to target assembly syntax ---===// +//===- MCInstPrinter.cpp - Convert an MCInst to target assembly syntax ----===// // // The LLVM Compiler Infrastructure // @@ -8,12 +8,16 @@ //===----------------------------------------------------------------------===// #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) { @@ -25,8 +29,7 @@ void llvm::dumpBytes(ArrayRef<uint8_t> bytes, raw_ostream &OS) { } } -MCInstPrinter::~MCInstPrinter() { -} +MCInstPrinter::~MCInstPrinter() = default; /// getOpcodeName - Return the name of the specified opcode enum (e.g. /// "MOV32ri") or empty if we can't resolve it. @@ -68,7 +71,7 @@ StringRef MCInstPrinter::markup(StringRef a, StringRef b) const { // For asm-style hex (e.g. 0ffh) the first digit always has to be a number. static bool needsLeadingZero(uint64_t Value) { - while(Value) + while (Value) { uint64_t digit = (Value >> 60) & 0xf; if (digit != 0) diff --git a/contrib/llvm/lib/MC/MCInstrAnalysis.cpp b/contrib/llvm/lib/MC/MCInstrAnalysis.cpp index 2d8336d..280b5cf 100644 --- a/contrib/llvm/lib/MC/MCInstrAnalysis.cpp +++ b/contrib/llvm/lib/MC/MCInstrAnalysis.cpp @@ -1,4 +1,4 @@ -//===-- MCInstrAnalysis.cpp - InstrDesc target hooks ------------*- C++ -*-===// +//===- MCInstrAnalysis.cpp - InstrDesc target hooks -----------------------===// // // The LLVM Compiler Infrastructure // @@ -8,6 +8,11 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCInstrAnalysis.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCInstrInfo.h" +#include <cstdint> + using namespace llvm; bool MCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr, diff --git a/contrib/llvm/lib/MC/MCLabel.cpp b/contrib/llvm/lib/MC/MCLabel.cpp index b443cbb..db25a46 100644 --- a/contrib/llvm/lib/MC/MCLabel.cpp +++ b/contrib/llvm/lib/MC/MCLabel.cpp @@ -1,4 +1,4 @@ -//===- lib/MC/MCLabel.cpp - MCLabel implementation ----------------------===// +//===- lib/MC/MCLabel.cpp - MCLabel implementation ------------------------===// // // The LLVM Compiler Infrastructure // @@ -8,14 +8,18 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCLabel.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" + using namespace llvm; void MCLabel::print(raw_ostream &OS) const { OS << '"' << getInstance() << '"'; } +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void MCLabel::dump() const { print(dbgs()); } +#endif diff --git a/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp b/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp index f71fc78..97f9541 100644 --- a/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp +++ b/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp @@ -1,4 +1,4 @@ -//===-- llvm/MC/MCLinkerOptimizationHint.cpp ----- LOH handling -*- C++ -*-===// +//===- llvm/MC/MCLinkerOptimizationHint.cpp ----- LOH handling ------------===// // // The LLVM Compiler Infrastructure // @@ -9,9 +9,11 @@ #include "llvm/MC/MCLinkerOptimizationHint.h" #include "llvm/MC/MCAsmLayout.h" -#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCMachObjectWriter.h" #include "llvm/Support/LEB128.h" +#include "llvm/Support/raw_ostream.h" +#include <cstddef> +#include <cstdint> using namespace llvm; @@ -41,14 +43,14 @@ void MCLOHDirective::emit(MachObjectWriter &ObjWriter, uint64_t MCLOHDirective::getEmitSize(const MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const { class raw_counting_ostream : public raw_ostream { - uint64_t Count; + 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() : Count(0) {} + raw_counting_ostream() = default; ~raw_counting_ostream() override { flush(); } }; diff --git a/contrib/llvm/lib/MC/MCMachOStreamer.cpp b/contrib/llvm/lib/MC/MCMachOStreamer.cpp index bd425bb..674c7b9 100644 --- a/contrib/llvm/lib/MC/MCMachOStreamer.cpp +++ b/contrib/llvm/lib/MC/MCMachOStreamer.cpp @@ -1,4 +1,4 @@ -//===-- MCMachOStreamer.cpp - MachO Streamer ------------------------------===// +//===- MCMachOStreamer.cpp - MachO Streamer -------------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,27 +7,35 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCStreamer.h" #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/MCDwarf.h" +#include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCFragment.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCLinkerOptimizationHint.h" #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbolMachO.h" #include "llvm/MC/MCValue.h" -#include "llvm/Support/Dwarf.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; @@ -70,7 +78,7 @@ public: /// @{ void ChangeSection(MCSection *Sect, const MCExpr *Subsect) override; - void EmitLabel(MCSymbol *Symbol) 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; @@ -83,18 +91,7 @@ public: void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; - void BeginCOFFSymbolDef(const MCSymbol *Symbol) override { - llvm_unreachable("macho doesn't support this directive"); - } - void EmitCOFFSymbolStorageClass(int StorageClass) override { - llvm_unreachable("macho doesn't support this directive"); - } - void EmitCOFFSymbolType(int Type) override { - llvm_unreachable("macho doesn't support this directive"); - } - void EndCOFFSymbolDef() override { - llvm_unreachable("macho doesn't support this directive"); - } + void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, @@ -102,13 +99,6 @@ public: void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment = 0) override; - void EmitFileDirective(StringRef Filename) override { - // FIXME: Just ignore the .file; it isn't important enough to fail the - // entire assembly. - - // report_fatal_error("unsupported directive: '.file'"); - } - void EmitIdent(StringRef IdentString) override { llvm_unreachable("macho doesn't support this directive"); } @@ -152,7 +142,7 @@ static bool canGoAfterDWARF(const MCSectionMachO &MSec) { void MCMachOStreamer::ChangeSection(MCSection *Section, const MCExpr *Subsection) { // Change the section normally. - bool Created = MCObjectStreamer::changeSectionImpl(Section, Subsection); + bool Created = changeSectionImpl(Section, Subsection); const MCSectionMachO &MSec = *cast<MCSectionMachO>(Section); StringRef SegName = MSec.getSegmentName(); if (SegName == "__DWARF") @@ -181,15 +171,13 @@ void MCMachOStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, EmitSymbolAttribute(EHSymbol, MCSA_PrivateExtern); } -void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { - assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - +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); + 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 diff --git a/contrib/llvm/lib/MC/MCMachObjectTargetWriter.cpp b/contrib/llvm/lib/MC/MCMachObjectTargetWriter.cpp index 4ffd6a7..8809a3c 100644 --- a/contrib/llvm/lib/MC/MCMachObjectTargetWriter.cpp +++ b/contrib/llvm/lib/MC/MCMachObjectTargetWriter.cpp @@ -1,4 +1,4 @@ -//===-- MCMachObjectTargetWriter.cpp - Mach-O Target Writer Subclass ------===// +//===- MCMachObjectTargetWriter.cpp - Mach-O Target Writer Subclass -------===// // // The LLVM Compiler Infrastructure // @@ -16,4 +16,4 @@ MCMachObjectTargetWriter::MCMachObjectTargetWriter(bool Is64Bit_, uint32_t CPUSubtype_) : Is64Bit(Is64Bit_), CPUType(CPUType_), CPUSubtype(CPUSubtype_) {} -MCMachObjectTargetWriter::~MCMachObjectTargetWriter() {} +MCMachObjectTargetWriter::~MCMachObjectTargetWriter() = default; diff --git a/contrib/llvm/lib/MC/MCNullStreamer.cpp b/contrib/llvm/lib/MC/MCNullStreamer.cpp index eb2d912..4db9a2c 100644 --- a/contrib/llvm/lib/MC/MCNullStreamer.cpp +++ b/contrib/llvm/lib/MC/MCNullStreamer.cpp @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" using namespace llvm; @@ -34,6 +34,10 @@ namespace { void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, uint64_t Size = 0, unsigned ByteAlignment = 0) override {} void EmitGPRel32Value(const MCExpr *Value) override {} + void BeginCOFFSymbolDef(const MCSymbol *Symbol) override {} + void EmitCOFFSymbolStorageClass(int StorageClass) override {} + void EmitCOFFSymbolType(int Type) override {} + void EndCOFFSymbolDef() override {} }; } diff --git a/contrib/llvm/lib/MC/MCObjectFileInfo.cpp b/contrib/llvm/lib/MC/MCObjectFileInfo.cpp index 8fd71f6..21c5516 100644 --- a/contrib/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/contrib/llvm/lib/MC/MCObjectFileInfo.cpp @@ -10,13 +10,15 @@ #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/Support/COFF.h" +#include "llvm/MC/MCSectionWasm.h" using namespace llvm; @@ -239,6 +241,9 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) { DwarfStrSection = Ctx->getMachOSection("__DWARF", "__debug_str", MachO::S_ATTR_DEBUG, SectionKind::getMetadata(), "info_string"); + DwarfStrOffSection = + Ctx->getMachOSection("__DWARF", "__debug_str_offs", MachO::S_ATTR_DEBUG, + SectionKind::getMetadata(), "section_str_off"); DwarfLocSection = Ctx->getMachOSection("__DWARF", "__debug_loc", MachO::S_ATTR_DEBUG, SectionKind::getMetadata(), "section_debug_loc"); @@ -284,6 +289,10 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T) { ((CMModel == CodeModel::Large) ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4); break; + case Triple::bpfel: + case Triple::bpfeb: + FDECFIEncoding = dwarf::DW_EH_PE_sdata8; + break; default: FDECFIEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; break; @@ -505,68 +514,79 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T) { COFFDebugSymbolsSection = nullptr; COFFDebugTypesSection = nullptr; + unsigned DebugSecType = ELF::SHT_PROGBITS; + + // MIPS .debug_* sections should have SHT_MIPS_DWARF section type + // to distinguish among sections contain DWARF and ECOFF debug formats. + // Sections with ECOFF debug format are obsoleted and marked by SHT_PROGBITS. + if (T.getArch() == Triple::mips || T.getArch() == Triple::mipsel || + T.getArch() == Triple::mips64 || T.getArch() == Triple::mips64el) + DebugSecType = ELF::SHT_MIPS_DWARF; + // Debug Info Sections. - DwarfAbbrevSection = Ctx->getELFSection(".debug_abbrev", ELF::SHT_PROGBITS, 0, - "section_abbrev"); - DwarfInfoSection = - Ctx->getELFSection(".debug_info", ELF::SHT_PROGBITS, 0, "section_info"); - DwarfLineSection = Ctx->getELFSection(".debug_line", ELF::SHT_PROGBITS, 0); - DwarfFrameSection = Ctx->getELFSection(".debug_frame", ELF::SHT_PROGBITS, 0); + DwarfAbbrevSection = + Ctx->getELFSection(".debug_abbrev", DebugSecType, 0); + DwarfInfoSection = Ctx->getELFSection(".debug_info", DebugSecType, 0); + DwarfLineSection = Ctx->getELFSection(".debug_line", DebugSecType, 0); + DwarfFrameSection = Ctx->getELFSection(".debug_frame", DebugSecType, 0); DwarfPubNamesSection = - Ctx->getELFSection(".debug_pubnames", ELF::SHT_PROGBITS, 0); + Ctx->getELFSection(".debug_pubnames", DebugSecType, 0); DwarfPubTypesSection = - Ctx->getELFSection(".debug_pubtypes", ELF::SHT_PROGBITS, 0); + Ctx->getELFSection(".debug_pubtypes", DebugSecType, 0); DwarfGnuPubNamesSection = - Ctx->getELFSection(".debug_gnu_pubnames", ELF::SHT_PROGBITS, 0); + Ctx->getELFSection(".debug_gnu_pubnames", DebugSecType, 0); DwarfGnuPubTypesSection = - Ctx->getELFSection(".debug_gnu_pubtypes", ELF::SHT_PROGBITS, 0); + Ctx->getELFSection(".debug_gnu_pubtypes", DebugSecType, 0); DwarfStrSection = - Ctx->getELFSection(".debug_str", ELF::SHT_PROGBITS, + Ctx->getELFSection(".debug_str", DebugSecType, ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, ""); - DwarfLocSection = Ctx->getELFSection(".debug_loc", ELF::SHT_PROGBITS, 0); + DwarfLocSection = Ctx->getELFSection(".debug_loc", DebugSecType, 0); DwarfARangesSection = - Ctx->getELFSection(".debug_aranges", ELF::SHT_PROGBITS, 0); + Ctx->getELFSection(".debug_aranges", DebugSecType, 0); DwarfRangesSection = - Ctx->getELFSection(".debug_ranges", ELF::SHT_PROGBITS, 0, "debug_range"); - DwarfMacinfoSection = Ctx->getELFSection(".debug_macinfo", ELF::SHT_PROGBITS, - 0, "debug_macinfo"); + Ctx->getELFSection(".debug_ranges", DebugSecType, 0); + DwarfMacinfoSection = + Ctx->getELFSection(".debug_macinfo", DebugSecType, 0); // DWARF5 Experimental Debug Info // Accelerator Tables DwarfAccelNamesSection = - Ctx->getELFSection(".apple_names", ELF::SHT_PROGBITS, 0, "names_begin"); + Ctx->getELFSection(".apple_names", ELF::SHT_PROGBITS, 0); DwarfAccelObjCSection = - Ctx->getELFSection(".apple_objc", ELF::SHT_PROGBITS, 0, "objc_begin"); - DwarfAccelNamespaceSection = Ctx->getELFSection( - ".apple_namespaces", ELF::SHT_PROGBITS, 0, "namespac_begin"); + 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, "types_begin"); + Ctx->getELFSection(".apple_types", ELF::SHT_PROGBITS, 0); + + // String Offset and Address Sections + DwarfStrOffSection = + Ctx->getELFSection(".debug_str_offsets", DebugSecType, 0); + DwarfAddrSection = Ctx->getELFSection(".debug_addr", DebugSecType, 0); // Fission Sections DwarfInfoDWOSection = - Ctx->getELFSection(".debug_info.dwo", ELF::SHT_PROGBITS, 0); + Ctx->getELFSection(".debug_info.dwo", DebugSecType, 0); DwarfTypesDWOSection = - Ctx->getELFSection(".debug_types.dwo", ELF::SHT_PROGBITS, 0); + Ctx->getELFSection(".debug_types.dwo", DebugSecType, 0); DwarfAbbrevDWOSection = - Ctx->getELFSection(".debug_abbrev.dwo", ELF::SHT_PROGBITS, 0); + Ctx->getELFSection(".debug_abbrev.dwo", DebugSecType, 0); DwarfStrDWOSection = - Ctx->getELFSection(".debug_str.dwo", ELF::SHT_PROGBITS, + Ctx->getELFSection(".debug_str.dwo", DebugSecType, ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, ""); DwarfLineDWOSection = - Ctx->getELFSection(".debug_line.dwo", ELF::SHT_PROGBITS, 0); + Ctx->getELFSection(".debug_line.dwo", DebugSecType, 0); DwarfLocDWOSection = - Ctx->getELFSection(".debug_loc.dwo", ELF::SHT_PROGBITS, 0, "skel_loc"); + Ctx->getELFSection(".debug_loc.dwo", DebugSecType, 0); DwarfStrOffDWOSection = - Ctx->getELFSection(".debug_str_offsets.dwo", ELF::SHT_PROGBITS, 0); - DwarfAddrSection = - Ctx->getELFSection(".debug_addr", ELF::SHT_PROGBITS, 0, "addr_sec"); + Ctx->getELFSection(".debug_str_offsets.dwo", DebugSecType, 0); // DWP Sections DwarfCUIndexSection = - Ctx->getELFSection(".debug_cu_index", ELF::SHT_PROGBITS, 0); + Ctx->getELFSection(".debug_cu_index", DebugSecType, 0); DwarfTUIndexSection = - Ctx->getELFSection(".debug_tu_index", ELF::SHT_PROGBITS, 0); + Ctx->getELFSection(".debug_tu_index", DebugSecType, 0); StackMapSection = Ctx->getELFSection(".llvm_stackmaps", ELF::SHT_PROGBITS, ELF::SHF_ALLOC); @@ -682,6 +702,11 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) { 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 | @@ -736,7 +761,7 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) { ".debug_str_offsets.dwo", COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); + SectionKind::getMetadata(), "section_str_off_dwo"); DwarfAddrSection = Ctx->getCOFFSection( ".debug_addr", COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | @@ -799,6 +824,30 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) { SectionKind::getReadOnly()); } +void MCObjectFileInfo::initWasmMCObjectFileInfo(const Triple &T) { + // TODO: Set the section types and flags. + TextSection = Ctx->getWasmSection(".text", 0, 0); + DataSection = Ctx->getWasmSection(".data", 0, 0); + + // TODO: Set the section types and flags. + DwarfLineSection = Ctx->getWasmSection(".debug_line", 0, 0); + DwarfStrSection = Ctx->getWasmSection(".debug_str", 0, 0); + DwarfLocSection = Ctx->getWasmSection(".debug_loc", 0, 0); + DwarfAbbrevSection = Ctx->getWasmSection(".debug_abbrev", 0, 0, "section_abbrev"); + DwarfARangesSection = Ctx->getWasmSection(".debug_aranges", 0, 0); + DwarfRangesSection = Ctx->getWasmSection(".debug_ranges", 0, 0, "debug_range"); + DwarfMacinfoSection = Ctx->getWasmSection(".debug_macinfo", 0, 0, "debug_macinfo"); + DwarfAddrSection = Ctx->getWasmSection(".debug_addr", 0, 0); + DwarfCUIndexSection = Ctx->getWasmSection(".debug_cu_index", 0, 0); + DwarfTUIndexSection = Ctx->getWasmSection(".debug_tu_index", 0, 0); + DwarfInfoSection = Ctx->getWasmSection(".debug_info", 0, 0, "section_info"); + DwarfFrameSection = Ctx->getWasmSection(".debug_frame", 0, 0); + DwarfPubNamesSection = Ctx->getWasmSection(".debug_pubnames", 0, 0); + DwarfPubTypesSection = Ctx->getWasmSection(".debug_pubtypes", 0, 0); + + // TODO: Define more sections. +} + void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC, CodeModel::Model cm, MCContext &ctx) { @@ -843,6 +892,10 @@ void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC, Env = IsELF; initELFMCObjectFileInfo(TT); break; + case Triple::Wasm: + Env = IsWasm; + initWasmMCObjectFileInfo(TT); + break; case Triple::UnknownObjectFormat: report_fatal_error("Cannot initialize MC for unknown object file format."); break; diff --git a/contrib/llvm/lib/MC/MCObjectStreamer.cpp b/contrib/llvm/lib/MC/MCObjectStreamer.cpp index cae5c1f..174397e 100644 --- a/contrib/llvm/lib/MC/MCObjectStreamer.cpp +++ b/contrib/llvm/lib/MC/MCObjectStreamer.cpp @@ -133,6 +133,11 @@ void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, // Avoid fixups when possible. int64_t AbsValue; if (Value->evaluateAsAbsolute(AbsValue, getAssembler())) { + if (!isUIntN(8 * Size, AbsValue) && !isIntN(8 * Size, AbsValue)) { + getContext().reportError( + Loc, "value evaluated as " + Twine(AbsValue) + " is out of range."); + return; + } EmitIntValue(AbsValue, Size); return; } @@ -153,8 +158,8 @@ void MCObjectStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { EmitLabel(Frame.End); } -void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) { - MCStreamer::EmitLabel(Symbol); +void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) { + MCStreamer::EmitLabel(Symbol, Loc); getAssembler().registerSymbol(*Symbol); @@ -171,6 +176,16 @@ void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) { } } +void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F) { + MCStreamer::EmitLabel(Symbol, Loc); + getAssembler().registerSymbol(*Symbol); + auto *DF = dyn_cast_or_null<MCDataFragment>(F); + if (DF) + Symbol->setFragment(F); + else + PendingLabels.push_back(Symbol); +} + void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) { int64_t IntValue; if (Value->evaluateAsAbsolute(IntValue, getAssembler())) { @@ -203,6 +218,7 @@ 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); @@ -227,7 +243,7 @@ bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) const { } void MCObjectStreamer::EmitInstruction(const MCInst &Inst, - const MCSubtargetInfo &STI) { + const MCSubtargetInfo &STI, bool) { MCStreamer::EmitInstruction(Inst, STI); MCSection *Sec = getCurrentSectionOnly(); @@ -490,8 +506,8 @@ 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->getFixups().push_back( + MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4)); DF->getContents().resize(DF->getContents().size() + 4, 0); } @@ -500,8 +516,8 @@ 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->getFixups().push_back( + MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4)); DF->getContents().resize(DF->getContents().size() + 8, 0); } @@ -572,6 +588,10 @@ void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size, MCStreamer::emitFill(IntNumValues, Size, Expr); } +void MCObjectStreamer::EmitFileDirective(StringRef Filename) { + getAssembler().addFileName(Filename); +} + void MCObjectStreamer::FinishImpl() { // If we are generating dwarf for assembly source files dump out the sections. if (getContext().getGenDwarfForAssembly()) diff --git a/contrib/llvm/lib/MC/MCObjectWriter.cpp b/contrib/llvm/lib/MC/MCObjectWriter.cpp index e84f74a..98ac48a 100644 --- a/contrib/llvm/lib/MC/MCObjectWriter.cpp +++ b/contrib/llvm/lib/MC/MCObjectWriter.cpp @@ -7,15 +7,15 @@ // //===----------------------------------------------------------------------===// +#include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCFragment.h" #include "llvm/MC/MCSymbol.h" using namespace llvm; -MCObjectWriter::~MCObjectWriter() { -} +MCObjectWriter::~MCObjectWriter() = default; bool MCObjectWriter::isSymbolRefDifferenceFullyResolved( const MCAssembler &Asm, const MCSymbolRefExpr *A, const MCSymbolRefExpr *B, @@ -51,5 +51,3 @@ bool MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl( // On ELF and COFF A - B is absolute if A and B are in the same section. return &SecA == &SecB; } - -bool MCObjectWriter::isWeak(const MCSymbol &) const { return false; } diff --git a/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp b/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp index 87ecf9e..2b96360 100644 --- a/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp +++ b/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp @@ -30,15 +30,11 @@ using namespace llvm; -AsmLexer::AsmLexer(const MCAsmInfo &MAI) - : MAI(MAI), CurPtr(nullptr), IsAtStartOfLine(true), - IsAtStartOfStatement(true), IsParsingMSInlineAsm(false), - IsPeeking(false) { +AsmLexer::AsmLexer(const MCAsmInfo &MAI) : MAI(MAI) { AllowAtInIdentifier = !StringRef(MAI.getCommentString()).startswith("@"); } -AsmLexer::~AsmLexer() { -} +AsmLexer::~AsmLexer() = default; void AsmLexer::setBuffer(StringRef Buf, const char *ptr) { CurBuf = Buf; diff --git a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp index fd40baa..dad47e4 100644 --- a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp @@ -15,12 +15,13 @@ #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/STLExtras.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" @@ -35,6 +36,7 @@ #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" @@ -42,10 +44,10 @@ #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/Dwarf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" @@ -55,6 +57,7 @@ #include <algorithm> #include <cassert> #include <cctype> +#include <climits> #include <cstddef> #include <cstdint> #include <deque> @@ -67,7 +70,7 @@ using namespace llvm; -MCAsmParserSemaCallback::~MCAsmParserSemaCallback() {} +MCAsmParserSemaCallback::~MCAsmParserSemaCallback() = default; static cl::opt<unsigned> AsmMacroMaxNestingDepth( "asm-macro-max-nesting-depth", cl::init(20), cl::Hidden, @@ -82,10 +85,10 @@ typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments; struct MCAsmMacroParameter { StringRef Name; MCAsmMacroArgument Value; - bool Required; - bool Vararg; + bool Required = false; + bool Vararg = false; - MCAsmMacroParameter() : Required(false), Vararg(false) {} + MCAsmMacroParameter() = default; }; typedef std::vector<MCAsmMacroParameter> MCAsmMacroParameters; @@ -124,23 +127,20 @@ struct ParseStatementInfo { SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands; /// \brief The opcode from the last parsed instruction. - unsigned Opcode; + unsigned Opcode = ~0U; /// \brief Was there an error parsing the inline assembly? - bool ParseError; + bool ParseError = false; - SmallVectorImpl<AsmRewrite> *AsmRewrites; + SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr; - ParseStatementInfo() : Opcode(~0U), ParseError(false), AsmRewrites(nullptr) {} + ParseStatementInfo() = delete; ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites) - : Opcode(~0), ParseError(false), AsmRewrites(rewrites) {} + : AsmRewrites(rewrites) {} }; /// \brief The concrete assembly parser instance. class AsmParser : public MCAsmParser { - AsmParser(const AsmParser &) = delete; - void operator=(const AsmParser &) = delete; - private: AsmLexer Lexer; MCContext &Ctx; @@ -199,17 +199,19 @@ private: unsigned LastQueryLine; /// AssemblerDialect. ~OU means unset value and use value provided by MAI. - unsigned AssemblerDialect; + unsigned AssemblerDialect = ~0U; /// \brief is Darwin compatibility enabled? - bool IsDarwin; + bool IsDarwin = false; /// \brief Are we parsing ms-style inline assembly? - bool ParsingInlineAsm; + bool ParsingInlineAsm = false; public: AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, const MCAsmInfo &MAI, unsigned CB); + AsmParser(const AsmParser &) = delete; + AsmParser &operator=(const AsmParser &) = delete; ~AsmParser() override; bool Run(bool NoInitialTextSection, bool NoFinalize = false) override; @@ -223,7 +225,6 @@ public: DirectiveKindMap[Directive] = DirectiveKindMap[Alias]; } -public: /// @name MCAsmParser Interface /// { @@ -258,7 +259,7 @@ public: bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, - SmallVectorImpl<std::pair<void *,bool> > &OpDecls, + SmallVectorImpl<std::pair<void *,bool>> &OpDecls, SmallVectorImpl<std::string> &Constraints, SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII, const MCInstPrinter *IP, @@ -286,6 +287,8 @@ public: /// } private: + bool isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc); + void altMacroString(StringRef AltMacroStr, std::string &Res); bool parseStatement(ParseStatementInfo &Info, MCAsmParserSemaCallback *SI); bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites); @@ -411,7 +414,7 @@ private: DK_CFI_REMEMBER_STATE, DK_CFI_RESTORE_STATE, DK_CFI_SAME_VALUE, DK_CFI_RESTORE, DK_CFI_ESCAPE, DK_CFI_SIGNAL_FRAME, DK_CFI_UNDEFINED, DK_CFI_REGISTER, DK_CFI_WINDOW_SAVE, - DK_MACROS_ON, DK_MACROS_OFF, + DK_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, @@ -483,7 +486,8 @@ private: 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" @@ -574,9 +578,7 @@ 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), - PlatformParser(nullptr), CurBuffer(CB ? CB : SM.getMainFileID()), - MacrosEnabledFlag(true), CppHashInfo(), AssemblerDialect(~0U), - IsDarwin(false), ParsingInlineAsm(false) { + CurBuffer(CB ? CB : SM.getMainFileID()), MacrosEnabledFlag(true) { HadError = false; // Save the old handler. SavedDiagHandler = SrcMgr.getDiagHandler(); @@ -597,6 +599,9 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, case MCObjectFileInfo::IsELF: PlatformParser.reset(createELFAsmParser()); break; + case MCObjectFileInfo::IsWasm: + llvm_unreachable("Wasm parsing not supported yet"); + break; } PlatformParser->Initialize(*this); @@ -698,7 +703,7 @@ const AsmToken &AsmParser::Lex() { // 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().front() != '\n' && + if (!getTok().getString().empty() && getTok().getString().front() != '\n' && getTok().getString().front() != '\r' && MAI.preserveAsmComments()) Out.addExplicitComment(Twine(getTok().getString())); } @@ -735,6 +740,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { HadError = false; AsmCond StartingCondState = TheCondState; + SmallVector<AsmRewrite, 4> AsmStrRewrites; // If we are generating dwarf for assembly source files save the initial text // section and generate a .file directive. @@ -754,7 +760,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // While we have input, parse each statement. while (Lexer.isNot(AsmToken::Eof)) { - ParseStatementInfo Info; + ParseStatementInfo Info(&AsmStrRewrites); if (!parseStatement(Info, nullptr)) continue; @@ -922,7 +928,7 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { Lex(); // Eat the operator. if (parsePrimaryExpr(Res, EndLoc)) return true; - Res = MCUnaryExpr::createLNot(Res, getContext()); + Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc); return false; case AsmToken::Dollar: case AsmToken::At: @@ -983,7 +989,7 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; // Lookup the symbol variant if used. - if (Split.second.size()) { + if (!Split.second.empty()) { Variant = MCSymbolRefExpr::getVariantKindForName(Split.second); if (Variant != MCSymbolRefExpr::VK_Invalid) { SymbolName = Split.first; @@ -1009,7 +1015,7 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { } // Otherwise create a symbol ref. - Res = MCSymbolRefExpr::create(Sym, Variant, getContext()); + Res = MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc); return false; } case AsmToken::BigNum: @@ -1075,19 +1081,19 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { Lex(); // Eat the operator. if (parsePrimaryExpr(Res, EndLoc)) return true; - Res = MCUnaryExpr::createMinus(Res, getContext()); + 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()); + 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()); + 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. @@ -1188,6 +1194,42 @@ AsmParser::applyModifierToExpr(const MCExpr *E, llvm_unreachable("Invalid expression kind!"); } +/// This function checks if the next token is <string> type or arithmetic. +/// string that begin with character '<' must end with character '>'. +/// otherwise it is arithmetics. +/// If the function returns a 'true' value, +/// the End argument will be filled with the last location pointed to the '>' +/// character. + +/// There is a gap between the AltMacro's documentation and the single quote implementation. +/// GCC does not fully support this feature and so we will not support it. +/// TODO: Adding single quote as a string. +bool AsmParser::isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc) { + assert((StrLoc.getPointer() != NULL) && + "Argument to the function cannot be a NULL value"); + const char *CharPtr = StrLoc.getPointer(); + while ((*CharPtr != '>') && (*CharPtr != '\n') && + (*CharPtr != '\r') && (*CharPtr != '\0')){ + if(*CharPtr == '!') + CharPtr++; + CharPtr++; + } + if (*CharPtr == '>') { + EndLoc = StrLoc.getFromPointer(CharPtr + 1); + return true; + } + return false; +} + +/// \brief creating a string without the escape characters '!'. +void AsmParser::altMacroString(StringRef AltMacroStr,std::string &Res) { + for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) { + if (AltMacroStr[Pos] == '!') + Pos++; + Res += AltMacroStr[Pos]; + } +} + /// \brief Parse an expression and return it. /// /// expr ::= expr &&,|| expr -> lowest. @@ -1440,6 +1482,7 @@ unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K, /// 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); @@ -1464,7 +1507,7 @@ bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, return true; // Merge LHS and RHS according to operator. - Res = MCBinaryExpr::create(Kind, Res, RHS, getContext()); + Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc); } } @@ -1480,7 +1523,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, Lex(); if (Lexer.is(AsmToken::EndOfStatement)) { // if this is a line comment we can drop it safely - if (getTok().getString().front() == '\r' || + if (getTok().getString().empty() || getTok().getString().front() == '\r' || getTok().getString().front() == '\n') Out.AddBlankLine(); Lex(); @@ -1621,7 +1664,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, if (ParsingInlineAsm && SI) { StringRef RewrittenLabel = SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true); - assert(RewrittenLabel.size() && + assert(!RewrittenLabel.empty() && "We should have an internal name here."); Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(), RewrittenLabel); @@ -1630,12 +1673,6 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, Sym = getContext().getOrCreateSymbol(IDVal); } else Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal); - - Sym->redefineIfPossible(); - - if (!Sym->isUndefined() || Sym->isVariable()) - return Error(IDLoc, "invalid symbol redefinition"); - // 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 @@ -1653,8 +1690,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, } // Emit the label. - if (!ParsingInlineAsm) - Out.EmitLabel(Sym); + 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. @@ -1758,8 +1795,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, case DK_8BYTE: return parseDirectiveValue(IDVal, 8); case DK_DC_A: - return parseDirectiveValue(IDVal, - getContext().getAsmInfo()->getPointerSize()); + return parseDirectiveValue( + IDVal, getContext().getAsmInfo()->getCodePointerSize()); case DK_OCTA: return parseDirectiveOctaValue(IDVal); case DK_SINGLE: @@ -1924,6 +1961,9 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, 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: @@ -1983,7 +2023,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, if (ParsingInlineAsm && (IDVal == "align" || IDVal == "ALIGN")) return parseDirectiveMSAlign(IDLoc, Info); - if (ParsingInlineAsm && (IDVal == "even")) + if (ParsingInlineAsm && (IDVal == "even" || IDVal == "EVEN")) Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4); if (checkForValidSection()) return true; @@ -2029,7 +2069,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, // 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.size()) { + if (!CppHashInfo.Filename.empty()) { unsigned FileNumber = getStreamer().EmitDwarfFileDirective( 0, StringRef(), CppHashInfo.Filename); getContext().setGenDwarfFileNumber(FileNumber); @@ -2060,9 +2100,9 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, // If parsing succeeded, match the instruction. if (!ParseHadError) { uint64_t ErrorInfo; - if (getTargetParser().MatchAndEmitInstruction(IDLoc, Info.Opcode, - Info.ParsedOperands, Out, - ErrorInfo, ParsingInlineAsm)) + if (getTargetParser().MatchAndEmitInstruction( + IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo, + getTargetParser().isParsingInlineAsm())) return true; } return false; @@ -2272,9 +2312,27 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, } else { bool VarargParameter = HasVararg && Index == (NParameters - 1); for (const AsmToken &Token : A[Index]) + // For altmacro mode, you can write '%expr'. + // The prefix '%' evaluates the expression 'expr' + // and uses the result as a string (e.g. replace %(1+2) with the string "3"). + // Here, we identify the integer token which is the result of the + // absolute expression evaluation and replace it with its string representation. + if ((Lexer.IsaAltMacroMode()) && + (*(Token.getString().begin()) == '%') && Token.is(AsmToken::Integer)) + // Emit an integer value to the buffer. + OS << Token.getIntVal(); + // Only Token that was validated as a string and begins with '<' + // is considered altMacroString!!! + else if ((Lexer.IsaAltMacroMode()) && + (*(Token.getString().begin()) == '<') && + Token.is(AsmToken::String)) { + std::string Res; + altMacroString(Token.getStringContents(), Res); + OS << Res; + } // We expect no quotes around the string's contents when // parsing for varargs. - if (Token.getKind() != AsmToken::String || VarargParameter) + else if (Token.isNot(AsmToken::String) || VarargParameter) OS << Token.getString(); else OS << Token.getStringContents(); @@ -2445,13 +2503,37 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M, NamedParametersFound = true; } + bool Vararg = HasVararg && Parameter == (NParameters - 1); if (NamedParametersFound && FA.Name.empty()) return Error(IDLoc, "cannot mix positional and keyword arguments"); - bool Vararg = HasVararg && Parameter == (NParameters - 1); - if (parseMacroArgument(FA.Value, Vararg)) - return true; + SMLoc StrLoc = Lexer.getLoc(); + SMLoc EndLoc; + if (Lexer.IsaAltMacroMode() && Lexer.is(AsmToken::Percent)) { + const MCExpr *AbsoluteExp; + int64_t Value; + /// Eat '%' + Lex(); + if (parseExpression(AbsoluteExp, EndLoc)) + return false; + if (!AbsoluteExp->evaluateAsAbsolute(Value)) + return Error(StrLoc, "expected absolute expression"); + const char *StrChar = StrLoc.getPointer(); + const char *EndChar = EndLoc.getPointer(); + AsmToken newToken(AsmToken::Integer, StringRef(StrChar , EndChar - StrChar), Value); + FA.Value.push_back(newToken); + } else if (Lexer.IsaAltMacroMode() && Lexer.is(AsmToken::Less) && + isAltmacroString(StrLoc, EndLoc)) { + const char *StrChar = StrLoc.getPointer(); + const char *EndChar = EndLoc.getPointer(); + jumpToLoc(EndLoc, CurBuffer); + /// Eat from '<' to '>' + Lex(); + AsmToken newToken(AsmToken::String, StringRef(StrChar, EndChar - StrChar)); + FA.Value.push_back(newToken); + } else if(parseMacroArgument(FA.Value, Vararg)) + return true; unsigned PI = Parameter; if (!FA.Name.empty()) { @@ -3843,6 +3925,19 @@ bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) { return false; } +/// parseDirectiveAltmacro +/// ::= .altmacro +/// ::= .noaltmacro +bool AsmParser::parseDirectiveAltmacro(StringRef Directive) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '" + Directive + "' directive"); + if (Directive == ".altmacro") + getLexer().SetAltMacroMode(true); + else + getLexer().SetAltMacroMode(false); + return false; +} + /// parseDirectiveMacrosOnOff /// ::= .macros_on /// ::= .macros_off @@ -3877,6 +3972,12 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) { 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 ':' @@ -4195,7 +4296,6 @@ bool AsmParser::parseDirectiveBundleUnlock() { /// parseDirectiveSpace /// ::= (.skip | .space) expression [ , expression ] bool AsmParser::parseDirectiveSpace(StringRef IDVal) { - SMLoc NumBytesLoc = Lexer.getLoc(); const MCExpr *NumBytes; if (checkForValidSection() || parseExpression(NumBytes)) @@ -4291,7 +4391,6 @@ bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Seman /// 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)) @@ -4420,6 +4519,7 @@ bool AsmParser::parseDirectiveComm(bool IsLocal) { 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"); @@ -4935,6 +5035,8 @@ void AsmParser::initializeDirectiveKindMap() { 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; @@ -5212,7 +5314,7 @@ static int rewritesSort(const AsmRewrite *AsmRewriteA, bool AsmParser::parseMSInlineAsm( void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, - unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool> > &OpDecls, + unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls, SmallVectorImpl<std::string> &Constraints, SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII, const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) { diff --git a/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp index f411479..b83d68d 100644 --- a/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp @@ -7,19 +7,27 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCParser/MCAsmParserExtension.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.h" -#include "llvm/MC/MCAsmInfo.h" +#include "llvm/BinaryFormat/COFF.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.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/Support/COFF.h" +#include "llvm/MC/SectionKind.h" +#include "llvm/Support/SMLoc.h" +#include <cassert> +#include <cstdint> +#include <limits> +#include <utility> + using namespace llvm; namespace { @@ -98,12 +106,14 @@ class COFFAsmParser : public MCAsmParserExtension { | 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 @@ -141,8 +151,9 @@ class COFFAsmParser : public MCAsmParserExtension { bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except); bool ParseSEHRegisterNumber(unsigned &RegNo); bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc); + public: - COFFAsmParser() {} + COFFAsmParser() = default; }; } // end annonomous namespace. @@ -277,7 +288,7 @@ bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { .Default(MCSA_Invalid); assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); if (getLexer().isNot(AsmToken::EndOfStatement)) { - for (;;) { + while (true) { StringRef Name; if (getParser().parseIdentifier(Name)) @@ -466,10 +477,11 @@ bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); - if (Offset < 0 || Offset > UINT32_MAX) - return Error(OffsetLoc, - "invalid '.secrel32' directive offset, can't be less " - "than zero or greater than UINT32_MAX"); + 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); @@ -817,4 +829,4 @@ 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 index 94aa70e..f4152a9 100644 --- a/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp @@ -7,22 +7,35 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCParser/MCAsmParserExtension.h" #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 { @@ -44,7 +57,7 @@ class DarwinAsmParser : public MCAsmParserExtension { SMLoc LastVersionMinDirective; public: - DarwinAsmParser() {} + DarwinAsmParser() = default; void Initialize(MCAsmParser &Parser) override { // Call the base implementation. @@ -209,37 +222,47 @@ public: 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 | @@ -247,144 +270,178 @@ public: // FIXME: Different on PPC and ARM. 0, 16); } + bool parseSectionDirectivePICSymbolStub(StringRef, SMLoc) { return parseSectionSwitch("__TEXT","__picsymbol_stub", MachO::S_SYMBOL_STUBS | MachO::S_ATTR_PURE_INSTRUCTIONS, 0, 26); } + bool parseSectionDirectiveData(StringRef, SMLoc) { return parseSectionSwitch("__DATA", "__data"); } + bool parseSectionDirectiveStaticData(StringRef, SMLoc) { return parseSectionSwitch("__DATA", "__static_data"); } + bool parseSectionDirectiveNonLazySymbolPointers(StringRef, SMLoc) { return parseSectionSwitch("__DATA", "__nl_symbol_ptr", MachO::S_NON_LAZY_SYMBOL_POINTERS, 4); } + bool parseSectionDirectiveLazySymbolPointers(StringRef, SMLoc) { return parseSectionSwitch("__DATA", "__la_symbol_ptr", MachO::S_LAZY_SYMBOL_POINTERS, 4); } + bool parseSectionDirectiveThreadLocalVariablePointers(StringRef, SMLoc) { return parseSectionSwitch("__DATA", "__thread_ptr", MachO::S_THREAD_LOCAL_VARIABLE_POINTERS, 4); } + bool parseSectionDirectiveDyld(StringRef, SMLoc) { return parseSectionSwitch("__DATA", "__dyld"); } + bool parseSectionDirectiveModInitFunc(StringRef, SMLoc) { return parseSectionSwitch("__DATA", "__mod_init_func", MachO::S_MOD_INIT_FUNC_POINTERS, 4); } + bool parseSectionDirectiveModTermFunc(StringRef, SMLoc) { return parseSectionSwitch("__DATA", "__mod_term_func", MachO::S_MOD_TERM_FUNC_POINTERS, 4); } + bool parseSectionDirectiveConstData(StringRef, SMLoc) { return parseSectionSwitch("__DATA", "__const"); } + bool parseSectionDirectiveObjCClass(StringRef, SMLoc) { return parseSectionSwitch("__OBJC", "__class", MachO::S_ATTR_NO_DEAD_STRIP); } + bool parseSectionDirectiveObjCMetaClass(StringRef, SMLoc) { return parseSectionSwitch("__OBJC", "__meta_class", MachO::S_ATTR_NO_DEAD_STRIP); } + bool parseSectionDirectiveObjCCatClsMeth(StringRef, SMLoc) { return parseSectionSwitch("__OBJC", "__cat_cls_meth", MachO::S_ATTR_NO_DEAD_STRIP); } + bool parseSectionDirectiveObjCCatInstMeth(StringRef, SMLoc) { return parseSectionSwitch("__OBJC", "__cat_inst_meth", MachO::S_ATTR_NO_DEAD_STRIP); } + bool parseSectionDirectiveObjCProtocol(StringRef, SMLoc) { return parseSectionSwitch("__OBJC", "__protocol", MachO::S_ATTR_NO_DEAD_STRIP); } + bool parseSectionDirectiveObjCStringObject(StringRef, SMLoc) { return parseSectionSwitch("__OBJC", "__string_object", MachO::S_ATTR_NO_DEAD_STRIP); } + bool parseSectionDirectiveObjCClsMeth(StringRef, SMLoc) { return parseSectionSwitch("__OBJC", "__cls_meth", MachO::S_ATTR_NO_DEAD_STRIP); } + bool parseSectionDirectiveObjCInstMeth(StringRef, SMLoc) { return parseSectionSwitch("__OBJC", "__inst_meth", MachO::S_ATTR_NO_DEAD_STRIP); } + bool parseSectionDirectiveObjCClsRefs(StringRef, SMLoc) { return parseSectionSwitch("__OBJC", "__cls_refs", MachO::S_ATTR_NO_DEAD_STRIP | MachO::S_LITERAL_POINTERS, 4); } + bool parseSectionDirectiveObjCMessageRefs(StringRef, SMLoc) { return parseSectionSwitch("__OBJC", "__message_refs", MachO::S_ATTR_NO_DEAD_STRIP | MachO::S_LITERAL_POINTERS, 4); } + bool parseSectionDirectiveObjCSymbols(StringRef, SMLoc) { return parseSectionSwitch("__OBJC", "__symbols", MachO::S_ATTR_NO_DEAD_STRIP); } + bool parseSectionDirectiveObjCCategory(StringRef, SMLoc) { return parseSectionSwitch("__OBJC", "__category", MachO::S_ATTR_NO_DEAD_STRIP); } + bool parseSectionDirectiveObjCClassVars(StringRef, SMLoc) { return parseSectionSwitch("__OBJC", "__class_vars", MachO::S_ATTR_NO_DEAD_STRIP); } + bool parseSectionDirectiveObjCInstanceVars(StringRef, SMLoc) { return parseSectionSwitch("__OBJC", "__instance_vars", MachO::S_ATTR_NO_DEAD_STRIP); } + bool parseSectionDirectiveObjCModuleInfo(StringRef, SMLoc) { return parseSectionSwitch("__OBJC", "__module_info", MachO::S_ATTR_NO_DEAD_STRIP); } + bool parseSectionDirectiveObjCClassNames(StringRef, SMLoc) { return parseSectionSwitch("__TEXT", "__cstring", MachO::S_CSTRING_LITERALS); } + bool parseSectionDirectiveObjCMethVarTypes(StringRef, SMLoc) { return parseSectionSwitch("__TEXT", "__cstring", MachO::S_CSTRING_LITERALS); } + bool parseSectionDirectiveObjCMethVarNames(StringRef, SMLoc) { return parseSectionSwitch("__TEXT", "__cstring", MachO::S_CSTRING_LITERALS); } + bool parseSectionDirectiveObjCSelectorStrs(StringRef, SMLoc) { return parseSectionSwitch("__OBJC", "__selector_strs", MachO::S_CSTRING_LITERALS); } + bool parseSectionDirectiveTData(StringRef, SMLoc) { return parseSectionSwitch("__DATA", "__thread_data", MachO::S_THREAD_LOCAL_REGULAR); } + bool parseSectionDirectiveText(StringRef, SMLoc) { return parseSectionSwitch("__TEXT", "__text", MachO::S_ATTR_PURE_INSTRUCTIONS); } + bool parseSectionDirectiveTLV(StringRef, SMLoc) { return parseSectionSwitch("__DATA", "__thread_vars", MachO::S_THREAD_LOCAL_VARIABLES); } + bool parseSectionDirectiveIdent(StringRef, SMLoc) { // Darwin silently ignores the .ident directive. getParser().eatToEndOfStatement(); return false; } + bool parseSectionDirectiveThreadInitFunc(StringRef, SMLoc) { return parseSectionSwitch("__DATA", "__thread_init", MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS); } - bool parseVersionMin(StringRef, SMLoc); + bool parseVersionMin(StringRef, SMLoc); }; } // end anonymous namespace @@ -526,7 +583,7 @@ bool DarwinAsmParser::parseDirectiveDumpOrLoad(StringRef Directive, /// ::= .linker_option "string" ( , "string" )* bool DarwinAsmParser::parseDirectiveLinkerOption(StringRef IDVal, SMLoc) { SmallVector<std::string, 4> Args; - for (;;) { + while (true) { if (getLexer().isNot(AsmToken::String)) return TokError("expected string in '" + Twine(IDVal) + "' directive"); @@ -604,7 +661,6 @@ bool DarwinAsmParser::parseDirectiveSection(StringRef, SMLoc) { return TokError("unexpected token in '.section' directive"); Lex(); - StringRef Segment, Section; unsigned StubSize; unsigned TAA; diff --git a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp index 8d7ba0d..a407691 100644 --- a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp @@ -7,17 +7,29 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCParser/MCAsmParserExtension.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/Twine.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/Support/ELF.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 { @@ -142,9 +154,14 @@ 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 )* ] @@ -158,7 +175,7 @@ bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { .Default(MCSA_Invalid); assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); if (getLexer().isNot(AsmToken::EndOfStatement)) { - for (;;) { + while (true) { StringRef Name; if (getParser().parseIdentifier(Name)) @@ -230,8 +247,7 @@ bool ELFAsmParser::ParseSectionName(StringRef &SectionName) { return false; } - for (;;) { - + while (true) { SMLoc PrevLoc = getLexer().getLoc(); if (getLexer().is(AsmToken::Comma) || getLexer().is(AsmToken::EndOfStatement)) @@ -282,6 +298,9 @@ static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) { case 'w': flags |= ELF::SHF_WRITE; break; + case 'o': + flags |= ELF::SHF_LINK_ORDER; + break; case 'M': flags |= ELF::SHF_MERGE; break; @@ -366,6 +385,97 @@ bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) { return ParseSectionArguments(/*IsPush=*/false, loc); } +bool ELFAsmParser::maybeParseSectionType(StringRef &TypeName) { + MCAsmLexer &L = getLexer(); + if (L.isNot(AsmToken::Comma)) + return false; + Lex(); + if (L.isNot(AsmToken::At) && L.isNot(AsmToken::Percent) && + L.isNot(AsmToken::String)) { + if (L.getAllowAtInIdentifier()) + return TokError("expected '@<type>', '%<type>' or \"<type>\""); + else + return TokError("expected '%<type>' or \"<type>\""); + } + if (!L.is(AsmToken::String)) + Lex(); + if (L.is(AsmToken::Integer)) { + TypeName = getTok().getString(); + Lex(); + } else if (getParser().parseIdentifier(TypeName)) + return TokError("expected identifier in directive"); + return false; +} + +bool ELFAsmParser::parseMergeSize(int64_t &Size) { + if (getLexer().isNot(AsmToken::Comma)) + return TokError("expected the entry size"); + Lex(); + if (getParser().parseAbsoluteExpression(Size)) + return true; + if (Size <= 0) + return TokError("entry size must be positive"); + return false; +} + +bool ELFAsmParser::parseGroup(StringRef &GroupName) { + MCAsmLexer &L = getLexer(); + if (L.isNot(AsmToken::Comma)) + return TokError("expected group name"); + Lex(); + if (getParser().parseIdentifier(GroupName)) + return true; + if (L.is(AsmToken::Comma)) { + Lex(); + StringRef Linkage; + if (getParser().parseIdentifier(Linkage)) + return true; + if (Linkage != "comdat") + return TokError("Linkage must be 'comdat'"); + } + return false; +} + +bool ELFAsmParser::parseMetadataSym(MCSymbolELF *&Associated) { + MCAsmLexer &L = getLexer(); + if (L.isNot(AsmToken::Comma)) + return TokError("expected metadata symbol"); + Lex(); + StringRef Name; + if (getParser().parseIdentifier(Name)) + return true; + Associated = dyn_cast_or_null<MCSymbolELF>(getContext().lookupSymbol(Name)); + if (!Associated || !Associated->isInSection()) + return TokError("symbol is not in a section: " + Name); + return false; +} + +bool ELFAsmParser::maybeParseUniqueID(int64_t &UniqueID) { + MCAsmLexer &L = getLexer(); + if (L.isNot(AsmToken::Comma)) + return false; + Lex(); + StringRef UniqueStr; + if (getParser().parseIdentifier(UniqueStr)) + return TokError("expected identifier in directive"); + if (UniqueStr != "unique") + return TokError("expected 'unique'"); + if (L.isNot(AsmToken::Comma)) + return TokError("expected commma"); + Lex(); + if (getParser().parseAbsoluteExpression(UniqueID)) + return true; + if (UniqueID < 0) + return TokError("unique id must be positive"); + if (!isUInt<32>(UniqueID) || UniqueID == ~0U) + return TokError("unique id is too large"); + return false; +} + +static bool hasPrefix(StringRef SectionName, StringRef Prefix) { + return SectionName.startswith(Prefix) || SectionName == Prefix.drop_back(); +} + bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) { StringRef SectionName; @@ -379,14 +489,24 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) { const MCExpr *Subsection = nullptr; bool UseLastGroup = false; StringRef UniqueStr; + MCSymbolELF *Associated = nullptr; int64_t UniqueID = ~0; // Set the defaults first. - if (SectionName == ".fini" || SectionName == ".init" || - SectionName == ".rodata") + if (hasPrefix(SectionName, ".rodata.") || SectionName == ".rodata1") Flags |= ELF::SHF_ALLOC; - if (SectionName == ".fini" || SectionName == ".init") - Flags |= ELF::SHF_EXECINSTR; + if (SectionName == ".fini" || SectionName == ".init" || + hasPrefix(SectionName, ".text.")) + Flags |= ELF::SHF_ALLOC | ELF::SHF_EXECINSTR; + if (hasPrefix(SectionName, ".data.") || SectionName == ".data1" || + hasPrefix(SectionName, ".bss.") || + hasPrefix(SectionName, ".init_array.") || + hasPrefix(SectionName, ".fini_array.") || + hasPrefix(SectionName, ".preinit_array.")) + Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE; + if (hasPrefix(SectionName, ".tdata.") || + hasPrefix(SectionName, ".tbss.")) + Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_TLS; if (getLexer().is(AsmToken::Comma)) { Lex(); @@ -422,65 +542,30 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) { return TokError("Section cannot specifiy a group name while also acting " "as a member of the last group"); - if (getLexer().isNot(AsmToken::Comma)) { + 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"); - } else { - Lex(); - if (getLexer().is(AsmToken::At) || getLexer().is(AsmToken::Percent) || - getLexer().is(AsmToken::String)) { - if (!getLexer().is(AsmToken::String)) - Lex(); - } else - return TokError("expected '@<type>', '%<type>' or \"<type>\""); - - if (getParser().parseIdentifier(TypeName)) - return TokError("expected identifier in directive"); - - if (Mergeable) { - 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"); - } - - if (Group) { - if (getLexer().isNot(AsmToken::Comma)) - return TokError("expected group name"); - Lex(); - if (getParser().parseIdentifier(GroupName)) - return true; - if (getLexer().is(AsmToken::Comma)) { - Lex(); - StringRef Linkage; - if (getParser().parseIdentifier(Linkage)) - return true; - if (Linkage != "comdat") - return TokError("Linkage must be 'comdat'"); - } - } - if (getLexer().is(AsmToken::Comma)) { - Lex(); - if (getParser().parseIdentifier(UniqueStr)) - return TokError("expected identifier in directive"); - if (UniqueStr != "unique") - return TokError("expected 'unique'"); - if (getLexer().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"); - } + 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: @@ -493,11 +578,15 @@ EndStmt: if (TypeName.empty()) { if (SectionName.startswith(".note")) Type = ELF::SHT_NOTE; - else if (SectionName == ".init_array") + else if (hasPrefix(SectionName, ".init_array.")) Type = ELF::SHT_INIT_ARRAY; - else if (SectionName == ".fini_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 (SectionName == ".preinit_array") + else if (hasPrefix(SectionName, ".preinit_array.")) Type = ELF::SHT_PREINIT_ARRAY; } else { if (TypeName == "init_array") @@ -514,7 +603,9 @@ EndStmt: Type = ELF::SHT_NOTE; else if (TypeName == "unwind") Type = ELF::SHT_X86_64_UNWIND; - else + else if (TypeName == "llvm_odrtab") + Type = ELF::SHT_LLVM_ODRTAB; + else if (TypeName.getAsInteger(0, Type)) return TokError("unknown section type"); } @@ -528,8 +619,9 @@ EndStmt: } } - MCSection *ELFSection = getContext().getELFSection(SectionName, Type, Flags, - Size, GroupName, UniqueID); + MCSection *ELFSection = + getContext().getELFSection(SectionName, Type, Flags, Size, GroupName, + UniqueID, Associated); getStreamer().SwitchSection(ELFSection, Subsection); if (getContext().getGenDwarfForAssembly()) { @@ -677,6 +769,7 @@ bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) { const MCExpr *Value = MCSymbolRefExpr::create(Sym, getContext()); getStreamer().EmitAssignment(Alias, Value); + getStreamer().emitELFSymverDirective(Alias, Sym); return false; } @@ -752,4 +845,4 @@ 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 index 63c0dab..8f845ee 100644 --- a/contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp +++ b/contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp @@ -1,4 +1,4 @@ -//===-- MCAsmLexer.cpp - Abstract Asm Lexer Interface ---------------------===// +//===- MCAsmLexer.cpp - Abstract Asm Lexer Interface ----------------------===// // // The LLVM Compiler Infrastructure // @@ -8,18 +8,16 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCParser/MCAsmLexer.h" -#include "llvm/Support/SourceMgr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/SMLoc.h" using namespace llvm; -MCAsmLexer::MCAsmLexer() - : TokStart(nullptr), SkipSpace(true), IsAtStartOfStatement(true), - CommentConsumer(nullptr) { +MCAsmLexer::MCAsmLexer() : AltMacroMode(false) { CurTok.emplace_back(AsmToken::Space, StringRef()); } -MCAsmLexer::~MCAsmLexer() { -} +MCAsmLexer::~MCAsmLexer() = default; SMLoc MCAsmLexer::getLoc() const { return SMLoc::getFromPointer(TokStart); diff --git a/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp index 98f4daf..ea36b3b 100644 --- a/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp @@ -8,21 +8,21 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/MC/MCParser/MCTargetAsmParser.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/SMLoc.h" #include "llvm/Support/raw_ostream.h" +#include <cassert> + using namespace llvm; -MCAsmParser::MCAsmParser() - : TargetParser(nullptr), ShowParsedOperands(0), HadError(false), - PendingErrors() {} +MCAsmParser::MCAsmParser() : ShowParsedOperands(0) {} -MCAsmParser::~MCAsmParser() { -} +MCAsmParser::~MCAsmParser() = default; void MCAsmParser::setTargetParser(MCTargetAsmParser &P) { assert(!TargetParser && "Target parser is already initialized!"); @@ -118,10 +118,10 @@ bool MCAsmParser::addErrorSuffix(const Twine &Suffix) { return true; } -bool MCAsmParser::parseMany(std::function<bool()> parseOne, bool hasComma) { +bool MCAsmParser::parseMany(function_ref<bool()> parseOne, bool hasComma) { if (parseOptionalToken(AsmToken::EndOfStatement)) return false; - while (1) { + while (true) { if (parseOne()) return true; if (parseOptionalToken(AsmToken::EndOfStatement)) @@ -137,6 +137,9 @@ bool MCAsmParser::parseExpression(const MCExpr *&Res) { return parseExpression(Res, L); } -LLVM_DUMP_METHOD void MCParsedAsmOperand::dump() const { +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 index 3f25a14..031f473 100644 --- a/contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp +++ b/contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp @@ -1,4 +1,4 @@ -//===-- MCAsmParserExtension.cpp - Asm Parser Hooks -----------------------===// +//===- MCAsmParserExtension.cpp - Asm Parser Hooks ------------------------===// // // The LLVM Compiler Infrastructure // @@ -8,14 +8,12 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCParser/MCAsmParserExtension.h" + using namespace llvm; -MCAsmParserExtension::MCAsmParserExtension() : - BracketExpressionsSupported(false) { -} +MCAsmParserExtension::MCAsmParserExtension() = default; -MCAsmParserExtension::~MCAsmParserExtension() { -} +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 index 14a22c6..64ac82a 100644 --- a/contrib/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp @@ -1,4 +1,4 @@ -//===-- MCTargetAsmParser.cpp - Target Assembly Parser ---------------------==// +//===-- MCTargetAsmParser.cpp - Target Assembly Parser --------------------===// // // The LLVM Compiler Infrastructure // @@ -9,17 +9,14 @@ #include "llvm/MC/MCParser/MCTargetAsmParser.h" #include "llvm/MC/MCContext.h" + using namespace llvm; MCTargetAsmParser::MCTargetAsmParser(MCTargetOptions const &MCOptions, const MCSubtargetInfo &STI) - : AvailableFeatures(0), ParsingInlineAsm(false), MCOptions(MCOptions), - STI(&STI) -{ -} + : MCOptions(MCOptions), STI(&STI) {} -MCTargetAsmParser::~MCTargetAsmParser() { -} +MCTargetAsmParser::~MCTargetAsmParser() = default; MCSubtargetInfo &MCTargetAsmParser::copySTI() { MCSubtargetInfo &STICopy = getContext().getSubtargetCopy(getSTI()); diff --git a/contrib/llvm/lib/MC/MCRegisterInfo.cpp b/contrib/llvm/lib/MC/MCRegisterInfo.cpp index ea117f3..0f76c18 100644 --- a/contrib/llvm/lib/MC/MCRegisterInfo.cpp +++ b/contrib/llvm/lib/MC/MCRegisterInfo.cpp @@ -1,4 +1,4 @@ -//=== MC/MCRegisterInfo.cpp - Target Register Description -------*- C++ -*-===// +//===- MC/MCRegisterInfo.cpp - Target Register Description ----------------===// // // The LLVM Compiler Infrastructure // @@ -12,8 +12,11 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCRegisterInfo.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/ErrorHandling.h" +#include <algorithm> +#include <cassert> +#include <cstdint> using namespace llvm; diff --git a/contrib/llvm/lib/MC/MCSection.cpp b/contrib/llvm/lib/MC/MCSection.cpp index 9064cdf..d141dd6 100644 --- a/contrib/llvm/lib/MC/MCSection.cpp +++ b/contrib/llvm/lib/MC/MCSection.cpp @@ -8,16 +8,17 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCSection.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCAsmInfo.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCFragment.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -using namespace llvm; +#include <algorithm> +#include <utility> -//===----------------------------------------------------------------------===// -// MCSection -//===----------------------------------------------------------------------===// +using namespace llvm; MCSection::MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin) : Begin(Begin), BundleGroupBeforeFirstInst(false), HasInstructions(false), @@ -31,8 +32,7 @@ MCSymbol *MCSection::getEndSymbol(MCContext &Ctx) { bool MCSection::hasEnded() const { return End && End->isInSection(); } -MCSection::~MCSection() { -} +MCSection::~MCSection() = default; void MCSection::setBundleLockState(BundleLockStateType NewState) { if (NewState == NotBundleLocked) { @@ -85,8 +85,9 @@ MCSection::getSubsectionInsertionPoint(unsigned Subsection) { return IP; } -LLVM_DUMP_METHOD void MCSection::dump() { - raw_ostream &OS = llvm::errs(); +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +LLVM_DUMP_METHOD void MCSection::dump() const { + raw_ostream &OS = errs(); OS << "<MCSection"; OS << " Fragments:[\n "; @@ -97,3 +98,4 @@ LLVM_DUMP_METHOD void MCSection::dump() { } OS << "]>"; } +#endif diff --git a/contrib/llvm/lib/MC/MCSectionCOFF.cpp b/contrib/llvm/lib/MC/MCSectionCOFF.cpp index f2dd47d..72a7fc3 100644 --- a/contrib/llvm/lib/MC/MCSectionCOFF.cpp +++ b/contrib/llvm/lib/MC/MCSectionCOFF.cpp @@ -8,14 +8,14 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCSectionCOFF.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" +#include "llvm/BinaryFormat/COFF.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Support/COFF.h" #include "llvm/Support/raw_ostream.h" +#include <cassert> + using namespace llvm; -MCSectionCOFF::~MCSectionCOFF() {} // anchor. +MCSectionCOFF::~MCSectionCOFF() = default; // anchor. // ShouldOmitSectionDirective - Decides whether a '.section' directive // should be printed before the section name @@ -37,10 +37,9 @@ void MCSectionCOFF::setSelection(int Selection) const { Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; } -void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, +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'; @@ -94,7 +93,7 @@ void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, OS << "newest,"; break; default: - assert (0 && "unsupported COFF selection type"); + assert(false && "unsupported COFF selection type"); break; } assert(COMDATSymbol); diff --git a/contrib/llvm/lib/MC/MCSectionELF.cpp b/contrib/llvm/lib/MC/MCSectionELF.cpp index 587b28f..2f4f61a 100644 --- a/contrib/llvm/lib/MC/MCSectionELF.cpp +++ b/contrib/llvm/lib/MC/MCSectionELF.cpp @@ -8,22 +8,22 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCSectionELF.h" +#include "llvm/ADT/Triple.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Support/ELF.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include <cassert> using namespace llvm; -MCSectionELF::~MCSectionELF() {} // anchor. +MCSectionELF::~MCSectionELF() = default; // anchor. // Decides whether a '.section' directive // should be printed before the section name. bool MCSectionELF::ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const { - if (isUnique()) return false; @@ -53,10 +53,9 @@ static void printName(raw_ostream &OS, StringRef Name) { OS << '"'; } -void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, +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) { @@ -104,14 +103,21 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, 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. - if (Flags & ELF::XCORE_SHF_CP_SECTION) - OS << 'c'; - if (Flags & ELF::XCORE_SHF_DP_SECTION) - OS << 'd'; - if (Flags & ELF::SHF_ARM_PURECODE) - OS << 'y'; + Triple::ArchType Arch = T.getArch(); + if (Arch == Triple::xcore) { + if (Flags & ELF::XCORE_SHF_CP_SECTION) + OS << 'c'; + if (Flags & ELF::XCORE_SHF_DP_SECTION) + OS << 'd'; + } else if (Arch == Triple::arm || Arch == Triple::armeb || + Arch == Triple::thumb || Arch == Triple::thumbeb) { + if (Flags & ELF::SHF_ARM_PURECODE) + OS << 'y'; + } OS << '"'; @@ -137,6 +143,15 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, OS << "progbits"; else if (Type == ELF::SHT_X86_64_UNWIND) OS << "unwind"; + else if (Type == ELF::SHT_MIPS_DWARF) + // Print hex value of the flag while we do not have + // any standard symbolic representation of the flag. + OS << "0x7000001e"; + else if (Type == ELF::SHT_LLVM_ODRTAB) + OS << "llvm_odrtab"; + else + report_fatal_error("unsupported type 0x" + Twine::utohexstr(Type) + + " for section " + getSectionName()); if (EntrySize) { assert(Flags & ELF::SHF_MERGE); @@ -149,6 +164,12 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, OS << ",comdat"; } + if (Flags & ELF::SHF_LINK_ORDER) { + assert(AssociatedSymbol); + OS << ","; + printName(OS, AssociatedSymbol->getName()); + } + if (isUnique()) OS << ",unique," << UniqueID; diff --git a/contrib/llvm/lib/MC/MCSectionMachO.cpp b/contrib/llvm/lib/MC/MCSectionMachO.cpp index c2a772f..f402372 100644 --- a/contrib/llvm/lib/MC/MCSectionMachO.cpp +++ b/contrib/llvm/lib/MC/MCSectionMachO.cpp @@ -16,45 +16,57 @@ 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 const struct { - StringRef AssemblerName, EnumName; -} SectionTypeDescriptors[MachO::LAST_KNOWN_SECTION_TYPE+1] = { - { "regular", "S_REGULAR" }, // 0x00 - { StringRef(), "S_ZEROFILL" }, // 0x01 - { "cstring_literals", "S_CSTRING_LITERALS" }, // 0x02 - { "4byte_literals", "S_4BYTE_LITERALS" }, // 0x03 - { "8byte_literals", "S_8BYTE_LITERALS" }, // 0x04 - { "literal_pointers", "S_LITERAL_POINTERS" }, // 0x05 - { "non_lazy_symbol_pointers", "S_NON_LAZY_SYMBOL_POINTERS" }, // 0x06 - { "lazy_symbol_pointers", "S_LAZY_SYMBOL_POINTERS" }, // 0x07 - { "symbol_stubs", "S_SYMBOL_STUBS" }, // 0x08 - { "mod_init_funcs", "S_MOD_INIT_FUNC_POINTERS" }, // 0x09 - { "mod_term_funcs", "S_MOD_TERM_FUNC_POINTERS" }, // 0x0A - { "coalesced", "S_COALESCED" }, // 0x0B - { StringRef(), /*FIXME??*/ "S_GB_ZEROFILL" }, // 0x0C - { "interposing", "S_INTERPOSING" }, // 0x0D - { "16byte_literals", "S_16BYTE_LITERALS" }, // 0x0E - { StringRef(), /*FIXME??*/ "S_DTRACE_DOF" }, // 0x0F - { StringRef(), /*FIXME??*/ "S_LAZY_DYLIB_SYMBOL_POINTERS" }, // 0x10 - { "thread_local_regular", "S_THREAD_LOCAL_REGULAR" }, // 0x11 - { "thread_local_zerofill", "S_THREAD_LOCAL_ZEROFILL" }, // 0x12 - { "thread_local_variables", "S_THREAD_LOCAL_VARIABLES" }, // 0x13 - { "thread_local_variable_pointers", - "S_THREAD_LOCAL_VARIABLE_POINTERS" }, // 0x14 - { "thread_local_init_function_pointers", - "S_THREAD_LOCAL_INIT_FUNCTION_POINTERS"}, // 0x15 +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 const struct { +static constexpr struct { unsigned AttrFlag; - StringRef AssemblerName, EnumName; + StringLiteral AssemblerName, EnumName; } SectionAttrDescriptors[] = { #define ENTRY(ASMNAME, ENUM) \ - { MachO::ENUM, 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) @@ -62,11 +74,11 @@ 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(StringRef() /*FIXME*/, S_ATTR_SOME_INSTRUCTIONS) -ENTRY(StringRef() /*FIXME*/, S_ATTR_EXT_RELOC) -ENTRY(StringRef() /*FIXME*/, S_ATTR_LOC_RELOC) +ENTRY("" /*FIXME*/, S_ATTR_SOME_INSTRUCTIONS) +ENTRY("" /*FIXME*/, S_ATTR_EXT_RELOC) +ENTRY("" /*FIXME*/, S_ATTR_LOC_RELOC) #undef ENTRY - { 0, "none", StringRef() }, // used if section has no attributes but has a stub size + { 0, StringLiteral("none"), StringLiteral("") }, // used if section has no attributes but has a stub size }; MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section, @@ -89,7 +101,7 @@ MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section, } } -void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI, +void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, raw_ostream &OS, const MCExpr *Subsection) const { OS << "\t.section\t" << getSegmentName() << ',' << getSectionName(); diff --git a/contrib/llvm/lib/MC/MCSectionWasm.cpp b/contrib/llvm/lib/MC/MCSectionWasm.cpp new file mode 100644 index 0000000..c61f28e --- /dev/null +++ b/contrib/llvm/lib/MC/MCSectionWasm.cpp @@ -0,0 +1,97 @@ +//===- lib/MC/MCSectionWasm.cpp - Wasm Code Section Representation --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCSectionWasm.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +MCSectionWasm::~MCSectionWasm() {} // anchor. + +// Decides whether a '.section' directive +// should be printed before the section name. +bool MCSectionWasm::ShouldOmitSectionDirective(StringRef Name, + const MCAsmInfo &MAI) const { + return MAI.shouldOmitSectionDirective(Name); +} + +static void printName(raw_ostream &OS, StringRef Name) { + if (Name.find_first_not_of("0123456789_." + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == Name.npos) { + OS << Name; + return; + } + OS << '"'; + for (const char *B = Name.begin(), *E = Name.end(); B < E; ++B) { + if (*B == '"') // Unquoted " + OS << "\\\""; + else if (*B != '\\') // Neither " or backslash + OS << *B; + else if (B + 1 == E) // Trailing backslash + OS << "\\\\"; + else { + OS << B[0] << B[1]; // Quoted character + ++B; + } + } + OS << '"'; +} + +void MCSectionWasm::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, + raw_ostream &OS, + const MCExpr *Subsection) const { + + if (ShouldOmitSectionDirective(SectionName, MAI)) { + OS << '\t' << getSectionName(); + if (Subsection) { + OS << '\t'; + Subsection->print(OS, &MAI); + } + OS << '\n'; + return; + } + + OS << "\t.section\t"; + printName(OS, getSectionName()); + OS << ",\""; + + // TODO: Print section flags. + + OS << '"'; + + OS << ','; + + // If comment string is '@', e.g. as on ARM - use '%' instead + if (MAI.getCommentString()[0] == '@') + OS << '%'; + else + OS << '@'; + + // TODO: Print section type. + + if (isUnique()) + OS << ",unique," << UniqueID; + + OS << '\n'; + + if (Subsection) { + OS << "\t.subsection\t"; + Subsection->print(OS, &MAI); + OS << '\n'; + } +} + +bool MCSectionWasm::UseCodeAlign() const { return false; } + +bool MCSectionWasm::isVirtualSection() const { return false; } diff --git a/contrib/llvm/lib/MC/MCStreamer.cpp b/contrib/llvm/lib/MC/MCStreamer.cpp index fb28f85..2bfb9a6 100644 --- a/contrib/llvm/lib/MC/MCStreamer.cpp +++ b/contrib/llvm/lib/MC/MCStreamer.cpp @@ -9,34 +9,42 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/BinaryFormat/COFF.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCCodeView.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCWin64EH.h" -#include "llvm/Support/COFF.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> -using namespace llvm; +#include <utility> -// Pin the vtables to this file. -MCTargetStreamer::~MCTargetStreamer() {} +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() {} @@ -290,10 +298,17 @@ void MCStreamer::AssignFragment(MCSymbol *Symbol, MCFragment *Fragment) { SymbolOrdering[Symbol] = 1 + SymbolOrdering.size(); } -void MCStreamer::EmitLabel(MCSymbol *Symbol) { +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(); @@ -666,7 +681,7 @@ void MCStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) { void MCStreamer::EmitWinCFIPushFrame(bool Code) { EnsureValidWinFrameInfo(); - if (CurrentWinFrameInfo->Instructions.size() > 0) + if (!CurrentWinFrameInfo->Instructions.empty()) report_fatal_error("If present, PushMachFrame must be the first UOP"); MCSymbol *Label = EmitCFILabel(); @@ -762,8 +777,8 @@ void MCStreamer::visitUsedExpr(const MCExpr &Expr) { } } -void MCStreamer::EmitInstruction(const MCInst &Inst, - const MCSubtargetInfo &STI) { +void MCStreamer::EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, + bool) { // Scan for values. for (unsigned i = Inst.getNumOperands(); i--;) if (Inst.getOperand(i).isExpr()) @@ -792,12 +807,22 @@ void MCStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, void MCStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {} void MCStreamer::EmitThumbFunc(MCSymbol *Func) {} void MCStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {} -void MCStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) {} -void MCStreamer::EndCOFFSymbolDef() {} +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) {} -void MCStreamer::EmitCOFFSymbolType(int Type) {} +void MCStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { + llvm_unreachable("this directive only supported on COFF targets"); +} +void MCStreamer::EmitCOFFSymbolType(int Type) { + llvm_unreachable("this directive only supported on COFF targets"); +} void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {} +void MCStreamer::emitELFSymverDirective(MCSymbol *Alias, + const MCSymbol *Aliasee) {} void MCStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) {} void MCStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, diff --git a/contrib/llvm/lib/MC/MCSubtargetInfo.cpp b/contrib/llvm/lib/MC/MCSubtargetInfo.cpp index 1b59250..385cdcc 100644 --- a/contrib/llvm/lib/MC/MCSubtargetInfo.cpp +++ b/contrib/llvm/lib/MC/MCSubtargetInfo.cpp @@ -1,4 +1,4 @@ -//===-- MCSubtargetInfo.cpp - Subtarget Information -----------------------===// +//===- MCSubtargetInfo.cpp - Subtarget Information ------------------------===// // // The LLVM Compiler Infrastructure // @@ -8,12 +8,15 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" #include "llvm/MC/MCInstrItineraries.h" +#include "llvm/MC/MCSchedule.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> +#include <cassert> +#include <cstring> using namespace llvm; diff --git a/contrib/llvm/lib/MC/MCSymbol.cpp b/contrib/llvm/lib/MC/MCSymbol.cpp index 20d985d..9abaaef 100644 --- a/contrib/llvm/lib/MC/MCSymbol.cpp +++ b/contrib/llvm/lib/MC/MCSymbol.cpp @@ -8,12 +8,18 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCSymbol.h" +#include "llvm/ADT/StringRef.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFragment.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstddef> + using namespace llvm; // Only the address of this fragment is ever actually used. @@ -75,4 +81,8 @@ void MCSymbol::print(raw_ostream &OS, const MCAsmInfo *MAI) const { OS << '"'; } -LLVM_DUMP_METHOD void MCSymbol::dump() const { dbgs() << *this; } +#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 index ec7ef44..67449eb 100644 --- a/contrib/llvm/lib/MC/MCSymbolELF.cpp +++ b/contrib/llvm/lib/MC/MCSymbolELF.cpp @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCSymbolELF.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCFixupKindInfo.h" -#include "llvm/Support/ELF.h" namespace llvm { @@ -42,6 +42,8 @@ enum { 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: @@ -93,6 +95,8 @@ unsigned MCSymbolELF::getBinding() const { 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"); diff --git a/contrib/llvm/lib/MC/MCTargetOptions.cpp b/contrib/llvm/lib/MC/MCTargetOptions.cpp index 4192105..b85e53d 100644 --- a/contrib/llvm/lib/MC/MCTargetOptions.cpp +++ b/contrib/llvm/lib/MC/MCTargetOptions.cpp @@ -1,4 +1,4 @@ -//===- lib/MC/MCTargetOptions.cpp - MC Target Options --------------------===// +//===- lib/MC/MCTargetOptions.cpp - MC Target Options ---------------------===// // // The LLVM Compiler Infrastructure // @@ -7,22 +7,19 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/StringRef.h" #include "llvm/MC/MCTargetOptions.h" +#include "llvm/ADT/StringRef.h" -namespace llvm { +using namespace llvm; MCTargetOptions::MCTargetOptions() : SanitizeAddress(false), MCRelaxAll(false), MCNoExecStack(false), MCFatalWarnings(false), MCNoWarn(false), MCNoDeprecatedWarn(false), - MCSaveTempLabels(false), - MCUseDwarfDirectory(false), MCIncrementalLinkerCompatible(false), - MCPIECopyRelocations(false), ShowMCEncoding(false), - ShowMCInst(false), AsmVerbose(false), - PreserveAsmComments(true), DwarfVersion(0), ABIName() {} + MCSaveTempLabels(false), MCUseDwarfDirectory(false), + MCIncrementalLinkerCompatible(false), MCPIECopyRelocations(false), + ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false), + PreserveAsmComments(true) {} StringRef MCTargetOptions::getABIName() const { return ABIName; } - -} // end namespace llvm diff --git a/contrib/llvm/lib/MC/MCValue.cpp b/contrib/llvm/lib/MC/MCValue.cpp index c1336d6..32a6adb 100644 --- a/contrib/llvm/lib/MC/MCValue.cpp +++ b/contrib/llvm/lib/MC/MCValue.cpp @@ -37,9 +37,11 @@ void MCValue::print(raw_ostream &OS) const { 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(); diff --git a/contrib/llvm/lib/MC/MCWasmObjectTargetWriter.cpp b/contrib/llvm/lib/MC/MCWasmObjectTargetWriter.cpp new file mode 100644 index 0000000..301f30d --- /dev/null +++ b/contrib/llvm/lib/MC/MCWasmObjectTargetWriter.cpp @@ -0,0 +1,21 @@ +//===-- MCWasmObjectTargetWriter.cpp - Wasm Target Writer Subclass --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/STLExtras.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCValue.h" +#include "llvm/MC/MCWasmObjectWriter.h" + +using namespace llvm; + +MCWasmObjectTargetWriter::MCWasmObjectTargetWriter(bool Is64Bit_) + : Is64Bit(Is64Bit_) {} + +// Pin the vtable to this object file +MCWasmObjectTargetWriter::~MCWasmObjectTargetWriter() = default; diff --git a/contrib/llvm/lib/MC/MCWasmStreamer.cpp b/contrib/llvm/lib/MC/MCWasmStreamer.cpp new file mode 100644 index 0000000..02fa070 --- /dev/null +++ b/contrib/llvm/lib/MC/MCWasmStreamer.cpp @@ -0,0 +1,228 @@ +//===- lib/MC/MCWasmStreamer.cpp - Wasm Object Output ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file assembles .s files and emits Wasm .o object files. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCWasmStreamer.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSectionWasm.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCSymbolWasm.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +MCWasmStreamer::~MCWasmStreamer() {} + +void MCWasmStreamer::mergeFragment(MCDataFragment *DF, MCDataFragment *EF) { + flushPendingLabels(DF, DF->getContents().size()); + + for (unsigned i = 0, e = EF->getFixups().size(); i != e; ++i) { + EF->getFixups()[i].setOffset(EF->getFixups()[i].getOffset() + + DF->getContents().size()); + DF->getFixups().push_back(EF->getFixups()[i]); + } + DF->setHasInstructions(true); + DF->getContents().append(EF->getContents().begin(), EF->getContents().end()); +} + +void MCWasmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { + // Let the target do whatever target specific stuff it needs to do. + getAssembler().getBackend().handleAssemblerFlag(Flag); + + // Do any generic stuff we need to do. + llvm_unreachable("invalid assembler flag!"); +} + +void MCWasmStreamer::ChangeSection(MCSection *Section, + const MCExpr *Subsection) { + MCAssembler &Asm = getAssembler(); + auto *SectionWasm = static_cast<const MCSectionWasm *>(Section); + const MCSymbol *Grp = SectionWasm->getGroup(); + if (Grp) + Asm.registerSymbol(*Grp); + + this->MCObjectStreamer::ChangeSection(Section, Subsection); +} + +void MCWasmStreamer::EmitWeakReference(MCSymbol *Alias, + const MCSymbol *Symbol) { + getAssembler().registerSymbol(*Symbol); + const MCExpr *Value = MCSymbolRefExpr::create( + Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext()); + Alias->setVariableValue(Value); +} + +bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) { + assert(Attribute != MCSA_IndirectSymbol && "indirect symbols not supported"); + + auto *Symbol = cast<MCSymbolWasm>(S); + + // Adding a symbol attribute always introduces the symbol, note that an + // important side effect of calling registerSymbol here is to register + // the symbol with the assembler. + getAssembler().registerSymbol(*Symbol); + + switch (Attribute) { + case MCSA_LazyReference: + case MCSA_Reference: + case MCSA_SymbolResolver: + case MCSA_PrivateExtern: + case MCSA_WeakDefinition: + case MCSA_WeakDefAutoPrivate: + case MCSA_Invalid: + case MCSA_IndirectSymbol: + case MCSA_Hidden: + return false; + + case MCSA_Weak: + case MCSA_WeakReference: + Symbol->setWeak(true); + Symbol->setExternal(true); + break; + + case MCSA_Global: + Symbol->setExternal(true); + break; + + case MCSA_ELF_TypeFunction: + Symbol->setIsFunction(true); + break; + + case MCSA_ELF_TypeObject: + Symbol->setIsFunction(false); + break; + + default: + // unrecognized directive + llvm_unreachable("unexpected MCSymbolAttr"); + return false; + } + + return true; +} + +void MCWasmStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size, + unsigned ByteAlignment) { + llvm_unreachable("Common symbols are not yet implemented for Wasm"); +} + +void MCWasmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) { + cast<MCSymbolWasm>(Symbol)->setSize(Value); +} + +void MCWasmStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size, + unsigned ByteAlignment) { + llvm_unreachable("Local common symbols are not yet implemented for Wasm"); +} + +void MCWasmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, + SMLoc Loc) { + MCObjectStreamer::EmitValueImpl(Value, Size, Loc); +} + +void MCWasmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, + unsigned ValueSize, + unsigned MaxBytesToEmit) { + MCObjectStreamer::EmitValueToAlignment(ByteAlignment, Value, ValueSize, + MaxBytesToEmit); +} + +void MCWasmStreamer::EmitIdent(StringRef IdentString) { + MCSection *Comment = getAssembler().getContext().getWasmSection( + ".comment", 0, 0); + PushSection(); + SwitchSection(Comment); + if (!SeenIdent) { + EmitIntValue(0, 1); + SeenIdent = true; + } + EmitBytes(IdentString); + EmitIntValue(0, 1); + PopSection(); +} + +void MCWasmStreamer::EmitInstToFragment(const MCInst &Inst, + const MCSubtargetInfo &STI) { + this->MCObjectStreamer::EmitInstToFragment(Inst, STI); +} + +void MCWasmStreamer::EmitInstToData(const MCInst &Inst, + const MCSubtargetInfo &STI) { + MCAssembler &Assembler = getAssembler(); + SmallVector<MCFixup, 4> Fixups; + SmallString<256> Code; + raw_svector_ostream VecOS(Code); + Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); + + // Append the encoded instruction to the current data fragment (or create a + // new such fragment if the current fragment is not a data fragment). + MCDataFragment *DF = getOrCreateDataFragment(); + + // Add the fixups and data. + for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { + Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); + DF->getFixups().push_back(Fixups[i]); + } + DF->setHasInstructions(true); + DF->getContents().append(Code.begin(), Code.end()); +} + +void MCWasmStreamer::FinishImpl() { + EmitFrames(nullptr); + + this->MCObjectStreamer::FinishImpl(); +} + +MCStreamer *llvm::createWasmStreamer(MCContext &Context, MCAsmBackend &MAB, + raw_pwrite_stream &OS, MCCodeEmitter *CE, + bool RelaxAll) { + MCWasmStreamer *S = new MCWasmStreamer(Context, MAB, OS, CE); + if (RelaxAll) + S->getAssembler().setRelaxAll(true); + return S; +} + +void MCWasmStreamer::EmitThumbFunc(MCSymbol *Func) { + llvm_unreachable("Generic Wasm doesn't support this directive"); +} + +void MCWasmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { + llvm_unreachable("Wasm doesn't support this directive"); +} + +void MCWasmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment) { + llvm_unreachable("Wasm doesn't support this directive"); +} + +void MCWasmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment) { + llvm_unreachable("Wasm doesn't support this directive"); +} diff --git a/contrib/llvm/lib/MC/WinCOFFStreamer.cpp b/contrib/llvm/lib/MC/MCWinCOFFStreamer.cpp index 6383d87..bf341bb 100644 --- a/contrib/llvm/lib/MC/WinCOFFStreamer.cpp +++ b/contrib/llvm/lib/MC/MCWinCOFFStreamer.cpp @@ -1,4 +1,4 @@ -//===-- llvm/MC/WinCOFFStreamer.cpp -----------------------------*- C++ -*-===// +//===- llvm/MC/MCWinCOFFStreamer.cpp --------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -11,32 +11,36 @@ // //===----------------------------------------------------------------------===// +#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/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/MCFixup.h" +#include "llvm/MC/MCFragment.h" #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSectionCOFF.h" -#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbolCOFF.h" -#include "llvm/MC/MCValue.h" #include "llvm/MC/MCWinCOFFStreamer.h" -#include "llvm/Support/COFF.h" -#include "llvm/Support/Debug.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/TargetRegistry.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" -namespace llvm { MCWinCOFFStreamer::MCWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, MCCodeEmitter &CE, raw_pwrite_stream &OS) : MCObjectStreamer(Context, MAB, OS, &CE), CurSymbol(nullptr) {} @@ -75,10 +79,9 @@ void MCWinCOFFStreamer::InitSections(bool NoExecStack) { SwitchSection(getContext().getObjectFileInfo()->getTextSection()); } -void MCWinCOFFStreamer::EmitLabel(MCSymbol *S) { +void MCWinCOFFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) { auto *Symbol = cast<MCSymbolCOFF>(S); - assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - MCObjectStreamer::EmitLabel(Symbol); + MCObjectStreamer::EmitLabel(Symbol, Loc); } void MCWinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { @@ -187,7 +190,8 @@ void MCWinCOFFStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) { << COFF::SCT_COMPLEX_TYPE_SHIFT); } -void MCWinCOFFStreamer::EmitCOFFSectionIndex(MCSymbol const *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); @@ -195,8 +199,9 @@ void MCWinCOFFStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { DF->getContents().resize(DF->getContents().size() + 2, 0); } -void MCWinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, +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()); @@ -275,10 +280,6 @@ void MCWinCOFFStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, llvm_unreachable("not implemented"); } -void MCWinCOFFStreamer::EmitFileDirective(StringRef Filename) { - getAssembler().addFileName(Filename); -} - // TODO: Implement this if you want to emit .comment section in COFF obj files. void MCWinCOFFStreamer::EmitIdent(StringRef IdentString) { llvm_unreachable("not implemented"); @@ -295,5 +296,3 @@ void MCWinCOFFStreamer::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 index 21a9139..a5d0f5a 100644 --- a/contrib/llvm/lib/MC/MCWinEH.cpp +++ b/contrib/llvm/lib/MC/MCWinEH.cpp @@ -7,14 +7,14 @@ // //===----------------------------------------------------------------------===// +#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" -#include "llvm/MC/MCWinEH.h" -#include "llvm/Support/COFF.h" namespace llvm { namespace WinEH { diff --git a/contrib/llvm/lib/MC/MachObjectWriter.cpp b/contrib/llvm/lib/MC/MachObjectWriter.cpp index c4b35f5..62bf0a5 100644 --- a/contrib/llvm/lib/MC/MachObjectWriter.cpp +++ b/contrib/llvm/lib/MC/MachObjectWriter.cpp @@ -7,23 +7,36 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCMachObjectWriter.h" -#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Twine.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/MachO.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/MC/MCFragment.h" +#include "llvm/MC/MCMachObjectWriter.h" #include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbolMachO.h" #include "llvm/MC/MCValue.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MachO.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" @@ -436,7 +449,7 @@ void MachObjectWriter::recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, - bool &IsPCRel, uint64_t &FixedValue) { + uint64_t &FixedValue) { TargetObjectWriter->recordRelocation(this, Asm, Layout, Fragment, Fixup, Target, FixedValue); } diff --git a/contrib/llvm/lib/MC/StringTableBuilder.cpp b/contrib/llvm/lib/MC/StringTableBuilder.cpp index 1a501bc..6025a20 100644 --- a/contrib/llvm/lib/MC/StringTableBuilder.cpp +++ b/contrib/llvm/lib/MC/StringTableBuilder.cpp @@ -1,4 +1,4 @@ -//===-- StringTableBuilder.cpp - String table building utility ------------===// +//===- StringTableBuilder.cpp - String table building utility -------------===// // // The LLVM Compiler Infrastructure // @@ -8,17 +8,23 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/StringTableBuilder.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/SmallString.h" -#include "llvm/Support/COFF.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() {} +StringTableBuilder::~StringTableBuilder() = default; void StringTableBuilder::initSize() { // Account for leading bytes in table so that offsets returned from add are @@ -48,11 +54,11 @@ void StringTableBuilder::write(raw_ostream &OS) const { assert(isFinalized()); SmallString<0> Data; Data.resize(getSize()); - write((uint8_t *)&Data[0]); + write((uint8_t *)Data.data()); OS << Data; } -typedef std::pair<CachedHashStringRef, size_t> StringPair; +using StringPair = std::pair<CachedHashStringRef, size_t>; void StringTableBuilder::write(uint8_t *Buf) const { assert(isFinalized()); diff --git a/contrib/llvm/lib/MC/SubtargetFeature.cpp b/contrib/llvm/lib/MC/SubtargetFeature.cpp index 32f06f8..b68e88c 100644 --- a/contrib/llvm/lib/MC/SubtargetFeature.cpp +++ b/contrib/llvm/lib/MC/SubtargetFeature.cpp @@ -7,28 +7,31 @@ // //===----------------------------------------------------------------------===// // -// This file implements the SubtargetFeature interface. +/// \file Implements the SubtargetFeature interface. // //===----------------------------------------------------------------------===// #include "llvm/MC/SubtargetFeature.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> -#include <cctype> -#include <cstdlib> -using namespace llvm; +#include <cstddef> +#include <cstring> +#include <iterator> +#include <string> +#include <vector> -//===----------------------------------------------------------------------===// -// Static Helper Functions -//===----------------------------------------------------------------------===// +using namespace llvm; -/// hasFlag - Determine if a feature has a flag; '+' or '-' -/// +/// Determine if a feature has a flag; '+' or '-' static inline bool hasFlag(StringRef Feature) { assert(!Feature.empty() && "Empty string"); // Get first character @@ -37,14 +40,12 @@ static inline bool hasFlag(StringRef Feature) { return Ch == '+' || Ch =='-'; } -/// StripFlag - Return string stripped of flag. -/// +/// Return string stripped of flag. static inline std::string StripFlag(StringRef Feature) { return hasFlag(Feature) ? Feature.substr(1) : Feature; } -/// isEnabled - Return true if enable flag; '+'. -/// +/// Return true if enable flag; '+'. static inline bool isEnabled(StringRef Feature) { assert(!Feature.empty() && "Empty string"); // Get first character @@ -53,15 +54,13 @@ static inline bool isEnabled(StringRef Feature) { return Ch == '+'; } -/// Split - Splits a string of comma separated items in to a vector of strings. -/// +/// Splits a string of comma separated items in to a vector of strings. static void Split(std::vector<std::string> &V, StringRef S) { SmallVector<StringRef, 3> Tmp; S.split(Tmp, ',', -1, false /* KeepEmpty */); V.assign(Tmp.begin(), Tmp.end()); } -/// Adding features. void SubtargetFeatures::AddFeature(StringRef String, bool Enable) { // Don't add empty features. if (!String.empty()) @@ -81,8 +80,7 @@ static const SubtargetFeatureKV *Find(StringRef S, return F; } -/// getLongestEntryLength - Return the length of the longest entry in the table. -/// +/// Return the length of the longest entry in the table. static size_t getLongestEntryLength(ArrayRef<SubtargetFeatureKV> Table) { size_t MaxLen = 0; for (auto &I : Table) @@ -91,7 +89,6 @@ static size_t getLongestEntryLength(ArrayRef<SubtargetFeatureKV> Table) { } /// Display help for feature choices. -/// static void Help(ArrayRef<SubtargetFeatureKV> CPUTable, ArrayRef<SubtargetFeatureKV> FeatTable) { // Determine the length of the longest CPU and Feature entries. @@ -114,58 +111,47 @@ static void Help(ArrayRef<SubtargetFeatureKV> CPUTable, "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n"; } -//===----------------------------------------------------------------------===// -// SubtargetFeatures Implementation -//===----------------------------------------------------------------------===// - SubtargetFeatures::SubtargetFeatures(StringRef Initial) { // Break up string into separate features Split(Features, Initial); } - std::string SubtargetFeatures::getString() const { return join(Features.begin(), Features.end(), ","); } -/// SetImpliedBits - For each feature that is (transitively) implied by this -/// feature, set it. -/// +/// For each feature that is (transitively) implied by this feature, set it. static -void SetImpliedBits(FeatureBitset &Bits, const SubtargetFeatureKV *FeatureEntry, +void SetImpliedBits(FeatureBitset &Bits, const SubtargetFeatureKV &FeatureEntry, ArrayRef<SubtargetFeatureKV> FeatureTable) { - for (auto &FE : FeatureTable) { - if (FeatureEntry->Value == FE.Value) continue; + for (const SubtargetFeatureKV &FE : FeatureTable) { + if (FeatureEntry.Value == FE.Value) continue; - if ((FeatureEntry->Implies & FE.Value).any()) { + if ((FeatureEntry.Implies & FE.Value).any()) { Bits |= FE.Value; - SetImpliedBits(Bits, &FE, FeatureTable); + SetImpliedBits(Bits, FE, FeatureTable); } } } -/// ClearImpliedBits - For each feature that (transitively) implies this -/// feature, clear it. -/// +/// For each feature that (transitively) implies this feature, clear it. static -void ClearImpliedBits(FeatureBitset &Bits, - const SubtargetFeatureKV *FeatureEntry, +void ClearImpliedBits(FeatureBitset &Bits, + const SubtargetFeatureKV &FeatureEntry, ArrayRef<SubtargetFeatureKV> FeatureTable) { - for (auto &FE : FeatureTable) { - if (FeatureEntry->Value == FE.Value) continue; + for (const SubtargetFeatureKV &FE : FeatureTable) { + if (FeatureEntry.Value == FE.Value) continue; - if ((FE.Implies & FeatureEntry->Value).any()) { + if ((FE.Implies & FeatureEntry.Value).any()) { Bits &= ~FE.Value; - ClearImpliedBits(Bits, &FE, FeatureTable); + ClearImpliedBits(Bits, FE, FeatureTable); } } } -/// ToggleFeature - Toggle a feature and update the feature bits. void SubtargetFeatures::ToggleFeature(FeatureBitset &Bits, StringRef Feature, ArrayRef<SubtargetFeatureKV> FeatureTable) { - // Find feature in table. const SubtargetFeatureKV *FeatureEntry = Find(StripFlag(Feature), FeatureTable); @@ -174,23 +160,21 @@ SubtargetFeatures::ToggleFeature(FeatureBitset &Bits, StringRef Feature, if ((Bits & FeatureEntry->Value) == FeatureEntry->Value) { Bits &= ~FeatureEntry->Value; // For each feature that implies this, clear it. - ClearImpliedBits(Bits, FeatureEntry, FeatureTable); + ClearImpliedBits(Bits, *FeatureEntry, FeatureTable); } else { Bits |= FeatureEntry->Value; // For each feature that this implies, set it. - SetImpliedBits(Bits, FeatureEntry, FeatureTable); + SetImpliedBits(Bits, *FeatureEntry, FeatureTable); } } else { - errs() << "'" << Feature - << "' is not a recognized feature for this target" + errs() << "'" << Feature << "' is not a recognized feature for this target" << " (ignoring feature)\n"; } } void SubtargetFeatures::ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature, ArrayRef<SubtargetFeatureKV> FeatureTable) { - assert(hasFlag(Feature)); // Find feature in table. @@ -203,37 +187,30 @@ void SubtargetFeatures::ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature, Bits |= FeatureEntry->Value; // For each feature that this implies, set it. - SetImpliedBits(Bits, FeatureEntry, FeatureTable); + SetImpliedBits(Bits, *FeatureEntry, FeatureTable); } else { Bits &= ~FeatureEntry->Value; // For each feature that implies this, clear it. - ClearImpliedBits(Bits, FeatureEntry, FeatureTable); + ClearImpliedBits(Bits, *FeatureEntry, FeatureTable); } } else { - errs() << "'" << Feature - << "' is not a recognized feature for this target" + errs() << "'" << Feature << "' is not a recognized feature for this target" << " (ignoring feature)\n"; } } - -/// getFeatureBits - Get feature bits a CPU. -/// FeatureBitset SubtargetFeatures::getFeatureBits(StringRef CPU, ArrayRef<SubtargetFeatureKV> CPUTable, ArrayRef<SubtargetFeatureKV> FeatureTable) { - if (CPUTable.empty() || FeatureTable.empty()) return FeatureBitset(); -#ifndef NDEBUG assert(std::is_sorted(std::begin(CPUTable), std::end(CPUTable)) && "CPU table is not sorted"); assert(std::is_sorted(std::begin(FeatureTable), std::end(FeatureTable)) && "CPU features table is not sorted"); -#endif // Resulting bits FeatureBitset Bits; @@ -253,17 +230,16 @@ SubtargetFeatures::getFeatureBits(StringRef CPU, // Set the feature implied by this CPU feature, if any. for (auto &FE : FeatureTable) { if ((CPUEntry->Value & FE.Value).any()) - SetImpliedBits(Bits, &FE, FeatureTable); + SetImpliedBits(Bits, FE, FeatureTable); } } else { - errs() << "'" << CPU - << "' is not a recognized processor for this target" + errs() << "'" << CPU << "' is not a recognized processor for this target" << " (ignoring processor)\n"; } } // Iterate through each feature - for (auto &Feature : Features) { + for (const std::string &Feature : Features) { // Check for help if (Feature == "+help") Help(CPUTable, FeatureTable); @@ -274,27 +250,22 @@ SubtargetFeatures::getFeatureBits(StringRef CPU, return Bits; } -/// print - Print feature string. -/// void SubtargetFeatures::print(raw_ostream &OS) const { for (auto &F : Features) OS << F << " "; OS << "\n"; } -/// dump - Dump feature info. -/// +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void SubtargetFeatures::dump() const { print(dbgs()); } +#endif -/// Adds the default features for the specified target 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>. -/// 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-* diff --git a/contrib/llvm/lib/MC/WasmObjectWriter.cpp b/contrib/llvm/lib/MC/WasmObjectWriter.cpp new file mode 100644 index 0000000..0d31f65 --- /dev/null +++ b/contrib/llvm/lib/MC/WasmObjectWriter.cpp @@ -0,0 +1,1295 @@ +//===- lib/MC/WasmObjectWriter.cpp - Wasm File Writer ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements Wasm object file writer information. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/BinaryFormat/Wasm.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSectionWasm.h" +#include "llvm/MC/MCSymbolWasm.h" +#include "llvm/MC/MCValue.h" +#include "llvm/MC/MCWasmObjectWriter.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/LEB128.h" +#include "llvm/Support/StringSaver.h" +#include <vector> + +using namespace llvm; + +#define DEBUG_TYPE "mc" + +namespace { + +// For patching purposes, we need to remember where each section starts, both +// for patching up the section size field, and for patching up references to +// locations within the section. +struct SectionBookkeeping { + // Where the size of the section is written. + uint64_t SizeOffset; + // Where the contents of the section starts (after the header). + uint64_t ContentsOffset; +}; + +// The signature of a wasm function, in a struct capable of being used as a +// DenseMap key. +struct WasmFunctionType { + // Support empty and tombstone instances, needed by DenseMap. + enum { Plain, Empty, Tombstone } State; + + // The return types of the function. + SmallVector<wasm::ValType, 1> Returns; + + // The parameter types of the function. + SmallVector<wasm::ValType, 4> Params; + + WasmFunctionType() : State(Plain) {} + + bool operator==(const WasmFunctionType &Other) const { + return State == Other.State && Returns == Other.Returns && + Params == Other.Params; + } +}; + +// Traits for using WasmFunctionType in a DenseMap. +struct WasmFunctionTypeDenseMapInfo { + static WasmFunctionType getEmptyKey() { + WasmFunctionType FuncTy; + FuncTy.State = WasmFunctionType::Empty; + return FuncTy; + } + static WasmFunctionType getTombstoneKey() { + WasmFunctionType FuncTy; + FuncTy.State = WasmFunctionType::Tombstone; + return FuncTy; + } + static unsigned getHashValue(const WasmFunctionType &FuncTy) { + uintptr_t Value = FuncTy.State; + for (wasm::ValType Ret : FuncTy.Returns) + Value += DenseMapInfo<int32_t>::getHashValue(int32_t(Ret)); + for (wasm::ValType Param : FuncTy.Params) + Value += DenseMapInfo<int32_t>::getHashValue(int32_t(Param)); + return Value; + } + static bool isEqual(const WasmFunctionType &LHS, + const WasmFunctionType &RHS) { + return LHS == RHS; + } +}; + +// A wasm import to be written into the import section. +struct WasmImport { + StringRef ModuleName; + StringRef FieldName; + unsigned Kind; + int32_t Type; +}; + +// A wasm function to be written into the function section. +struct WasmFunction { + int32_t Type; + const MCSymbolWasm *Sym; +}; + +// A wasm export to be written into the export section. +struct WasmExport { + StringRef FieldName; + unsigned Kind; + uint32_t Index; +}; + +// A wasm global to be written into the global section. +struct WasmGlobal { + wasm::ValType Type; + bool IsMutable; + bool HasImport; + uint64_t InitialValue; + uint32_t ImportIndex; +}; + +// Information about a single relocation. +struct WasmRelocationEntry { + uint64_t Offset; // Where is the relocation. + const MCSymbolWasm *Symbol; // The symbol to relocate with. + int64_t Addend; // A value to add to the symbol. + unsigned Type; // The type of the relocation. + const MCSectionWasm *FixupSection;// The section the relocation is targeting. + + WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol, + int64_t Addend, unsigned Type, + const MCSectionWasm *FixupSection) + : Offset(Offset), Symbol(Symbol), Addend(Addend), Type(Type), + FixupSection(FixupSection) {} + + bool hasAddend() const { + switch (Type) { + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: + return true; + default: + return false; + } + } + + void print(raw_ostream &Out) const { + Out << "Off=" << Offset << ", Sym=" << *Symbol << ", Addend=" << Addend + << ", Type=" << Type << ", FixupSection=" << FixupSection; + } + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + LLVM_DUMP_METHOD void dump() const { print(dbgs()); } +#endif +}; + +#if !defined(NDEBUG) +raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) { + Rel.print(OS); + return OS; +} +#endif + +class WasmObjectWriter : public MCObjectWriter { + /// Helper struct for containing some precomputed information on symbols. + struct WasmSymbolData { + const MCSymbolWasm *Symbol; + StringRef Name; + + // Support lexicographic sorting. + bool operator<(const WasmSymbolData &RHS) const { return Name < RHS.Name; } + }; + + /// The target specific Wasm writer instance. + std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter; + + // Relocations for fixing up references in the code section. + std::vector<WasmRelocationEntry> CodeRelocations; + + // Relocations for fixing up references in the data section. + std::vector<WasmRelocationEntry> DataRelocations; + + // Index values to use for fixing up call_indirect type indices. + // Maps function symbols to the index of the type of the function + DenseMap<const MCSymbolWasm *, uint32_t> TypeIndices; + // Maps function symbols to the table element index space. Used + // for TABLE_INDEX relocation types (i.e. address taken functions). + DenseMap<const MCSymbolWasm *, uint32_t> IndirectSymbolIndices; + // Maps function/global symbols to the function/global index space. + DenseMap<const MCSymbolWasm *, uint32_t> SymbolIndices; + + DenseMap<WasmFunctionType, int32_t, WasmFunctionTypeDenseMapInfo> + FunctionTypeIndices; + SmallVector<WasmFunctionType, 4> FunctionTypes; + + // TargetObjectWriter wrappers. + bool is64Bit() const { return TargetObjectWriter->is64Bit(); } + unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup) const { + return TargetObjectWriter->getRelocType(Target, Fixup); + } + + void startSection(SectionBookkeeping &Section, unsigned SectionId, + const char *Name = nullptr); + void endSection(SectionBookkeeping &Section); + +public: + WasmObjectWriter(MCWasmObjectTargetWriter *MOTW, raw_pwrite_stream &OS) + : MCObjectWriter(OS, /*IsLittleEndian=*/true), TargetObjectWriter(MOTW) {} + +private: + ~WasmObjectWriter() override; + + void reset() override { + CodeRelocations.clear(); + DataRelocations.clear(); + TypeIndices.clear(); + SymbolIndices.clear(); + IndirectSymbolIndices.clear(); + FunctionTypeIndices.clear(); + FunctionTypes.clear(); + 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; + + void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; + + void writeString(const StringRef Str) { + encodeULEB128(Str.size(), getStream()); + writeBytes(Str); + } + + void writeValueType(wasm::ValType Ty) { + encodeSLEB128(int32_t(Ty), getStream()); + } + + void writeTypeSection(const SmallVector<WasmFunctionType, 4> &FunctionTypes); + void writeImportSection(const SmallVector<WasmImport, 4> &Imports); + void writeFunctionSection(const SmallVector<WasmFunction, 4> &Functions); + void writeTableSection(uint32_t NumElements); + void writeMemorySection(const SmallVector<char, 0> &DataBytes); + void writeGlobalSection(const SmallVector<WasmGlobal, 4> &Globals); + void writeExportSection(const SmallVector<WasmExport, 4> &Exports); + void writeElemSection(const SmallVector<uint32_t, 4> &TableElems); + void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout, + const SmallVector<WasmFunction, 4> &Functions); + uint64_t + writeDataSection(const SmallVector<char, 0> &DataBytes); + void writeNameSection(const SmallVector<WasmFunction, 4> &Functions, + const SmallVector<WasmImport, 4> &Imports, + uint32_t NumFuncImports); + void writeCodeRelocSection(); + void writeDataRelocSection(uint64_t DataSectionHeaderSize); + void writeLinkingMetaDataSection(uint32_t DataSize, uint32_t DataAlignment, + ArrayRef<StringRef> WeakSymbols, + bool HasStackPointer, + uint32_t StackPointerGlobal); + + void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations, + uint64_t ContentsOffset); + + void writeRelocations(ArrayRef<WasmRelocationEntry> Relocations, + uint64_t HeaderSize); + uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry); + uint32_t getFunctionType(const MCSymbolWasm& Symbol); + uint32_t registerFunctionType(const MCSymbolWasm& Symbol); +}; + +} // end anonymous namespace + +WasmObjectWriter::~WasmObjectWriter() {} + +// Return the padding size to write a 32-bit value into a 5-byte ULEB128. +static unsigned PaddingFor5ByteULEB128(uint32_t X) { + return X == 0 ? 4 : (4u - (31u - countLeadingZeros(X)) / 7u); +} + +// Return the padding size to write a 32-bit value into a 5-byte SLEB128. +static unsigned PaddingFor5ByteSLEB128(int32_t X) { + return 5 - getSLEB128Size(X); +} + +// Write out a section header and a patchable section size field. +void WasmObjectWriter::startSection(SectionBookkeeping &Section, + unsigned SectionId, + const char *Name) { + assert((Name != nullptr) == (SectionId == wasm::WASM_SEC_CUSTOM) && + "Only custom sections can have names"); + + DEBUG(dbgs() << "startSection " << SectionId << ": " << Name << "\n"); + encodeULEB128(SectionId, getStream()); + + Section.SizeOffset = getStream().tell(); + + // The section size. We don't know the size yet, so reserve enough space + // for any 32-bit value; we'll patch it later. + encodeULEB128(UINT32_MAX, getStream()); + + // The position where the section starts, for measuring its size. + Section.ContentsOffset = getStream().tell(); + + // Custom sections in wasm also have a string identifier. + if (SectionId == wasm::WASM_SEC_CUSTOM) { + assert(Name); + writeString(StringRef(Name)); + } +} + +// Now that the section is complete and we know how big it is, patch up the +// section size field at the start of the section. +void WasmObjectWriter::endSection(SectionBookkeeping &Section) { + uint64_t Size = getStream().tell() - Section.ContentsOffset; + if (uint32_t(Size) != Size) + report_fatal_error("section size does not fit in a uint32_t"); + + DEBUG(dbgs() << "endSection size=" << Size << "\n"); + unsigned Padding = PaddingFor5ByteULEB128(Size); + + // Write the final section size to the payload_len field, which follows + // the section id byte. + uint8_t Buffer[16]; + unsigned SizeLen = encodeULEB128(Size, Buffer, Padding); + assert(SizeLen == 5); + getStream().pwrite((char *)Buffer, SizeLen, Section.SizeOffset); +} + +// Emit the Wasm header. +void WasmObjectWriter::writeHeader(const MCAssembler &Asm) { + writeBytes(StringRef(wasm::WasmMagic, sizeof(wasm::WasmMagic))); + writeLE32(wasm::WasmVersion); +} + +void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) { +} + +void WasmObjectWriter::recordRelocation(MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + 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(); + + 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; + + if (SymA) + SymA->setUsedInReloc(); + + assert(!IsPCRel); + assert(SymA); + + unsigned Type = getRelocType(Target, Fixup); + + WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection); + DEBUG(dbgs() << "WasmReloc: " << Rec << "\n"); + + if (FixupSection.hasInstructions()) + CodeRelocations.push_back(Rec); + else + DataRelocations.push_back(Rec); +} + +// Write X as an (unsigned) LEB value at offset Offset in Stream, padded +// to allow patching. +static void +WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) { + uint8_t Buffer[5]; + unsigned Padding = PaddingFor5ByteULEB128(X); + unsigned SizeLen = encodeULEB128(X, Buffer, Padding); + assert(SizeLen == 5); + Stream.pwrite((char *)Buffer, SizeLen, Offset); +} + +// Write X as an signed LEB value at offset Offset in Stream, padded +// to allow patching. +static void +WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X, uint64_t Offset) { + uint8_t Buffer[5]; + unsigned Padding = PaddingFor5ByteSLEB128(X); + unsigned SizeLen = encodeSLEB128(X, Buffer, Padding); + assert(SizeLen == 5); + Stream.pwrite((char *)Buffer, SizeLen, Offset); +} + +// Write X as a plain integer value at offset Offset in Stream. +static void WriteI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) { + uint8_t Buffer[4]; + support::endian::write32le(Buffer, X); + Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset); +} + +// Compute a value to write into the code at the location covered +// by RelEntry. This value isn't used by the static linker, since +// we have addends; it just serves to make the code more readable +// and to make standalone wasm modules directly usable. +static uint32_t ProvisionalValue(const WasmRelocationEntry &RelEntry) { + const MCSymbolWasm *Sym = RelEntry.Symbol; + + // For undefined symbols, use a hopefully invalid value. + if (!Sym->isDefined(/*SetUsed=*/false)) + return UINT32_MAX; + + const auto &Section = cast<MCSectionWasm>(RelEntry.Symbol->getSection(false)); + uint64_t Address = Section.getSectionOffset() + RelEntry.Addend; + + // Ignore overflow. LLVM allows address arithmetic to silently wrap. + uint32_t Value = Address; + + return Value; +} + +uint32_t WasmObjectWriter::getRelocationIndexValue( + const WasmRelocationEntry &RelEntry) { + switch (RelEntry.Type) { + case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: + case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: + if (!IndirectSymbolIndices.count(RelEntry.Symbol)) + report_fatal_error("symbol not found table index space: " + + RelEntry.Symbol->getName()); + return IndirectSymbolIndices[RelEntry.Symbol]; + case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: + case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: + if (!SymbolIndices.count(RelEntry.Symbol)) + report_fatal_error("symbol not found function/global index space: " + + RelEntry.Symbol->getName()); + return SymbolIndices[RelEntry.Symbol]; + case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: + if (!TypeIndices.count(RelEntry.Symbol)) + report_fatal_error("symbol not found in type index space: " + + RelEntry.Symbol->getName()); + return TypeIndices[RelEntry.Symbol]; + default: + llvm_unreachable("invalid relocation type"); + } +} + +// Apply the portions of the relocation records that we can handle ourselves +// directly. +void WasmObjectWriter::applyRelocations( + ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset) { + raw_pwrite_stream &Stream = getStream(); + for (const WasmRelocationEntry &RelEntry : Relocations) { + uint64_t Offset = ContentsOffset + + RelEntry.FixupSection->getSectionOffset() + + RelEntry.Offset; + + DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n"); + switch (RelEntry.Type) { + case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: + case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: + case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: + case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: { + uint32_t Index = getRelocationIndexValue(RelEntry); + WritePatchableSLEB(Stream, Index, Offset); + break; + } + case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: { + uint32_t Index = getRelocationIndexValue(RelEntry); + WriteI32(Stream, Index, Offset); + break; + } + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: { + uint32_t Value = ProvisionalValue(RelEntry); + WritePatchableSLEB(Stream, Value, Offset); + break; + } + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: { + uint32_t Value = ProvisionalValue(RelEntry); + WritePatchableLEB(Stream, Value, Offset); + break; + } + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: { + uint32_t Value = ProvisionalValue(RelEntry); + WriteI32(Stream, Value, Offset); + break; + } + default: + llvm_unreachable("invalid relocation type"); + } + } +} + +// Write out the portions of the relocation records that the linker will +// need to handle. +void WasmObjectWriter::writeRelocations( + ArrayRef<WasmRelocationEntry> Relocations, uint64_t HeaderSize) { + raw_pwrite_stream &Stream = getStream(); + for (const WasmRelocationEntry& RelEntry : Relocations) { + + uint64_t Offset = RelEntry.Offset + + RelEntry.FixupSection->getSectionOffset() + HeaderSize; + uint32_t Index = getRelocationIndexValue(RelEntry); + + encodeULEB128(RelEntry.Type, Stream); + encodeULEB128(Offset, Stream); + encodeULEB128(Index, Stream); + if (RelEntry.hasAddend()) + encodeSLEB128(RelEntry.Addend, Stream); + } +} + +void WasmObjectWriter::writeTypeSection( + const SmallVector<WasmFunctionType, 4> &FunctionTypes) { + if (FunctionTypes.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_TYPE); + + encodeULEB128(FunctionTypes.size(), getStream()); + + for (const WasmFunctionType &FuncTy : FunctionTypes) { + encodeSLEB128(wasm::WASM_TYPE_FUNC, getStream()); + encodeULEB128(FuncTy.Params.size(), getStream()); + for (wasm::ValType Ty : FuncTy.Params) + writeValueType(Ty); + encodeULEB128(FuncTy.Returns.size(), getStream()); + for (wasm::ValType Ty : FuncTy.Returns) + writeValueType(Ty); + } + + endSection(Section); +} + + +void WasmObjectWriter::writeImportSection( + const SmallVector<WasmImport, 4> &Imports) { + if (Imports.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_IMPORT); + + encodeULEB128(Imports.size(), getStream()); + for (const WasmImport &Import : Imports) { + writeString(Import.ModuleName); + writeString(Import.FieldName); + + encodeULEB128(Import.Kind, getStream()); + + switch (Import.Kind) { + case wasm::WASM_EXTERNAL_FUNCTION: + encodeULEB128(Import.Type, getStream()); + break; + case wasm::WASM_EXTERNAL_GLOBAL: + encodeSLEB128(int32_t(Import.Type), getStream()); + encodeULEB128(0, getStream()); // mutability + break; + default: + llvm_unreachable("unsupported import kind"); + } + } + + endSection(Section); +} + +void WasmObjectWriter::writeFunctionSection( + const SmallVector<WasmFunction, 4> &Functions) { + if (Functions.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_FUNCTION); + + encodeULEB128(Functions.size(), getStream()); + for (const WasmFunction &Func : Functions) + encodeULEB128(Func.Type, getStream()); + + endSection(Section); +} + +void WasmObjectWriter::writeTableSection(uint32_t NumElements) { + // For now, always emit the table section, since indirect calls are not + // valid without it. In the future, we could perhaps be more clever and omit + // it if there are no indirect calls. + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_TABLE); + + encodeULEB128(1, getStream()); // The number of tables. + // Fixed to 1 for now. + encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream()); // Type of table + encodeULEB128(0, getStream()); // flags + encodeULEB128(NumElements, getStream()); // initial + + endSection(Section); +} + +void WasmObjectWriter::writeMemorySection( + const SmallVector<char, 0> &DataBytes) { + // For now, always emit the memory section, since loads and stores are not + // valid without it. In the future, we could perhaps be more clever and omit + // it if there are no loads or stores. + SectionBookkeeping Section; + uint32_t NumPages = + (DataBytes.size() + wasm::WasmPageSize - 1) / wasm::WasmPageSize; + + startSection(Section, wasm::WASM_SEC_MEMORY); + encodeULEB128(1, getStream()); // number of memory spaces + + encodeULEB128(0, getStream()); // flags + encodeULEB128(NumPages, getStream()); // initial + + endSection(Section); +} + +void WasmObjectWriter::writeGlobalSection( + const SmallVector<WasmGlobal, 4> &Globals) { + if (Globals.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_GLOBAL); + + encodeULEB128(Globals.size(), getStream()); + for (const WasmGlobal &Global : Globals) { + writeValueType(Global.Type); + write8(Global.IsMutable); + + if (Global.HasImport) { + assert(Global.InitialValue == 0); + write8(wasm::WASM_OPCODE_GET_GLOBAL); + encodeULEB128(Global.ImportIndex, getStream()); + } else { + assert(Global.ImportIndex == 0); + write8(wasm::WASM_OPCODE_I32_CONST); + encodeSLEB128(Global.InitialValue, getStream()); // offset + } + write8(wasm::WASM_OPCODE_END); + } + + endSection(Section); +} + +void WasmObjectWriter::writeExportSection( + const SmallVector<WasmExport, 4> &Exports) { + if (Exports.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_EXPORT); + + encodeULEB128(Exports.size(), getStream()); + for (const WasmExport &Export : Exports) { + writeString(Export.FieldName); + encodeSLEB128(Export.Kind, getStream()); + encodeULEB128(Export.Index, getStream()); + } + + endSection(Section); +} + +void WasmObjectWriter::writeElemSection( + const SmallVector<uint32_t, 4> &TableElems) { + if (TableElems.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_ELEM); + + encodeULEB128(1, getStream()); // number of "segments" + encodeULEB128(0, getStream()); // the table index + + // init expr for starting offset + write8(wasm::WASM_OPCODE_I32_CONST); + encodeSLEB128(0, getStream()); + write8(wasm::WASM_OPCODE_END); + + encodeULEB128(TableElems.size(), getStream()); + for (uint32_t Elem : TableElems) + encodeULEB128(Elem, getStream()); + + endSection(Section); +} + +void WasmObjectWriter::writeCodeSection( + const MCAssembler &Asm, const MCAsmLayout &Layout, + const SmallVector<WasmFunction, 4> &Functions) { + if (Functions.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_CODE); + + encodeULEB128(Functions.size(), getStream()); + + for (const WasmFunction &Func : Functions) { + auto &FuncSection = static_cast<MCSectionWasm &>(Func.Sym->getSection()); + + int64_t Size = 0; + if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout)) + report_fatal_error(".size expression must be evaluatable"); + + encodeULEB128(Size, getStream()); + + FuncSection.setSectionOffset(getStream().tell() - Section.ContentsOffset); + + Asm.writeSectionData(&FuncSection, Layout); + } + + // Apply fixups. + applyRelocations(CodeRelocations, Section.ContentsOffset); + + endSection(Section); +} + +uint64_t WasmObjectWriter::writeDataSection( + const SmallVector<char, 0> &DataBytes) { + if (DataBytes.empty()) + return 0; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_DATA); + + encodeULEB128(1, getStream()); // count + encodeULEB128(0, getStream()); // memory index + write8(wasm::WASM_OPCODE_I32_CONST); + encodeSLEB128(0, getStream()); // offset + write8(wasm::WASM_OPCODE_END); + encodeULEB128(DataBytes.size(), getStream()); // size + uint32_t HeaderSize = getStream().tell() - Section.ContentsOffset; + writeBytes(DataBytes); // data + + // Apply fixups. + applyRelocations(DataRelocations, Section.ContentsOffset + HeaderSize); + + endSection(Section); + return HeaderSize; +} + +void WasmObjectWriter::writeNameSection( + const SmallVector<WasmFunction, 4> &Functions, + const SmallVector<WasmImport, 4> &Imports, + unsigned NumFuncImports) { + uint32_t TotalFunctions = NumFuncImports + Functions.size(); + if (TotalFunctions == 0) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_CUSTOM, "name"); + SectionBookkeeping SubSection; + startSection(SubSection, wasm::WASM_NAMES_FUNCTION); + + encodeULEB128(TotalFunctions, getStream()); + uint32_t Index = 0; + for (const WasmImport &Import : Imports) { + if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) { + encodeULEB128(Index, getStream()); + writeString(Import.FieldName); + ++Index; + } + } + for (const WasmFunction &Func : Functions) { + encodeULEB128(Index, getStream()); + writeString(Func.Sym->getName()); + ++Index; + } + + endSection(SubSection); + endSection(Section); +} + +void WasmObjectWriter::writeCodeRelocSection() { + // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md + // for descriptions of the reloc sections. + + if (CodeRelocations.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.CODE"); + + encodeULEB128(wasm::WASM_SEC_CODE, getStream()); + encodeULEB128(CodeRelocations.size(), getStream()); + + writeRelocations(CodeRelocations, 0); + + endSection(Section); +} + +void WasmObjectWriter::writeDataRelocSection(uint64_t DataSectionHeaderSize) { + // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md + // for descriptions of the reloc sections. + + if (DataRelocations.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.DATA"); + + encodeULEB128(wasm::WASM_SEC_DATA, getStream()); + encodeULEB128(DataRelocations.size(), getStream()); + + writeRelocations(DataRelocations, DataSectionHeaderSize); + + endSection(Section); +} + +void WasmObjectWriter::writeLinkingMetaDataSection( + uint32_t DataSize, uint32_t DataAlignment, ArrayRef<StringRef> WeakSymbols, + bool HasStackPointer, uint32_t StackPointerGlobal) { + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_CUSTOM, "linking"); + SectionBookkeeping SubSection; + + if (HasStackPointer) { + startSection(SubSection, wasm::WASM_STACK_POINTER); + encodeULEB128(StackPointerGlobal, getStream()); // id + endSection(SubSection); + } + + if (WeakSymbols.size() != 0) { + startSection(SubSection, wasm::WASM_SYMBOL_INFO); + encodeULEB128(WeakSymbols.size(), getStream()); + for (const StringRef Export: WeakSymbols) { + writeString(Export); + encodeULEB128(wasm::WASM_SYMBOL_FLAG_WEAK, getStream()); + } + endSection(SubSection); + } + + if (DataSize > 0) { + startSection(SubSection, wasm::WASM_DATA_SIZE); + encodeULEB128(DataSize, getStream()); + endSection(SubSection); + + startSection(SubSection, wasm::WASM_DATA_ALIGNMENT); + encodeULEB128(DataAlignment, getStream()); + endSection(SubSection); + } + + endSection(Section); +} + +uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm& Symbol) { + assert(Symbol.isFunction()); + assert(TypeIndices.count(&Symbol)); + return TypeIndices[&Symbol]; +} + +uint32_t WasmObjectWriter::registerFunctionType(const MCSymbolWasm& Symbol) { + assert(Symbol.isFunction()); + + WasmFunctionType F; + if (Symbol.isVariable()) { + const MCExpr *Expr = Symbol.getVariableValue(); + auto *Inner = cast<MCSymbolRefExpr>(Expr); + const auto *ResolvedSym = cast<MCSymbolWasm>(&Inner->getSymbol()); + F.Returns = ResolvedSym->getReturns(); + F.Params = ResolvedSym->getParams(); + } else { + F.Returns = Symbol.getReturns(); + F.Params = Symbol.getParams(); + } + + auto Pair = + FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size())); + if (Pair.second) + FunctionTypes.push_back(F); + TypeIndices[&Symbol] = Pair.first->second; + + DEBUG(dbgs() << "registerFunctionType: " << Symbol << " new:" << Pair.second << "\n"); + DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n"); + return Pair.first->second; +} + +void WasmObjectWriter::writeObject(MCAssembler &Asm, + const MCAsmLayout &Layout) { + DEBUG(dbgs() << "WasmObjectWriter::writeObject\n"); + MCContext &Ctx = Asm.getContext(); + wasm::ValType PtrType = is64Bit() ? wasm::ValType::I64 : wasm::ValType::I32; + + // Collect information from the available symbols. + SmallVector<WasmFunction, 4> Functions; + SmallVector<uint32_t, 4> TableElems; + SmallVector<WasmGlobal, 4> Globals; + SmallVector<WasmImport, 4> Imports; + SmallVector<WasmExport, 4> Exports; + SmallVector<StringRef, 4> WeakSymbols; + SmallPtrSet<const MCSymbolWasm *, 4> IsAddressTaken; + unsigned NumFuncImports = 0; + unsigned NumGlobalImports = 0; + SmallVector<char, 0> DataBytes; + uint32_t DataAlignment = 1; + uint32_t StackPointerGlobal = 0; + bool HasStackPointer = false; + + // Populate the IsAddressTaken set. + for (const WasmRelocationEntry &RelEntry : CodeRelocations) { + switch (RelEntry.Type) { + case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: + IsAddressTaken.insert(RelEntry.Symbol); + break; + default: + break; + } + } + for (const WasmRelocationEntry &RelEntry : DataRelocations) { + switch (RelEntry.Type) { + case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: + IsAddressTaken.insert(RelEntry.Symbol); + break; + default: + break; + } + } + + // Populate the Imports set. + for (const MCSymbol &S : Asm.symbols()) { + const auto &WS = static_cast<const MCSymbolWasm &>(S); + + if (WS.isTemporary()) + continue; + + if (WS.isFunction()) + registerFunctionType(WS); + + // If the symbol is not defined in this translation unit, import it. + if (!WS.isDefined(/*SetUsed=*/false) || WS.isVariable()) { + WasmImport Import; + Import.ModuleName = WS.getModuleName(); + Import.FieldName = WS.getName(); + + if (WS.isFunction()) { + Import.Kind = wasm::WASM_EXTERNAL_FUNCTION; + Import.Type = getFunctionType(WS); + SymbolIndices[&WS] = NumFuncImports; + ++NumFuncImports; + } else { + Import.Kind = wasm::WASM_EXTERNAL_GLOBAL; + Import.Type = int32_t(PtrType); + SymbolIndices[&WS] = NumGlobalImports; + ++NumGlobalImports; + } + + Imports.push_back(Import); + } + } + + // In the special .global_variables section, we've encoded global + // variables used by the function. Translate them into the Globals + // list. + MCSectionWasm *GlobalVars = Ctx.getWasmSection(".global_variables", 0, 0); + if (!GlobalVars->getFragmentList().empty()) { + if (GlobalVars->getFragmentList().size() != 1) + report_fatal_error("only one .global_variables fragment supported"); + const MCFragment &Frag = *GlobalVars->begin(); + if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data) + report_fatal_error("only data supported in .global_variables"); + const auto &DataFrag = cast<MCDataFragment>(Frag); + if (!DataFrag.getFixups().empty()) + report_fatal_error("fixups not supported in .global_variables"); + const SmallVectorImpl<char> &Contents = DataFrag.getContents(); + for (const uint8_t *p = (const uint8_t *)Contents.data(), + *end = (const uint8_t *)Contents.data() + Contents.size(); + p != end; ) { + WasmGlobal G; + if (end - p < 3) + report_fatal_error("truncated global variable encoding"); + G.Type = wasm::ValType(int8_t(*p++)); + G.IsMutable = bool(*p++); + G.HasImport = bool(*p++); + if (G.HasImport) { + G.InitialValue = 0; + + WasmImport Import; + Import.ModuleName = (const char *)p; + const uint8_t *nul = (const uint8_t *)memchr(p, '\0', end - p); + if (!nul) + report_fatal_error("global module name must be nul-terminated"); + p = nul + 1; + nul = (const uint8_t *)memchr(p, '\0', end - p); + if (!nul) + report_fatal_error("global base name must be nul-terminated"); + Import.FieldName = (const char *)p; + p = nul + 1; + + Import.Kind = wasm::WASM_EXTERNAL_GLOBAL; + Import.Type = int32_t(G.Type); + + G.ImportIndex = NumGlobalImports; + ++NumGlobalImports; + + Imports.push_back(Import); + } else { + unsigned n; + G.InitialValue = decodeSLEB128(p, &n); + G.ImportIndex = 0; + if ((ptrdiff_t)n > end - p) + report_fatal_error("global initial value must be valid SLEB128"); + p += n; + } + Globals.push_back(G); + } + } + + // In the special .stack_pointer section, we've encoded the stack pointer + // index. + MCSectionWasm *StackPtr = Ctx.getWasmSection(".stack_pointer", 0, 0); + if (!StackPtr->getFragmentList().empty()) { + if (StackPtr->getFragmentList().size() != 1) + report_fatal_error("only one .stack_pointer fragment supported"); + const MCFragment &Frag = *StackPtr->begin(); + if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data) + report_fatal_error("only data supported in .stack_pointer"); + const auto &DataFrag = cast<MCDataFragment>(Frag); + if (!DataFrag.getFixups().empty()) + report_fatal_error("fixups not supported in .stack_pointer"); + const SmallVectorImpl<char> &Contents = DataFrag.getContents(); + if (Contents.size() != 4) + report_fatal_error("only one entry supported in .stack_pointer"); + HasStackPointer = true; + StackPointerGlobal = NumGlobalImports + *(const int32_t *)Contents.data(); + } + + // Handle regular defined and undefined symbols. + for (const MCSymbol &S : Asm.symbols()) { + // Ignore unnamed temporary symbols, which aren't ever exported, imported, + // or used in relocations. + if (S.isTemporary() && S.getName().empty()) + continue; + + const auto &WS = static_cast<const MCSymbolWasm &>(S); + DEBUG(dbgs() << "MCSymbol: '" << S << "'" + << " isDefined=" << S.isDefined() << " isExternal=" + << S.isExternal() << " isTemporary=" << S.isTemporary() + << " isFunction=" << WS.isFunction() + << " isWeak=" << WS.isWeak() + << " isVariable=" << WS.isVariable() << "\n"); + + if (WS.isWeak()) + WeakSymbols.push_back(WS.getName()); + + if (WS.isVariable()) + continue; + + unsigned Index; + + if (WS.isFunction()) { + if (WS.isDefined(/*SetUsed=*/false)) { + if (WS.getOffset() != 0) + report_fatal_error( + "function sections must contain one function each"); + + if (WS.getSize() == 0) + report_fatal_error( + "function symbols must have a size set with .size"); + + // A definition. Take the next available index. + Index = NumFuncImports + Functions.size(); + + // Prepare the function. + WasmFunction Func; + Func.Type = getFunctionType(WS); + Func.Sym = &WS; + SymbolIndices[&WS] = Index; + Functions.push_back(Func); + } else { + // An import; the index was assigned above. + Index = SymbolIndices.find(&WS)->second; + } + + DEBUG(dbgs() << " -> function index: " << Index << "\n"); + + // If needed, prepare the function to be called indirectly. + if (IsAddressTaken.count(&WS) != 0) { + IndirectSymbolIndices[&WS] = TableElems.size(); + DEBUG(dbgs() << " -> adding to table: " << TableElems.size() << "\n"); + TableElems.push_back(Index); + } + } else { + if (WS.isTemporary() && !WS.getSize()) + continue; + + if (!WS.isDefined(/*SetUsed=*/false)) + continue; + + if (WS.getOffset() != 0) + report_fatal_error("data sections must contain one variable each: " + + WS.getName()); + if (!WS.getSize()) + report_fatal_error("data symbols must have a size set with .size: " + + WS.getName()); + + int64_t Size = 0; + if (!WS.getSize()->evaluateAsAbsolute(Size, Layout)) + report_fatal_error(".size expression must be evaluatable"); + + auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection()); + + if (uint64_t(Size) != Layout.getSectionFileSize(&DataSection)) + report_fatal_error("data sections must contain at most one variable"); + + DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment())); + DataAlignment = std::max(DataAlignment, DataSection.getAlignment()); + + DataSection.setSectionOffset(DataBytes.size()); + + for (const MCFragment &Frag : DataSection) { + if (Frag.hasInstructions()) + report_fatal_error("only data supported in data sections"); + + if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) { + if (Align->getValueSize() != 1) + report_fatal_error("only byte values supported for alignment"); + // If nops are requested, use zeros, as this is the data section. + uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue(); + uint64_t Size = std::min<uint64_t>(alignTo(DataBytes.size(), + Align->getAlignment()), + DataBytes.size() + + Align->getMaxBytesToEmit()); + DataBytes.resize(Size, Value); + } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) { + DataBytes.insert(DataBytes.end(), Fill->getSize(), Fill->getValue()); + } else { + const auto &DataFrag = cast<MCDataFragment>(Frag); + const SmallVectorImpl<char> &Contents = DataFrag.getContents(); + + DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end()); + } + } + + // For each global, prepare a corresponding wasm global holding its + // address. For externals these will also be named exports. + Index = NumGlobalImports + Globals.size(); + + WasmGlobal Global; + Global.Type = PtrType; + Global.IsMutable = false; + Global.HasImport = false; + Global.InitialValue = DataSection.getSectionOffset(); + Global.ImportIndex = 0; + SymbolIndices[&WS] = Index; + DEBUG(dbgs() << " -> global index: " << Index << "\n"); + Globals.push_back(Global); + } + + // If the symbol is visible outside this translation unit, export it. + if ((WS.isExternal() && WS.isDefined(/*SetUsed=*/false))) { + WasmExport Export; + Export.FieldName = WS.getName(); + Export.Index = Index; + if (WS.isFunction()) + Export.Kind = wasm::WASM_EXTERNAL_FUNCTION; + else + Export.Kind = wasm::WASM_EXTERNAL_GLOBAL; + DEBUG(dbgs() << " -> export " << Exports.size() << "\n"); + Exports.push_back(Export); + } + } + + // Handle weak aliases. 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(/*SetUsed=*/false)); + + const auto &WS = static_cast<const MCSymbolWasm &>(S); + // Find the target symbol of this weak alias and export that index + const MCExpr *Expr = WS.getVariableValue(); + auto *Inner = cast<MCSymbolRefExpr>(Expr); + const auto *ResolvedSym = cast<MCSymbolWasm>(&Inner->getSymbol()); + DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *ResolvedSym << "'\n"); + assert(SymbolIndices.count(ResolvedSym) > 0); + uint32_t Index = SymbolIndices.find(ResolvedSym)->second; + DEBUG(dbgs() << " -> index:" << Index << "\n"); + + WasmExport Export; + Export.FieldName = WS.getName(); + Export.Index = Index; + if (WS.isFunction()) + Export.Kind = wasm::WASM_EXTERNAL_FUNCTION; + else + Export.Kind = wasm::WASM_EXTERNAL_GLOBAL; + DEBUG(dbgs() << " -> export " << Exports.size() << "\n"); + Exports.push_back(Export); + } + + // Add types for indirect function calls. + for (const WasmRelocationEntry &Fixup : CodeRelocations) { + if (Fixup.Type != wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB) + continue; + + registerFunctionType(*Fixup.Symbol); + } + + // Write out the Wasm header. + writeHeader(Asm); + + writeTypeSection(FunctionTypes); + writeImportSection(Imports); + writeFunctionSection(Functions); + writeTableSection(TableElems.size()); + writeMemorySection(DataBytes); + writeGlobalSection(Globals); + writeExportSection(Exports); + // TODO: Start Section + writeElemSection(TableElems); + writeCodeSection(Asm, Layout, Functions); + uint64_t DataSectionHeaderSize = writeDataSection(DataBytes); + writeNameSection(Functions, Imports, NumFuncImports); + writeCodeRelocSection(); + writeDataRelocSection(DataSectionHeaderSize); + writeLinkingMetaDataSection(DataBytes.size(), DataAlignment, WeakSymbols, HasStackPointer, StackPointerGlobal); + + // TODO: Translate the .comment section to the output. + // TODO: Translate debug sections to the output. +} + +MCObjectWriter *llvm::createWasmObjectWriter(MCWasmObjectTargetWriter *MOTW, + raw_pwrite_stream &OS) { + return new WasmObjectWriter(MOTW, OS); +} diff --git a/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp b/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp index afc5c6a..956ae70 100644 --- a/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -1,4 +1,4 @@ -//===-- llvm/MC/WinCOFFObjectWriter.cpp -------------------------*- C++ -*-===// +//===- llvm/MC/WinCOFFObjectWriter.cpp ------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -11,38 +11,51 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCWinCOFFObjectWriter.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" -#include "llvm/Config/config.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/MCObjectFileInfo.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/COFF.h" -#include "llvm/Support/Debug.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/JamCRC.h" -#include <cstdio> +#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 { -typedef SmallString<COFF::NameSize> name; + +using name = SmallString<COFF::NameSize>; enum AuxiliaryType { ATFunctionDefinition, @@ -57,25 +70,24 @@ struct AuxSymbol { COFF::Auxiliary Aux; }; -class COFFSymbol; class COFFSection; class COFFSymbol { public: - COFF::symbol Data; + COFF::symbol Data = {}; - typedef SmallVector<AuxSymbol, 1> AuxiliarySymbols; + using AuxiliarySymbols = SmallVector<AuxSymbol, 1>; name Name; int Index; AuxiliarySymbols Aux; - COFFSymbol *Other; - COFFSection *Section; - int Relocations; + COFFSymbol *Other = nullptr; + COFFSection *Section = nullptr; + int Relocations = 0; + const MCSymbol *MC = nullptr; - const MCSymbol *MC; + COFFSymbol(StringRef Name) : Name(Name) {} - COFFSymbol(StringRef name); void set_name_offset(uint32_t Offset); int64_t getIndex() const { return Index; } @@ -89,39 +101,40 @@ public: // This class contains staging data for a COFF relocation entry. struct COFFRelocation { COFF::relocation Data; - COFFSymbol *Symb; + COFFSymbol *Symb = nullptr; + + COFFRelocation() = default; - COFFRelocation() : Symb(nullptr) {} static size_t size() { return COFF::RelocationSize; } }; -typedef std::vector<COFFRelocation> relocations; +using relocations = std::vector<COFFRelocation>; class COFFSection { public: - COFF::section Header; + COFF::section Header = {}; std::string Name; int Number; - MCSectionCOFF const *MCSection; - COFFSymbol *Symbol; + MCSectionCOFF const *MCSection = nullptr; + COFFSymbol *Symbol = nullptr; relocations Relocations; - COFFSection(StringRef name); + COFFSection(StringRef Name) : Name(Name) {} }; class WinCOFFObjectWriter : public MCObjectWriter { public: - typedef std::vector<std::unique_ptr<COFFSymbol>> symbols; - typedef std::vector<std::unique_ptr<COFFSection>> sections; + using symbols = std::vector<std::unique_ptr<COFFSymbol>>; + using sections = std::vector<std::unique_ptr<COFFSection>>; - typedef DenseMap<MCSymbol const *, COFFSymbol *> symbol_map; - typedef DenseMap<MCSection const *, COFFSection *> section_map; + 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; + COFF::header Header = {}; sections Sections; symbols Symbols; StringTableBuilder Strings{StringTableBuilder::WinCOFF}; @@ -149,9 +162,6 @@ public: COFFSymbol *GetOrCreateCOFFSymbol(const MCSymbol *Symbol); COFFSection *createSection(StringRef Name); - template <typename object_t, typename list_t> - object_t *createCOFFEntity(StringRef Name, list_t &List); - void defineSection(MCSectionCOFF const &Sec); COFFSymbol *getLinkedSymbol(const MCSymbol &Symbol); @@ -168,8 +178,12 @@ public: void WriteFileHeader(const COFF::header &Header); void WriteSymbol(const COFFSymbol &S); void WriteAuxiliarySymbols(const COFFSymbol::AuxiliarySymbols &S); - void writeSectionHeader(const COFF::section &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. @@ -181,45 +195,28 @@ public: const MCFragment &FB, bool InSet, bool IsPCRel) const override; - bool isWeak(const MCSymbol &Sym) const override; - void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, - MCValue Target, bool &IsPCRel, - uint64_t &FixedValue) override; + MCValue Target, uint64_t &FixedValue) override; + + void createFileSymbols(MCAssembler &Asm); + void assignSectionNumbers(); + void assignFileOffsets(MCAssembler &Asm, const MCAsmLayout &Layout); void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; }; -} -static inline void write_uint32_le(void *Data, uint32_t Value) { - support::endian::write<uint32_t, support::little, support::unaligned>(Data, - Value); -} +} // end anonymous namespace //------------------------------------------------------------------------------ // Symbol class implementation -COFFSymbol::COFFSymbol(StringRef name) - : Name(name.begin(), name.end()), Other(nullptr), Section(nullptr), - Relocations(0), MC(nullptr) { - memset(&Data, 0, sizeof(Data)); -} - // 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) { - write_uint32_le(Data.Name + 0, 0); - write_uint32_le(Data.Name + 4, Offset); -} - -//------------------------------------------------------------------------------ -// Section class implementation - -COFFSection::COFFSection(StringRef name) - : Name(name), MCSection(nullptr), Symbol(nullptr) { - memset(&Header, 0, sizeof(Header)); + write32le(Data.Name + 0, 0); + write32le(Data.Name + 4, Offset); } //------------------------------------------------------------------------------ @@ -228,115 +225,92 @@ COFFSection::COFFSection(StringRef name) WinCOFFObjectWriter::WinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW, raw_pwrite_stream &OS) : MCObjectWriter(OS, true), TargetObjectWriter(MOTW) { - memset(&Header, 0, sizeof(Header)); - Header.Machine = TargetObjectWriter->getMachine(); } COFFSymbol *WinCOFFObjectWriter::createSymbol(StringRef Name) { - return createCOFFEntity<COFFSymbol>(Name, Symbols); + Symbols.push_back(make_unique<COFFSymbol>(Name)); + return Symbols.back().get(); } COFFSymbol *WinCOFFObjectWriter::GetOrCreateCOFFSymbol(const MCSymbol *Symbol) { - symbol_map::iterator i = SymbolMap.find(Symbol); - if (i != SymbolMap.end()) - return i->second; - COFFSymbol *RetSymbol = - createCOFFEntity<COFFSymbol>(Symbol->getName(), Symbols); - SymbolMap[Symbol] = RetSymbol; - return RetSymbol; + COFFSymbol *&Ret = SymbolMap[Symbol]; + if (!Ret) + Ret = createSymbol(Symbol->getName()); + return Ret; } COFFSection *WinCOFFObjectWriter::createSection(StringRef Name) { - return createCOFFEntity<COFFSection>(Name, Sections); + Sections.emplace_back(make_unique<COFFSection>(Name)); + return Sections.back().get(); } -/// A template used to lookup or create a symbol/section, and initialize it if -/// needed. -template <typename object_t, typename list_t> -object_t *WinCOFFObjectWriter::createCOFFEntity(StringRef Name, list_t &List) { - List.push_back(make_unique<object_t>(Name)); - - return List.back().get(); -} - -/// This function takes a section data object from the assembler -/// and creates the associated COFF section staging object. -void WinCOFFObjectWriter::defineSection(MCSectionCOFF const &Sec) { - COFFSection *coff_section = createSection(Sec.getSectionName()); - COFFSymbol *coff_symbol = createSymbol(Sec.getSectionName()); - if (Sec.getSelection() != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { - if (const MCSymbol *S = Sec.getCOMDATSymbol()) { - COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(S); - if (COMDATSymbol->Section) - report_fatal_error("two sections have the same comdat"); - COMDATSymbol->Section = coff_section; - } - } - - coff_section->Symbol = coff_symbol; - coff_symbol->Section = coff_section; - coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_STATIC; - - // In this case the auxiliary symbol is a Section Definition. - coff_symbol->Aux.resize(1); - memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0])); - coff_symbol->Aux[0].AuxType = ATSectionDefinition; - coff_symbol->Aux[0].Aux.SectionDefinition.Selection = Sec.getSelection(); - - coff_section->Header.Characteristics = Sec.getCharacteristics(); - - uint32_t &Characteristics = coff_section->Header.Characteristics; +static uint32_t getAlignment(const MCSectionCOFF &Sec) { switch (Sec.getAlignment()) { case 1: - Characteristics |= COFF::IMAGE_SCN_ALIGN_1BYTES; - break; + return COFF::IMAGE_SCN_ALIGN_1BYTES; case 2: - Characteristics |= COFF::IMAGE_SCN_ALIGN_2BYTES; - break; + return COFF::IMAGE_SCN_ALIGN_2BYTES; case 4: - Characteristics |= COFF::IMAGE_SCN_ALIGN_4BYTES; - break; + return COFF::IMAGE_SCN_ALIGN_4BYTES; case 8: - Characteristics |= COFF::IMAGE_SCN_ALIGN_8BYTES; - break; + return COFF::IMAGE_SCN_ALIGN_8BYTES; case 16: - Characteristics |= COFF::IMAGE_SCN_ALIGN_16BYTES; - break; + return COFF::IMAGE_SCN_ALIGN_16BYTES; case 32: - Characteristics |= COFF::IMAGE_SCN_ALIGN_32BYTES; - break; + return COFF::IMAGE_SCN_ALIGN_32BYTES; case 64: - Characteristics |= COFF::IMAGE_SCN_ALIGN_64BYTES; - break; + return COFF::IMAGE_SCN_ALIGN_64BYTES; case 128: - Characteristics |= COFF::IMAGE_SCN_ALIGN_128BYTES; - break; + return COFF::IMAGE_SCN_ALIGN_128BYTES; case 256: - Characteristics |= COFF::IMAGE_SCN_ALIGN_256BYTES; - break; + return COFF::IMAGE_SCN_ALIGN_256BYTES; case 512: - Characteristics |= COFF::IMAGE_SCN_ALIGN_512BYTES; - break; + return COFF::IMAGE_SCN_ALIGN_512BYTES; case 1024: - Characteristics |= COFF::IMAGE_SCN_ALIGN_1024BYTES; - break; + return COFF::IMAGE_SCN_ALIGN_1024BYTES; case 2048: - Characteristics |= COFF::IMAGE_SCN_ALIGN_2048BYTES; - break; + return COFF::IMAGE_SCN_ALIGN_2048BYTES; case 4096: - Characteristics |= COFF::IMAGE_SCN_ALIGN_4096BYTES; - break; + return COFF::IMAGE_SCN_ALIGN_4096BYTES; case 8192: - Characteristics |= COFF::IMAGE_SCN_ALIGN_8192BYTES; - break; - default: - llvm_unreachable("unsupported section alignment"); + 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. - coff_section->MCSection = &Sec; - SectionMap[&Sec] = coff_section; + Section->MCSection = &MCSec; + SectionMap[&MCSec] = Section; } static uint64_t getSymbolValue(const MCSymbol &Symbol, @@ -368,25 +342,25 @@ COFFSymbol *WinCOFFObjectWriter::getLinkedSymbol(const MCSymbol &Symbol) { /// This function takes a symbol data object from the assembler /// and creates the associated COFF symbol staging object. -void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &Symbol, +void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &MCSym, MCAssembler &Assembler, const MCAsmLayout &Layout) { - COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&Symbol); - const MCSymbol *Base = Layout.getBaseSymbol(Symbol); + COFFSymbol *Sym = GetOrCreateCOFFSymbol(&MCSym); + const MCSymbol *Base = Layout.getBaseSymbol(MCSym); COFFSection *Sec = nullptr; if (Base && Base->getFragment()) { Sec = SectionMap[Base->getFragment()->getParent()]; - if (coff_symbol->Section && coff_symbol->Section != Sec) + if (Sym->Section && Sym->Section != Sec) report_fatal_error("conflicting sections for symbol"); } COFFSymbol *Local = nullptr; - if (cast<MCSymbolCOFF>(Symbol).isWeakExternal()) { - coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; + if (cast<MCSymbolCOFF>(MCSym).isWeakExternal()) { + Sym->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; - COFFSymbol *WeakDefault = getLinkedSymbol(Symbol); + COFFSymbol *WeakDefault = getLinkedSymbol(MCSym); if (!WeakDefault) { - std::string WeakName = (".weak." + Symbol.getName() + ".default").str(); + std::string WeakName = (".weak." + MCSym.getName() + ".default").str(); WeakDefault = createSymbol(WeakName); if (!Sec) WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; @@ -395,41 +369,41 @@ void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &Symbol, Local = WeakDefault; } - coff_symbol->Other = WeakDefault; + Sym->Other = WeakDefault; // Setup the Weak External auxiliary symbol. - coff_symbol->Aux.resize(1); - memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0])); - coff_symbol->Aux[0].AuxType = ATWeakExternal; - coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0; - coff_symbol->Aux[0].Aux.WeakExternal.Characteristics = + Sym->Aux.resize(1); + memset(&Sym->Aux[0], 0, sizeof(Sym->Aux[0])); + Sym->Aux[0].AuxType = ATWeakExternal; + Sym->Aux[0].Aux.WeakExternal.TagIndex = 0; + Sym->Aux[0].Aux.WeakExternal.Characteristics = COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY; } else { if (!Base) - coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; + Sym->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; else - coff_symbol->Section = Sec; - Local = coff_symbol; + Sym->Section = Sec; + Local = Sym; } if (Local) { - Local->Data.Value = getSymbolValue(Symbol, Layout); + Local->Data.Value = getSymbolValue(MCSym, Layout); - const MCSymbolCOFF &SymbolCOFF = cast<MCSymbolCOFF>(Symbol); + 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 = Symbol.isExternal() || - (!Symbol.getFragment() && !Symbol.isVariable()); + bool IsExternal = MCSym.isExternal() || + (!MCSym.getFragment() && !MCSym.isVariable()); Local->Data.StorageClass = IsExternal ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC; } } - coff_symbol->MC = &Symbol; + Sym->MC = &MCSym; } // Maximum offsets for different string table entry encodings. @@ -459,24 +433,25 @@ static void encodeBase64StringEntry(char *Buffer, uint64_t Value) { } void WinCOFFObjectWriter::SetSectionName(COFFSection &S) { - if (S.Name.size() > COFF::NameSize) { - 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()); - } else if (StringTableEntry <= MaxBase64Offset) { - // Starting with 10,000,000, offsets are encoded as base64. - encodeBase64StringEntry(S.Header.Name, StringTableEntry); - } else { - report_fatal_error("COFF string table is greater than 64 GB."); - } - } else { + 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) { @@ -583,18 +558,37 @@ void WinCOFFObjectWriter::WriteAuxiliarySymbols( } } -void WinCOFFObjectWriter::writeSectionHeader(const COFF::section &S) { - writeBytes(StringRef(S.Name, COFF::NameSize)); - - writeLE32(S.VirtualSize); - writeLE32(S.VirtualAddress); - writeLE32(S.SizeOfRawData); - writeLE32(S.PointerToRawData); - writeLE32(S.PointerToRelocations); - writeLE32(S.PointerToLineNumbers); - writeLE16(S.NumberOfRelocations); - writeLE16(S.NumberOfLineNumbers); - writeLE32(S.Characteristics); +// Write the section header. +void WinCOFFObjectWriter::writeSectionHeaders() { + // Section numbers must be monotonically increasing in the section + // header, but our Sections array is not sorted by section number, + // so make a copy of Sections and sort it. + std::vector<COFFSection *> Arr; + for (auto &Section : Sections) + Arr.push_back(Section.get()); + std::sort(Arr.begin(), Arr.end(), + [](const COFFSection *A, const COFFSection *B) { + return A->Number < B->Number; + }); + + for (auto &Section : Arr) { + if (Section->Number == -1) + continue; + + COFF::section &S = Section->Header; + if (Section->Relocations.size() >= 0xffff) + S.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL; + writeBytes(StringRef(S.Name, COFF::NameSize)); + writeLE32(S.VirtualSize); + writeLE32(S.VirtualAddress); + writeLE32(S.SizeOfRawData); + writeLE32(S.PointerToRawData); + writeLE32(S.PointerToRelocations); + writeLE32(S.PointerToLineNumbers); + writeLE16(S.NumberOfRelocations); + writeLE16(S.NumberOfLineNumbers); + writeLE32(S.Characteristics); + } } void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) { @@ -603,6 +597,87 @@ void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) { writeLE16(R.Type); } +// Write MCSec's contents. What this function does is essentially +// "Asm.writeSectionData(&MCSec, Layout)", but it's a bit complicated +// because it needs to compute a CRC. +uint32_t WinCOFFObjectWriter::writeSectionContents(MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCSection &MCSec) { + // Save the contents of the section to a temporary buffer, we need this + // to CRC the data before we dump it into the object file. + SmallVector<char, 128> Buf; + raw_svector_ostream VecOS(Buf); + raw_pwrite_stream &OldStream = getStream(); + + // Redirect the output stream to our buffer and fill our buffer with + // the section data. + setStream(VecOS); + Asm.writeSectionData(&MCSec, Layout); + + // Reset the stream back to what it was before. + setStream(OldStream); + + // Write the section contents to the object file. + getStream() << Buf; + + // Calculate our CRC with an initial value of '0', this is not how + // JamCRC is specified but it aligns with the expected output. + JamCRC JC(/*Init=*/0); + JC.update(Buf); + return JC.getCRC(); +} + +void WinCOFFObjectWriter::writeSection(MCAssembler &Asm, + const MCAsmLayout &Layout, + const COFFSection &Sec, + const MCSection &MCSec) { + if (Sec.Number == -1) + return; + + // Write the section contents. + if (Sec.Header.PointerToRawData != 0) { + assert(getStream().tell() <= Sec.Header.PointerToRawData && + "Section::PointerToRawData is insane!"); + + unsigned PaddingSize = Sec.Header.PointerToRawData - getStream().tell(); + assert(PaddingSize < 4 && + "Should only need at most three bytes of padding!"); + WriteZeros(PaddingSize); + + uint32_t CRC = writeSectionContents(Asm, Layout, MCSec); + + // Update the section definition auxiliary symbol to record the CRC. + COFFSection *Sec = SectionMap[&MCSec]; + COFFSymbol::AuxiliarySymbols &AuxSyms = Sec->Symbol->Aux; + assert(AuxSyms.size() == 1 && AuxSyms[0].AuxType == ATSectionDefinition); + AuxSymbol &SecDef = AuxSyms[0]; + SecDef.Aux.SectionDefinition.CheckSum = CRC; + } + + // Write relocations for this section. + if (Sec.Relocations.empty()) { + assert(Sec.Header.PointerToRelocations == 0 && + "Section::PointerToRelocations is insane!"); + return; + } + + assert(getStream().tell() == Sec.Header.PointerToRelocations && + "Section::PointerToRelocations is insane!"); + + if (Sec.Relocations.size() >= 0xffff) { + // In case of overflow, write actual relocation count as first + // relocation. Including the synthetic reloc itself (+ 1). + COFF::relocation R; + R.VirtualAddress = Sec.Relocations.size() + 1; + R.SymbolTableIndex = 0; + R.Type = 0; + WriteRelocation(R); + } + + for (const auto &Relocation : Sec.Relocations) + WriteRelocation(Relocation.Data); +} + //////////////////////////////////////////////////////////////////////////////// // MCObjectWriter interface implementations @@ -632,26 +707,11 @@ bool WinCOFFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl( InSet, IsPCRel); } -bool WinCOFFObjectWriter::isWeak(const MCSymbol &Sym) const { - if (!Sym.isExternal()) - return false; - - if (!Sym.isInSection()) - return false; - - const auto &Sec = cast<MCSectionCOFF>(Sym.getSection()); - if (!Sec.getCOMDATSymbol()) - return false; - - // It looks like for COFF it is invalid to replace a reference to a global - // in a comdat with a reference to a local. - // FIXME: Add a specification reference if available. - return true; -} - -void WinCOFFObjectWriter::recordRelocation( - MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, - const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue) { +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(); @@ -668,15 +728,14 @@ void WinCOFFObjectWriter::recordRelocation( return; } - MCSection *Section = Fragment->getParent(); + MCSection *MCSec = Fragment->getParent(); // Mark this symbol as requiring an entry in the symbol table. - assert(SectionMap.find(Section) != SectionMap.end() && + assert(SectionMap.find(MCSec) != SectionMap.end() && "Section must already have been defined in executePostLayoutBinding!"); - COFFSection *coff_section = SectionMap[Section]; + COFFSection *Sec = SectionMap[MCSec]; const MCSymbolRefExpr *SymB = Target.getSymB(); - bool CrossSection = false; if (SymB) { const MCSymbol *B = &SymB->getSymbol(); @@ -688,28 +747,9 @@ void WinCOFFObjectWriter::recordRelocation( return; } - if (!A.getFragment()) { - Asm.getContext().reportError( - Fixup.getLoc(), - Twine("symbol '") + A.getName() + - "' can not be undefined in a subtraction expression"); - return; - } - - CrossSection = &A.getSection() != &B->getSection(); - // Offset of the symbol in the section int64_t OffsetOfB = Layout.getSymbolOffset(*B); - // In the case where we have SymbA and SymB, we just need to store the delta - // between the two symbols. Update FixedValue to account for the delta, and - // skip recording the relocation. - if (!CrossSection) { - int64_t OffsetOfA = Layout.getSymbolOffset(A); - FixedValue = (OffsetOfA - OffsetOfB) + Target.getConstant(); - return; - } - // Offset of the relocation in the section int64_t OffsetOfRelocation = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); @@ -725,7 +765,7 @@ void WinCOFFObjectWriter::recordRelocation( Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment); // Turn relocations for temporary symbols into section relocations. - if (A.isTemporary() || CrossSection) { + if (A.isTemporary()) { MCSection *TargetSection = &A.getSection(); assert( SectionMap.find(TargetSection) != SectionMap.end() && @@ -743,7 +783,7 @@ void WinCOFFObjectWriter::recordRelocation( Reloc.Data.VirtualAddress += Fixup.getOffset(); Reloc.Data.Type = TargetObjectWriter->getRelocType( - Target, Fixup, CrossSection, Asm.getBackend()); + Asm.getContext(), Target, Fixup, SymB, Asm.getBackend()); // FIXME: Can anyone explain what this does other than adjust for the size // of the offset? @@ -796,46 +836,31 @@ void WinCOFFObjectWriter::recordRelocation( FixedValue = 0; if (TargetObjectWriter->recordRelocation(Fixup)) - coff_section->Relocations.push_back(Reloc); + Sec->Relocations.push_back(Reloc); } -void WinCOFFObjectWriter::writeObject(MCAssembler &Asm, - const MCAsmLayout &Layout) { - size_t SectionsSize = Sections.size(); - if (SectionsSize > static_cast<size_t>(INT32_MAX)) - report_fatal_error( - "PE COFF object files can't have more than 2147483647 sections"); - - // Assign symbol and section indexes and offsets. - int32_t NumberOfSections = static_cast<int32_t>(SectionsSize); - - UseBigObj = NumberOfSections > COFF::MaxNumberOfSections16; - - // Assign section numbers. - size_t Number = 1; - for (const auto &Section : Sections) { - Section->Number = Number; - Section->Symbol->Data.SectionNumber = Number; - Section->Symbol->Aux[0].Aux.SectionDefinition.Number = Number; - ++Number; - } - - Header.NumberOfSections = NumberOfSections; - Header.NumberOfSymbols = 0; +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); + 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) { + for (auto &Aux : File->Aux) { Aux.AuxType = ATFile; if (Length > SymbolSize) { @@ -850,6 +875,109 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm, Offset += SymbolSize; } } +} + +static bool isAssociative(const COFFSection &Section) { + return Section.Symbol->Aux[0].Aux.SectionDefinition.Selection == + COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE; +} + +void WinCOFFObjectWriter::assignSectionNumbers() { + size_t I = 1; + auto Assign = [&](COFFSection &Section) { + Section.Number = I; + Section.Symbol->Data.SectionNumber = I; + Section.Symbol->Aux[0].Aux.SectionDefinition.Number = I; + ++I; + }; + + // Although it is not explicitly requested by the Microsoft COFF spec, + // we should avoid emitting forward associative section references, + // because MSVC link.exe as of 2017 cannot handle that. + for (const std::unique_ptr<COFFSection> &Section : Sections) + if (!isAssociative(*Section)) + Assign(*Section); + for (const std::unique_ptr<COFFSection> &Section : Sections) + if (isAssociative(*Section)) + Assign(*Section); +} + +// Assign file offsets to COFF object file structures. +void WinCOFFObjectWriter::assignFileOffsets(MCAssembler &Asm, + const MCAsmLayout &Layout) { + unsigned Offset = getInitialOffset(); + + Offset += UseBigObj ? COFF::Header32Size : COFF::Header16Size; + Offset += COFF::SectionSize * Header.NumberOfSections; + + for (const auto &Section : Asm) { + COFFSection *Sec = SectionMap[&Section]; + + if (Sec->Number == -1) + continue; + + Sec->Header.SizeOfRawData = Layout.getSectionAddressSize(&Section); + + if (IsPhysicalSection(Sec)) { + // Align the section data to a four byte boundary. + Offset = alignTo(Offset, 4); + Sec->Header.PointerToRawData = Offset; + + Offset += Sec->Header.SizeOfRawData; + } + + if (!Sec->Relocations.empty()) { + bool RelocationsOverflow = Sec->Relocations.size() >= 0xffff; + + if (RelocationsOverflow) { + // Signal overflow by setting NumberOfRelocations to max value. Actual + // size is found in reloc #0. Microsoft tools understand this. + Sec->Header.NumberOfRelocations = 0xffff; + } else { + Sec->Header.NumberOfRelocations = Sec->Relocations.size(); + } + Sec->Header.PointerToRelocations = Offset; + + if (RelocationsOverflow) { + // Reloc #0 will contain actual count, so make room for it. + Offset += COFF::RelocationSize; + } + + Offset += COFF::RelocationSize * Sec->Relocations.size(); + + for (auto &Relocation : Sec->Relocations) { + assert(Relocation.Symb->getIndex() != -1); + Relocation.Data.SymbolTableIndex = Relocation.Symb->getIndex(); + } + } + + assert(Sec->Symbol->Aux.size() == 1 && + "Section's symbol must have one aux!"); + AuxSymbol &Aux = Sec->Symbol->Aux[0]; + assert(Aux.AuxType == ATSectionDefinition && + "Section's symbol's aux symbol must be a Section Definition!"); + Aux.Aux.SectionDefinition.Length = Sec->Header.SizeOfRawData; + Aux.Aux.SectionDefinition.NumberOfRelocations = + Sec->Header.NumberOfRelocations; + Aux.Aux.SectionDefinition.NumberOfLinenumbers = + Sec->Header.NumberOfLineNumbers; + } + + Header.PointerToSymbolTable = Offset; +} + +void WinCOFFObjectWriter::writeObject(MCAssembler &Asm, + const MCAsmLayout &Layout) { + if (Sections.size() > INT32_MAX) + report_fatal_error( + "PE COFF object files can't have more than 2147483647 sections"); + + UseBigObj = Sections.size() > COFF::MaxNumberOfSections16; + Header.NumberOfSections = Sections.size(); + Header.NumberOfSymbols = 0; + + assignSectionNumbers(); + createFileSymbols(Asm); for (auto &Symbol : Symbols) { // Update section number & offset for symbols that have them. @@ -912,78 +1040,12 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm, Section->Symbol->Aux[0].Aux.SectionDefinition.Number = Assoc->Number; } - // Assign file offsets to COFF object file structures. - - unsigned offset = getInitialOffset(); - - if (UseBigObj) - offset += COFF::Header32Size; - else - offset += COFF::Header16Size; - offset += COFF::SectionSize * Header.NumberOfSections; - - for (const auto &Section : Asm) { - COFFSection *Sec = SectionMap[&Section]; - - if (Sec->Number == -1) - continue; - - Sec->Header.SizeOfRawData = Layout.getSectionAddressSize(&Section); - - if (IsPhysicalSection(Sec)) { - // Align the section data to a four byte boundary. - offset = alignTo(offset, 4); - Sec->Header.PointerToRawData = offset; - - offset += Sec->Header.SizeOfRawData; - } - - if (Sec->Relocations.size() > 0) { - 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; + assignFileOffsets(Asm, Layout); // MS LINK expects to be able to use this timestamp to implement their // /INCREMENTAL feature. if (Asm.isIncrementalLinkerCompatible()) { - std::time_t Now = time(nullptr); - if (Now < 0 || !isUInt<32>(Now)) - Now = UINT32_MAX; - Header.TimeDateStamp = Now; + Header.TimeDateStamp = getTime(); } else { // Have deterministic output if /INCREMENTAL isn't needed. Also matches GNU. Header.TimeDateStamp = 0; @@ -991,96 +1053,25 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm, // Write it all to disk... WriteFileHeader(Header); + writeSectionHeaders(); - { - sections::iterator i, ie; - MCAssembler::iterator j, je; - - for (auto &Section : Sections) { - if (Section->Number != -1) { - if (Section->Relocations.size() >= 0xffff) - Section->Header.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL; - writeSectionHeader(Section->Header); - } - } - - SmallVector<char, 128> SectionContents; - for (i = Sections.begin(), ie = Sections.end(), j = Asm.begin(), - je = Asm.end(); - (i != ie) && (j != je); ++i, ++j) { - - if ((*i)->Number == -1) - continue; - - if ((*i)->Header.PointerToRawData != 0) { - assert(getStream().tell() <= (*i)->Header.PointerToRawData && - "Section::PointerToRawData is insane!"); - - unsigned SectionDataPadding = - (*i)->Header.PointerToRawData - getStream().tell(); - assert(SectionDataPadding < 4 && - "Should only need at most three bytes of padding!"); - - WriteZeros(SectionDataPadding); - - // 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. - SectionContents.clear(); - raw_svector_ostream VecOS(SectionContents); - raw_pwrite_stream &OldStream = getStream(); - // Redirect the output stream to our buffer. - setStream(VecOS); - // Fill our buffer with the section data. - Asm.writeSectionData(&*j, Layout); - // Reset the stream back to what it was before. - setStream(OldStream); - - // 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=*/0x00000000U); - JC.update(SectionContents); - - // Write the section contents to the object file. - getStream() << SectionContents; - - // Update the section definition auxiliary symbol to record the CRC. - COFFSection *Sec = SectionMap[&*j]; - COFFSymbol::AuxiliarySymbols &AuxSyms = Sec->Symbol->Aux; - assert(AuxSyms.size() == 1 && - AuxSyms[0].AuxType == ATSectionDefinition); - AuxSymbol &SecDef = AuxSyms[0]; - SecDef.Aux.SectionDefinition.CheckSum = JC.getCRC(); - } - - if ((*i)->Relocations.size() > 0) { - assert(getStream().tell() == (*i)->Header.PointerToRelocations && - "Section::PointerToRelocations is insane!"); - - if ((*i)->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 = (*i)->Relocations.size() + 1; - r.SymbolTableIndex = 0; - r.Type = 0; - WriteRelocation(r); - } - - for (const auto &Relocation : (*i)->Relocations) - WriteRelocation(Relocation.Data); - } else - assert((*i)->Header.PointerToRelocations == 0 && - "Section::PointerToRelocations is insane!"); - } - } + // Write section contents. + sections::iterator I = Sections.begin(); + sections::iterator IE = Sections.end(); + MCAssembler::iterator J = Asm.begin(); + MCAssembler::iterator JE = Asm.end(); + for (; I != IE && J != JE; ++I, ++J) + writeSection(Asm, Layout, **I, *J); assert(getStream().tell() == Header.PointerToSymbolTable && "Header::PointerToSymbolTable is insane!"); + // Write a symbol table. for (auto &Symbol : Symbols) if (Symbol->getIndex() != -1) WriteSymbol(*Symbol); + // Write a string table, which completes the entire COFF file. Strings.write(getStream()); } |