diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2017-01-14 19:56:11 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2017-01-14 19:56:11 +0000 |
commit | ca82c85029ae0befb17bc14a4faa9f3d51dd72b3 (patch) | |
tree | 2df9dea922feef454abe6d1499112a4abc270079 /gnu/llvm/lib/MC | |
parent | 04c0d479b956b5e4f4e20ce989b95443aa03da0b (diff) |
Import LLVM 3.9.1 including clang and lld.
Diffstat (limited to 'gnu/llvm/lib/MC')
48 files changed, 2618 insertions, 1276 deletions
diff --git a/gnu/llvm/lib/MC/CMakeLists.txt b/gnu/llvm/lib/MC/CMakeLists.txt index 8c015644d8a..2f1b39e58e3 100644 --- a/gnu/llvm/lib/MC/CMakeLists.txt +++ b/gnu/llvm/lib/MC/CMakeLists.txt @@ -9,7 +9,7 @@ add_llvm_library(LLVMMC MCAsmStreamer.cpp MCAssembler.cpp MCCodeEmitter.cpp - MCCodeGenInfo.cpp + MCCodeView.cpp MCContext.cpp MCDwarf.cpp MCELFObjectTargetWriter.cpp @@ -38,7 +38,6 @@ add_llvm_library(LLVMMC MCSubtargetInfo.cpp MCSymbol.cpp MCSymbolELF.cpp - MCSymbolizer.cpp MCTargetOptions.cpp MCValue.cpp MCWin64EH.cpp @@ -48,7 +47,6 @@ add_llvm_library(LLVMMC SubtargetFeature.cpp WinCOFFObjectWriter.cpp WinCOFFStreamer.cpp - YAML.cpp ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/MC diff --git a/gnu/llvm/lib/MC/ConstantPools.cpp b/gnu/llvm/lib/MC/ConstantPools.cpp index 9643b759468..17a23d063b7 100644 --- a/gnu/llvm/lib/MC/ConstantPools.cpp +++ b/gnu/llvm/lib/MC/ConstantPools.cpp @@ -25,11 +25,10 @@ void ConstantPool::emitEntries(MCStreamer &Streamer) { if (Entries.empty()) return; Streamer.EmitDataRegion(MCDR_DataRegion); - for (EntryVecTy::const_iterator I = Entries.begin(), E = Entries.end(); - I != E; ++I) { - Streamer.EmitCodeAlignment(I->Size); // align naturally - Streamer.EmitLabel(I->Label); - Streamer.EmitValue(I->Value, I->Size, I->Loc); + for (const ConstantPoolEntry &Entry : Entries) { + Streamer.EmitCodeAlignment(Entry.Size); // align naturally + Streamer.EmitLabel(Entry.Label); + Streamer.EmitValue(Entry.Value, Entry.Size, Entry.Loc); } Streamer.EmitDataRegion(MCDR_DataRegionEnd); Entries.clear(); @@ -71,11 +70,9 @@ static void emitConstantPool(MCStreamer &Streamer, MCSection *Section, void AssemblerConstantPools::emitAll(MCStreamer &Streamer) { // Dump contents of assembler constant pools. - for (ConstantPoolMapTy::iterator CPI = ConstantPools.begin(), - CPE = ConstantPools.end(); - CPI != CPE; ++CPI) { - MCSection *Section = CPI->first; - ConstantPool &CP = CPI->second; + for (auto &CPI : ConstantPools) { + MCSection *Section = CPI.first; + ConstantPool &CP = CPI.second; emitConstantPool(Streamer, Section, CP); } diff --git a/gnu/llvm/lib/MC/ELFObjectWriter.cpp b/gnu/llvm/lib/MC/ELFObjectWriter.cpp index e6552beefd0..dc21b48ca6f 100644 --- a/gnu/llvm/lib/MC/ELFObjectWriter.cpp +++ b/gnu/llvm/lib/MC/ELFObjectWriter.cpp @@ -35,13 +35,13 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/StringSaver.h" #include <vector> + using namespace llvm; #undef DEBUG_TYPE #define DEBUG_TYPE "reloc-info" namespace { - typedef DenseMap<const MCSectionELF *, uint32_t> SectionIndexMapTy; class ELFObjectWriter; @@ -70,169 +70,171 @@ public: }; class ELFObjectWriter : public MCObjectWriter { - static bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind); - static uint64_t SymbolValue(const MCSymbol &Sym, const MCAsmLayout &Layout); - static bool isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol, - bool Used, bool Renamed); - - /// Helper struct for containing some precomputed information on symbols. - struct ELFSymbolData { - const MCSymbolELF *Symbol; - uint32_t SectionIndex; - StringRef Name; - - // Support lexicographic sorting. - bool operator<(const ELFSymbolData &RHS) const { - unsigned LHSType = Symbol->getType(); - unsigned RHSType = RHS.Symbol->getType(); - if (LHSType == ELF::STT_SECTION && RHSType != ELF::STT_SECTION) - return false; - if (LHSType != ELF::STT_SECTION && RHSType == ELF::STT_SECTION) - return true; - if (LHSType == ELF::STT_SECTION && RHSType == ELF::STT_SECTION) - return SectionIndex < RHS.SectionIndex; - return Name < RHS.Name; - } - }; + static uint64_t SymbolValue(const MCSymbol &Sym, const MCAsmLayout &Layout); + static bool isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol, + bool Used, bool Renamed); + + /// Helper struct for containing some precomputed information on symbols. + struct ELFSymbolData { + const MCSymbolELF *Symbol; + uint32_t SectionIndex; + StringRef Name; + + // Support lexicographic sorting. + bool operator<(const ELFSymbolData &RHS) const { + unsigned LHSType = Symbol->getType(); + unsigned RHSType = RHS.Symbol->getType(); + if (LHSType == ELF::STT_SECTION && RHSType != ELF::STT_SECTION) + return false; + if (LHSType != ELF::STT_SECTION && RHSType == ELF::STT_SECTION) + return true; + if (LHSType == ELF::STT_SECTION && RHSType == ELF::STT_SECTION) + return SectionIndex < RHS.SectionIndex; + return Name < RHS.Name; + } + }; - /// The target specific ELF writer instance. - std::unique_ptr<MCELFObjectTargetWriter> TargetObjectWriter; + /// The target specific ELF writer instance. + std::unique_ptr<MCELFObjectTargetWriter> TargetObjectWriter; - DenseMap<const MCSymbolELF *, const MCSymbolELF *> Renames; + DenseMap<const MCSymbolELF *, const MCSymbolELF *> Renames; - llvm::DenseMap<const MCSectionELF *, std::vector<ELFRelocationEntry>> - Relocations; + llvm::DenseMap<const MCSectionELF *, std::vector<ELFRelocationEntry>> + Relocations; - /// @} - /// @name Symbol Table Data - /// @{ + /// @} + /// @name Symbol Table Data + /// @{ - BumpPtrAllocator Alloc; - StringSaver VersionSymSaver{Alloc}; - StringTableBuilder StrTabBuilder{StringTableBuilder::ELF}; + BumpPtrAllocator Alloc; + StringSaver VersionSymSaver{Alloc}; + StringTableBuilder StrTabBuilder{StringTableBuilder::ELF}; - /// @} + /// @} - // This holds the symbol table index of the last local symbol. - unsigned LastLocalSymbolIndex; - // This holds the .strtab section index. - unsigned StringTableIndex; - // This holds the .symtab section index. - unsigned SymbolTableIndex; + // This holds the symbol table index of the last local symbol. + unsigned LastLocalSymbolIndex; + // This holds the .strtab section index. + unsigned StringTableIndex; + // This holds the .symtab section index. + unsigned SymbolTableIndex; - // Sections in the order they are to be output in the section table. - std::vector<const MCSectionELF *> SectionTable; - unsigned addToSectionTable(const MCSectionELF *Sec); + // Sections in the order they are to be output in the section table. + std::vector<const MCSectionELF *> SectionTable; + unsigned addToSectionTable(const MCSectionELF *Sec); - // TargetObjectWriter wrappers. - bool is64Bit() const { return TargetObjectWriter->is64Bit(); } - bool hasRelocationAddend() const { - return TargetObjectWriter->hasRelocationAddend(); - } - unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, - bool IsPCRel) const { - return TargetObjectWriter->GetRelocType(Target, Fixup, IsPCRel); - } + // TargetObjectWriter wrappers. + bool is64Bit() const { return TargetObjectWriter->is64Bit(); } + bool hasRelocationAddend() const { + return TargetObjectWriter->hasRelocationAddend(); + } + unsigned getRelocType(MCContext &Ctx, const MCValue &Target, + const MCFixup &Fixup, bool IsPCRel) const { + return TargetObjectWriter->getRelocType(Ctx, Target, Fixup, IsPCRel); + } - void align(unsigned Alignment); + void align(unsigned Alignment); - public: - ELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_pwrite_stream &OS, - bool IsLittleEndian) - : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {} + bool maybeWriteCompression(uint64_t Size, + SmallVectorImpl<char> &CompressedContents, + bool ZLibStyle, unsigned Alignment); - void reset() override { - Renames.clear(); - Relocations.clear(); - StrTabBuilder.clear(); - SectionTable.clear(); - MCObjectWriter::reset(); - } +public: + ELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_pwrite_stream &OS, + bool IsLittleEndian) + : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {} + + void reset() override { + Renames.clear(); + Relocations.clear(); + StrTabBuilder.clear(); + SectionTable.clear(); + MCObjectWriter::reset(); + } - ~ELFObjectWriter() override; + ~ELFObjectWriter() override; - void WriteWord(uint64_t W) { - if (is64Bit()) - write64(W); - else - write32(W); - } + void WriteWord(uint64_t W) { + if (is64Bit()) + write64(W); + else + write32(W); + } - template <typename T> void write(T Val) { - if (IsLittleEndian) - support::endian::Writer<support::little>(getStream()).write(Val); - else - support::endian::Writer<support::big>(getStream()).write(Val); - } + template <typename T> void write(T Val) { + if (IsLittleEndian) + support::endian::Writer<support::little>(getStream()).write(Val); + else + support::endian::Writer<support::big>(getStream()).write(Val); + } - void writeHeader(const MCAssembler &Asm); + void writeHeader(const MCAssembler &Asm); - void writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex, - ELFSymbolData &MSD, const MCAsmLayout &Layout); + void writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex, + ELFSymbolData &MSD, const MCAsmLayout &Layout); - // Start and end offset of each section - typedef std::map<const MCSectionELF *, std::pair<uint64_t, uint64_t>> - SectionOffsetsTy; + // Start and end offset of each section + typedef std::map<const MCSectionELF *, std::pair<uint64_t, uint64_t>> + SectionOffsetsTy; - bool shouldRelocateWithSymbol(const MCAssembler &Asm, - const MCSymbolRefExpr *RefA, - const MCSymbol *Sym, uint64_t C, - unsigned Type) const; + bool shouldRelocateWithSymbol(const MCAssembler &Asm, + const MCSymbolRefExpr *RefA, + const MCSymbol *Sym, uint64_t C, + unsigned Type) const; - void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, - const MCFragment *Fragment, const MCFixup &Fixup, - MCValue Target, bool &IsPCRel, - uint64_t &FixedValue) override; + void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, bool &IsPCRel, + uint64_t &FixedValue) override; - // Map from a signature symbol to the group section index - typedef DenseMap<const MCSymbol *, unsigned> RevGroupMapTy; + // Map from a signature symbol to the group section index + typedef DenseMap<const MCSymbol *, unsigned> RevGroupMapTy; - /// Compute the symbol table data - /// - /// \param Asm - The assembler. - /// \param SectionIndexMap - Maps a section to its index. - /// \param RevGroupMap - Maps a signature symbol to the group section. - void computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap, - const RevGroupMapTy &RevGroupMap, - SectionOffsetsTy &SectionOffsets); + /// Compute the symbol table data + /// + /// \param Asm - The assembler. + /// \param SectionIndexMap - Maps a section to its index. + /// \param RevGroupMap - Maps a signature symbol to the group section. + void computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, + const SectionIndexMapTy &SectionIndexMap, + const RevGroupMapTy &RevGroupMap, + SectionOffsetsTy &SectionOffsets); - MCSectionELF *createRelocationSection(MCContext &Ctx, - const MCSectionELF &Sec); + MCSectionELF *createRelocationSection(MCContext &Ctx, + const MCSectionELF &Sec); - const MCSectionELF *createStringTable(MCContext &Ctx); + const MCSectionELF *createStringTable(MCContext &Ctx); - void executePostLayoutBinding(MCAssembler &Asm, - const MCAsmLayout &Layout) override; + void executePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) override; - void writeSectionHeader(const MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap, - const SectionOffsetsTy &SectionOffsets); + void writeSectionHeader(const MCAsmLayout &Layout, + const SectionIndexMapTy &SectionIndexMap, + const SectionOffsetsTy &SectionOffsets); - void writeSectionData(const MCAssembler &Asm, MCSection &Sec, - const MCAsmLayout &Layout); + void writeSectionData(const MCAssembler &Asm, MCSection &Sec, + const MCAsmLayout &Layout); - void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, - uint64_t Address, uint64_t Offset, uint64_t Size, - uint32_t Link, uint32_t Info, uint64_t Alignment, - uint64_t EntrySize); + void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, + uint64_t Address, uint64_t Offset, uint64_t Size, + uint32_t Link, uint32_t Info, uint64_t Alignment, + uint64_t EntrySize); - void writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec); + void writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec); - bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, - const MCSymbol &SymA, - const MCFragment &FB, - bool InSet, - bool IsPCRel) const override; + bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbol &SymA, + const MCFragment &FB, bool InSet, + bool IsPCRel) const override; - bool isWeak(const MCSymbol &Sym) 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); - }; -} + void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; + void writeSection(const SectionIndexMapTy &SectionIndexMap, + uint32_t GroupSymbolIndex, uint64_t Offset, uint64_t Size, + const MCSectionELF &Section); +}; +} // end anonymous namespace void ELFObjectWriter::align(unsigned Alignment) { uint64_t Padding = OffsetToAlignment(getStream().tell(), Alignment); @@ -295,13 +297,6 @@ void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value, ++NumWritten; } -bool ELFObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) { - const MCFixupKindInfo &FKI = - Asm.getBackend().getFixupKindInfo((MCFixupKind) Kind); - - return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel; -} - ELFObjectWriter::~ELFObjectWriter() {} @@ -375,9 +370,24 @@ 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()) { const auto &Alias = cast<MCSymbolELF>(A); // Not an alias. @@ -522,7 +532,6 @@ bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm, case MCSymbolRefExpr::VK_GOT: case MCSymbolRefExpr::VK_PLT: case MCSymbolRefExpr::VK_GOTPCREL: - case MCSymbolRefExpr::VK_Mips_GOT: case MCSymbolRefExpr::VK_PPC_GOT_LO: case MCSymbolRefExpr::VK_PPC_GOT_HI: case MCSymbolRefExpr::VK_PPC_GOT_HA: @@ -618,6 +627,7 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm, const MCSectionELF &FixupSection = cast<MCSectionELF>(*Fragment->getParent()); uint64_t C = Target.getConstant(); uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + MCContext &Ctx = Asm.getContext(); if (const MCSymbolRefExpr *RefB = Target.getSymB()) { assert(RefB->getKind() == MCSymbolRefExpr::VK_None && @@ -631,7 +641,7 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm, // 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) { - Asm.getContext().reportError( + Ctx.reportError( Fixup.getLoc(), "No relocation available to represent this relative expression"); return; @@ -640,24 +650,17 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm, const auto &SymB = cast<MCSymbolELF>(RefB->getSymbol()); if (SymB.isUndefined()) { - Asm.getContext().reportError( - Fixup.getLoc(), - Twine("symbol '") + SymB.getName() + - "' can not be undefined in a subtraction expression"); + 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) { - Asm.getContext().reportError( - Fixup.getLoc(), "Cannot represent a difference across sections"); - return; - } - - if (::isWeak(SymB)) { - Asm.getContext().reportError( - Fixup.getLoc(), "Cannot represent a subtraction with a weak symbol"); + Ctx.reportError(Fixup.getLoc(), + "Cannot represent a difference across sections"); return; } @@ -682,7 +685,8 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm, } } - unsigned Type = GetRelocType(Target, Fixup, IsPCRel); + unsigned Type = getRelocType(Ctx, Target, Fixup, IsPCRel); + uint64_t OriginalC = C; bool RelocateWithSymbol = shouldRelocateWithSymbol(Asm, RefA, SymA, C, Type); if (!RelocateWithSymbol && SymA && !SymA->isUndefined()) C += Layout.getSymbolOffset(*SymA); @@ -703,23 +707,25 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm, ELFSec ? cast<MCSymbolELF>(ELFSec->getBeginSymbol()) : nullptr; if (SectionSymbol) SectionSymbol->setUsedInReloc(); - ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend); + ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend, SymA, + OriginalC); Relocations[&FixupSection].push_back(Rec); return; } + const auto *RenamedSymA = SymA; if (SymA) { if (const MCSymbolELF *R = Renames.lookup(SymA)) - SymA = R; + RenamedSymA = R; if (ViaWeakRef) - SymA->setIsWeakrefUsedInReloc(); + RenamedSymA->setIsWeakrefUsedInReloc(); else - SymA->setUsedInReloc(); + RenamedSymA->setUsedInReloc(); } - ELFRelocationEntry Rec(FixupOffset, SymA, Type, Addend); + ELFRelocationEntry Rec(FixupOffset, RenamedSymA, Type, Addend, SymA, + OriginalC); Relocations[&FixupSection].push_back(Rec); - return; } bool ELFObjectWriter::isInSymtab(const MCAsmLayout &Layout, @@ -969,23 +975,38 @@ ELFObjectWriter::createRelocationSection(MCContext &Ctx, return RelaSection; } -// Include the debug info compression header: -// "ZLIB" followed by 8 bytes representing the uncompressed size of the section, -// useful for consumers to preallocate a buffer to decompress into. -static bool -prependCompressionHeader(uint64_t Size, - SmallVectorImpl<char> &CompressedContents) { +// Include the debug info compression header. +bool ELFObjectWriter::maybeWriteCompression( + uint64_t Size, SmallVectorImpl<char> &CompressedContents, bool ZLibStyle, + unsigned Alignment) { + if (ZLibStyle) { + uint64_t HdrSize = + is64Bit() ? sizeof(ELF::Elf32_Chdr) : sizeof(ELF::Elf64_Chdr); + if (Size <= HdrSize + CompressedContents.size()) + return false; + // Platform specific header is followed by compressed data. + if (is64Bit()) { + // Write Elf64_Chdr header. + write(static_cast<ELF::Elf64_Word>(ELF::ELFCOMPRESS_ZLIB)); + write(static_cast<ELF::Elf64_Word>(0)); // ch_reserved field. + write(static_cast<ELF::Elf64_Xword>(Size)); + write(static_cast<ELF::Elf64_Xword>(Alignment)); + } else { + // Write Elf32_Chdr header otherwise. + write(static_cast<ELF::Elf32_Word>(ELF::ELFCOMPRESS_ZLIB)); + write(static_cast<ELF::Elf32_Word>(Size)); + write(static_cast<ELF::Elf32_Word>(Alignment)); + } + return true; + } + + // "ZLIB" followed by 8 bytes representing the uncompressed size of the section, + // useful for consumers to preallocate a buffer to decompress into. const StringRef Magic = "ZLIB"; if (Size <= Magic.size() + sizeof(Size) + CompressedContents.size()) return false; - if (sys::IsLittleEndianHost) - sys::swapByteOrder(Size); - CompressedContents.insert(CompressedContents.begin(), - Magic.size() + sizeof(Size), 0); - std::copy(Magic.begin(), Magic.end(), CompressedContents.begin()); - std::copy(reinterpret_cast<char *>(&Size), - reinterpret_cast<char *>(&Size + 1), - CompressedContents.begin() + Magic.size()); + write(ArrayRef<char>(Magic.begin(), Magic.size())); + writeBE64(Size); return true; } @@ -997,8 +1018,11 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec, // Compressing debug_frame requires handling alignment fragments which is // more work (possibly generalizing MCAssembler.cpp:writeFragment to allow // for writing to arbitrary buffers) for little benefit. - if (!Asm.getContext().getAsmInfo()->compressDebugSections() || - !SectionName.startswith(".debug_") || SectionName == ".debug_frame") { + bool CompressionEnabled = + Asm.getContext().getAsmInfo()->compressDebugSections() != + DebugCompressionType::DCT_None; + if (!CompressionEnabled || !SectionName.startswith(".debug_") || + SectionName == ".debug_frame") { Asm.writeSectionData(&Section, Layout); return; } @@ -1019,12 +1043,21 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec, return; } - if (!prependCompressionHeader(UncompressedData.size(), CompressedContents)) { + bool ZlibStyle = Asm.getContext().getAsmInfo()->compressDebugSections() == + DebugCompressionType::DCT_Zlib; + if (!maybeWriteCompression(UncompressedData.size(), CompressedContents, + ZlibStyle, Sec.getAlignment())) { getStream() << UncompressedData; return; } - Asm.getContext().renameELFSection(&Section, - (".z" + SectionName.drop_front(1)).str()); + + if (ZlibStyle) + // Set the compressed flag. That is zlib style. + Section.setFlags(Section.getFlags() | ELF::SHF_COMPRESSED); + else + // Add "z" prefix to section name. This is zlib-gnu style. + Asm.getContext().renameELFSection(&Section, + (".z" + SectionName.drop_front(1)).str()); getStream() << CompressedContents; } @@ -1279,7 +1312,7 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm, uint64_t NaturalAlignment = is64Bit() ? 8 : 4; align(NaturalAlignment); - const unsigned SectionHeaderOffset = getStream().tell(); + const uint64_t SectionHeaderOffset = getStream().tell(); // ... then the section header table ... writeSectionHeader(Layout, SectionIndexMap, SectionOffsets); diff --git a/gnu/llvm/lib/MC/MCAsmBackend.cpp b/gnu/llvm/lib/MC/MCAsmBackend.cpp index fcf139b7253..b868b9d4889 100644 --- a/gnu/llvm/lib/MC/MCAsmBackend.cpp +++ b/gnu/llvm/lib/MC/MCAsmBackend.cpp @@ -12,12 +12,12 @@ #include "llvm/MC/MCFixupKindInfo.h" using namespace llvm; -MCAsmBackend::MCAsmBackend() : HasDataInCodeSupport(false) {} +MCAsmBackend::MCAsmBackend() {} MCAsmBackend::~MCAsmBackend() {} -bool MCAsmBackend::getFixupKind(StringRef Name, MCFixupKind &MappedKind) const { - return false; +Optional<MCFixupKind> MCAsmBackend::getFixupKind(StringRef Name) const { + return None; } const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { diff --git a/gnu/llvm/lib/MC/MCAsmInfo.cpp b/gnu/llvm/lib/MC/MCAsmInfo.cpp index 36e10b3c6a0..4a05175fdec 100644 --- a/gnu/llvm/lib/MC/MCAsmInfo.cpp +++ b/gnu/llvm/lib/MC/MCAsmInfo.cpp @@ -75,6 +75,7 @@ MCAsmInfo::MCAsmInfo() { HasSingleParameterDotFile = true; HasIdentDirective = false; HasNoDeadStrip = false; + HasAltEntry = false; WeakDirective = "\t.weak\t"; WeakRefDirective = nullptr; HasWeakDefDirective = false; @@ -106,8 +107,9 @@ MCAsmInfo::MCAsmInfo() { // architecture basis. // - The target subclasses for AArch64, ARM, and X86 handle these cases UseIntegratedAssembler = false; + PreserveAsmComments = true; - CompressDebugSections = false; + CompressDebugSections = DebugCompressionType::DCT_None; } MCAsmInfo::~MCAsmInfo() { diff --git a/gnu/llvm/lib/MC/MCAsmInfoDarwin.cpp b/gnu/llvm/lib/MC/MCAsmInfoDarwin.cpp index ae9486d3db4..fc60313dd6b 100644 --- a/gnu/llvm/lib/MC/MCAsmInfoDarwin.cpp +++ b/gnu/llvm/lib/MC/MCAsmInfoDarwin.cpp @@ -48,6 +48,7 @@ bool MCAsmInfoDarwin::isSectionAtomizableBySymbols( case MachO::S_LITERAL_POINTERS: case MachO::S_NON_LAZY_SYMBOL_POINTERS: case MachO::S_LAZY_SYMBOL_POINTERS: + case MachO::S_THREAD_LOCAL_VARIABLE_POINTERS: case MachO::S_MOD_INIT_FUNC_POINTERS: case MachO::S_MOD_TERM_FUNC_POINTERS: case MachO::S_INTERPOSING: @@ -88,6 +89,7 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { HasDotTypeDotSizeDirective = false; HasNoDeadStrip = true; + HasAltEntry = true; DwarfUsesRelocationsAcrossSections = false; diff --git a/gnu/llvm/lib/MC/MCAsmInfoELF.cpp b/gnu/llvm/lib/MC/MCAsmInfoELF.cpp index 2bff6e05966..26e5608d873 100644 --- a/gnu/llvm/lib/MC/MCAsmInfoELF.cpp +++ b/gnu/llvm/lib/MC/MCAsmInfoELF.cpp @@ -21,6 +21,8 @@ using namespace llvm; void MCAsmInfoELF::anchor() { } MCSection *MCAsmInfoELF::getNonexecutableStackSection(MCContext &Ctx) const { + if (!UsesNonexecutableStackSection) + return nullptr; return Ctx.getELFSection(".note.GNU-stack", ELF::SHT_PROGBITS, 0); } @@ -29,4 +31,5 @@ MCAsmInfoELF::MCAsmInfoELF() { WeakRefDirective = "\t.weak\t"; PrivateGlobalPrefix = ".L"; PrivateLabelPrefix = ".L"; + UsesNonexecutableStackSection = true; } diff --git a/gnu/llvm/lib/MC/MCAsmStreamer.cpp b/gnu/llvm/lib/MC/MCAsmStreamer.cpp index c99ce7752b3..ef2f7810dea 100644 --- a/gnu/llvm/lib/MC/MCAsmStreamer.cpp +++ b/gnu/llvm/lib/MC/MCAsmStreamer.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCStreamer.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -24,14 +23,15 @@ #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbolELF.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" +#include "llvm/Support/SourceMgr.h" #include <cctype> using namespace llvm; @@ -46,6 +46,7 @@ class MCAsmStreamer final : public MCStreamer { std::unique_ptr<MCCodeEmitter> Emitter; std::unique_ptr<MCAsmBackend> AsmBackend; + SmallString<128> ExplicitCommentToEmit; SmallString<128> CommentToEmit; raw_svector_ostream CommentStream; @@ -73,6 +74,8 @@ public: } inline void EmitEOL() { + // Dump Explicit Comments here. + emitExplicitComments(); // If we don't have any comments, just emit a \n. if (!IsVerboseAsm) { OS << '\n'; @@ -112,6 +115,9 @@ public: void emitRawComment(const Twine &T, bool TabPrefix = true) override; + void addExplicitComment(const Twine &T) override; + void emitExplicitComments() override; + /// AddBlankLine - Emit a blank line to a .s file to pretty it up. void AddBlankLine() override { EmitEOL(); @@ -162,6 +168,8 @@ public: void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment = 0) override; + void EmitBinaryData(StringRef Data) override; + void EmitBytes(StringRef Data) override; void EmitValueImpl(const MCExpr *Value, unsigned Size, @@ -177,7 +185,15 @@ public: void EmitGPRel32Value(const MCExpr *Value) override; - void EmitFill(uint64_t NumBytes, uint8_t FillValue) override; + void emitFill(uint64_t NumBytes, uint8_t FillValue) override; + + void emitFill(const MCExpr &NumBytes, uint64_t FillValue, + SMLoc Loc = SMLoc()) override; + + void emitFill(uint64_t NumValues, int64_t Size, int64_t Expr) override; + + void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr, + SMLoc Loc = SMLoc()) override; void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, @@ -199,6 +215,22 @@ public: StringRef FileName) override; MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override; + unsigned EmitCVFileDirective(unsigned FileNo, StringRef Filename) override; + void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line, + unsigned Column, bool PrologueEnd, bool IsStmt, + StringRef FileName) override; + void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart, + const MCSymbol *FnEnd) override; + void EmitCVInlineLinetableDirective( + unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, + const MCSymbol *FnStartSym, const MCSymbol *FnEndSym, + ArrayRef<unsigned> SecondaryFunctionIds) override; + void EmitCVDefRangeDirective( + ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, + StringRef FixedSizePortion) override; + void EmitCVStringTableDirective() override; + void EmitCVFileChecksumsDirective() override; + void EmitIdent(StringRef IdentString) override; void EmitCFISections(bool EH, bool Debug) override; void EmitCFIDefCfa(int64_t Register, int64_t Offset) override; @@ -288,7 +320,7 @@ void MCAsmStreamer::EmitCommentsAndEOL() { } static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { - assert(Bytes && "Invalid size!"); + assert(Bytes > 0 && Bytes <= 8 && "Invalid size!"); return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); } @@ -299,6 +331,49 @@ void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) { EmitEOL(); } +void MCAsmStreamer::addExplicitComment(const Twine &T) { + StringRef c = T.getSingleStringRef(); + if (c.equals(StringRef(MAI->getSeparatorString()))) + return; + if (c.startswith(StringRef("//"))) { + ExplicitCommentToEmit.append("\t"); + ExplicitCommentToEmit.append(MAI->getCommentString()); + // drop // + ExplicitCommentToEmit.append(c.slice(2, c.size()).str()); + } else if (c.startswith(StringRef("/*"))) { + size_t p = 2, len = c.size() - 2; + // emit each line in comment as separate newline. + do { + size_t newp = std::min(len, c.find_first_of("\r\n", p)); + ExplicitCommentToEmit.append("\t"); + ExplicitCommentToEmit.append(MAI->getCommentString()); + ExplicitCommentToEmit.append(c.slice(p, newp).str()); + // If we have another line in this comment add line + if (newp < len) + ExplicitCommentToEmit.append("\n"); + p = newp + 1; + } while (p < len); + } else if (c.startswith(StringRef(MAI->getCommentString()))) { + ExplicitCommentToEmit.append("\t"); + ExplicitCommentToEmit.append(c.str()); + } else if (c.front() == '#') { + // # are comments for ## commentString. Output extra #. + ExplicitCommentToEmit.append("\t#"); + ExplicitCommentToEmit.append(c.str()); + } else + assert(false && "Unexpected Assembly Comment"); + // full line comments immediately output + if (c.back() == '\n') + emitExplicitComments(); +} + +void MCAsmStreamer::emitExplicitComments() { + StringRef Comments = ExplicitCommentToEmit; + if (!Comments.empty()) + OS << Comments; + ExplicitCommentToEmit.clear(); +} + void MCAsmStreamer::ChangeSection(MCSection *Section, const MCExpr *Subsection) { assert(Section && "Cannot switch to a null section!"); @@ -326,12 +401,11 @@ void MCAsmStreamer::EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) { OS << "\t" << MCLOHDirectiveName() << " " << str << "\t"; bool IsFirst = true; - for (MCLOHArgs::const_iterator It = Args.begin(), EndIt = Args.end(); - It != EndIt; ++It) { + for (const MCSymbol *Arg : Args) { if (!IsFirst) OS << ", "; IsFirst = false; - (*It)->print(OS, MAI); + Arg->print(OS, MAI); } EmitEOL(); } @@ -354,7 +428,7 @@ void MCAsmStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) { ie = Options.end(); it != ie; ++it) { OS << ", " << '"' << *it << '"'; } - OS << "\n"; + EmitEOL(); } void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) { @@ -456,6 +530,7 @@ bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, OS << "\t.no_dead_strip\t"; break; case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break; + case MCSA_AltEntry: OS << "\t.alt_entry\t"; break; case MCSA_PrivateExtern: OS << "\t.private_extern\t"; break; @@ -484,8 +559,10 @@ void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { } void MCAsmStreamer::EmitSyntaxDirective() { - if (MAI->getAssemblerDialect() == 1) - OS << "\t.intel_syntax noprefix\n"; + if (MAI->getAssemblerDialect() == 1) { + OS << "\t.intel_syntax noprefix"; + EmitEOL(); + } // FIXME: Currently emit unprefix'ed registers. // The intel_syntax directive has one optional argument // with may have a value of prefix or noprefix. @@ -537,7 +614,7 @@ void MCAsmStreamer::emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) { Symbol->print(OS, MAI); OS << ", "; Value->print(OS, MAI); - OS << '\n'; + EmitEOL(); } void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, @@ -684,6 +761,20 @@ void MCAsmStreamer::EmitBytes(StringRef Data) { EmitEOL(); } +void MCAsmStreamer::EmitBinaryData(StringRef Data) { + // This is binary data. Print it in a grid of hex bytes for readability. + const size_t Cols = 4; + for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) { + size_t J = I, EJ = std::min(I + Cols, Data.size()); + assert(EJ > 0); + OS << MAI->getData8bitsDirective(); + for (; J < EJ - 1; ++J) + OS << format("0x%02x", uint8_t(Data[J])) << ", "; + OS << format("0x%02x", uint8_t(Data[J])); + EmitEOL(); + } +} + void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size) { EmitValue(MCConstantExpr::create(Value, getContext()), Size); } @@ -708,17 +799,15 @@ void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, report_fatal_error("Don't know how to emit this value."); // We couldn't handle the requested integer size so we fallback by breaking - // the request down into several, smaller, integers. Since sizes greater - // than eight are invalid and size equivalent to eight should have been - // handled earlier, we use four bytes as our largest piece of granularity. + // the request down into several, smaller, integers. + // Since sizes greater or equal to "Size" are invalid, we use the greatest + // power of 2 that is less than "Size" as our largest piece of granularity. bool IsLittleEndian = MAI->isLittleEndian(); for (unsigned Emitted = 0; Emitted != Size;) { unsigned Remaining = Size - Emitted; // The size of our partial emission must be a power of two less than - // eight. - unsigned EmissionSize = PowerOf2Floor(Remaining); - if (EmissionSize > 4) - EmissionSize = 4; + // Size. + unsigned EmissionSize = PowerOf2Floor(std::min(Remaining, Size - 1)); // Calculate the byte offset of our partial emission taking into account // the endianness of the target. unsigned ByteOffset = @@ -780,21 +869,46 @@ void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) { EmitEOL(); } -/// EmitFill - Emit NumBytes bytes worth of the value specified by +/// emitFill - Emit NumBytes bytes worth of the value specified by /// FillValue. This implements directives such as '.space'. -void MCAsmStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue) { +void MCAsmStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) { if (NumBytes == 0) return; + const MCExpr *E = MCConstantExpr::create(NumBytes, getContext()); + emitFill(*E, FillValue); +} + +void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue, + SMLoc Loc) { if (const char *ZeroDirective = MAI->getZeroDirective()) { - OS << ZeroDirective << NumBytes; + // FIXME: Emit location directives + OS << ZeroDirective; + NumBytes.print(OS, MAI); if (FillValue != 0) OS << ',' << (int)FillValue; EmitEOL(); return; } - // Emit a byte at a time. - MCStreamer::EmitFill(NumBytes, FillValue); + MCStreamer::emitFill(NumBytes, FillValue); +} + +void MCAsmStreamer::emitFill(uint64_t NumValues, int64_t Size, int64_t Expr) { + if (NumValues == 0) + return; + + const MCExpr *E = MCConstantExpr::create(NumValues, getContext()); + emitFill(*E, Size, Expr); +} + +void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size, + int64_t Expr, SMLoc Loc) { + // FIXME: Emit location directives + OS << "\t.fill\t"; + NumValues.print(OS, MAI); + OS << ", " << Size << ", 0x"; + OS.write_hex(truncateToSize(Expr, 4)); + EmitEOL(); } void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, @@ -807,7 +921,7 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, default: llvm_unreachable("Invalid size for machine code value!"); case 1: - OS << "\t.align\t"; + OS << "\t.p2align\t"; break; case 2: OS << ".p2alignw "; @@ -819,10 +933,7 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, llvm_unreachable("Unsupported alignment size!"); } - if (MAI->getAlignmentIsInBytes()) - OS << ByteAlignment; - else - OS << Log2_32(ByteAlignment); + OS << Log2_32(ByteAlignment); if (Value || MaxBytesToEmit) { OS << ", 0x"; @@ -957,6 +1068,105 @@ MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) { return MCStreamer::getDwarfLineTableSymbol(0); } +unsigned MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, + StringRef Filename) { + if (!getContext().getCVFile(Filename, FileNo)) + return 0; + + OS << "\t.cv_file\t" << FileNo << ' '; + + PrintQuotedString(Filename, OS); + EmitEOL(); + + return FileNo; +} + +void MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, + unsigned Line, unsigned Column, + bool PrologueEnd, bool IsStmt, + StringRef FileName) { + OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " " + << Column; + if (PrologueEnd) + OS << " prologue_end"; + + unsigned OldIsStmt = getContext().getCurrentCVLoc().isStmt(); + if (IsStmt != OldIsStmt) { + OS << " is_stmt "; + + if (IsStmt) + OS << "1"; + else + OS << "0"; + } + + if (IsVerboseAsm) { + OS.PadToColumn(MAI->getCommentColumn()); + OS << MAI->getCommentString() << ' ' << FileName << ':' + << Line << ':' << Column; + } + EmitEOL(); + this->MCStreamer::EmitCVLocDirective(FunctionId, FileNo, Line, Column, + PrologueEnd, IsStmt, FileName); +} + +void MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId, + const MCSymbol *FnStart, + const MCSymbol *FnEnd) { + OS << "\t.cv_linetable\t" << FunctionId << ", "; + FnStart->print(OS, MAI); + OS << ", "; + FnEnd->print(OS, MAI); + EmitEOL(); + this->MCStreamer::EmitCVLinetableDirective(FunctionId, FnStart, FnEnd); +} + +void MCAsmStreamer::EmitCVInlineLinetableDirective( + unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, + const MCSymbol *FnStartSym, const MCSymbol *FnEndSym, + ArrayRef<unsigned> SecondaryFunctionIds) { + OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId + << ' ' << SourceLineNum << ' '; + FnStartSym->print(OS, MAI); + OS << ' '; + FnEndSym->print(OS, MAI); + if (!SecondaryFunctionIds.empty()) { + OS << " contains"; + for (unsigned SecondaryFunctionId : SecondaryFunctionIds) + OS << ' ' << SecondaryFunctionId; + } + EmitEOL(); + this->MCStreamer::EmitCVInlineLinetableDirective( + PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym, + SecondaryFunctionIds); +} + +void MCAsmStreamer::EmitCVDefRangeDirective( + ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, + StringRef FixedSizePortion) { + OS << "\t.cv_def_range\t"; + for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) { + OS << ' '; + Range.first->print(OS, MAI); + OS << ' '; + Range.second->print(OS, MAI); + } + OS << ", "; + PrintQuotedString(FixedSizePortion, OS); + EmitEOL(); + this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion); +} + +void MCAsmStreamer::EmitCVStringTableDirective() { + OS << "\t.cv_stringtable"; + EmitEOL(); +} + +void MCAsmStreamer::EmitCVFileChecksumsDirective() { + OS << "\t.cv_filechecksums"; + EmitEOL(); +} + void MCAsmStreamer::EmitIdent(StringRef IdentString) { assert(MAI->hasIdentDirective() && ".ident directive not supported"); OS << "\t.ident\t"; @@ -1033,10 +1243,10 @@ void MCAsmStreamer::EmitCFIEscape(StringRef Values) { void MCAsmStreamer::EmitCFIGnuArgsSize(int64_t Size) { MCStreamer::EmitCFIGnuArgsSize(Size); - + uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size }; unsigned Len = encodeULEB128(Size, Buffer + 1) + 1; - + PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len)); EmitEOL(); } @@ -1178,8 +1388,8 @@ void MCAsmStreamer::EmitWinEHHandlerData() { // We only do this so the section switch that terminates the handler // data block is visible. WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo(); - MCSection *XData = - WinEH::UnwindEmitter::getXDataSection(CurFrame->Function, getContext()); + MCSection *TextSec = &CurFrame->Function->getSection(); + MCSection *XData = getAssociatedXDataSection(TextSec); SwitchSectionNoChange(XData); OS << "\t.seh_handlerdata"; diff --git a/gnu/llvm/lib/MC/MCAssembler.cpp b/gnu/llvm/lib/MC/MCAssembler.cpp index 15e82fa4938..7a42108ceaf 100644 --- a/gnu/llvm/lib/MC/MCAssembler.cpp +++ b/gnu/llvm/lib/MC/MCAssembler.cpp @@ -15,6 +15,7 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCCodeView.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCExpr.h" @@ -64,9 +65,9 @@ STATISTIC(RelaxedInstructions, "Number of relaxed instructions"); /* *** */ -MCAssembler::MCAssembler(MCContext &Context_, MCAsmBackend &Backend_, - MCCodeEmitter &Emitter_, MCObjectWriter &Writer_) - : Context(Context_), Backend(Backend_), Emitter(Emitter_), Writer(Writer_), +MCAssembler::MCAssembler(MCContext &Context, MCAsmBackend &Backend, + MCCodeEmitter &Emitter, MCObjectWriter &Writer) + : Context(Context), Backend(Backend), Emitter(Emitter), Writer(Writer), BundleAlignSize(0), RelaxAll(false), SubsectionsViaSymbols(false), IncrementalLinkerCompatible(false), ELFHeaderEFlags(0) { VersionMinInfo.Major = 0; // Major version == 0 for "none specified" @@ -300,6 +301,10 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, return cast<MCDwarfLineAddrFragment>(F).getContents().size(); case MCFragment::FT_DwarfFrame: return cast<MCDwarfCallFrameFragment>(F).getContents().size(); + case MCFragment::FT_CVInlineLines: + return cast<MCCVInlineLineTableFragment>(F).getContents().size(); + case MCFragment::FT_CVDefRange: + return cast<MCCVDefRangeFragment>(F).getContents().size(); case MCFragment::FT_Dummy: llvm_unreachable("Should not have been added"); } @@ -488,17 +493,19 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, case MCFragment::FT_Fill: { ++stats::EmittedFillFragments; const MCFillFragment &FF = cast<MCFillFragment>(F); - - assert(FF.getValueSize() && "Invalid virtual align in concrete fragment!"); - - for (uint64_t i = 0, e = FF.getSize() / FF.getValueSize(); i != e; ++i) { - switch (FF.getValueSize()) { - default: llvm_unreachable("Invalid size!"); - case 1: OW->write8 (uint8_t (FF.getValue())); break; - case 2: OW->write16(uint16_t(FF.getValue())); break; - case 4: OW->write32(uint32_t(FF.getValue())); break; - case 8: OW->write64(uint64_t(FF.getValue())); break; - } + uint8_t V = FF.getValue(); + const unsigned MaxChunkSize = 16; + char Data[MaxChunkSize]; + memcpy(Data, &V, 1); + for (unsigned I = 1; I < MaxChunkSize; ++I) + Data[I] = Data[0]; + + uint64_t Size = FF.getSize(); + for (unsigned ChunkSize = MaxChunkSize; ChunkSize; ChunkSize /= 2) { + StringRef Ref(Data, ChunkSize); + for (uint64_t I = 0, E = Size / ChunkSize; I != E; ++I) + OW->writeBytes(Ref); + Size = Size % ChunkSize; } break; } @@ -535,6 +542,16 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, OW->writeBytes(CF.getContents()); break; } + case MCFragment::FT_CVInlineLines: { + const auto &OF = cast<MCCVInlineLineTableFragment>(F); + OW->writeBytes(OF.getContents()); + break; + } + case MCFragment::FT_CVDefRange: { + const auto &DRF = cast<MCCVDefRangeFragment>(F); + OW->writeBytes(DRF.getContents()); + break; + } case MCFragment::FT_Dummy: llvm_unreachable("Should not have been added"); } @@ -578,8 +595,7 @@ void MCAssembler::writeSectionData(const MCSection *Sec, "Invalid align in virtual section!"); break; case MCFragment::FT_Fill: - assert((cast<MCFillFragment>(F).getValueSize() == 0 || - cast<MCFillFragment>(F).getValue() == 0) && + assert((cast<MCFillFragment>(F).getValue() == 0) && "Invalid fill in virtual section!"); break; } @@ -664,19 +680,24 @@ void MCAssembler::layout(MCAsmLayout &Layout) { // Evaluate and apply the fixups, generating relocation entries as necessary. for (MCSection &Sec : *this) { for (MCFragment &Frag : Sec) { - MCEncodedFragment *F = dyn_cast<MCEncodedFragment>(&Frag); // Data and relaxable fragments both have fixups. So only process // those here. // FIXME: Is there a better way to do this? MCEncodedFragmentWithFixups // being templated makes this tricky. - if (!F || isa<MCCompactEncodedInstFragment>(F)) + if (isa<MCEncodedFragment>(&Frag) && + isa<MCCompactEncodedInstFragment>(&Frag)) + continue; + if (!isa<MCEncodedFragment>(&Frag) && !isa<MCCVDefRangeFragment>(&Frag)) continue; ArrayRef<MCFixup> Fixups; MutableArrayRef<char> Contents; - if (auto *FragWithFixups = dyn_cast<MCDataFragment>(F)) { + if (auto *FragWithFixups = dyn_cast<MCDataFragment>(&Frag)) { Fixups = FragWithFixups->getFixups(); Contents = FragWithFixups->getContents(); - } else if (auto *FragWithFixups = dyn_cast<MCRelaxableFragment>(F)) { + } else if (auto *FragWithFixups = dyn_cast<MCRelaxableFragment>(&Frag)) { + Fixups = FragWithFixups->getFixups(); + Contents = FragWithFixups->getContents(); + } else if (auto *FragWithFixups = dyn_cast<MCCVDefRangeFragment>(&Frag)) { Fixups = FragWithFixups->getFixups(); Contents = FragWithFixups->getContents(); } else @@ -684,7 +705,7 @@ void MCAssembler::layout(MCAsmLayout &Layout) { for (const MCFixup &Fixup : Fixups) { uint64_t FixedValue; bool IsPCRel; - std::tie(FixedValue, IsPCRel) = handleFixup(Layout, *F, Fixup); + std::tie(FixedValue, IsPCRel) = handleFixup(Layout, Frag, Fixup); getBackend().applyFixup(Fixup, Contents.data(), Contents.size(), FixedValue, IsPCRel); } @@ -744,7 +765,7 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout, // Relax the fragment. MCInst Relaxed; - getBackend().relaxInstruction(F.getInst(), Relaxed); + getBackend().relaxInstruction(F.getInst(), F.getSubtargetInfo(), Relaxed); // Encode the new instruction. // @@ -812,6 +833,20 @@ bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout, return OldSize != Data.size(); } +bool MCAssembler::relaxCVInlineLineTable(MCAsmLayout &Layout, + MCCVInlineLineTableFragment &F) { + unsigned OldSize = F.getContents().size(); + getContext().getCVContext().encodeInlineLineTable(Layout, F); + return OldSize != F.getContents().size(); +} + +bool MCAssembler::relaxCVDefRange(MCAsmLayout &Layout, + MCCVDefRangeFragment &F) { + unsigned OldSize = F.getContents().size(); + getContext().getCVContext().encodeDefRange(Layout, F); + return OldSize != F.getContents().size(); +} + bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec) { // Holds the first fragment which needed relaxing during this layout. It will // remain NULL if none were relaxed. @@ -843,6 +878,13 @@ bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec) { case MCFragment::FT_LEB: RelaxedFrag = relaxLEB(Layout, *cast<MCLEBFragment>(I)); break; + case MCFragment::FT_CVInlineLines: + RelaxedFrag = + relaxCVInlineLineTable(Layout, *cast<MCCVInlineLineTableFragment>(I)); + break; + case MCFragment::FT_CVDefRange: + RelaxedFrag = relaxCVDefRange(Layout, *cast<MCCVDefRangeFragment>(I)); + break; } if (RelaxedFrag && !FirstRelaxedFragment) FirstRelaxedFragment = &*I; @@ -872,4 +914,5 @@ void MCAssembler::finishLayout(MCAsmLayout &Layout) { for (unsigned int i = 0, n = Layout.getSectionOrder().size(); i != n; ++i) { Layout.getFragmentOffset(&*Layout.getSectionOrder()[i]->rbegin()); } + getBackend().finishLayout(*this, Layout); } diff --git a/gnu/llvm/lib/MC/MCCodeView.cpp b/gnu/llvm/lib/MC/MCCodeView.cpp new file mode 100644 index 00000000000..65cff41abeb --- /dev/null +++ b/gnu/llvm/lib/MC/MCCodeView.cpp @@ -0,0 +1,464 @@ +//===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Holds state from .cv_file and .cv_loc directives for later emission. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCCodeView.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/Line.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/COFF.h" +#include "llvm/Support/EndianStream.h" + +using namespace llvm; +using namespace llvm::codeview; + +CodeViewContext::CodeViewContext() {} + +CodeViewContext::~CodeViewContext() { + // If someone inserted strings into the string table but never actually + // emitted them somewhere, clean up the fragment. + if (!InsertedStrTabFragment) + delete StrTabFragment; +} + +/// This is a valid number for use with .cv_loc if we've already seen a .cv_file +/// for it. +bool CodeViewContext::isValidFileNumber(unsigned FileNumber) const { + unsigned Idx = FileNumber - 1; + if (Idx < Filenames.size()) + return !Filenames[Idx].empty(); + return false; +} + +bool CodeViewContext::addFile(unsigned FileNumber, StringRef Filename) { + assert(FileNumber > 0); + Filename = addToStringTable(Filename); + unsigned Idx = FileNumber - 1; + if (Idx >= Filenames.size()) + Filenames.resize(Idx + 1); + + if (Filename.empty()) + Filename = "<stdin>"; + + if (!Filenames[Idx].empty()) + return false; + + // FIXME: We should store the string table offset of the filename, rather than + // the filename itself for efficiency. + Filename = addToStringTable(Filename); + + Filenames[Idx] = Filename; + return true; +} + +MCDataFragment *CodeViewContext::getStringTableFragment() { + if (!StrTabFragment) { + StrTabFragment = new MCDataFragment(); + // Start a new string table out with a null byte. + StrTabFragment->getContents().push_back('\0'); + } + return StrTabFragment; +} + +StringRef CodeViewContext::addToStringTable(StringRef S) { + SmallVectorImpl<char> &Contents = getStringTableFragment()->getContents(); + auto Insertion = + StringTable.insert(std::make_pair(S, unsigned(Contents.size()))); + // Return the string from the table, since it is stable. + S = Insertion.first->first(); + if (Insertion.second) { + // The string map key is always null terminated. + Contents.append(S.begin(), S.end() + 1); + } + return S; +} + +unsigned CodeViewContext::getStringTableOffset(StringRef S) { + // A string table offset of zero is always the empty string. + if (S.empty()) + return 0; + auto I = StringTable.find(S); + assert(I != StringTable.end()); + return I->second; +} + +void CodeViewContext::emitStringTable(MCObjectStreamer &OS) { + MCContext &Ctx = OS.getContext(); + MCSymbol *StringBegin = Ctx.createTempSymbol("strtab_begin", false), + *StringEnd = Ctx.createTempSymbol("strtab_end", false); + + OS.EmitIntValue(unsigned(ModuleSubstreamKind::StringTable), 4); + OS.emitAbsoluteSymbolDiff(StringEnd, StringBegin, 4); + OS.EmitLabel(StringBegin); + + // Put the string table data fragment here, if we haven't already put it + // somewhere else. If somebody wants two string tables in their .s file, one + // will just be empty. + if (!InsertedStrTabFragment) { + OS.insert(getStringTableFragment()); + InsertedStrTabFragment = true; + } + + OS.EmitValueToAlignment(4, 0); + + OS.EmitLabel(StringEnd); +} + +void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) { + // Do nothing if there are no file checksums. Microsoft's linker rejects empty + // CodeView substreams. + if (Filenames.empty()) + return; + + MCContext &Ctx = OS.getContext(); + MCSymbol *FileBegin = Ctx.createTempSymbol("filechecksums_begin", false), + *FileEnd = Ctx.createTempSymbol("filechecksums_end", false); + + OS.EmitIntValue(unsigned(ModuleSubstreamKind::FileChecksums), 4); + OS.emitAbsoluteSymbolDiff(FileEnd, FileBegin, 4); + OS.EmitLabel(FileBegin); + + // Emit an array of FileChecksum entries. We index into this table using the + // user-provided file number. Each entry is currently 8 bytes, as we don't + // emit checksums. + for (StringRef Filename : Filenames) { + OS.EmitIntValue(getStringTableOffset(Filename), 4); + // Zero the next two fields and align back to 4 bytes. This indicates that + // no checksum is present. + OS.EmitIntValue(0, 4); + } + + OS.EmitLabel(FileEnd); +} + +void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS, + unsigned FuncId, + const MCSymbol *FuncBegin, + const MCSymbol *FuncEnd) { + MCContext &Ctx = OS.getContext(); + MCSymbol *LineBegin = Ctx.createTempSymbol("linetable_begin", false), + *LineEnd = Ctx.createTempSymbol("linetable_end", false); + + OS.EmitIntValue(unsigned(ModuleSubstreamKind::Lines), 4); + OS.emitAbsoluteSymbolDiff(LineEnd, LineBegin, 4); + OS.EmitLabel(LineBegin); + OS.EmitCOFFSecRel32(FuncBegin); + OS.EmitCOFFSectionIndex(FuncBegin); + + // Actual line info. + std::vector<MCCVLineEntry> Locs = getFunctionLineEntries(FuncId); + bool HaveColumns = any_of(Locs, [](const MCCVLineEntry &LineEntry) { + return LineEntry.getColumn() != 0; + }); + OS.EmitIntValue(HaveColumns ? int(LineFlags::HaveColumns) : 0, 2); + OS.emitAbsoluteSymbolDiff(FuncEnd, FuncBegin, 4); + + for (auto I = Locs.begin(), E = Locs.end(); I != E;) { + // Emit a file segment for the run of locations that share a file id. + unsigned CurFileNum = I->getFileNum(); + auto FileSegEnd = + std::find_if(I, E, [CurFileNum](const MCCVLineEntry &Loc) { + return Loc.getFileNum() != CurFileNum; + }); + unsigned EntryCount = FileSegEnd - I; + OS.AddComment("Segment for file '" + Twine(Filenames[CurFileNum - 1]) + + "' begins"); + OS.EmitIntValue(8 * (CurFileNum - 1), 4); + OS.EmitIntValue(EntryCount, 4); + uint32_t SegmentSize = 12; + SegmentSize += 8 * EntryCount; + if (HaveColumns) + SegmentSize += 4 * EntryCount; + OS.EmitIntValue(SegmentSize, 4); + + for (auto J = I; J != FileSegEnd; ++J) { + OS.emitAbsoluteSymbolDiff(J->getLabel(), FuncBegin, 4); + unsigned LineData = J->getLine(); + if (J->isStmt()) + LineData |= LineInfo::StatementFlag; + OS.EmitIntValue(LineData, 4); + } + if (HaveColumns) { + for (auto J = I; J != FileSegEnd; ++J) { + OS.EmitIntValue(J->getColumn(), 2); + OS.EmitIntValue(0, 2); + } + } + I = FileSegEnd; + } + OS.EmitLabel(LineEnd); +} + +static bool compressAnnotation(uint32_t Data, SmallVectorImpl<char> &Buffer) { + if (isUInt<7>(Data)) { + Buffer.push_back(Data); + return true; + } + + if (isUInt<14>(Data)) { + Buffer.push_back((Data >> 8) | 0x80); + Buffer.push_back(Data & 0xff); + return true; + } + + if (isUInt<29>(Data)) { + Buffer.push_back((Data >> 24) | 0xC0); + Buffer.push_back((Data >> 16) & 0xff); + Buffer.push_back((Data >> 8) & 0xff); + Buffer.push_back(Data & 0xff); + return true; + } + + return false; +} + +static bool compressAnnotation(BinaryAnnotationsOpCode Annotation, + SmallVectorImpl<char> &Buffer) { + return compressAnnotation(static_cast<uint32_t>(Annotation), Buffer); +} + +static uint32_t encodeSignedNumber(uint32_t Data) { + if (Data >> 31) + return ((-Data) << 1) | 1; + return Data << 1; +} + +void CodeViewContext::emitInlineLineTableForFunction( + MCObjectStreamer &OS, unsigned PrimaryFunctionId, unsigned SourceFileId, + unsigned SourceLineNum, const MCSymbol *FnStartSym, + const MCSymbol *FnEndSym, ArrayRef<unsigned> SecondaryFunctionIds) { + // Create and insert a fragment into the current section that will be encoded + // later. + new MCCVInlineLineTableFragment( + PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym, + SecondaryFunctionIds, OS.getCurrentSectionOnly()); +} + +void CodeViewContext::emitDefRange( + MCObjectStreamer &OS, + ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, + StringRef FixedSizePortion) { + // Create and insert a fragment into the current section that will be encoded + // later. + new MCCVDefRangeFragment(Ranges, FixedSizePortion, + OS.getCurrentSectionOnly()); +} + +static unsigned computeLabelDiff(MCAsmLayout &Layout, const MCSymbol *Begin, + const MCSymbol *End) { + MCContext &Ctx = Layout.getAssembler().getContext(); + MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; + const MCExpr *BeginRef = MCSymbolRefExpr::create(Begin, Variant, Ctx), + *EndRef = MCSymbolRefExpr::create(End, Variant, Ctx); + const MCExpr *AddrDelta = + MCBinaryExpr::create(MCBinaryExpr::Sub, EndRef, BeginRef, Ctx); + int64_t Result; + bool Success = AddrDelta->evaluateKnownAbsolute(Result, Layout); + assert(Success && "failed to evaluate label difference as absolute"); + (void)Success; + assert(Result >= 0 && "negative label difference requested"); + assert(Result < UINT_MAX && "label difference greater than 2GB"); + return unsigned(Result); +} + +void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout, + MCCVInlineLineTableFragment &Frag) { + size_t LocBegin; + size_t LocEnd; + std::tie(LocBegin, LocEnd) = getLineExtent(Frag.SiteFuncId); + for (unsigned SecondaryId : Frag.SecondaryFuncs) { + auto Extent = getLineExtent(SecondaryId); + LocBegin = std::min(LocBegin, Extent.first); + LocEnd = std::max(LocEnd, Extent.second); + } + if (LocBegin >= LocEnd) + return; + ArrayRef<MCCVLineEntry> Locs = getLinesForExtent(LocBegin, LocEnd); + if (Locs.empty()) + return; + + SmallSet<unsigned, 8> InlinedFuncIds; + InlinedFuncIds.insert(Frag.SiteFuncId); + InlinedFuncIds.insert(Frag.SecondaryFuncs.begin(), Frag.SecondaryFuncs.end()); + + // Make an artificial start location using the function start and the inlinee + // lines start location information. All deltas start relative to this + // location. + MCCVLineEntry StartLoc(Frag.getFnStartSym(), MCCVLoc(Locs.front())); + StartLoc.setFileNum(Frag.StartFileId); + StartLoc.setLine(Frag.StartLineNum); + const MCCVLineEntry *LastLoc = &StartLoc; + bool HaveOpenRange = false; + + SmallVectorImpl<char> &Buffer = Frag.getContents(); + Buffer.clear(); // Clear old contents if we went through relaxation. + for (const MCCVLineEntry &Loc : Locs) { + if (!InlinedFuncIds.count(Loc.getFunctionId())) { + // We've hit a cv_loc not attributed to this inline call site. Use this + // label to end the PC range. + if (HaveOpenRange) { + unsigned Length = + computeLabelDiff(Layout, LastLoc->getLabel(), Loc.getLabel()); + compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer); + compressAnnotation(Length, Buffer); + } + HaveOpenRange = false; + continue; + } + + // If we've already opened the function and we're at an indirectly inlined + // location, continue until the next directly inlined location. + bool DirectlyInlined = Loc.getFunctionId() == Frag.SiteFuncId; + if (!DirectlyInlined && HaveOpenRange) + continue; + HaveOpenRange = true; + + if (Loc.getFileNum() != LastLoc->getFileNum()) { + // File ids are 1 based, and each file checksum table entry is 8 bytes + // long. See emitFileChecksums above. + unsigned FileOffset = 8 * (Loc.getFileNum() - 1); + compressAnnotation(BinaryAnnotationsOpCode::ChangeFile, Buffer); + compressAnnotation(FileOffset, Buffer); + } + + int LineDelta = Loc.getLine() - LastLoc->getLine(); + if (LineDelta == 0) + continue; + + unsigned EncodedLineDelta = encodeSignedNumber(LineDelta); + unsigned CodeDelta = + computeLabelDiff(Layout, LastLoc->getLabel(), Loc.getLabel()); + if (CodeDelta == 0) { + compressAnnotation(BinaryAnnotationsOpCode::ChangeLineOffset, Buffer); + compressAnnotation(EncodedLineDelta, Buffer); + } else if (EncodedLineDelta < 0x8 && CodeDelta <= 0xf) { + // The ChangeCodeOffsetAndLineOffset combination opcode is used when the + // encoded line delta uses 3 or fewer set bits and the code offset fits + // in one nibble. + unsigned Operand = (EncodedLineDelta << 4) | CodeDelta; + compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset, + Buffer); + compressAnnotation(Operand, Buffer); + } else { + // Otherwise use the separate line and code deltas. + compressAnnotation(BinaryAnnotationsOpCode::ChangeLineOffset, Buffer); + compressAnnotation(EncodedLineDelta, Buffer); + compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeOffset, Buffer); + compressAnnotation(CodeDelta, Buffer); + } + + LastLoc = &Loc; + } + + assert(HaveOpenRange); + + unsigned EndSymLength = + computeLabelDiff(Layout, LastLoc->getLabel(), Frag.getFnEndSym()); + unsigned LocAfterLength = ~0U; + ArrayRef<MCCVLineEntry> LocAfter = getLinesForExtent(LocEnd, LocEnd + 1); + if (!LocAfter.empty()) { + // Only try to compute this difference if we're in the same section. + const MCCVLineEntry &Loc = LocAfter[0]; + if (&Loc.getLabel()->getSection(false) == + &LastLoc->getLabel()->getSection(false)) { + LocAfterLength = + computeLabelDiff(Layout, LastLoc->getLabel(), Loc.getLabel()); + } + } + + compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer); + compressAnnotation(std::min(EndSymLength, LocAfterLength), Buffer); +} + +void CodeViewContext::encodeDefRange(MCAsmLayout &Layout, + MCCVDefRangeFragment &Frag) { + MCContext &Ctx = Layout.getAssembler().getContext(); + SmallVectorImpl<char> &Contents = Frag.getContents(); + Contents.clear(); + SmallVectorImpl<MCFixup> &Fixups = Frag.getFixups(); + Fixups.clear(); + raw_svector_ostream OS(Contents); + + // Write down each range where the variable is defined. + for (std::pair<const MCSymbol *, const MCSymbol *> Range : Frag.getRanges()) { + unsigned RangeSize = computeLabelDiff(Layout, Range.first, Range.second); + unsigned Bias = 0; + // We must split the range into chunks of MaxDefRange, this is a fundamental + // limitation of the file format. + do { + uint16_t Chunk = std::min((uint32_t)MaxDefRange, RangeSize); + + const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Range.first, Ctx); + const MCBinaryExpr *BE = + MCBinaryExpr::createAdd(SRE, MCConstantExpr::create(Bias, Ctx), Ctx); + MCValue Res; + BE->evaluateAsRelocatable(Res, &Layout, /*Fixup=*/nullptr); + + // Each record begins with a 2-byte number indicating how large the record + // is. + StringRef FixedSizePortion = Frag.getFixedSizePortion(); + // Our record is a fixed sized prefix and a LocalVariableAddrRange that we + // are artificially constructing. + size_t RecordSize = + FixedSizePortion.size() + sizeof(LocalVariableAddrRange); + // Write out the recrod size. + support::endian::Writer<support::little>(OS).write<uint16_t>(RecordSize); + // Write out the fixed size prefix. + OS << FixedSizePortion; + // Make space for a fixup that will eventually have a section relative + // relocation pointing at the offset where the variable becomes live. + Fixups.push_back(MCFixup::create(Contents.size(), BE, FK_SecRel_4)); + Contents.resize(Contents.size() + 4); // Fixup for code start. + // Make space for a fixup that will record the section index for the code. + Fixups.push_back(MCFixup::create(Contents.size(), BE, FK_SecRel_2)); + Contents.resize(Contents.size() + 2); // Fixup for section index. + // Write down the range's extent. + support::endian::Writer<support::little>(OS).write<uint16_t>(Chunk); + + // Move on to the next range. + Bias += Chunk; + RangeSize -= Chunk; + } while (RangeSize > 0); + } +} + +// +// This is called when an instruction is assembled into the specified section +// and if there is information from the last .cv_loc directive that has yet to have +// a line entry made for it is made. +// +void MCCVLineEntry::Make(MCObjectStreamer *MCOS) { + if (!MCOS->getContext().getCVLocSeen()) + return; + + // Create a symbol at in the current section for use in the line entry. + MCSymbol *LineSym = MCOS->getContext().createTempSymbol(); + // Set the value of the symbol to use for the MCCVLineEntry. + MCOS->EmitLabel(LineSym); + + // Get the current .loc info saved in the context. + const MCCVLoc &CVLoc = MCOS->getContext().getCurrentCVLoc(); + + // Create a (local) line entry with the symbol and the current .loc info. + MCCVLineEntry LineEntry(LineSym, CVLoc); + + // clear CVLocSeen saying the current .loc info is now used. + MCOS->getContext().clearCVLocSeen(); + + // Add the line entry to this section's entries. + MCOS->getContext().getCVContext().addLineEntry(LineEntry); +} diff --git a/gnu/llvm/lib/MC/MCContext.cpp b/gnu/llvm/lib/MC/MCContext.cpp index b5ad518d033..47ed1ca3add 100644 --- a/gnu/llvm/lib/MC/MCContext.cpp +++ b/gnu/llvm/lib/MC/MCContext.cpp @@ -10,8 +10,9 @@ #include "llvm/MC/MCContext.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" -#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCCodeView.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCLabel.h" #include "llvm/MC/MCObjectFileInfo.h" @@ -24,16 +25,22 @@ #include "llvm/MC/MCSymbolELF.h" #include "llvm/MC/MCSymbolMachO.h" #include "llvm/Support/COFF.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Signals.h" #include "llvm/Support/SourceMgr.h" -#include <map> using namespace llvm; +static cl::opt<char*> +AsSecureLogFileName("as-secure-log-file-name", + cl::desc("As secure log file name (initialized from " + "AS_SECURE_LOG_FILE env variable)"), + cl::init(getenv("AS_SECURE_LOG_FILE")), cl::Hidden); + + MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri, const MCObjectFileInfo *mofi, const SourceMgr *mgr, bool DoAutoReset) @@ -43,12 +50,7 @@ MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri, GenDwarfForAssembly(false), GenDwarfFileNumber(0), DwarfVersion(4), AllowTemporaryLabels(true), DwarfCompileUnitID(0), AutoReset(DoAutoReset), HadError(false) { - - std::error_code EC = llvm::sys::fs::current_path(CompilationDir); - if (EC) - CompilationDir.clear(); - - SecureLogFile = getenv("AS_SECURE_LOG_FILE"); + SecureLogFile = AsSecureLogFileName; SecureLog = nullptr; SecureLogUsed = false; @@ -90,6 +92,8 @@ void MCContext::reset() { DwarfCompileUnitID = 0; CurrentDwarfLoc = MCDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0); + CVContext.reset(); + MachOUniquingMap.clear(); ELFUniquingMap.clear(); COFFUniquingMap.clear(); @@ -126,19 +130,9 @@ MCSymbolELF *MCContext::getOrCreateSectionSymbol(const MCSectionELF &Section) { return Sym; StringRef Name = Section.getSectionName(); - - MCSymbol *&OldSym = Symbols[Name]; - if (OldSym && OldSym->isUndefined()) { - Sym = cast<MCSymbolELF>(OldSym); - return Sym; - } - - auto NameIter = UsedNames.insert(std::make_pair(Name, true)).first; + auto NameIter = UsedNames.insert(std::make_pair(Name, false)).first; Sym = new (&*NameIter, *this) MCSymbolELF(&*NameIter, /*isTemporary*/ false); - if (!OldSym) - OldSym = Sym; - return Sym; } @@ -194,9 +188,12 @@ MCSymbol *MCContext::createSymbol(StringRef Name, bool AlwaysAddSuffix, raw_svector_ostream(NewName) << NextUniqueID++; } auto NameEntry = UsedNames.insert(std::make_pair(NewName, true)); - if (NameEntry.second) { - // Ok, we found a name. Have the MCSymbol object itself refer to the copy - // of the string that is embedded in the UsedNames entry. + if (NameEntry.second || !NameEntry.first->second) { + // Ok, we found a name. + // Mark it as used for a non-section symbol. + NameEntry.first->second = true; + // Have the MCSymbol object itself refer to the copy of the string that is + // embedded in the UsedNames entry. return createSymbolImpl(&*NameEntry.first, IsTemporary); } assert(IsTemporary && "Cannot rename non-temporary symbols"); @@ -312,32 +309,40 @@ void MCContext::renameELFSection(MCSectionELF *Section, StringRef Name) { const_cast<MCSectionELF *>(Section)->setSectionName(CachedName); } -MCSectionELF *MCContext::createELFRelSection(StringRef Name, unsigned Type, +MCSectionELF *MCContext::createELFRelSection(const Twine &Name, unsigned Type, unsigned Flags, unsigned EntrySize, const MCSymbolELF *Group, const MCSectionELF *Associated) { StringMap<bool>::iterator I; bool Inserted; - std::tie(I, Inserted) = ELFRelSecNames.insert(std::make_pair(Name, true)); + std::tie(I, Inserted) = + ELFRelSecNames.insert(std::make_pair(Name.str(), true)); return new (ELFAllocator.Allocate()) MCSectionELF(I->getKey(), Type, Flags, SectionKind::getReadOnly(), EntrySize, Group, true, nullptr, Associated); } -MCSectionELF *MCContext::getELFSection(StringRef Section, unsigned Type, +MCSectionELF *MCContext::getELFNamedSection(const Twine &Prefix, + const Twine &Suffix, unsigned Type, + unsigned Flags, + unsigned EntrySize) { + return getELFSection(Prefix + "." + Suffix, Type, Flags, EntrySize, Suffix); +} + +MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type, unsigned Flags, unsigned EntrySize, - StringRef Group, unsigned UniqueID, + const Twine &Group, unsigned UniqueID, const char *BeginSymName) { MCSymbolELF *GroupSym = nullptr; - if (!Group.empty()) + if (!Group.isTriviallyEmpty() && !Group.str().empty()) GroupSym = cast<MCSymbolELF>(getOrCreateSymbol(Group)); return getELFSection(Section, Type, Flags, EntrySize, GroupSym, UniqueID, BeginSymName, nullptr); } -MCSectionELF *MCContext::getELFSection(StringRef Section, unsigned Type, +MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type, unsigned Flags, unsigned EntrySize, const MCSymbolELF *GroupSym, unsigned UniqueID, @@ -348,7 +353,7 @@ MCSectionELF *MCContext::getELFSection(StringRef Section, unsigned Type, Group = GroupSym->getName(); // Do the lookup, if we have a hit, return it. auto IterBool = ELFUniquingMap.insert( - std::make_pair(ELFSectionKey{Section, Group, UniqueID}, nullptr)); + std::make_pair(ELFSectionKey{Section.str(), Group, UniqueID}, nullptr)); auto &Entry = *IterBool.first; if (!IterBool.second) return Entry.second; @@ -383,6 +388,7 @@ MCSectionCOFF *MCContext::getCOFFSection(StringRef Section, unsigned Characteristics, SectionKind Kind, StringRef COMDATSymName, int Selection, + unsigned UniqueID, const char *BeginSymName) { MCSymbol *COMDATSymbol = nullptr; if (!COMDATSymName.empty()) { @@ -390,8 +396,9 @@ MCSectionCOFF *MCContext::getCOFFSection(StringRef Section, COMDATSymName = COMDATSymbol->getName(); } + // Do the lookup, if we have a hit, return it. - COFFSectionKey T{Section, COMDATSymName, Selection}; + COFFSectionKey T{Section, COMDATSymName, Selection, UniqueID}; auto IterBool = COFFUniquingMap.insert(std::make_pair(T, nullptr)); auto Iter = IterBool.first; if (!IterBool.second) @@ -413,11 +420,12 @@ MCSectionCOFF *MCContext::getCOFFSection(StringRef Section, unsigned Characteristics, SectionKind Kind, const char *BeginSymName) { - return getCOFFSection(Section, Characteristics, Kind, "", 0, BeginSymName); + return getCOFFSection(Section, Characteristics, Kind, "", 0, GenericSectionID, + BeginSymName); } MCSectionCOFF *MCContext::getCOFFSection(StringRef Section) { - COFFSectionKey T{Section, "", 0}; + COFFSectionKey T{Section, "", 0, GenericSectionID}; auto Iter = COFFUniquingMap.find(T); if (Iter == COFFUniquingMap.end()) return nullptr; @@ -425,18 +433,24 @@ MCSectionCOFF *MCContext::getCOFFSection(StringRef Section) { } MCSectionCOFF *MCContext::getAssociativeCOFFSection(MCSectionCOFF *Sec, - const MCSymbol *KeySym) { - // Return the normal section if we don't have to be associative. - if (!KeySym) + const MCSymbol *KeySym, + unsigned UniqueID) { + // Return the normal section if we don't have to be associative or unique. + if (!KeySym && UniqueID == GenericSectionID) return Sec; - // Make an associative section with the same name and kind as the normal - // section. - unsigned Characteristics = - Sec->getCharacteristics() | COFF::IMAGE_SCN_LNK_COMDAT; + // If we have a key symbol, make an associative section with the same name and + // kind as the normal section. + unsigned Characteristics = Sec->getCharacteristics(); + if (KeySym) { + Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; + return getCOFFSection(Sec->getSectionName(), Characteristics, + Sec->getKind(), KeySym->getName(), + COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, UniqueID); + } + return getCOFFSection(Sec->getSectionName(), Characteristics, Sec->getKind(), - KeySym->getName(), - COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE); + "", 0, UniqueID); } MCSubtargetInfo &MCContext::getSubtargetCopy(const MCSubtargetInfo &STI) { @@ -474,6 +488,20 @@ void MCContext::finalizeDwarfSections(MCStreamer &MCOS) { [&](MCSection *Sec) { return !MCOS.mayHaveInstructions(*Sec); }); } +CodeViewContext &MCContext::getCVContext() { + if (!CVContext.get()) + CVContext.reset(new CodeViewContext); + return *CVContext.get(); +} + +unsigned MCContext::getCVFile(StringRef FileName, unsigned FileNumber) { + return getCVContext().addFile(FileNumber, FileName) ? FileNumber : 0; +} + +bool MCContext::isValidCVFileNumber(unsigned FileNumber) { + return getCVContext().isValidFileNumber(FileNumber); +} + //===----------------------------------------------------------------------===// // Error Reporting //===----------------------------------------------------------------------===// diff --git a/gnu/llvm/lib/MC/MCDisassembler/CMakeLists.txt b/gnu/llvm/lib/MC/MCDisassembler/CMakeLists.txt index f266f8fcd30..e940afc56f5 100644 --- a/gnu/llvm/lib/MC/MCDisassembler/CMakeLists.txt +++ b/gnu/llvm/lib/MC/MCDisassembler/CMakeLists.txt @@ -1,6 +1,7 @@ add_llvm_library(LLVMMCDisassembler Disassembler.cpp - MCRelocationInfo.cpp - MCExternalSymbolizer.cpp MCDisassembler.cpp + MCExternalSymbolizer.cpp + MCRelocationInfo.cpp + MCSymbolizer.cpp ) diff --git a/gnu/llvm/lib/MC/MCDisassembler/Disassembler.cpp b/gnu/llvm/lib/MC/MCDisassembler/Disassembler.cpp index 82063fb7469..21e8748b797 100644 --- a/gnu/llvm/lib/MC/MCDisassembler/Disassembler.cpp +++ b/gnu/llvm/lib/MC/MCDisassembler/Disassembler.cpp @@ -11,14 +11,14 @@ #include "llvm-c/Disassembler.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" +#include "llvm/MC/MCDisassembler/MCRelocationInfo.h" +#include "llvm/MC/MCDisassembler/MCSymbolizer.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCRelocationInfo.h" #include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCSymbolizer.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/TargetRegistry.h" diff --git a/gnu/llvm/lib/MC/MCDisassembler/Disassembler.h b/gnu/llvm/lib/MC/MCDisassembler/Disassembler.h index 46d0c4c3d94..25d17dafb57 100644 --- a/gnu/llvm/lib/MC/MCDisassembler/Disassembler.h +++ b/gnu/llvm/lib/MC/MCDisassembler/Disassembler.h @@ -19,17 +19,18 @@ #include "llvm-c/Disassembler.h" #include "llvm/ADT/SmallString.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/raw_ostream.h" #include <string> +#include <utility> namespace llvm { -class MCContext; -class MCAsmInfo; -class MCDisassembler; -class MCInstPrinter; -class MCInstrInfo; -class MCRegisterInfo; -class MCSubtargetInfo; class Target; // @@ -86,15 +87,12 @@ public: LLVMOpInfoCallback getOpInfo, LLVMSymbolLookupCallback symbolLookUp, const Target *theTarget, const MCAsmInfo *mAI, - const MCRegisterInfo *mRI, - const MCSubtargetInfo *mSI, - const MCInstrInfo *mII, - llvm::MCContext *ctx, const MCDisassembler *disAsm, - MCInstPrinter *iP) : TripleName(tripleName), - DisInfo(disInfo), TagType(tagType), GetOpInfo(getOpInfo), - SymbolLookUp(symbolLookUp), TheTarget(theTarget), - Options(0), - CommentStream(CommentsToEmit) { + const MCRegisterInfo *mRI, const MCSubtargetInfo *mSI, + const MCInstrInfo *mII, llvm::MCContext *ctx, + const MCDisassembler *disAsm, MCInstPrinter *iP) + : TripleName(std::move(tripleName)), DisInfo(disInfo), TagType(tagType), + GetOpInfo(getOpInfo), SymbolLookUp(symbolLookUp), TheTarget(theTarget), + Options(0), CommentStream(CommentsToEmit) { MAI.reset(mAI); MRI.reset(mRI); MSI.reset(mSI); diff --git a/gnu/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp b/gnu/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp index 1084e5ea766..3a4f7382bd3 100644 --- a/gnu/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp +++ b/gnu/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCDisassembler.h" -#include "llvm/MC/MCExternalSymbolizer.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" +#include "llvm/MC/MCDisassembler/MCExternalSymbolizer.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; diff --git a/gnu/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp b/gnu/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp index 5fc2ca44f5d..1969c5dc66a 100644 --- a/gnu/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp +++ b/gnu/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCExternalSymbolizer.h" +#include "llvm/MC/MCDisassembler/MCExternalSymbolizer.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" diff --git a/gnu/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp b/gnu/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp index 43005e7c740..1612562497d 100644 --- a/gnu/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp +++ b/gnu/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp @@ -7,9 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCRelocationInfo.h" +#include "llvm/MC/MCDisassembler/MCRelocationInfo.h" #include "llvm-c/Disassembler.h" -#include "llvm/Object/ObjectFile.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; @@ -22,11 +21,6 @@ MCRelocationInfo::~MCRelocationInfo() { } const MCExpr * -MCRelocationInfo::createExprForRelocation(object::RelocationRef Rel) { - return nullptr; -} - -const MCExpr * MCRelocationInfo::createExprForCAPIVariantKind(const MCExpr *SubExpr, unsigned VariantKind) { if (VariantKind != LLVMDisassembler_VariantKind_None) diff --git a/gnu/llvm/lib/MC/MCDisassembler/MCSymbolizer.cpp b/gnu/llvm/lib/MC/MCDisassembler/MCSymbolizer.cpp new file mode 100644 index 00000000000..c0f707d356c --- /dev/null +++ b/gnu/llvm/lib/MC/MCDisassembler/MCSymbolizer.cpp @@ -0,0 +1,15 @@ +//===-- llvm/MC/MCSymbolizer.cpp - MCSymbolizer class -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCDisassembler/MCSymbolizer.h" + +using namespace llvm; + +MCSymbolizer::~MCSymbolizer() { +} diff --git a/gnu/llvm/lib/MC/MCDwarf.cpp b/gnu/llvm/lib/MC/MCDwarf.cpp index dafa7683b1a..54b2c918c84 100644 --- a/gnu/llvm/lib/MC/MCDwarf.cpp +++ b/gnu/llvm/lib/MC/MCDwarf.cpp @@ -22,6 +22,7 @@ #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/EndianStream.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/Path.h" @@ -46,20 +47,20 @@ static inline uint64_t ScaleAddrDelta(MCContext &Context, uint64_t AddrDelta) { // and if there is information from the last .loc directive that has yet to have // a line entry made for it is made. // -void MCLineEntry::Make(MCObjectStreamer *MCOS, MCSection *Section) { +void MCDwarfLineEntry::Make(MCObjectStreamer *MCOS, MCSection *Section) { if (!MCOS->getContext().getDwarfLocSeen()) return; // Create a symbol at in the current section for use in the line entry. MCSymbol *LineSym = MCOS->getContext().createTempSymbol(); - // Set the value of the symbol to use for the MCLineEntry. + // Set the value of the symbol to use for the MCDwarfLineEntry. MCOS->EmitLabel(LineSym); // Get the current .loc info saved in the context. const MCDwarfLoc &DwarfLoc = MCOS->getContext().getCurrentDwarfLoc(); // Create a (local) line entry with the symbol and the current .loc info. - MCLineEntry LineEntry(LineSym, DwarfLoc); + MCDwarfLineEntry LineEntry(LineSym, DwarfLoc); // clear DwarfLocSeen saying the current .loc info is now used. MCOS->getContext().clearDwarfLocSeen(); @@ -98,7 +99,7 @@ static inline const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS, // static inline void EmitDwarfLineTable(MCObjectStreamer *MCOS, MCSection *Section, - const MCLineSection::MCLineEntryCollection &LineEntries) { + const MCLineSection::MCDwarfLineEntryCollection &LineEntries) { unsigned FileNum = 1; unsigned LastLine = 1; unsigned Column = 0; @@ -107,47 +108,45 @@ EmitDwarfLineTable(MCObjectStreamer *MCOS, MCSection *Section, unsigned Discriminator = 0; MCSymbol *LastLabel = nullptr; - // Loop through each MCLineEntry and encode the dwarf line number table. - for (auto it = LineEntries.begin(), - ie = LineEntries.end(); - it != ie; ++it) { + // Loop through each MCDwarfLineEntry and encode the dwarf line number table. + for (const MCDwarfLineEntry &LineEntry : LineEntries) { + int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine; - if (FileNum != it->getFileNum()) { - FileNum = it->getFileNum(); + if (FileNum != LineEntry.getFileNum()) { + FileNum = LineEntry.getFileNum(); MCOS->EmitIntValue(dwarf::DW_LNS_set_file, 1); MCOS->EmitULEB128IntValue(FileNum); } - if (Column != it->getColumn()) { - Column = it->getColumn(); + if (Column != LineEntry.getColumn()) { + Column = LineEntry.getColumn(); MCOS->EmitIntValue(dwarf::DW_LNS_set_column, 1); MCOS->EmitULEB128IntValue(Column); } - if (Discriminator != it->getDiscriminator()) { - Discriminator = it->getDiscriminator(); + if (Discriminator != LineEntry.getDiscriminator()) { + Discriminator = LineEntry.getDiscriminator(); unsigned Size = getULEB128Size(Discriminator); MCOS->EmitIntValue(dwarf::DW_LNS_extended_op, 1); MCOS->EmitULEB128IntValue(Size + 1); MCOS->EmitIntValue(dwarf::DW_LNE_set_discriminator, 1); MCOS->EmitULEB128IntValue(Discriminator); } - if (Isa != it->getIsa()) { - Isa = it->getIsa(); + if (Isa != LineEntry.getIsa()) { + Isa = LineEntry.getIsa(); MCOS->EmitIntValue(dwarf::DW_LNS_set_isa, 1); MCOS->EmitULEB128IntValue(Isa); } - if ((it->getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { - Flags = it->getFlags(); + if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { + Flags = LineEntry.getFlags(); MCOS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1); } - if (it->getFlags() & DWARF2_FLAG_BASIC_BLOCK) + if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK) MCOS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1); - if (it->getFlags() & DWARF2_FLAG_PROLOGUE_END) + if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END) MCOS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1); - if (it->getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) + if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) MCOS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1); - int64_t LineDelta = static_cast<int64_t>(it->getLine()) - LastLine; - MCSymbol *Label = it->getLabel(); + MCSymbol *Label = LineEntry.getLabel(); // At this point we want to emit/create the sequence to encode the delta in // line numbers and the increment of the address from the previous Label @@ -156,7 +155,8 @@ EmitDwarfLineTable(MCObjectStreamer *MCOS, MCSection *Section, MCOS->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, asmInfo->getPointerSize()); - LastLine = it->getLine(); + Discriminator = 0; + LastLine = LineEntry.getLine(); LastLabel = Label; } @@ -344,9 +344,9 @@ unsigned MCDwarfLineTableHeader::getFile(StringRef &Directory, } assert(!FileName.empty()); if (FileNumber == 0) { - FileNumber = SourceIdMap.size() + 1; - assert((MCDwarfFiles.empty() || FileNumber == MCDwarfFiles.size()) && - "Don't mix autonumbered and explicit numbered line table usage"); + // File numbers start with 1 and/or after any file numbers + // allocated by inline-assembler .file directives. + FileNumber = MCDwarfFiles.empty() ? 1 : MCDwarfFiles.size(); SmallString<256> Buffer; auto IterBool = SourceIdMap.insert( std::make_pair((Directory + Twine('\0') + FileName).toStringRef(Buffer), @@ -452,7 +452,8 @@ void MCDwarfLineAddr::Encode(MCContext &Context, MCDwarfLineTableParams Params, // If the line increment is out of range of a special opcode, we must encode // it with DW_LNS_advance_line. - if (Temp >= Params.DWARF2LineRange) { + if (Temp >= Params.DWARF2LineRange || + Temp + Params.DWARF2LineOpcodeBase > 255) { OS << char(dwarf::DW_LNS_advance_line); encodeSLEB128(LineDelta, OS); @@ -494,8 +495,10 @@ void MCDwarfLineAddr::Encode(MCContext &Context, MCDwarfLineTableParams Params, if (NeedCopy) OS << char(dwarf::DW_LNS_copy); - else + else { + assert(Temp <= 255 && "Buggy special opcode encoding."); OS << char(Temp); + } } // Utility function to write a tuple for .debug_abbrev. @@ -815,7 +818,7 @@ static void EmitGenDwarfRanges(MCStreamer *MCOS) { // Emit a base address selection entry for the start of this section const MCExpr *SectionStartAddr = MCSymbolRefExpr::create( StartSymbol, MCSymbolRefExpr::VK_None, context); - MCOS->EmitFill(AddrSize, 0xFF); + MCOS->emitFill(AddrSize, 0xFF); MCOS->EmitValue(SectionStartAddr, AddrSize); // Emit a range list entry spanning this section @@ -1156,8 +1159,7 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) { /// Emit frame instructions to describe the layout of the frame. void FrameEmitterImpl::EmitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs, MCSymbol *BaseLabel) { - for (unsigned i = 0, N = Instrs.size(); i < N; ++i) { - const MCCFIInstruction &Instr = Instrs[i]; + for (const MCCFIInstruction &Instr : Instrs) { MCSymbol *Label = Instr.getLabel(); // Throw out move if the label is invalid. if (Label && !Label->isDefined()) continue; // Not emitted, in dead code. @@ -1494,8 +1496,7 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB, bool NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame(); if (IsEH && MOFI->getCompactUnwindSection()) { bool SectionEmitted = false; - for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) { - const MCDwarfFrameInfo &Frame = FrameArray[i]; + for (const MCDwarfFrameInfo &Frame : FrameArray) { if (Frame.CompactUnwindEncoding == 0) continue; if (!SectionEmitted) { Streamer.SwitchSection(MOFI->getCompactUnwindSection()); diff --git a/gnu/llvm/lib/MC/MCELFStreamer.cpp b/gnu/llvm/lib/MC/MCELFStreamer.cpp index 06d161bccab..7d858c306d2 100644 --- a/gnu/llvm/lib/MC/MCELFStreamer.cpp +++ b/gnu/llvm/lib/MC/MCELFStreamer.cpp @@ -24,6 +24,7 @@ #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/MCSectionELF.h" #include "llvm/MC/MCSymbolELF.h" @@ -283,6 +284,9 @@ bool MCELFStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) { case MCSA_Internal: Symbol->setVisibility(ELF::STV_INTERNAL); break; + + case MCSA_AltEntry: + llvm_unreachable("ELF doesn't support the .alt_entry attribute"); } return true; @@ -406,13 +410,10 @@ void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { case MCSymbolRefExpr::VK_TLSLD: case MCSymbolRefExpr::VK_TLSLDM: case MCSymbolRefExpr::VK_TPOFF: + case MCSymbolRefExpr::VK_TPREL: case MCSymbolRefExpr::VK_DTPOFF: - case MCSymbolRefExpr::VK_Mips_TLSGD: - case MCSymbolRefExpr::VK_Mips_GOTTPREL: - case MCSymbolRefExpr::VK_Mips_TPREL_HI: - case MCSymbolRefExpr::VK_Mips_TPREL_LO: + case MCSymbolRefExpr::VK_DTPREL: case MCSymbolRefExpr::VK_PPC_DTPMOD: - case MCSymbolRefExpr::VK_PPC_TPREL: case MCSymbolRefExpr::VK_PPC_TPREL_LO: case MCSymbolRefExpr::VK_PPC_TPREL_HI: case MCSymbolRefExpr::VK_PPC_TPREL_HA: @@ -420,7 +421,6 @@ void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA: case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST: case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA: - case MCSymbolRefExpr::VK_PPC_DTPREL: case MCSymbolRefExpr::VK_PPC_DTPREL_LO: case MCSymbolRefExpr::VK_PPC_DTPREL_HI: case MCSymbolRefExpr::VK_PPC_DTPREL_HA: diff --git a/gnu/llvm/lib/MC/MCExpr.cpp b/gnu/llvm/lib/MC/MCExpr.cpp index 748644bd9c8..6f90ff843bd 100644 --- a/gnu/llvm/lib/MC/MCExpr.cpp +++ b/gnu/llvm/lib/MC/MCExpr.cpp @@ -30,7 +30,7 @@ STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations"); } } -void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const { +void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const { switch (getKind()) { case MCExpr::Target: return cast<MCTargetExpr>(this)->printImpl(OS, MAI); @@ -43,7 +43,8 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const { const MCSymbol &Sym = SRE.getSymbol(); // Parenthesize names that start with $ so that they don't look like // absolute names. - bool UseParens = Sym.getName().size() && Sym.getName()[0] == '$'; + bool UseParens = + !InParens && Sym.getName().size() && Sym.getName()[0] == '$'; if (UseParens) { OS << '('; Sym.print(OS, MAI); @@ -129,7 +130,7 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const { } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -void MCExpr::dump() const { +LLVM_DUMP_METHOD void MCExpr::dump() const { dbgs() << *this; dbgs() << '\n'; } @@ -178,8 +179,11 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_Invalid: return "<<invalid>>"; case VK_None: return "<<none>>"; + case VK_DTPOFF: return "DTPOFF"; + case VK_DTPREL: return "DTPREL"; case VK_GOT: return "GOT"; case VK_GOTOFF: return "GOTOFF"; + case VK_GOTREL: return "GOTREL"; case VK_GOTPCREL: return "GOTPCREL"; case VK_GOTTPOFF: return "GOTTPOFF"; case VK_INDNTPOFF: return "INDNTPOFF"; @@ -190,7 +194,9 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_TLSLD: return "TLSLD"; case VK_TLSLDM: return "TLSLDM"; case VK_TPOFF: return "TPOFF"; - case VK_DTPOFF: return "DTPOFF"; + case VK_TPREL: return "TPREL"; + case VK_TLSCALL: return "tlscall"; + case VK_TLSDESC: return "tlsdesc"; case VK_TLVP: return "TLVP"; case VK_TLVPPAGE: return "TLVPPAGE"; case VK_TLVPPAGEOFF: return "TLVPPAGEOFF"; @@ -208,8 +214,6 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_ARM_PREL31: return "prel31"; case VK_ARM_SBREL: return "sbrel"; case VK_ARM_TLSLDO: return "tlsldo"; - case VK_ARM_TLSCALL: return "tlscall"; - case VK_ARM_TLSDESC: return "tlsdesc"; case VK_ARM_TLSDESCSEQ: return "tlsdescseq"; case VK_PPC_LO: return "l"; case VK_PPC_HI: return "h"; @@ -227,7 +231,6 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_PPC_TOC_HI: return "toc@h"; case VK_PPC_TOC_HA: return "toc@ha"; case VK_PPC_DTPMOD: return "dtpmod"; - case VK_PPC_TPREL: return "tprel"; case VK_PPC_TPREL_LO: return "tprel@l"; case VK_PPC_TPREL_HI: return "tprel@h"; case VK_PPC_TPREL_HA: return "tprel@ha"; @@ -235,7 +238,6 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_PPC_TPREL_HIGHERA: return "tprel@highera"; case VK_PPC_TPREL_HIGHEST: return "tprel@highest"; case VK_PPC_TPREL_HIGHESTA: return "tprel@highesta"; - case VK_PPC_DTPREL: return "dtprel"; case VK_PPC_DTPREL_LO: return "dtprel@l"; case VK_PPC_DTPREL_HI: return "dtprel@h"; case VK_PPC_DTPREL_HA: return "dtprel@ha"; @@ -263,32 +265,6 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha"; case VK_PPC_TLSLD: return "tlsld"; case VK_PPC_LOCAL: return "local"; - case VK_Mips_GPREL: return "GPREL"; - case VK_Mips_GOT_CALL: return "GOT_CALL"; - case VK_Mips_GOT16: return "GOT16"; - case VK_Mips_GOT: return "GOT"; - case VK_Mips_ABS_HI: return "ABS_HI"; - case VK_Mips_ABS_LO: return "ABS_LO"; - case VK_Mips_TLSGD: return "TLSGD"; - case VK_Mips_TLSLDM: return "TLSLDM"; - case VK_Mips_DTPREL_HI: return "DTPREL_HI"; - case VK_Mips_DTPREL_LO: return "DTPREL_LO"; - case VK_Mips_GOTTPREL: return "GOTTPREL"; - case VK_Mips_TPREL_HI: return "TPREL_HI"; - case VK_Mips_TPREL_LO: return "TPREL_LO"; - case VK_Mips_GPOFF_HI: return "GPOFF_HI"; - case VK_Mips_GPOFF_LO: return "GPOFF_LO"; - case VK_Mips_GOT_DISP: return "GOT_DISP"; - case VK_Mips_GOT_PAGE: return "GOT_PAGE"; - case VK_Mips_GOT_OFST: return "GOT_OFST"; - case VK_Mips_HIGHER: return "HIGHER"; - case VK_Mips_HIGHEST: return "HIGHEST"; - case VK_Mips_GOT_HI16: return "GOT_HI16"; - case VK_Mips_GOT_LO16: return "GOT_LO16"; - case VK_Mips_CALL_HI16: return "CALL_HI16"; - case VK_Mips_CALL_LO16: return "CALL_LO16"; - case VK_Mips_PCREL_HI16: return "PCREL_HI16"; - case VK_Mips_PCREL_LO16: return "PCREL_LO16"; case VK_COFF_IMGREL32: return "IMGREL"; case VK_Hexagon_PCREL: return "PCREL"; case VK_Hexagon_LO16: return "LO16"; @@ -301,8 +277,6 @@ 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_TPREL: return "tprel"; - case VK_DTPREL: return "dtprel"; } llvm_unreachable("Invalid variant kind"); } @@ -310,19 +284,24 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { MCSymbolRefExpr::VariantKind MCSymbolRefExpr::getVariantKindForName(StringRef Name) { return StringSwitch<VariantKind>(Name.lower()) + .Case("dtprel", VK_DTPREL) + .Case("dtpoff", VK_DTPOFF) .Case("got", VK_GOT) .Case("gotoff", VK_GOTOFF) + .Case("gotrel", VK_GOTREL) .Case("gotpcrel", VK_GOTPCREL) .Case("gottpoff", VK_GOTTPOFF) .Case("indntpoff", VK_INDNTPOFF) .Case("ntpoff", VK_NTPOFF) .Case("gotntpoff", VK_GOTNTPOFF) .Case("plt", VK_PLT) + .Case("tlscall", VK_TLSCALL) + .Case("tlsdesc", VK_TLSDESC) .Case("tlsgd", VK_TLSGD) .Case("tlsld", VK_TLSLD) .Case("tlsldm", VK_TLSLDM) .Case("tpoff", VK_TPOFF) - .Case("dtpoff", VK_DTPOFF) + .Case("tprel", VK_TPREL) .Case("tlvp", VK_TLVP) .Case("tlvppage", VK_TLVPPAGE) .Case("tlvppageoff", VK_TLVPPAGEOFF) @@ -351,7 +330,6 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) { .Case("toc@ha", VK_PPC_TOC_HA) .Case("tls", VK_PPC_TLS) .Case("dtpmod", VK_PPC_DTPMOD) - .Case("tprel", VK_PPC_TPREL) .Case("tprel@l", VK_PPC_TPREL_LO) .Case("tprel@h", VK_PPC_TPREL_HI) .Case("tprel@ha", VK_PPC_TPREL_HA) @@ -359,7 +337,6 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) { .Case("tprel@highera", VK_PPC_TPREL_HIGHERA) .Case("tprel@highest", VK_PPC_TPREL_HIGHEST) .Case("tprel@highesta", VK_PPC_TPREL_HIGHESTA) - .Case("dtprel", VK_PPC_DTPREL) .Case("dtprel@l", VK_PPC_DTPREL_LO) .Case("dtprel@h", VK_PPC_DTPREL_HI) .Case("dtprel@ha", VK_PPC_DTPREL_HA) @@ -397,8 +374,6 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) { .Case("prel31", VK_ARM_PREL31) .Case("sbrel", VK_ARM_SBREL) .Case("tlsldo", VK_ARM_TLSLDO) - .Case("tlscall", VK_ARM_TLSCALL) - .Case("tlsdesc", VK_ARM_TLSDESC) .Default(VK_Invalid); } @@ -688,8 +663,10 @@ bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, /// -(a - b + const) ==> (b - a - const) if (Value.getSymA() && !Value.getSymB()) return false; + + // The cast avoids undefined behavior if the constant is INT64_MIN. Res = MCValue::get(Value.getSymB(), Value.getSymA(), - -Value.getConstant()); + -(uint64_t)Value.getConstant()); break; case MCUnaryExpr::Not: if (!Value.isAbsolute()) @@ -722,9 +699,10 @@ bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, return false; case MCBinaryExpr::Sub: // Negate RHS and add. + // The cast avoids undefined behavior if the constant is INT64_MIN. return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, RHSValue.getSymB(), RHSValue.getSymA(), - -RHSValue.getConstant(), Res); + -(uint64_t)RHSValue.getConstant(), Res); case MCBinaryExpr::Add: return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, diff --git a/gnu/llvm/lib/MC/MCFragment.cpp b/gnu/llvm/lib/MC/MCFragment.cpp index efdb7049203..1eb1d2996cb 100644 --- a/gnu/llvm/lib/MC/MCFragment.cpp +++ b/gnu/llvm/lib/MC/MCFragment.cpp @@ -25,7 +25,6 @@ #include "llvm/Support/LEB128.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" -#include <tuple> using namespace llvm; MCAsmLayout::MCAsmLayout(MCAssembler &Asm) @@ -289,6 +288,12 @@ void MCFragment::destroy() { case FT_SafeSEH: delete cast<MCSafeSEHFragment>(this); return; + case FT_CVInlineLines: + delete cast<MCCVInlineLineTableFragment>(this); + return; + case FT_CVDefRange: + delete cast<MCCVDefRangeFragment>(this); + return; case FT_Dummy: delete cast<MCDummyFragment>(this); return; @@ -311,7 +316,7 @@ raw_ostream &operator<<(raw_ostream &OS, const MCFixup &AF) { } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -void MCFragment::dump() { +LLVM_DUMP_METHOD void MCFragment::dump() { raw_ostream &OS = llvm::errs(); OS << "<"; @@ -327,9 +332,9 @@ void MCFragment::dump() { case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break; case MCFragment::FT_LEB: OS << "MCLEBFragment"; break; case MCFragment::FT_SafeSEH: OS << "MCSafeSEHFragment"; break; - case MCFragment::FT_Dummy: - OS << "MCDummyFragment"; - break; + case MCFragment::FT_CVInlineLines: OS << "MCCVInlineLineTableFragment"; break; + case MCFragment::FT_CVDefRange: OS << "MCCVDefRangeTableFragment"; break; + case MCFragment::FT_Dummy: OS << "MCDummyFragment"; break; } OS << "<MCFragment " << (void*) this << " LayoutOrder:" << LayoutOrder @@ -386,8 +391,7 @@ void MCFragment::dump() { } case MCFragment::FT_Fill: { const MCFillFragment *FF = cast<MCFillFragment>(this); - OS << " Value:" << FF->getValue() << " ValueSize:" << FF->getValueSize() - << " Size:" << FF->getSize(); + OS << " Value:" << FF->getValue() << " Size:" << FF->getSize(); break; } case MCFragment::FT_Relaxable: { @@ -428,13 +432,29 @@ void MCFragment::dump() { OS << " Sym:" << F->getSymbol(); break; } + case MCFragment::FT_CVInlineLines: { + const auto *F = cast<MCCVInlineLineTableFragment>(this); + OS << "\n "; + OS << " Sym:" << *F->getFnStartSym(); + break; + } + case MCFragment::FT_CVDefRange: { + const auto *F = cast<MCCVDefRangeFragment>(this); + OS << "\n "; + for (std::pair<const MCSymbol *, const MCSymbol *> RangeStartEnd : + F->getRanges()) { + OS << " RangeStart:" << RangeStartEnd.first; + OS << " RangeEnd:" << RangeStartEnd.second; + } + break; + } case MCFragment::FT_Dummy: break; } OS << ">"; } -void MCAssembler::dump() { +LLVM_DUMP_METHOD void MCAssembler::dump() { raw_ostream &OS = llvm::errs(); OS << "<MCAssembler\n"; diff --git a/gnu/llvm/lib/MC/MCInst.cpp b/gnu/llvm/lib/MC/MCInst.cpp index 5f829aeb339..16bc597cf3a 100644 --- a/gnu/llvm/lib/MC/MCInst.cpp +++ b/gnu/llvm/lib/MC/MCInst.cpp @@ -35,7 +35,7 @@ void MCOperand::print(raw_ostream &OS) const { } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -void MCOperand::dump() const { +LLVM_DUMP_METHOD void MCOperand::dump() const { print(dbgs()); dbgs() << "\n"; } @@ -66,7 +66,7 @@ void MCInst::dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer, } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -void MCInst::dump() const { +LLVM_DUMP_METHOD void MCInst::dump() const { print(dbgs()); dbgs() << "\n"; } diff --git a/gnu/llvm/lib/MC/MCLabel.cpp b/gnu/llvm/lib/MC/MCLabel.cpp index 1d3022a93e8..d973fc93b98 100644 --- a/gnu/llvm/lib/MC/MCLabel.cpp +++ b/gnu/llvm/lib/MC/MCLabel.cpp @@ -17,7 +17,7 @@ void MCLabel::print(raw_ostream &OS) const { } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -void MCLabel::dump() const { +LLVM_DUMP_METHOD void MCLabel::dump() const { print(dbgs()); } #endif diff --git a/gnu/llvm/lib/MC/MCLinkerOptimizationHint.cpp b/gnu/llvm/lib/MC/MCLinkerOptimizationHint.cpp index 5f6a57980ad..f71fc783012 100644 --- a/gnu/llvm/lib/MC/MCLinkerOptimizationHint.cpp +++ b/gnu/llvm/lib/MC/MCLinkerOptimizationHint.cpp @@ -10,6 +10,7 @@ #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" using namespace llvm; @@ -27,7 +28,31 @@ void MCLOHDirective::emit_impl(raw_ostream &OutStream, const MCAsmLayout &Layout) const { encodeULEB128(Kind, OutStream); encodeULEB128(Args.size(), OutStream); - for (LOHArgs::const_iterator It = Args.begin(), EndIt = Args.end(); - It != EndIt; ++It) - encodeULEB128(ObjWriter.getSymbolAddress(**It, Layout), OutStream); + for (const MCSymbol *Arg : Args) + encodeULEB128(ObjWriter.getSymbolAddress(*Arg, Layout), OutStream); +} + +void MCLOHDirective::emit(MachObjectWriter &ObjWriter, + const MCAsmLayout &Layout) const { + raw_ostream &OutStream = ObjWriter.getStream(); + emit_impl(OutStream, ObjWriter, Layout); +} + +uint64_t MCLOHDirective::getEmitSize(const MachObjectWriter &ObjWriter, + const MCAsmLayout &Layout) const { + class raw_counting_ostream : public raw_ostream { + uint64_t Count; + + 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() override { flush(); } + }; + + raw_counting_ostream OutStream; + emit_impl(OutStream, ObjWriter, Layout); + return OutStream.tell(); } diff --git a/gnu/llvm/lib/MC/MCMachOStreamer.cpp b/gnu/llvm/lib/MC/MCMachOStreamer.cpp index 21f7571eec4..45a497240b4 100644 --- a/gnu/llvm/lib/MC/MCMachOStreamer.cpp +++ b/gnu/llvm/lib/MC/MCMachOStreamer.cpp @@ -23,6 +23,7 @@ #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSymbolMachO.h" +#include "llvm/MC/MCValue.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" @@ -70,6 +71,7 @@ public: void ChangeSection(MCSection *Sect, const MCExpr *Subsect) override; void EmitLabel(MCSymbol *Symbol) override; + void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) override; void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitLinkerOptions(ArrayRef<std::string> Options) override; @@ -198,9 +200,20 @@ void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { cast<MCSymbolMachO>(Symbol)->clearReferenceType(); } +void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { + MCValue Res; + + if (Value->evaluateAsRelocatable(Res, nullptr, nullptr)) { + if (const MCSymbolRefExpr *SymAExpr = Res.getSymA()) { + const MCSymbol &SymA = SymAExpr->getSymbol(); + if (!Res.getSymB() && (SymA.getName() == "" || Res.getConstant() != 0)) + cast<MCSymbolMachO>(Symbol)->setAltEntry(); + } + } + MCObjectStreamer::EmitAssignment(Symbol, Value); +} + void MCMachOStreamer::EmitDataRegion(DataRegionData::KindTy Kind) { - if (!getAssembler().getBackend().hasDataInCodeSupport()) - return; // Create a temporary label to mark the start of the data region. MCSymbol *Start = getContext().createTempSymbol(); EmitLabel(Start); @@ -211,8 +224,6 @@ void MCMachOStreamer::EmitDataRegion(DataRegionData::KindTy Kind) { } void MCMachOStreamer::EmitDataRegionEnd() { - if (!getAssembler().getBackend().hasDataInCodeSupport()) - return; std::vector<DataRegionData> &Regions = getAssembler().getDataRegions(); assert(!Regions.empty() && "Mismatched .end_data_region!"); DataRegionData &Data = Regions.back(); @@ -346,6 +357,10 @@ bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Sym, Symbol->setSymbolResolver(); break; + case MCSA_AltEntry: + Symbol->setAltEntry(); + break; + case MCSA_PrivateExtern: Symbol->setExternal(true); Symbol->setPrivateExtern(true); @@ -414,7 +429,7 @@ void MCMachOStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, if (ByteAlignment != 1) new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, Section); - MCFragment *F = new MCFillFragment(0, 0, Size, Section); + MCFragment *F = new MCFillFragment(0, Size, Section); Symbol->setFragment(F); // Update the maximum alignment on the zero fill section if necessary. @@ -427,7 +442,6 @@ void MCMachOStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, void MCMachOStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { EmitZerofill(Section, Symbol, Size, ByteAlignment); - return; } void MCMachOStreamer::EmitInstToData(const MCInst &Inst, diff --git a/gnu/llvm/lib/MC/MCObjectFileInfo.cpp b/gnu/llvm/lib/MC/MCObjectFileInfo.cpp index f86f7e40acb..d05bcea14c9 100644 --- a/gnu/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/gnu/llvm/lib/MC/MCObjectFileInfo.cpp @@ -30,7 +30,7 @@ static bool useCompactUnwind(const Triple &T) { return true; // armv7k always has it. - if (T.isWatchOS()) + if (T.isWatchABI()) return true; // Use it on newer version of OS X. @@ -45,7 +45,7 @@ static bool useCompactUnwind(const Triple &T) { return false; } -void MCObjectFileInfo::initMachOMCObjectFileInfo(Triple T) { +void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) { // MachO SupportsWeakOmittedEHFrame = false; @@ -58,7 +58,7 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(Triple T) { if (T.isOSDarwin() && T.getArch() == Triple::aarch64) SupportsCompactUnwindWithoutEHFrame = true; - if (T.isWatchOS()) + if (T.isWatchABI()) OmitDwarfIfHaveCompactUnwind = true; PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel @@ -172,7 +172,12 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(Triple T) { MachO::S_NON_LAZY_SYMBOL_POINTERS, SectionKind::getMetadata()); - if (RelocM == Reloc::Static) { + ThreadLocalPointerSection + = Ctx->getMachOSection("__DATA", "__thread_ptr", + MachO::S_THREAD_LOCAL_VARIABLE_POINTERS, + SectionKind::getMetadata()); + + if (!PositionIndependent) { StaticCtorSection = Ctx->getMachOSection("__TEXT", "__constructor", 0, SectionKind::getData()); StaticDtorSection = Ctx->getMachOSection("__TEXT", "__destructor", 0, @@ -191,6 +196,7 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(Triple T) { SectionKind::getReadOnlyWithRel()); COFFDebugSymbolsSection = nullptr; + COFFDebugTypesSection = nullptr; if (useCompactUnwind(T)) { CompactUnwindSection = @@ -258,7 +264,7 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(Triple T) { SectionKind::getMetadata(), "debug_range"); DwarfMacinfoSection = Ctx->getMachOSection("__DWARF", "__debug_macinfo", MachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); + SectionKind::getMetadata(), "debug_macinfo"); DwarfDebugInlineSection = Ctx->getMachOSection("__DWARF", "__debug_inlined", MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); @@ -277,7 +283,7 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(Triple T) { TLSExtraDataSection = TLSTLVSection; } -void MCObjectFileInfo::initELFMCObjectFileInfo(Triple T) { +void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T) { switch (T.getArch()) { case Triple::mips: case Triple::mipsel: @@ -307,18 +313,21 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(Triple T) { // Fallthrough if not using EHABI case Triple::ppc: case Triple::x86: - PersonalityEncoding = (RelocM == Reloc::PIC_) - ? dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 - : dwarf::DW_EH_PE_absptr; - LSDAEncoding = (RelocM == Reloc::PIC_) - ? dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 - : dwarf::DW_EH_PE_absptr; - TTypeEncoding = (RelocM == Reloc::PIC_) - ? dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 - : dwarf::DW_EH_PE_absptr; + PersonalityEncoding = PositionIndependent + ? dwarf::DW_EH_PE_indirect | + dwarf::DW_EH_PE_pcrel | + dwarf::DW_EH_PE_sdata4 + : dwarf::DW_EH_PE_absptr; + LSDAEncoding = PositionIndependent + ? dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 + : dwarf::DW_EH_PE_absptr; + TTypeEncoding = PositionIndependent + ? dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | + dwarf::DW_EH_PE_sdata4 + : dwarf::DW_EH_PE_absptr; break; case Triple::x86_64: - if (RelocM == Reloc::PIC_) { + if (PositionIndependent) { PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | ((CMModel == CodeModel::Small || CMModel == CodeModel::Medium) ? dwarf::DW_EH_PE_sdata4 : dwarf::DW_EH_PE_sdata8); @@ -338,12 +347,24 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(Triple T) { ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_absptr; } break; + case Triple::hexagon: + PersonalityEncoding = dwarf::DW_EH_PE_absptr; + LSDAEncoding = dwarf::DW_EH_PE_absptr; + FDECFIEncoding = dwarf::DW_EH_PE_absptr; + TTypeEncoding = dwarf::DW_EH_PE_absptr; + if (PositionIndependent) { + PersonalityEncoding |= dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel; + LSDAEncoding |= dwarf::DW_EH_PE_pcrel; + FDECFIEncoding |= dwarf::DW_EH_PE_pcrel; + TTypeEncoding |= dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel; + } + break; case Triple::aarch64: case Triple::aarch64_be: // The small model guarantees static code/data size < 4GB, but not where it // will be in memory. Most of these could end up >2GB away so even a signed // pc-relative 32-bit address is insufficient, theoretically. - if (RelocM == Reloc::PIC_) { + if (PositionIndependent) { PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8; LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8; @@ -355,6 +376,11 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(Triple T) { TTypeEncoding = dwarf::DW_EH_PE_absptr; } break; + case Triple::lanai: + LSDAEncoding = dwarf::DW_EH_PE_absptr; + PersonalityEncoding = dwarf::DW_EH_PE_absptr; + TTypeEncoding = dwarf::DW_EH_PE_absptr; + break; case Triple::mips: case Triple::mipsel: case Triple::mips64: @@ -380,7 +406,7 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(Triple T) { break; case Triple::sparcel: case Triple::sparc: - if (RelocM == Reloc::PIC_) { + if (PositionIndependent) { LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; @@ -394,7 +420,7 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(Triple T) { break; case Triple::sparcv9: LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; - if (RelocM == Reloc::PIC_) { + if (PositionIndependent) { PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | @@ -407,7 +433,7 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(Triple T) { case Triple::systemz: // All currently-defined code models guarantee that 4-byte PC-relative // values will be in range. - if (RelocM == Reloc::PIC_) { + if (PositionIndependent) { PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; @@ -468,6 +494,10 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(Triple T) { Ctx->getELFSection(".rodata.cst16", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_MERGE, 16, ""); + MergeableConst32Section = + Ctx->getELFSection(".rodata.cst32", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | ELF::SHF_MERGE, 32, ""); + StaticCtorSection = Ctx->getELFSection(".ctors", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_WRITE); @@ -484,6 +514,7 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(Triple T) { ELF::SHF_ALLOC); COFFDebugSymbolsSection = nullptr; + COFFDebugTypesSection = nullptr; // Debug Info Sections. DwarfAbbrevSection = Ctx->getELFSection(".debug_abbrev", ELF::SHT_PROGBITS, 0, @@ -508,8 +539,8 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(Triple T) { Ctx->getELFSection(".debug_aranges", ELF::SHT_PROGBITS, 0); DwarfRangesSection = Ctx->getELFSection(".debug_ranges", ELF::SHT_PROGBITS, 0, "debug_range"); - DwarfMacinfoSection = - Ctx->getELFSection(".debug_macinfo", ELF::SHT_PROGBITS, 0); + DwarfMacinfoSection = Ctx->getELFSection(".debug_macinfo", ELF::SHT_PROGBITS, + 0, "debug_macinfo"); // DWARF5 Experimental Debug Info @@ -558,13 +589,16 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(Triple T) { Ctx->getELFSection(".eh_frame", EHSectionType, EHSectionFlags); } -void MCObjectFileInfo::initCOFFMCObjectFileInfo(Triple T) { +void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) { EHFrameSection = Ctx->getCOFFSection( ".eh_frame", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE, SectionKind::getData()); - bool IsWoA = T.getArch() == Triple::arm || T.getArch() == Triple::thumb; + // Set the `IMAGE_SCN_MEM_16BIT` flag when compiling for thumb mode. This is + // used to indicate to the linker that the text segment contains thumb instructions + // and to set the ISA selection bit for calls accordingly. + const bool IsThumb = T.getArch() == Triple::thumb; CommDirectiveSupportsAlignment = true; @@ -575,7 +609,7 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(Triple T) { SectionKind::getBSS()); TextSection = Ctx->getCOFFSection( ".text", - (IsWoA ? COFF::IMAGE_SCN_MEM_16BIT : (COFF::SectionCharacteristics)0) | + (IsThumb ? COFF::IMAGE_SCN_MEM_16BIT : (COFF::SectionCharacteristics)0) | COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE | COFF::IMAGE_SCN_MEM_READ, SectionKind::getText()); @@ -623,9 +657,14 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(Triple T) { // Debug info. COFFDebugSymbolsSection = - Ctx->getCOFFSection(".debug$S", COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, + Ctx->getCOFFSection(".debug$S", (COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ), + SectionKind::getMetadata()); + COFFDebugTypesSection = + Ctx->getCOFFSection(".debug$T", (COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ), SectionKind::getMetadata()); DwarfAbbrevSection = Ctx->getCOFFSection( @@ -693,7 +732,7 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(Triple T) { ".debug_macinfo", COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); + SectionKind::getMetadata(), "debug_macinfo"); DwarfInfoDWOSection = Ctx->getCOFFSection( ".debug_info.dwo", COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | @@ -791,11 +830,10 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(Triple T) { SectionKind::getReadOnly()); } -void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, - Reloc::Model relocm, +void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC, CodeModel::Model cm, MCContext &ctx) { - RelocM = relocm; + PositionIndependent = PIC; CMModel = cm; Ctx = &ctx; @@ -842,12 +880,6 @@ void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, } } -void MCObjectFileInfo::InitMCObjectFileInfo(StringRef TT, Reloc::Model RM, - CodeModel::Model CM, - MCContext &ctx) { - InitMCObjectFileInfo(Triple(TT), RM, CM, ctx); -} - MCSection *MCObjectFileInfo::getDwarfTypesSection(uint64_t Hash) const { return Ctx->getELFSection(".debug_types", ELF::SHT_PROGBITS, ELF::SHF_GROUP, 0, utostr(Hash)); diff --git a/gnu/llvm/lib/MC/MCObjectStreamer.cpp b/gnu/llvm/lib/MC/MCObjectStreamer.cpp index 972610ac8d6..d2ac0f50261 100644 --- a/gnu/llvm/lib/MC/MCObjectStreamer.cpp +++ b/gnu/llvm/lib/MC/MCObjectStreamer.cpp @@ -20,6 +20,7 @@ #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; @@ -125,7 +126,8 @@ void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, MCDataFragment *DF = getOrCreateDataFragment(); flushPendingLabels(DF, DF->getContents().size()); - MCLineEntry::Make(this, getCurrentSection().first); + MCCVLineEntry::Make(this); + MCDwarfLineEntry::Make(this, getCurrentSection().first); // Avoid fixups when possible. int64_t AbsValue; @@ -232,7 +234,8 @@ void MCObjectStreamer::EmitInstruction(const MCInst &Inst, // Now that a machine instruction has been assembled into this section, make // a line entry for any .loc directive that has been seen. - MCLineEntry::Make(this, getCurrentSection().first); + MCCVLineEntry::Make(this); + MCDwarfLineEntry::Make(this, getCurrentSection().first); // If this instruction doesn't need relaxation, just emit it as data. MCAssembler &Assembler = getAssembler(); @@ -249,9 +252,9 @@ void MCObjectStreamer::EmitInstruction(const MCInst &Inst, if (Assembler.getRelaxAll() || (Assembler.isBundlingEnabled() && Sec->isBundleLocked())) { MCInst Relaxed; - getAssembler().getBackend().relaxInstruction(Inst, Relaxed); + getAssembler().getBackend().relaxInstruction(Inst, STI, Relaxed); while (getAssembler().getBackend().mayNeedRelaxation(Relaxed)) - getAssembler().getBackend().relaxInstruction(Relaxed, Relaxed); + getAssembler().getBackend().relaxInstruction(Relaxed, STI, Relaxed); EmitInstToData(Relaxed, STI); return; } @@ -301,7 +304,7 @@ void MCObjectStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, StringRef FileName) { // In case we see two .loc directives in a row, make sure the // first one gets a line entry. - MCLineEntry::Make(this, getCurrentSection().first); + MCDwarfLineEntry::Make(this, getCurrentSection().first); this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, Isa, Discriminator, FileName); @@ -362,8 +365,56 @@ void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, insert(new MCDwarfCallFrameFragment(*AddrDelta)); } +void MCObjectStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, + unsigned Line, unsigned Column, + bool PrologueEnd, bool IsStmt, + StringRef FileName) { + // In case we see two .cv_loc directives in a row, make sure the + // first one gets a line entry. + MCCVLineEntry::Make(this); + + this->MCStreamer::EmitCVLocDirective(FunctionId, FileNo, Line, Column, + PrologueEnd, IsStmt, FileName); +} + +void MCObjectStreamer::EmitCVLinetableDirective(unsigned FunctionId, + const MCSymbol *Begin, + const MCSymbol *End) { + getContext().getCVContext().emitLineTableForFunction(*this, FunctionId, Begin, + End); + this->MCStreamer::EmitCVLinetableDirective(FunctionId, Begin, End); +} + +void MCObjectStreamer::EmitCVInlineLinetableDirective( + unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, + const MCSymbol *FnStartSym, const MCSymbol *FnEndSym, + ArrayRef<unsigned> SecondaryFunctionIds) { + getContext().getCVContext().emitInlineLineTableForFunction( + *this, PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, + FnEndSym, SecondaryFunctionIds); + this->MCStreamer::EmitCVInlineLinetableDirective( + PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym, + SecondaryFunctionIds); +} + +void MCObjectStreamer::EmitCVDefRangeDirective( + ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, + StringRef FixedSizePortion) { + getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion); + this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion); +} + +void MCObjectStreamer::EmitCVStringTableDirective() { + getContext().getCVContext().emitStringTable(*this); +} +void MCObjectStreamer::EmitCVFileChecksumsDirective() { + getContext().getCVContext().emitFileChecksums(*this); +} + + void MCObjectStreamer::EmitBytes(StringRef Data) { - MCLineEntry::Make(this, getCurrentSection().first); + MCCVLineEntry::Make(this); + MCDwarfLineEntry::Make(this, getCurrentSection().first); MCDataFragment *DF = getOrCreateDataFragment(); flushPendingLabels(DF, DF->getContents().size()); DF->getContents().append(Data.begin(), Data.end()); @@ -420,13 +471,18 @@ bool MCObjectStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name, if (!Offset.evaluateAsAbsolute(OffsetValue)) llvm_unreachable("Offset is not absolute"); + if (OffsetValue < 0) + llvm_unreachable("Offset is negative"); + MCDataFragment *DF = getOrCreateDataFragment(); flushPendingLabels(DF, DF->getContents().size()); - MCFixupKind Kind; - if (!Assembler->getBackend().getFixupKind(Name, Kind)) + Optional<MCFixupKind> MaybeKind = Assembler->getBackend().getFixupKind(Name); + if (!MaybeKind.hasValue()) return true; + MCFixupKind Kind = *MaybeKind; + if (Expr == nullptr) Expr = MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext()); @@ -434,11 +490,48 @@ bool MCObjectStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name, return false; } -void MCObjectStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue) { +void MCObjectStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) { const MCSection *Sec = getCurrentSection().first; + (void)Sec; assert(Sec && "need a section"); - unsigned ItemSize = Sec->isVirtualSection() ? 0 : 1; - insert(new MCFillFragment(FillValue, ItemSize, NumBytes)); + insert(new MCFillFragment(FillValue, NumBytes)); +} + +void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue, + SMLoc Loc) { + MCDataFragment *DF = getOrCreateDataFragment(); + flushPendingLabels(DF, DF->getContents().size()); + + int64_t IntNumBytes; + if (!NumBytes.evaluateAsAbsolute(IntNumBytes, getAssembler())) { + getContext().reportError(Loc, "expected absolute expression"); + return; + } + + if (IntNumBytes <= 0) { + getContext().reportError(Loc, "invalid number of bytes"); + return; + } + + emitFill(IntNumBytes, FillValue); +} + +void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size, + int64_t Expr, SMLoc Loc) { + int64_t IntNumValues; + if (!NumValues.evaluateAsAbsolute(IntNumValues, getAssembler())) { + getContext().reportError(Loc, "expected absolute expression"); + return; + } + + if (IntNumValues < 0) { + getContext().getSourceManager()->PrintMessage( + Loc, SourceMgr::DK_Warning, + "'.fill' directive with negative repeat count has no effect"); + return; + } + + MCStreamer::emitFill(IntNumValues, Size, Expr); } void MCObjectStreamer::FinishImpl() { diff --git a/gnu/llvm/lib/MC/MCParser/AsmLexer.cpp b/gnu/llvm/lib/MC/MCParser/AsmLexer.cpp index 36c19202685..d56071aea4d 100644 --- a/gnu/llvm/lib/MC/MCParser/AsmLexer.cpp +++ b/gnu/llvm/lib/MC/MCParser/AsmLexer.cpp @@ -23,7 +23,8 @@ using namespace llvm; AsmLexer::AsmLexer(const MCAsmInfo &MAI) : MAI(MAI) { CurPtr = nullptr; - isAtStartOfLine = true; + IsAtStartOfLine = true; + IsAtStartOfStatement = true; AllowAtInIdentifier = !StringRef(MAI.getCommentString()).startswith("@"); } @@ -46,24 +47,13 @@ void AsmLexer::setBuffer(StringRef Buf, const char *ptr) { AsmToken AsmLexer::ReturnError(const char *Loc, const std::string &Msg) { SetError(SMLoc::getFromPointer(Loc), Msg); - return AsmToken(AsmToken::Error, StringRef(Loc, 0)); + return AsmToken(AsmToken::Error, StringRef(Loc, CurPtr - Loc)); } int AsmLexer::getNextChar() { - char CurChar = *CurPtr++; - switch (CurChar) { - default: - return (unsigned char)CurChar; - case 0: - // A nul character in the stream is either the end of the current buffer or - // a random nul in the file. Disambiguate that here. - if (CurPtr - 1 != CurBuf.end()) - return 0; // Just whitespace. - - // Otherwise, return end of file. - --CurPtr; // Another call to lex will return EOF again. + if (CurPtr == CurBuf.end()) return EOF; - } + return (unsigned char)*CurPtr++; } /// LexFloatLiteral: [0-9]*[.][0-9]*([eE][+-]?[0-9]*)? @@ -168,40 +158,53 @@ AsmToken AsmLexer::LexIdentifier() { /// C-Style Comment: /* ... */ AsmToken AsmLexer::LexSlash() { switch (*CurPtr) { - case '*': break; // C style comment. - case '/': return ++CurPtr, LexLineComment(); - default: return AsmToken(AsmToken::Slash, StringRef(CurPtr-1, 1)); + case '*': + IsAtStartOfStatement = false; + break; // C style comment. + case '/': + ++CurPtr; + return LexLineComment(); + default: + IsAtStartOfStatement = false; + return AsmToken(AsmToken::Slash, StringRef(TokStart, 1)); } // C Style comment. ++CurPtr; // skip the star. - while (1) { - int CurChar = getNextChar(); - switch (CurChar) { - case EOF: - return ReturnError(TokStart, "unterminated comment"); + while (CurPtr != CurBuf.end()) { + switch (*CurPtr++) { case '*': // End of the comment? - if (CurPtr[0] != '/') break; - + if (*CurPtr != '/') + break; ++CurPtr; // End the */. - return LexToken(); + return AsmToken(AsmToken::Comment, + StringRef(TokStart, CurPtr - TokStart)); } } + return ReturnError(TokStart, "unterminated comment"); } /// LexLineComment: Comment: #[^\n]* /// : //[^\n]* AsmToken AsmLexer::LexLineComment() { - // FIXME: This is broken if we happen to a comment at the end of a file, which - // was .included, and which doesn't end with a newline. + // Mark This as an end of statement with a body of the + // comment. While it would be nicer to leave this two tokens, + // backwards compatability with TargetParsers makes keeping this in this form + // better. int CurChar = getNextChar(); while (CurChar != '\n' && CurChar != '\r' && CurChar != EOF) CurChar = getNextChar(); - if (CurChar == EOF) - return AsmToken(AsmToken::Eof, StringRef(TokStart, 0)); - return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 0)); + IsAtStartOfLine = true; + // Whis is a whole line comment. leave newline + if (IsAtStartOfStatement) + return AsmToken(AsmToken::EndOfStatement, + StringRef(TokStart, CurPtr - TokStart)); + IsAtStartOfStatement = true; + + return AsmToken(AsmToken::EndOfStatement, + StringRef(TokStart, CurPtr - 1 - TokStart)); } static void SkipIgnoredIntegerSuffix(const char *&CurPtr) { @@ -280,7 +283,7 @@ AsmToken AsmLexer::LexDigit() { return intToken(Result, Value); } - if (*CurPtr == 'b') { + if ((*CurPtr == 'b') || (*CurPtr == 'B')) { ++CurPtr; // See if we actually have "0b" as part of something like "jmp 0b\n" if (!isdigit(CurPtr[0])) { @@ -309,7 +312,7 @@ AsmToken AsmLexer::LexDigit() { return intToken(Result, Value); } - if (*CurPtr == 'x') { + if ((*CurPtr == 'x') || (*CurPtr == 'X')) { ++CurPtr; const char *NumStart = CurPtr; while (isxdigit(CurPtr[0])) @@ -419,8 +422,7 @@ StringRef AsmLexer::LexUntilEndOfStatement() { while (!isAtStartOfComment(CurPtr) && // Start of line comment. !isAtStatementSeparator(CurPtr) && // End of statement marker. - *CurPtr != '\n' && *CurPtr != '\r' && - (*CurPtr != 0 || CurPtr != CurBuf.end())) { + *CurPtr != '\n' && *CurPtr != '\r' && CurPtr != CurBuf.end()) { ++CurPtr; } return StringRef(TokStart, CurPtr-TokStart); @@ -429,8 +431,7 @@ StringRef AsmLexer::LexUntilEndOfStatement() { StringRef AsmLexer::LexUntilEndOfLine() { TokStart = CurPtr; - while (*CurPtr != '\n' && *CurPtr != '\r' && - (*CurPtr != 0 || CurPtr != CurBuf.end())) { + while (*CurPtr != '\n' && *CurPtr != '\r' && CurPtr != CurBuf.end()) { ++CurPtr; } return StringRef(TokStart, CurPtr-TokStart); @@ -440,7 +441,8 @@ size_t AsmLexer::peekTokens(MutableArrayRef<AsmToken> Buf, bool ShouldSkipSpace) { const char *SavedTokStart = TokStart; const char *SavedCurPtr = CurPtr; - bool SavedAtStartOfLine = isAtStartOfLine; + bool SavedAtStartOfLine = IsAtStartOfLine; + bool SavedAtStartOfStatement = IsAtStartOfStatement; bool SavedSkipSpace = SkipSpace; std::string SavedErr = getErr(); @@ -461,7 +463,8 @@ size_t AsmLexer::peekTokens(MutableArrayRef<AsmToken> Buf, SetError(SavedErrLoc, SavedErr); SkipSpace = SavedSkipSpace; - isAtStartOfLine = SavedAtStartOfLine; + IsAtStartOfLine = SavedAtStartOfLine; + IsAtStartOfStatement = SavedAtStartOfStatement; CurPtr = SavedCurPtr; TokStart = SavedTokStart; @@ -491,29 +494,45 @@ AsmToken AsmLexer::LexToken() { // This always consumes at least one character. int CurChar = getNextChar(); - if (isAtStartOfComment(TokStart)) { - // If this comment starts with a '#', then return the Hash token and let - // the assembler parser see if it can be parsed as a cpp line filename - // comment. We do this only if we are at the start of a line. - if (CurChar == '#' && isAtStartOfLine) - return AsmToken(AsmToken::Hash, StringRef(TokStart, 1)); - isAtStartOfLine = true; + if (CurChar == '#' && IsAtStartOfStatement) { + // If this starts with a '#', this may be a cpp + // hash directive and otherwise a line comment. + AsmToken TokenBuf[2]; + MutableArrayRef<AsmToken> Buf(TokenBuf, 2); + size_t num = peekTokens(Buf, true); + // There cannot be a space preceeding this + if (IsAtStartOfLine && num == 2 && TokenBuf[0].is(AsmToken::Integer) && + TokenBuf[1].is(AsmToken::String)) { + CurPtr = TokStart; // reset curPtr; + StringRef s = LexUntilEndOfLine(); + UnLex(TokenBuf[1]); + UnLex(TokenBuf[0]); + return AsmToken(AsmToken::HashDirective, s); + } return LexLineComment(); } + + if (isAtStartOfComment(TokStart)) + return LexLineComment(); + if (isAtStatementSeparator(TokStart)) { CurPtr += strlen(MAI.getSeparatorString()) - 1; + IsAtStartOfLine = true; + IsAtStartOfStatement = true; return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, strlen(MAI.getSeparatorString()))); } // If we're missing a newline at EOF, make sure we still get an // EndOfStatement token before the Eof token. - if (CurChar == EOF && !isAtStartOfLine) { - isAtStartOfLine = true; + if (CurChar == EOF && !IsAtStartOfStatement) { + IsAtStartOfLine = true; + IsAtStartOfStatement = true; return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1)); } - - isAtStartOfLine = false; + IsAtStartOfLine = false; + bool OldIsAtStartOfStatement = IsAtStartOfStatement; + IsAtStartOfStatement = false; switch (CurChar) { default: // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]* @@ -522,24 +541,24 @@ AsmToken AsmLexer::LexToken() { // Unknown character, emit an error. return ReturnError(TokStart, "invalid character in input"); - case EOF: return AsmToken(AsmToken::Eof, StringRef(TokStart, 0)); + case EOF: + IsAtStartOfLine = true; + IsAtStartOfStatement = true; + return AsmToken(AsmToken::Eof, StringRef(TokStart, 0)); case 0: case ' ': case '\t': - if (SkipSpace) { - // Ignore whitespace. - return LexToken(); - } else { - int len = 1; - while (*CurPtr==' ' || *CurPtr=='\t') { - CurPtr++; - len++; - } - return AsmToken(AsmToken::Space, StringRef(TokStart, len)); - } - case '\n': // FALL THROUGH. + IsAtStartOfStatement = OldIsAtStartOfStatement; + while (*CurPtr == ' ' || *CurPtr == '\t') + CurPtr++; + if (SkipSpace) + return LexToken(); // Ignore whitespace. + else + return AsmToken(AsmToken::Space, StringRef(TokStart, CurPtr - TokStart)); + case '\n': case '\r': - isAtStartOfLine = true; + IsAtStartOfLine = true; + IsAtStartOfStatement = true; return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1)); case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1)); case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1)); @@ -557,24 +576,34 @@ AsmToken AsmLexer::LexToken() { case '@': return AsmToken(AsmToken::At, StringRef(TokStart, 1)); case '\\': return AsmToken(AsmToken::BackSlash, StringRef(TokStart, 1)); case '=': - if (*CurPtr == '=') - return ++CurPtr, AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2)); + if (*CurPtr == '=') { + ++CurPtr; + return AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2)); + } return AsmToken(AsmToken::Equal, StringRef(TokStart, 1)); case '|': - if (*CurPtr == '|') - return ++CurPtr, AsmToken(AsmToken::PipePipe, StringRef(TokStart, 2)); + if (*CurPtr == '|') { + ++CurPtr; + return AsmToken(AsmToken::PipePipe, StringRef(TokStart, 2)); + } return AsmToken(AsmToken::Pipe, StringRef(TokStart, 1)); case '^': return AsmToken(AsmToken::Caret, StringRef(TokStart, 1)); case '&': - if (*CurPtr == '&') - return ++CurPtr, AsmToken(AsmToken::AmpAmp, StringRef(TokStart, 2)); + if (*CurPtr == '&') { + ++CurPtr; + return AsmToken(AsmToken::AmpAmp, StringRef(TokStart, 2)); + } return AsmToken(AsmToken::Amp, StringRef(TokStart, 1)); case '!': - if (*CurPtr == '=') - return ++CurPtr, AsmToken(AsmToken::ExclaimEqual, StringRef(TokStart, 2)); + if (*CurPtr == '=') { + ++CurPtr; + return AsmToken(AsmToken::ExclaimEqual, StringRef(TokStart, 2)); + } return AsmToken(AsmToken::Exclaim, StringRef(TokStart, 1)); case '%': return AsmToken(AsmToken::Percent, StringRef(TokStart, 1)); - case '/': return LexSlash(); + case '/': + IsAtStartOfStatement = OldIsAtStartOfStatement; + return LexSlash(); case '#': return AsmToken(AsmToken::Hash, StringRef(TokStart, 1)); case '\'': return LexSingleQuote(); case '"': return LexQuote(); @@ -583,21 +612,28 @@ AsmToken AsmLexer::LexToken() { return LexDigit(); case '<': switch (*CurPtr) { - case '<': return ++CurPtr, AsmToken(AsmToken::LessLess, - StringRef(TokStart, 2)); - case '=': return ++CurPtr, AsmToken(AsmToken::LessEqual, - StringRef(TokStart, 2)); - case '>': return ++CurPtr, AsmToken(AsmToken::LessGreater, - StringRef(TokStart, 2)); - default: return AsmToken(AsmToken::Less, StringRef(TokStart, 1)); + case '<': + ++CurPtr; + return AsmToken(AsmToken::LessLess, StringRef(TokStart, 2)); + case '=': + ++CurPtr; + return AsmToken(AsmToken::LessEqual, StringRef(TokStart, 2)); + case '>': + ++CurPtr; + return AsmToken(AsmToken::LessGreater, StringRef(TokStart, 2)); + default: + return AsmToken(AsmToken::Less, StringRef(TokStart, 1)); } case '>': switch (*CurPtr) { - case '>': return ++CurPtr, AsmToken(AsmToken::GreaterGreater, - StringRef(TokStart, 2)); - case '=': return ++CurPtr, AsmToken(AsmToken::GreaterEqual, - StringRef(TokStart, 2)); - default: return AsmToken(AsmToken::Greater, StringRef(TokStart, 1)); + case '>': + ++CurPtr; + return AsmToken(AsmToken::GreaterGreater, StringRef(TokStart, 2)); + case '=': + ++CurPtr; + return AsmToken(AsmToken::GreaterEqual, StringRef(TokStart, 2)); + default: + return AsmToken(AsmToken::Greater, StringRef(TokStart, 1)); } // TODO: Quoted identifiers (objc methods etc) diff --git a/gnu/llvm/lib/MC/MCParser/AsmParser.cpp b/gnu/llvm/lib/MC/MCParser/AsmParser.cpp index 646cbb43cae..1548aee8422 100644 --- a/gnu/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/gnu/llvm/lib/MC/MCParser/AsmParser.cpp @@ -28,13 +28,12 @@ #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCParser/MCAsmParserUtils.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/MC/MCParser/MCTargetAsmParser.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCTargetAsmParser.h" #include "llvm/MC/MCValue.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" @@ -42,7 +41,6 @@ #include "llvm/Support/raw_ostream.h" #include <cctype> #include <deque> -#include <set> #include <string> #include <vector> using namespace llvm; @@ -156,10 +154,17 @@ private: unsigned HadError : 1; /// The values from the last parsed cpp hash file line comment if any. - StringRef CppHashFilename; - int64_t CppHashLineNumber; - SMLoc CppHashLoc; - unsigned CppHashBuf; + struct CppHashInfoTy { + StringRef Filename; + int64_t LineNumber = 0; + SMLoc Loc; + unsigned Buf = 0; + }; + CppHashInfoTy CppHashInfo; + + /// \brief List of forward directional labels for diagnosis at the end. + SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels; + /// When generating dwarf for assembly source files we need to calculate the /// logical line number based on the last parsed cpp hash file line comment /// and current line. Since this is slow and messes up the SourceMgr's @@ -245,13 +250,36 @@ public: void eatToEndOfStatement() override; void checkForValidSection() override; + + bool getTokenLoc(SMLoc &Loc) { + Loc = getTok().getLoc(); + return false; + } + + /// parseToken - If current token has the specified kind, eat it and + /// return success. Otherwise, emit the specified error and return failure. + bool parseToken(AsmToken::TokenKind T, const Twine &ErrMsg) { + if (getTok().getKind() != T) + return TokError(ErrMsg); + Lex(); + return false; + } + + bool parseIntToken(int64_t &V, const Twine &ErrMsg) { + if (getTok().getKind() != AsmToken::Integer) + return TokError(ErrMsg); + V = getTok().getIntVal(); + Lex(); + return false; + } + /// } private: bool parseStatement(ParseStatementInfo &Info, MCAsmParserSemaCallback *SI); - void eatToEndOfLine(); + bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites); bool parseCppHashLineFilenameComment(SMLoc L); void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body, @@ -303,6 +331,18 @@ private: } static void DiagHandler(const SMDiagnostic &Diag, void *Context); + bool check(bool P, SMLoc Loc, const Twine &Msg) { + if (P) + return Error(Loc, Msg); + return false; + } + + bool check(bool P, const Twine &Msg) { + if (P) + return TokError(Msg); + return false; + } + /// \brief Enter the specified file. This returns true on failure. bool enterIncludeFile(const std::string &Filename); @@ -349,14 +389,16 @@ private: DK_BALIGNL, DK_P2ALIGN, DK_P2ALIGNW, DK_P2ALIGNL, DK_ORG, DK_FILL, DK_ENDR, DK_BUNDLE_ALIGN_MODE, DK_BUNDLE_LOCK, DK_BUNDLE_UNLOCK, DK_ZERO, DK_EXTERN, DK_GLOBL, DK_GLOBAL, - DK_LAZY_REFERENCE, DK_NO_DEAD_STRIP, DK_SYMBOL_RESOLVER, DK_PRIVATE_EXTERN, - DK_REFERENCE, DK_WEAK_DEFINITION, DK_WEAK_REFERENCE, + DK_LAZY_REFERENCE, DK_NO_DEAD_STRIP, DK_SYMBOL_RESOLVER, + DK_PRIVATE_EXTERN, DK_REFERENCE, DK_WEAK_DEFINITION, DK_WEAK_REFERENCE, DK_WEAK_DEF_CAN_BE_HIDDEN, DK_COMM, DK_COMMON, DK_LCOMM, DK_ABORT, DK_INCLUDE, DK_INCBIN, DK_CODE16, DK_CODE16GCC, DK_REPT, DK_IRP, DK_IRPC, DK_IF, DK_IFEQ, DK_IFGE, DK_IFGT, DK_IFLE, DK_IFLT, DK_IFNE, DK_IFB, DK_IFNB, DK_IFC, DK_IFEQS, DK_IFNC, DK_IFNES, DK_IFDEF, DK_IFNDEF, DK_IFNOTDEF, DK_ELSEIF, DK_ELSE, DK_ENDIF, DK_SPACE, DK_SKIP, DK_FILE, DK_LINE, DK_LOC, DK_STABS, + DK_CV_FILE, DK_CV_LOC, DK_CV_LINETABLE, DK_CV_INLINE_LINETABLE, + DK_CV_DEF_RANGE, DK_CV_STRINGTABLE, DK_CV_FILECHECKSUMS, DK_CFI_SECTIONS, DK_CFI_STARTPROC, DK_CFI_ENDPROC, DK_CFI_DEF_CFA, DK_CFI_DEF_CFA_OFFSET, DK_CFI_ADJUST_CFA_OFFSET, DK_CFI_DEF_CFA_REGISTER, DK_CFI_OFFSET, DK_CFI_REL_OFFSET, DK_CFI_PERSONALITY, DK_CFI_LSDA, @@ -394,6 +436,16 @@ private: bool parseDirectiveLoc(); bool parseDirectiveStabs(); + // ".cv_file", ".cv_loc", ".cv_linetable", "cv_inline_linetable", + // ".cv_def_range" + bool parseDirectiveCVFile(); + bool parseDirectiveCVLoc(); + bool parseDirectiveCVLinetable(); + bool parseDirectiveCVInlineLinetable(); + bool parseDirectiveCVDefRange(); + bool parseDirectiveCVStringTable(); + bool parseDirectiveCVFileChecksums(); + // .cfi directives bool parseDirectiveCFIRegister(SMLoc DirectiveLoc); bool parseDirectiveCFIWindowSave(); @@ -506,7 +558,7 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, const MCAsmInfo &MAI) : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM), PlatformParser(nullptr), CurBuffer(SM.getMainFileID()), - MacrosEnabledFlag(true), HadError(false), CppHashLineNumber(0), + MacrosEnabledFlag(true), HadError(false), CppHashInfo(), AssemblerDialect(~0U), IsDarwin(false), ParsingInlineAsm(false) { // Save the old handler. SavedDiagHandler = SrcMgr.getDiagHandler(); @@ -606,20 +658,36 @@ void AsmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) { } const AsmToken &AsmParser::Lex() { + if (Lexer.getTok().is(AsmToken::Error)) + Error(Lexer.getErrLoc(), Lexer.getErr()); + + // if it's a end of statement with a comment in it + if (getTok().is(AsmToken::EndOfStatement)) { + // if this is a line comment output it. + if (getTok().getString().front() != '\n' && + getTok().getString().front() != '\r' && MAI.preserveAsmComments()) + Out.addExplicitComment(Twine(getTok().getString())); + } + const AsmToken *tok = &Lexer.Lex(); + // Parse comments here to be deferred until end of next statement. + while (tok->is(AsmToken::Comment)) { + if (MAI.preserveAsmComments()) + Out.addExplicitComment(Twine(tok->getString())); + tok = &Lexer.Lex(); + } + if (tok->is(AsmToken::Eof)) { // If this is the end of an included file, pop the parent file off the // include stack. SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); if (ParentIncludeLoc != SMLoc()) { jumpToLoc(ParentIncludeLoc); - tok = &Lexer.Lex(); + return Lex(); } } - if (tok->is(AsmToken::Error)) - Error(Lexer.getErrLoc(), Lexer.getErr()); return *tok; } @@ -657,6 +725,12 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { if (!parseStatement(Info, nullptr)) continue; + // If we've failed, but on a Error Token, but did not consume it in + // favor of a better message, emit it now. + if (Lexer.getTok().is(AsmToken::Error)) { + Lex(); + } + // We had an error, validate that one was emitted and recover by skipping to // the next line. assert(HadError && "Parse statement returned an error, but none emitted!"); @@ -683,18 +757,32 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // Targets that don't do subsections via symbols may not want this, though, // so conservatively exclude them. Only do this if we're finalizing, though, // as otherwise we won't necessarilly have seen everything yet. - if (!NoFinalize && MAI.hasSubsectionsViaSymbols()) { - for (const auto &TableEntry : getContext().getSymbols()) { - MCSymbol *Sym = TableEntry.getValue(); - // Variable symbols may not be marked as defined, so check those - // explicitly. If we know it's a variable, we have a definition for - // the purposes of this check. - if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined()) - // FIXME: We would really like to refer back to where the symbol was - // first referenced for a source location. We need to add something - // to track that. Currently, we just point to the end of the file. - return Error(getLexer().getLoc(), "assembler local symbol '" + - Sym->getName() + "' not defined"); + if (!NoFinalize) { + if (MAI.hasSubsectionsViaSymbols()) { + for (const auto &TableEntry : getContext().getSymbols()) { + MCSymbol *Sym = TableEntry.getValue(); + // Variable symbols may not be marked as defined, so check those + // explicitly. If we know it's a variable, we have a definition for + // the purposes of this check. + if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined()) + // FIXME: We would really like to refer back to where the symbol was + // first referenced for a source location. We need to add something + // to track that. Currently, we just point to the end of the file. + HadError |= + Error(getTok().getLoc(), "assembler local symbol '" + + Sym->getName() + "' not defined"); + } + } + + // Temporary symbols like the ones for directional jumps don't go in the + // symbol table. They also need to be diagnosed in all (final) cases. + for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) { + if (std::get<2>(LocSym)->isUndefined()) { + // Reset the state of any "# line file" directives we've seen to the + // context as it was at the diagnostic site. + CppHashInfo = std::get<1>(LocSym); + HadError |= Error(std::get<0>(LocSym), "directional label undefined"); + } } } @@ -716,18 +804,18 @@ void AsmParser::checkForValidSection() { /// \brief Throw away the rest of the line for testing purposes. void AsmParser::eatToEndOfStatement() { while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof)) - Lex(); + Lexer.Lex(); // Eat EOL. if (Lexer.is(AsmToken::EndOfStatement)) - Lex(); + Lexer.Lex(); } StringRef AsmParser::parseStringToEndOfStatement() { const char *Start = getTok().getLoc().getPointer(); while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof)) - Lex(); + Lexer.Lex(); const char *End = getTok().getLoc().getPointer(); return StringRef(Start, End - Start); @@ -738,7 +826,7 @@ StringRef AsmParser::parseStringToComma() { while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Comma) && Lexer.isNot(AsmToken::Eof)) - Lex(); + Lexer.Lex(); const char *End = getTok().getLoc().getPointer(); return StringRef(Start, End - Start); @@ -767,10 +855,9 @@ bool AsmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) { bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) { if (parseExpression(Res)) return true; - if (Lexer.isNot(AsmToken::RBrac)) - return TokError("expected ']' in brackets expression"); - EndLoc = Lexer.getTok().getEndLoc(); - Lex(); + EndLoc = getTok().getEndLoc(); + if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression")) + return true; return false; } @@ -820,7 +907,7 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { if (!MAI.useParensForSymbolVariant()) { if (FirstTokenKind == AsmToken::String) { if (Lexer.is(AsmToken::At)) { - Lexer.Lex(); // eat @ + Lex(); // eat @ SMLoc AtLoc = getLexer().getLoc(); StringRef VName; if (parseIdentifier(VName)) @@ -832,14 +919,13 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { Split = Identifier.split('@'); } } else if (Lexer.is(AsmToken::LParen)) { - Lexer.Lex(); // eat ( + Lex(); // eat '('. StringRef VName; parseIdentifier(VName); - if (Lexer.isNot(AsmToken::RParen)) { - return Error(Lexer.getTok().getLoc(), - "unexpected token in variant, expected ')'"); - } - Lexer.Lex(); // eat ) + // eat ')'. + if (parseToken(AsmToken::RParen, + "unexpected token in variant, expected ')'")) + return true; Split = std::make_pair(Identifier, VName); } @@ -904,7 +990,8 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b"); Res = MCSymbolRefExpr::create(Sym, Variant, getContext()); if (IDVal == "b" && Sym->isUndefined()) - return Error(Loc, "invalid reference to undefined symbol"); + return Error(Loc, "directional label undefined"); + DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym)); EndLoc = Lexer.getTok().getEndLoc(); Lex(); // Eat identifier. } @@ -1082,10 +1169,10 @@ bool AsmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res, // We don't Lex() the last RParen. // This is the same behavior as parseParenExpression(). if (ParenDepth - 1 > 0) { - if (Lexer.isNot(AsmToken::RParen)) - return TokError("expected ')' in parentheses expression"); - EndLoc = Lexer.getTok().getEndLoc(); - Lex(); + EndLoc = getTok().getEndLoc(); + if (parseToken(AsmToken::RParen, + "expected ')' in parentheses expression")) + return true; } } return false; @@ -1303,21 +1390,24 @@ bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, /// ::= Label* Identifier OperandList* EndOfStatement bool AsmParser::parseStatement(ParseStatementInfo &Info, MCAsmParserSemaCallback *SI) { + // Eat initial spaces and comments + while (Lexer.is(AsmToken::Space)) + Lex(); if (Lexer.is(AsmToken::EndOfStatement)) { - Out.AddBlankLine(); + // if this is a line comment we can drop it safely + if (getTok().getString().front() == '\r' || + getTok().getString().front() == '\n') + Out.AddBlankLine(); Lex(); return false; } - - // Statements always start with an identifier or are a full line comment. + // Statements always start with an identifier. AsmToken ID = getTok(); SMLoc IDLoc = ID.getLoc(); StringRef IDVal; int64_t LocalLabelVal = -1; - // A full line comment is a '#' as the first token. - if (Lexer.is(AsmToken::Hash)) + if (Lexer.is(AsmToken::HashDirective)) return parseCppHashLineFilenameComment(IDLoc); - // Allow an integer followed by a ':' as a directional local label. if (Lexer.is(AsmToken::Integer)) { LocalLabelVal = getTok().getIntVal(); @@ -1444,6 +1534,12 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, if (!Sym->isUndefined() || Sym->isVariable()) return Error(IDLoc, "invalid symbol redefinition"); + // Consume any end of statement token, if present, to avoid spurious + // AddBlankLine calls(). + if (getTok().is(AsmToken::EndOfStatement)) { + Lex(); + } + // Emit the label. if (!ParsingInlineAsm) Out.EmitLabel(Sym); @@ -1456,13 +1552,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, getTargetParser().onLabelParsed(Sym); - // Consume any end of statement token, if present, to avoid spurious - // AddBlankLine calls(). - if (Lexer.is(AsmToken::EndOfStatement)) { - Lex(); - if (Lexer.is(AsmToken::Eof)) - return false; - } + return false; } @@ -1608,7 +1698,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, return parseDirectiveIncbin(); case DK_CODE16: case DK_CODE16GCC: - return TokError(Twine(IDVal) + " not supported yet"); + return TokError(Twine(IDVal) + + " not currently supported for this target"); case DK_REPT: return parseDirectiveRept(IDLoc, IDVal); case DK_IRP: @@ -1638,6 +1729,20 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, return parseDirectiveLoc(); case DK_STABS: return parseDirectiveStabs(); + case DK_CV_FILE: + return parseDirectiveCVFile(); + case DK_CV_LOC: + return parseDirectiveCVLoc(); + case DK_CV_LINETABLE: + return parseDirectiveCVLinetable(); + case DK_CV_INLINE_LINETABLE: + return parseDirectiveCVInlineLinetable(); + case DK_CV_DEF_RANGE: + return parseDirectiveCVDefRange(); + case DK_CV_STRINGTABLE: + return parseDirectiveCVStringTable(); + case DK_CV_FILECHECKSUMS: + return parseDirectiveCVFileChecksums(); case DK_CFI_SECTIONS: return parseDirectiveCFISections(); case DK_CFI_STARTPROC: @@ -1755,24 +1860,26 @@ 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 (CppHashFilename.size()) { + if (CppHashInfo.Filename.size()) { unsigned FileNumber = getStreamer().EmitDwarfFileDirective( - 0, StringRef(), CppHashFilename); + 0, StringRef(), CppHashInfo.Filename); getContext().setGenDwarfFileNumber(FileNumber); // Since SrcMgr.FindLineNumber() is slow and messes up the SourceMgr's // cache with the different Loc from the call above we save the last // info we queried here with SrcMgr.FindLineNumber(). unsigned CppHashLocLineNo; - if (LastQueryIDLoc == CppHashLoc && LastQueryBuffer == CppHashBuf) + if (LastQueryIDLoc == CppHashInfo.Loc && + LastQueryBuffer == CppHashInfo.Buf) CppHashLocLineNo = LastQueryLine; else { - CppHashLocLineNo = SrcMgr.FindLineNumber(CppHashLoc, CppHashBuf); + CppHashLocLineNo = + SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf); LastQueryLine = CppHashLocLineNo; - LastQueryIDLoc = CppHashLoc; - LastQueryBuffer = CppHashBuf; + LastQueryIDLoc = CppHashInfo.Loc; + LastQueryBuffer = CppHashInfo.Buf; } - Line = CppHashLineNumber - 1 + (Line - CppHashLocLineNo); + Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo); } getStreamer().EmitDwarfLocDirective( @@ -1794,48 +1901,46 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, return false; } -/// eatToEndOfLine uses the Lexer to eat the characters to the end of the line -/// since they may not be able to be tokenized to get to the end of line token. -void AsmParser::eatToEndOfLine() { - if (!Lexer.is(AsmToken::EndOfStatement)) - Lexer.LexUntilEndOfLine(); - // Eat EOL. - Lex(); +// Parse and erase curly braces marking block start/end +bool +AsmParser::parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> &AsmStrRewrites) { + // Identify curly brace marking block start/end + if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly)) + return false; + + SMLoc StartLoc = Lexer.getLoc(); + Lex(); // Eat the brace + if (Lexer.is(AsmToken::EndOfStatement)) + Lex(); // Eat EndOfStatement following the brace + + // Erase the block start/end brace from the output asm string + AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() - + StartLoc.getPointer()); + return true; } /// parseCppHashLineFilenameComment as this: /// ::= # number "filename" -/// or just as a full line comment if it doesn't have a number and a string. bool AsmParser::parseCppHashLineFilenameComment(SMLoc L) { Lex(); // Eat the hash token. - - if (getLexer().isNot(AsmToken::Integer)) { - // Consume the line since in cases it is not a well-formed line directive, - // as if were simply a full line comment. - eatToEndOfLine(); - return false; - } - + // Lexer only ever emits HashDirective if it fully formed if it's + // done the checking already so this is an internal error. + assert(getTok().is(AsmToken::Integer) && + "Lexing Cpp line comment: Expected Integer"); int64_t LineNumber = getTok().getIntVal(); Lex(); - - if (getLexer().isNot(AsmToken::String)) { - eatToEndOfLine(); - return false; - } - + assert(getTok().is(AsmToken::String) && + "Lexing Cpp line comment: Expected String"); StringRef Filename = getTok().getString(); + Lex(); // Get rid of the enclosing quotes. Filename = Filename.substr(1, Filename.size() - 2); // Save the SMLoc, Filename and LineNumber for later use by diagnostics. - CppHashLoc = L; - CppHashFilename = Filename; - CppHashLineNumber = LineNumber; - CppHashBuf = CurBuffer; - - // Ignore any trailing characters, they're just comment. - eatToEndOfLine(); + CppHashInfo.Loc = L; + CppHashInfo.Filename = Filename; + CppHashInfo.LineNumber = LineNumber; + CppHashInfo.Buf = CurBuffer; return false; } @@ -1849,7 +1954,7 @@ void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { SMLoc DiagLoc = Diag.getLoc(); unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); unsigned CppHashBuf = - Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashLoc); + Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc); // Like SourceMgr::printMessage() we need to print the include stack if any // before printing the message. @@ -1863,7 +1968,7 @@ void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { // If we have not parsed a cpp hash line filename comment or the source // manager changed or buffer changed (like in a nested include) then just // print the normal diagnostic using its Filename and LineNo. - if (!Parser->CppHashLineNumber || &DiagSrcMgr != &Parser->SrcMgr || + if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr || DiagBuf != CppHashBuf) { if (Parser->SavedDiagHandler) Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext); @@ -1873,15 +1978,15 @@ void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { } // Use the CppHashFilename and calculate a line number based on the - // CppHashLoc and CppHashLineNumber relative to this Diag's SMLoc for - // the diagnostic. - const std::string &Filename = Parser->CppHashFilename; + // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc + // for the diagnostic. + const std::string &Filename = Parser->CppHashInfo.Filename; int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf); int CppHashLocLineNo = - Parser->SrcMgr.FindLineNumber(Parser->CppHashLoc, CppHashBuf); + Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf); int LineNo = - Parser->CppHashLineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo); + Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo); SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo, Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(), @@ -2041,7 +2146,6 @@ static bool isOperator(AsmToken::TokenKind kind) { case AsmToken::AmpAmp: case AsmToken::Exclaim: case AsmToken::ExclaimEqual: - case AsmToken::Percent: case AsmToken::Less: case AsmToken::LessEqual: case AsmToken::LessLess: @@ -2080,37 +2184,44 @@ bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) { } unsigned ParenLevel = 0; - unsigned AddTokens = 0; // Darwin doesn't use spaces to delmit arguments. AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin); + bool SpaceEaten; + for (;;) { + SpaceEaten = false; if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal)) return TokError("unexpected token in macro instantiation"); - if (ParenLevel == 0 && Lexer.is(AsmToken::Comma)) - break; + if (ParenLevel == 0) { + + if (Lexer.is(AsmToken::Comma)) + break; - if (Lexer.is(AsmToken::Space)) { - Lex(); // Eat spaces + if (Lexer.is(AsmToken::Space)) { + SpaceEaten = true; + Lexer.Lex(); // Eat spaces + } // Spaces can delimit parameters, but could also be part an expression. // If the token after a space is an operator, add the token and the next // one into this argument if (!IsDarwin) { if (isOperator(Lexer.getKind())) { - // Check to see whether the token is used as an operator, - // or part of an identifier - const char *NextChar = getTok().getEndLoc().getPointer(); - if (*NextChar == ' ') - AddTokens = 2; - } + MA.push_back(getTok()); + Lexer.Lex(); - if (!AddTokens && ParenLevel == 0) { - break; + // Whitespace after an operator can be ignored. + if (Lexer.is(AsmToken::Space)) + Lexer.Lex(); + + continue; } } + if (SpaceEaten) + break; } // handleMacroEntry relies on not advancing the lexer here @@ -2126,9 +2237,7 @@ bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) { // Append the token to the current argument list. MA.push_back(getTok()); - if (AddTokens) - AddTokens--; - Lex(); + Lexer.Lex(); } if (ParenLevel != 0) @@ -2162,7 +2271,7 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M, return true; } - if (!Lexer.is(AsmToken::Equal)) { + if (Lexer.isNot(AsmToken::Equal)) { TokError("expected '=' after formal parameter identifier"); eatToEndOfStatement(); return true; @@ -2190,7 +2299,7 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M, break; if (FAI >= NParameters) { - assert(M && "expected macro to be defined"); + assert(M && "expected macro to be defined"); Error(IDLoc, "parameter named '" + FA.Name + "' does not exist for macro '" + M->Name + "'"); @@ -2337,7 +2446,7 @@ bool AsmParser::parseIdentifier(StringRef &Res) { SMLoc PrefixLoc = getLexer().getLoc(); // Consume the prefix character, and check for a following identifier. - Lex(); + Lexer.Lex(); // Lexer's Lex guarantees consecutive token. if (Lexer.isNot(AsmToken::Identifier)) return true; @@ -2348,7 +2457,7 @@ bool AsmParser::parseIdentifier(StringRef &Res) { // Construct the joined identifier and consume the token. Res = StringRef(PrefixLoc.getPointer(), getTok().getIdentifier().size() + 1); - Lex(); + Lex(); // Parser Lex to maintain invariants. return false; } @@ -2369,12 +2478,10 @@ bool AsmParser::parseIdentifier(StringRef &Res) { bool AsmParser::parseDirectiveSet(StringRef IDVal, bool allow_redef) { StringRef Name; - if (parseIdentifier(Name)) - return TokError("expected identifier after '" + Twine(IDVal) + "'"); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '" + Twine(IDVal) + "'"); - Lex(); + if (check(parseIdentifier(Name), + "expected identifier after '" + Twine(IDVal) + "'") || + parseToken(AsmToken::Comma, "unexpected token in '" + Twine(IDVal) + "'")) + return true; return parseAssignment(Name, allow_redef, true); } @@ -2434,6 +2541,7 @@ bool AsmParser::parseEscapedString(std::string &Data) { } } + Lex(); return false; } @@ -2444,25 +2552,22 @@ bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) { checkForValidSection(); for (;;) { - if (getLexer().isNot(AsmToken::String)) - return TokError("expected string in '" + Twine(IDVal) + "' directive"); - std::string Data; - if (parseEscapedString(Data)) + if (check(getTok().isNot(AsmToken::String), + "expected string in '" + Twine(IDVal) + "' directive") || + parseEscapedString(Data)) return true; getStreamer().EmitBytes(Data); if (ZeroTerminated) getStreamer().EmitBytes(StringRef("\0", 1)); - Lex(); - if (getLexer().is(AsmToken::EndOfStatement)) break; - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '" + Twine(IDVal) + "' directive"); - Lex(); + if (parseToken(AsmToken::Comma, + "unexpected token in '" + Twine(IDVal) + "' directive")) + return true; } } @@ -2482,21 +2587,19 @@ bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) { // We can only deal with constant expressions at the moment. int64_t OffsetValue; - if (!Offset->evaluateAsAbsolute(OffsetValue)) - return Error(OffsetLoc, "expression is not a constant value"); - - if (Lexer.isNot(AsmToken::Comma)) - return TokError("expected comma"); - Lexer.Lex(); + if (check(!Offset->evaluateAsAbsolute(OffsetValue), OffsetLoc, + "expression is not a constant value") || + check(OffsetValue < 0, OffsetLoc, "expression is negative") || + parseToken(AsmToken::Comma, "expected comma") || + check(getTok().isNot(AsmToken::Identifier), "expected relocation name")) + return true; - if (Lexer.isNot(AsmToken::Identifier)) - return TokError("expected relocation name"); SMLoc NameLoc = Lexer.getTok().getLoc(); StringRef Name = Lexer.getTok().getIdentifier(); - Lexer.Lex(); + Lex(); if (Lexer.is(AsmToken::Comma)) { - Lexer.Lex(); + Lex(); SMLoc ExprLoc = Lexer.getLoc(); if (parseExpression(Expr)) return true; @@ -2506,12 +2609,11 @@ bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) { return Error(ExprLoc, "expression must be relocatable"); } - if (Lexer.isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in .reloc directive"); - - if (getStreamer().EmitRelocDirective(*Offset, Name, Expr, DirectiveLoc)) - return Error(NameLoc, "unknown relocation name"); - + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in .reloc directive") || + check(getStreamer().EmitRelocDirective(*Offset, Name, Expr, DirectiveLoc), + NameLoc, "unknown relocation name")) + return true; return false; } @@ -2541,9 +2643,8 @@ bool AsmParser::parseDirectiveValue(unsigned Size) { break; // FIXME: Improve diagnostic. - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); + if (parseToken(AsmToken::Comma, "unexpected token in directive")) + return true; } } @@ -2558,10 +2659,9 @@ bool AsmParser::parseDirectiveOctaValue() { checkForValidSection(); for (;;) { - if (Lexer.getKind() == AsmToken::Error) + if (getTok().is(AsmToken::Error)) return true; - if (Lexer.getKind() != AsmToken::Integer && - Lexer.getKind() != AsmToken::BigNum) + if (getTok().isNot(AsmToken::Integer) && getTok().isNot(AsmToken::BigNum)) return TokError("unknown token in expression"); SMLoc ExprLoc = getLexer().getLoc(); @@ -2591,9 +2691,8 @@ bool AsmParser::parseDirectiveOctaValue() { break; // FIXME: Improve diagnostic. - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); + if (parseToken(AsmToken::Comma, "unexpected token in directive")) + return true; } } @@ -2612,14 +2711,15 @@ bool AsmParser::parseDirectiveRealValue(const fltSemantics &Semantics) { // have to manually parse unary prefixes. bool IsNeg = false; if (getLexer().is(AsmToken::Minus)) { - Lex(); + Lexer.Lex(); IsNeg = true; } else if (getLexer().is(AsmToken::Plus)) - Lex(); + Lexer.Lex(); - if (getLexer().isNot(AsmToken::Integer) && - getLexer().isNot(AsmToken::Real) && - getLexer().isNot(AsmToken::Identifier)) + if (Lexer.is(AsmToken::Error)) + return TokError(Lexer.getErr()); + if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) && + Lexer.isNot(AsmToken::Identifier)) return TokError("unexpected token in directive"); // Convert to an APFloat. @@ -2646,12 +2746,11 @@ bool AsmParser::parseDirectiveRealValue(const fltSemantics &Semantics) { getStreamer().EmitIntValue(AsInt.getLimitedValue(), AsInt.getBitWidth() / 8); - if (getLexer().is(AsmToken::EndOfStatement)) + if (Lexer.is(AsmToken::EndOfStatement)) break; - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); + if (parseToken(AsmToken::Comma, "unexpected token in directive")) + return true; } } @@ -2664,8 +2763,9 @@ bool AsmParser::parseDirectiveRealValue(const fltSemantics &Semantics) { bool AsmParser::parseDirectiveZero() { checkForValidSection(); - int64_t NumBytes; - if (parseAbsoluteExpression(NumBytes)) + SMLoc NumBytesLoc = Lexer.getLoc(); + const MCExpr *NumBytes; + if (parseExpression(NumBytes)) return true; int64_t Val = 0; @@ -2675,12 +2775,10 @@ bool AsmParser::parseDirectiveZero() { return true; } - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.zero' directive"); - - Lex(); - - getStreamer().EmitFill(NumBytes, Val); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.zero' directive")) + return true; + getStreamer().emitFill(*NumBytes, Val, NumBytesLoc); return false; } @@ -2690,49 +2788,34 @@ bool AsmParser::parseDirectiveZero() { bool AsmParser::parseDirectiveFill() { checkForValidSection(); - SMLoc RepeatLoc = getLexer().getLoc(); - int64_t NumValues; - if (parseAbsoluteExpression(NumValues)) + SMLoc NumValuesLoc = Lexer.getLoc(); + const MCExpr *NumValues; + if (parseExpression(NumValues)) return true; - if (NumValues < 0) { - Warning(RepeatLoc, - "'.fill' directive with negative repeat count has no effect"); - NumValues = 0; - } - int64_t FillSize = 1; int64_t FillExpr = 0; SMLoc SizeLoc, ExprLoc; if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '.fill' directive"); - Lex(); - SizeLoc = getLexer().getLoc(); - if (parseAbsoluteExpression(FillSize)) + if (parseToken(AsmToken::Comma, "unexpected token in '.fill' directive") || + getTokenLoc(SizeLoc) || parseAbsoluteExpression(FillSize)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '.fill' directive"); - Lex(); - - ExprLoc = getLexer().getLoc(); - if (parseAbsoluteExpression(FillExpr)) + if (parseToken(AsmToken::Comma, + "unexpected token in '.fill' directive") || + getTokenLoc(ExprLoc) || parseAbsoluteExpression(FillExpr) || + parseToken(AsmToken::EndOfStatement, + "unexpected token in '.fill' directive")) return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.fill' directive"); - - Lex(); } } if (FillSize < 0) { Warning(SizeLoc, "'.fill' directive with negative size has no effect"); - NumValues = 0; + return false; } if (FillSize > 8) { Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8"); @@ -2742,15 +2825,7 @@ bool AsmParser::parseDirectiveFill() { if (!isUInt<32>(FillExpr) && FillSize > 4) Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits"); - if (NumValues > 0) { - int64_t NonZeroFillSize = FillSize > 4 ? 4 : FillSize; - FillExpr &= ~0ULL >> (64 - NonZeroFillSize * 8); - for (uint64_t i = 0, e = NumValues; i != e; ++i) { - getStreamer().EmitIntValue(FillExpr, NonZeroFillSize); - if (NonZeroFillSize < FillSize) - getStreamer().EmitIntValue(0, FillSize - NonZeroFillSize); - } - } + getStreamer().emitFill(*NumValues, FillSize, FillExpr, NumValuesLoc); return false; } @@ -2767,18 +2842,15 @@ bool AsmParser::parseDirectiveOrg() { // Parse optional fill expression. int64_t FillExpr = 0; if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '.org' directive"); - Lex(); - - if (parseAbsoluteExpression(FillExpr)) + if (parseToken(AsmToken::Comma, "unexpected token in '.org' directive") || + parseAbsoluteExpression(FillExpr)) return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.org' directive"); } - Lex(); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.org' directive")) + return true; + getStreamer().emitValueToOffset(Offset, FillExpr); return false; } @@ -2798,34 +2870,27 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) { int64_t FillExpr = 0; int64_t MaxBytesToFill = 0; if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); + if (parseToken(AsmToken::Comma, "unexpected token in directive")) + return true; // The fill expression can be omitted while specifying a maximum number of // alignment bytes, e.g: // .align 3,,4 - if (getLexer().isNot(AsmToken::Comma)) { + if (getTok().isNot(AsmToken::Comma)) { HasFillExpr = true; if (parseAbsoluteExpression(FillExpr)) return true; } - if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - - MaxBytesLoc = getLexer().getLoc(); - if (parseAbsoluteExpression(MaxBytesToFill)) + if (getTok().isNot(AsmToken::EndOfStatement)) { + if (parseToken(AsmToken::Comma, "unexpected token in directive") || + getTokenLoc(MaxBytesLoc) || parseAbsoluteExpression(MaxBytesToFill)) return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); } } - Lex(); + if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive")) + return true; if (!HasFillExpr) FillExpr = 0; @@ -2896,43 +2961,41 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) { return TokError("file number less than one"); } - if (getLexer().isNot(AsmToken::String)) - return TokError("unexpected token in '.file' directive"); + std::string Path = getTok().getString(); // Usually the directory and filename together, otherwise just the directory. // Allow the strings to have escaped octal character sequence. - std::string Path = getTok().getString(); - if (parseEscapedString(Path)) + if (check(getTok().isNot(AsmToken::String), + "unexpected token in '.file' directive") || + parseEscapedString(Path)) return true; - Lex(); StringRef Directory; StringRef Filename; std::string FilenameData; if (getLexer().is(AsmToken::String)) { - if (FileNumber == -1) - return TokError("explicit path specified, but no file number"); - if (parseEscapedString(FilenameData)) + if (check(FileNumber == -1, + "explicit path specified, but no file number") || + parseEscapedString(FilenameData)) return true; Filename = FilenameData; Directory = Path; - Lex(); } else { Filename = Path; } - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.file' directive"); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.file' directive")) + return true; if (FileNumber == -1) getStreamer().EmitFileDirective(Filename); else { + // If there is -g option as well as debug info from directive file, + // we turn off -g option, directly use the existing debug info instead. if (getContext().getGenDwarfForAssembly()) - Error(DirectiveLoc, - "input can't have .file dwarf directives when -g is " - "used to generate dwarf debug info for assembly code"); - - if (getStreamer().EmitDwarfFileDirective(FileNumber, Directory, Filename) == + getContext().setGenDwarfForAssembly(false); + else if (getStreamer().EmitDwarfFileDirective(FileNumber, Directory, Filename) == 0) Error(FileNumberLoc, "file number already allocated"); } @@ -2943,19 +3006,16 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) { /// parseDirectiveLine /// ::= .line [number] bool AsmParser::parseDirectiveLine() { + int64_t LineNumber; if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (getLexer().isNot(AsmToken::Integer)) - return TokError("unexpected token in '.line' directive"); - - int64_t LineNumber = getTok().getIntVal(); + if (parseIntToken(LineNumber, "unexpected token in '.line' directive")) + return true; (void)LineNumber; - Lex(); - // FIXME: Do something with the .line. } - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.line' directive"); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.line' directive")) + return true; return false; } @@ -2968,16 +3028,16 @@ bool AsmParser::parseDirectiveLine() { /// third number is a column position (zero if not specified). The remaining /// optional items are .loc sub-directives. bool AsmParser::parseDirectiveLoc() { - if (getLexer().isNot(AsmToken::Integer)) - return TokError("unexpected token in '.loc' directive"); - int64_t FileNumber = getTok().getIntVal(); - if (FileNumber < 1) - return TokError("file number less than one in '.loc' directive"); - if (!getContext().isValidDwarfFileNumber(FileNumber)) - return TokError("unassigned file number in '.loc' directive"); - Lex(); + int64_t FileNumber = 0, LineNumber = 0; + SMLoc Loc = getTok().getLoc(); + if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") || + check(FileNumber < 1, Loc, + "file number less than one in '.loc' directive") || + check(!getContext().isValidDwarfFileNumber(FileNumber), Loc, + "unassigned file number in '.loc' directive")) + return true; - int64_t LineNumber = 0; + // optional if (getLexer().is(AsmToken::Integer)) { LineNumber = getTok().getIntVal(); if (LineNumber < 0) @@ -3054,6 +3114,7 @@ bool AsmParser::parseDirectiveLoc() { break; } } + Lex(); getStreamer().EmitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags, Isa, Discriminator, StringRef()); @@ -3067,6 +3128,231 @@ bool AsmParser::parseDirectiveStabs() { return TokError("unsupported directive '.stabs'"); } +/// parseDirectiveCVFile +/// ::= .cv_file number filename +bool AsmParser::parseDirectiveCVFile() { + SMLoc FileNumberLoc = getTok().getLoc(); + int64_t FileNumber; + std::string Filename; + + if (parseIntToken(FileNumber, + "expected file number in '.cv_file' directive") || + check(FileNumber < 1, FileNumberLoc, "file number less than one") || + check(getTok().isNot(AsmToken::String), + "unexpected token in '.cv_file' directive") || + // Usually directory and filename are together, otherwise just + // directory. Allow the strings to have escaped octal character sequence. + parseEscapedString(Filename) || + parseToken(AsmToken::EndOfStatement, + "unexpected token in '.cv_file' directive") || + check(getStreamer().EmitCVFileDirective(FileNumber, Filename) == 0, + FileNumberLoc, "file number already allocated")) + return true; + + return false; +} + +/// parseDirectiveCVLoc +/// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end] +/// [is_stmt VALUE] +/// The first number is a file number, must have been previously assigned with +/// a .file directive, the second number is the line number and optionally the +/// third number is a column position (zero if not specified). The remaining +/// optional items are .loc sub-directives. +bool AsmParser::parseDirectiveCVLoc() { + SMLoc Loc; + int64_t FunctionId, FileNumber; + if (getTokenLoc(Loc) || + parseIntToken(FunctionId, "unexpected token in '.cv_loc' directive") || + check(FunctionId < 0, Loc, + "function id less than zero in '.cv_loc' directive") || + getTokenLoc(Loc) || + parseIntToken(FileNumber, "expected integer in '.cv_loc' directive") || + check(FileNumber < 1, Loc, + "file number less than one in '.cv_loc' directive") || + check(!getContext().isValidCVFileNumber(FileNumber), Loc, + "unassigned file number in '.cv_loc' directive")) + return true; + + int64_t LineNumber = 0; + if (getLexer().is(AsmToken::Integer)) { + LineNumber = getTok().getIntVal(); + if (LineNumber < 0) + return TokError("line number less than zero in '.cv_loc' directive"); + Lex(); + } + + int64_t ColumnPos = 0; + if (getLexer().is(AsmToken::Integer)) { + ColumnPos = getTok().getIntVal(); + if (ColumnPos < 0) + return TokError("column position less than zero in '.cv_loc' directive"); + Lex(); + } + + bool PrologueEnd = false; + uint64_t IsStmt = 0; + while (getLexer().isNot(AsmToken::EndOfStatement)) { + StringRef Name; + SMLoc Loc = getTok().getLoc(); + if (parseIdentifier(Name)) + return TokError("unexpected token in '.cv_loc' directive"); + + if (Name == "prologue_end") + PrologueEnd = true; + else if (Name == "is_stmt") { + Loc = getTok().getLoc(); + const MCExpr *Value; + if (parseExpression(Value)) + return true; + // The expression must be the constant 0 or 1. + IsStmt = ~0ULL; + if (const auto *MCE = dyn_cast<MCConstantExpr>(Value)) + IsStmt = MCE->getValue(); + + if (IsStmt > 1) + return Error(Loc, "is_stmt value not 0 or 1"); + } else { + return Error(Loc, "unknown sub-directive in '.cv_loc' directive"); + } + } + Lex(); + + getStreamer().EmitCVLocDirective(FunctionId, FileNumber, LineNumber, + ColumnPos, PrologueEnd, IsStmt, StringRef()); + return false; +} + +/// parseDirectiveCVLinetable +/// ::= .cv_linetable FunctionId, FnStart, FnEnd +bool AsmParser::parseDirectiveCVLinetable() { + int64_t FunctionId; + StringRef FnStartName, FnEndName; + SMLoc Loc = getTok().getLoc(); + if (parseIntToken(FunctionId, + "expected Integer in '.cv_linetable' directive") || + check(FunctionId < 0, Loc, + "function id less than zero in '.cv_linetable' directive") || + parseToken(AsmToken::Comma, + "unexpected token in '.cv_linetable' directive") || + getTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc, + "expected identifier in directive") || + parseToken(AsmToken::Comma, + "unexpected token in '.cv_linetable' directive") || + getTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc, + "expected identifier in directive")) + return true; + + MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName); + MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName); + + getStreamer().EmitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym); + return false; +} + +/// parseDirectiveCVInlineLinetable +/// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd +/// ("contains" SecondaryFunctionId+)? +bool AsmParser::parseDirectiveCVInlineLinetable() { + int64_t PrimaryFunctionId, SourceFileId, SourceLineNum; + StringRef FnStartName, FnEndName; + SMLoc Loc = getTok().getLoc(); + if (parseIntToken( + PrimaryFunctionId, + "expected PrimaryFunctionId in '.cv_inline_linetable' directive") || + check(PrimaryFunctionId < 0, Loc, + "function id less than zero in '.cv_inline_linetable' directive") || + getTokenLoc(Loc) || + parseIntToken( + SourceFileId, + "expected SourceField in '.cv_inline_linetable' directive") || + check(SourceFileId <= 0, Loc, + "File id less than zero in '.cv_inline_linetable' directive") || + getTokenLoc(Loc) || + parseIntToken( + SourceLineNum, + "expected SourceLineNum in '.cv_inline_linetable' directive") || + check(SourceLineNum < 0, Loc, + "Line number less than zero in '.cv_inline_linetable' directive") || + getTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc, + "expected identifier in directive") || + getTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc, + "expected identifier in directive")) + return true; + + SmallVector<unsigned, 8> SecondaryFunctionIds; + if (getLexer().is(AsmToken::Identifier)) { + if (getTok().getIdentifier() != "contains") + return TokError( + "unexpected identifier in '.cv_inline_linetable' directive"); + Lex(); + + while (getLexer().isNot(AsmToken::EndOfStatement)) { + int64_t SecondaryFunctionId = getTok().getIntVal(); + if (SecondaryFunctionId < 0) + return TokError( + "function id less than zero in '.cv_inline_linetable' directive"); + Lex(); + + SecondaryFunctionIds.push_back(SecondaryFunctionId); + } + } + + if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement")) + return true; + + MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName); + MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName); + getStreamer().EmitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId, + SourceLineNum, FnStartSym, + FnEndSym, SecondaryFunctionIds); + return false; +} + +/// parseDirectiveCVDefRange +/// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes* +bool AsmParser::parseDirectiveCVDefRange() { + SMLoc Loc; + std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges; + while (getLexer().is(AsmToken::Identifier)) { + Loc = getLexer().getLoc(); + StringRef GapStartName; + if (parseIdentifier(GapStartName)) + return Error(Loc, "expected identifier in directive"); + MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName); + + Loc = getLexer().getLoc(); + StringRef GapEndName; + if (parseIdentifier(GapEndName)) + return Error(Loc, "expected identifier in directive"); + MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName); + + Ranges.push_back({GapStartSym, GapEndSym}); + } + + std::string FixedSizePortion; + if (parseToken(AsmToken::Comma, "unexpected token in directive") || + parseEscapedString(FixedSizePortion)) + return true; + + getStreamer().EmitCVDefRangeDirective(Ranges, FixedSizePortion); + return false; +} + +/// parseDirectiveCVStringTable +/// ::= .cv_stringtable +bool AsmParser::parseDirectiveCVStringTable() { + getStreamer().EmitCVStringTableDirective(); + return false; +} + +/// parseDirectiveCVFileChecksums +/// ::= .cv_filechecksums +bool AsmParser::parseDirectiveCVFileChecksums() { + getStreamer().EmitCVFileChecksumsDirective(); + return false; +} + /// parseDirectiveCFISections /// ::= .cfi_sections section [, section] bool AsmParser::parseDirectiveCFISections() { @@ -3106,6 +3392,9 @@ bool AsmParser::parseDirectiveCFIStartProc() { if (parseIdentifier(Simple) || Simple != "simple") return TokError("unexpected token in .cfi_startproc directive"); + if (parseToken(AsmToken::EndOfStatement, "Expected end of statement")) + return true; + getStreamer().EmitCFIStartProc(!Simple.empty()); return false; } @@ -3135,16 +3424,10 @@ bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register, /// parseDirectiveCFIDefCfa /// ::= .cfi_def_cfa register, offset bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) { - int64_t Register = 0; - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) - return true; - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - - int64_t Offset = 0; - if (parseAbsoluteExpression(Offset)) + int64_t Register = 0, Offset = 0; + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || + parseToken(AsmToken::Comma, "unexpected token in directive") || + parseAbsoluteExpression(Offset)) return true; getStreamer().EmitCFIDefCfa(Register, Offset); @@ -3165,16 +3448,10 @@ bool AsmParser::parseDirectiveCFIDefCfaOffset() { /// parseDirectiveCFIRegister /// ::= .cfi_register register, register bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) { - int64_t Register1 = 0; - if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc)) - return true; - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - - int64_t Register2 = 0; - if (parseRegisterOrRegisterNumber(Register2, DirectiveLoc)) + int64_t Register1 = 0, Register2 = 0; + if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) || + parseToken(AsmToken::Comma, "unexpected token in directive") || + parseRegisterOrRegisterNumber(Register2, DirectiveLoc)) return true; getStreamer().EmitCFIRegister(Register1, Register2); @@ -3216,14 +3493,9 @@ bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) { int64_t Register = 0; int64_t Offset = 0; - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) - return true; - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - - if (parseAbsoluteExpression(Offset)) + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || + parseToken(AsmToken::Comma, "unexpected token in directive") || + parseAbsoluteExpression(Offset)) return true; getStreamer().EmitCFIOffset(Register, Offset); @@ -3233,17 +3505,11 @@ bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) { /// parseDirectiveCFIRelOffset /// ::= .cfi_rel_offset register, offset bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) { - int64_t Register = 0; + int64_t Register = 0, Offset = 0; - if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) - return true; - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - - int64_t Offset = 0; - if (parseAbsoluteExpression(Offset)) + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || + parseToken(AsmToken::Comma, "unexpected token in directive") || + parseAbsoluteExpression(Offset)) return true; getStreamer().EmitCFIRelOffset(Register, Offset); @@ -3283,16 +3549,11 @@ bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) { if (Encoding == dwarf::DW_EH_PE_omit) return false; - if (!isValidEncoding(Encoding)) - return TokError("unsupported encoding."); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - StringRef Name; - if (parseIdentifier(Name)) - return TokError("expected identifier in directive"); + if (check(!isValidEncoding(Encoding), "unsupported encoding.") || + parseToken(AsmToken::Comma, "unexpected token in directive") || + check(parseIdentifier(Name), "expected identifier in directive")) + return true; MCSymbol *Sym = getContext().getOrCreateSymbol(Name); @@ -3366,9 +3627,9 @@ bool AsmParser::parseDirectiveCFIEscape() { /// parseDirectiveCFISignalFrame /// ::= .cfi_signal_frame bool AsmParser::parseDirectiveCFISignalFrame() { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(getLexer().getLoc(), - "unexpected token in '.cfi_signal_frame'"); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.cfi_signal_frame'")) + return true; getStreamer().EmitCFISignalFrame(); return false; @@ -3390,9 +3651,9 @@ bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) { /// ::= .macros_on /// ::= .macros_off bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(getLexer().getLoc(), - "unexpected token in '" + Directive + "' directive"); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '" + Directive + "' directive")) + return true; setMacrosEnabled(Directive == ".macros_on"); return false; @@ -3460,14 +3721,19 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) { Lex(); } - // Eat the end of statement. - Lex(); + // Eat just the end of statement. + Lexer.Lex(); + // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors AsmToken EndToken, StartToken = getTok(); unsigned MacroDepth = 0; - // Lex the macro definition. for (;;) { + // Ignore Lexing errors in macros. + while (Lexer.is(AsmToken::Error)) { + Lexer.Lex(); + } + // Check whether we have reached the end of the file. if (getLexer().is(AsmToken::Eof)) return Error(DirectiveLoc, "no matching '.endmacro' in definition"); @@ -3478,7 +3744,7 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) { getTok().getIdentifier() == ".endmacro") { if (MacroDepth == 0) { // Outermost macro. EndToken = getTok(); - Lex(); + Lexer.Lex(); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '" + EndToken.getIdentifier() + "' directive"); @@ -3615,8 +3881,9 @@ void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, /// parseDirectiveExitMacro /// ::= .exitm bool AsmParser::parseDirectiveExitMacro(StringRef Directive) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '" + Directive + "' directive"); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '" + Directive + "' directive")) + return true; if (!isInsideMacroInstantiation()) return TokError("unexpected '" + Directive + "' in file, " @@ -3656,14 +3923,14 @@ bool AsmParser::parseDirectiveEndMacro(StringRef Directive) { /// ::= .purgem bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) { StringRef Name; - if (parseIdentifier(Name)) - return TokError("expected identifier in '.purgem' directive"); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.purgem' directive"); - - if (!lookupMacro(Name)) - return Error(DirectiveLoc, "macro '" + Name + "' is not defined"); + SMLoc Loc; + if (getTokenLoc(Loc) || check(parseIdentifier(Name), Loc, + "expected identifier in '.purgem' directive") || + parseToken(AsmToken::EndOfStatement, + "unexpected token in '.purgem' directive") || + check(!lookupMacro(Name), DirectiveLoc, + "macro '" + Name + "' is not defined")) + return true; undefineMacro(Name); return false; @@ -3678,16 +3945,13 @@ bool AsmParser::parseDirectiveBundleAlignMode() { // in the inclusive range 0-30. SMLoc ExprLoc = getLexer().getLoc(); int64_t AlignSizePow2; - if (parseAbsoluteExpression(AlignSizePow2)) + if (parseAbsoluteExpression(AlignSizePow2) || + parseToken(AsmToken::EndOfStatement, "unexpected token after expression " + "in '.bundle_align_mode' " + "directive") || + check(AlignSizePow2 < 0 || AlignSizePow2 > 30, ExprLoc, + "invalid bundle alignment size (expected between 0 and 30)")) return true; - else if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token after expression in" - " '.bundle_align_mode' directive"); - else if (AlignSizePow2 < 0 || AlignSizePow2 > 30) - return Error(ExprLoc, - "invalid bundle alignment size (expected between 0 and 30)"); - - Lex(); // Because of AlignSizePow2's verified range we can safely truncate it to // unsigned. @@ -3707,14 +3971,11 @@ bool AsmParser::parseDirectiveBundleLock() { const char *kInvalidOptionError = "invalid option for '.bundle_lock' directive"; - if (parseIdentifier(Option)) - return Error(Loc, kInvalidOptionError); - - if (Option != "align_to_end") - return Error(Loc, kInvalidOptionError); - else if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(Loc, - "unexpected token after '.bundle_lock' directive option"); + if (check(parseIdentifier(Option), Loc, kInvalidOptionError) || + check(Option != "align_to_end", Loc, kInvalidOptionError) || + check(getTok().isNot(AsmToken::EndOfStatement), Loc, + "unexpected token after '.bundle_lock' directive option")) + return true; AlignToEnd = true; } @@ -3729,9 +3990,9 @@ bool AsmParser::parseDirectiveBundleLock() { bool AsmParser::parseDirectiveBundleUnlock() { checkForValidSection(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.bundle_unlock' directive"); - Lex(); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.bundle_unlock' directive")) + return true; getStreamer().EmitBundleUnlock(); return false; @@ -3742,31 +4003,26 @@ bool AsmParser::parseDirectiveBundleUnlock() { bool AsmParser::parseDirectiveSpace(StringRef IDVal) { checkForValidSection(); - int64_t NumBytes; - if (parseAbsoluteExpression(NumBytes)) + SMLoc NumBytesLoc = Lexer.getLoc(); + const MCExpr *NumBytes; + if (parseExpression(NumBytes)) return true; int64_t FillExpr = 0; if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '" + Twine(IDVal) + "' directive"); - Lex(); - if (parseAbsoluteExpression(FillExpr)) + if (parseToken(AsmToken::Comma, + "unexpected token in '" + Twine(IDVal) + "' directive") || + parseAbsoluteExpression(FillExpr)) return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '" + Twine(IDVal) + "' directive"); } - Lex(); - - if (NumBytes <= 0) - return TokError("invalid number of bytes in '" + Twine(IDVal) + - "' directive"); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '" + Twine(IDVal) + "' directive")) + return true; // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0. - getStreamer().EmitFill(NumBytes, FillExpr); + getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc); return false; } @@ -3789,10 +4045,10 @@ bool AsmParser::parseDirectiveLEB128(bool Signed) { if (getLexer().is(AsmToken::EndOfStatement)) break; - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); + if (parseToken(AsmToken::Comma, "unexpected token in directive")) + return true; } + Lex(); return false; } @@ -3820,9 +4076,8 @@ bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) { if (getLexer().is(AsmToken::EndOfStatement)) break; - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); + if (parseToken(AsmToken::Comma, "unexpected token in directive")) + return true; } } @@ -3911,10 +4166,9 @@ bool AsmParser::parseDirectiveAbort() { SMLoc Loc = getLexer().getLoc(); StringRef Str = parseStringToEndOfStatement(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.abort' directive"); - - Lex(); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.abort' directive")) + return true; if (Str.empty()) Error(Loc, ".abort detected. Assembly stopping."); @@ -3928,25 +4182,20 @@ bool AsmParser::parseDirectiveAbort() { /// parseDirectiveInclude /// ::= .include "filename" bool AsmParser::parseDirectiveInclude() { - if (getLexer().isNot(AsmToken::String)) - return TokError("expected string in '.include' directive"); - // Allow the strings to have escaped octal character sequence. std::string Filename; - if (parseEscapedString(Filename)) - return true; - SMLoc IncludeLoc = getLexer().getLoc(); - Lex(); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.include' directive"); - - // Attempt to switch the lexer to the included file before consuming the end - // of statement to avoid losing it when we switch. - if (enterIncludeFile(Filename)) { - Error(IncludeLoc, "Could not find include file '" + Filename + "'"); + SMLoc IncludeLoc = getTok().getLoc(); + + if (check(getTok().isNot(AsmToken::String), + "expected string in '.include' directive") || + parseEscapedString(Filename) || + check(getTok().isNot(AsmToken::EndOfStatement), + "unexpected token in '.include' directive") || + // Attempt to switch the lexer to the included file before consuming the + // end of statement to avoid losing it when we switch. + check(enterIncludeFile(Filename), IncludeLoc, + "Could not find include file '" + Filename + "'")) return true; - } return false; } @@ -3954,25 +4203,18 @@ bool AsmParser::parseDirectiveInclude() { /// parseDirectiveIncbin /// ::= .incbin "filename" bool AsmParser::parseDirectiveIncbin() { - if (getLexer().isNot(AsmToken::String)) - return TokError("expected string in '.incbin' directive"); - // Allow the strings to have escaped octal character sequence. std::string Filename; - if (parseEscapedString(Filename)) - return true; - SMLoc IncbinLoc = getLexer().getLoc(); - Lex(); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.incbin' directive"); - - // Attempt to process the included file. - if (processIncbinFile(Filename)) { - Error(IncbinLoc, "Could not find incbin file '" + Filename + "'"); + SMLoc IncbinLoc = getTok().getLoc(); + if (check(getTok().isNot(AsmToken::String), + "expected string in '.incbin' directive") || + parseEscapedString(Filename) || + parseToken(AsmToken::EndOfStatement, + "unexpected token in '.incbin' directive") || + // Attempt to process the included file. + check(processIncbinFile(Filename), IncbinLoc, + "Could not find incbin file '" + Filename + "'")) return true; - } - return false; } @@ -3985,14 +4227,11 @@ bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) { eatToEndOfStatement(); } else { int64_t ExprValue; - if (parseAbsoluteExpression(ExprValue)) + if (parseAbsoluteExpression(ExprValue) || + parseToken(AsmToken::EndOfStatement, + "unexpected token in '.if' directive")) return true; - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.if' directive"); - - Lex(); - switch (DirKind) { default: llvm_unreachable("unsupported directive"); @@ -4034,10 +4273,9 @@ bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) { } else { StringRef Str = parseStringToEndOfStatement(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.ifb' directive"); - - Lex(); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.ifb' directive")) + return true; TheCondState.CondMet = ExpectBlank == Str.empty(); TheCondState.Ignore = !TheCondState.CondMet; @@ -4058,17 +4296,14 @@ bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) { } else { StringRef Str1 = parseStringToComma(); - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '.ifc' directive"); - - Lex(); + if (parseToken(AsmToken::Comma, "unexpected token in '.ifc' directive")) + return true; StringRef Str2 = parseStringToEndOfStatement(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.ifc' directive"); - - Lex(); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.ifc' directive")) + return true; TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim()); TheCondState.Ignore = !TheCondState.CondMet; @@ -4133,10 +4368,9 @@ bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { if (TheCondState.Ignore) { eatToEndOfStatement(); } else { - if (parseIdentifier(Name)) - return TokError("expected identifier after '.ifdef'"); - - Lex(); + if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") || + parseToken(AsmToken::EndOfStatement, "unexpected token in '.ifdef'")) + return true; MCSymbol *Sym = getContext().lookupSymbol(Name); @@ -4184,10 +4418,9 @@ bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) { /// parseDirectiveElse /// ::= .else bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.else' directive"); - - Lex(); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.else' directive")) + return true; if (TheCondState.TheCond != AsmCond::IfCond && TheCondState.TheCond != AsmCond::ElseIfCond) @@ -4208,10 +4441,9 @@ bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) { /// parseDirectiveEnd /// ::= .end bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.end' directive"); - - Lex(); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.end' directive")) + return true; while (Lexer.isNot(AsmToken::Eof)) Lex(); @@ -4278,10 +4510,9 @@ bool AsmParser::parseDirectiveWarning(SMLoc L) { /// parseDirectiveEndIf /// ::= .endif bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.endif' directive"); - - Lex(); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.endif' directive")) + return true; if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty()) Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or " @@ -4378,6 +4609,13 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".line"] = DK_LINE; DirectiveKindMap[".loc"] = DK_LOC; DirectiveKindMap[".stabs"] = DK_STABS; + DirectiveKindMap[".cv_file"] = DK_CV_FILE; + DirectiveKindMap[".cv_loc"] = DK_CV_LOC; + DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE; + DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE; + DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE; + DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE; + DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS; DirectiveKindMap[".sleb128"] = DK_SLEB128; DirectiveKindMap[".uleb128"] = DK_ULEB128; DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS; @@ -4425,7 +4663,9 @@ MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { } if (Lexer.is(AsmToken::Identifier) && - (getTok().getIdentifier() == ".rept")) { + (getTok().getIdentifier() == ".rept" || + getTok().getIdentifier() == ".irp" || + getTok().getIdentifier() == ".irpc")) { ++NestLevel; } @@ -4489,14 +4729,10 @@ bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) { return Error(CountLoc, "unexpected token in '" + Dir + "' directive"); } - if (Count < 0) - return Error(CountLoc, "Count is negative"); - - if (Lexer.isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '" + Dir + "' directive"); - - // Eat the end of statement. - Lex(); + if (check(Count < 0, CountLoc, "Count is negative") || + parseToken(AsmToken::EndOfStatement, + "unexpected token in '" + Dir + "' directive")) + return true; // Lex the rept definition. MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); @@ -4521,22 +4757,14 @@ bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) { /// ::= .irp symbol,values bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) { MCAsmMacroParameter Parameter; - - if (parseIdentifier(Parameter.Name)) - return TokError("expected identifier in '.irp' directive"); - - if (Lexer.isNot(AsmToken::Comma)) - return TokError("expected comma in '.irp' directive"); - - Lex(); - MCAsmMacroArguments A; - if (parseMacroArguments(nullptr, A)) + if (check(parseIdentifier(Parameter.Name), + "expected identifier in '.irp' directive") || + parseToken(AsmToken::Comma, "expected comma in '.irp' directive") || + parseMacroArguments(nullptr, A) || + parseToken(AsmToken::EndOfStatement, "expected End of Statement")) return true; - // Eat the end of statement. - Lex(); - // Lex the irp definition. MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); if (!M) @@ -4563,24 +4791,20 @@ bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) { /// ::= .irpc symbol,values bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) { MCAsmMacroParameter Parameter; - - if (parseIdentifier(Parameter.Name)) - return TokError("expected identifier in '.irpc' directive"); - - if (Lexer.isNot(AsmToken::Comma)) - return TokError("expected comma in '.irpc' directive"); - - Lex(); - MCAsmMacroArguments A; - if (parseMacroArguments(nullptr, A)) + + if (check(parseIdentifier(Parameter.Name), + "expected identifier in '.irpc' directive") || + parseToken(AsmToken::Comma, "expected comma in '.irpc' directive") || + parseMacroArguments(nullptr, A)) return true; if (A.size() != 1 || A.front().size() != 1) return TokError("unexpected token in '.irpc' directive"); // Eat the end of statement. - Lex(); + if (parseToken(AsmToken::EndOfStatement, "expected end of statement")) + return true; // Lex the irpc definition. MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); @@ -4699,6 +4923,10 @@ bool AsmParser::parseMSInlineAsm( unsigned InputIdx = 0; unsigned OutputIdx = 0; while (getLexer().isNot(AsmToken::Eof)) { + // Parse curly braces marking block start/end + if (parseCurlyBlockScope(AsmStrRewrites)) + continue; + ParseStatementInfo Info(&AsmStrRewrites); if (parseStatement(Info, &SI)) return true; @@ -4875,6 +5103,9 @@ bool AsmParser::parseMSInlineAsm( OS << '.'; OS << AR.Val; break; + case AOK_EndOfStatement: + OS << "\n\t"; + break; } // Skip the original expression. @@ -4922,10 +5153,9 @@ static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *Value) { bool parseAssignmentExpression(StringRef Name, bool allow_redef, MCAsmParser &Parser, MCSymbol *&Sym, const MCExpr *&Value) { - MCAsmLexer &Lexer = Parser.getLexer(); // FIXME: Use better location, we should use proper tokens. - SMLoc EqualLoc = Lexer.getLoc(); + SMLoc EqualLoc = Parser.getTok().getLoc(); if (Parser.parseExpression(Value)) { Parser.TokError("missing expression"); @@ -4937,7 +5167,7 @@ bool parseAssignmentExpression(StringRef Name, bool allow_redef, // a = b // b = c - if (Lexer.isNot(AsmToken::EndOfStatement)) + if (Parser.getTok().isNot(AsmToken::EndOfStatement)) return Parser.TokError("unexpected token in assignment"); // Eat the end of statement marker. diff --git a/gnu/llvm/lib/MC/MCParser/COFFAsmParser.cpp b/gnu/llvm/lib/MC/MCParser/COFFAsmParser.cpp index a4b2b195f71..653627ad8dc 100644 --- a/gnu/llvm/lib/MC/MCParser/COFFAsmParser.cpp +++ b/gnu/llvm/lib/MC/MCParser/COFFAsmParser.cpp @@ -15,10 +15,10 @@ #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCParser/MCAsmLexer.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/MCTargetAsmParser.h" #include "llvm/Support/COFF.h" using namespace llvm; diff --git a/gnu/llvm/lib/MC/MCParser/DarwinAsmParser.cpp b/gnu/llvm/lib/MC/MCParser/DarwinAsmParser.cpp index 73e068a3439..37515d9c074 100644 --- a/gnu/llvm/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/gnu/llvm/lib/MC/MCParser/DarwinAsmParser.cpp @@ -50,6 +50,7 @@ public: // Call the base implementation. this->MCAsmParserExtension::Initialize(Parser); + addDirectiveHandler<&DarwinAsmParser::parseDirectiveAltEntry>(".alt_entry"); addDirectiveHandler<&DarwinAsmParser::parseDirectiveDesc>(".desc"); addDirectiveHandler<&DarwinAsmParser::parseDirectiveIndirectSymbol>( ".indirect_symbol"); @@ -111,6 +112,9 @@ public: addDirectiveHandler< &DarwinAsmParser::parseSectionDirectiveNonLazySymbolPointers>( ".non_lazy_symbol_pointer"); + addDirectiveHandler< + &DarwinAsmParser::parseSectionDirectiveThreadLocalVariablePointers>( + ".thread_local_variable_pointer"); addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatClsMeth>( ".objc_cat_cls_meth"); addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatInstMeth>( @@ -179,6 +183,7 @@ public: LastVersionMinDirective = SMLoc(); } + bool parseDirectiveAltEntry(StringRef, SMLoc); bool parseDirectiveDesc(StringRef, SMLoc); bool parseDirectiveIndirectSymbol(StringRef, SMLoc); bool parseDirectiveDumpOrLoad(StringRef, SMLoc); @@ -261,6 +266,10 @@ public: 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"); } @@ -408,6 +417,26 @@ bool DarwinAsmParser::parseSectionSwitch(const char *Segment, return false; } +/// parseDirectiveAltEntry +/// ::= .alt_entry identifier +bool DarwinAsmParser::parseDirectiveAltEntry(StringRef, SMLoc) { + StringRef Name; + if (getParser().parseIdentifier(Name)) + return TokError("expected identifier in directive"); + + // Look up symbol. + MCSymbol *Sym = getContext().getOrCreateSymbol(Name); + + if (Sym->isDefined()) + return TokError(".alt_entry must preceed symbol definition"); + + if (!getStreamer().EmitSymbolAttribute(Sym, MCSA_AltEntry)) + return TokError("unable to emit symbol attribute"); + + Lex(); + return false; +} + /// parseDirectiveDesc /// ::= .desc identifier , expression bool DarwinAsmParser::parseDirectiveDesc(StringRef, SMLoc) { @@ -445,6 +474,7 @@ bool DarwinAsmParser::parseDirectiveIndirectSymbol(StringRef, SMLoc Loc) { MachO::SectionType SectionType = Current->getType(); if (SectionType != MachO::S_NON_LAZY_SYMBOL_POINTERS && SectionType != MachO::S_LAZY_SYMBOL_POINTERS && + SectionType != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS && SectionType != MachO::S_SYMBOL_STUBS) return Error(Loc, "indirect symbol not in a symbol pointer or stub " "section"); @@ -507,7 +537,6 @@ bool DarwinAsmParser::parseDirectiveLinkerOption(StringRef IDVal, SMLoc) { Args.push_back(Data); - Lex(); if (getLexer().is(AsmToken::EndOfStatement)) break; @@ -929,8 +958,8 @@ bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc) { if (getLexer().isNot(AsmToken::Integer)) return TokError("invalid OS update number"); Update = getLexer().getTok().getIntVal(); - if (Update > 255 || Update < 0) - return TokError("invalid OS update number"); + if (Update > 255 || Update < 0) + return TokError("invalid OS update number"); Lex(); } diff --git a/gnu/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/gnu/llvm/lib/MC/MCParser/ELFAsmParser.cpp index 6cbcdec5e27..47d19a824d1 100644 --- a/gnu/llvm/lib/MC/MCParser/ELFAsmParser.cpp +++ b/gnu/llvm/lib/MC/MCParser/ELFAsmParser.cpp @@ -188,6 +188,7 @@ bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type, if (getParser().parseExpression(Subsection)) return true; } + Lex(); getStreamer().SwitchSection(getContext().getELFSection(Section, Type, Flags), Subsection); @@ -211,6 +212,7 @@ bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); + Lex(); getStreamer().emitELFSize(Sym, Expr); return false; @@ -229,22 +231,23 @@ bool ELFAsmParser::ParseSectionName(StringRef &SectionName) { } for (;;) { - unsigned CurSize; - + SMLoc PrevLoc = getLexer().getLoc(); - if (getLexer().is(AsmToken::Minus)) { - CurSize = 1; - Lex(); // Consume the "-". - } else if (getLexer().is(AsmToken::String)) { + if (getLexer().is(AsmToken::Comma) || + getLexer().is(AsmToken::EndOfStatement)) + break; + + unsigned CurSize; + if (getLexer().is(AsmToken::String)) { CurSize = getTok().getIdentifier().size() + 2; Lex(); } else if (getLexer().is(AsmToken::Identifier)) { CurSize = getTok().getIdentifier().size(); Lex(); } else { - break; + CurSize = getTok().getString().size(); + Lex(); } - Size += CurSize; SectionName = StringRef(FirstLoc.getPointer(), Size); @@ -261,8 +264,8 @@ bool ELFAsmParser::ParseSectionName(StringRef &SectionName) { static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) { unsigned flags = 0; - for (unsigned i = 0; i < flagsStr.size(); i++) { - switch (flagsStr[i]) { + for (char i : flagsStr) { + switch (i) { case 'a': flags |= ELF::SHF_ALLOC; break; @@ -476,6 +479,7 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) { EndStmt: if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); + Lex(); unsigned Type = ELF::SHT_PROGBITS; @@ -627,6 +631,10 @@ bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) { Lex(); + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.ident' directive"); + Lex(); + getStreamer().EmitIdent(Data); return false; } @@ -725,6 +733,8 @@ bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); + Lex(); + getStreamer().SubSection(Subsection); return false; } diff --git a/gnu/llvm/lib/MC/MCParser/MCAsmLexer.cpp b/gnu/llvm/lib/MC/MCParser/MCAsmLexer.cpp index e891bd2c624..d95cd12accb 100644 --- a/gnu/llvm/lib/MC/MCParser/MCAsmLexer.cpp +++ b/gnu/llvm/lib/MC/MCParser/MCAsmLexer.cpp @@ -13,7 +13,7 @@ using namespace llvm; MCAsmLexer::MCAsmLexer() : TokStart(nullptr), SkipSpace(true) { - CurTok.emplace_back(AsmToken::Error, StringRef()); + CurTok.emplace_back(AsmToken::Space, StringRef()); } MCAsmLexer::~MCAsmLexer() { diff --git a/gnu/llvm/lib/MC/MCParser/MCAsmParser.cpp b/gnu/llvm/lib/MC/MCParser/MCAsmParser.cpp index 290dcb29774..dc7a3f00840 100644 --- a/gnu/llvm/lib/MC/MCParser/MCAsmParser.cpp +++ b/gnu/llvm/lib/MC/MCParser/MCAsmParser.cpp @@ -11,7 +11,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" -#include "llvm/MC/MCTargetAsmParser.h" +#include "llvm/MC/MCParser/MCTargetAsmParser.h" #include "llvm/Support/Debug.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" @@ -43,7 +43,7 @@ bool MCAsmParser::parseExpression(const MCExpr *&Res) { return parseExpression(Res, L); } -void MCParsedAsmOperand::dump() const { +LLVM_DUMP_METHOD void MCParsedAsmOperand::dump() const { #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) dbgs() << " " << *this; #endif diff --git a/gnu/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp b/gnu/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp index 4e4b47805cd..14a22c6b8a2 100644 --- a/gnu/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp +++ b/gnu/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// +#include "llvm/MC/MCParser/MCTargetAsmParser.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCTargetAsmParser.h" using namespace llvm; MCTargetAsmParser::MCTargetAsmParser(MCTargetOptions const &MCOptions, diff --git a/gnu/llvm/lib/MC/MCRegisterInfo.cpp b/gnu/llvm/lib/MC/MCRegisterInfo.cpp index ce79cd5c2c6..c76bb646c12 100644 --- a/gnu/llvm/lib/MC/MCRegisterInfo.cpp +++ b/gnu/llvm/lib/MC/MCRegisterInfo.cpp @@ -84,3 +84,12 @@ int MCRegisterInfo::getSEHRegNum(unsigned RegNum) const { if (I == L2SEHRegs.end()) return (int)RegNum; return I->second; } + +int MCRegisterInfo::getCodeViewRegNum(unsigned RegNum) const { + if (L2CVRegs.empty()) + report_fatal_error("target does not implement codeview register mapping"); + const DenseMap<unsigned, int>::const_iterator I = L2CVRegs.find(RegNum); + if (I == L2CVRegs.end()) + report_fatal_error("unknown codeview register"); + return I->second; +} diff --git a/gnu/llvm/lib/MC/MCSection.cpp b/gnu/llvm/lib/MC/MCSection.cpp index dbd544a44ce..32e4cce4f68 100644 --- a/gnu/llvm/lib/MC/MCSection.cpp +++ b/gnu/llvm/lib/MC/MCSection.cpp @@ -86,7 +86,7 @@ MCSection::getSubsectionInsertionPoint(unsigned Subsection) { } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -void MCSection::dump() { +LLVM_DUMP_METHOD void MCSection::dump() { raw_ostream &OS = llvm::errs(); OS << "<MCSection"; diff --git a/gnu/llvm/lib/MC/MCStreamer.cpp b/gnu/llvm/lib/MC/MCStreamer.cpp index 836b4054464..6c8828f71ba 100644 --- a/gnu/llvm/lib/MC/MCStreamer.cpp +++ b/gnu/llvm/lib/MC/MCStreamer.cpp @@ -19,8 +19,10 @@ #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCWin64EH.h" +#include "llvm/Support/COFF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/raw_ostream.h" @@ -68,6 +70,9 @@ raw_ostream &MCStreamer::GetCommentOS() { void MCStreamer::emitRawComment(const Twine &T, bool TabPrefix) {} +void MCStreamer::addExplicitComment(const Twine &T) {} +void MCStreamer::emitExplicitComments() {} + void MCStreamer::generateCompactUnwindEncodings(MCAsmBackend *MAB) { for (auto &FI : DwarfFrameInfos) FI.CompactUnwindEncoding = @@ -130,17 +135,26 @@ void MCStreamer::EmitGPRel32Value(const MCExpr *Value) { report_fatal_error("unsupported directive in streamer"); } -/// EmitFill - Emit NumBytes bytes worth of the value specified by -/// FillValue. This implements directives such as '.space'. -void MCStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue) { - const MCExpr *E = MCConstantExpr::create(FillValue, getContext()); +/// Emit NumBytes bytes worth of the value specified by FillValue. +/// This implements directives such as '.space'. +void MCStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) { for (uint64_t i = 0, e = NumBytes; i != e; ++i) - EmitValue(E, 1); + EmitIntValue(FillValue, 1); +} + +void MCStreamer::emitFill(uint64_t NumValues, int64_t Size, int64_t Expr) { + int64_t NonZeroSize = Size > 4 ? 4 : Size; + Expr &= ~0ULL >> (64 - NonZeroSize * 8); + for (uint64_t i = 0, e = NumValues; i != e; ++i) { + EmitIntValue(Expr, NonZeroSize); + if (NonZeroSize < Size) + EmitIntValue(0, Size - NonZeroSize); + } } -/// The implementation in this class just redirects to EmitFill. +/// The implementation in this class just redirects to emitFill. void MCStreamer::EmitZeros(uint64_t NumBytes) { - EmitFill(NumBytes, 0); + emitFill(NumBytes, 0); } unsigned MCStreamer::EmitDwarfFileDirective(unsigned FileNo, @@ -174,12 +188,42 @@ MCDwarfFrameInfo *MCStreamer::getCurrentDwarfFrameInfo() { return &DwarfFrameInfos.back(); } +bool MCStreamer::hasUnfinishedDwarfFrameInfo() { + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); + return CurFrame && !CurFrame->End; +} + void MCStreamer::EnsureValidDwarfFrame() { MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); if (!CurFrame || CurFrame->End) report_fatal_error("No open frame"); } +unsigned MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename) { + return getContext().getCVFile(Filename, FileNo); +} + +void MCStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, + unsigned Line, unsigned Column, + bool PrologueEnd, bool IsStmt, + StringRef FileName) { + getContext().setCurrentCVLoc(FunctionId, FileNo, Line, Column, PrologueEnd, + IsStmt); +} + +void MCStreamer::EmitCVLinetableDirective(unsigned FunctionId, + const MCSymbol *Begin, + const MCSymbol *End) {} + +void MCStreamer::EmitCVInlineLinetableDirective( + unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, + const MCSymbol *FnStartSym, const MCSymbol *FnEndSym, + ArrayRef<unsigned> SecondaryFunctionIds) {} + +void MCStreamer::EmitCVDefRangeDirective( + ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, + StringRef FixedSizePortion) {} + void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) { } @@ -213,8 +257,7 @@ void MCStreamer::EmitCFISections(bool EH, bool Debug) { } void MCStreamer::EmitCFIStartProc(bool IsSimple) { - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - if (CurFrame && !CurFrame->End) + if (hasUnfinishedDwarfFrameInfo()) report_fatal_error("Starting a frame before finishing the previous one!"); MCDwarfFrameInfo Frame; @@ -417,6 +460,7 @@ void MCStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) { WinFrameInfos.push_back(new WinEH::FrameInfo(Symbol, StartProc)); CurrentWinFrameInfo = WinFrameInfos.back(); + CurrentWinFrameInfo->TextSection = getCurrentSectionOnly(); } void MCStreamer::EmitWinCFIEndProc() { @@ -438,6 +482,7 @@ void MCStreamer::EmitWinCFIStartChained() { WinFrameInfos.push_back(new WinEH::FrameInfo(CurrentWinFrameInfo->Function, StartProc, CurrentWinFrameInfo)); CurrentWinFrameInfo = WinFrameInfos.back(); + CurrentWinFrameInfo->TextSection = getCurrentSectionOnly(); } void MCStreamer::EmitWinCFIEndChained() { @@ -473,6 +518,38 @@ void MCStreamer::EmitWinEHHandlerData() { report_fatal_error("Chained unwind areas can't have handlers!"); } +static MCSection *getWinCFISection(MCContext &Context, unsigned *NextWinCFIID, + MCSection *MainCFISec, + const MCSection *TextSec) { + // If this is the main .text section, use the main unwind info section. + if (TextSec == Context.getObjectFileInfo()->getTextSection()) + return MainCFISec; + + const auto *TextSecCOFF = cast<MCSectionCOFF>(TextSec); + unsigned UniqueID = TextSecCOFF->getOrAssignWinCFISectionID(NextWinCFIID); + + // If this section is COMDAT, this unwind section should be COMDAT associative + // with its group. + const MCSymbol *KeySym = nullptr; + if (TextSecCOFF->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) + KeySym = TextSecCOFF->getCOMDATSymbol(); + + return Context.getAssociativeCOFFSection(cast<MCSectionCOFF>(MainCFISec), + KeySym, UniqueID); +} + +MCSection *MCStreamer::getAssociatedPDataSection(const MCSection *TextSec) { + return getWinCFISection(getContext(), &NextWinCFIID, + getContext().getObjectFileInfo()->getPDataSection(), + TextSec); +} + +MCSection *MCStreamer::getAssociatedXDataSection(const MCSection *TextSec) { + return getWinCFISection(getContext(), &NextWinCFIID, + getContext().getObjectFileInfo()->getXDataSection(), + TextSec); +} + void MCStreamer::EmitSyntaxDirective() {} void MCStreamer::EmitWinCFIPushReg(unsigned Register) { @@ -660,7 +737,7 @@ void MCStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, MCSymbolRefExpr::create(Lo, Context), Context); const MCAsmInfo *MAI = Context.getAsmInfo(); - if (!MAI->doesSetDirectiveSuppressesReloc()) { + if (!MAI->doesSetDirectiveSuppressReloc()) { EmitValue(Diff, Size); return; } @@ -687,11 +764,15 @@ void MCStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, void MCStreamer::ChangeSection(MCSection *, const MCExpr *) {} void MCStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {} void MCStreamer::EmitBytes(StringRef Data) {} +void MCStreamer::EmitBinaryData(StringRef Data) { EmitBytes(Data); } void MCStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) { visitUsedExpr(*Value); } void MCStreamer::EmitULEB128Value(const MCExpr *Value) {} void MCStreamer::EmitSLEB128Value(const MCExpr *Value) {} +void MCStreamer::emitFill(const MCExpr &NumBytes, uint64_t Value, SMLoc Loc) {} +void MCStreamer::emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr, + SMLoc Loc) {} void MCStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, unsigned ValueSize, unsigned MaxBytesToEmit) {} diff --git a/gnu/llvm/lib/MC/MCSymbol.cpp b/gnu/llvm/lib/MC/MCSymbol.cpp index ab3b8eb6832..2ddece6bddc 100644 --- a/gnu/llvm/lib/MC/MCSymbol.cpp +++ b/gnu/llvm/lib/MC/MCSymbol.cpp @@ -77,5 +77,5 @@ void MCSymbol::print(raw_ostream &OS, const MCAsmInfo *MAI) const { } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -void MCSymbol::dump() const { dbgs() << *this; } +LLVM_DUMP_METHOD void MCSymbol::dump() const { dbgs() << *this; } #endif diff --git a/gnu/llvm/lib/MC/MCValue.cpp b/gnu/llvm/lib/MC/MCValue.cpp index 495a2b6ea5b..32a6adbf224 100644 --- a/gnu/llvm/lib/MC/MCValue.cpp +++ b/gnu/llvm/lib/MC/MCValue.cpp @@ -38,7 +38,7 @@ void MCValue::print(raw_ostream &OS) const { } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -void MCValue::dump() const { +LLVM_DUMP_METHOD void MCValue::dump() const { print(dbgs()); } #endif diff --git a/gnu/llvm/lib/MC/MCWin64EH.cpp b/gnu/llvm/lib/MC/MCWin64EH.cpp index 1b73b7afb6a..fdc4c10cd6c 100644 --- a/gnu/llvm/lib/MC/MCWin64EH.cpp +++ b/gnu/llvm/lib/MC/MCWin64EH.cpp @@ -17,7 +17,7 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/Support/Win64EH.h" -namespace llvm { +using namespace llvm; // NOTE: All relocations generated here are 4-byte image-relative. @@ -218,35 +218,29 @@ static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) { } } -namespace Win64EH { -void UnwindEmitter::Emit(MCStreamer &Streamer) const { - MCContext &Context = Streamer.getContext(); - +void llvm::Win64EH::UnwindEmitter::Emit(MCStreamer &Streamer) const { // Emit the unwind info structs first. - for (const auto &CFI : Streamer.getWinFrameInfos()) { - MCSection *XData = getXDataSection(CFI->Function, Context); + for (WinEH::FrameInfo *CFI : Streamer.getWinFrameInfos()) { + MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection); Streamer.SwitchSection(XData); - EmitUnwindInfo(Streamer, CFI); + ::EmitUnwindInfo(Streamer, CFI); } // Now emit RUNTIME_FUNCTION entries. - for (const auto &CFI : Streamer.getWinFrameInfos()) { - MCSection *PData = getPDataSection(CFI->Function, Context); + for (WinEH::FrameInfo *CFI : Streamer.getWinFrameInfos()) { + MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection); Streamer.SwitchSection(PData); EmitRuntimeFunction(Streamer, CFI); } } -void UnwindEmitter::EmitUnwindInfo(MCStreamer &Streamer, - WinEH::FrameInfo *info) const { +void llvm::Win64EH::UnwindEmitter::EmitUnwindInfo( + MCStreamer &Streamer, WinEH::FrameInfo *info) const { // Switch sections (the static function above is meant to be called from // here and from Emit(). - MCContext &context = Streamer.getContext(); - MCSection *xdataSect = getXDataSection(info->Function, context); - Streamer.SwitchSection(xdataSect); + MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection); + Streamer.SwitchSection(XData); - llvm::EmitUnwindInfo(Streamer, info); -} + ::EmitUnwindInfo(Streamer, info); } -} // End of namespace llvm diff --git a/gnu/llvm/lib/MC/MCWinEH.cpp b/gnu/llvm/lib/MC/MCWinEH.cpp index 83af203c7ac..21a913999f6 100644 --- a/gnu/llvm/lib/MC/MCWinEH.cpp +++ b/gnu/llvm/lib/MC/MCWinEH.cpp @@ -19,60 +19,7 @@ namespace llvm { namespace WinEH { -/// We can't have one section for all .pdata or .xdata because the Microsoft -/// linker seems to want all code relocations to refer to the same object file -/// section. If the code described is comdat, create a new comdat section -/// associated with that comdat. If the code described is not in the main .text -/// section, make a new section for it. Otherwise use the main unwind info -/// section. -static MCSection *getUnwindInfoSection(StringRef SecName, - MCSectionCOFF *UnwindSec, - const MCSymbol *Function, - MCContext &Context) { - if (Function && Function->isInSection()) { - // If Function is in a COMDAT, get or create an unwind info section in that - // COMDAT group. - const MCSectionCOFF *FunctionSection = - cast<MCSectionCOFF>(&Function->getSection()); - if (FunctionSection->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) { - return Context.getAssociativeCOFFSection( - UnwindSec, FunctionSection->getCOMDATSymbol()); - } - - // If Function is in a section other than .text, create a new .pdata section. - // Otherwise use the plain .pdata section. - if (const auto *Section = dyn_cast<MCSectionCOFF>(FunctionSection)) { - StringRef CodeSecName = Section->getSectionName(); - if (CodeSecName == ".text") - return UnwindSec; - - if (CodeSecName.startswith(".text$")) - CodeSecName = CodeSecName.substr(6); - - return Context.getCOFFSection((SecName + Twine('$') + CodeSecName).str(), - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getData()); - } - } - - return UnwindSec; - -} - -MCSection *UnwindEmitter::getPDataSection(const MCSymbol *Function, - MCContext &Context) { - MCSectionCOFF *PData = - cast<MCSectionCOFF>(Context.getObjectFileInfo()->getPDataSection()); - return getUnwindInfoSection(".pdata", PData, Function, Context); -} - -MCSection *UnwindEmitter::getXDataSection(const MCSymbol *Function, - MCContext &Context) { - MCSectionCOFF *XData = - cast<MCSectionCOFF>(Context.getObjectFileInfo()->getXDataSection()); - return getUnwindInfoSection(".xdata", XData, Function, Context); -} +UnwindEmitter::~UnwindEmitter() {} } } diff --git a/gnu/llvm/lib/MC/MachObjectWriter.cpp b/gnu/llvm/lib/MC/MachObjectWriter.cpp index 324385fa132..e39271949d9 100644 --- a/gnu/llvm/lib/MC/MachObjectWriter.cpp +++ b/gnu/llvm/lib/MC/MachObjectWriter.cpp @@ -334,7 +334,7 @@ void MachObjectWriter::writeNlist(MachSymbolData &MSD, if (AliaseeInfo) SectionIndex = AliaseeInfo->SectionIndex; Symbol = AliasedSymbol; - // FIXME: Should this update Data as well? Do we need OrigSymbol at all? + // FIXME: Should this update Data as well? } // Set the N_TYPE bits. See <mach-o/nlist.h>. @@ -377,7 +377,9 @@ void MachObjectWriter::writeNlist(MachSymbolData &MSD, // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc' // value. - write16(cast<MCSymbolMachO>(Symbol)->getEncodedFlags()); + bool EncodeAsAltEntry = + IsAlias && cast<MCSymbolMachO>(OrigSymbol).isAltEntry(); + write16(cast<MCSymbolMachO>(Symbol)->getEncodedFlags(EncodeAsAltEntry)); if (is64Bit()) write64(Address); else @@ -404,7 +406,7 @@ static unsigned ComputeLinkerOptionsLoadCommandSize( unsigned Size = sizeof(MachO::linker_option_command); for (const std::string &Option : Options) Size += Option.size() + 1; - return RoundUpToAlignment(Size, is64Bit ? 8 : 4); + return alignTo(Size, is64Bit ? 8 : 4); } void MachObjectWriter::writeLinkerOptionsLoadCommand( @@ -455,6 +457,7 @@ void MachObjectWriter::bindIndirectSymbols(MCAssembler &Asm) { if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS && Section.getType() != MachO::S_LAZY_SYMBOL_POINTERS && + Section.getType() != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS && Section.getType() != MachO::S_SYMBOL_STUBS) { MCSymbol &Symbol = *it->Symbol; report_fatal_error("indirect symbol '" + Symbol.getName() + @@ -468,7 +471,8 @@ void MachObjectWriter::bindIndirectSymbols(MCAssembler &Asm) { ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) { const MCSectionMachO &Section = cast<MCSectionMachO>(*it->Section); - if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS) + if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS && + Section.getType() != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) continue; // Initialize the section indirect symbol base, if necessary. @@ -606,7 +610,7 @@ void MachObjectWriter::computeSectionAddresses(const MCAssembler &Asm, const MCAsmLayout &Layout) { uint64_t StartAddress = 0; for (const MCSection *Sec : Layout.getSectionOrder()) { - StartAddress = RoundUpToAlignment(StartAddress, Sec->getAlignment()); + StartAddress = alignTo(StartAddress, Sec->getAlignment()); SectionAddress[Sec] = StartAddress; StartAddress += Layout.getSectionAddressSize(Sec); @@ -736,7 +740,7 @@ void MachObjectWriter::writeObject(MCAssembler &Asm, // Add the loh load command size, if used. uint64_t LOHRawSize = Asm.getLOHContainer().getEmitSize(*this, Layout); - uint64_t LOHSize = RoundUpToAlignment(LOHRawSize, is64Bit() ? 8 : 4); + uint64_t LOHSize = alignTo(LOHRawSize, is64Bit() ? 8 : 4); if (LOHSize) { ++NumLoadCommands; LoadCommandsSize += sizeof(MachO::linkedit_data_command); diff --git a/gnu/llvm/lib/MC/StringTableBuilder.cpp b/gnu/llvm/lib/MC/StringTableBuilder.cpp index 80e552287b3..9d95952a6d3 100644 --- a/gnu/llvm/lib/MC/StringTableBuilder.cpp +++ b/gnu/llvm/lib/MC/StringTableBuilder.cpp @@ -16,13 +16,29 @@ using namespace llvm; -StringTableBuilder::StringTableBuilder(Kind K) : K(K) {} +StringTableBuilder::StringTableBuilder(Kind K, unsigned Alignment) + : K(K), Alignment(Alignment) { + // Account for leading bytes in table so that offsets returned from add are + // correct. + switch (K) { + case RAW: + Size = 0; + break; + case MachO: + case ELF: + Size = 1; + break; + case WinCOFF: + Size = 4; + break; + } +} -typedef std::pair<StringRef, size_t> StringPair; +typedef std::pair<CachedHash<StringRef>, size_t> StringPair; // Returns the character at Pos from end of a string. static int charTailAt(StringPair *P, size_t Pos) { - StringRef S = P->first; + StringRef S = P->first.Val; if (Pos >= S.size()) return -1; return (unsigned char)S[S.size() - Pos - 1]; @@ -62,13 +78,32 @@ tailcall: } void StringTableBuilder::finalize() { - std::vector<std::pair<StringRef, size_t> *> Strings; + finalizeStringTable(/*Optimize=*/true); +} + +void StringTableBuilder::finalizeInOrder() { + finalizeStringTable(/*Optimize=*/false); +} + +void StringTableBuilder::finalizeStringTable(bool Optimize) { + typedef std::pair<CachedHash<StringRef>, size_t> StringOffsetPair; + std::vector<StringOffsetPair *> Strings; Strings.reserve(StringIndexMap.size()); - for (std::pair<StringRef, size_t> &P : StringIndexMap) + for (StringOffsetPair &P : StringIndexMap) Strings.push_back(&P); - if (!Strings.empty()) - multikey_qsort(&Strings[0], &Strings[0] + Strings.size(), 0); + if (!Strings.empty()) { + // If we're optimizing, sort by name. If not, sort by previously assigned + // offset. + if (Optimize) { + multikey_qsort(&Strings[0], &Strings[0] + Strings.size(), 0); + } else { + std::sort(Strings.begin(), Strings.end(), + [](const StringOffsetPair *LHS, const StringOffsetPair *RHS) { + return LHS->second < RHS->second; + }); + } + } switch (K) { case RAW: @@ -85,17 +120,28 @@ void StringTableBuilder::finalize() { } StringRef Previous; - for (std::pair<StringRef, size_t> *P : Strings) { - StringRef S = P->first; + for (StringOffsetPair *P : Strings) { + StringRef S = P->first.Val; if (K == WinCOFF) assert(S.size() > COFF::NameSize && "Short string in COFF string table!"); - if (Previous.endswith(S)) { - P->second = StringTable.size() - S.size() - (K != RAW); - continue; + if (Optimize && Previous.endswith(S)) { + size_t Pos = StringTable.size() - S.size() - (K != RAW); + if (!(Pos & (Alignment - 1))) { + P->second = Pos; + continue; + } + } + + if (Optimize) { + size_t Start = alignTo(StringTable.size(), Alignment); + P->second = Start; + StringTable.append(Start - StringTable.size(), '\0'); + } else { + assert(P->second == StringTable.size() && + "different strtab offset after finalization"); } - P->second = StringTable.size(); StringTable += S; if (K != RAW) StringTable += '\x00'; @@ -137,8 +183,9 @@ size_t StringTableBuilder::getOffset(StringRef S) const { size_t StringTableBuilder::add(StringRef S) { assert(!isFinalized()); - auto P = StringIndexMap.insert(std::make_pair(S, Size)); + size_t Start = alignTo(Size, Alignment); + auto P = StringIndexMap.insert(std::make_pair(S, Start)); if (P.second) - Size += S.size() + (K != RAW); + Size = Start + S.size() + (K != RAW); return P.first->second; } diff --git a/gnu/llvm/lib/MC/SubtargetFeature.cpp b/gnu/llvm/lib/MC/SubtargetFeature.cpp index 7cce0fe756e..a97cd1db693 100644 --- a/gnu/llvm/lib/MC/SubtargetFeature.cpp +++ b/gnu/llvm/lib/MC/SubtargetFeature.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/SubtargetFeature.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" @@ -284,7 +285,7 @@ void SubtargetFeatures::print(raw_ostream &OS) const { #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) /// dump - Dump feature info. /// -void SubtargetFeatures::dump() const { +LLVM_DUMP_METHOD void SubtargetFeatures::dump() const { print(dbgs()); } #endif diff --git a/gnu/llvm/lib/MC/WinCOFFObjectWriter.cpp b/gnu/llvm/lib/MC/WinCOFFObjectWriter.cpp index a76cbdbd544..f316a5af387 100644 --- a/gnu/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/gnu/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -109,7 +109,6 @@ public: relocations Relocations; COFFSection(StringRef name); - static size_t size(); }; class WinCOFFObjectWriter : public MCObjectWriter { @@ -155,6 +154,8 @@ public: object_t *createCOFFEntity(StringRef Name, list_t &List); void defineSection(MCSectionCOFF const &Sec); + + COFFSymbol *getLinkedSymbol(const MCSymbol &Symbol); void DefineSymbol(const MCSymbol &Symbol, MCAssembler &Assembler, const MCAsmLayout &Layout); @@ -222,8 +223,6 @@ COFFSection::COFFSection(StringRef name) memset(&Header, 0, sizeof(Header)); } -size_t COFFSection::size() { return COFF::SectionSize; } - //------------------------------------------------------------------------------ // WinCOFFObjectWriter class implementation @@ -353,34 +352,52 @@ static uint64_t getSymbolValue(const MCSymbol &Symbol, return Res; } +COFFSymbol *WinCOFFObjectWriter::getLinkedSymbol(const MCSymbol &Symbol) { + if (!Symbol.isVariable()) + return nullptr; + + const MCSymbolRefExpr *SymRef = + dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue()); + if (!SymRef) + return nullptr; + + const MCSymbol &Aliasee = SymRef->getSymbol(); + if (!Aliasee.isUndefined()) + return nullptr; + return GetOrCreateCOFFSymbol(&Aliasee); +} + /// This function takes a symbol data object from the assembler /// and creates the associated COFF symbol staging object. void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &Symbol, MCAssembler &Assembler, const MCAsmLayout &Layout) { COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&Symbol); + const MCSymbol *Base = Layout.getBaseSymbol(Symbol); + COFFSection *Sec = nullptr; + if (Base && Base->getFragment()) { + Sec = SectionMap[Base->getFragment()->getParent()]; + if (coff_symbol->Section && coff_symbol->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 (Symbol.isVariable()) { - const MCSymbolRefExpr *SymRef = - dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue()); - - if (!SymRef) - report_fatal_error("Weak externals may only alias symbols"); - - coff_symbol->Other = GetOrCreateCOFFSymbol(&SymRef->getSymbol()); - } else { + COFFSymbol *WeakDefault = getLinkedSymbol(Symbol); + if (!WeakDefault) { std::string WeakName = (".weak." + Symbol.getName() + ".default").str(); - COFFSymbol *WeakDefault = createSymbol(WeakName); - WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; - WeakDefault->Data.StorageClass = COFF::IMAGE_SYM_CLASS_EXTERNAL; - WeakDefault->Data.Type = 0; - WeakDefault->Data.Value = 0; - coff_symbol->Other = WeakDefault; + WeakDefault = createSymbol(WeakName); + if (!Sec) + WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; + else + WeakDefault->Section = Sec; + Local = WeakDefault; } + coff_symbol->Other = WeakDefault; + // Setup the Weak External auxiliary symbol. coff_symbol->Aux.resize(1); memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0])); @@ -388,47 +405,37 @@ void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &Symbol, coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0; coff_symbol->Aux[0].Aux.WeakExternal.Characteristics = COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY; - - coff_symbol->MC = &Symbol; } else { - const MCSymbol *Base = Layout.getBaseSymbol(Symbol); - coff_symbol->Data.Value = getSymbolValue(Symbol, Layout); + if (!Base) + coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; + else + coff_symbol->Section = Sec; + Local = coff_symbol; + } + + if (Local) { + Local->Data.Value = getSymbolValue(Symbol, Layout); const MCSymbolCOFF &SymbolCOFF = cast<MCSymbolCOFF>(Symbol); - coff_symbol->Data.Type = SymbolCOFF.getType(); - coff_symbol->Data.StorageClass = SymbolCOFF.getClass(); + Local->Data.Type = SymbolCOFF.getType(); + Local->Data.StorageClass = SymbolCOFF.getClass(); // If no storage class was specified in the streamer, define it here. - if (coff_symbol->Data.StorageClass == COFF::IMAGE_SYM_CLASS_NULL) { + if (Local->Data.StorageClass == COFF::IMAGE_SYM_CLASS_NULL) { bool IsExternal = Symbol.isExternal() || (!Symbol.getFragment() && !Symbol.isVariable()); - coff_symbol->Data.StorageClass = IsExternal - ? COFF::IMAGE_SYM_CLASS_EXTERNAL - : COFF::IMAGE_SYM_CLASS_STATIC; - } - - if (!Base) { - coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; - } else { - if (Base->getFragment()) { - COFFSection *Sec = SectionMap[Base->getFragment()->getParent()]; - - if (coff_symbol->Section && coff_symbol->Section != Sec) - report_fatal_error("conflicting sections for symbol"); - - coff_symbol->Section = Sec; - } + Local->Data.StorageClass = IsExternal ? COFF::IMAGE_SYM_CLASS_EXTERNAL + : COFF::IMAGE_SYM_CLASS_STATIC; } - - coff_symbol->MC = &Symbol; } + + coff_symbol->MC = &Symbol; } // Maximum offsets for different string table entry encodings. -static const unsigned Max6DecimalOffset = 999999; -static const unsigned Max7DecimalOffset = 9999999; -static const uint64_t MaxBase64Offset = 0xFFFFFFFFFULL; // 64^6, including 0 +enum : unsigned { Max7DecimalOffset = 9999999U }; +enum : uint64_t { MaxBase64Offset = 0xFFFFFFFFFULL }; // 64^6, including 0 // Encode a string table entry offset in base 64, padded to 6 chars, and // prefixed with a double slash: '//AAAAAA', '//AAAAAB', ... @@ -456,22 +463,21 @@ void WinCOFFObjectWriter::SetSectionName(COFFSection &S) { if (S.Name.size() > COFF::NameSize) { uint64_t StringTableEntry = Strings.getOffset(S.Name); - if (StringTableEntry <= Max6DecimalOffset) { - std::sprintf(S.Header.Name, "/%d", unsigned(StringTableEntry)); - } else if (StringTableEntry <= Max7DecimalOffset) { - // With seven digits, we have to skip the terminating null. Because - // sprintf always appends it, we use a larger temporary buffer. - char buffer[9] = {}; - std::sprintf(buffer, "/%d", unsigned(StringTableEntry)); - std::memcpy(S.Header.Name, buffer, 8); + 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 + } else { std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size()); + } } void WinCOFFObjectWriter::SetSymbolName(COFFSymbol &S) { @@ -530,48 +536,47 @@ void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol &S) { void WinCOFFObjectWriter::WriteAuxiliarySymbols( const COFFSymbol::AuxiliarySymbols &S) { - for (COFFSymbol::AuxiliarySymbols::const_iterator i = S.begin(), e = S.end(); - i != e; ++i) { - switch (i->AuxType) { + for (const AuxSymbol &i : S) { + switch (i.AuxType) { case ATFunctionDefinition: - writeLE32(i->Aux.FunctionDefinition.TagIndex); - writeLE32(i->Aux.FunctionDefinition.TotalSize); - writeLE32(i->Aux.FunctionDefinition.PointerToLinenumber); - writeLE32(i->Aux.FunctionDefinition.PointerToNextFunction); - WriteZeros(sizeof(i->Aux.FunctionDefinition.unused)); + writeLE32(i.Aux.FunctionDefinition.TagIndex); + writeLE32(i.Aux.FunctionDefinition.TotalSize); + writeLE32(i.Aux.FunctionDefinition.PointerToLinenumber); + writeLE32(i.Aux.FunctionDefinition.PointerToNextFunction); + WriteZeros(sizeof(i.Aux.FunctionDefinition.unused)); if (UseBigObj) WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size); break; case ATbfAndefSymbol: - WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused1)); - writeLE16(i->Aux.bfAndefSymbol.Linenumber); - WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused2)); - writeLE32(i->Aux.bfAndefSymbol.PointerToNextFunction); - WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused3)); + WriteZeros(sizeof(i.Aux.bfAndefSymbol.unused1)); + writeLE16(i.Aux.bfAndefSymbol.Linenumber); + WriteZeros(sizeof(i.Aux.bfAndefSymbol.unused2)); + writeLE32(i.Aux.bfAndefSymbol.PointerToNextFunction); + WriteZeros(sizeof(i.Aux.bfAndefSymbol.unused3)); if (UseBigObj) WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size); break; case ATWeakExternal: - writeLE32(i->Aux.WeakExternal.TagIndex); - writeLE32(i->Aux.WeakExternal.Characteristics); - WriteZeros(sizeof(i->Aux.WeakExternal.unused)); + writeLE32(i.Aux.WeakExternal.TagIndex); + writeLE32(i.Aux.WeakExternal.Characteristics); + WriteZeros(sizeof(i.Aux.WeakExternal.unused)); if (UseBigObj) WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size); break; case ATFile: writeBytes( - StringRef(reinterpret_cast<const char *>(&i->Aux), + StringRef(reinterpret_cast<const char *>(&i.Aux), UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size)); break; case ATSectionDefinition: - writeLE32(i->Aux.SectionDefinition.Length); - writeLE16(i->Aux.SectionDefinition.NumberOfRelocations); - writeLE16(i->Aux.SectionDefinition.NumberOfLinenumbers); - writeLE32(i->Aux.SectionDefinition.CheckSum); - writeLE16(static_cast<int16_t>(i->Aux.SectionDefinition.Number)); - write8(i->Aux.SectionDefinition.Selection); - WriteZeros(sizeof(i->Aux.SectionDefinition.unused)); - writeLE16(static_cast<int16_t>(i->Aux.SectionDefinition.Number >> 16)); + writeLE32(i.Aux.SectionDefinition.Length); + writeLE16(i.Aux.SectionDefinition.NumberOfRelocations); + writeLE16(i.Aux.SectionDefinition.NumberOfLinenumbers); + writeLE32(i.Aux.SectionDefinition.CheckSum); + writeLE16(static_cast<int16_t>(i.Aux.SectionDefinition.Number)); + write8(i.Aux.SectionDefinition.Selection); + WriteZeros(sizeof(i.Aux.SectionDefinition.unused)); + writeLE16(static_cast<int16_t>(i.Aux.SectionDefinition.Number >> 16)); if (UseBigObj) WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size); break; @@ -787,6 +792,10 @@ void WinCOFFObjectWriter::recordRelocation( } } + // The fixed value never makes sense for section indicies, ignore it. + if (Fixup.getKind() == FK_SecRel_2) + FixedValue = 0; + if (TargetObjectWriter->recordRelocation(Fixup)) coff_section->Relocations.push_back(Reloc); } @@ -924,7 +933,7 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm, if (IsPhysicalSection(Sec)) { // Align the section data to a four byte boundary. - offset = RoundUpToAlignment(offset, 4); + offset = alignTo(offset, 4); Sec->Header.PointerToRawData = offset; offset += Sec->Header.SizeOfRawData; diff --git a/gnu/llvm/lib/MC/WinCOFFStreamer.cpp b/gnu/llvm/lib/MC/WinCOFFStreamer.cpp index a38b1a41a9b..5c6407ef1e5 100644 --- a/gnu/llvm/lib/MC/WinCOFFStreamer.cpp +++ b/gnu/llvm/lib/MC/WinCOFFStreamer.cpp @@ -75,7 +75,8 @@ void MCWinCOFFStreamer::InitSections(bool NoExecStack) { SwitchSection(getContext().getObjectFileInfo()->getTextSection()); } -void MCWinCOFFStreamer::EmitLabel(MCSymbol *Symbol) { +void MCWinCOFFStreamer::EmitLabel(MCSymbol *S) { + auto *Symbol = cast<MCSymbolCOFF>(S); assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); MCObjectStreamer::EmitLabel(Symbol); } @@ -88,25 +89,23 @@ void MCWinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) { llvm_unreachable("not implemented"); } -bool MCWinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, +bool MCWinCOFFStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) { - assert(Symbol && "Symbol must be non-null!"); - assert((!Symbol->isInSection() || - Symbol->getSection().getVariant() == MCSection::SV_COFF) && - "Got non-COFF section in the COFF backend!"); - + auto *Symbol = cast<MCSymbolCOFF>(S); getAssembler().registerSymbol(*Symbol); switch (Attribute) { default: return false; case MCSA_WeakReference: case MCSA_Weak: - cast<MCSymbolCOFF>(Symbol)->setIsWeakExternal(); + Symbol->setIsWeakExternal(); Symbol->setExternal(true); break; case MCSA_Global: Symbol->setExternal(true); break; + case MCSA_AltEntry: + llvm_unreachable("COFF doesn't support the .alt_entry attribute"); } return true; @@ -116,11 +115,8 @@ void MCWinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { llvm_unreachable("not implemented"); } -void MCWinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *Symbol) { - assert((!Symbol->isInSection() || - Symbol->getSection().getVariant() == MCSection::SV_COFF) && - "Got non-COFF section in the COFF backend!"); - +void MCWinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *S) { + auto *Symbol = cast<MCSymbolCOFF>(S); if (CurSymbol) Error("starting a new symbol definition without completing the " "previous one"); @@ -207,11 +203,9 @@ void MCWinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) { DF->getContents().resize(DF->getContents().size() + 4, 0); } -void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, +void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size, unsigned ByteAlignment) { - assert((!Symbol->isInSection() || - Symbol->getSection().getVariant() == MCSection::SV_COFF) && - "Got non-COFF section in the COFF backend!"); + auto *Symbol = cast<MCSymbolCOFF>(S); const Triple &T = getContext().getObjectFileInfo()->getTargetTriple(); if (T.isKnownWindowsMSVCEnvironment()) { @@ -241,9 +235,9 @@ void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, } } -void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, +void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size, unsigned ByteAlignment) { - assert(!Symbol->isInSection() && "Symbol must not already have a section!"); + auto *Symbol = cast<MCSymbolCOFF>(S); MCSection *Section = getContext().getObjectFileInfo()->getBSSSection(); getAssembler().registerSection(*Section); @@ -258,7 +252,7 @@ void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, ByteAlignment, Section); MCFillFragment *Fragment = new MCFillFragment( - /*Value=*/0, /*ValueSize=*/0, Size, Section); + /*Value=*/0, Size, Section); Symbol->setFragment(Fragment); } |