diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:01:22 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:01:22 +0000 |
commit | 71d5a2540a98c81f5bcaeb48805e0e2881f530ef (patch) | |
tree | 5343938942df402b49ec7300a1c25a2d4ccd5821 /lib/MC | |
parent | 31bbf64f3a4974a2d6c8b3b27ad2f519caf74057 (diff) |
Diffstat (limited to 'lib/MC')
61 files changed, 3068 insertions, 1173 deletions
diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt index 2f1b39e58e33..a86fd383003d 100644 --- a/lib/MC/CMakeLists.txt +++ b/lib/MC/CMakeLists.txt @@ -6,6 +6,7 @@ add_llvm_library(LLVMMC MCAsmInfoCOFF.cpp MCAsmInfoDarwin.cpp MCAsmInfoELF.cpp + MCAsmInfoWasm.cpp MCAsmStreamer.cpp MCAssembler.cpp MCCodeEmitter.cpp @@ -34,17 +35,21 @@ add_llvm_library(LLVMMC MCSectionCOFF.cpp MCSectionELF.cpp MCSectionMachO.cpp + MCSectionWasm.cpp MCStreamer.cpp MCSubtargetInfo.cpp MCSymbol.cpp MCSymbolELF.cpp MCTargetOptions.cpp MCValue.cpp + MCWasmObjectTargetWriter.cpp + MCWasmStreamer.cpp MCWin64EH.cpp MCWinEH.cpp MachObjectWriter.cpp StringTableBuilder.cpp SubtargetFeature.cpp + WasmObjectWriter.cpp WinCOFFObjectWriter.cpp WinCOFFStreamer.cpp diff --git a/lib/MC/ConstantPools.cpp b/lib/MC/ConstantPools.cpp index 9608c2c656b7..8c94e2780998 100644 --- a/lib/MC/ConstantPools.cpp +++ b/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/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index a8c88dda6936..ee9c25cda94f 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -11,29 +11,49 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCELFObjectWriter.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/MC/MCAsmBackend.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.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/MCFixupKindInfo.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCFragment.h" #include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbolELF.h" #include "llvm/MC/MCValue.h" #include "llvm/MC/StringTableBuilder.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Compression.h" -#include "llvm/Support/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,6 +62,7 @@ using namespace llvm; #define DEBUG_TYPE "reloc-info" namespace { + typedef DenseMap<const MCSectionELF *, uint32_t> SectionIndexMapTy; class ELFObjectWriter; @@ -99,8 +120,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 +164,8 @@ public: bool IsLittleEndian) : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {} + ~ELFObjectWriter() override = default; + void reset() override { Renames.clear(); Relocations.clear(); @@ -152,8 +174,6 @@ public: MCObjectWriter::reset(); } - ~ELFObjectWriter() override; - void WriteWord(uint64_t W) { if (is64Bit()) write64(W); @@ -222,18 +242,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 +317,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 +387,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()) { @@ -900,6 +901,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, @@ -1037,10 +1040,10 @@ 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; } @@ -1151,8 +1154,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 +1175,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 +1303,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 +1357,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/lib/MC/MCAsmBackend.cpp b/lib/MC/MCAsmBackend.cpp index 570f764f6642..fc0aa788f6d3 100644 --- a/lib/MC/MCAsmBackend.cpp +++ b/lib/MC/MCAsmBackend.cpp @@ -1,4 +1,4 @@ -//===-- MCAsmBackend.cpp - Target MC Assembly Backend ----------------------==// +//===- MCAsmBackend.cpp - Target MC Assembly Backend ----------------------===// // // The LLVM Compiler Infrastructure // @@ -7,14 +7,19 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCAsmBackend.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/MC/MCAsmBackend.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/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index 3eb8f50de5a8..b9be685cedc4 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -1,4 +1,4 @@ -//===-- MCAsmInfo.cpp - Asm Info -------------------------------------------==// +//===- MCAsmInfo.cpp - Asm Info -------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -16,29 +16,14 @@ #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/lib/MC/MCAsmInfoCOFF.cpp b/lib/MC/MCAsmInfoCOFF.cpp index 5b9dd2009f8b..85104484fd40 100644 --- a/lib/MC/MCAsmInfoCOFF.cpp +++ b/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/lib/MC/MCAsmInfoDarwin.cpp b/lib/MC/MCAsmInfoDarwin.cpp index e95cf488cd30..4b2001764e97 100644 --- a/lib/MC/MCAsmInfoDarwin.cpp +++ b/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/MC/MCDirectives.h" #include "llvm/MC/MCSectionMachO.h" +#include "llvm/Support/MachO.h" + using namespace llvm; bool MCAsmInfoDarwin::isSectionAtomizableBySymbols( diff --git a/lib/MC/MCAsmInfoELF.cpp b/lib/MC/MCAsmInfoELF.cpp index 26e5608d8733..e44c08b50d76 100644 --- a/lib/MC/MCAsmInfoELF.cpp +++ b/lib/MC/MCAsmInfoELF.cpp @@ -1,4 +1,4 @@ -//===-- MCAsmInfoELF.cpp - ELF asm properties -------------------*- C++ -*-===// +//===- MCAsmInfoELF.cpp - ELF asm properties ------------------------------===// // // The LLVM Compiler Infrastructure // @@ -16,9 +16,10 @@ #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/lib/MC/MCAsmInfoWasm.cpp b/lib/MC/MCAsmInfoWasm.cpp new file mode 100644 index 000000000000..aa26616dda36 --- /dev/null +++ b/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/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 817009a65363..9e5553fa8d42 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/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/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 83fcec92e2b5..c2bb7b277181 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -7,36 +7,49 @@ // //===----------------------------------------------------------------------===// -#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" #include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCCodeView.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/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 <cstring> +#include <cassert> +#include <cstdint> #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; @@ -219,7 +238,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) && @@ -641,7 +659,7 @@ std::pair<uint64_t, bool> MCAssembler::handleFixup(const MCAsmLayout &Layout, 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 +689,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 @@ -714,8 +732,8 @@ void MCAssembler::layout(MCAsmLayout &Layout) { uint64_t FixedValue; bool IsPCRel; std::tie(FixedValue, IsPCRel) = handleFixup(Layout, Frag, Fixup); - getBackend().applyFixup(Fixup, Contents.data(), - Contents.size(), FixedValue, IsPCRel); + getBackend().applyFixup(Fixup, Contents.data(), Contents.size(), + FixedValue, IsPCRel, getContext()); } } } @@ -741,6 +759,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/lib/MC/MCCodeEmitter.cpp b/lib/MC/MCCodeEmitter.cpp index c122763b2fe5..ca69478ed10d 100644 --- a/lib/MC/MCCodeEmitter.cpp +++ b/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/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp index 4798991ceed6..4628d0ab88f3 100644 --- a/lib/MC/MCContext.cpp +++ b/lib/MC/MCContext.cpp @@ -7,30 +7,43 @@ // //===----------------------------------------------------------------------===// -#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/MC/MCAsmInfo.h" -#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCCodeView.h" +#include "llvm/MC/MCContext.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/MC/MCSymbolWasm.h" +#include "llvm/MC/SectionKind.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/COFF.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Signals.h" #include "llvm/Support/SourceMgr.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); } @@ -510,13 +608,15 @@ CodeViewContext &MCContext::getCVContext() { void MCContext::reportError(SMLoc Loc, const Twine &Msg) { HadError = true; - // If we have a source manager use it. Otherwise just use the generic - // report_fatal_error(). - if (!SrcMgr) + // If we have a source manager use it. Otherwise, try using the inline source + // manager. + // If that fails, use the generic report_fatal_error(). + if (SrcMgr) + SrcMgr->PrintMessage(Loc, SourceMgr::DK_Error, Msg); + else if (InlineSrcMgr) + InlineSrcMgr->PrintMessage(Loc, SourceMgr::DK_Error, Msg); + else report_fatal_error(Msg, false); - - // Use the source manager to print the message. - SrcMgr->PrintMessage(Loc, SourceMgr::DK_Error, Msg); } void MCContext::reportFatalError(SMLoc Loc, const Twine &Msg) { diff --git a/lib/MC/MCDisassembler/MCDisassembler.cpp b/lib/MC/MCDisassembler/MCDisassembler.cpp index 3a4f7382bd3c..2f1275d00b86 100644 --- a/lib/MC/MCDisassembler/MCDisassembler.cpp +++ b/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/lib/MC/MCDisassembler/MCRelocationInfo.cpp b/lib/MC/MCDisassembler/MCRelocationInfo.cpp index 1612562497d9..5805fd7007d2 100644 --- a/lib/MC/MCDisassembler/MCRelocationInfo.cpp +++ b/lib/MC/MCDisassembler/MCRelocationInfo.cpp @@ -1,4 +1,4 @@ -//==-- MCRelocationInfo.cpp ------------------------------------------------==// +//===-- MCRelocationInfo.cpp ----------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -8,17 +8,14 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCDisassembler/MCRelocationInfo.h" -#include "llvm-c/Disassembler.h" #include "llvm/Support/TargetRegistry.h" +#include "llvm-c/Disassembler.h" 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/lib/MC/MCDisassembler/MCSymbolizer.cpp b/lib/MC/MCDisassembler/MCSymbolizer.cpp index c0f707d356c1..78e611e3ddda 100644 --- a/lib/MC/MCDisassembler/MCSymbolizer.cpp +++ b/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/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index a7551a3283a3..cc32e90ad36e 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -7,27 +7,41 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCDwarf.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Hashing.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Config/config.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Support/Debug.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Dwarf.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; @@ -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.getPointerSize(); + 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. @@ -885,7 +902,7 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) { } } - assert((RangesSectionSymbol != NULL) || !UseRangesSection); + assert((RangesSectionSymbol != nullptr) || !UseRangesSection); MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); @@ -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; @@ -1444,10 +1460,12 @@ void FrameEmitterImpl::EmitFDE(const MCSymbol &cieStart, } 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) { diff --git a/lib/MC/MCELFObjectTargetWriter.cpp b/lib/MC/MCELFObjectTargetWriter.cpp index de645cac7370..68fb5e7cbb3d 100644 --- a/lib/MC/MCELFObjectTargetWriter.cpp +++ b/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/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 0ef1b2a8bdca..c8e0223c0573 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -11,30 +11,31 @@ // //===----------------------------------------------------------------------===// -#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/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/MCELFStreamer.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/MCStreamer.h" #include "llvm/MC/MCSymbolELF.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCValue.h" -#include "llvm/Support/Debug.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/ELF.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/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index bcc43a54d620..8149aa27327c 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -7,28 +7,35 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCExpr.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstdint> + using namespace llvm; #define DEBUG_TYPE "mcexpr" namespace { namespace stats { + STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations"); -} -} + +} // end namespace stats +} // end anonymous namespace void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const { switch (getKind()) { @@ -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) diff --git a/lib/MC/MCFragment.cpp b/lib/MC/MCFragment.cpp index 8ff8f8aba1c1..90b44177cf5e 100644 --- a/lib/MC/MCFragment.cpp +++ b/lib/MC/MCFragment.cpp @@ -7,30 +7,29 @@ // //===----------------------------------------------------------------------===// -#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/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/MCFragment.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 +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void MCFragment::dump() { - raw_ostream &OS = llvm::errs(); + raw_ostream &OS = errs(); OS << "<"; switch (getKind()) { @@ -449,7 +446,7 @@ LLVM_DUMP_METHOD void MCFragment::dump() { } LLVM_DUMP_METHOD void MCAssembler::dump() { - raw_ostream &OS = llvm::errs(); + raw_ostream &OS = errs(); OS << "<MCAssembler\n"; OS << " Sections:[\n "; @@ -469,3 +466,4 @@ LLVM_DUMP_METHOD void MCAssembler::dump() { } OS << "]>\n"; } +#endif diff --git a/lib/MC/MCInst.cpp b/lib/MC/MCInst.cpp index 2da8ecc4ff6a..f6d1d3cffca0 100644 --- a/lib/MC/MCInst.cpp +++ b/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/lib/MC/MCInstPrinter.cpp b/lib/MC/MCInstPrinter.cpp index 23afe8054840..912179095974 100644 --- a/lib/MC/MCInstPrinter.cpp +++ b/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 // @@ -7,13 +7,17 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCInstPrinter.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCInstPrinter.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/lib/MC/MCInstrAnalysis.cpp b/lib/MC/MCInstrAnalysis.cpp index 2d8336d77ac7..566944c53548 100644 --- a/lib/MC/MCInstrAnalysis.cpp +++ b/lib/MC/MCInstrAnalysis.cpp @@ -1,4 +1,4 @@ -//===-- MCInstrAnalysis.cpp - InstrDesc target hooks ------------*- C++ -*-===// +//===- MCInstrAnalysis.cpp - InstrDesc target hooks -----------------------===// // // The LLVM Compiler Infrastructure // @@ -7,7 +7,12 @@ // //===----------------------------------------------------------------------===// +#include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrAnalysis.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/lib/MC/MCLabel.cpp b/lib/MC/MCLabel.cpp index b443cbbbf43e..db25a46fce18 100644 --- a/lib/MC/MCLabel.cpp +++ b/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/lib/MC/MCLinkerOptimizationHint.cpp b/lib/MC/MCLinkerOptimizationHint.cpp index f71fc7830129..97f95418e054 100644 --- a/lib/MC/MCLinkerOptimizationHint.cpp +++ b/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/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index bd425bb73093..1e9ef4163256 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/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 "llvm/Support/TargetRegistry.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/lib/MC/MCMachObjectTargetWriter.cpp b/lib/MC/MCMachObjectTargetWriter.cpp index 4ffd6a78a61f..8809a3c320f8 100644 --- a/lib/MC/MCMachObjectTargetWriter.cpp +++ b/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/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp index eb2d91254b34..d156f5d05a31 100644 --- a/lib/MC/MCNullStreamer.cpp +++ b/lib/MC/MCNullStreamer.cpp @@ -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/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp index 8fd71f62e4e5..9f94264684f9 100644 --- a/lib/MC/MCObjectFileInfo.cpp +++ b/lib/MC/MCObjectFileInfo.cpp @@ -16,7 +16,9 @@ #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSectionWasm.h" #include "llvm/Support/COFF.h" +#include "llvm/Support/ELF.h" using namespace llvm; @@ -505,68 +507,75 @@ 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); // 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); + DwarfAddrSection = Ctx->getELFSection(".debug_addr", 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); @@ -799,6 +808,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 +876,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/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index cae5c1f8d156..f7f2253256eb 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -153,8 +153,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 +171,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 +213,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 +238,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 +501,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 +511,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 +583,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/lib/MC/MCObjectWriter.cpp b/lib/MC/MCObjectWriter.cpp index e84f74ae81d6..478b4e84e74a 100644 --- a/lib/MC/MCObjectWriter.cpp +++ b/lib/MC/MCObjectWriter.cpp @@ -8,14 +8,14 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCFragment.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.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/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp index 87ecf9e0227f..38dadfe62135 100644 --- a/lib/MC/MCParser/AsmLexer.cpp +++ b/lib/MC/MCParser/AsmLexer.cpp @@ -11,12 +11,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCParser/AsmLexer.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCParser/AsmLexer.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/Support/SMLoc.h" #include "llvm/Support/SaveAndRestore.h" @@ -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/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index da54155b3b9d..e65ce9f0b936 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -35,6 +35,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,6 +43,7 @@ #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" @@ -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() = default; 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); + 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, @@ -572,11 +573,9 @@ extern MCAsmParserExtension *createCOFFAsmParser(); enum { DEFAULT_ADDRSPACE = 0 }; AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, - const MCAsmInfo &MAI) + const MCAsmInfo &MAI, unsigned CB = 0) : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM), - PlatformParser(nullptr), CurBuffer(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 +596,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); @@ -608,6 +610,10 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, AsmParser::~AsmParser() { assert((HadError || ActiveMacros.empty()) && "Unexpected active macro instantiation!"); + + // Restore the saved diagnostics handler and context for use during + // finalization. + SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext); } void AsmParser::printMacroInstantiations() { @@ -918,7 +924,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: @@ -979,7 +985,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; @@ -1005,7 +1011,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: @@ -1071,19 +1077,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. @@ -1436,6 +1442,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); @@ -1460,7 +1467,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); } } @@ -1617,7 +1624,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); @@ -1626,12 +1633,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 @@ -1650,7 +1651,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, // Emit the label. if (!ParsingInlineAsm) - Out.EmitLabel(Sym); + 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. @@ -1979,7 +1980,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; @@ -2025,7 +2026,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); @@ -3873,6 +3874,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 ':' @@ -4191,7 +4198,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)) @@ -4287,7 +4293,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)) @@ -4416,6 +4421,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"); @@ -5208,7 +5214,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) { @@ -5518,6 +5524,7 @@ bool parseAssignmentExpression(StringRef Name, bool allow_redef, /// \brief Create an MCAsmParser instance. MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C, - MCStreamer &Out, const MCAsmInfo &MAI) { - return new AsmParser(SM, C, Out, MAI); + MCStreamer &Out, const MCAsmInfo &MAI, + unsigned CB) { + return new AsmParser(SM, C, Out, MAI, CB); } diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp index f4114795a92d..bec62ccb2f7f 100644 --- a/lib/MC/MCParser/COFFAsmParser.cpp +++ b/lib/MC/MCParser/COFFAsmParser.cpp @@ -7,19 +7,27 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCParser/MCAsmParserExtension.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.h" -#include "llvm/MC/MCAsmInfo.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/MC/SectionKind.h" #include "llvm/Support/COFF.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/lib/MC/MCParser/DarwinAsmParser.cpp b/lib/MC/MCParser/DarwinAsmParser.cpp index 94aa70ef0326..73a7ad0500c3 100644 --- a/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/lib/MC/MCParser/DarwinAsmParser.cpp @@ -7,22 +7,35 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCParser/MCAsmParserExtension.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.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/MachO.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SMLoc.h" #include "llvm/Support/SourceMgr.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/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp index 8d7ba0d03362..401011a027f4 100644 --- a/lib/MC/MCParser/ELFAsmParser.cpp +++ b/lib/MC/MCParser/ELFAsmParser.cpp @@ -7,17 +7,29 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCParser/MCAsmParserExtension.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/Twine.h" +#include "llvm/ADT/StringRef.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCParser/MCAsmParserExtension.h" +#include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbolELF.h" +#include "llvm/MC/SectionKind.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/ELF.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,7 @@ EndStmt: Type = ELF::SHT_NOTE; else if (TypeName == "unwind") Type = ELF::SHT_X86_64_UNWIND; - else + else if (TypeName.getAsInteger(0, Type)) return TokError("unknown section type"); } @@ -528,8 +617,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 +767,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 +843,4 @@ MCAsmParserExtension *createELFAsmParser() { return new ELFAsmParser; } -} +} // end namespace llvm diff --git a/lib/MC/MCParser/MCAsmLexer.cpp b/lib/MC/MCParser/MCAsmLexer.cpp index 63c0daba09a0..f8fe78aece0c 100644 --- a/lib/MC/MCParser/MCAsmLexer.cpp +++ b/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 // @@ -7,19 +7,17 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/StringRef.h" #include "llvm/MC/MCParser/MCAsmLexer.h" -#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/SMLoc.h" using namespace llvm; -MCAsmLexer::MCAsmLexer() - : TokStart(nullptr), SkipSpace(true), IsAtStartOfStatement(true), - CommentConsumer(nullptr) { +MCAsmLexer::MCAsmLexer() { CurTok.emplace_back(AsmToken::Space, StringRef()); } -MCAsmLexer::~MCAsmLexer() { -} +MCAsmLexer::~MCAsmLexer() = default; SMLoc MCAsmLexer::getLoc() const { return SMLoc::getFromPointer(TokStart); diff --git a/lib/MC/MCParser/MCAsmParser.cpp b/lib/MC/MCParser/MCAsmParser.cpp index 98f4daf972d6..27b37f3e2dfb 100644 --- a/lib/MC/MCParser/MCAsmParser.cpp +++ b/lib/MC/MCParser/MCAsmParser.cpp @@ -7,22 +7,22 @@ // //===----------------------------------------------------------------------===// -#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/MCAsmParser.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/lib/MC/MCParser/MCAsmParserExtension.cpp b/lib/MC/MCParser/MCAsmParserExtension.cpp index 3f25a14926b6..031f473dc5fe 100644 --- a/lib/MC/MCParser/MCAsmParserExtension.cpp +++ b/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/lib/MC/MCParser/MCTargetAsmParser.cpp b/lib/MC/MCParser/MCTargetAsmParser.cpp index 14a22c6b8a2f..5f821443bb96 100644 --- a/lib/MC/MCParser/MCTargetAsmParser.cpp +++ b/lib/MC/MCParser/MCTargetAsmParser.cpp @@ -1,4 +1,4 @@ -//===-- MCTargetAsmParser.cpp - Target Assembly Parser ---------------------==// +//===-- MCTargetAsmParser.cpp - Target Assembly Parser --------------------===// // // The LLVM Compiler Infrastructure // @@ -7,19 +7,16 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCParser/MCTargetAsmParser.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCParser/MCTargetAsmParser.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/lib/MC/MCRegisterInfo.cpp b/lib/MC/MCRegisterInfo.cpp index ea117f3caa85..a75100a4876b 100644 --- a/lib/MC/MCRegisterInfo.cpp +++ b/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 // @@ -11,9 +11,12 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/DenseMap.h" #include "llvm/MC/MCRegisterInfo.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ErrorHandling.h" +#include <algorithm> +#include <cassert> +#include <cstdint> using namespace llvm; diff --git a/lib/MC/MCSection.cpp b/lib/MC/MCSection.cpp index 9064cdf2f319..7986c0122043 100644 --- a/lib/MC/MCSection.cpp +++ b/lib/MC/MCSection.cpp @@ -7,17 +7,18 @@ // //===----------------------------------------------------------------------===// -#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/MCSection.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; } +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void MCSection::dump() { - raw_ostream &OS = llvm::errs(); + raw_ostream &OS = errs(); OS << "<MCSection"; OS << " Fragments:[\n "; @@ -97,3 +98,4 @@ LLVM_DUMP_METHOD void MCSection::dump() { } OS << "]>"; } +#endif diff --git a/lib/MC/MCSectionCOFF.cpp b/lib/MC/MCSectionCOFF.cpp index f2dd47d81b7e..f0709cbc2515 100644 --- a/lib/MC/MCSectionCOFF.cpp +++ b/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/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/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp index 587b28f71b7d..78fe01cca24a 100644 --- a/lib/MC/MCSectionELF.cpp +++ b/lib/MC/MCSectionELF.cpp @@ -7,23 +7,23 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCSectionELF.h" +#include "llvm/ADT/Triple.h" #include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCSectionELF.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,13 @@ 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 + report_fatal_error("unsupported type 0x" + Twine::utohexstr(Type) + + " for section " + getSectionName()); if (EntrySize) { assert(Flags & ELF::SHF_MERGE); @@ -149,6 +162,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/lib/MC/MCSectionMachO.cpp b/lib/MC/MCSectionMachO.cpp index c2a772fdbdac..f40237231a2f 100644 --- a/lib/MC/MCSectionMachO.cpp +++ b/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/lib/MC/MCSectionWasm.cpp b/lib/MC/MCSectionWasm.cpp new file mode 100644 index 000000000000..c61f28e129f5 --- /dev/null +++ b/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/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index fb28f856f671..c9a6f12b6a58 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -7,36 +7,44 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCStreamer.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.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/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCWin64EH.h" +#include "llvm/MC/MCWinEH.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/COFF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/LEB128.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include <cstdlib> -using namespace llvm; +#include <cassert> +#include <cstdint> +#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/lib/MC/MCSubtargetInfo.cpp b/lib/MC/MCSubtargetInfo.cpp index 1b592504b1e4..777b4e3d6b67 100644 --- a/lib/MC/MCSubtargetInfo.cpp +++ b/lib/MC/MCSubtargetInfo.cpp @@ -1,4 +1,4 @@ -//===-- MCSubtargetInfo.cpp - Subtarget Information -----------------------===// +//===- MCSubtargetInfo.cpp - Subtarget Information ------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,13 +7,16 @@ // //===----------------------------------------------------------------------===// -#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/MCSubtargetInfo.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> +#include <cassert> +#include <cstring> using namespace llvm; diff --git a/lib/MC/MCSymbol.cpp b/lib/MC/MCSymbol.cpp index 20d985df7ea0..cb262542b89f 100644 --- a/lib/MC/MCSymbol.cpp +++ b/lib/MC/MCSymbol.cpp @@ -7,13 +7,19 @@ // //===----------------------------------------------------------------------===// -#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/MC/MCSymbol.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/lib/MC/MCSymbolELF.cpp b/lib/MC/MCSymbolELF.cpp index ec7ef447ff89..ffa8260d4342 100644 --- a/lib/MC/MCSymbolELF.cpp +++ b/lib/MC/MCSymbolELF.cpp @@ -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/lib/MC/MCTargetOptions.cpp b/lib/MC/MCTargetOptions.cpp index 419210537eea..5d666b67fddb 100644 --- a/lib/MC/MCTargetOptions.cpp +++ b/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 // @@ -10,19 +10,16 @@ #include "llvm/ADT/StringRef.h" #include "llvm/MC/MCTargetOptions.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/lib/MC/MCValue.cpp b/lib/MC/MCValue.cpp index c1336d6d1b49..32a6adbf224e 100644 --- a/lib/MC/MCValue.cpp +++ b/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/lib/MC/MCWasmObjectTargetWriter.cpp b/lib/MC/MCWasmObjectTargetWriter.cpp new file mode 100644 index 000000000000..a09a17d7a124 --- /dev/null +++ b/lib/MC/MCWasmObjectTargetWriter.cpp @@ -0,0 +1,27 @@ +//===-- 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_) {} + +bool MCWasmObjectTargetWriter::needsRelocateWithSymbol(const MCSymbol &Sym, + unsigned Type) const { + return false; +} + +void MCWasmObjectTargetWriter::sortRelocs( + const MCAssembler &Asm, std::vector<WasmRelocationEntry> &Relocs) { +} diff --git a/lib/MC/MCWasmStreamer.cpp b/lib/MC/MCWasmStreamer.cpp new file mode 100644 index 000000000000..59b62b8d37c3 --- /dev/null +++ b/lib/MC/MCWasmStreamer.cpp @@ -0,0 +1,216 @@ +//===- 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: + return false; + 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 + 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/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index c4b35f5db9b4..d9ccf0dd661f 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/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/iterator_range.h" #include "llvm/ADT/Twine.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" diff --git a/lib/MC/StringTableBuilder.cpp b/lib/MC/StringTableBuilder.cpp index 1a501bcafc12..fbd7ba60bc90 100644 --- a/lib/MC/StringTableBuilder.cpp +++ b/lib/MC/StringTableBuilder.cpp @@ -1,4 +1,4 @@ -//===-- StringTableBuilder.cpp - String table building utility ------------===// +//===- StringTableBuilder.cpp - String table building utility -------------===// // // The LLVM Compiler Infrastructure // @@ -7,18 +7,24 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/StringTableBuilder.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/StringTableBuilder.h" #include "llvm/Support/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,7 +54,7 @@ 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; } diff --git a/lib/MC/SubtargetFeature.cpp b/lib/MC/SubtargetFeature.cpp index 32f06f8a7d6a..51aaa4b0aa25 100644 --- a/lib/MC/SubtargetFeature.cpp +++ b/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/MC/SubtargetFeature.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/lib/MC/WasmObjectWriter.cpp b/lib/MC/WasmObjectWriter.cpp new file mode 100644 index 000000000000..159cc3b4def2 --- /dev/null +++ b/lib/MC/WasmObjectWriter.cpp @@ -0,0 +1,1149 @@ +//===- 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/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 "llvm/Support/Wasm.h" +#include <vector> + +using namespace llvm; + +#undef DEBUG_TYPE +#define DEBUG_TYPE "reloc-info" + +namespace { +// For patching purposes, we need to remember where each section starts, both +// for patching up the section size field, and for patching up references to +// locations within the section. +struct SectionBookkeeping { + // Where the size of the section is written. + uint64_t SizeOffset; + // Where the contents of the section starts (after the header). + uint64_t ContentsOffset; +}; + +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; + + // Fixups for call_indirect type indices. + std::vector<WasmRelocationEntry> TypeIndexFixups; + + // Index values to use for fixing up call_indirect type indices. + std::vector<uint32_t> TypeIndexFixupTypes; + + // TargetObjectWriter wrappers. + bool is64Bit() const { return TargetObjectWriter->is64Bit(); } + unsigned getRelocType(MCContext &Ctx, const MCValue &Target, + const MCFixup &Fixup, bool IsPCRel) const { + return TargetObjectWriter->getRelocType(Ctx, Target, Fixup, IsPCRel); + } + + 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: + void reset() override { + MCObjectWriter::reset(); + } + + ~WasmObjectWriter() override; + + void writeHeader(const MCAssembler &Asm); + + void writeValueType(wasm::ValType Ty) { + encodeSLEB128(int32_t(Ty), getStream()); + } + + void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, bool &IsPCRel, + uint64_t &FixedValue) override; + + void executePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) override; + + void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; +}; +} // 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"); + + 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) { + encodeULEB128(strlen(Name), getStream()); + writeBytes(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"); + + unsigned Padding = PaddingFor5ByteULEB128(Size); + + // Write the final section size to the payload_len field, which follows + // the section id byte. + uint8_t Buffer[16]; + unsigned SizeLen = encodeULEB128(Size, Buffer, Padding); + assert(SizeLen == 5); + getStream().pwrite((char *)Buffer, SizeLen, Section.SizeOffset); +} + +// Emit the Wasm header. +void WasmObjectWriter::writeHeader(const MCAssembler &Asm) { + writeBytes(StringRef(wasm::WasmMagic, sizeof(wasm::WasmMagic))); + writeLE32(wasm::WasmVersion); +} + +void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) { +} + +void WasmObjectWriter::recordRelocation(MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + bool &IsPCRel, uint64_t &FixedValue) { + MCSectionWasm &FixupSection = cast<MCSectionWasm>(*Fragment->getParent()); + uint64_t C = Target.getConstant(); + uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + MCContext &Ctx = Asm.getContext(); + + if (const MCSymbolRefExpr *RefB = Target.getSymB()) { + assert(RefB->getKind() == MCSymbolRefExpr::VK_None && + "Should not have constructed this"); + + // Let A, B and C being the components of Target and R be the location of + // the fixup. If the fixup is not pcrel, we want to compute (A - B + C). + // If it is pcrel, we want to compute (A - B + C - R). + + // In general, Wasm has no relocations for -B. It can only represent (A + C) + // or (A + C - R). If B = R + K and the relocation is not pcrel, we can + // replace B to implement it: (A - R - K + C) + if (IsPCRel) { + Ctx.reportError( + Fixup.getLoc(), + "No relocation available to represent this relative expression"); + return; + } + + const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol()); + + if (SymB.isUndefined()) { + Ctx.reportError(Fixup.getLoc(), + Twine("symbol '") + SymB.getName() + + "' can not be undefined in a subtraction expression"); + return; + } + + assert(!SymB.isAbsolute() && "Should have been folded"); + const MCSection &SecB = SymB.getSection(); + if (&SecB != &FixupSection) { + Ctx.reportError(Fixup.getLoc(), + "Cannot represent a difference across sections"); + return; + } + + uint64_t SymBOffset = Layout.getSymbolOffset(SymB); + uint64_t K = SymBOffset - FixupOffset; + IsPCRel = true; + C -= K; + } + + // We either rejected the fixup or folded B into C at this point. + const MCSymbolRefExpr *RefA = Target.getSymA(); + const auto *SymA = RefA ? cast<MCSymbolWasm>(&RefA->getSymbol()) : nullptr; + + bool ViaWeakRef = false; + if (SymA && SymA->isVariable()) { + const MCExpr *Expr = SymA->getVariableValue(); + if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr)) { + if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) { + SymA = cast<MCSymbolWasm>(&Inner->getSymbol()); + ViaWeakRef = true; + } + } + } + + // Put any constant offset in an addend. Offsets can be negative, and + // LLVM expects wrapping, in contrast to wasm's immediates which can't + // be negative and don't wrap. + FixedValue = 0; + + if (SymA) { + if (ViaWeakRef) + llvm_unreachable("weakref used in reloc not yet implemented"); + else + SymA->setUsedInReloc(); + } + + if (RefA) { + if (RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_TYPEINDEX) { + assert(C == 0); + WasmRelocationEntry Rec(FixupOffset, SymA, C, + wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB, + &FixupSection); + TypeIndexFixups.push_back(Rec); + return; + } + } + + unsigned Type = getRelocType(Ctx, Target, Fixup, IsPCRel); + + WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection); + + if (FixupSection.hasInstructions()) + CodeRelocations.push_back(Rec); + else + DataRelocations.push_back(Rec); +} + +namespace { + +// 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; +}; + +} // end anonymous namespace + +// 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(false)) + return UINT32_MAX; + + MCSectionWasm &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; +} + +// Apply the portions of the relocation records that we can handle ourselves +// directly. +static void ApplyRelocations( + ArrayRef<WasmRelocationEntry> Relocations, + raw_pwrite_stream &Stream, + DenseMap<const MCSymbolWasm *, uint32_t> &SymbolIndices, + uint64_t ContentsOffset) +{ + for (const WasmRelocationEntry &RelEntry : Relocations) { + uint64_t Offset = ContentsOffset + + RelEntry.FixupSection->getSectionOffset() + + RelEntry.Offset; + switch (RelEntry.Type) { + case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: { + uint32_t Index = SymbolIndices[RelEntry.Symbol]; + assert(RelEntry.Addend == 0); + + WritePatchableLEB(Stream, Index, Offset); + break; + } + case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: { + uint32_t Index = SymbolIndices[RelEntry.Symbol]; + assert(RelEntry.Addend == 0); + + WritePatchableSLEB(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_TABLE_INDEX_I32: { + uint32_t Index = SymbolIndices[RelEntry.Symbol]; + assert(RelEntry.Addend == 0); + + WriteI32(Stream, Index, Offset); + break; + } + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: { + uint32_t Value = ProvisionalValue(RelEntry); + + WriteI32(Stream, Value, Offset); + break; + } + default: + break; + } + } +} + +// Write out the portions of the relocation records that the linker will +// need to handle. +static void WriteRelocations( + ArrayRef<WasmRelocationEntry> Relocations, + raw_pwrite_stream &Stream, + DenseMap<const MCSymbolWasm *, uint32_t> &SymbolIndices) +{ + for (const WasmRelocationEntry RelEntry : Relocations) { + encodeULEB128(RelEntry.Type, Stream); + + uint64_t Offset = RelEntry.Offset + + RelEntry.FixupSection->getSectionOffset(); + uint32_t Index = SymbolIndices[RelEntry.Symbol]; + int64_t Addend = RelEntry.Addend; + + switch (RelEntry.Type) { + case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: + case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: + case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: + encodeULEB128(Offset, Stream); + encodeULEB128(Index, Stream); + assert(Addend == 0 && "addends not supported for functions"); + break; + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: + encodeULEB128(Offset, Stream); + encodeULEB128(Index, Stream); + encodeSLEB128(Addend, Stream); + break; + default: + llvm_unreachable("unsupported relocation type"); + } + } +} + +// Write out the the type relocation records that the linker will +// need to handle. +static void WriteTypeRelocations( + ArrayRef<WasmRelocationEntry> TypeIndexFixups, + ArrayRef<uint32_t> TypeIndexFixupTypes, + raw_pwrite_stream &Stream) +{ + for (size_t i = 0, e = TypeIndexFixups.size(); i < e; ++i) { + const WasmRelocationEntry &Fixup = TypeIndexFixups[i]; + uint32_t Type = TypeIndexFixupTypes[i]; + + assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB); + assert(Fixup.Addend == 0); + + uint64_t Offset = Fixup.Offset + + Fixup.FixupSection->getSectionOffset(); + + encodeULEB128(Fixup.Type, Stream); + encodeULEB128(Offset, Stream); + encodeULEB128(Type, Stream); + } +} + +void WasmObjectWriter::writeObject(MCAssembler &Asm, + const MCAsmLayout &Layout) { + MCContext &Ctx = Asm.getContext(); + wasm::ValType PtrType = is64Bit() ? wasm::ValType::I64 : wasm::ValType::I32; + + // Collect information from the available symbols. + DenseMap<WasmFunctionType, int32_t, WasmFunctionTypeDenseMapInfo> + FunctionTypeIndices; + SmallVector<WasmFunctionType, 4> FunctionTypes; + SmallVector<WasmFunction, 4> Functions; + SmallVector<uint32_t, 4> TableElems; + SmallVector<WasmGlobal, 4> Globals; + SmallVector<WasmImport, 4> Imports; + SmallVector<WasmExport, 4> Exports; + DenseMap<const MCSymbolWasm *, uint32_t> SymbolIndices; + SmallPtrSet<const MCSymbolWasm *, 4> IsAddressTaken; + unsigned NumFuncImports = 0; + unsigned NumGlobalImports = 0; + SmallVector<char, 0> DataBytes; + uint32_t StackPointerGlobal = 0; + bool HasStackPointer = false; + + // Populate the IsAddressTaken set. + for (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 (WasmRelocationEntry RelEntry : DataRelocations) { + switch (RelEntry.Type) { + case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: + IsAddressTaken.insert(RelEntry.Symbol); + break; + default: + break; + } + } + + // Populate the Imports set. + for (const MCSymbol &S : Asm.symbols()) { + const auto &WS = static_cast<const MCSymbolWasm &>(S); + int32_t Type; + + if (WS.isFunction()) { + // Prepare the function's type, if we haven't seen it yet. + WasmFunctionType F; + F.Returns = WS.getReturns(); + F.Params = WS.getParams(); + auto Pair = + FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size())); + if (Pair.second) + FunctionTypes.push_back(F); + + Type = Pair.first->second; + } else { + Type = int32_t(PtrType); + } + + // If the symbol is not defined in this translation unit, import it. + if (!WS.isTemporary() && !WS.isDefined(/*SetUsed=*/false)) { + WasmImport Import; + Import.ModuleName = WS.getModuleName(); + Import.FieldName = WS.getName(); + + if (WS.isFunction()) { + Import.Kind = wasm::WASM_EXTERNAL_FUNCTION; + Import.Type = Type; + SymbolIndices[&WS] = NumFuncImports; + ++NumFuncImports; + } else { + Import.Kind = wasm::WASM_EXTERNAL_GLOBAL; + Import.Type = Type; + SymbolIndices[&WS] = NumGlobalImports; + ++NumGlobalImports; + } + + Imports.push_back(Import); + } + } + + // In the special .global_variables section, we've encoded global + // variables used by the function. Translate them into the Globals + // list. + MCSectionWasm *GlobalVars = Ctx.getWasmSection(".global_variables", 0, 0); + if (!GlobalVars->getFragmentList().empty()) { + if (GlobalVars->getFragmentList().size() != 1) + report_fatal_error("only one .global_variables fragment supported"); + const MCFragment &Frag = *GlobalVars->begin(); + if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data) + report_fatal_error("only data supported in .global_variables"); + const MCDataFragment &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 MCDataFragment &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 defined symbols. + for (const MCSymbol &S : Asm.symbols()) { + // Ignore unnamed temporary symbols, which aren't ever exported, imported, + // or used in relocations. + if (S.isTemporary() && S.getName().empty()) + continue; + const auto &WS = static_cast<const MCSymbolWasm &>(S); + unsigned Index; + if (WS.isFunction()) { + // Prepare the function's type, if we haven't seen it yet. + WasmFunctionType F; + F.Returns = WS.getReturns(); + F.Params = WS.getParams(); + auto Pair = + FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size())); + if (Pair.second) + FunctionTypes.push_back(F); + + int32_t Type = Pair.first->second; + + if (WS.isDefined(/*SetUsed=*/false)) { + // A definition. Take the next available index. + Index = NumFuncImports + Functions.size(); + + // Prepare the function. + WasmFunction Func; + Func.Type = Type; + Func.Sym = &WS; + SymbolIndices[&WS] = Index; + Functions.push_back(Func); + } else { + // An import; the index was assigned above. + Index = SymbolIndices.find(&WS)->second; + } + + // If needed, prepare the function to be called indirectly. + if (IsAddressTaken.count(&WS)) + TableElems.push_back(Index); + } else { + // For now, ignore temporary non-function symbols. + if (S.isTemporary()) + continue; + + if (WS.getOffset() != 0) + report_fatal_error("data sections must contain one variable each"); + if (!WS.getSize()) + report_fatal_error("data symbols must have a size set with .size"); + + int64_t Size = 0; + if (!WS.getSize()->evaluateAsAbsolute(Size, Layout)) + report_fatal_error(".size expression must be evaluatable"); + + if (WS.isDefined(false)) { + MCSectionWasm &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())); + + DataSection.setSectionOffset(DataBytes.size()); + + for (MCSection::iterator I = DataSection.begin(), E = DataSection.end(); + I != E; ++I) { + const MCFragment &Frag = *I; + if (Frag.hasInstructions()) + report_fatal_error("only data supported in data sections"); + + if (const MCAlignFragment *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 (const MCFillFragment *Fill = + dyn_cast<MCFillFragment>(&Frag)) { + DataBytes.insert(DataBytes.end(), Size, Fill->getValue()); + } else { + const MCDataFragment &DataFrag = cast<MCDataFragment>(Frag); + const SmallVectorImpl<char> &Contents = DataFrag.getContents(); + + DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end()); + } + } + + // For each external global, prepare a corresponding wasm global + // holding its address. + if (WS.isExternal()) { + Index = NumGlobalImports + Globals.size(); + + WasmGlobal Global; + Global.Type = PtrType; + Global.IsMutable = false; + Global.HasImport = false; + Global.InitialValue = DataSection.getSectionOffset(); + Global.ImportIndex = 0; + SymbolIndices[&WS] = Index; + Globals.push_back(Global); + } + } + } + + // If the symbol is visible outside this translation unit, export it. + if (WS.isExternal()) { + assert(WS.isDefined(false)); + WasmExport Export; + Export.FieldName = WS.getName(); + Export.Index = Index; + + if (WS.isFunction()) + Export.Kind = wasm::WASM_EXTERNAL_FUNCTION; + else + Export.Kind = wasm::WASM_EXTERNAL_GLOBAL; + + Exports.push_back(Export); + } + } + + // Add types for indirect function calls. + for (const WasmRelocationEntry &Fixup : TypeIndexFixups) { + assert(Fixup.Addend == 0); + assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB); + + WasmFunctionType F; + F.Returns = Fixup.Symbol->getReturns(); + F.Params = Fixup.Symbol->getParams(); + auto Pair = + FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size())); + if (Pair.second) + FunctionTypes.push_back(F); + + TypeIndexFixupTypes.push_back(Pair.first->second); + } + + // Write out the Wasm header. + writeHeader(Asm); + + SectionBookkeeping Section; + + // === Type Section ========================================================= + if (!FunctionTypes.empty()) { + startSection(Section, wasm::WASM_SEC_TYPE); + + encodeULEB128(FunctionTypes.size(), getStream()); + + for (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); + } + + // === Import Section ======================================================== + if (!Imports.empty()) { + startSection(Section, wasm::WASM_SEC_IMPORT); + + encodeULEB128(Imports.size(), getStream()); + for (const WasmImport &Import : Imports) { + StringRef ModuleName = Import.ModuleName; + encodeULEB128(ModuleName.size(), getStream()); + writeBytes(ModuleName); + + StringRef FieldName = Import.FieldName; + encodeULEB128(FieldName.size(), getStream()); + writeBytes(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); + } + + // === Function Section ====================================================== + if (!Functions.empty()) { + startSection(Section, wasm::WASM_SEC_FUNCTION); + + encodeULEB128(Functions.size(), getStream()); + for (const WasmFunction &Func : Functions) + encodeULEB128(Func.Type, getStream()); + + endSection(Section); + } + + // === Table Section ========================================================= + // 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. + startSection(Section, wasm::WASM_SEC_TABLE); + + // The number of tables, fixed to 1 for now. + encodeULEB128(1, getStream()); + + encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream()); + + encodeULEB128(0, getStream()); // flags + encodeULEB128(TableElems.size(), getStream()); // initial + + endSection(Section); + + // === Memory Section ======================================================== + // 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. + startSection(Section, wasm::WASM_SEC_MEMORY); + + encodeULEB128(1, getStream()); // number of memory spaces + + encodeULEB128(0, getStream()); // flags + encodeULEB128(DataBytes.size(), getStream()); // initial + + endSection(Section); + + // === Global Section ======================================================== + if (!Globals.empty()) { + 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); + } + + // === Export Section ======================================================== + if (!Exports.empty()) { + startSection(Section, wasm::WASM_SEC_EXPORT); + + encodeULEB128(Exports.size(), getStream()); + for (const WasmExport &Export : Exports) { + encodeULEB128(Export.FieldName.size(), getStream()); + writeBytes(Export.FieldName); + + encodeSLEB128(Export.Kind, getStream()); + + encodeULEB128(Export.Index, getStream()); + } + + endSection(Section); + } + +#if 0 // TODO: Start Section + if (HaveStartFunction) { + // === Start Section ========================================================= + startSection(Section, wasm::WASM_SEC_START); + + encodeSLEB128(StartFunction, getStream()); + + endSection(Section); + } +#endif + + // === Elem Section ========================================================== + if (!TableElems.empty()) { + 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); + } + + // === Code Section ========================================================== + if (!Functions.empty()) { + startSection(Section, wasm::WASM_SEC_CODE); + + encodeULEB128(Functions.size(), getStream()); + + for (const WasmFunction &Func : Functions) { + MCSectionWasm &FuncSection = + static_cast<MCSectionWasm &>(Func.Sym->getSection()); + + if (Func.Sym->isVariable()) + report_fatal_error("weak symbols not supported yet"); + + if (Func.Sym->getOffset() != 0) + report_fatal_error("function sections must contain one function each"); + + if (!Func.Sym->getSize()) + report_fatal_error("function symbols must have a size set with .size"); + + 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 the type index fixups for call_indirect etc. instructions. + for (size_t i = 0, e = TypeIndexFixups.size(); i < e; ++i) { + uint32_t Type = TypeIndexFixupTypes[i]; + unsigned Padding = PaddingFor5ByteULEB128(Type); + + const WasmRelocationEntry &Fixup = TypeIndexFixups[i]; + assert(Fixup.Addend == 0); + assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB); + uint64_t Offset = Fixup.Offset + + Fixup.FixupSection->getSectionOffset(); + + uint8_t Buffer[16]; + unsigned SizeLen = encodeULEB128(Type, Buffer, Padding); + assert(SizeLen == 5); + getStream().pwrite((char *)Buffer, SizeLen, + Section.ContentsOffset + Offset); + } + + // Apply fixups. + ApplyRelocations(CodeRelocations, getStream(), SymbolIndices, + Section.ContentsOffset); + + endSection(Section); + } + + // === Data Section ========================================================== + if (!DataBytes.empty()) { + 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 + writeBytes(DataBytes); // data + + // Apply fixups. + ApplyRelocations(DataRelocations, getStream(), SymbolIndices, + Section.ContentsOffset); + + endSection(Section); + } + + // === Name Section ========================================================== + uint32_t TotalFunctions = NumFuncImports + Functions.size(); + if (TotalFunctions != 0) { + 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()); + encodeULEB128(Import.FieldName.size(), getStream()); + writeBytes(Import.FieldName); + ++Index; + } + } + for (const WasmFunction &Func : Functions) { + encodeULEB128(Index, getStream()); + encodeULEB128(Func.Sym->getName().size(), getStream()); + writeBytes(Func.Sym->getName()); + ++Index; + } + + endSection(SubSection); + endSection(Section); + } + + // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md + // for descriptions of the reloc sections. + + // === Code Reloc Section ==================================================== + if (!CodeRelocations.empty()) { + startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.CODE"); + + encodeULEB128(wasm::WASM_SEC_CODE, getStream()); + + encodeULEB128(CodeRelocations.size(), getStream()); + + WriteRelocations(CodeRelocations, getStream(), SymbolIndices); + WriteTypeRelocations(TypeIndexFixups, TypeIndexFixupTypes, getStream()); + + endSection(Section); + } + + // === Data Reloc Section ==================================================== + if (!DataRelocations.empty()) { + startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.DATA"); + + encodeULEB128(wasm::WASM_SEC_DATA, getStream()); + + encodeULEB128(DataRelocations.size(), getStream()); + + WriteRelocations(DataRelocations, getStream(), SymbolIndices); + + endSection(Section); + } + + // === Linking Metadata Section ============================================== + if (HasStackPointer) { + startSection(Section, wasm::WASM_SEC_CUSTOM, "linking"); + + encodeULEB128(1, getStream()); // count + + encodeULEB128(wasm::WASM_STACK_POINTER, getStream()); // type + encodeULEB128(StackPointerGlobal, getStream()); // id + + endSection(Section); + } + + // 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/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp index afc5c6a14d11..da8fe73f823b 100644 --- a/lib/MC/WinCOFFObjectWriter.cpp +++ b/lib/MC/WinCOFFObjectWriter.cpp @@ -1,4 +1,4 @@ -//===-- llvm/MC/WinCOFFObjectWriter.cpp -------------------------*- C++ -*-===// +//===- llvm/MC/WinCOFFObjectWriter.cpp ------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -11,37 +11,49 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCWinCOFFObjectWriter.h" #include "llvm/ADT/DenseMap.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/Config/config.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" -#include "llvm/MC/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/Casting.h" #include "llvm/Support/COFF.h" -#include "llvm/Support/Debug.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 <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; enum AuxiliaryType { @@ -57,25 +69,24 @@ struct AuxSymbol { COFF::Auxiliary Aux; }; -class COFFSymbol; class COFFSection; class COFFSymbol { public: - COFF::symbol Data; + COFF::symbol Data = {}; typedef SmallVector<AuxSymbol, 1> AuxiliarySymbols; 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,9 +100,10 @@ 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; } }; @@ -99,15 +111,15 @@ typedef std::vector<COFFRelocation> relocations; 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 { @@ -121,7 +133,7 @@ public: 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 +161,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 +177,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 +194,29 @@ 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; + 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,23 +707,6 @@ 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) { @@ -668,13 +726,13 @@ 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; @@ -796,46 +854,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 +893,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 +1058,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 +1071,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()); } diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp index 6383d8794030..c26d87f36f83 100644 --- a/lib/MC/WinCOFFStreamer.cpp +++ b/lib/MC/WinCOFFStreamer.cpp @@ -1,4 +1,4 @@ -//===-- llvm/MC/WinCOFFStreamer.cpp -----------------------------*- C++ -*-===// +//===- llvm/MC/WinCOFFStreamer.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/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/Casting.h" #include "llvm/Support/COFF.h" -#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SMLoc.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) { @@ -275,10 +278,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 +294,3 @@ void MCWinCOFFStreamer::FinishImpl() { void MCWinCOFFStreamer::Error(const Twine &Msg) const { getContext().reportError(SMLoc(), Msg); } -} - |