diff options
author | dim <dim@FreeBSD.org> | 2016-12-26 20:36:37 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2016-12-26 20:36:37 +0000 |
commit | 06210ae42d418d50d8d9365d5c9419308ae9e7ee (patch) | |
tree | ab60b4cdd6e430dda1f292a46a77ddb744723f31 /contrib/llvm/lib/MC | |
parent | 2dd166267f53df1c3748b4325d294b9b839de74b (diff) | |
download | FreeBSD-src-06210ae42d418d50d8d9365d5c9419308ae9e7ee.zip FreeBSD-src-06210ae42d418d50d8d9365d5c9419308ae9e7ee.tar.gz |
MFC r309124:
Upgrade our copies of clang, llvm, lldb, compiler-rt and libc++ to 3.9.0
release, and add lld 3.9.0. Also completely revamp the build system for
clang, llvm, lldb and their related tools.
Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11
support to build; see UPDATING for more information.
Release notes for llvm, clang and lld are available here:
<http://llvm.org/releases/3.9.0/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.9.0/tools/clang/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.9.0/tools/lld/docs/ReleaseNotes.html>
Thanks to Ed Maste, Bryan Drewery, Andrew Turner, Antoine Brodin and Jan
Beich for their help.
Relnotes: yes
MFC r309147:
Pull in r282174 from upstream llvm trunk (by Krzysztof Parzyszek):
[PPC] Set SP after loading data from stack frame, if no red zone is
present
Follow-up to r280705: Make sure that the SP is only restored after
all data is loaded from the stack frame, if there is no red zone.
This completes the fix for
https://llvm.org/bugs/show_bug.cgi?id=26519.
Differential Revision: https://reviews.llvm.org/D24466
Reported by: Mark Millard
PR: 214433
MFC r309149:
Pull in r283060 from upstream llvm trunk (by Hal Finkel):
[PowerPC] Refactor soft-float support, and enable PPC64 soft float
This change enables soft-float for PowerPC64, and also makes
soft-float disable all vector instruction sets for both 32-bit and
64-bit modes. This latter part is necessary because the PPC backend
canonicalizes many Altivec vector types to floating-point types, and
so soft-float breaks scalarization support for many operations. Both
for embedded targets and for operating-system kernels desiring
soft-float support, it seems reasonable that disabling hardware
floating-point also disables vector instructions (embedded targets
without hardware floating point support are unlikely to have Altivec,
etc. and operating system kernels desiring not to use floating-point
registers to lower syscall cost are unlikely to want to use vector
registers either). If someone needs this to work, we'll need to
change the fact that we promote many Altivec operations to act on
v4f32. To make it possible to disable Altivec when soft-float is
enabled, hardware floating-point support needs to be expressed as a
positive feature, like the others, and not a negative feature,
because target features cannot have dependencies on the disabling of
some other feature. So +soft-float has now become -hard-float.
Fixes PR26970.
Pull in r283061 from upstream clang trunk (by Hal Finkel):
[PowerPC] Enable soft-float for PPC64, and +soft-float -> -hard-float
Enable soft-float support on PPC64, as the backend now supports it.
Also, the backend now uses -hard-float instead of +soft-float, so set
the target features accordingly.
Fixes PR26970.
Reported by: Mark Millard
PR: 214433
MFC r309212:
Add a few missed clang 3.9.0 files to OptionalObsoleteFiles.
MFC r309262:
Fix packaging for clang, lldb and lld 3.9.0
During the upgrade of clang/llvm etc to 3.9.0 in r309124, the PACKAGE
directive in the usr.bin/clang/*.mk files got dropped accidentally.
Restore it, with a few minor changes and additions:
* Correct license in clang.ucl to NCSA
* Add PACKAGE=clang for clang and most of the "ll" tools
* Put lldb in its own package
* Put lld in its own package
Reviewed by: gjb, jmallett
Differential Revision: https://reviews.freebsd.org/D8666
MFC r309656:
During the bootstrap phase, when building the minimal llvm library on
PowerPC, add lib/Support/Atomic.cpp. This is needed because upstream
llvm revision r271821 disabled the use of std::call_once, which causes
some fallback functions from Atomic.cpp to be used instead.
Reported by: Mark Millard
PR: 214902
MFC r309835:
Tentatively apply https://reviews.llvm.org/D18730 to work around gcc PR
70528 (bogus error: constructor required before non-static data member).
This should fix buildworld with the external gcc package.
Reported by: https://jenkins.freebsd.org/job/FreeBSD_HEAD_amd64_gcc/
MFC r310194:
Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to
3.9.1 release.
Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11
support to build; see UPDATING for more information.
Release notes for llvm, clang and lld will be available here:
<http://releases.llvm.org/3.9.1/docs/ReleaseNotes.html>
<http://releases.llvm.org/3.9.1/tools/clang/docs/ReleaseNotes.html>
<http://releases.llvm.org/3.9.1/tools/lld/docs/ReleaseNotes.html>
Relnotes: yes
Diffstat (limited to 'contrib/llvm/lib/MC')
48 files changed, 2600 insertions, 1360 deletions
diff --git a/contrib/llvm/lib/MC/ConstantPools.cpp b/contrib/llvm/lib/MC/ConstantPools.cpp index 9643b75..17a23d0 100644 --- a/contrib/llvm/lib/MC/ConstantPools.cpp +++ b/contrib/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/contrib/llvm/lib/MC/ELFObjectWriter.cpp b/contrib/llvm/lib/MC/ELFObjectWriter.cpp index e6552be..dc21b48 100644 --- a/contrib/llvm/lib/MC/ELFObjectWriter.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCAsmBackend.cpp b/contrib/llvm/lib/MC/MCAsmBackend.cpp index fcf139b..b868b9d 100644 --- a/contrib/llvm/lib/MC/MCAsmBackend.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCAsmInfo.cpp b/contrib/llvm/lib/MC/MCAsmInfo.cpp index 36e10b3..4a05175 100644 --- a/contrib/llvm/lib/MC/MCAsmInfo.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp b/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp index ae9486d..fc60313 100644 --- a/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCAsmInfoELF.cpp b/contrib/llvm/lib/MC/MCAsmInfoELF.cpp index 2bff6e0..26e5608 100644 --- a/contrib/llvm/lib/MC/MCAsmInfoELF.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCAsmStreamer.cpp b/contrib/llvm/lib/MC/MCAsmStreamer.cpp index c99ce77..ef2f781 100644 --- a/contrib/llvm/lib/MC/MCAsmStreamer.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCAssembler.cpp b/contrib/llvm/lib/MC/MCAssembler.cpp index 15e82fa..7a42108 100644 --- a/contrib/llvm/lib/MC/MCAssembler.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCCodeGenInfo.cpp b/contrib/llvm/lib/MC/MCCodeGenInfo.cpp deleted file mode 100644 index 347ec2c..0000000 --- a/contrib/llvm/lib/MC/MCCodeGenInfo.cpp +++ /dev/null @@ -1,23 +0,0 @@ -//===-- MCCodeGenInfo.cpp - Target CodeGen Info -----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file tracks information about the target which can affect codegen, -// asm parsing, and asm printing. For example, relocation model. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCCodeGenInfo.h" -using namespace llvm; - -void MCCodeGenInfo::initMCCodeGenInfo(Reloc::Model RM, CodeModel::Model CM, - CodeGenOpt::Level OL) { - RelocationModel = RM; - CMModel = CM; - OptLevel = OL; -} diff --git a/contrib/llvm/lib/MC/MCCodeView.cpp b/contrib/llvm/lib/MC/MCCodeView.cpp new file mode 100644 index 0000000..65cff41 --- /dev/null +++ b/contrib/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/contrib/llvm/lib/MC/MCContext.cpp b/contrib/llvm/lib/MC/MCContext.cpp index b5ad518..47ed1ca 100644 --- a/contrib/llvm/lib/MC/MCContext.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp index 82063fb..21e8748 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h index 46d0c4c..25d17da 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h +++ b/contrib/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/contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp b/contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp index 1084e5e..3a4f738 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp b/contrib/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp index 5fc2ca4..1969c5d 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp b/contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp index 43005e7..1612562 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCSymbolizer.cpp b/contrib/llvm/lib/MC/MCDisassembler/MCSymbolizer.cpp index 4080e40..c0f707d 100644 --- a/contrib/llvm/lib/MC/MCSymbolizer.cpp +++ b/contrib/llvm/lib/MC/MCDisassembler/MCSymbolizer.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCSymbolizer.h" +#include "llvm/MC/MCDisassembler/MCSymbolizer.h" using namespace llvm; diff --git a/contrib/llvm/lib/MC/MCDwarf.cpp b/contrib/llvm/lib/MC/MCDwarf.cpp index dafa768..54b2c91 100644 --- a/contrib/llvm/lib/MC/MCDwarf.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCELFStreamer.cpp b/contrib/llvm/lib/MC/MCELFStreamer.cpp index 06d161b..7d858c3 100644 --- a/contrib/llvm/lib/MC/MCELFStreamer.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCExpr.cpp b/contrib/llvm/lib/MC/MCExpr.cpp index 748644b..6f90ff8 100644 --- a/contrib/llvm/lib/MC/MCExpr.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCFragment.cpp b/contrib/llvm/lib/MC/MCFragment.cpp index efdb704..1eb1d29 100644 --- a/contrib/llvm/lib/MC/MCFragment.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCInst.cpp b/contrib/llvm/lib/MC/MCInst.cpp index 5f829ae..16bc597 100644 --- a/contrib/llvm/lib/MC/MCInst.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCLabel.cpp b/contrib/llvm/lib/MC/MCLabel.cpp index 1d3022a..d973fc9 100644 --- a/contrib/llvm/lib/MC/MCLabel.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp b/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp index 5f6a579..f71fc78 100644 --- a/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCMachOStreamer.cpp b/contrib/llvm/lib/MC/MCMachOStreamer.cpp index 21f7571..45a4972 100644 --- a/contrib/llvm/lib/MC/MCMachOStreamer.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCObjectFileInfo.cpp b/contrib/llvm/lib/MC/MCObjectFileInfo.cpp index f86f7e4..d05bcea 100644 --- a/contrib/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCObjectStreamer.cpp b/contrib/llvm/lib/MC/MCObjectStreamer.cpp index 972610a..d2ac0f5 100644 --- a/contrib/llvm/lib/MC/MCObjectStreamer.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp b/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp index 36c1920..d56071a 100644 --- a/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCParser/AsmParser.cpp b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp index 646cbb4..1548aee 100644 --- a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp index a4b2b19..653627a 100644 --- a/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp index 73e068a..37515d9 100644 --- a/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp index 6cbcdec..47d19a8 100644 --- a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp b/contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp index e891bd2..d95cd12 100644 --- a/contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp index 290dcb2..dc7a3f0 100644 --- a/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp index 4e4b478..14a22c6 100644 --- a/contrib/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCRegisterInfo.cpp b/contrib/llvm/lib/MC/MCRegisterInfo.cpp index ce79cd5..c76bb64 100644 --- a/contrib/llvm/lib/MC/MCRegisterInfo.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCSection.cpp b/contrib/llvm/lib/MC/MCSection.cpp index dbd544a..32e4cce 100644 --- a/contrib/llvm/lib/MC/MCSection.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCStreamer.cpp b/contrib/llvm/lib/MC/MCStreamer.cpp index 836b405..6c8828f 100644 --- a/contrib/llvm/lib/MC/MCStreamer.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCSymbol.cpp b/contrib/llvm/lib/MC/MCSymbol.cpp index ab3b8eb..2ddece6 100644 --- a/contrib/llvm/lib/MC/MCSymbol.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCValue.cpp b/contrib/llvm/lib/MC/MCValue.cpp index 495a2b6..32a6adb 100644 --- a/contrib/llvm/lib/MC/MCValue.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCWin64EH.cpp b/contrib/llvm/lib/MC/MCWin64EH.cpp index 1b73b7a..fdc4c10 100644 --- a/contrib/llvm/lib/MC/MCWin64EH.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MCWinEH.cpp b/contrib/llvm/lib/MC/MCWinEH.cpp index 83af203..21a9139 100644 --- a/contrib/llvm/lib/MC/MCWinEH.cpp +++ b/contrib/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/contrib/llvm/lib/MC/MachObjectWriter.cpp b/contrib/llvm/lib/MC/MachObjectWriter.cpp index 324385f..e392719 100644 --- a/contrib/llvm/lib/MC/MachObjectWriter.cpp +++ b/contrib/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/contrib/llvm/lib/MC/StringTableBuilder.cpp b/contrib/llvm/lib/MC/StringTableBuilder.cpp index 80e5522..9d95952 100644 --- a/contrib/llvm/lib/MC/StringTableBuilder.cpp +++ b/contrib/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/contrib/llvm/lib/MC/SubtargetFeature.cpp b/contrib/llvm/lib/MC/SubtargetFeature.cpp index 7cce0fe..a97cd1d 100644 --- a/contrib/llvm/lib/MC/SubtargetFeature.cpp +++ b/contrib/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/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp b/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp index a76cbdb..f316a5a 100644 --- a/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/contrib/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/contrib/llvm/lib/MC/WinCOFFStreamer.cpp b/contrib/llvm/lib/MC/WinCOFFStreamer.cpp index a38b1a4..5c6407e 100644 --- a/contrib/llvm/lib/MC/WinCOFFStreamer.cpp +++ b/contrib/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); } diff --git a/contrib/llvm/lib/MC/YAML.cpp b/contrib/llvm/lib/MC/YAML.cpp deleted file mode 100644 index 067e91a..0000000 --- a/contrib/llvm/lib/MC/YAML.cpp +++ /dev/null @@ -1,65 +0,0 @@ -//===- YAML.cpp - YAMLIO utilities for object files -----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines utility classes for handling the YAML representation of -// object files. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/YAML.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Support/raw_ostream.h" -#include <cctype> - -using namespace llvm; - -void yaml::ScalarTraits<yaml::BinaryRef>::output( - const yaml::BinaryRef &Val, void *, llvm::raw_ostream &Out) { - Val.writeAsHex(Out); -} - -StringRef yaml::ScalarTraits<yaml::BinaryRef>::input(StringRef Scalar, void *, - yaml::BinaryRef &Val) { - if (Scalar.size() % 2 != 0) - return "BinaryRef hex string must contain an even number of nybbles."; - // TODO: Can we improve YAMLIO to permit a more accurate diagnostic here? - // (e.g. a caret pointing to the offending character). - for (unsigned I = 0, N = Scalar.size(); I != N; ++I) - if (!isxdigit(Scalar[I])) - return "BinaryRef hex string must contain only hex digits."; - Val = yaml::BinaryRef(Scalar); - return StringRef(); -} - -void yaml::BinaryRef::writeAsBinary(raw_ostream &OS) const { - if (!DataIsHexString) { - OS.write((const char *)Data.data(), Data.size()); - return; - } - for (unsigned I = 0, N = Data.size(); I != N; I += 2) { - uint8_t Byte; - StringRef((const char *)&Data[I], 2).getAsInteger(16, Byte); - OS.write(Byte); - } -} - -void yaml::BinaryRef::writeAsHex(raw_ostream &OS) const { - if (binary_size() == 0) - return; - if (DataIsHexString) { - OS.write((const char *)Data.data(), Data.size()); - return; - } - for (ArrayRef<uint8_t>::iterator I = Data.begin(), E = Data.end(); I != E; - ++I) { - uint8_t Byte = *I; - OS << hexdigit(Byte >> 4); - OS << hexdigit(Byte & 0xf); - } -} |