diff options
Diffstat (limited to 'contrib/llvm/lib/MC')
57 files changed, 5053 insertions, 4021 deletions
diff --git a/contrib/llvm/lib/MC/ConstantPools.cpp b/contrib/llvm/lib/MC/ConstantPools.cpp new file mode 100644 index 0000000..c4cea60 --- /dev/null +++ b/contrib/llvm/lib/MC/ConstantPools.cpp @@ -0,0 +1,98 @@ +//===- ConstantPools.cpp - ConstantPool class --*- C++ -*---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the ConstantPool and AssemblerConstantPools classes. +// +//===----------------------------------------------------------------------===// +#include "llvm/ADT/MapVector.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/ConstantPools.h" + +using namespace llvm; +// +// ConstantPool implementation +// +// Emit the contents of the constant pool using the provided streamer. +void ConstantPool::emitEntries(MCStreamer &Streamer) { + if (Entries.empty()) + return; + Streamer.EmitDataRegion(MCDR_DataRegion); + for (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); + } + Streamer.EmitDataRegion(MCDR_DataRegionEnd); + Entries.clear(); +} + +const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context, + unsigned Size) { + MCSymbol *CPEntryLabel = Context.CreateTempSymbol(); + + Entries.push_back(ConstantPoolEntry(CPEntryLabel, Value, Size)); + return MCSymbolRefExpr::Create(CPEntryLabel, Context); +} + +bool ConstantPool::empty() { return Entries.empty(); } + +// +// AssemblerConstantPools implementation +// +ConstantPool * +AssemblerConstantPools::getConstantPool(const MCSection *Section) { + ConstantPoolMapTy::iterator CP = ConstantPools.find(Section); + if (CP == ConstantPools.end()) + return nullptr; + + return &CP->second; +} + +ConstantPool & +AssemblerConstantPools::getOrCreateConstantPool(const MCSection *Section) { + return ConstantPools[Section]; +} + +static void emitConstantPool(MCStreamer &Streamer, const MCSection *Section, + ConstantPool &CP) { + if (!CP.empty()) { + Streamer.SwitchSection(Section); + CP.emitEntries(Streamer); + } +} + +void AssemblerConstantPools::emitAll(MCStreamer &Streamer) { + // Dump contents of assembler constant pools. + for (ConstantPoolMapTy::iterator CPI = ConstantPools.begin(), + CPE = ConstantPools.end(); + CPI != CPE; ++CPI) { + const MCSection *Section = CPI->first; + ConstantPool &CP = CPI->second; + + emitConstantPool(Streamer, Section, CP); + } +} + +void AssemblerConstantPools::emitForCurrentSection(MCStreamer &Streamer) { + const MCSection *Section = Streamer.getCurrentSection().first; + if (ConstantPool *CP = getConstantPool(Section)) { + emitConstantPool(Streamer, Section, *CP); + } +} + +const MCExpr *AssemblerConstantPools::addEntry(MCStreamer &Streamer, + const MCExpr *Expr, + unsigned Size) { + const MCSection *Section = Streamer.getCurrentSection().first; + return getOrCreateConstantPool(Section).addEntry(Expr, Streamer.getContext(), + Size); +} diff --git a/contrib/llvm/lib/MC/ELFObjectWriter.cpp b/contrib/llvm/lib/MC/ELFObjectWriter.cpp index 9899bb2..5779b27 100644 --- a/contrib/llvm/lib/MC/ELFObjectWriter.cpp +++ b/contrib/llvm/lib/MC/ELFObjectWriter.cpp @@ -12,12 +12,12 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCELFObjectWriter.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" #include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" @@ -28,7 +28,10 @@ #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCValue.h" +#include "llvm/MC/StringTableBuilder.h" +#include "llvm/Support/Compression.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" #include <vector> @@ -38,16 +41,76 @@ using namespace llvm; #define DEBUG_TYPE "reloc-info" namespace { +class FragmentWriter { + bool IsLittleEndian; + +public: + FragmentWriter(bool IsLittleEndian); + template <typename T> void write(MCDataFragment &F, T Val); +}; + +typedef DenseMap<const MCSectionELF *, uint32_t> SectionIndexMapTy; + +class SymbolTableWriter { + MCAssembler &Asm; + FragmentWriter &FWriter; + bool Is64Bit; + SectionIndexMapTy &SectionIndexMap; + + // The symbol .symtab fragment we are writting to. + MCDataFragment *SymtabF; + + // .symtab_shndx fragment we are writting to. + MCDataFragment *ShndxF; + + // The numbel of symbols written so far. + unsigned NumWritten; + + void createSymtabShndx(); + + template <typename T> void write(MCDataFragment &F, T Value); + +public: + SymbolTableWriter(MCAssembler &Asm, FragmentWriter &FWriter, bool Is64Bit, + SectionIndexMapTy &SectionIndexMap, + MCDataFragment *SymtabF); + + void writeSymbol(uint32_t name, uint8_t info, uint64_t value, uint64_t size, + uint8_t other, uint32_t shndx, bool Reserved); +}; + +struct ELFRelocationEntry { + uint64_t Offset; // Where is the relocation. + bool UseSymbol; // Relocate with a symbol, not the section. + union { + const MCSymbol *Symbol; // The symbol to relocate with. + const MCSectionData *Section; // The section to relocate with. + }; + unsigned Type; // The type of the relocation. + uint64_t Addend; // The addend to use. + + ELFRelocationEntry(uint64_t Offset, const MCSymbol *Symbol, unsigned Type, + uint64_t Addend) + : Offset(Offset), UseSymbol(true), Symbol(Symbol), Type(Type), + Addend(Addend) {} + + ELFRelocationEntry(uint64_t Offset, const MCSectionData *Section, + unsigned Type, uint64_t Addend) + : Offset(Offset), UseSymbol(false), Section(Section), Type(Type), + Addend(Addend) {} +}; + class ELFObjectWriter : public MCObjectWriter { + FragmentWriter FWriter; + protected: static bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind); static bool RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant); static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout); - static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data, + static bool isInSymtab(const MCAsmLayout &Layout, const MCSymbolData &Data, bool Used, bool Renamed); - static bool isLocal(const MCSymbolData &Data, bool isSignature, - bool isUsedInReloc); + static bool isLocal(const MCSymbolData &Data, bool isUsedInReloc); static bool IsELFMetaDataSection(const MCSectionData &SD); static uint64_t DataSectionSize(const MCSectionData &SD); static uint64_t GetSectionFileSize(const MCAsmLayout &Layout, @@ -70,30 +133,30 @@ class ELFObjectWriter : public MCObjectWriter { MCSymbolData *SymbolData; uint64_t StringIndex; uint32_t SectionIndex; + StringRef Name; // Support lexicographic sorting. bool operator<(const ELFSymbolData &RHS) const { - return SymbolData->getSymbol().getName() < - RHS.SymbolData->getSymbol().getName(); + return Name < RHS.Name; } }; /// The target specific ELF writer instance. - llvm::OwningPtr<MCELFObjectTargetWriter> TargetObjectWriter; + std::unique_ptr<MCELFObjectTargetWriter> TargetObjectWriter; SmallPtrSet<const MCSymbol *, 16> UsedInReloc; SmallPtrSet<const MCSymbol *, 16> WeakrefUsedInReloc; DenseMap<const MCSymbol *, const MCSymbol *> Renames; - llvm::DenseMap<const MCSectionData*, - std::vector<ELFRelocationEntry> > Relocations; - DenseMap<const MCSection*, uint64_t> SectionStringTableIndex; + llvm::DenseMap<const MCSectionData *, std::vector<ELFRelocationEntry>> + Relocations; + StringTableBuilder ShStrTabBuilder; /// @} /// @name Symbol Table Data /// @{ - SmallString<256> StringTable; + StringTableBuilder StrTabBuilder; std::vector<uint64_t> FileSymbolData; std::vector<ELFSymbolData> LocalSymbolData; std::vector<ELFSymbolData> ExternalSymbolData; @@ -103,8 +166,6 @@ class ELFObjectWriter : public MCObjectWriter { bool NeedsGOT; - bool NeedsSymtabShndx; - // This holds the symbol table index of the last local symbol. unsigned LastLocalSymbolIndex; // This holds the .strtab section index. @@ -115,45 +176,21 @@ class ELFObjectWriter : public MCObjectWriter { unsigned ShstrtabIndex; - const MCSymbol *SymbolToReloc(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const; - // TargetObjectWriter wrappers. - const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const { - return TargetObjectWriter->ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel); - } - const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, - const MCFixup &Fixup, - bool IsPCRel) const { - return TargetObjectWriter->undefinedExplicitRelSym(Target, Fixup, - IsPCRel); - } - bool is64Bit() const { return TargetObjectWriter->is64Bit(); } bool hasRelocationAddend() const { return TargetObjectWriter->hasRelocationAddend(); } unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, - bool IsPCRel, bool IsRelocWithSymbol, - int64_t Addend) const { - return TargetObjectWriter->GetRelocType(Target, Fixup, IsPCRel, - IsRelocWithSymbol, Addend); + bool IsPCRel) const { + return TargetObjectWriter->GetRelocType(Target, Fixup, IsPCRel); } public: - ELFObjectWriter(MCELFObjectTargetWriter *MOTW, - raw_ostream &_OS, bool IsLittleEndian) - : MCObjectWriter(_OS, IsLittleEndian), - TargetObjectWriter(MOTW), - NeedsGOT(false), NeedsSymtabShndx(false) { - } + ELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_ostream &_OS, + bool IsLittleEndian) + : MCObjectWriter(_OS, IsLittleEndian), FWriter(IsLittleEndian), + TargetObjectWriter(MOTW), NeedsGOT(false) {} virtual ~ELFObjectWriter(); @@ -164,96 +201,30 @@ class ELFObjectWriter : public MCObjectWriter { Write32(W); } - void StringLE16(char *buf, uint16_t Value) { - buf[0] = char(Value >> 0); - buf[1] = char(Value >> 8); - } - - void StringLE32(char *buf, uint32_t Value) { - StringLE16(buf, uint16_t(Value >> 0)); - StringLE16(buf + 2, uint16_t(Value >> 16)); - } - - void StringLE64(char *buf, uint64_t Value) { - StringLE32(buf, uint32_t(Value >> 0)); - StringLE32(buf + 4, uint32_t(Value >> 32)); - } - - void StringBE16(char *buf ,uint16_t Value) { - buf[0] = char(Value >> 8); - buf[1] = char(Value >> 0); - } - - void StringBE32(char *buf, uint32_t Value) { - StringBE16(buf, uint16_t(Value >> 16)); - StringBE16(buf + 2, uint16_t(Value >> 0)); - } - - void StringBE64(char *buf, uint64_t Value) { - StringBE32(buf, uint32_t(Value >> 32)); - StringBE32(buf + 4, uint32_t(Value >> 0)); - } - - void String8(MCDataFragment &F, uint8_t Value) { - char buf[1]; - buf[0] = Value; - F.getContents().append(&buf[0], &buf[1]); - } - - void String16(MCDataFragment &F, uint16_t Value) { - char buf[2]; - if (isLittleEndian()) - StringLE16(buf, Value); - else - StringBE16(buf, Value); - F.getContents().append(&buf[0], &buf[2]); - } - - void String32(MCDataFragment &F, uint32_t Value) { - char buf[4]; - if (isLittleEndian()) - StringLE32(buf, Value); - else - StringBE32(buf, Value); - F.getContents().append(&buf[0], &buf[4]); - } - - void String64(MCDataFragment &F, uint64_t Value) { - char buf[8]; - if (isLittleEndian()) - StringLE64(buf, Value); - else - StringBE64(buf, Value); - F.getContents().append(&buf[0], &buf[8]); + template <typename T> void write(MCDataFragment &F, T Value) { + FWriter.write(F, Value); } void WriteHeader(const MCAssembler &Asm, uint64_t SectionDataSize, unsigned NumberOfSections); - void WriteSymbolEntry(MCDataFragment *SymtabF, - MCDataFragment *ShndxF, - uint64_t name, uint8_t info, - uint64_t value, uint64_t size, - uint8_t other, uint32_t shndx, - bool Reserved); - - void WriteSymbol(MCDataFragment *SymtabF, MCDataFragment *ShndxF, - ELFSymbolData &MSD, + void WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD, const MCAsmLayout &Layout); - typedef DenseMap<const MCSectionELF*, uint32_t> SectionIndexMapTy; - void WriteSymbolTable(MCDataFragment *SymtabF, - MCDataFragment *ShndxF, - const MCAssembler &Asm, + void WriteSymbolTable(MCDataFragment *SymtabF, MCAssembler &Asm, const MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap); + SectionIndexMapTy &SectionIndexMap); + + bool shouldRelocateWithSymbol(const MCAssembler &Asm, + const MCSymbolRefExpr *RefA, + const MCSymbolData *SD, uint64_t C, + unsigned Type) const; - virtual void RecordRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, uint64_t &FixedValue); + void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, bool &IsPCRel, + uint64_t &FixedValue) override; uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm, const MCSymbol *S); @@ -267,13 +238,13 @@ class ELFObjectWriter : public MCObjectWriter { // Map from a section to its offset typedef DenseMap<const MCSectionELF*, uint64_t> SectionOffsetMapTy; - /// ComputeSymbolTable - Compute the symbol table data + /// 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. /// \param NumRegularSections - Number of non-relocation sections. - void ComputeSymbolTable(MCAssembler &Asm, + void computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, RevGroupMapTy RevGroupMap, unsigned NumRegularSections); @@ -285,6 +256,8 @@ class ELFObjectWriter : public MCObjectWriter { void CreateRelocationSections(MCAssembler &Asm, MCAsmLayout &Layout, RelMapTy &RelMap); + void CompressDebugSections(MCAssembler &Asm, MCAsmLayout &Layout); + void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout, const RelMapTy &RelMap); @@ -300,8 +273,8 @@ class ELFObjectWriter : public MCObjectWriter { SectionIndexMapTy &SectionIndexMap, const RelMapTy &RelMap); - virtual void ExecutePostLayoutBinding(MCAssembler &Asm, - const MCAsmLayout &Layout); + void ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) override; void WriteSectionHeader(MCAssembler &Asm, const GroupMapTy &GroupMap, const MCAsmLayout &Layout, @@ -320,14 +293,14 @@ class ELFObjectWriter : public MCObjectWriter { MCDataFragment *F, const MCSectionData *SD); - virtual bool + bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, const MCSymbolData &DataA, const MCFragment &FB, bool InSet, - bool IsPCRel) const; + bool IsPCRel) const override; - virtual void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); + void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; void WriteSection(MCAssembler &Asm, const SectionIndexMapTy &SectionIndexMap, uint32_t GroupSymbolIndex, @@ -336,6 +309,88 @@ class ELFObjectWriter : public MCObjectWriter { }; } +FragmentWriter::FragmentWriter(bool IsLittleEndian) + : IsLittleEndian(IsLittleEndian) {} + +template <typename T> void FragmentWriter::write(MCDataFragment &F, T Val) { + if (IsLittleEndian) + Val = support::endian::byte_swap<T, support::little>(Val); + else + Val = support::endian::byte_swap<T, support::big>(Val); + const char *Start = (const char *)&Val; + F.getContents().append(Start, Start + sizeof(T)); +} + +void SymbolTableWriter::createSymtabShndx() { + if (ShndxF) + return; + + MCContext &Ctx = Asm.getContext(); + const MCSectionELF *SymtabShndxSection = + Ctx.getELFSection(".symtab_shndxr", ELF::SHT_SYMTAB_SHNDX, 0, + SectionKind::getReadOnly(), 4, ""); + MCSectionData *SymtabShndxSD = + &Asm.getOrCreateSectionData(*SymtabShndxSection); + SymtabShndxSD->setAlignment(4); + ShndxF = new MCDataFragment(SymtabShndxSD); + unsigned Index = SectionIndexMap.size() + 1; + SectionIndexMap[SymtabShndxSection] = Index; + + for (unsigned I = 0; I < NumWritten; ++I) + write(*ShndxF, uint32_t(0)); +} + +template <typename T> +void SymbolTableWriter::write(MCDataFragment &F, T Value) { + FWriter.write(F, Value); +} + +SymbolTableWriter::SymbolTableWriter(MCAssembler &Asm, FragmentWriter &FWriter, + bool Is64Bit, + SectionIndexMapTy &SectionIndexMap, + MCDataFragment *SymtabF) + : Asm(Asm), FWriter(FWriter), Is64Bit(Is64Bit), + SectionIndexMap(SectionIndexMap), SymtabF(SymtabF), ShndxF(nullptr), + NumWritten(0) {} + +void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value, + uint64_t size, uint8_t other, + uint32_t shndx, bool Reserved) { + bool LargeIndex = shndx >= ELF::SHN_LORESERVE && !Reserved; + + if (LargeIndex) + createSymtabShndx(); + + if (ShndxF) { + if (LargeIndex) + write(*ShndxF, shndx); + else + write(*ShndxF, uint32_t(0)); + } + + uint16_t Index = LargeIndex ? uint16_t(ELF::SHN_XINDEX) : shndx; + + raw_svector_ostream OS(SymtabF->getContents()); + + if (Is64Bit) { + write(*SymtabF, name); // st_name + write(*SymtabF, info); // st_info + write(*SymtabF, other); // st_other + write(*SymtabF, Index); // st_shndx + write(*SymtabF, value); // st_value + write(*SymtabF, size); // st_size + } else { + write(*SymtabF, name); // st_name + write(*SymtabF, uint32_t(value)); // st_value + write(*SymtabF, uint32_t(size)); // st_size + write(*SymtabF, info); // st_info + write(*SymtabF, other); // st_other + write(*SymtabF, Index); // st_shndx + } + + ++NumWritten; +} + bool ELFObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) { const MCFixupKindInfo &FKI = Asm.getBackend().getFixupKindInfo((MCFixupKind) Kind); @@ -431,67 +486,19 @@ void ELFObjectWriter::WriteHeader(const MCAssembler &Asm, Write16(ShstrtabIndex); } -void ELFObjectWriter::WriteSymbolEntry(MCDataFragment *SymtabF, - MCDataFragment *ShndxF, - uint64_t name, - uint8_t info, uint64_t value, - uint64_t size, uint8_t other, - uint32_t shndx, - bool Reserved) { - if (ShndxF) { - if (shndx >= ELF::SHN_LORESERVE && !Reserved) - String32(*ShndxF, shndx); - else - String32(*ShndxF, 0); - } - - uint16_t Index = (shndx >= ELF::SHN_LORESERVE && !Reserved) ? - uint16_t(ELF::SHN_XINDEX) : shndx; - - if (is64Bit()) { - String32(*SymtabF, name); // st_name - String8(*SymtabF, info); // st_info - String8(*SymtabF, other); // st_other - String16(*SymtabF, Index); // st_shndx - String64(*SymtabF, value); // st_value - String64(*SymtabF, size); // st_size - } else { - String32(*SymtabF, name); // st_name - String32(*SymtabF, value); // st_value - String32(*SymtabF, size); // st_size - String8(*SymtabF, info); // st_info - String8(*SymtabF, other); // st_other - String16(*SymtabF, Index); // st_shndx - } -} - uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout) { if (Data.isCommon() && Data.isExternal()) return Data.getCommonAlignment(); - const MCSymbol &Symbol = Data.getSymbol(); - - if (Symbol.isAbsolute() && Symbol.isVariable()) { - if (const MCExpr *Value = Symbol.getVariableValue()) { - int64_t IntValue; - if (Value->EvaluateAsAbsolute(IntValue, Layout)) - return (uint64_t)IntValue; - } - } - - if (!Symbol.isInSection()) + uint64_t Res; + if (!Layout.getSymbolOffset(&Data, Res)) return 0; + if (Layout.getAssembler().isThumbFunc(&Data.getSymbol())) + Res |= 1; - if (Data.getFragment()) { - if (Data.getFlags() & ELF_Other_ThumbFunc) - return Layout.getSymbolOffset(&Data)+1; - else - return Layout.getSymbolOffset(&Data); - } - - return 0; + return Res; } void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, @@ -499,15 +506,17 @@ void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, // The presence of symbol versions causes undefined symbols and // versions declared with @@@ to be renamed. - for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), - ie = Asm.symbol_end(); it != ie; ++it) { - const MCSymbol &Alias = it->getSymbol(); - const MCSymbol &Symbol = Alias.AliasedSymbol(); - MCSymbolData &SD = Asm.getSymbolData(Symbol); + for (MCSymbolData &OriginalData : Asm.symbols()) { + const MCSymbol &Alias = OriginalData.getSymbol(); // Not an alias. - if (&Symbol == &Alias) + if (!Alias.isVariable()) continue; + auto *Ref = dyn_cast<MCSymbolRefExpr>(Alias.getVariableValue()); + if (!Ref) + continue; + const MCSymbol &Symbol = Ref->getSymbol(); + MCSymbolData &SD = Asm.getSymbolData(Symbol); StringRef AliasName = Alias.getName(); size_t Pos = AliasName.find('@'); @@ -516,8 +525,8 @@ void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, // Aliases defined with .symvar copy the binding from the symbol they alias. // This is the first place we are able to copy this information. - it->setExternal(SD.isExternal()); - MCELF::SetBinding(*it, MCELF::GetBinding(SD)); + OriginalData.setExternal(SD.isExternal()); + MCELF::SetBinding(OriginalData, MCELF::GetBinding(SD)); StringRef Rest = AliasName.substr(Pos); if (!Symbol.isUndefined() && !Rest.startswith("@@@")) @@ -532,35 +541,77 @@ void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, } } -void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF, - MCDataFragment *ShndxF, - ELFSymbolData &MSD, +static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType) { + uint8_t Type = newType; + + // Propagation rules: + // IFUNC > FUNC > OBJECT > NOTYPE + // TLS_OBJECT > OBJECT > NOTYPE + // + // dont let the new type degrade the old type + switch (origType) { + default: + break; + case ELF::STT_GNU_IFUNC: + if (Type == ELF::STT_FUNC || Type == ELF::STT_OBJECT || + Type == ELF::STT_NOTYPE || Type == ELF::STT_TLS) + Type = ELF::STT_GNU_IFUNC; + break; + case ELF::STT_FUNC: + if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE || + Type == ELF::STT_TLS) + Type = ELF::STT_FUNC; + break; + case ELF::STT_OBJECT: + if (Type == ELF::STT_NOTYPE) + Type = ELF::STT_OBJECT; + break; + case ELF::STT_TLS: + if (Type == ELF::STT_OBJECT || Type == ELF::STT_NOTYPE || + Type == ELF::STT_GNU_IFUNC || Type == ELF::STT_FUNC) + Type = ELF::STT_TLS; + break; + } + + return Type; +} + +void ELFObjectWriter::WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD, const MCAsmLayout &Layout) { MCSymbolData &OrigData = *MSD.SymbolData; - MCSymbolData &Data = - Layout.getAssembler().getSymbolData(OrigData.getSymbol().AliasedSymbol()); + assert((!OrigData.getFragment() || + (&OrigData.getFragment()->getParent()->getSection() == + &OrigData.getSymbol().getSection())) && + "The symbol's section doesn't match the fragment's symbol"); + const MCSymbol *Base = Layout.getBaseSymbol(OrigData.getSymbol()); - bool IsReserved = Data.isCommon() || Data.getSymbol().isAbsolute() || - Data.getSymbol().isVariable(); + // This has to be in sync with when computeSymbolTable uses SHN_ABS or + // SHN_COMMON. + bool IsReserved = !Base || OrigData.isCommon(); // Binding and Type share the same byte as upper and lower nibbles uint8_t Binding = MCELF::GetBinding(OrigData); - uint8_t Type = MCELF::GetType(Data); + uint8_t Type = MCELF::GetType(OrigData); + MCSymbolData *BaseSD = nullptr; + if (Base) { + BaseSD = &Layout.getAssembler().getSymbolData(*Base); + Type = mergeTypeForSet(Type, MCELF::GetType(*BaseSD)); + } uint8_t Info = (Binding << ELF_STB_Shift) | (Type << ELF_STT_Shift); // Other and Visibility share the same byte with Visibility using the lower // 2 bits uint8_t Visibility = MCELF::GetVisibility(OrigData); - uint8_t Other = MCELF::getOther(OrigData) << - (ELF_Other_Shift - ELF_STV_Shift); + uint8_t Other = MCELF::getOther(OrigData) << (ELF_STO_Shift - ELF_STV_Shift); Other |= Visibility; - uint64_t Value = SymbolValue(Data, Layout); + uint64_t Value = SymbolValue(OrigData, Layout); uint64_t Size = 0; - assert(!(Data.isCommon() && !Data.isExternal())); + const MCExpr *ESize = OrigData.getSize(); + if (!ESize && Base) + ESize = BaseSD->getSize(); - const MCExpr *ESize = Data.getSize(); if (ESize) { int64_t Res; if (!ESize->EvaluateAsAbsolute(Res, Layout)) @@ -569,28 +620,27 @@ void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF, } // Write out the symbol table entry - WriteSymbolEntry(SymtabF, ShndxF, MSD.StringIndex, Info, Value, - Size, Other, MSD.SectionIndex, IsReserved); + Writer.writeSymbol(MSD.StringIndex, Info, Value, Size, Other, + MSD.SectionIndex, IsReserved); } void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, - MCDataFragment *ShndxF, - const MCAssembler &Asm, + MCAssembler &Asm, const MCAsmLayout &Layout, - const SectionIndexMapTy &SectionIndexMap) { + SectionIndexMapTy &SectionIndexMap) { // The string table must be emitted first because we need the index // into the string table for all the symbol names. - assert(StringTable.size() && "Missing string table"); // FIXME: Make sure the start of the symbol table is aligned. + SymbolTableWriter Writer(Asm, FWriter, is64Bit(), SectionIndexMap, SymtabF); + // The first entry is the undefined symbol entry. - WriteSymbolEntry(SymtabF, ShndxF, 0, 0, 0, 0, 0, 0, false); + Writer.writeSymbol(0, 0, 0, 0, 0, 0, false); for (unsigned i = 0, e = FileSymbolData.size(); i != e; ++i) { - WriteSymbolEntry(SymtabF, ShndxF, FileSymbolData[i], - ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, - ELF::STV_DEFAULT, ELF::SHN_ABS, true); + Writer.writeSymbol(FileSymbolData[i], ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, + ELF::STV_DEFAULT, ELF::SHN_ABS, true); } // Write the symbol table entries. @@ -598,7 +648,7 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) { ELFSymbolData &MSD = LocalSymbolData[i]; - WriteSymbol(SymtabF, ShndxF, MSD, Layout); + WriteSymbol(Writer, MSD, Layout); } // Write out a symbol table entry for each regular section. @@ -612,9 +662,8 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, Section.getType() == ELF::SHT_SYMTAB || Section.getType() == ELF::SHT_SYMTAB_SHNDX) continue; - WriteSymbolEntry(SymtabF, ShndxF, 0, ELF::STT_SECTION, 0, 0, - ELF::STV_DEFAULT, SectionIndexMap.lookup(&Section), - false); + Writer.writeSymbol(0, ELF::STT_SECTION, 0, 0, ELF::STV_DEFAULT, + SectionIndexMap.lookup(&Section), false); LastLocalSymbolIndex++; } @@ -624,7 +673,7 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, assert(((Data.getFlags() & ELF_STB_Global) || (Data.getFlags() & ELF_STB_Weak)) && "External symbol requires STB_GLOBAL or STB_WEAK flag"); - WriteSymbol(SymtabF, ShndxF, MSD, Layout); + WriteSymbol(Writer, MSD, Layout); if (MCELF::GetBinding(Data) == ELF::STB_LOCAL) LastLocalSymbolIndex++; } @@ -632,162 +681,245 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) { ELFSymbolData &MSD = UndefinedSymbolData[i]; MCSymbolData &Data = *MSD.SymbolData; - WriteSymbol(SymtabF, ShndxF, MSD, Layout); + WriteSymbol(Writer, MSD, Layout); if (MCELF::GetBinding(Data) == ELF::STB_LOCAL) LastLocalSymbolIndex++; } } -const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const { - const MCSymbol &Symbol = Target.getSymA()->getSymbol(); - const MCSymbol &ASymbol = Symbol.AliasedSymbol(); - const MCSymbol *Renamed = Renames.lookup(&Symbol); - const MCSymbolData &SD = Asm.getSymbolData(Symbol); - - if (ASymbol.isUndefined()) { - if (Renamed) - return Renamed; - return undefinedExplicitRelSym(Target, Fixup, IsPCRel); - } +// It is always valid to create a relocation with a symbol. It is preferable +// to use a relocation with a section if that is possible. Using the section +// allows us to omit some local symbols from the symbol table. +bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm, + const MCSymbolRefExpr *RefA, + const MCSymbolData *SD, + uint64_t C, + unsigned Type) const { + // A PCRel relocation to an absolute value has no symbol (or section). We + // represent that with a relocation to a null section. + if (!RefA) + return false; - if (SD.isExternal()) { - if (Renamed) - return Renamed; - return &Symbol; - } + MCSymbolRefExpr::VariantKind Kind = RefA->getKind(); + switch (Kind) { + default: + break; + // The .odp creation emits a relocation against the symbol ".TOC." which + // create a R_PPC64_TOC relocation. However the relocation symbol name + // in final object creation should be NULL, since the symbol does not + // really exist, it is just the reference to TOC base for the current + // object file. Since the symbol is undefined, returning false results + // in a relocation with a null section which is the desired result. + case MCSymbolRefExpr::VK_PPC_TOCBASE: + return false; - const MCSectionELF &Section = - static_cast<const MCSectionELF&>(ASymbol.getSection()); - const SectionKind secKind = Section.getKind(); + // These VariantKind cause the relocation to refer to something other than + // the symbol itself, like a linker generated table. Since the address of + // symbol is not relevant, we cannot replace the symbol with the + // section and patch the difference in the addend. + case MCSymbolRefExpr::VK_GOT: + case MCSymbolRefExpr::VK_PLT: + case MCSymbolRefExpr::VK_GOTPCREL: + case MCSymbolRefExpr::VK_Mips_GOT: + case MCSymbolRefExpr::VK_PPC_GOT_LO: + case MCSymbolRefExpr::VK_PPC_GOT_HI: + case MCSymbolRefExpr::VK_PPC_GOT_HA: + return true; + } - if (secKind.isBSS()) - return ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel); + // An undefined symbol is not in any section, so the relocation has to point + // to the symbol itself. + const MCSymbol &Sym = SD->getSymbol(); + if (Sym.isUndefined()) + return true; - if (secKind.isThreadLocal()) { - if (Renamed) - return Renamed; - return &Symbol; + unsigned Binding = MCELF::GetBinding(*SD); + switch(Binding) { + default: + llvm_unreachable("Invalid Binding"); + case ELF::STB_LOCAL: + break; + case ELF::STB_WEAK: + // If the symbol is weak, it might be overridden by a symbol in another + // file. The relocation has to point to the symbol so that the linker + // can update it. + return true; + case ELF::STB_GLOBAL: + // Global ELF symbols can be preempted by the dynamic linker. The relocation + // has to point to the symbol for a reason analogous to the STB_WEAK case. + return true; } - MCSymbolRefExpr::VariantKind Kind = Target.getSymA()->getKind(); - const MCSectionELF &Sec2 = - static_cast<const MCSectionELF&>(F.getParent()->getSection()); - - if (&Sec2 != &Section && - (Kind == MCSymbolRefExpr::VK_PLT || - Kind == MCSymbolRefExpr::VK_GOTPCREL || - Kind == MCSymbolRefExpr::VK_GOTOFF)) { - if (Renamed) - return Renamed; - return &Symbol; - } + // If a relocation points to a mergeable section, we have to be careful. + // If the offset is zero, a relocation with the section will encode the + // same information. With a non-zero offset, the situation is different. + // For example, a relocation can point 42 bytes past the end of a string. + // If we change such a relocation to use the section, the linker would think + // that it pointed to another string and subtracting 42 at runtime will + // produce the wrong value. + auto &Sec = cast<MCSectionELF>(Sym.getSection()); + unsigned Flags = Sec.getFlags(); + if (Flags & ELF::SHF_MERGE) { + if (C != 0) + return true; - if (Section.getFlags() & ELF::SHF_MERGE) { - if (Target.getConstant() == 0) - return ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel); - if (Renamed) - return Renamed; - return &Symbol; + // It looks like gold has a bug (http://sourceware.org/PR16794) and can + // only handle section relocations to mergeable sections if using RELA. + if (!hasRelocationAddend()) + return true; } - return ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel); + // Most TLS relocations use a got, so they need the symbol. Even those that + // are just an offset (@tpoff), require a symbol in some linkers (gold, + // but not bfd ld). + if (Flags & ELF::SHF_TLS) + return true; + + // If the symbol is a thumb function the final relocation must set the lowest + // bit. With a symbol that is done by just having the symbol have that bit + // set, so we would lose the bit if we relocated with the section. + // FIXME: We could use the section but add the bit to the relocation value. + if (Asm.isThumbFunc(&Sym)) + return true; + if (TargetObjectWriter->needsRelocateWithSymbol(*SD, Type)) + return true; + return false; } +static const MCSymbol *getWeakRef(const MCSymbolRefExpr &Ref) { + const MCSymbol &Sym = Ref.getSymbol(); + + if (Ref.getKind() == MCSymbolRefExpr::VK_WEAKREF) + return &Sym; + + if (!Sym.isVariable()) + return nullptr; + + const MCExpr *Expr = Sym.getVariableValue(); + const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr); + if (!Inner) + return nullptr; + + if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) + return &Inner->getSymbol(); + return nullptr; +} void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, + bool &IsPCRel, uint64_t &FixedValue) { - int64_t Addend = 0; - int Index = 0; - int64_t Value = Target.getConstant(); - const MCSymbol *RelocSymbol = NULL; - - bool IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); - if (!Target.isAbsolute()) { - const MCSymbol &Symbol = Target.getSymA()->getSymbol(); - const MCSymbol &ASymbol = Symbol.AliasedSymbol(); - RelocSymbol = SymbolToReloc(Asm, Target, *Fragment, Fixup, IsPCRel); - - if (const MCSymbolRefExpr *RefB = Target.getSymB()) { - const MCSymbol &SymbolB = RefB->getSymbol(); - MCSymbolData &SDB = Asm.getSymbolData(SymbolB); - IsPCRel = true; - - // Offset of the symbol in the section - int64_t a = Layout.getSymbolOffset(&SDB); - - // Offset of the relocation in the section - int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); - Value += b - a; - } + const MCSectionData *FixupSection = Fragment->getParent(); + uint64_t C = Target.getConstant(); + uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + + if (const MCSymbolRefExpr *RefB = Target.getSymB()) { + assert(RefB->getKind() == MCSymbolRefExpr::VK_None && + "Should not have constructed this"); + + // Let A, B and C being the components of Target and R be the location of + // the fixup. If the fixup is not pcrel, we want to compute (A - B + C). + // If it is pcrel, we want to compute (A - B + C - R). + + // In general, ELF has no relocations for -B. It can only represent (A + C) + // or (A + C - R). If B = R + K and the relocation is not pcrel, we can + // replace B to implement it: (A - R - K + C) + if (IsPCRel) + Asm.getContext().FatalError( + Fixup.getLoc(), + "No relocation available to represent this relative expression"); + + const MCSymbol &SymB = RefB->getSymbol(); + + if (SymB.isUndefined()) + Asm.getContext().FatalError( + Fixup.getLoc(), + Twine("symbol '") + SymB.getName() + + "' can not be undefined in a subtraction expression"); + + assert(!SymB.isAbsolute() && "Should have been folded"); + const MCSection &SecB = SymB.getSection(); + if (&SecB != &FixupSection->getSection()) + Asm.getContext().FatalError( + Fixup.getLoc(), "Cannot represent a difference across sections"); + + const MCSymbolData &SymBD = Asm.getSymbolData(SymB); + uint64_t SymBOffset = Layout.getSymbolOffset(&SymBD); + uint64_t K = SymBOffset - FixupOffset; + IsPCRel = true; + C -= K; + } - if (!RelocSymbol) { - MCSymbolData &SD = Asm.getSymbolData(ASymbol); - MCFragment *F = SD.getFragment(); + // We either rejected the fixup or folded B into C at this point. + const MCSymbolRefExpr *RefA = Target.getSymA(); + const MCSymbol *SymA = RefA ? &RefA->getSymbol() : nullptr; + const MCSymbolData *SymAD = SymA ? &Asm.getSymbolData(*SymA) : nullptr; - if (F) { - Index = F->getParent()->getOrdinal() + 1; - // Offset of the symbol in the section - Value += Layout.getSymbolOffset(&SD); - } else { - Index = 0; - } - } else { - if (Asm.getSymbolData(Symbol).getFlags() & ELF_Other_Weakref) - WeakrefUsedInReloc.insert(RelocSymbol); - else - UsedInReloc.insert(RelocSymbol); - Index = -1; - } - Addend = Value; - if (hasRelocationAddend()) - Value = 0; + unsigned Type = GetRelocType(Target, Fixup, IsPCRel); + bool RelocateWithSymbol = shouldRelocateWithSymbol(Asm, RefA, SymAD, C, Type); + if (!RelocateWithSymbol && SymA && !SymA->isUndefined()) + C += Layout.getSymbolOffset(SymAD); + + uint64_t Addend = 0; + if (hasRelocationAddend()) { + Addend = C; + C = 0; } - FixedValue = Value; - unsigned Type = GetRelocType(Target, Fixup, IsPCRel, - (RelocSymbol != 0), Addend); - MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ? - MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); + FixedValue = C; + + // FIXME: What is this!?!? + MCSymbolRefExpr::VariantKind Modifier = + RefA ? RefA->getKind() : MCSymbolRefExpr::VK_None; if (RelocNeedsGOT(Modifier)) NeedsGOT = true; - uint64_t RelocOffset = Layout.getFragmentOffset(Fragment) + - Fixup.getOffset(); + if (!RelocateWithSymbol) { + const MCSection *SecA = + (SymA && !SymA->isUndefined()) ? &SymA->getSection() : nullptr; + const MCSectionData *SecAD = SecA ? &Asm.getSectionData(*SecA) : nullptr; + ELFRelocationEntry Rec(FixupOffset, SecAD, Type, Addend); + Relocations[FixupSection].push_back(Rec); + return; + } - if (!hasRelocationAddend()) - Addend = 0; + if (SymA) { + if (const MCSymbol *R = Renames.lookup(SymA)) + SymA = R; - if (is64Bit()) - assert(isInt<64>(Addend)); - else - assert(isInt<32>(Addend)); - - ELFRelocationEntry ERE(RelocOffset, Index, Type, RelocSymbol, Addend, Fixup); - Relocations[Fragment->getParent()].push_back(ERE); + if (const MCSymbol *WeakRef = getWeakRef(*RefA)) + WeakrefUsedInReloc.insert(WeakRef); + else + UsedInReloc.insert(SymA); + } + ELFRelocationEntry Rec(FixupOffset, SymA, Type, Addend); + Relocations[FixupSection].push_back(Rec); + return; } uint64_t ELFObjectWriter::getSymbolIndexInSymbolTable(const MCAssembler &Asm, const MCSymbol *S) { - MCSymbolData &SD = Asm.getSymbolData(*S); + const MCSymbolData &SD = Asm.getSymbolData(*S); return SD.getIndex(); } -bool ELFObjectWriter::isInSymtab(const MCAssembler &Asm, - const MCSymbolData &Data, - bool Used, bool Renamed) { - if (Data.getFlags() & ELF_Other_Weakref) - return false; +bool ELFObjectWriter::isInSymtab(const MCAsmLayout &Layout, + const MCSymbolData &Data, bool Used, + bool Renamed) { + const MCSymbol &Symbol = Data.getSymbol(); + if (Symbol.isVariable()) { + const MCExpr *Expr = Symbol.getVariableValue(); + if (const MCSymbolRefExpr *Ref = dyn_cast<MCSymbolRefExpr>(Expr)) { + if (Ref->getKind() == MCSymbolRefExpr::VK_WEAKREF) + return false; + } + } if (Used) return true; @@ -795,42 +927,35 @@ bool ELFObjectWriter::isInSymtab(const MCAssembler &Asm, if (Renamed) return false; - const MCSymbol &Symbol = Data.getSymbol(); - if (Symbol.getName() == "_GLOBAL_OFFSET_TABLE_") return true; - const MCSymbol &A = Symbol.AliasedSymbol(); - if (Symbol.isVariable() && !A.isVariable() && A.isUndefined()) - return false; + if (Symbol.isVariable()) { + const MCSymbol *Base = Layout.getBaseSymbol(Symbol); + if (Base && Base->isUndefined()) + return false; + } bool IsGlobal = MCELF::GetBinding(Data) == ELF::STB_GLOBAL; if (!Symbol.isVariable() && Symbol.isUndefined() && !IsGlobal) return false; - if (!Asm.isSymbolLinkerVisible(Symbol) && !Symbol.isUndefined()) - return false; - if (Symbol.isTemporary()) return false; return true; } -bool ELFObjectWriter::isLocal(const MCSymbolData &Data, bool isSignature, - bool isUsedInReloc) { +bool ELFObjectWriter::isLocal(const MCSymbolData &Data, bool isUsedInReloc) { if (Data.isExternal()) return false; const MCSymbol &Symbol = Data.getSymbol(); - const MCSymbol &RefSymbol = Symbol.AliasedSymbol(); - - if (RefSymbol.isUndefined() && !RefSymbol.isVariable()) { - if (isSignature && !isUsedInReloc) - return true; + if (Symbol.isDefined()) + return true; + if (isUsedInReloc) return false; - } return true; } @@ -863,10 +988,11 @@ void ELFObjectWriter::ComputeIndexMap(MCAssembler &Asm, } } -void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, - const SectionIndexMapTy &SectionIndexMap, - RevGroupMapTy RevGroupMap, - unsigned NumRegularSections) { +void +ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, + const SectionIndexMapTy &SectionIndexMap, + RevGroupMapTy RevGroupMap, + unsigned NumRegularSections) { // FIXME: Is this the correct place to do this? // FIXME: Why is an undefined reference to _GLOBAL_OFFSET_TABLE_ needed? if (NeedsGOT) { @@ -877,73 +1003,49 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, MCELF::SetBinding(Data, ELF::STB_GLOBAL); } - // Index 0 is always the empty string. - StringMap<uint64_t> StringIndexMap; - StringTable += '\x00'; - - // FIXME: We could optimize suffixes in strtab in the same way we - // optimize them in shstrtab. - - for (MCAssembler::const_file_name_iterator it = Asm.file_names_begin(), - ie = Asm.file_names_end(); - it != ie; - ++it) { - StringRef Name = *it; - uint64_t &Entry = StringIndexMap[Name]; - if (!Entry) { - Entry = StringTable.size(); - StringTable += Name; - StringTable += '\x00'; - } - FileSymbolData.push_back(Entry); - } - // Add the data for the symbols. - for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), - ie = Asm.symbol_end(); it != ie; ++it) { - const MCSymbol &Symbol = it->getSymbol(); + for (MCSymbolData &SD : Asm.symbols()) { + const MCSymbol &Symbol = SD.getSymbol(); bool Used = UsedInReloc.count(&Symbol); bool WeakrefUsed = WeakrefUsedInReloc.count(&Symbol); bool isSignature = RevGroupMap.count(&Symbol); - if (!isInSymtab(Asm, *it, + if (!isInSymtab(Layout, SD, Used || WeakrefUsed || isSignature, Renames.count(&Symbol))) continue; ELFSymbolData MSD; - MSD.SymbolData = it; - const MCSymbol &RefSymbol = Symbol.AliasedSymbol(); + MSD.SymbolData = &SD; + const MCSymbol *BaseSymbol = Layout.getBaseSymbol(Symbol); // Undefined symbols are global, but this is the first place we // are able to set it. - bool Local = isLocal(*it, isSignature, Used); - if (!Local && MCELF::GetBinding(*it) == ELF::STB_LOCAL) { - MCSymbolData &SD = Asm.getSymbolData(RefSymbol); - MCELF::SetBinding(*it, ELF::STB_GLOBAL); + bool Local = isLocal(SD, Used); + if (!Local && MCELF::GetBinding(SD) == ELF::STB_LOCAL) { + assert(BaseSymbol); + MCSymbolData &BaseData = Asm.getSymbolData(*BaseSymbol); MCELF::SetBinding(SD, ELF::STB_GLOBAL); + MCELF::SetBinding(BaseData, ELF::STB_GLOBAL); } - if (RefSymbol.isUndefined() && !Used && WeakrefUsed) - MCELF::SetBinding(*it, ELF::STB_WEAK); - - if (it->isCommon()) { + if (!BaseSymbol) { + MSD.SectionIndex = ELF::SHN_ABS; + } else if (SD.isCommon()) { assert(!Local); MSD.SectionIndex = ELF::SHN_COMMON; - } else if (Symbol.isAbsolute() || RefSymbol.isVariable()) { - MSD.SectionIndex = ELF::SHN_ABS; - } else if (RefSymbol.isUndefined()) { + } else if (BaseSymbol->isUndefined()) { if (isSignature && !Used) MSD.SectionIndex = SectionIndexMap.lookup(RevGroupMap[&Symbol]); else MSD.SectionIndex = ELF::SHN_UNDEF; + if (!Used && WeakrefUsed) + MCELF::SetBinding(SD, ELF::STB_WEAK); } else { const MCSectionELF &Section = - static_cast<const MCSectionELF&>(RefSymbol.getSection()); + static_cast<const MCSectionELF&>(BaseSymbol->getSection()); MSD.SectionIndex = SectionIndexMap.lookup(&Section); - if (MSD.SectionIndex >= ELF::SHN_LORESERVE) - NeedsSymtabShndx = true; assert(MSD.SectionIndex && "Invalid section index!"); } @@ -951,7 +1053,6 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, // @@ in defined ones. StringRef Name = Symbol.getName(); SmallString<32> Buf; - size_t Pos = Name.find("@@@"); if (Pos != StringRef::npos) { Buf += Name.substr(0, Pos); @@ -959,14 +1060,8 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, Buf += Name.substr(Pos + Skip); Name = Buf; } + MSD.Name = StrTabBuilder.add(Name); - uint64_t &Entry = StringIndexMap[Name]; - if (!Entry) { - Entry = StringTable.size(); - StringTable += Name; - StringTable += '\x00'; - } - MSD.StringIndex = Entry; if (MSD.SectionIndex == ELF::SHN_UNDEF) UndefinedSymbolData.push_back(MSD); else if (Local) @@ -975,6 +1070,21 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, ExternalSymbolData.push_back(MSD); } + for (auto i = Asm.file_names_begin(), e = Asm.file_names_end(); i != e; ++i) + StrTabBuilder.add(*i); + + StrTabBuilder.finalize(); + + for (auto i = Asm.file_names_begin(), e = Asm.file_names_end(); i != e; ++i) + FileSymbolData.push_back(StrTabBuilder.getOffset(*i)); + + for (ELFSymbolData& MSD : LocalSymbolData) + MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name); + for (ELFSymbolData& MSD : ExternalSymbolData) + MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name); + for (ELFSymbolData& MSD : UndefinedSymbolData) + MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name); + // Symbols are required to be in lexicographic order. array_pod_sort(LocalSymbolData.begin(), LocalSymbolData.end()); array_pod_sort(ExternalSymbolData.begin(), ExternalSymbolData.end()); @@ -992,9 +1102,6 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, ExternalSymbolData[i].SymbolData->setIndex(Index++); for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) UndefinedSymbolData[i].SymbolData->setIndex(Index++); - - if (Index >= ELF::SHN_LORESERVE) - NeedsSymtabShndx = true; } void ELFObjectWriter::CreateRelocationSections(MCAssembler &Asm, @@ -1037,6 +1144,151 @@ void ELFObjectWriter::CreateRelocationSections(MCAssembler &Asm, } } +static SmallVector<char, 128> +getUncompressedData(MCAsmLayout &Layout, + MCSectionData::FragmentListType &Fragments) { + SmallVector<char, 128> UncompressedData; + for (const MCFragment &F : Fragments) { + const SmallVectorImpl<char> *Contents; + switch (F.getKind()) { + case MCFragment::FT_Data: + Contents = &cast<MCDataFragment>(F).getContents(); + break; + case MCFragment::FT_Dwarf: + Contents = &cast<MCDwarfLineAddrFragment>(F).getContents(); + break; + case MCFragment::FT_DwarfFrame: + Contents = &cast<MCDwarfCallFrameFragment>(F).getContents(); + break; + default: + llvm_unreachable( + "Not expecting any other fragment types in a debug_* section"); + } + UncompressedData.append(Contents->begin(), Contents->end()); + } + return UncompressedData; +} + +// 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) { + static 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()); + return true; +} + +// Return a single fragment containing the compressed contents of the whole +// section. Null if the section was not compressed for any reason. +static std::unique_ptr<MCDataFragment> +getCompressedFragment(MCAsmLayout &Layout, + MCSectionData::FragmentListType &Fragments) { + std::unique_ptr<MCDataFragment> CompressedFragment(new MCDataFragment()); + + // Gather the uncompressed data from all the fragments, recording the + // alignment fragment, if seen, and any fixups. + SmallVector<char, 128> UncompressedData = + getUncompressedData(Layout, Fragments); + + SmallVectorImpl<char> &CompressedContents = CompressedFragment->getContents(); + + zlib::Status Success = zlib::compress( + StringRef(UncompressedData.data(), UncompressedData.size()), + CompressedContents); + if (Success != zlib::StatusOK) + return nullptr; + + if (!prependCompressionHeader(UncompressedData.size(), CompressedContents)) + return nullptr; + + return CompressedFragment; +} + +typedef DenseMap<const MCSectionData *, std::vector<MCSymbolData *>> +DefiningSymbolMap; + +static void UpdateSymbols(const MCAsmLayout &Layout, + const std::vector<MCSymbolData *> &Symbols, + MCFragment &NewFragment) { + for (MCSymbolData *Sym : Symbols) { + Sym->setOffset(Sym->getOffset() + + Layout.getFragmentOffset(Sym->getFragment())); + Sym->setFragment(&NewFragment); + } +} + +static void CompressDebugSection(MCAssembler &Asm, MCAsmLayout &Layout, + const DefiningSymbolMap &DefiningSymbols, + const MCSectionELF &Section, + MCSectionData &SD) { + StringRef SectionName = Section.getSectionName(); + MCSectionData::FragmentListType &Fragments = SD.getFragmentList(); + + std::unique_ptr<MCDataFragment> CompressedFragment = + getCompressedFragment(Layout, Fragments); + + // Leave the section as-is if the fragments could not be compressed. + if (!CompressedFragment) + return; + + // Update the fragment+offsets of any symbols referring to fragments in this + // section to refer to the new fragment. + auto I = DefiningSymbols.find(&SD); + if (I != DefiningSymbols.end()) + UpdateSymbols(Layout, I->second, *CompressedFragment); + + // Invalidate the layout for the whole section since it will have new and + // different fragments now. + Layout.invalidateFragmentsFrom(&Fragments.front()); + Fragments.clear(); + + // Complete the initialization of the new fragment + CompressedFragment->setParent(&SD); + CompressedFragment->setLayoutOrder(0); + Fragments.push_back(CompressedFragment.release()); + + // Rename from .debug_* to .zdebug_* + Asm.getContext().renameELFSection(&Section, + (".z" + SectionName.drop_front(1)).str()); +} + +void ELFObjectWriter::CompressDebugSections(MCAssembler &Asm, + MCAsmLayout &Layout) { + if (!Asm.getContext().getAsmInfo()->compressDebugSections()) + return; + + DefiningSymbolMap DefiningSymbols; + + for (MCSymbolData &SD : Asm.symbols()) + if (MCFragment *F = SD.getFragment()) + DefiningSymbols[F->getParent()].push_back(&SD); + + for (MCSectionData &SD : Asm) { + const MCSectionELF &Section = + static_cast<const MCSectionELF &>(SD.getSection()); + StringRef SectionName = Section.getSectionName(); + + // 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 (!SectionName.startswith(".debug_") || SectionName == ".debug_frame") + continue; + + CompressDebugSection(Asm, Layout, DefiningSymbols, Section, SD); + } +} + void ELFObjectWriter::WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout, const RelMapTy &RelMap) { for (MCAssembler::const_iterator it = Asm.begin(), @@ -1074,71 +1326,75 @@ void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, WriteWord(EntrySize); // sh_entsize } +// ELF doesn't require relocations to be in any order. We sort by the r_offset, +// just to match gnu as for easier comparison. The use type is an arbitrary way +// of making the sort deterministic. +static int cmpRel(const ELFRelocationEntry *AP, const ELFRelocationEntry *BP) { + const ELFRelocationEntry &A = *AP; + const ELFRelocationEntry &B = *BP; + if (A.Offset != B.Offset) + return B.Offset - A.Offset; + if (B.Type != A.Type) + return A.Type - B.Type; + llvm_unreachable("ELFRelocs might be unstable!"); +} + +static void sortRelocs(const MCAssembler &Asm, + std::vector<ELFRelocationEntry> &Relocs) { + array_pod_sort(Relocs.begin(), Relocs.end(), cmpRel); +} + void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm, MCDataFragment *F, const MCSectionData *SD) { std::vector<ELFRelocationEntry> &Relocs = Relocations[SD]; - // Sort the relocation entries. Most targets just sort by r_offset, but some - // (e.g., MIPS) have additional constraints. - TargetObjectWriter->sortRelocs(Asm, Relocs); + sortRelocs(Asm, Relocs); for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { - ELFRelocationEntry entry = Relocs[e - i - 1]; + const ELFRelocationEntry &Entry = Relocs[e - i - 1]; + + unsigned Index; + if (Entry.UseSymbol) { + Index = getSymbolIndexInSymbolTable(Asm, Entry.Symbol); + } else { + const MCSectionData *Sec = Entry.Section; + if (Sec) + Index = Sec->getOrdinal() + FileSymbolData.size() + + LocalSymbolData.size() + 1; + else + Index = 0; + } - if (!entry.Index) - ; - else if (entry.Index < 0) - entry.Index = getSymbolIndexInSymbolTable(Asm, entry.Symbol); - else - entry.Index += FileSymbolData.size() + LocalSymbolData.size(); if (is64Bit()) { - String64(*F, entry.r_offset); + write(*F, Entry.Offset); if (TargetObjectWriter->isN64()) { - String32(*F, entry.Index); + write(*F, uint32_t(Index)); - String8(*F, TargetObjectWriter->getRSsym(entry.Type)); - String8(*F, TargetObjectWriter->getRType3(entry.Type)); - String8(*F, TargetObjectWriter->getRType2(entry.Type)); - String8(*F, TargetObjectWriter->getRType(entry.Type)); - } - else { + write(*F, TargetObjectWriter->getRSsym(Entry.Type)); + write(*F, TargetObjectWriter->getRType3(Entry.Type)); + write(*F, TargetObjectWriter->getRType2(Entry.Type)); + write(*F, TargetObjectWriter->getRType(Entry.Type)); + } else { struct ELF::Elf64_Rela ERE64; - ERE64.setSymbolAndType(entry.Index, entry.Type); - String64(*F, ERE64.r_info); + ERE64.setSymbolAndType(Index, Entry.Type); + write(*F, ERE64.r_info); } if (hasRelocationAddend()) - String64(*F, entry.r_addend); + write(*F, Entry.Addend); } else { - String32(*F, entry.r_offset); + write(*F, uint32_t(Entry.Offset)); struct ELF::Elf32_Rela ERE32; - ERE32.setSymbolAndType(entry.Index, entry.Type); - String32(*F, ERE32.r_info); + ERE32.setSymbolAndType(Index, Entry.Type); + write(*F, ERE32.r_info); if (hasRelocationAddend()) - String32(*F, entry.r_addend); + write(*F, uint32_t(Entry.Addend)); } } } -static int compareBySuffix(const MCSectionELF *const *a, - const MCSectionELF *const *b) { - const StringRef &NameA = (*a)->getSectionName(); - const StringRef &NameB = (*b)->getSectionName(); - const unsigned sizeA = NameA.size(); - const unsigned sizeB = NameB.size(); - const unsigned len = std::min(sizeA, sizeB); - for (unsigned int i = 0; i < len; ++i) { - char ca = NameA[sizeA - i - 1]; - char cb = NameB[sizeB - i - 1]; - if (ca != cb) - return cb - ca; - } - - return sizeB - sizeA; -} - void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout, SectionIndexMapTy &SectionIndexMap, @@ -1162,16 +1418,6 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, MCSectionData &SymtabSD = Asm.getOrCreateSectionData(*SymtabSection); SymtabSD.setAlignment(is64Bit() ? 8 : 4); - MCSectionData *SymtabShndxSD = NULL; - - if (NeedsSymtabShndx) { - const MCSectionELF *SymtabShndxSection = - Ctx.getELFSection(".symtab_shndx", ELF::SHT_SYMTAB_SHNDX, 0, - SectionKind::getReadOnly(), 4, ""); - SymtabShndxSD = &Asm.getOrCreateSectionData(*SymtabShndxSection); - SymtabShndxSD->setAlignment(4); - } - const MCSectionELF *StrtabSection; StrtabSection = Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0, SectionKind::getReadOnly()); @@ -1186,52 +1432,23 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, // Symbol table F = new MCDataFragment(&SymtabSD); - MCDataFragment *ShndxF = NULL; - if (NeedsSymtabShndx) { - ShndxF = new MCDataFragment(SymtabShndxSD); - } - WriteSymbolTable(F, ShndxF, Asm, Layout, SectionIndexMap); + WriteSymbolTable(F, Asm, Layout, SectionIndexMap); F = new MCDataFragment(&StrtabSD); - F->getContents().append(StringTable.begin(), StringTable.end()); + F->getContents().append(StrTabBuilder.data().begin(), + StrTabBuilder.data().end()); F = new MCDataFragment(&ShstrtabSD); - std::vector<const MCSectionELF*> Sections; - for (MCAssembler::const_iterator it = Asm.begin(), - ie = Asm.end(); it != ie; ++it) { + // Section header string table. + for (auto it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { const MCSectionELF &Section = static_cast<const MCSectionELF&>(it->getSection()); - Sections.push_back(&Section); - } - array_pod_sort(Sections.begin(), Sections.end(), compareBySuffix); - - // Section header string table. - // - // The first entry of a string table holds a null character so skip - // section 0. - uint64_t Index = 1; - F->getContents().push_back('\x00'); - - for (unsigned int I = 0, E = Sections.size(); I != E; ++I) { - const MCSectionELF &Section = *Sections[I]; - - StringRef Name = Section.getSectionName(); - if (I != 0) { - StringRef PreviousName = Sections[I - 1]->getSectionName(); - if (PreviousName.endswith(Name)) { - SectionStringTableIndex[&Section] = Index - Name.size() - 1; - continue; - } - } - // Remember the index into the string table so we can write it - // into the sh_name field of the section header table. - SectionStringTableIndex[&Section] = Index; - - Index += Name.size() + 1; - F->getContents().append(Name.begin(), Name.end()); - F->getContents().push_back('\x00'); + ShStrTabBuilder.add(Section.getSectionName()); } + ShStrTabBuilder.finalize(); + F->getContents().append(ShStrTabBuilder.data().begin(), + ShStrTabBuilder.data().end()); } void ELFObjectWriter::CreateIndexedSections(MCAssembler &Asm, @@ -1265,7 +1482,7 @@ void ELFObjectWriter::CreateIndexedSections(MCAssembler &Asm, MCSectionData &Data = Asm.getOrCreateSectionData(*Group); Data.setAlignment(4); MCDataFragment *F = new MCDataFragment(&Data); - String32(*F, ELF::GRP_COMDAT); + write(*F, uint32_t(ELF::GRP_COMDAT)); } GroupMap[Group] = SignatureSymbol; } @@ -1283,8 +1500,8 @@ void ELFObjectWriter::CreateIndexedSections(MCAssembler &Asm, MCSectionData &Data = Asm.getOrCreateSectionData(*Group); // FIXME: we could use the previous fragment MCDataFragment *F = new MCDataFragment(&Data); - unsigned Index = SectionIndexMap.lookup(&Section); - String32(*F, Index); + uint32_t Index = SectionIndexMap.lookup(&Section); + write(*F, Index); } } @@ -1299,7 +1516,7 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, switch(Section.getType()) { case ELF::SHT_DYNAMIC: - sh_link = SectionStringTableIndex[&Section]; + sh_link = ShStrTabBuilder.getOffset(Section.getSectionName()); sh_info = 0; break; @@ -1348,6 +1565,7 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, case ELF::SHT_X86_64_UNWIND: case ELF::SHT_MIPS_REGINFO: case ELF::SHT_MIPS_OPTIONS: + case ELF::SHT_MIPS_ABIFLAGS: // Nothing to do. break; @@ -1357,8 +1575,7 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, break; default: - assert(0 && "FIXME: sh_type value not supported!"); - break; + llvm_unreachable("FIXME: sh_type value not supported!"); } if (TargetObjectWriter->getEMachine() == ELF::EM_ARM && @@ -1380,7 +1597,8 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, } } - WriteSecHdrEntry(SectionStringTableIndex[&Section], Section.getType(), + WriteSecHdrEntry(ShStrTabBuilder.getOffset(Section.getSectionName()), + Section.getType(), Section.getFlags(), 0, Offset, Size, sh_link, sh_info, Alignment, Section.getEntrySize()); } @@ -1514,6 +1732,8 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, unsigned NumUserSections = Asm.size(); + CompressDebugSections(Asm, const_cast<MCAsmLayout &>(Layout)); + DenseMap<const MCSectionELF*, const MCSectionELF*> RelMap; CreateRelocationSections(Asm, const_cast<MCAsmLayout&>(Layout), RelMap); @@ -1526,8 +1746,8 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, unsigned NumRegularSections = NumUserSections + NumIndexedSections; // Compute symbol table information. - ComputeSymbolTable(Asm, SectionIndexMap, RevGroupMap, NumRegularSections); - + computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap, + NumRegularSections); WriteRelocations(Asm, const_cast<MCAsmLayout&>(Layout), RelMap); @@ -1605,7 +1825,7 @@ ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, const MCFragment &FB, bool InSet, bool IsPCRel) const { - if (DataA.getFlags() & ELF_STB_Weak) + if (DataA.getFlags() & ELF_STB_Weak || MCELF::GetType(DataA) == ELF::STT_GNU_IFUNC) return false; return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( Asm, DataA, FB,InSet, IsPCRel); diff --git a/contrib/llvm/lib/MC/MCAnalysis/CMakeLists.txt b/contrib/llvm/lib/MC/MCAnalysis/CMakeLists.txt new file mode 100644 index 0000000..81eae2d --- /dev/null +++ b/contrib/llvm/lib/MC/MCAnalysis/CMakeLists.txt @@ -0,0 +1,8 @@ +add_llvm_library(LLVMMCAnalysis + MCAtom.cpp + MCFunction.cpp + MCModule.cpp + MCModuleYAML.cpp + MCObjectDisassembler.cpp + MCObjectSymbolizer.cpp +) diff --git a/contrib/llvm/lib/MC/MCAnalysis/LLVMBuild.txt b/contrib/llvm/lib/MC/MCAnalysis/LLVMBuild.txt new file mode 100644 index 0000000..1b58fec --- /dev/null +++ b/contrib/llvm/lib/MC/MCAnalysis/LLVMBuild.txt @@ -0,0 +1,5 @@ +[component_0] +type = Library +name = MCAnalysis +parent = Libraries +required_libraries = MC Object Support diff --git a/contrib/llvm/lib/MC/MCAtom.cpp b/contrib/llvm/lib/MC/MCAnalysis/MCAtom.cpp index bc353cd..82056ee 100644 --- a/contrib/llvm/lib/MC/MCAtom.cpp +++ b/contrib/llvm/lib/MC/MCAnalysis/MCAtom.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCAtom.h" -#include "llvm/MC/MCModule.h" +#include "llvm/MC/MCAnalysis/MCAtom.h" +#include "llvm/MC/MCAnalysis/MCModule.h" #include "llvm/Support/ErrorHandling.h" #include <iterator> diff --git a/contrib/llvm/lib/MC/MCFunction.cpp b/contrib/llvm/lib/MC/MCAnalysis/MCFunction.cpp index 767e1e0..4e09d1a 100644 --- a/contrib/llvm/lib/MC/MCFunction.cpp +++ b/contrib/llvm/lib/MC/MCAnalysis/MCFunction.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCFunction.h" -#include "llvm/MC/MCAtom.h" -#include "llvm/MC/MCModule.h" +#include "llvm/MC/MCAnalysis/MCFunction.h" +#include "llvm/MC/MCAnalysis/MCAtom.h" +#include "llvm/MC/MCAnalysis/MCModule.h" #include <algorithm> using namespace llvm; @@ -20,22 +20,17 @@ MCFunction::MCFunction(StringRef Name, MCModule *Parent) : Name(Name), ParentModule(Parent) {} -MCFunction::~MCFunction() { - for (iterator I = begin(), E = end(); I != E; ++I) - delete *I; -} - MCBasicBlock &MCFunction::createBlock(const MCTextAtom &TA) { - MCBasicBlock *MCBB = new MCBasicBlock(TA, this); - Blocks.push_back(MCBB); - return *MCBB; + std::unique_ptr<MCBasicBlock> MCBB(new MCBasicBlock(TA, this)); + Blocks.push_back(std::move(MCBB)); + return *Blocks.back(); } MCBasicBlock *MCFunction::find(uint64_t StartAddr) { for (const_iterator I = begin(), E = end(); I != E; ++I) if ((*I)->getInsts()->getBeginAddr() == StartAddr) - return *I; - return 0; + return I->get(); + return nullptr; } const MCBasicBlock *MCFunction::find(uint64_t StartAddr) const { diff --git a/contrib/llvm/lib/MC/MCModule.cpp b/contrib/llvm/lib/MC/MCAnalysis/MCModule.cpp index 7e9e18a..7512299 100644 --- a/contrib/llvm/lib/MC/MCModule.cpp +++ b/contrib/llvm/lib/MC/MCAnalysis/MCModule.cpp @@ -7,9 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCModule.h" -#include "llvm/MC/MCAtom.h" -#include "llvm/MC/MCFunction.h" +#include "llvm/MC/MCAnalysis/MCModule.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/MC/MCAnalysis/MCAtom.h" +#include "llvm/MC/MCAnalysis/MCFunction.h" #include <algorithm> using namespace llvm; @@ -77,7 +78,7 @@ const MCAtom *MCModule::findAtomContaining(uint64_t Addr) const { Addr, AtomComp); if (I != atom_end() && (*I)->getBeginAddr() <= Addr) return *I; - return 0; + return nullptr; } MCAtom *MCModule::findAtomContaining(uint64_t Addr) { @@ -90,7 +91,7 @@ const MCAtom *MCModule::findFirstAtomAfter(uint64_t Addr) const { Addr, AtomCompInv); if (I != atom_end()) return *I; - return 0; + return nullptr; } MCAtom *MCModule::findFirstAtomAfter(uint64_t Addr) { @@ -99,8 +100,9 @@ MCAtom *MCModule::findFirstAtomAfter(uint64_t Addr) { } MCFunction *MCModule::createFunction(StringRef Name) { - Functions.push_back(new MCFunction(Name, this)); - return Functions.back(); + std::unique_ptr<MCFunction> MCF(new MCFunction(Name, this)); + Functions.push_back(std::move(MCF)); + return Functions.back().get(); } static bool CompBBToAtom(MCBasicBlock *BB, const MCTextAtom *Atom) { @@ -130,13 +132,11 @@ void MCModule::trackBBForAtom(const MCTextAtom *Atom, MCBasicBlock *BB) { BBsByAtom.insert(I, BB); } +MCModule::MCModule() : Entrypoint(0) { } + MCModule::~MCModule() { for (AtomListTy::iterator AI = atom_begin(), AE = atom_end(); AI != AE; ++AI) delete *AI; - for (FunctionListTy::iterator FI = func_begin(), - FE = func_end(); - FI != FE; ++FI) - delete *FI; } diff --git a/contrib/llvm/lib/MC/MCModuleYAML.cpp b/contrib/llvm/lib/MC/MCAnalysis/MCModuleYAML.cpp index e2de578..876b06d 100644 --- a/contrib/llvm/lib/MC/MCModuleYAML.cpp +++ b/contrib/llvm/lib/MC/MCAnalysis/MCModuleYAML.cpp @@ -11,14 +11,15 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCModuleYAML.h" +#include "llvm/MC/MCAnalysis/MCModuleYAML.h" #include "llvm/ADT/StringMap.h" -#include "llvm/MC/MCAtom.h" -#include "llvm/MC/MCFunction.h" +#include "llvm/MC/MCAnalysis/MCAtom.h" +#include "llvm/MC/MCAnalysis/MCFunction.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" -#include "llvm/Object/YAML.h" +#include "llvm/MC/YAML.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/YAMLTraits.h" #include <vector> @@ -101,7 +102,7 @@ struct Atom { uint64_t Size; std::vector<Inst> Insts; - object::yaml::BinaryRef Data; + yaml::BinaryRef Data; }; struct BasicBlock { @@ -162,12 +163,14 @@ template <> struct ScalarTraits<MCModuleYAML::Operand> { static void output(const MCModuleYAML::Operand &, void *, llvm::raw_ostream &); static StringRef input(StringRef, void *, MCModuleYAML::Operand &); + static bool mustQuote(StringRef) { return false; } }; template <> struct ScalarTraits<MCModuleYAML::OpcodeEnum> { static void output(const MCModuleYAML::OpcodeEnum &, void *, llvm::raw_ostream &); static StringRef input(StringRef, void *, MCModuleYAML::OpcodeEnum &); + static bool mustQuote(StringRef) { return false; } }; void ScalarEnumerationTraits<MCAtom::AtomKind>::enumeration( @@ -276,7 +279,7 @@ class MCModule2YAML { const MCModule &MCM; MCModuleYAML::Module YAMLModule; void dumpAtom(const MCAtom *MCA); - void dumpFunction(const MCFunction *MCF); + void dumpFunction(const MCFunction &MCF); void dumpBasicBlock(const MCBasicBlock *MCBB); public: @@ -300,7 +303,7 @@ MCModule2YAML::MCModule2YAML(const MCModule &MCM) : MCM(MCM), YAMLModule() { dumpAtom(*AI); for (MCModule::const_func_iterator FI = MCM.func_begin(), FE = MCM.func_end(); FI != FE; ++FI) - dumpFunction(*FI); + dumpFunction(**FI); } void MCModule2YAML::dumpAtom(const MCAtom *MCA) { @@ -328,22 +331,22 @@ void MCModule2YAML::dumpAtom(const MCAtom *MCA) { } } -void MCModule2YAML::dumpFunction(const MCFunction *MCF) { +void MCModule2YAML::dumpFunction(const MCFunction &MCF) { YAMLModule.Functions.resize(YAMLModule.Functions.size() + 1); MCModuleYAML::Function &F = YAMLModule.Functions.back(); - F.Name = MCF->getName(); - for (MCFunction::const_iterator BBI = MCF->begin(), BBE = MCF->end(); + F.Name = MCF.getName(); + for (MCFunction::const_iterator BBI = MCF.begin(), BBE = MCF.end(); BBI != BBE; ++BBI) { - const MCBasicBlock *MCBB = *BBI; + const MCBasicBlock &MCBB = **BBI; F.BasicBlocks.resize(F.BasicBlocks.size() + 1); MCModuleYAML::BasicBlock &BB = F.BasicBlocks.back(); - BB.Address = MCBB->getInsts()->getBeginAddr(); - for (MCBasicBlock::pred_const_iterator PI = MCBB->pred_begin(), - PE = MCBB->pred_end(); + BB.Address = MCBB.getInsts()->getBeginAddr(); + for (MCBasicBlock::pred_const_iterator PI = MCBB.pred_begin(), + PE = MCBB.pred_end(); PI != PE; ++PI) BB.Preds.push_back((*PI)->getInsts()->getBeginAddr()); - for (MCBasicBlock::succ_const_iterator SI = MCBB->succ_begin(), - SE = MCBB->succ_end(); + for (MCBasicBlock::succ_const_iterator SI = MCBB.succ_begin(), + SE = MCBB.succ_end(); SI != SE; ++SI) BB.Succs.push_back((*SI)->getInsts()->getBeginAddr()); } @@ -442,7 +445,7 @@ StringRef mcmodule2yaml(raw_ostream &OS, const MCModule &MCM, return ""; } -StringRef yaml2mcmodule(OwningPtr<MCModule> &MCM, StringRef YamlContent, +StringRef yaml2mcmodule(std::unique_ptr<MCModule> &MCM, StringRef YamlContent, const MCInstrInfo &MII, const MCRegisterInfo &MRI) { MCM.reset(new MCModule); YAML2MCModule Parser(*MCM); @@ -450,7 +453,7 @@ StringRef yaml2mcmodule(OwningPtr<MCModule> &MCM, StringRef YamlContent, InstrRegInfoHolder IRI(MII, MRI); yaml::Input YIn(YamlContent, (void *)&IRI); YIn >> YAMLModule; - if (error_code ec = YIn.error()) + if (std::error_code ec = YIn.error()) return ec.message(); StringRef err = Parser.parse(YAMLModule); if (!err.empty()) diff --git a/contrib/llvm/lib/MC/MCObjectDisassembler.cpp b/contrib/llvm/lib/MC/MCAnalysis/MCObjectDisassembler.cpp index 16a110f0..0f789ff 100644 --- a/contrib/llvm/lib/MC/MCObjectDisassembler.cpp +++ b/contrib/llvm/lib/MC/MCAnalysis/MCObjectDisassembler.cpp @@ -13,11 +13,11 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" -#include "llvm/MC/MCAtom.h" +#include "llvm/MC/MCAnalysis/MCAtom.h" +#include "llvm/MC/MCAnalysis/MCFunction.h" +#include "llvm/MC/MCAnalysis/MCModule.h" #include "llvm/MC/MCDisassembler.h" -#include "llvm/MC/MCFunction.h" #include "llvm/MC/MCInstrAnalysis.h" -#include "llvm/MC/MCModule.h" #include "llvm/MC/MCObjectSymbolizer.h" #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" @@ -31,22 +31,20 @@ using namespace llvm; using namespace object; +#define DEBUG_TYPE "mc" + MCObjectDisassembler::MCObjectDisassembler(const ObjectFile &Obj, const MCDisassembler &Dis, const MCInstrAnalysis &MIA) - : Obj(Obj), Dis(Dis), MIA(MIA), MOS(0) {} + : Obj(Obj), Dis(Dis), MIA(MIA), MOS(nullptr) {} uint64_t MCObjectDisassembler::getEntrypoint() { - error_code ec; - for (symbol_iterator SI = Obj.begin_symbols(), SE = Obj.end_symbols(); - SI != SE; SI.increment(ec)) { - if (ec) - break; + for (const SymbolRef &Symbol : Obj.symbols()) { StringRef Name; - SI->getName(Name); + Symbol.getName(Name); if (Name == "main" || Name == "_main") { uint64_t Entrypoint; - SI->getAddress(Entrypoint); + Symbol.getAddress(Entrypoint); return getEffectiveLoadAddr(Entrypoint); } } @@ -90,25 +88,24 @@ MCModule *MCObjectDisassembler::buildModule(bool withCFG) { } void MCObjectDisassembler::buildSectionAtoms(MCModule *Module) { - error_code ec; - for (section_iterator SI = Obj.begin_sections(), - SE = Obj.end_sections(); - SI != SE; - SI.increment(ec)) { - if (ec) break; - - bool isText; SI->isText(isText); - bool isData; SI->isData(isData); + for (const SectionRef &Section : Obj.sections()) { + bool isText; + Section.isText(isText); + bool isData; + Section.isData(isData); if (!isData && !isText) continue; - uint64_t StartAddr; SI->getAddress(StartAddr); - uint64_t SecSize; SI->getSize(SecSize); + uint64_t StartAddr; + Section.getAddress(StartAddr); + uint64_t SecSize; + Section.getSize(SecSize); if (StartAddr == UnknownAddressOrSize || SecSize == UnknownAddressOrSize) continue; StartAddr = getEffectiveLoadAddr(StartAddr); - StringRef Contents; SI->getContents(Contents); + StringRef Contents; + Section.getContents(Contents); StringRefMemoryObject memoryObject(Contents, StartAddr); // We don't care about things like non-file-backed sections yet. @@ -116,11 +113,12 @@ void MCObjectDisassembler::buildSectionAtoms(MCModule *Module) { continue; uint64_t EndAddr = StartAddr + SecSize - 1; - StringRef SecName; SI->getName(SecName); + StringRef SecName; + Section.getName(SecName); if (isText) { - MCTextAtom *Text = 0; - MCDataAtom *InvalidData = 0; + MCTextAtom *Text = nullptr; + MCDataAtom *InvalidData = nullptr; uint64_t InstSize; for (uint64_t Index = 0; Index < SecSize; Index += InstSize) { @@ -133,11 +131,11 @@ void MCObjectDisassembler::buildSectionAtoms(MCModule *Module) { Text->setName(SecName); } Text->addInst(Inst, InstSize); - InvalidData = 0; + InvalidData = nullptr; } else { assert(InstSize && "getInstruction() consumed no bytes"); if (!InvalidData) { - Text = 0; + Text = nullptr; InvalidData = Module->createDataAtom(CurAddr, CurAddr+InstSize - 1); } for (uint64_t I = 0; I < InstSize; ++I) @@ -164,7 +162,7 @@ namespace { BBInfoSetTy Preds; MCObjectDisassembler::AddressSetTy SuccAddrs; - BBInfo() : Atom(0), BB(0) {} + BBInfo() : Atom(nullptr), BB(nullptr) {} void addSucc(BBInfo &Succ) { Succs.insert(&Succ); @@ -184,16 +182,12 @@ void MCObjectDisassembler::buildCFG(MCModule *Module) { AddressSetTy Splits; AddressSetTy Calls; - error_code ec; - for (symbol_iterator SI = Obj.begin_symbols(), SE = Obj.end_symbols(); - SI != SE; SI.increment(ec)) { - if (ec) - break; + for (const SymbolRef &Symbol : Obj.symbols()) { SymbolRef::Type SymType; - SI->getType(SymType); + Symbol.getType(SymType); if (SymType == SymbolRef::ST_Function) { uint64_t SymAddr; - SI->getAddress(SymAddr); + Symbol.getAddress(SymAddr); SymAddr = getEffectiveLoadAddr(SymAddr); Calls.push_back(SymAddr); Splits.push_back(SymAddr); @@ -488,7 +482,7 @@ MCObjectDisassembler::createFunction(MCModule *Module, uint64_t BeginAddr, continue; // FIXME: MCModule should provide a findFunctionByAddr() if ((*FI)->getEntryBlock()->getInsts()->getBeginAddr() == BeginAddr) - return *FI; + return FI->get(); } // Finally, just create a new one. @@ -506,20 +500,16 @@ MCMachOObjectDisassembler::MCMachOObjectDisassembler( : MCObjectDisassembler(MOOF, Dis, MIA), MOOF(MOOF), VMAddrSlide(VMAddrSlide), HeaderLoadAddress(HeaderLoadAddress) { - error_code ec; - for (section_iterator SI = MOOF.begin_sections(), SE = MOOF.end_sections(); - SI != SE; SI.increment(ec)) { - if (ec) - break; + for (const SectionRef &Section : MOOF.sections()) { StringRef Name; - SI->getName(Name); + Section.getName(Name); // FIXME: We should use the S_ section type instead of the name. if (Name == "__mod_init_func") { DEBUG(dbgs() << "Found __mod_init_func section!\n"); - SI->getContents(ModInitContents); + Section.getContents(ModInitContents); } else if (Name == "__mod_exit_func") { DEBUG(dbgs() << "Found __mod_exit_func section!\n"); - SI->getContents(ModExitContents); + Section.getContents(ModExitContents); } } } diff --git a/contrib/llvm/lib/MC/MCObjectSymbolizer.cpp b/contrib/llvm/lib/MC/MCAnalysis/MCObjectSymbolizer.cpp index b9131d1..b149596 100644 --- a/contrib/llvm/lib/MC/MCObjectSymbolizer.cpp +++ b/contrib/llvm/lib/MC/MCAnalysis/MCObjectSymbolizer.cpp @@ -14,8 +14,8 @@ #include "llvm/MC/MCInst.h" #include "llvm/MC/MCRelocationInfo.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Object/MachO.h" #include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/MachO.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -34,31 +34,28 @@ class MCMachObjectSymbolizer : public MCObjectSymbolizer { uint64_t StubsIndSymIndex; public: - MCMachObjectSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo, + MCMachObjectSymbolizer(MCContext &Ctx, + std::unique_ptr<MCRelocationInfo> RelInfo, const MachOObjectFile *MOOF); - StringRef findExternalFunctionAt(uint64_t Addr) LLVM_OVERRIDE; + StringRef findExternalFunctionAt(uint64_t Addr) override; - void tryAddingPcLoadReferenceComment(raw_ostream &cStream, - int64_t Value, - uint64_t Address) LLVM_OVERRIDE; + void tryAddingPcLoadReferenceComment(raw_ostream &cStream, int64_t Value, + uint64_t Address) override; }; } // End unnamed namespace +MCMachObjectSymbolizer::MCMachObjectSymbolizer( + MCContext &Ctx, std::unique_ptr<MCRelocationInfo> RelInfo, + const MachOObjectFile *MOOF) + : MCObjectSymbolizer(Ctx, std::move(RelInfo), MOOF), MOOF(MOOF), + StubsStart(0), StubsCount(0), StubSize(0), StubsIndSymIndex(0) { -MCMachObjectSymbolizer:: -MCMachObjectSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo, - const MachOObjectFile *MOOF) - : MCObjectSymbolizer(Ctx, RelInfo, MOOF), MOOF(MOOF), - StubsStart(0), StubsCount(0), StubSize(0), StubsIndSymIndex(0) { - - error_code ec; - for (section_iterator SI = MOOF->begin_sections(), SE = MOOF->end_sections(); - SI != SE; SI.increment(ec)) { - if (ec) break; - StringRef Name; SI->getName(Name); + for (const SectionRef &Section : MOOF->sections()) { + StringRef Name; + Section.getName(Name); if (Name == "__stubs") { - SectionRef StubsSec = *SI; + SectionRef StubsSec = Section; if (MOOF->is64Bit()) { MachO::section_64 S = MOOF->getSection64(StubsSec.getRawDataRefImpl()); StubsIndSymIndex = S.reserved1; @@ -90,13 +87,11 @@ StringRef MCMachObjectSymbolizer::findExternalFunctionAt(uint64_t Addr) { MOOF->getIndirectSymbolTableEntry(MOOF->getDysymtabLoadCommand(), StubIdx); StringRef SymName; - symbol_iterator SI = MOOF->begin_symbols(); - error_code ec; - for (uint32_t i = 0; i != SymtabIdx; ++i) { - SI.increment(ec); - } + symbol_iterator SI = MOOF->symbol_begin(); + for (uint32_t i = 0; i != SymtabIdx; ++i) + ++SI; SI->getName(SymName); - assert(SI != MOOF->end_symbols() && "Stub wasn't found in the symbol table!"); + assert(SI != MOOF->symbol_end() && "Stub wasn't found in the symbol table!"); assert(SymName.front() == '_' && "Mach-O symbol doesn't start with '_'!"); return SymName.substr(1); } @@ -125,11 +120,11 @@ tryAddingPcLoadReferenceComment(raw_ostream &cStream, int64_t Value, //===- MCObjectSymbolizer -------------------------------------------------===// -MCObjectSymbolizer::MCObjectSymbolizer(MCContext &Ctx, - OwningPtr<MCRelocationInfo> &RelInfo, - const ObjectFile *Obj) - : MCSymbolizer(Ctx, RelInfo), Obj(Obj), SortedSections(), AddrToReloc() { -} +MCObjectSymbolizer::MCObjectSymbolizer( + MCContext &Ctx, std::unique_ptr<MCRelocationInfo> RelInfo, + const ObjectFile *Obj) + : MCSymbolizer(Ctx, std::move(RelInfo)), Obj(Obj), SortedSections(), + AddrToReloc() {} bool MCObjectSymbolizer:: tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream, @@ -159,16 +154,17 @@ tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream, return false; uint64_t UValue = Value; // FIXME: map instead of looping each time? - error_code ec; - for (symbol_iterator SI = Obj->begin_symbols(), SE = Obj->end_symbols(); - SI != SE; SI.increment(ec)) { - if (ec) break; - uint64_t SymAddr; SI->getAddress(SymAddr); - uint64_t SymSize; SI->getSize(SymSize); - StringRef SymName; SI->getName(SymName); - SymbolRef::Type SymType; SI->getType(SymType); - if (SymAddr == UnknownAddressOrSize || SymSize == UnknownAddressOrSize - || SymName.empty() || SymType != SymbolRef::ST_Function) + for (const SymbolRef &Symbol : Obj->symbols()) { + uint64_t SymAddr; + Symbol.getAddress(SymAddr); + uint64_t SymSize; + Symbol.getSize(SymSize); + StringRef SymName; + Symbol.getName(SymName); + SymbolRef::Type SymType; + Symbol.getType(SymType); + if (SymAddr == UnknownAddressOrSize || SymSize == UnknownAddressOrSize || + SymName.empty() || SymType != SymbolRef::ST_Function) continue; if ( SymAddr == UValue || @@ -195,13 +191,12 @@ StringRef MCObjectSymbolizer::findExternalFunctionAt(uint64_t Addr) { return StringRef(); } -MCObjectSymbolizer * -MCObjectSymbolizer::createObjectSymbolizer(MCContext &Ctx, - OwningPtr<MCRelocationInfo> &RelInfo, - const ObjectFile *Obj) { +MCObjectSymbolizer *MCObjectSymbolizer::createObjectSymbolizer( + MCContext &Ctx, std::unique_ptr<MCRelocationInfo> RelInfo, + const ObjectFile *Obj) { if (const MachOObjectFile *MOOF = dyn_cast<MachOObjectFile>(Obj)) - return new MCMachObjectSymbolizer(Ctx, RelInfo, MOOF); - return new MCObjectSymbolizer(Ctx, RelInfo, Obj); + return new MCMachObjectSymbolizer(Ctx, std::move(RelInfo), MOOF); + return new MCObjectSymbolizer(Ctx, std::move(RelInfo), Obj); } // SortedSections implementation. @@ -220,11 +215,11 @@ const SectionRef *MCObjectSymbolizer::findSectionContaining(uint64_t Addr) { It = std::lower_bound(SortedSections.begin(), EndIt, Addr, SectionStartsBefore); if (It == EndIt) - return 0; + return nullptr; uint64_t SAddr; It->getAddress(SAddr); uint64_t SSize; It->getSize(SSize); if (Addr >= SAddr + SSize) - return 0; + return nullptr; return &*It; } @@ -234,77 +229,40 @@ const RelocationRef *MCObjectSymbolizer::findRelocationAt(uint64_t Addr) { AddrToRelocMap::const_iterator RI = AddrToReloc.find(Addr); if (RI == AddrToReloc.end()) - return 0; + return nullptr; return &RI->second; } void MCObjectSymbolizer::buildSectionList() { - error_code ec; - for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections(); - SI != SE; SI.increment(ec)) { - if (ec) break; - - bool RequiredForExec; SI->isRequiredForExecution(RequiredForExec); + for (const SectionRef &Section : Obj->sections()) { + bool RequiredForExec; + Section.isRequiredForExecution(RequiredForExec); if (RequiredForExec == false) continue; - uint64_t SAddr; SI->getAddress(SAddr); - uint64_t SSize; SI->getSize(SSize); - SortedSectionList::iterator It = std::lower_bound(SortedSections.begin(), - SortedSections.end(), - SAddr, - SectionStartsBefore); + uint64_t SAddr; + Section.getAddress(SAddr); + uint64_t SSize; + Section.getSize(SSize); + SortedSectionList::iterator It = + std::lower_bound(SortedSections.begin(), SortedSections.end(), SAddr, + SectionStartsBefore); if (It != SortedSections.end()) { uint64_t FoundSAddr; It->getAddress(FoundSAddr); if (FoundSAddr < SAddr + SSize) llvm_unreachable("Inserting overlapping sections"); } - SortedSections.insert(It, *SI); + SortedSections.insert(It, Section); } } void MCObjectSymbolizer::buildRelocationByAddrMap() { - error_code ec; - for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections(); - SI != SE; SI.increment(ec)) { - if (ec) break; - - section_iterator RelSecI = SI->getRelocatedSection(); - if (RelSecI == Obj->end_sections()) - continue; - - uint64_t StartAddr; RelSecI->getAddress(StartAddr); - uint64_t Size; RelSecI->getSize(Size); - bool RequiredForExec; RelSecI->isRequiredForExecution(RequiredForExec); - if (RequiredForExec == false || Size == 0) - continue; - for (relocation_iterator RI = SI->begin_relocations(), - RE = SI->end_relocations(); - RI != RE; - RI.increment(ec)) { - if (ec) break; - // FIXME: libObject is inconsistent regarding error handling. The - // overwhelming majority of methods always return object_error::success, - // and assert for simple errors.. Here, ELFObjectFile::getRelocationOffset - // asserts when the file type isn't ET_REL. - // This workaround handles x86-64 elf, the only one that has a relocinfo. - uint64_t Offset; - if (Obj->isELF()) { - const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj); - if (ELFObj == 0) - break; - if (ELFObj->getELFFile()->getHeader()->e_type == ELF::ET_REL) { - RI->getOffset(Offset); - Offset += StartAddr; - } else { - RI->getAddress(Offset); - } - } else { - RI->getOffset(Offset); - Offset += StartAddr; - } + for (const SectionRef &Section : Obj->sections()) { + for (const RelocationRef &Reloc : Section.relocations()) { + uint64_t Address; + Reloc.getAddress(Address); // At a specific address, only keep the first relocation. - if (AddrToReloc.find(Offset) == AddrToReloc.end()) - AddrToReloc[Offset] = *RI; + if (AddrToReloc.find(Address) == AddrToReloc.end()) + AddrToReloc[Address] = Reloc; } } } diff --git a/contrib/llvm/lib/MC/MCAnalysis/Makefile b/contrib/llvm/lib/MC/MCAnalysis/Makefile new file mode 100644 index 0000000..add2dbd --- /dev/null +++ b/contrib/llvm/lib/MC/MCAnalysis/Makefile @@ -0,0 +1,14 @@ +##===- lib/MC/MCAnalysys/Makefile --------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMMCAnalysis +BUILD_ARCHIVE := 1 + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/lib/MC/MCAsmBackend.cpp b/contrib/llvm/lib/MC/MCAsmBackend.cpp index c4c98cc..c42757b 100644 --- a/contrib/llvm/lib/MC/MCAsmBackend.cpp +++ b/contrib/llvm/lib/MC/MCAsmBackend.cpp @@ -12,8 +12,7 @@ #include "llvm/MC/MCFixupKindInfo.h" using namespace llvm; -MCAsmBackend::MCAsmBackend() - : HasReliableSymbolDifference(false), HasDataInCodeSupport(false) {} +MCAsmBackend::MCAsmBackend() : HasDataInCodeSupport(false) {} MCAsmBackend::~MCAsmBackend() {} diff --git a/contrib/llvm/lib/MC/MCAsmInfo.cpp b/contrib/llvm/lib/MC/MCAsmInfo.cpp index daf19e9..f8081ef 100644 --- a/contrib/llvm/lib/MC/MCAsmInfo.cpp +++ b/contrib/llvm/lib/MC/MCAsmInfo.cpp @@ -37,12 +37,10 @@ MCAsmInfo::MCAsmInfo() { MinInstAlignment = 1; DollarIsPC = false; SeparatorString = ";"; - CommentColumn = 40; CommentString = "#"; LabelSuffix = ":"; - DebugLabelSuffix = ":"; - GlobalPrefix = ""; - PrivateGlobalPrefix = "."; + UseAssignmentForEHBegin = false; + PrivateGlobalPrefix = "L"; LinkerPrivateGlobalPrefix = ""; InlineAsmStart = "APP"; InlineAsmEnd = "NO_APP"; @@ -61,11 +59,10 @@ MCAsmInfo::MCAsmInfo() { Data64bitsDirective = "\t.quad\t"; SunStyleELFSectionSwitchSyntax = false; UsesELFSectionDirectiveForBSS = false; - AlignDirective = "\t.align\t"; AlignmentIsInBytes = true; TextAlignFillValue = 0; - GPRel64Directive = 0; - GPRel32Directive = 0; + GPRel64Directive = nullptr; + GPRel32Directive = nullptr; GlobalDirective = "\t.globl\t"; HasSetDirective = true; HasAggressiveSymbolFolding = true; @@ -75,7 +72,7 @@ MCAsmInfo::MCAsmInfo() { HasSingleParameterDotFile = true; HasIdentDirective = false; HasNoDeadStrip = false; - WeakRefDirective = 0; + WeakRefDirective = nullptr; HasWeakDefDirective = false; HasWeakDefCanBeHiddenDirective = false; HasLinkOnceDirective = false; @@ -85,38 +82,31 @@ MCAsmInfo::MCAsmInfo() { HasLEB128 = false; SupportsDebugInformation = false; ExceptionsType = ExceptionHandling::None; + WinEHEncodingType = WinEH::EncodingType::ET_Invalid; DwarfUsesRelocationsAcrossSections = true; DwarfFDESymbolsUseAbsDiff = false; DwarfRegNumForCFI = false; - HasMicrosoftFastStdCallMangling = false; NeedsDwarfSectionOffsetDirective = false; -} - -MCAsmInfo::~MCAsmInfo() { -} + UseParensForSymbolVariant = false; + // FIXME: Clang's logic should be synced with the logic used to initialize + // this member and the two implementations should be merged. + // For reference: + // - Solaris always enables the integrated assembler by default + // - SparcELFMCAsmInfo and X86ELFMCAsmInfo are handling this case + // - Windows always enables the integrated assembler by default + // - MCAsmInfoCOFF is handling this case, should it be MCAsmInfoMicrosoft? + // - MachO targets always enables the integrated assembler by default + // - MCAsmInfoDarwin is handling this case + // - Generic_GCC toolchains enable the integrated assembler on a per + // architecture basis. + // - The target subclasses for AArch64, ARM, and X86 handle these cases + UseIntegratedAssembler = false; -unsigned MCAsmInfo::getULEB128Size(uint64_t Value) { - unsigned Size = 0; - do { - Value >>= 7; - Size += sizeof(int8_t); - } while (Value); - return Size; + CompressDebugSections = false; } -unsigned MCAsmInfo::getSLEB128Size(int64_t Value) { - unsigned Size = 0; - int Sign = Value >> (8 * sizeof(Value) - 1); - bool IsMore; - - do { - unsigned Byte = Value & 0x7f; - Value >>= 7; - IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; - Size += sizeof(int8_t); - } while (IsMore); - return Size; +MCAsmInfo::~MCAsmInfo() { } const MCExpr * diff --git a/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp b/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp index 1cac71f..9945637 100644 --- a/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp +++ b/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp @@ -18,14 +18,12 @@ using namespace llvm; void MCAsmInfoCOFF::anchor() { } MCAsmInfoCOFF::MCAsmInfoCOFF() { - GlobalPrefix = "_"; // MingW 4.5 and later support .comm with log2 alignment, but .lcomm uses byte // alignment. COMMDirectiveAlignmentIsInBytes = false; LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment; HasDotTypeDotSizeDirective = false; HasSingleParameterDotFile = false; - PrivateGlobalPrefix = "L"; // Prefix for private global symbols WeakRefDirective = "\t.weak\t"; HasLinkOnceDirective = true; @@ -36,8 +34,9 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() { // Set up DWARF directives HasLEB128 = true; // Target asm supports leb128 directives (little-endian) SupportsDebugInformation = true; - HasMicrosoftFastStdCallMangling = true; NeedsDwarfSectionOffsetDirective = true; + + UseIntegratedAssembler = true; } void MCAsmInfoMicrosoft::anchor() { } diff --git a/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp b/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp index 351ec56..eaf28dd 100644 --- a/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp +++ b/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp @@ -23,8 +23,6 @@ void MCAsmInfoDarwin::anchor() { } MCAsmInfoDarwin::MCAsmInfoDarwin() { // Common settings for all Darwin targets. // Syntax: - GlobalPrefix = "_"; - PrivateGlobalPrefix = "L"; LinkerPrivateGlobalPrefix = "l"; HasSingleParameterDotFile = false; HasSubsectionsViaSymbols = true; @@ -60,4 +58,6 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { HasNoDeadStrip = true; DwarfUsesRelocationsAcrossSections = false; + + UseIntegratedAssembler = true; } diff --git a/contrib/llvm/lib/MC/MCAsmInfoELF.cpp b/contrib/llvm/lib/MC/MCAsmInfoELF.cpp index 8cf4e4f..ccb3dc3 100644 --- a/contrib/llvm/lib/MC/MCAsmInfoELF.cpp +++ b/contrib/llvm/lib/MC/MCAsmInfoELF.cpp @@ -20,4 +20,5 @@ void MCAsmInfoELF::anchor() { } MCAsmInfoELF::MCAsmInfoELF() { HasIdentDirective = true; WeakRefDirective = "\t.weak\t"; + PrivateGlobalPrefix = ".L"; } diff --git a/contrib/llvm/lib/MC/MCAsmStreamer.cpp b/contrib/llvm/lib/MC/MCAsmStreamer.cpp index ca49f8f..14f0f05 100644 --- a/contrib/llvm/lib/MC/MCAsmStreamer.cpp +++ b/contrib/llvm/lib/MC/MCAsmStreamer.cpp @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCStreamer.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAsmBackend.h" @@ -32,6 +32,7 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include <cctype> +#include <unordered_map> using namespace llvm; namespace { @@ -41,44 +42,33 @@ protected: formatted_raw_ostream &OS; const MCAsmInfo *MAI; private: - OwningPtr<MCInstPrinter> InstPrinter; - OwningPtr<MCCodeEmitter> Emitter; - OwningPtr<MCAsmBackend> AsmBackend; + std::unique_ptr<MCInstPrinter> InstPrinter; + std::unique_ptr<MCCodeEmitter> Emitter; + std::unique_ptr<MCAsmBackend> AsmBackend; SmallString<128> CommentToEmit; raw_svector_ostream CommentStream; unsigned IsVerboseAsm : 1; unsigned ShowInst : 1; - unsigned UseLoc : 1; - unsigned UseCFI : 1; unsigned UseDwarfDirectory : 1; - enum EHSymbolFlags { EHGlobal = 1, - EHWeakDefinition = 1 << 1, - EHPrivateExtern = 1 << 2 }; - DenseMap<const MCSymbol*, unsigned> FlagMap; - - bool needsSet(const MCExpr *Value); - void EmitRegisterName(int64_t Register); - virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame); - virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame); + void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; + void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; public: - MCAsmStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, - formatted_raw_ostream &os, bool isVerboseAsm, bool useLoc, - bool useCFI, bool useDwarfDirectory, MCInstPrinter *printer, - MCCodeEmitter *emitter, MCAsmBackend *asmbackend, bool showInst) - : MCStreamer(Context, TargetStreamer), OS(os), MAI(Context.getAsmInfo()), + MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os, + bool isVerboseAsm, bool useDwarfDirectory, + MCInstPrinter *printer, MCCodeEmitter *emitter, + MCAsmBackend *asmbackend, bool showInst) + : MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()), InstPrinter(printer), Emitter(emitter), AsmBackend(asmbackend), CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm), - ShowInst(showInst), UseLoc(useLoc), UseCFI(useCFI), - UseDwarfDirectory(useDwarfDirectory) { + ShowInst(showInst), UseDwarfDirectory(useDwarfDirectory) { if (InstPrinter && IsVerboseAsm) InstPrinter->setCommentStream(CommentStream); } - ~MCAsmStreamer() {} inline void EmitEOL() { // If we don't have any comments, just emit a \n. @@ -92,172 +82,163 @@ public: /// isVerboseAsm - Return true if this streamer supports verbose assembly at /// all. - virtual bool isVerboseAsm() const { return IsVerboseAsm; } + bool isVerboseAsm() const override { return IsVerboseAsm; } /// hasRawTextSupport - We support EmitRawText. - virtual bool hasRawTextSupport() const { return true; } + bool hasRawTextSupport() const override { return true; } /// AddComment - Add a comment that can be emitted to the generated .s /// file if applicable as a QoI issue to make the output of the compiler /// more readable. This only affects the MCAsmStreamer, and only when /// verbose assembly output is enabled. - virtual void AddComment(const Twine &T); + void AddComment(const Twine &T) override; /// AddEncodingComment - Add a comment showing the encoding of an instruction. - virtual void AddEncodingComment(const MCInst &Inst); + void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &); /// GetCommentOS - Return a raw_ostream that comments can be written to. /// Unlike AddComment, you are required to terminate comments with \n if you /// use this method. - virtual raw_ostream &GetCommentOS() { + raw_ostream &GetCommentOS() override { if (!IsVerboseAsm) return nulls(); // Discard comments unless in verbose asm mode. return CommentStream; } + void emitRawComment(const Twine &T, bool TabPrefix = true) override; + /// AddBlankLine - Emit a blank line to a .s file to pretty it up. - virtual void AddBlankLine() { + void AddBlankLine() override { EmitEOL(); } /// @name MCStreamer Interface /// @{ - virtual void ChangeSection(const MCSection *Section, - const MCExpr *Subsection); - - virtual void InitSections() { - InitToTextSection(); - } - - virtual void InitToTextSection() { - SwitchSection(getContext().getObjectFileInfo()->getTextSection()); - } - - virtual void EmitLabel(MCSymbol *Symbol); - virtual void EmitDebugLabel(MCSymbol *Symbol); - - virtual void EmitEHSymAttributes(const MCSymbol *Symbol, - MCSymbol *EHSymbol); - virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); - virtual void EmitLinkerOptions(ArrayRef<std::string> Options); - virtual void EmitDataRegion(MCDataRegionType Kind); - virtual void EmitThumbFunc(MCSymbol *Func); - - virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); - virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); - virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, - const MCSymbol *LastLabel, - const MCSymbol *Label, - unsigned PointerSize); - virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, - const MCSymbol *Label); - - virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); - - virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); - virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol); - virtual void EmitCOFFSymbolStorageClass(int StorageClass); - virtual void EmitCOFFSymbolType(int Type); - virtual void EndCOFFSymbolDef(); - virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); - virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); - virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment); + void ChangeSection(const MCSection *Section, + const MCExpr *Subsection) override; + + void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override; + void EmitLabel(MCSymbol *Symbol) override; + + void EmitAssemblerFlag(MCAssemblerFlag Flag) override; + void EmitLinkerOptions(ArrayRef<std::string> Options) override; + void EmitDataRegion(MCDataRegionType Kind) override; + void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor, + unsigned Update) override; + void EmitThumbFunc(MCSymbol *Func) override; + + void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; + void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; + bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; + + void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; + void BeginCOFFSymbolDef(const MCSymbol *Symbol) override; + void EmitCOFFSymbolStorageClass(int StorageClass) override; + void EmitCOFFSymbolType(int Type) override; + void EndCOFFSymbolDef() override; + void EmitCOFFSectionIndex(MCSymbol const *Symbol) override; + void EmitCOFFSecRel32(MCSymbol const *Symbol) override; + void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; + void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. /// /// @param Symbol - The common symbol to emit. /// @param Size - The size of the common symbol. /// @param ByteAlignment - The alignment of the common symbol in bytes. - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment); - - virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, - uint64_t Size = 0, unsigned ByteAlignment = 0); - - virtual void EmitTBSSSymbol (const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment = 0); - - virtual void EmitBytes(StringRef Data); - - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size); - virtual void EmitIntValue(uint64_t Value, unsigned Size); - - virtual void EmitULEB128Value(const MCExpr *Value); - - virtual void EmitSLEB128Value(const MCExpr *Value); - - virtual void EmitGPRel64Value(const MCExpr *Value); - - virtual void EmitGPRel32Value(const MCExpr *Value); - - - virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue); - - virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, - unsigned ValueSize = 1, - unsigned MaxBytesToEmit = 0); - - virtual void EmitCodeAlignment(unsigned ByteAlignment, - unsigned MaxBytesToEmit = 0); - - virtual bool EmitValueToOffset(const MCExpr *Offset, - unsigned char Value = 0); - - virtual void EmitFileDirective(StringRef Filename); - virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, - StringRef Filename, unsigned CUID = 0); - virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, - unsigned Column, unsigned Flags, - unsigned Isa, unsigned Discriminator, - StringRef FileName); - - virtual void EmitIdent(StringRef IdentString); - virtual void EmitCFISections(bool EH, bool Debug); - virtual void EmitCFIDefCfa(int64_t Register, int64_t Offset); - virtual void EmitCFIDefCfaOffset(int64_t Offset); - virtual void EmitCFIDefCfaRegister(int64_t Register); - virtual void EmitCFIOffset(int64_t Register, int64_t Offset); - virtual void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding); - virtual void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); - virtual void EmitCFIRememberState(); - virtual void EmitCFIRestoreState(); - virtual void EmitCFISameValue(int64_t Register); - virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset); - virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment); - virtual void EmitCFISignalFrame(); - virtual void EmitCFIUndefined(int64_t Register); - virtual void EmitCFIRegister(int64_t Register1, int64_t Register2); - virtual void EmitCFIWindowSave(); - - virtual void EmitWin64EHStartProc(const MCSymbol *Symbol); - virtual void EmitWin64EHEndProc(); - virtual void EmitWin64EHStartChained(); - virtual void EmitWin64EHEndChained(); - virtual void EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, - bool Except); - virtual void EmitWin64EHHandlerData(); - virtual void EmitWin64EHPushReg(unsigned Register); - virtual void EmitWin64EHSetFrame(unsigned Register, unsigned Offset); - virtual void EmitWin64EHAllocStack(unsigned Size); - virtual void EmitWin64EHSaveReg(unsigned Register, unsigned Offset); - virtual void EmitWin64EHSaveXMM(unsigned Register, unsigned Offset); - virtual void EmitWin64EHPushFrame(bool Code); - virtual void EmitWin64EHEndProlog(); - - virtual void EmitInstruction(const MCInst &Inst); - - virtual void EmitBundleAlignMode(unsigned AlignPow2); - virtual void EmitBundleLock(bool AlignToEnd); - virtual void EmitBundleUnlock(); + void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + + void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = nullptr, + uint64_t Size = 0, unsigned ByteAlignment = 0) override; + + void EmitTBSSSymbol (const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment = 0) override; + + void EmitBytes(StringRef Data) override; + + void EmitValueImpl(const MCExpr *Value, unsigned Size, + const SMLoc &Loc = SMLoc()) override; + void EmitIntValue(uint64_t Value, unsigned Size) override; + + void EmitULEB128Value(const MCExpr *Value) override; + + void EmitSLEB128Value(const MCExpr *Value) override; + + void EmitGPRel64Value(const MCExpr *Value) override; + + void EmitGPRel32Value(const MCExpr *Value) override; + + + void EmitFill(uint64_t NumBytes, uint8_t FillValue) override; + + void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0) override; + + void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0) override; + + bool EmitValueToOffset(const MCExpr *Offset, + unsigned char Value = 0) override; + + void EmitFileDirective(StringRef Filename) override; + unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, + StringRef Filename, + unsigned CUID = 0) override; + void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, unsigned Discriminator, + StringRef FileName) override; + MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override; + + void EmitIdent(StringRef IdentString) override; + void EmitCFISections(bool EH, bool Debug) override; + void EmitCFIDefCfa(int64_t Register, int64_t Offset) override; + void EmitCFIDefCfaOffset(int64_t Offset) override; + void EmitCFIDefCfaRegister(int64_t Register) override; + void EmitCFIOffset(int64_t Register, int64_t Offset) override; + void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override; + void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) override; + void EmitCFIRememberState() override; + void EmitCFIRestoreState() override; + void EmitCFISameValue(int64_t Register) override; + void EmitCFIRelOffset(int64_t Register, int64_t Offset) override; + void EmitCFIAdjustCfaOffset(int64_t Adjustment) override; + void EmitCFISignalFrame() override; + void EmitCFIUndefined(int64_t Register) override; + void EmitCFIRegister(int64_t Register1, int64_t Register2) override; + void EmitCFIWindowSave() override; + + void EmitWinCFIStartProc(const MCSymbol *Symbol) override; + void EmitWinCFIEndProc() override; + void EmitWinCFIStartChained() override; + void EmitWinCFIEndChained() override; + void EmitWinCFIPushReg(unsigned Register) override; + void EmitWinCFISetFrame(unsigned Register, unsigned Offset) override; + void EmitWinCFIAllocStack(unsigned Size) override; + void EmitWinCFISaveReg(unsigned Register, unsigned Offset) override; + void EmitWinCFISaveXMM(unsigned Register, unsigned Offset) override; + void EmitWinCFIPushFrame(bool Code) override; + void EmitWinCFIEndProlog() override; + + void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except) override; + void EmitWinEHHandlerData() override; + + void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; + + void EmitBundleAlignMode(unsigned AlignPow2) override; + void EmitBundleLock(bool AlignToEnd) override; + void EmitBundleUnlock() override; /// EmitRawText - If this file is backed by an assembly streamer, this dumps /// the specified string in the output .s file. This capability is /// indicated by the hasRawTextSupport() predicate. - virtual void EmitRawTextImpl(StringRef String); + void EmitRawTextImpl(StringRef String) override; - virtual void FinishImpl(); + void FinishImpl() override; }; } // end anonymous namespace. @@ -310,27 +291,19 @@ static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); } +void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) { + if (TabPrefix) + OS << '\t'; + OS << MAI->getCommentString() << T; + EmitEOL(); +} + void MCAsmStreamer::ChangeSection(const MCSection *Section, const MCExpr *Subsection) { assert(Section && "Cannot switch to a null section!"); Section->PrintSwitchToSection(*MAI, OS, Subsection); } -void MCAsmStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, - MCSymbol *EHSymbol) { - if (UseCFI) - return; - - unsigned Flags = FlagMap.lookup(Symbol); - - if (Flags & EHGlobal) - EmitSymbolAttribute(EHSymbol, MCSA_Global); - if (Flags & EHWeakDefinition) - EmitSymbolAttribute(EHSymbol, MCSA_WeakDefinition); - if (Flags & EHPrivateExtern) - EmitSymbolAttribute(EHSymbol, MCSA_PrivateExtern); -} - void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); MCStreamer::EmitLabel(Symbol); @@ -339,11 +312,24 @@ void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) { EmitEOL(); } -void MCAsmStreamer::EmitDebugLabel(MCSymbol *Symbol) { - assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - MCStreamer::EmitDebugLabel(Symbol); +void MCAsmStreamer::EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) { + StringRef str = MCLOHIdToName(Kind); + +#ifndef NDEBUG + int NbArgs = MCLOHIdToNbArgs(Kind); + assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!"); + assert(str != "" && "Invalid LOH name"); +#endif - OS << *Symbol << MAI->getDebugLabelSuffix(); + OS << "\t" << MCLOHDirectiveName() << " " << str << "\t"; + bool IsFirst = true; + for (MCLOHArgs::const_iterator It = Args.begin(), EndIt = Args.end(); + It != EndIt; ++It) { + if (!IsFirst) + OS << ", "; + IsFirst = false; + OS << **It; + } EmitEOL(); } @@ -381,6 +367,18 @@ void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) { EmitEOL(); } +void MCAsmStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major, + unsigned Minor, unsigned Update) { + switch (Kind) { + case MCVM_IOSVersionMin: OS << "\t.ios_version_min"; break; + case MCVM_OSXVersionMin: OS << "\t.macosx_version_min"; break; + } + OS << " " << Major << ", " << Minor; + if (Update) + OS << ", " << Update; + EmitEOL(); +} + void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) { // This needs to emit to a temporary string to get properly quoted // MCSymbols when they have spaces in them. @@ -395,8 +393,7 @@ void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { OS << *Symbol << " = " << *Value; EmitEOL(); - // FIXME: Lift context changes into super class. - Symbol->setVariableValue(Value); + MCStreamer::EmitAssignment(Symbol, Value); } void MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { @@ -404,22 +401,6 @@ void MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { EmitEOL(); } -void MCAsmStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta, - const MCSymbol *LastLabel, - const MCSymbol *Label, - unsigned PointerSize) { - EmitDwarfSetLineAddr(LineDelta, Label, PointerSize); -} - -void MCAsmStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, - const MCSymbol *Label) { - EmitIntValue(dwarf::DW_CFA_advance_loc4, 1); - const MCExpr *AddrDelta = BuildSymbolDiff(getContext(), Label, LastLabel); - AddrDelta = ForceExpAbs(AddrDelta); - EmitValue(AddrDelta, 4); -} - - bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { switch (Attribute) { @@ -449,7 +430,6 @@ bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, return true; case MCSA_Global: // .globl/.global OS << MAI->getGlobalDirective(); - FlagMap[Symbol] |= EHGlobal; break; case MCSA_Hidden: OS << "\t.hidden\t"; break; case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break; @@ -460,14 +440,12 @@ bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break; case MCSA_PrivateExtern: OS << "\t.private_extern\t"; - FlagMap[Symbol] |= EHPrivateExtern; break; case MCSA_Protected: OS << "\t.protected\t"; break; case MCSA_Reference: OS << "\t.reference\t"; break; case MCSA_Weak: OS << "\t.weak\t"; break; case MCSA_WeakDefinition: OS << "\t.weak_definition\t"; - FlagMap[Symbol] |= EHWeakDefinition; break; // .weak_reference case MCSA_WeakReference: OS << MAI->getWeakRefDirective(); break; @@ -505,8 +483,13 @@ void MCAsmStreamer::EndCOFFSymbolDef() { EmitEOL(); } +void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { + OS << "\t.secidx\t" << *Symbol; + EmitEOL(); +} + void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) { - OS << "\t.secrel32\t" << *Symbol << '\n'; + OS << "\t.secrel32\t" << *Symbol; EmitEOL(); } @@ -518,7 +501,7 @@ void MCAsmStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { // Common symbols do not belong to any actual section. - AssignSection(Symbol, NULL); + AssignSection(Symbol, nullptr); OS << "\t.comm\t" << *Symbol << ',' << Size; if (ByteAlignment != 0) { @@ -537,7 +520,7 @@ void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlign) { // Common symbols do not belong to any actual section. - AssignSection(Symbol, NULL); + AssignSection(Symbol, nullptr); OS << "\t.lcomm\t" << *Symbol << ',' << Size; if (ByteAlign > 1) { @@ -568,7 +551,7 @@ void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section); OS << MOSection->getSegmentName() << "," << MOSection->getSectionName(); - if (Symbol != NULL) { + if (Symbol) { OS << ',' << *Symbol << ',' << Size; if (ByteAlignment != 0) OS << ',' << Log2_32(ByteAlignment); @@ -583,7 +566,7 @@ void MCAsmStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { AssignSection(Symbol, Section); - assert(Symbol != NULL && "Symbol shouldn't be NULL!"); + assert(Symbol && "Symbol shouldn't be NULL!"); // Instead of using the Section we'll just use the shortcut. // This is a mach-o specific directive and section. OS << ".tbss " << *Symbol << ", " << Size; @@ -660,28 +643,48 @@ void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size) { EmitValue(MCConstantExpr::Create(Value, getContext()), Size); } -void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size) { +void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, + const SMLoc &Loc) { + assert(Size <= 8 && "Invalid size"); assert(getCurrentSection().first && "Cannot emit contents before setting section!"); - const char *Directive = 0; + const char *Directive = nullptr; switch (Size) { default: break; case 1: Directive = MAI->getData8bitsDirective(); break; case 2: Directive = MAI->getData16bitsDirective(); break; case 4: Directive = MAI->getData32bitsDirective(); break; - case 8: - Directive = MAI->getData64bitsDirective(); - // If the target doesn't support 64-bit data, emit as two 32-bit halves. - if (Directive) break; + case 8: Directive = MAI->getData64bitsDirective(); break; + } + + if (!Directive) { int64_t IntValue; if (!Value->EvaluateAsAbsolute(IntValue)) report_fatal_error("Don't know how to emit this value."); - if (MAI->isLittleEndian()) { - EmitIntValue((uint32_t)(IntValue >> 0 ), 4); - EmitIntValue((uint32_t)(IntValue >> 32), 4); - } else { - EmitIntValue((uint32_t)(IntValue >> 32), 4); - EmitIntValue((uint32_t)(IntValue >> 0 ), 4); + + // 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. + 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; + // Calculate the byte offset of our partial emission taking into account + // the endianness of the target. + unsigned ByteOffset = + IsLittleEndian ? Emitted : (Remaining - EmissionSize); + uint64_t ValueToEmit = IntValue >> (ByteOffset * 8); + // We truncate our partial emission to fit within the bounds of the + // emission domain. This produces nicer output and silences potential + // truncation warnings when round tripping through another assembler. + ValueToEmit &= ~0ULL >> (64 - EmissionSize * 8); + EmitIntValue(ValueToEmit, EmissionSize); + Emitted += EmissionSize; } return; } @@ -714,13 +717,13 @@ void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) { } void MCAsmStreamer::EmitGPRel64Value(const MCExpr *Value) { - assert(MAI->getGPRel64Directive() != 0); + assert(MAI->getGPRel64Directive() != nullptr); OS << MAI->getGPRel64Directive() << *Value; EmitEOL(); } void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) { - assert(MAI->getGPRel32Directive() != 0); + assert(MAI->getGPRel32Directive() != nullptr); OS << MAI->getGPRel32Directive() << *Value; EmitEOL(); } @@ -750,12 +753,19 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, // emit alignments as a power of two if possible. if (isPowerOf2_32(ByteAlignment)) { switch (ValueSize) { - default: llvm_unreachable("Invalid size for machine code value!"); - case 1: OS << MAI->getAlignDirective(); break; - // FIXME: use MAI for this! - case 2: OS << ".p2alignw "; break; - case 4: OS << ".p2alignl "; break; - case 8: llvm_unreachable("Unsupported alignment size!"); + default: + llvm_unreachable("Invalid size for machine code value!"); + case 1: + OS << "\t.align\t"; + break; + case 2: + OS << ".p2alignw "; + break; + case 4: + OS << ".p2alignl "; + break; + case 8: + llvm_unreachable("Unsupported alignment size!"); } if (MAI->getAlignmentIsInBytes()) @@ -814,30 +824,42 @@ void MCAsmStreamer::EmitFileDirective(StringRef Filename) { EmitEOL(); } -bool MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, - StringRef Filename, unsigned CUID) { +unsigned MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo, + StringRef Directory, + StringRef Filename, + unsigned CUID) { + assert(CUID == 0); + + MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID); + unsigned NumFiles = Table.getMCDwarfFiles().size(); + FileNo = Table.getFile(Directory, Filename, FileNo); + if (FileNo == 0) + return 0; + if (NumFiles == Table.getMCDwarfFiles().size()) + return FileNo; + + SmallString<128> FullPathName; + if (!UseDwarfDirectory && !Directory.empty()) { if (sys::path::is_absolute(Filename)) - return EmitDwarfFileDirective(FileNo, "", Filename, CUID); - - SmallString<128> FullPathName = Directory; - sys::path::append(FullPathName, Filename); - return EmitDwarfFileDirective(FileNo, "", FullPathName, CUID); + Directory = ""; + else { + FullPathName = Directory; + sys::path::append(FullPathName, Filename); + Directory = ""; + Filename = FullPathName; + } } - if (UseLoc) { - OS << "\t.file\t" << FileNo << ' '; - if (!Directory.empty()) { - PrintQuotedString(Directory, OS); - OS << ' '; - } - PrintQuotedString(Filename, OS); - EmitEOL(); - // All .file will belong to a single CUID. - CUID = 0; + OS << "\t.file\t" << FileNo << ' '; + if (!Directory.empty()) { + PrintQuotedString(Directory, OS); + OS << ' '; } - return this->MCStreamer::EmitDwarfFileDirective(FileNo, Directory, Filename, - CUID); + PrintQuotedString(Filename, OS); + EmitEOL(); + + return FileNo; } void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, @@ -847,9 +869,6 @@ void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, StringRef FileName) { this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, Isa, Discriminator, FileName); - if (!UseLoc) - return; - OS << "\t.loc\t" << FileNo << " " << Line << " " << Column; if (Flags & DWARF2_FLAG_BASIC_BLOCK) OS << " basic_block"; @@ -869,9 +888,9 @@ void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, } if (Isa) - OS << "isa " << Isa; + OS << " isa " << Isa; if (Discriminator) - OS << "discriminator " << Discriminator; + OS << " discriminator " << Discriminator; if (IsVerboseAsm) { OS.PadToColumn(MAI->getCommentColumn()); @@ -881,6 +900,12 @@ void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, EmitEOL(); } +MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) { + // Always use the zeroth line table, since asm syntax only supports one line + // table for now. + return MCStreamer::getDwarfLineTableSymbol(0); +} + void MCAsmStreamer::EmitIdent(StringRef IdentString) { assert(MAI->hasIdentDirective() && ".ident directive not supported"); OS << "\t.ident\t"; @@ -890,10 +915,6 @@ void MCAsmStreamer::EmitIdent(StringRef IdentString) { void MCAsmStreamer::EmitCFISections(bool EH, bool Debug) { MCStreamer::EmitCFISections(EH, Debug); - - if (!UseCFI) - return; - OS << "\t.cfi_sections "; if (EH) { OS << ".eh_frame"; @@ -907,25 +928,14 @@ void MCAsmStreamer::EmitCFISections(bool EH, bool Debug) { } void MCAsmStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { - if (!UseCFI) { - RecordProcStart(Frame); - return; - } - OS << "\t.cfi_startproc"; + if (Frame.IsSimple) + OS << " simple"; EmitEOL(); } void MCAsmStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { - if (!UseCFI) { - RecordProcEnd(Frame); - return; - } - - // Put a dummy non-null value in Frame.End to mark that this frame has been - // closed. - Frame.End = (MCSymbol *) 1; - + MCStreamer::EmitCFIEndProcImpl(Frame); OS << "\t.cfi_endproc"; EmitEOL(); } @@ -942,10 +952,6 @@ void MCAsmStreamer::EmitRegisterName(int64_t Register) { void MCAsmStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { MCStreamer::EmitCFIDefCfa(Register, Offset); - - if (!UseCFI) - return; - OS << "\t.cfi_def_cfa "; EmitRegisterName(Register); OS << ", " << Offset; @@ -954,20 +960,12 @@ void MCAsmStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { void MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) { MCStreamer::EmitCFIDefCfaOffset(Offset); - - if (!UseCFI) - return; - OS << "\t.cfi_def_cfa_offset " << Offset; EmitEOL(); } void MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) { MCStreamer::EmitCFIDefCfaRegister(Register); - - if (!UseCFI) - return; - OS << "\t.cfi_def_cfa_register "; EmitRegisterName(Register); EmitEOL(); @@ -975,10 +973,6 @@ void MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) { void MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { this->MCStreamer::EmitCFIOffset(Register, Offset); - - if (!UseCFI) - return; - OS << "\t.cfi_offset "; EmitRegisterName(Register); OS << ", " << Offset; @@ -988,50 +982,30 @@ void MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { void MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) { MCStreamer::EmitCFIPersonality(Sym, Encoding); - - if (!UseCFI) - return; - OS << "\t.cfi_personality " << Encoding << ", " << *Sym; EmitEOL(); } void MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { MCStreamer::EmitCFILsda(Sym, Encoding); - - if (!UseCFI) - return; - OS << "\t.cfi_lsda " << Encoding << ", " << *Sym; EmitEOL(); } void MCAsmStreamer::EmitCFIRememberState() { MCStreamer::EmitCFIRememberState(); - - if (!UseCFI) - return; - OS << "\t.cfi_remember_state"; EmitEOL(); } void MCAsmStreamer::EmitCFIRestoreState() { MCStreamer::EmitCFIRestoreState(); - - if (!UseCFI) - return; - OS << "\t.cfi_restore_state"; EmitEOL(); } void MCAsmStreamer::EmitCFISameValue(int64_t Register) { MCStreamer::EmitCFISameValue(Register); - - if (!UseCFI) - return; - OS << "\t.cfi_same_value "; EmitRegisterName(Register); EmitEOL(); @@ -1039,10 +1013,6 @@ void MCAsmStreamer::EmitCFISameValue(int64_t Register) { void MCAsmStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) { MCStreamer::EmitCFIRelOffset(Register, Offset); - - if (!UseCFI) - return; - OS << "\t.cfi_rel_offset "; EmitRegisterName(Register); OS << ", " << Offset; @@ -1051,85 +1021,65 @@ void MCAsmStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) { void MCAsmStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) { MCStreamer::EmitCFIAdjustCfaOffset(Adjustment); - - if (!UseCFI) - return; - OS << "\t.cfi_adjust_cfa_offset " << Adjustment; EmitEOL(); } void MCAsmStreamer::EmitCFISignalFrame() { MCStreamer::EmitCFISignalFrame(); - - if (!UseCFI) - return; - OS << "\t.cfi_signal_frame"; EmitEOL(); } void MCAsmStreamer::EmitCFIUndefined(int64_t Register) { MCStreamer::EmitCFIUndefined(Register); - - if (!UseCFI) - return; - OS << "\t.cfi_undefined " << Register; EmitEOL(); } void MCAsmStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) { MCStreamer::EmitCFIRegister(Register1, Register2); - - if (!UseCFI) - return; - OS << "\t.cfi_register " << Register1 << ", " << Register2; EmitEOL(); } void MCAsmStreamer::EmitCFIWindowSave() { MCStreamer::EmitCFIWindowSave(); - - if (!UseCFI) - return; - OS << "\t.cfi_window_save"; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHStartProc(const MCSymbol *Symbol) { - MCStreamer::EmitWin64EHStartProc(Symbol); +void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) { + MCStreamer::EmitWinCFIStartProc(Symbol); OS << ".seh_proc " << *Symbol; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHEndProc() { - MCStreamer::EmitWin64EHEndProc(); +void MCAsmStreamer::EmitWinCFIEndProc() { + MCStreamer::EmitWinCFIEndProc(); OS << "\t.seh_endproc"; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHStartChained() { - MCStreamer::EmitWin64EHStartChained(); +void MCAsmStreamer::EmitWinCFIStartChained() { + MCStreamer::EmitWinCFIStartChained(); OS << "\t.seh_startchained"; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHEndChained() { - MCStreamer::EmitWin64EHEndChained(); +void MCAsmStreamer::EmitWinCFIEndChained() { + MCStreamer::EmitWinCFIEndChained(); OS << "\t.seh_endchained"; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, - bool Except) { - MCStreamer::EmitWin64EHHandler(Sym, Unwind, Except); +void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, + bool Except) { + MCStreamer::EmitWinEHHandler(Sym, Unwind, Except); OS << "\t.seh_handler " << *Sym; if (Unwind) @@ -1152,14 +1102,14 @@ static const MCSection *getWin64EHTableSection(StringRef suffix, SectionKind::getDataRel()); } -void MCAsmStreamer::EmitWin64EHHandlerData() { - MCStreamer::EmitWin64EHHandlerData(); +void MCAsmStreamer::EmitWinEHHandlerData() { + MCStreamer::EmitWinEHHandlerData(); // Switch sections. Don't call SwitchSection directly, because that will // cause the section switch to be visible in the emitted assembly. // We only do this so the section switch that terminates the handler // data block is visible. - MCWin64EHUnwindInfo *CurFrame = getCurrentW64UnwindInfo(); + MCWinFrameInfo *CurFrame = getCurrentWinFrameInfo(); StringRef suffix=MCWin64EHUnwindEmitter::GetSectionSuffix(CurFrame->Function); const MCSection *xdataSect = getWin64EHTableSection(suffix, getContext()); if (xdataSect) @@ -1169,43 +1119,43 @@ void MCAsmStreamer::EmitWin64EHHandlerData() { EmitEOL(); } -void MCAsmStreamer::EmitWin64EHPushReg(unsigned Register) { - MCStreamer::EmitWin64EHPushReg(Register); +void MCAsmStreamer::EmitWinCFIPushReg(unsigned Register) { + MCStreamer::EmitWinCFIPushReg(Register); OS << "\t.seh_pushreg " << Register; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHSetFrame(unsigned Register, unsigned Offset) { - MCStreamer::EmitWin64EHSetFrame(Register, Offset); +void MCAsmStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset) { + MCStreamer::EmitWinCFISetFrame(Register, Offset); OS << "\t.seh_setframe " << Register << ", " << Offset; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHAllocStack(unsigned Size) { - MCStreamer::EmitWin64EHAllocStack(Size); +void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size) { + MCStreamer::EmitWinCFIAllocStack(Size); OS << "\t.seh_stackalloc " << Size; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHSaveReg(unsigned Register, unsigned Offset) { - MCStreamer::EmitWin64EHSaveReg(Register, Offset); +void MCAsmStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset) { + MCStreamer::EmitWinCFISaveReg(Register, Offset); OS << "\t.seh_savereg " << Register << ", " << Offset; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHSaveXMM(unsigned Register, unsigned Offset) { - MCStreamer::EmitWin64EHSaveXMM(Register, Offset); +void MCAsmStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) { + MCStreamer::EmitWinCFISaveXMM(Register, Offset); OS << "\t.seh_savexmm " << Register << ", " << Offset; EmitEOL(); } -void MCAsmStreamer::EmitWin64EHPushFrame(bool Code) { - MCStreamer::EmitWin64EHPushFrame(Code); +void MCAsmStreamer::EmitWinCFIPushFrame(bool Code) { + MCStreamer::EmitWinCFIPushFrame(Code); OS << "\t.seh_pushframe"; if (Code) @@ -1213,19 +1163,20 @@ void MCAsmStreamer::EmitWin64EHPushFrame(bool Code) { EmitEOL(); } -void MCAsmStreamer::EmitWin64EHEndProlog(void) { - MCStreamer::EmitWin64EHEndProlog(); +void MCAsmStreamer::EmitWinCFIEndProlog(void) { + MCStreamer::EmitWinCFIEndProlog(); OS << "\t.seh_endprologue"; EmitEOL(); } -void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { +void MCAsmStreamer::AddEncodingComment(const MCInst &Inst, + const MCSubtargetInfo &STI) { raw_ostream &OS = GetCommentOS(); SmallString<256> Code; SmallVector<MCFixup, 4> Fixups; raw_svector_ostream VecOS(Code); - Emitter->EncodeInstruction(Inst, VecOS, Fixups); + Emitter->EncodeInstruction(Inst, VecOS, Fixups, STI); VecOS.flush(); // If we are showing fixups, create symbolic markers in the encoded @@ -1304,13 +1255,13 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { } } -void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { +void MCAsmStreamer::EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) { assert(getCurrentSection().first && "Cannot emit contents before setting section!"); // Show the encoding in a comment if we have a code emitter. if (Emitter) - AddEncodingComment(Inst); + AddEncodingComment(Inst, STI); // Show the MCInst if enabled. if (ShowInst) { @@ -1354,27 +1305,28 @@ void MCAsmStreamer::EmitRawTextImpl(StringRef String) { } void MCAsmStreamer::FinishImpl() { - // FIXME: This header is duplicated with MCObjectStreamer - // Dump out the dwarf file & directory tables and line tables. - const MCSymbol *LineSectionSymbol = NULL; - if (getContext().hasDwarfFiles() && !UseLoc) - LineSectionSymbol = MCDwarfFileTable::Emit(this); - // If we are generating dwarf for assembly source files dump out the sections. if (getContext().getGenDwarfForAssembly()) - MCGenDwarfInfo::Emit(this, LineSectionSymbol); - - if (!UseCFI) - EmitFrames(AsmBackend.get(), false); + MCGenDwarfInfo::Emit(this); + + // Emit the label for the line table, if requested - since the rest of the + // line table will be defined by .loc/.file directives, and not emitted + // directly, the label is the only work required here. + auto &Tables = getContext().getMCDwarfLineTables(); + if (!Tables.empty()) { + assert(Tables.size() == 1 && "asm output only supports one line table"); + if (auto *Label = Tables.begin()->second.getLabel()) { + SwitchSection(getContext().getObjectFileInfo()->getDwarfLineSection()); + EmitLabel(Label); + } + } } MCStreamer *llvm::createAsmStreamer(MCContext &Context, - MCTargetStreamer *TargetStreamer, formatted_raw_ostream &OS, - bool isVerboseAsm, bool useLoc, bool useCFI, - bool useDwarfDirectory, MCInstPrinter *IP, - MCCodeEmitter *CE, MCAsmBackend *MAB, - bool ShowInst) { - return new MCAsmStreamer(Context, TargetStreamer, OS, isVerboseAsm, useLoc, - useCFI, useDwarfDirectory, IP, CE, MAB, ShowInst); + bool isVerboseAsm, bool useDwarfDirectory, + MCInstPrinter *IP, MCCodeEmitter *CE, + MCAsmBackend *MAB, bool ShowInst) { + return new MCAsmStreamer(Context, OS, isVerboseAsm, useDwarfDirectory, IP, CE, + MAB, ShowInst); } diff --git a/contrib/llvm/lib/MC/MCAssembler.cpp b/contrib/llvm/lib/MC/MCAssembler.cpp index 68111f1..a8aad71 100644 --- a/contrib/llvm/lib/MC/MCAssembler.cpp +++ b/contrib/llvm/lib/MC/MCAssembler.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "assembler" #include "llvm/MC/MCAssembler.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" @@ -28,9 +27,12 @@ #include "llvm/Support/LEB128.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" - +#include "llvm/MC/MCSectionELF.h" +#include <tuple> using namespace llvm; +#define DEBUG_TYPE "assembler" + namespace { namespace stats { STATISTIC(EmittedFragments, "Number of emitted assembler fragments - total"); @@ -116,36 +118,89 @@ uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const { return F->Offset; } -uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const { +// Simple getSymbolOffset helper for the non-varibale case. +static bool getLabelOffset(const MCAsmLayout &Layout, const MCSymbolData &SD, + bool ReportError, uint64_t &Val) { + if (!SD.getFragment()) { + if (ReportError) + report_fatal_error("unable to evaluate offset to undefined symbol '" + + SD.getSymbol().getName() + "'"); + return false; + } + Val = Layout.getFragmentOffset(SD.getFragment()) + SD.getOffset(); + return true; +} + +static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, + const MCSymbolData *SD, bool ReportError, + uint64_t &Val) { const MCSymbol &S = SD->getSymbol(); - // If this is a variable, then recursively evaluate now. - if (S.isVariable()) { - MCValue Target; - if (!S.getVariableValue()->EvaluateAsRelocatable(Target, *this)) - report_fatal_error("unable to evaluate offset for variable '" + - S.getName() + "'"); + if (!S.isVariable()) + return getLabelOffset(Layout, *SD, ReportError, Val); - // Verify that any used symbols are defined. - if (Target.getSymA() && Target.getSymA()->getSymbol().isUndefined()) - report_fatal_error("unable to evaluate offset to undefined symbol '" + - Target.getSymA()->getSymbol().getName() + "'"); - if (Target.getSymB() && Target.getSymB()->getSymbol().isUndefined()) - report_fatal_error("unable to evaluate offset to undefined symbol '" + - Target.getSymB()->getSymbol().getName() + "'"); - - uint64_t Offset = Target.getConstant(); - if (Target.getSymA()) - Offset += getSymbolOffset(&Assembler.getSymbolData( - Target.getSymA()->getSymbol())); - if (Target.getSymB()) - Offset -= getSymbolOffset(&Assembler.getSymbolData( - Target.getSymB()->getSymbol())); - return Offset; + // If SD is a variable, evaluate it. + MCValue Target; + if (!S.getVariableValue()->EvaluateAsValue(Target, &Layout)) + report_fatal_error("unable to evaluate offset for variable '" + + S.getName() + "'"); + + uint64_t Offset = Target.getConstant(); + + const MCAssembler &Asm = Layout.getAssembler(); + + const MCSymbolRefExpr *A = Target.getSymA(); + if (A) { + uint64_t ValA; + if (!getLabelOffset(Layout, Asm.getSymbolData(A->getSymbol()), ReportError, + ValA)) + return false; + Offset += ValA; } - assert(SD->getFragment() && "Invalid getOffset() on undefined symbol!"); - return getFragmentOffset(SD->getFragment()) + SD->getOffset(); + const MCSymbolRefExpr *B = Target.getSymB(); + if (B) { + uint64_t ValB; + if (!getLabelOffset(Layout, Asm.getSymbolData(B->getSymbol()), ReportError, + ValB)) + return false; + Offset -= ValB; + } + + Val = Offset; + return true; +} + +bool MCAsmLayout::getSymbolOffset(const MCSymbolData *SD, uint64_t &Val) const { + return getSymbolOffsetImpl(*this, SD, false, Val); +} + +uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const { + uint64_t Val; + getSymbolOffsetImpl(*this, SD, true, Val); + return Val; +} + +const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const { + if (!Symbol.isVariable()) + return &Symbol; + + const MCExpr *Expr = Symbol.getVariableValue(); + MCValue Value; + if (!Expr->EvaluateAsValue(Value, this)) + llvm_unreachable("Invalid Expression"); + + const MCSymbolRefExpr *RefB = Value.getSymB(); + if (RefB) + Assembler.getContext().FatalError( + SMLoc(), Twine("symbol '") + RefB->getSymbol().getName() + + "' could not be evaluated in a subtraction expression"); + + const MCSymbolRefExpr *A = Value.getSymA(); + if (!A) + return nullptr; + + return &A->getSymbol(); } uint64_t MCAsmLayout::getSectionAddressSize(const MCSectionData *SD) const { @@ -212,7 +267,7 @@ MCFragment::~MCFragment() { } MCFragment::MCFragment(FragmentType _Kind, MCSectionData *_Parent) - : Kind(_Kind), Parent(_Parent), Atom(0), Offset(~UINT64_C(0)) + : Kind(_Kind), Parent(_Parent), Atom(nullptr), Offset(~UINT64_C(0)) { if (Parent) Parent->getFragmentList().push_back(this); @@ -230,7 +285,7 @@ MCEncodedFragmentWithFixups::~MCEncodedFragmentWithFixups() { /* *** */ -MCSectionData::MCSectionData() : Section(0) {} +MCSectionData::MCSectionData() : Section(nullptr) {} MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A) : Section(&_Section), @@ -250,7 +305,7 @@ MCSectionData::getSubsectionInsertionPoint(unsigned Subsection) { SmallVectorImpl<std::pair<unsigned, MCFragment *> >::iterator MI = std::lower_bound(SubsectionFragmentMap.begin(), SubsectionFragmentMap.end(), - std::make_pair(Subsection, (MCFragment *)0)); + std::make_pair(Subsection, (MCFragment *)nullptr)); bool ExactMatch = false; if (MI != SubsectionFragmentMap.end()) { ExactMatch = MI->first == Subsection; @@ -275,13 +330,13 @@ MCSectionData::getSubsectionInsertionPoint(unsigned Subsection) { /* *** */ -MCSymbolData::MCSymbolData() : Symbol(0) {} +MCSymbolData::MCSymbolData() : Symbol(nullptr) {} MCSymbolData::MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset, MCAssembler *A) : Symbol(&_Symbol), Fragment(_Fragment), Offset(_Offset), IsExternal(false), IsPrivateExtern(false), - CommonSize(0), SymbolSize(0), CommonAlign(0), + CommonSize(0), SymbolSize(nullptr), CommonAlign(0), Flags(0), Index(0) { if (A) @@ -296,6 +351,7 @@ MCAssembler::MCAssembler(MCContext &Context_, MCAsmBackend &Backend_, : Context(Context_), Backend(Backend_), Emitter(Emitter_), Writer(Writer_), OS(OS_), BundleAlignSize(0), RelaxAll(false), NoExecStack(false), SubsectionsViaSymbols(false), ELFHeaderEFlags(0) { + VersionMinInfo.Major = 0; // Major version == 0 for "none specified" } MCAssembler::~MCAssembler() { @@ -318,6 +374,32 @@ void MCAssembler::reset() { getBackend().reset(); getEmitter().reset(); getWriter().reset(); + getLOHContainer().reset(); +} + +bool MCAssembler::isThumbFunc(const MCSymbol *Symbol) const { + if (ThumbFuncs.count(Symbol)) + return true; + + if (!Symbol->isVariable()) + return false; + + // FIXME: It looks like gas supports some cases of the form "foo + 2". It + // is not clear if that is a bug or a feature. + const MCExpr *Expr = Symbol->getVariableValue(); + const MCSymbolRefExpr *Ref = dyn_cast<MCSymbolRefExpr>(Expr); + if (!Ref) + return false; + + if (Ref->getKind() != MCSymbolRefExpr::VK_None) + return false; + + const MCSymbol &Sym = Ref->getSymbol(); + if (!isThumbFunc(&Sym)) + return false; + + ThumbFuncs.insert(Symbol); // Cache it. + return true; } bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const { @@ -340,24 +422,39 @@ const MCSymbolData *MCAssembler::getAtom(const MCSymbolData *SD) const { // Absolute and undefined symbols have no defining atom. if (!SD->getFragment()) - return 0; + return nullptr; // Non-linker visible symbols in sections which can't be atomized have no // defining atom. if (!getBackend().isSectionAtomizable( SD->getFragment()->getParent()->getSection())) - return 0; + return nullptr; // Otherwise, return the atom for the containing fragment. return SD->getFragment()->getAtom(); } +// Try to fully compute Expr to an absolute value and if that fails produce +// a relocatable expr. +// FIXME: Should this be the behavior of EvaluateAsRelocatable itself? +static bool evaluate(const MCExpr &Expr, const MCAsmLayout &Layout, + MCValue &Target) { + if (Expr.EvaluateAsValue(Target, &Layout)) + if (Target.isAbsolute()) + return true; + return Expr.EvaluateAsRelocatable(Target, &Layout); +} + bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, MCValue &Target, uint64_t &Value) const { ++stats::evaluateFixup; - if (!Fixup.getValue()->EvaluateAsRelocatable(Target, Layout)) + // FIXME: This code has some duplication with RecordRelocation. We should + // probably merge the two into a single callback that tries to evaluate a + // fixup and records a relocation if one is needed. + const MCExpr *Expr = Fixup.getValue(); + if (!evaluate(*Expr, Layout, Target)) getContext().FatalError(Fixup.getLoc(), "expected relocatable expression"); bool IsPCRel = Backend.getFixupKindInfo( @@ -701,8 +798,13 @@ void MCAssembler::writeSectionData(const MCSectionData *SD, assert(DF.fixup_begin() == DF.fixup_end() && "Cannot have fixups in virtual section!"); for (unsigned i = 0, e = DF.getContents().size(); i != e; ++i) - assert(DF.getContents()[i] == 0 && - "Invalid data value for virtual section!"); + if (DF.getContents()[i]) { + if (auto *ELFSec = dyn_cast<const MCSectionELF>(&SD->getSection())) + report_fatal_error("non-zero initializer found in section '" + + ELFSec->getSectionName() + "'"); + else + report_fatal_error("non-zero initializer found in virtual section"); + } break; } case MCFragment::FT_Align: @@ -734,21 +836,23 @@ void MCAssembler::writeSectionData(const MCSectionData *SD, Layout.getSectionAddressSize(SD)); } - -uint64_t MCAssembler::handleFixup(const MCAsmLayout &Layout, - MCFragment &F, - const MCFixup &Fixup) { - // Evaluate the fixup. - MCValue Target; - uint64_t FixedValue; - if (!evaluateFixup(Layout, Fixup, &F, Target, FixedValue)) { - // The fixup was unresolved, we need a relocation. Inform the object - // writer of the relocation, and give it an opportunity to adjust the - // fixup value if need be. - getWriter().RecordRelocation(*this, Layout, &F, Fixup, Target, FixedValue); - } - return FixedValue; - } +std::pair<uint64_t, bool> MCAssembler::handleFixup(const MCAsmLayout &Layout, + MCFragment &F, + const MCFixup &Fixup) { + // Evaluate the fixup. + MCValue Target; + uint64_t FixedValue; + bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags & + MCFixupKindInfo::FKF_IsPCRel; + if (!evaluateFixup(Layout, Fixup, &F, Target, FixedValue)) { + // The fixup was unresolved, we need a relocation. Inform the object + // writer of the relocation, and give it an opportunity to adjust the + // fixup value if need be. + getWriter().RecordRelocation(*this, Layout, &F, Fixup, Target, IsPCRel, + FixedValue); + } + return std::make_pair(FixedValue, IsPCRel); +} void MCAssembler::Finish() { DEBUG_WITH_TYPE("mc-dump", { @@ -811,9 +915,11 @@ void MCAssembler::Finish() { for (MCEncodedFragmentWithFixups::fixup_iterator it3 = F->fixup_begin(), ie3 = F->fixup_end(); it3 != ie3; ++it3) { MCFixup &Fixup = *it3; - uint64_t FixedValue = handleFixup(Layout, *F, Fixup); + uint64_t FixedValue; + bool IsPCRel; + std::tie(FixedValue, IsPCRel) = handleFixup(Layout, *F, Fixup); getBackend().applyFixup(Fixup, F->getContents().data(), - F->getContents().size(), FixedValue); + F->getContents().size(), FixedValue, IsPCRel); } } } @@ -875,7 +981,7 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout, SmallVector<MCFixup, 4> Fixups; SmallString<256> Code; raw_svector_ostream VecOS(Code); - getEmitter().EncodeInstruction(Relaxed, VecOS, Fixups); + getEmitter().EncodeInstruction(Relaxed, VecOS, Fixups, F.getSubtargetInfo()); VecOS.flush(); // Update the fragment. @@ -942,7 +1048,7 @@ bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD) { // remain NULL if none were relaxed. // When a fragment is relaxed, all the fragments following it should get // invalidated because their offset is going to change. - MCFragment *FirstRelaxedFragment = NULL; + MCFragment *FirstRelaxedFragment = nullptr; // Attempt to relax all the fragments in the section. for (MCSectionData::iterator I = SD.begin(), IE = SD.end(); I != IE; ++I) { @@ -1137,7 +1243,7 @@ void MCSectionData::dump() { OS << "]>"; } -void MCSymbolData::dump() { +void MCSymbolData::dump() const { raw_ostream &OS = llvm::errs(); OS << "<MCSymbolData Symbol:" << getSymbol() diff --git a/contrib/llvm/lib/MC/MCContext.cpp b/contrib/llvm/lib/MC/MCContext.cpp index a0acda5..7702da3 100644 --- a/contrib/llvm/lib/MC/MCContext.cpp +++ b/contrib/llvm/lib/MC/MCContext.cpp @@ -25,43 +25,31 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Signals.h" #include "llvm/Support/SourceMgr.h" - #include <map> using namespace llvm; -typedef std::pair<std::string, std::string> SectionGroupPair; - -typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy; -typedef std::map<SectionGroupPair, const MCSectionELF *> ELFUniqueMapTy; -typedef std::map<SectionGroupPair, const MCSectionCOFF *> COFFUniqueMapTy; - MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri, const MCObjectFileInfo *mofi, const SourceMgr *mgr, - bool DoAutoReset) : - SrcMgr(mgr), MAI(mai), MRI(mri), MOFI(mofi), - Allocator(), Symbols(Allocator), UsedNames(Allocator), - NextUniqueID(0), - CurrentDwarfLoc(0,0,0,DWARF2_FLAG_IS_STMT,0,0), - DwarfLocSeen(false), GenDwarfForAssembly(false), GenDwarfFileNumber(0), - AllowTemporaryLabels(true), DwarfCompileUnitID(0), AutoReset(DoAutoReset) { - - error_code EC = llvm::sys::fs::current_path(CompilationDir); + bool DoAutoReset) + : SrcMgr(mgr), MAI(mai), MRI(mri), MOFI(mofi), Allocator(), + Symbols(Allocator), UsedNames(Allocator), NextUniqueID(0), + CurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0), DwarfLocSeen(false), + GenDwarfForAssembly(false), GenDwarfFileNumber(0), DwarfVersion(4), + AllowTemporaryLabels(true), DwarfCompileUnitID(0), + AutoReset(DoAutoReset) { + + std::error_code EC = llvm::sys::fs::current_path(CompilationDir); if (EC) CompilationDir.clear(); - MachOUniquingMap = 0; - ELFUniquingMap = 0; - COFFUniquingMap = 0; - SecureLogFile = getenv("AS_SECURE_LOG_FILE"); - SecureLog = 0; + SecureLog = nullptr; SecureLogUsed = false; - if (SrcMgr && SrcMgr->getNumBuffers() > 0) - MainFileName = SrcMgr->getMemoryBuffer(0)->getBufferIdentifier(); - else - MainFileName = ""; + if (SrcMgr && SrcMgr->getNumBuffers()) + MainFileName = + SrcMgr->getMemoryBuffer(SrcMgr->getMainFileID())->getBufferIdentifier(); } MCContext::~MCContext() { @@ -71,7 +59,7 @@ MCContext::~MCContext() { // NOTE: The symbols are all allocated out of a bump pointer allocator, // we don't need to free them here. - + // If the stream for the .secure_log_unique directive was created free it. delete (raw_ostream*)SecureLog; } @@ -85,23 +73,15 @@ void MCContext::reset() { Symbols.clear(); Allocator.Reset(); Instances.clear(); - MCDwarfFilesCUMap.clear(); - MCDwarfDirsCUMap.clear(); + MCDwarfLineTablesCUMap.clear(); MCGenDwarfLabelEntries.clear(); DwarfDebugFlags = StringRef(); - MCLineSections.clear(); - MCLineSectionOrder.clear(); DwarfCompileUnitID = 0; - MCLineTableSymbols.clear(); CurrentDwarfLoc = MCDwarfLoc(0,0,0,DWARF2_FLAG_IS_STMT,0,0); - // If we have the MachO uniquing map, free it. - delete (MachOUniqueMapTy*)MachOUniquingMap; - delete (ELFUniqueMapTy*)ELFUniquingMap; - delete (COFFUniqueMapTy*)COFFUniquingMap; - MachOUniquingMap = 0; - ELFUniquingMap = 0; - COFFUniquingMap = 0; + MachOUniquingMap.clear(); + ELFUniquingMap.clear(); + COFFUniquingMap.clear(); NextUniqueID = 0; AllowTemporaryLabels = true; @@ -138,7 +118,7 @@ MCSymbol *MCContext::CreateSymbol(StringRef Name) { StringMapEntry<bool> *NameEntry = &UsedNames.GetOrCreateValue(Name); if (NameEntry->getValue()) { - assert(isTemporary && "Cannot rename non temporary symbols"); + assert(isTemporary && "Cannot rename non-temporary symbols"); SmallString<128> NewName = Name; do { NewName.resize(Name.size()); @@ -157,8 +137,14 @@ MCSymbol *MCContext::CreateSymbol(StringRef Name) { MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) { SmallString<128> NameSV; - Name.toVector(NameSV); - return GetOrCreateSymbol(NameSV.str()); + return GetOrCreateSymbol(Name.toStringRef(NameSV)); +} + +MCSymbol *MCContext::CreateLinkerPrivateTempSymbol() { + SmallString<128> NameSV; + raw_svector_ostream(NameSV) + << MAI->getLinkerPrivateGlobalPrefix() << "tmp" << NextUniqueID++; + return CreateSymbol(NameSV); } MCSymbol *MCContext::CreateTempSymbol() { @@ -168,32 +154,39 @@ MCSymbol *MCContext::CreateTempSymbol() { return CreateSymbol(NameSV); } -unsigned MCContext::NextInstance(int64_t LocalLabelVal) { +unsigned MCContext::NextInstance(unsigned LocalLabelVal) { MCLabel *&Label = Instances[LocalLabelVal]; if (!Label) Label = new (*this) MCLabel(0); return Label->incInstance(); } -unsigned MCContext::GetInstance(int64_t LocalLabelVal) { +unsigned MCContext::GetInstance(unsigned LocalLabelVal) { MCLabel *&Label = Instances[LocalLabelVal]; if (!Label) Label = new (*this) MCLabel(0); return Label->getInstance(); } -MCSymbol *MCContext::CreateDirectionalLocalSymbol(int64_t LocalLabelVal) { - return GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + - Twine(LocalLabelVal) + - "\2" + - Twine(NextInstance(LocalLabelVal))); +MCSymbol *MCContext::getOrCreateDirectionalLocalSymbol(unsigned LocalLabelVal, + unsigned Instance) { + MCSymbol *&Sym = LocalSymbols[std::make_pair(LocalLabelVal, Instance)]; + if (!Sym) + Sym = CreateTempSymbol(); + return Sym; } -MCSymbol *MCContext::GetDirectionalLocalSymbol(int64_t LocalLabelVal, - int bORf) { - return GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + - Twine(LocalLabelVal) + - "\2" + - Twine(GetInstance(LocalLabelVal) + bORf)); + +MCSymbol *MCContext::CreateDirectionalLocalSymbol(unsigned LocalLabelVal) { + unsigned Instance = NextInstance(LocalLabelVal); + return getOrCreateDirectionalLocalSymbol(LocalLabelVal, Instance); +} + +MCSymbol *MCContext::GetDirectionalLocalSymbol(unsigned LocalLabelVal, + bool Before) { + unsigned Instance = GetInstance(LocalLabelVal); + if (!Before) + ++Instance; + return getOrCreateDirectionalLocalSymbol(LocalLabelVal, Instance); } MCSymbol *MCContext::LookupSymbol(StringRef Name) const { @@ -219,11 +212,6 @@ getMachOSection(StringRef Segment, StringRef Section, // may not have the same flags as the requested section, if so this should be // diagnosed by the client as an error. - // Create the map if it doesn't already exist. - if (MachOUniquingMap == 0) - MachOUniquingMap = new MachOUniqueMapTy(); - MachOUniqueMapTy &Map = *(MachOUniqueMapTy*)MachOUniquingMap; - // Form the name to look up. SmallString<64> Name; Name += Segment; @@ -231,7 +219,7 @@ getMachOSection(StringRef Segment, StringRef Section, Name += Section; // Do the lookup, if we have a hit, return it. - const MCSectionMachO *&Entry = Map[Name.str()]; + const MCSectionMachO *&Entry = MachOUniquingMap[Name.str()]; if (Entry) return Entry; // Otherwise, return a new section. @@ -245,64 +233,71 @@ getELFSection(StringRef Section, unsigned Type, unsigned Flags, return getELFSection(Section, Type, Flags, Kind, 0, ""); } +void MCContext::renameELFSection(const MCSectionELF *Section, StringRef Name) { + StringRef GroupName; + if (const MCSymbol *Group = Section->getGroup()) + GroupName = Group->getName(); + + ELFUniquingMap.erase(SectionGroupPair(Section->getSectionName(), GroupName)); + auto I = + ELFUniquingMap.insert(std::make_pair(SectionGroupPair(Name, GroupName), + Section)).first; + StringRef CachedName = I->first.first; + const_cast<MCSectionELF*>(Section)->setSectionName(CachedName); +} + const MCSectionELF *MCContext:: getELFSection(StringRef Section, unsigned Type, unsigned Flags, SectionKind Kind, unsigned EntrySize, StringRef Group) { - if (ELFUniquingMap == 0) - ELFUniquingMap = new ELFUniqueMapTy(); - ELFUniqueMapTy &Map = *(ELFUniqueMapTy*)ELFUniquingMap; - // Do the lookup, if we have a hit, return it. - std::pair<ELFUniqueMapTy::iterator, bool> Entry = Map.insert( - std::make_pair(SectionGroupPair(Section, Group), (MCSectionELF *)0)); - if (!Entry.second) return Entry.first->second; + auto IterBool = ELFUniquingMap.insert( + std::make_pair(SectionGroupPair(Section, Group), nullptr)); + auto &Entry = *IterBool.first; + if (!IterBool.second) return Entry.second; // Possibly refine the entry size first. if (!EntrySize) { EntrySize = MCSectionELF::DetermineEntrySize(Kind); } - MCSymbol *GroupSym = NULL; + MCSymbol *GroupSym = nullptr; if (!Group.empty()) GroupSym = GetOrCreateSymbol(Group); - MCSectionELF *Result = new (*this) MCSectionELF( - Entry.first->first.first, Type, Flags, Kind, EntrySize, GroupSym); - Entry.first->second = Result; + StringRef CachedName = Entry.first.first; + MCSectionELF *Result = new (*this) + MCSectionELF(CachedName, Type, Flags, Kind, EntrySize, GroupSym); + Entry.second = Result; return Result; } const MCSectionELF *MCContext::CreateELFGroupSection() { MCSectionELF *Result = new (*this) MCSectionELF(".group", ELF::SHT_GROUP, 0, - SectionKind::getReadOnly(), 4, NULL); + SectionKind::getReadOnly(), 4, nullptr); return Result; } -const MCSectionCOFF * -MCContext::getCOFFSection(StringRef Section, unsigned Characteristics, - SectionKind Kind, StringRef COMDATSymName, - int Selection, const MCSectionCOFF *Assoc) { - if (COFFUniquingMap == 0) - COFFUniquingMap = new COFFUniqueMapTy(); - COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)COFFUniquingMap; - +const MCSectionCOFF *MCContext::getCOFFSection(StringRef Section, + unsigned Characteristics, + SectionKind Kind, + StringRef COMDATSymName, + int Selection) { // Do the lookup, if we have a hit, return it. - SectionGroupPair P(Section, COMDATSymName); - std::pair<COFFUniqueMapTy::iterator, bool> Entry = - Map.insert(std::make_pair(P, (MCSectionCOFF *)0)); - COFFUniqueMapTy::iterator Iter = Entry.first; - if (!Entry.second) + SectionGroupTriple T(Section, COMDATSymName, Selection); + auto IterBool = COFFUniquingMap.insert(std::make_pair(T, nullptr)); + auto Iter = IterBool.first; + if (!IterBool.second) return Iter->second; - const MCSymbol *COMDATSymbol = NULL; + MCSymbol *COMDATSymbol = nullptr; if (!COMDATSymName.empty()) COMDATSymbol = GetOrCreateSymbol(COMDATSymName); - MCSectionCOFF *Result = - new (*this) MCSectionCOFF(Iter->first.first, Characteristics, - COMDATSymbol, Selection, Assoc, Kind); + StringRef CachedName = std::get<0>(Iter->first); + MCSectionCOFF *Result = new (*this) + MCSectionCOFF(CachedName, Characteristics, COMDATSymbol, Selection, Kind); Iter->second = Result; return Result; @@ -315,14 +310,10 @@ MCContext::getCOFFSection(StringRef Section, unsigned Characteristics, } const MCSectionCOFF *MCContext::getCOFFSection(StringRef Section) { - if (COFFUniquingMap == 0) - COFFUniquingMap = new COFFUniqueMapTy(); - COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)COFFUniquingMap; - - SectionGroupPair P(Section, ""); - COFFUniqueMapTy::iterator Iter = Map.find(P); - if (Iter == Map.end()) - return 0; + SectionGroupTriple T(Section, "", 0); + auto Iter = COFFUniquingMap.find(T); + if (Iter == COFFUniquingMap.end()) + return nullptr; return Iter->second; } @@ -336,84 +327,48 @@ const MCSectionCOFF *MCContext::getCOFFSection(StringRef Section) { /// allocated file number is returned. The file numbers may be in any order. unsigned MCContext::GetDwarfFile(StringRef Directory, StringRef FileName, unsigned FileNumber, unsigned CUID) { - // TODO: a FileNumber of zero says to use the next available file number. - // Note: in GenericAsmParser::ParseDirectiveFile() FileNumber was checked - // to not be less than one. This needs to be change to be not less than zero. - - SmallVectorImpl<MCDwarfFile *>& MCDwarfFiles = MCDwarfFilesCUMap[CUID]; - SmallVectorImpl<StringRef>& MCDwarfDirs = MCDwarfDirsCUMap[CUID]; - // Make space for this FileNumber in the MCDwarfFiles vector if needed. - if (FileNumber >= MCDwarfFiles.size()) { - MCDwarfFiles.resize(FileNumber + 1); - } else { - MCDwarfFile *&ExistingFile = MCDwarfFiles[FileNumber]; - if (ExistingFile) - // It is an error to use see the same number more than once. - return 0; - } - - // Get the new MCDwarfFile slot for this FileNumber. - MCDwarfFile *&File = MCDwarfFiles[FileNumber]; - - if (Directory.empty()) { - // Separate the directory part from the basename of the FileName. - StringRef tFileName = sys::path::filename(FileName); - if (!tFileName.empty()) { - Directory = sys::path::parent_path(FileName); - if (!Directory.empty()) - FileName = tFileName; - } - } - - // Find or make a entry in the MCDwarfDirs vector for this Directory. - // Capture directory name. - unsigned DirIndex; - if (Directory.empty()) { - // For FileNames with no directories a DirIndex of 0 is used. - DirIndex = 0; - } else { - DirIndex = 0; - for (unsigned End = MCDwarfDirs.size(); DirIndex < End; DirIndex++) { - if (Directory == MCDwarfDirs[DirIndex]) - break; - } - if (DirIndex >= MCDwarfDirs.size()) { - char *Buf = static_cast<char *>(Allocate(Directory.size())); - memcpy(Buf, Directory.data(), Directory.size()); - MCDwarfDirs.push_back(StringRef(Buf, Directory.size())); - } - // The DirIndex is one based, as DirIndex of 0 is used for FileNames with - // no directories. MCDwarfDirs[] is unlike MCDwarfFiles[] in that the - // directory names are stored at MCDwarfDirs[DirIndex-1] where FileNames - // are stored at MCDwarfFiles[FileNumber].Name . - DirIndex++; - } - - // Now make the MCDwarfFile entry and place it in the slot in the MCDwarfFiles - // vector. - char *Buf = static_cast<char *>(Allocate(FileName.size())); - memcpy(Buf, FileName.data(), FileName.size()); - File = new (*this) MCDwarfFile(StringRef(Buf, FileName.size()), DirIndex); - - // return the allocated FileNumber. - return FileNumber; + MCDwarfLineTable &Table = MCDwarfLineTablesCUMap[CUID]; + return Table.getFile(Directory, FileName, FileNumber); } /// isValidDwarfFileNumber - takes a dwarf file number and returns true if it /// currently is assigned and false otherwise. bool MCContext::isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID) { - SmallVectorImpl<MCDwarfFile *>& MCDwarfFiles = MCDwarfFilesCUMap[CUID]; + const SmallVectorImpl<MCDwarfFile>& MCDwarfFiles = getMCDwarfFiles(CUID); if(FileNumber == 0 || FileNumber >= MCDwarfFiles.size()) return false; - return MCDwarfFiles[FileNumber] != 0; + return !MCDwarfFiles[FileNumber].Name.empty(); +} + +/// finalizeDwarfSections - Emit end symbols for each non-empty code section. +/// Also remove empty sections from SectionStartEndSyms, to avoid generating +/// useless debug info for them. +void MCContext::finalizeDwarfSections(MCStreamer &MCOS) { + MCContext &context = MCOS.getContext(); + + auto sec = SectionStartEndSyms.begin(); + while (sec != SectionStartEndSyms.end()) { + assert(sec->second.first && "Start symbol must be set by now"); + MCOS.SwitchSection(sec->first); + if (MCOS.mayHaveInstructions()) { + MCSymbol *SectionEndSym = context.CreateTempSymbol(); + MCOS.EmitLabel(SectionEndSym); + sec->second.second = SectionEndSym; + ++sec; + } else { + MapVector<const MCSection *, std::pair<MCSymbol *, MCSymbol *> >::iterator + to_erase = sec; + sec = SectionStartEndSyms.erase(to_erase); + } + } } -void MCContext::FatalError(SMLoc Loc, const Twine &Msg) { +void MCContext::FatalError(SMLoc Loc, const Twine &Msg) const { // If we have a source manager and a location, use it. Otherwise just // use the generic report_fatal_error(). if (!SrcMgr || Loc == SMLoc()) - report_fatal_error(Msg); + report_fatal_error(Msg, false); // Use the source manager to print the message. SrcMgr->PrintMessage(Loc, SourceMgr::DK_Error, Msg); diff --git a/contrib/llvm/lib/MC/MCDisassembler.cpp b/contrib/llvm/lib/MC/MCDisassembler.cpp index bfd51ab..77d9ce1 100644 --- a/contrib/llvm/lib/MC/MCDisassembler.cpp +++ b/contrib/llvm/lib/MC/MCDisassembler.cpp @@ -16,23 +16,6 @@ using namespace llvm; MCDisassembler::~MCDisassembler() { } -void -MCDisassembler::setupForSymbolicDisassembly( - LLVMOpInfoCallback GetOpInfo, - LLVMSymbolLookupCallback SymbolLookUp, - void *DisInfo, - MCContext *Ctx, - OwningPtr<MCRelocationInfo> &RelInfo) { - this->GetOpInfo = GetOpInfo; - this->SymbolLookUp = SymbolLookUp; - this->DisInfo = DisInfo; - this->Ctx = Ctx; - assert(Ctx != 0 && "No MCContext given for symbolic disassembly"); - if (!Symbolizer) - Symbolizer.reset(new MCExternalSymbolizer(*Ctx, RelInfo, GetOpInfo, - SymbolLookUp, DisInfo)); -} - bool MCDisassembler::tryAddingSymbolicOperand(MCInst &Inst, int64_t Value, uint64_t Address, bool IsBranch, uint64_t Offset, @@ -51,6 +34,6 @@ void MCDisassembler::tryAddingPcLoadReferenceComment(int64_t Value, Symbolizer->tryAddingPcLoadReferenceComment(cStream, Value, Address); } -void MCDisassembler::setSymbolizer(OwningPtr<MCSymbolizer> &Symzer) { - Symbolizer.reset(Symzer.take()); +void MCDisassembler::setSymbolizer(std::unique_ptr<MCSymbolizer> Symzer) { + Symbolizer = std::move(Symzer); } diff --git a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp index a0066c8..0530c26 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp +++ b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp @@ -24,9 +24,6 @@ #include "llvm/Support/MemoryObject.h" #include "llvm/Support/TargetRegistry.h" -namespace llvm { -class Target; -} // namespace llvm using namespace llvm; // LLVMCreateDisasm() creates a disassembler for the TripleName. Symbolic @@ -44,20 +41,20 @@ LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, std::string Error; const Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error); if (!TheTarget) - return 0; + return nullptr; const MCRegisterInfo *MRI = TheTarget->createMCRegInfo(Triple); if (!MRI) - return 0; + return nullptr; // Get the assembler info needed to setup the MCContext. const MCAsmInfo *MAI = TheTarget->createMCAsmInfo(*MRI, Triple); if (!MAI) - return 0; + return nullptr; const MCInstrInfo *MII = TheTarget->createMCInstrInfo(); if (!MII) - return 0; + return nullptr; // Package up features to be passed to target/subtarget std::string FeaturesStr; @@ -65,42 +62,40 @@ LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, const MCSubtargetInfo *STI = TheTarget->createMCSubtargetInfo(Triple, CPU, FeaturesStr); if (!STI) - return 0; + return nullptr; // Set up the MCContext for creating symbols and MCExpr's. - MCContext *Ctx = new MCContext(MAI, MRI, 0); + MCContext *Ctx = new MCContext(MAI, MRI, nullptr); if (!Ctx) - return 0; + return nullptr; // Set up disassembler. - MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI); + MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI, *Ctx); if (!DisAsm) - return 0; + return nullptr; - OwningPtr<MCRelocationInfo> RelInfo( - TheTarget->createMCRelocationInfo(Triple, *Ctx)); + std::unique_ptr<MCRelocationInfo> RelInfo( + TheTarget->createMCRelocationInfo(Triple, *Ctx)); if (!RelInfo) - return 0; + return nullptr; + + std::unique_ptr<MCSymbolizer> Symbolizer(TheTarget->createMCSymbolizer( + Triple, GetOpInfo, SymbolLookUp, DisInfo, Ctx, RelInfo.release())); + DisAsm->setSymbolizer(std::move(Symbolizer)); - OwningPtr<MCSymbolizer> Symbolizer( - TheTarget->createMCSymbolizer(Triple, GetOpInfo, SymbolLookUp, DisInfo, - Ctx, RelInfo.take())); - DisAsm->setSymbolizer(Symbolizer); - DisAsm->setupForSymbolicDisassembly(GetOpInfo, SymbolLookUp, DisInfo, - Ctx, RelInfo); // Set up the instruction printer. int AsmPrinterVariant = MAI->getAssemblerDialect(); MCInstPrinter *IP = TheTarget->createMCInstPrinter(AsmPrinterVariant, *MAI, *MII, *MRI, *STI); if (!IP) - return 0; + return nullptr; LLVMDisasmContext *DC = new LLVMDisasmContext(Triple, DisInfo, TagType, GetOpInfo, SymbolLookUp, TheTarget, MAI, MRI, STI, MII, Ctx, DisAsm, IP); if (!DC) - return 0; + return nullptr; DC->setCPU(CPU); return DC; @@ -132,11 +127,11 @@ class DisasmMemoryObject : public MemoryObject { public: DisasmMemoryObject(uint8_t *bytes, uint64_t size, uint64_t basePC) : Bytes(bytes), Size(size), BasePC(basePC) {} - - uint64_t getBase() const { return BasePC; } - uint64_t getExtent() const { return Size; } - int readByte(uint64_t Addr, uint8_t *Byte) const { + uint64_t getBase() const override { return BasePC; } + uint64_t getExtent() const override { return Size; } + + int readByte(uint64_t Addr, uint8_t *Byte) const override { if (Addr - BasePC >= Size) return -1; *Byte = Bytes[Addr - BasePC]; @@ -298,6 +293,7 @@ size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes, emitLatency(DC, Inst); emitComments(DC, FormattedOS); + OS.flush(); assert(OutStringSize != 0 && "Output buffer cannot be zero size"); size_t OutputSize = std::min(OutStringSize-1, InsnStr.size()); diff --git a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h index 4855af2..d1d40cd 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h +++ b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h @@ -18,7 +18,6 @@ #define LLVM_MC_DISASSEMBLER_H #include "llvm-c/Disassembler.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" #include <string> @@ -56,23 +55,23 @@ private: // LLVMDisasmInstruction(). // // The LLVM target corresponding to the disassembler. - // FIXME: using llvm::OwningPtr<const llvm::Target> causes a malloc error + // FIXME: using std::unique_ptr<const llvm::Target> causes a malloc error // when this LLVMDisasmContext is deleted. const Target *TheTarget; // The assembly information for the target architecture. - llvm::OwningPtr<const llvm::MCAsmInfo> MAI; + std::unique_ptr<const llvm::MCAsmInfo> MAI; // The register information for the target architecture. - llvm::OwningPtr<const llvm::MCRegisterInfo> MRI; + std::unique_ptr<const llvm::MCRegisterInfo> MRI; // The subtarget information for the target architecture. - llvm::OwningPtr<const llvm::MCSubtargetInfo> MSI; + std::unique_ptr<const llvm::MCSubtargetInfo> MSI; // The instruction information for the target architecture. - llvm::OwningPtr<const llvm::MCInstrInfo> MII; + std::unique_ptr<const llvm::MCInstrInfo> MII; // The assembly context for creating symbols and MCExprs. - llvm::OwningPtr<const llvm::MCContext> Ctx; + std::unique_ptr<const llvm::MCContext> Ctx; // The disassembler for the target architecture. - llvm::OwningPtr<const llvm::MCDisassembler> DisAsm; + std::unique_ptr<const llvm::MCDisassembler> DisAsm; // The instruction printer for the target architecture. - llvm::OwningPtr<llvm::MCInstPrinter> IP; + std::unique_ptr<llvm::MCInstPrinter> IP; // The options used to set up the disassembler. uint64_t Options; // The CPU string. diff --git a/contrib/llvm/lib/MC/MCDwarf.cpp b/contrib/llvm/lib/MC/MCDwarf.cpp index 12070f3..3bf6f0f 100644 --- a/contrib/llvm/lib/MC/MCDwarf.cpp +++ b/contrib/llvm/lib/MC/MCDwarf.cpp @@ -9,6 +9,7 @@ #include "llvm/MC/MCDwarf.h" #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/Config/config.h" @@ -16,8 +17,9 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSection.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -62,7 +64,7 @@ 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(MCStreamer *MCOS, const MCSection *Section) { +void MCLineEntry::Make(MCObjectStreamer *MCOS, const MCSection *Section) { if (!MCOS->getContext().getDwarfLocSeen()) return; @@ -80,23 +82,11 @@ void MCLineEntry::Make(MCStreamer *MCOS, const MCSection *Section) { // clear DwarfLocSeen saying the current .loc info is now used. MCOS->getContext().ClearDwarfLocSeen(); - // Get the MCLineSection for this section, if one does not exist for this - // section create it. - const DenseMap<const MCSection *, MCLineSection *> &MCLineSections = - MCOS->getContext().getMCLineSections(); - MCLineSection *LineSection = MCLineSections.lookup(Section); - if (!LineSection) { - // Create a new MCLineSection. This will be deleted after the dwarf line - // table is created using it by iterating through the MCLineSections - // DenseMap. - LineSection = new MCLineSection; - // Save a pointer to the new LineSection into the MCLineSections DenseMap. - MCOS->getContext().addMCLineSection(Section, LineSection); - } - // Add the line entry to this section's entries. - LineSection->addLineEntry(LineEntry, - MCOS->getContext().getDwarfCompileUnitID()); + MCOS->getContext() + .getMCDwarfLineTable(MCOS->getContext().getDwarfCompileUnitID()) + .getMCLineSections() + .addLineEntry(LineEntry, Section); } // @@ -124,25 +114,21 @@ static inline const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS, // This emits the Dwarf line table for the specified section from the entries // in the LineSection. // -static inline void EmitDwarfLineTable(MCStreamer *MCOS, - const MCSection *Section, - const MCLineSection *LineSection, - unsigned CUID) { - // This LineSection does not contain any LineEntry for the given Compile Unit. - if (!LineSection->containEntriesForID(CUID)) - return; - +static inline void +EmitDwarfLineTable(MCObjectStreamer *MCOS, const MCSection *Section, + const MCLineSection::MCLineEntryCollection &LineEntries) { unsigned FileNum = 1; unsigned LastLine = 1; unsigned Column = 0; unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; unsigned Isa = 0; - MCSymbol *LastLabel = NULL; + unsigned Discriminator = 0; + MCSymbol *LastLabel = nullptr; // Loop through each MCLineEntry and encode the dwarf line number table. - for (MCLineSection::const_iterator - it = LineSection->getMCLineEntries(CUID).begin(), - ie = LineSection->getMCLineEntries(CUID).end(); it != ie; ++it) { + for (auto it = LineEntries.begin(), + ie = LineEntries.end(); + it != ie; ++it) { if (FileNum != it->getFileNum()) { FileNum = it->getFileNum(); @@ -154,6 +140,14 @@ static inline void EmitDwarfLineTable(MCStreamer *MCOS, MCOS->EmitIntValue(dwarf::DW_LNS_set_column, 1); MCOS->EmitULEB128IntValue(Column); } + if (Discriminator != it->getDiscriminator()) { + Discriminator = it->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(); MCOS->EmitIntValue(dwarf::DW_LNS_set_isa, 1); @@ -212,38 +206,55 @@ static inline void EmitDwarfLineTable(MCStreamer *MCOS, // // This emits the Dwarf file and the line tables. // -const MCSymbol *MCDwarfFileTable::Emit(MCStreamer *MCOS) { +void MCDwarfLineTable::Emit(MCObjectStreamer *MCOS) { MCContext &context = MCOS->getContext(); + + auto &LineTables = context.getMCDwarfLineTables(); + + // Bail out early so we don't switch to the debug_line section needlessly and + // in doing so create an unnecessary (if empty) section. + if (LineTables.empty()) + return; + // Switch to the section where the table will be emitted into. MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection()); - const DenseMap<unsigned, MCSymbol *> &MCLineTableSymbols = - MCOS->getContext().getMCLineTableSymbols(); - // CUID and MCLineTableSymbols are set in DwarfDebug, when DwarfDebug does - // not exist, CUID will be 0 and MCLineTableSymbols will be empty. - // Handle Compile Unit 0, the line table start symbol is the section symbol. - const MCSymbol *LineStartSym = EmitCU(MCOS, 0); // Handle the rest of the Compile Units. - for (unsigned Is = 1, Ie = MCLineTableSymbols.size(); Is < Ie; Is++) - EmitCU(MCOS, Is); - - // Now delete the MCLineSections that were created in MCLineEntry::Make() - // and used to emit the line table. - const DenseMap<const MCSection *, MCLineSection *> &MCLineSections = - MCOS->getContext().getMCLineSections(); - for (DenseMap<const MCSection *, MCLineSection *>::const_iterator it = - MCLineSections.begin(), ie = MCLineSections.end(); it != ie; - ++it) - delete it->second; - - return LineStartSym; + for (const auto &CUIDTablePair : LineTables) + CUIDTablePair.second.EmitCU(MCOS); +} + +void MCDwarfDwoLineTable::Emit(MCStreamer &MCOS) const { + MCOS.EmitLabel(Header.Emit(&MCOS, None).second); } -const MCSymbol *MCDwarfFileTable::EmitCU(MCStreamer *MCOS, unsigned CUID) { +std::pair<MCSymbol *, MCSymbol *> MCDwarfLineTableHeader::Emit(MCStreamer *MCOS) const { + static const char StandardOpcodeLengths[] = { + 0, // length of DW_LNS_copy + 1, // length of DW_LNS_advance_pc + 1, // length of DW_LNS_advance_line + 1, // length of DW_LNS_set_file + 1, // length of DW_LNS_set_column + 0, // length of DW_LNS_negate_stmt + 0, // length of DW_LNS_set_basic_block + 0, // length of DW_LNS_const_add_pc + 1, // length of DW_LNS_fixed_advance_pc + 0, // length of DW_LNS_set_prologue_end + 0, // length of DW_LNS_set_epilogue_begin + 1 // DW_LNS_set_isa + }; + assert(array_lengthof(StandardOpcodeLengths) == (DWARF2_LINE_OPCODE_BASE - 1)); + return Emit(MCOS, StandardOpcodeLengths); +} + +std::pair<MCSymbol *, MCSymbol *> +MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, + ArrayRef<char> StandardOpcodeLengths) const { + MCContext &context = MCOS->getContext(); // Create a symbol at the beginning of the line table. - MCSymbol *LineStartSym = MCOS->getContext().getMCLineTableSymbol(CUID); + MCSymbol *LineStartSym = Label; if (!LineStartSym) LineStartSym = context.CreateTempSymbol(); // Set the value of the symbol, as we are at the start of the line table. @@ -275,27 +286,15 @@ const MCSymbol *MCDwarfFileTable::EmitCU(MCStreamer *MCOS, unsigned CUID) { MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1); MCOS->EmitIntValue(DWARF2_LINE_BASE, 1); MCOS->EmitIntValue(DWARF2_LINE_RANGE, 1); - MCOS->EmitIntValue(DWARF2_LINE_OPCODE_BASE, 1); + MCOS->EmitIntValue(StandardOpcodeLengths.size() + 1, 1); // Standard opcode lengths - MCOS->EmitIntValue(0, 1); // length of DW_LNS_copy - MCOS->EmitIntValue(1, 1); // length of DW_LNS_advance_pc - MCOS->EmitIntValue(1, 1); // length of DW_LNS_advance_line - MCOS->EmitIntValue(1, 1); // length of DW_LNS_set_file - MCOS->EmitIntValue(1, 1); // length of DW_LNS_set_column - MCOS->EmitIntValue(0, 1); // length of DW_LNS_negate_stmt - MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_basic_block - MCOS->EmitIntValue(0, 1); // length of DW_LNS_const_add_pc - MCOS->EmitIntValue(1, 1); // length of DW_LNS_fixed_advance_pc - MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_prologue_end - MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_epilogue_begin - MCOS->EmitIntValue(1, 1); // DW_LNS_set_isa + for (char Length : StandardOpcodeLengths) + MCOS->EmitIntValue(Length, 1); // Put out the directory and file tables. // First the directory table. - const SmallVectorImpl<StringRef> &MCDwarfDirs = - context.getMCDwarfDirs(CUID); for (unsigned i = 0; i < MCDwarfDirs.size(); i++) { MCOS->EmitBytes(MCDwarfDirs[i]); // the DirectoryName MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string @@ -303,13 +302,12 @@ const MCSymbol *MCDwarfFileTable::EmitCU(MCStreamer *MCOS, unsigned CUID) { MCOS->EmitIntValue(0, 1); // Terminate the directory list // Second the file table. - const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles = - MCOS->getContext().getMCDwarfFiles(CUID); for (unsigned i = 1; i < MCDwarfFiles.size(); i++) { - MCOS->EmitBytes(MCDwarfFiles[i]->getName()); // FileName + assert(!MCDwarfFiles[i].Name.empty()); + MCOS->EmitBytes(MCDwarfFiles[i].Name); // FileName MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string // the Directory num - MCOS->EmitULEB128IntValue(MCDwarfFiles[i]->getDirIndex()); + MCOS->EmitULEB128IntValue(MCDwarfFiles[i].DirIndex); MCOS->EmitIntValue(0, 1); // last modification timestamp (always 0) MCOS->EmitIntValue(0, 1); // filesize (always 0) } @@ -319,21 +317,18 @@ const MCSymbol *MCDwarfFileTable::EmitCU(MCStreamer *MCOS, unsigned CUID) { // end of the prologue (that was used in a previous expression). MCOS->EmitLabel(ProEndSym); + return std::make_pair(LineStartSym, LineEndSym); +} + +void MCDwarfLineTable::EmitCU(MCObjectStreamer *MCOS) const { + MCSymbol *LineEndSym = Header.Emit(MCOS).second; + // Put out the line tables. - const DenseMap<const MCSection *, MCLineSection *> &MCLineSections = - MCOS->getContext().getMCLineSections(); - const std::vector<const MCSection *> &MCLineSectionOrder = - MCOS->getContext().getMCLineSectionOrder(); - for (std::vector<const MCSection*>::const_iterator it = - MCLineSectionOrder.begin(), ie = MCLineSectionOrder.end(); it != ie; - ++it) { - const MCSection *Sec = *it; - const MCLineSection *Line = MCLineSections.lookup(Sec); - EmitDwarfLineTable(MCOS, Sec, Line, CUID); - } + for (const auto &LineSec : MCLineSections.getMCLineEntries()) + EmitDwarfLineTable(MCOS, LineSec.first, LineSec.second); - if (MCOS->getContext().getAsmInfo()->getLinkerRequiresNonEmptyDwarfLines() - && MCLineSectionOrder.begin() == MCLineSectionOrder.end()) { + if (MCOS->getContext().getAsmInfo()->getLinkerRequiresNonEmptyDwarfLines() && + MCLineSections.getMCLineEntries().empty()) { // The darwin9 linker has a bug (see PR8715). For for 32-bit architectures // it requires: // total_length >= prologue_length + 10 @@ -347,8 +342,78 @@ const MCSymbol *MCDwarfFileTable::EmitCU(MCStreamer *MCOS, unsigned CUID) { // This is the end of the section, so set the value of the symbol at the end // of this section (that was used in a previous expression). MCOS->EmitLabel(LineEndSym); +} + +unsigned MCDwarfLineTable::getFile(StringRef &Directory, StringRef &FileName, + unsigned FileNumber) { + return Header.getFile(Directory, FileName, FileNumber); +} + +unsigned MCDwarfLineTableHeader::getFile(StringRef &Directory, + StringRef &FileName, + unsigned FileNumber) { + if (Directory == CompilationDir) + Directory = ""; + if (FileName.empty()) { + FileName = "<stdin>"; + 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"); + StringMapEntry<unsigned> &Ent = SourceIdMap.GetOrCreateValue( + (Directory + Twine('\0') + FileName).str(), FileNumber); + if (Ent.getValue() != FileNumber) + return Ent.getValue(); + } + // Make space for this FileNumber in the MCDwarfFiles vector if needed. + MCDwarfFiles.resize(FileNumber + 1); + + // Get the new MCDwarfFile slot for this FileNumber. + MCDwarfFile &File = MCDwarfFiles[FileNumber]; + + // It is an error to use see the same number more than once. + if (!File.Name.empty()) + return 0; + + if (Directory.empty()) { + // Separate the directory part from the basename of the FileName. + StringRef tFileName = sys::path::filename(FileName); + if (!tFileName.empty()) { + Directory = sys::path::parent_path(FileName); + if (!Directory.empty()) + FileName = tFileName; + } + } + + // Find or make an entry in the MCDwarfDirs vector for this Directory. + // Capture directory name. + unsigned DirIndex; + if (Directory.empty()) { + // For FileNames with no directories a DirIndex of 0 is used. + DirIndex = 0; + } else { + DirIndex = 0; + for (unsigned End = MCDwarfDirs.size(); DirIndex < End; DirIndex++) { + if (Directory == MCDwarfDirs[DirIndex]) + break; + } + if (DirIndex >= MCDwarfDirs.size()) + MCDwarfDirs.push_back(Directory); + // The DirIndex is one based, as DirIndex of 0 is used for FileNames with + // no directories. MCDwarfDirs[] is unlike MCDwarfFiles[] in that the + // directory names are stored at MCDwarfDirs[DirIndex-1] where FileNames + // are stored at MCDwarfFiles[FileNumber].Name . + DirIndex++; + } + + File.Name = FileName; + File.DirIndex = DirIndex; - return LineStartSym; + // return the allocated FileNumber. + return FileNumber; } /// Utility function to emit the encoding to a streamer. @@ -437,16 +502,6 @@ void MCDwarfLineAddr::Encode(MCContext &Context, int64_t LineDelta, OS << char(Temp); } -void MCDwarfFile::print(raw_ostream &OS) const { - OS << '"' << getName() << '"'; -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -void MCDwarfFile::dump() const { - print(dbgs()); -} -#endif - // Utility function to write a tuple for .debug_abbrev. static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) { MCOS->EmitULEB128IntValue(Name); @@ -464,8 +519,13 @@ static void EmitGenDwarfAbbrev(MCStreamer *MCOS) { MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit); MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1); EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4); - EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); - EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr); + if (MCOS->getContext().getGenDwarfSectionSyms().size() > 1 && + MCOS->getContext().getDwarfVersion() >= 3) { + EmitAbbrev(MCOS, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4); + } else { + EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); + EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr); + } EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string); if (!context.getCompilationDir().empty()) EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string); @@ -498,20 +558,14 @@ static void EmitGenDwarfAbbrev(MCStreamer *MCOS) { } // When generating dwarf for assembly source files this emits the data for -// .debug_aranges section. Which contains a header and a table of pairs of -// PointerSize'ed values for the address and size of section(s) with line table -// entries (just the default .text in our case) and a terminating pair of zeros. +// .debug_aranges section. This section contains a header and a table of pairs +// of PointerSize'ed values for the address and size of section(s) with line +// table entries. static void EmitGenDwarfAranges(MCStreamer *MCOS, const MCSymbol *InfoSectionSymbol) { MCContext &context = MCOS->getContext(); - // Create a symbol at the end of the section that we are creating the dwarf - // debugging info to use later in here as part of the expression to calculate - // the size of the section for the table. - MCOS->SwitchSection(context.getGenDwarfSection()); - MCSymbol *SectionEndSym = context.CreateTempSymbol(); - MCOS->EmitLabel(SectionEndSym); - context.setGenDwarfSectionEndSym(SectionEndSym); + auto &Sections = context.getGenDwarfSectionSyms(); MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); @@ -529,8 +583,8 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS, Length += Pad; // Add the size of the pair of PointerSize'ed values for the address and size - // of the one default .text section we have in the table. - Length += 2 * AddrSize; + // of each section we have in the table. + Length += 2 * AddrSize * Sections.size(); // And the pair of terminating zeros. Length += 2 * AddrSize; @@ -554,14 +608,21 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS, for(int i = 0; i < Pad; i++) MCOS->EmitIntValue(0, 1); - // Now emit the table of pairs of PointerSize'ed values for the section(s) - // address and size, in our case just the one default .text section. - const MCExpr *Addr = MCSymbolRefExpr::Create( - context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context); - const MCExpr *Size = MakeStartMinusEndExpr(*MCOS, - *context.getGenDwarfSectionStartSym(), *SectionEndSym, 0); - MCOS->EmitAbsValue(Addr, AddrSize); - MCOS->EmitAbsValue(Size, AddrSize); + // Now emit the table of pairs of PointerSize'ed values for the section + // addresses and sizes. + for (const auto &sec : Sections) { + MCSymbol *StartSymbol = sec.second.first; + MCSymbol *EndSymbol = sec.second.second; + assert(StartSymbol && "StartSymbol must not be NULL"); + assert(EndSymbol && "EndSymbol must not be NULL"); + + const MCExpr *Addr = MCSymbolRefExpr::Create( + StartSymbol, MCSymbolRefExpr::VK_None, context); + const MCExpr *Size = MakeStartMinusEndExpr(*MCOS, + *StartSymbol, *EndSymbol, 0); + MCOS->EmitValue(Addr, AddrSize); + MCOS->EmitAbsValue(Size, AddrSize); + } // And finally the pair of terminating zeros. MCOS->EmitIntValue(0, AddrSize); @@ -573,7 +634,8 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS, // DIE and a list of label DIEs. static void EmitGenDwarfInfo(MCStreamer *MCOS, const MCSymbol *AbbrevSectionSymbol, - const MCSymbol *LineSectionSymbol) { + const MCSymbol *LineSectionSymbol, + const MCSymbol *RangesSectionSymbol) { MCContext &context = MCOS->getContext(); MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); @@ -591,16 +653,17 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS, const MCExpr *Length = MakeStartMinusEndExpr(*MCOS, *InfoStart, *InfoEnd, 4); MCOS->EmitAbsValue(Length, 4); - // The 2 byte DWARF version, which is 2. - MCOS->EmitIntValue(2, 2); + // The 2 byte DWARF version. + MCOS->EmitIntValue(context.getDwarfVersion(), 2); + const MCAsmInfo &AsmInfo = *context.getAsmInfo(); // The 4 byte offset to the debug abbrevs from the start of the .debug_abbrev, // it is at the start of that section so this is zero. - if (AbbrevSectionSymbol) { - MCOS->EmitSymbolValue(AbbrevSectionSymbol, 4); - } else { + if (AbbrevSectionSymbol == nullptr) MCOS->EmitIntValue(0, 4); - } + else + MCOS->EmitSymbolValue(AbbrevSectionSymbol, 4, + AsmInfo.needsDwarfSectionOffsetDirective()); const MCAsmInfo *asmInfo = context.getAsmInfo(); int AddrSize = asmInfo->getPointerSize(); @@ -620,27 +683,48 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS, MCOS->EmitIntValue(0, 4); } - // AT_low_pc, the first address of the default .text section. - const MCExpr *Start = MCSymbolRefExpr::Create( - context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context); - MCOS->EmitAbsValue(Start, AddrSize); + if (RangesSectionSymbol) { + // There are multiple sections containing code, so we must use the + // .debug_ranges sections. - // AT_high_pc, the last address of the default .text section. - const MCExpr *End = MCSymbolRefExpr::Create( - context.getGenDwarfSectionEndSym(), MCSymbolRefExpr::VK_None, context); - MCOS->EmitAbsValue(End, AddrSize); + // AT_ranges, the 4 byte offset from the start of the .debug_ranges section + // to the address range list for this compilation unit. + MCOS->EmitSymbolValue(RangesSectionSymbol, 4); + } else { + // If we only have one non-empty code section, we can use the simpler + // AT_low_pc and AT_high_pc attributes. + + // Find the first (and only) non-empty text section + auto &Sections = context.getGenDwarfSectionSyms(); + const auto TextSection = Sections.begin(); + assert(TextSection != Sections.end() && "No text section found"); + + MCSymbol *StartSymbol = TextSection->second.first; + MCSymbol *EndSymbol = TextSection->second.second; + assert(StartSymbol && "StartSymbol must not be NULL"); + assert(EndSymbol && "EndSymbol must not be NULL"); + + // AT_low_pc, the first address of the default .text section. + const MCExpr *Start = MCSymbolRefExpr::Create( + StartSymbol, MCSymbolRefExpr::VK_None, context); + MCOS->EmitValue(Start, AddrSize); + + // AT_high_pc, the last address of the default .text section. + const MCExpr *End = MCSymbolRefExpr::Create( + EndSymbol, MCSymbolRefExpr::VK_None, context); + MCOS->EmitValue(End, AddrSize); + } // AT_name, the name of the source file. Reconstruct from the first directory // and file table entries. - const SmallVectorImpl<StringRef> &MCDwarfDirs = - context.getMCDwarfDirs(); + const SmallVectorImpl<std::string> &MCDwarfDirs = context.getMCDwarfDirs(); if (MCDwarfDirs.size() > 0) { MCOS->EmitBytes(MCDwarfDirs[0]); - MCOS->EmitBytes("/"); + MCOS->EmitBytes(sys::path::get_separator()); } - const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles = + const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles = MCOS->getContext().getMCDwarfFiles(); - MCOS->EmitBytes(MCDwarfFiles[1]->getName()); + MCOS->EmitBytes(MCDwarfFiles[1].Name); MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. // AT_comp_dir, the working directory the assembly was done in. @@ -658,14 +742,10 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS, // AT_producer, the version of the assembler tool. StringRef DwarfDebugProducer = context.getDwarfDebugProducer(); - if (!DwarfDebugProducer.empty()){ + if (!DwarfDebugProducer.empty()) MCOS->EmitBytes(DwarfDebugProducer); - } - else { - MCOS->EmitBytes(StringRef("llvm-mc (based on LLVM ")); - MCOS->EmitBytes(StringRef(PACKAGE_VERSION)); - MCOS->EmitBytes(StringRef(")")); - } + else + MCOS->EmitBytes(StringRef("llvm-mc (based on LLVM " PACKAGE_VERSION ")")); MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. // AT_language, a 4 byte value. We use DW_LANG_Mips_Assembler as the dwarf2 @@ -675,30 +755,26 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS, // Third part: the list of label DIEs. // Loop on saved info for dwarf labels and create the DIEs for them. - const std::vector<const MCGenDwarfLabelEntry *> &Entries = - MCOS->getContext().getMCGenDwarfLabelEntries(); - for (std::vector<const MCGenDwarfLabelEntry *>::const_iterator it = - Entries.begin(), ie = Entries.end(); it != ie; - ++it) { - const MCGenDwarfLabelEntry *Entry = *it; - + const std::vector<MCGenDwarfLabelEntry> &Entries = + MCOS->getContext().getMCGenDwarfLabelEntries(); + for (const auto &Entry : Entries) { // The DW_TAG_label DIE abbrev (2). MCOS->EmitULEB128IntValue(2); // AT_name, of the label without any leading underbar. - MCOS->EmitBytes(Entry->getName()); + MCOS->EmitBytes(Entry.getName()); MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. // AT_decl_file, index into the file table. - MCOS->EmitIntValue(Entry->getFileNumber(), 4); + MCOS->EmitIntValue(Entry.getFileNumber(), 4); // AT_decl_line, source line number. - MCOS->EmitIntValue(Entry->getLineNumber(), 4); + MCOS->EmitIntValue(Entry.getLineNumber(), 4); // AT_low_pc, start address of the label. - const MCExpr *AT_low_pc = MCSymbolRefExpr::Create(Entry->getLabel(), + const MCExpr *AT_low_pc = MCSymbolRefExpr::Create(Entry.getLabel(), MCSymbolRefExpr::VK_None, context); - MCOS->EmitAbsValue(AT_low_pc, AddrSize); + MCOS->EmitValue(AT_low_pc, AddrSize); // DW_AT_prototyped, a one byte flag value of 0 saying we have no prototype. MCOS->EmitIntValue(0, 1); @@ -709,14 +785,6 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS, // Add the NULL DIE terminating the DW_TAG_unspecified_parameters DIE's. MCOS->EmitIntValue(0, 1); } - // Deallocate the MCGenDwarfLabelEntry classes that saved away the info - // for the dwarf labels. - for (std::vector<const MCGenDwarfLabelEntry *>::const_iterator it = - Entries.begin(), ie = Entries.end(); it != ie; - ++it) { - const MCGenDwarfLabelEntry *Entry = *it; - delete Entry; - } // Add the NULL DIE terminating the Compile Unit DIE's. MCOS->EmitIntValue(0, 1); @@ -725,20 +793,76 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS, MCOS->EmitLabel(InfoEnd); } +// When generating dwarf for assembly source files this emits the data for +// .debug_ranges section. We only emit one range list, which spans all of the +// executable sections of this file. +static void EmitGenDwarfRanges(MCStreamer *MCOS) { + MCContext &context = MCOS->getContext(); + auto &Sections = context.getGenDwarfSectionSyms(); + + const MCAsmInfo *AsmInfo = context.getAsmInfo(); + int AddrSize = AsmInfo->getPointerSize(); + + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection()); + + for (const auto sec : Sections) { + + MCSymbol *StartSymbol = sec.second.first; + MCSymbol *EndSymbol = sec.second.second; + assert(StartSymbol && "StartSymbol must not be NULL"); + assert(EndSymbol && "EndSymbol must not be NULL"); + + // Emit a base address selection entry for the start of this section + const MCExpr *SectionStartAddr = MCSymbolRefExpr::Create( + StartSymbol, MCSymbolRefExpr::VK_None, context); + MCOS->EmitFill(AddrSize, 0xFF); + MCOS->EmitValue(SectionStartAddr, AddrSize); + + // Emit a range list entry spanning this section + const MCExpr *SectionSize = MakeStartMinusEndExpr(*MCOS, + *StartSymbol, *EndSymbol, 0); + MCOS->EmitIntValue(0, AddrSize); + MCOS->EmitAbsValue(SectionSize, AddrSize); + } + + // Emit end of list entry + MCOS->EmitIntValue(0, AddrSize); + MCOS->EmitIntValue(0, AddrSize); +} + // // When generating dwarf for assembly source files this emits the Dwarf // sections. // -void MCGenDwarfInfo::Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol) { - // Create the dwarf sections in this order (.debug_line already created). +void MCGenDwarfInfo::Emit(MCStreamer *MCOS) { MCContext &context = MCOS->getContext(); + + // Create the dwarf sections in this order (.debug_line already created). const MCAsmInfo *AsmInfo = context.getAsmInfo(); bool CreateDwarfSectionSymbols = AsmInfo->doesDwarfUseRelocationsAcrossSections(); - if (!CreateDwarfSectionSymbols) - LineSectionSymbol = NULL; - MCSymbol *AbbrevSectionSymbol = NULL; - MCSymbol *InfoSectionSymbol = NULL; + MCSymbol *LineSectionSymbol = nullptr; + if (CreateDwarfSectionSymbols) + LineSectionSymbol = MCOS->getDwarfLineTableSymbol(0); + MCSymbol *AbbrevSectionSymbol = nullptr; + MCSymbol *InfoSectionSymbol = nullptr; + MCSymbol *RangesSectionSymbol = NULL; + + // Create end symbols for each section, and remove empty sections + MCOS->getContext().finalizeDwarfSections(*MCOS); + + // If there are no sections to generate debug info for, we don't need + // to do anything + if (MCOS->getContext().getGenDwarfSectionSyms().empty()) + return; + + // We only use the .debug_ranges section if we have multiple code sections, + // and we are emitting a DWARF version which supports it. + const bool UseRangesSection = + MCOS->getContext().getGenDwarfSectionSyms().size() > 1 && + MCOS->getContext().getDwarfVersion() >= 3; + CreateDwarfSectionSymbols |= UseRangesSection; + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); if (CreateDwarfSectionSymbols) { InfoSectionSymbol = context.CreateTempSymbol(); @@ -749,20 +873,30 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol) { AbbrevSectionSymbol = context.CreateTempSymbol(); MCOS->EmitLabel(AbbrevSectionSymbol); } - MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); + if (UseRangesSection) { + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection()); + if (CreateDwarfSectionSymbols) { + RangesSectionSymbol = context.CreateTempSymbol(); + MCOS->EmitLabel(RangesSectionSymbol); + } + } - // If there are no line table entries then do not emit any section contents. - if (context.getMCLineSections().empty()) - return; + assert((RangesSectionSymbol != NULL) || !UseRangesSection); + + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); // Output the data for .debug_aranges section. EmitGenDwarfAranges(MCOS, InfoSectionSymbol); + if (UseRangesSection) + EmitGenDwarfRanges(MCOS); + // Output the data for .debug_abbrev section. EmitGenDwarfAbbrev(MCOS); // Output the data for .debug_info section. - EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol); + EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol, + RangesSectionSymbol); } // @@ -773,12 +907,13 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol) { // void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, SMLoc &Loc) { - // We won't create dwarf labels for temporary symbols or symbols not in - // the default text. + // We won't create dwarf labels for temporary symbols. if (Symbol->isTemporary()) return; MCContext &context = MCOS->getContext(); - if (context.getGenDwarfSection() != MCOS->getCurrentSection().first) + // We won't create dwarf labels for symbols in sections that we are not + // generating debug info for. + if (!context.getGenDwarfSectionSyms().count(MCOS->getCurrentSection().first)) return; // The dwarf label's name does not have the symbol name's leading @@ -792,7 +927,7 @@ void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS, // Finding the line number is the expensive part which is why we just don't // pass it in as for some symbols we won't create a dwarf label. - int CurBuffer = SrcMgr.FindBufferContainingLoc(Loc); + unsigned CurBuffer = SrcMgr.FindBufferContainingLoc(Loc); unsigned LineNumber = SrcMgr.FindLineNumber(Loc, CurBuffer); // We create a temporary symbol for use for the AT_high_pc and AT_low_pc @@ -803,9 +938,8 @@ void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS, MCOS->EmitLabel(Label); // Create and entry for the info and add it to the other entries. - MCGenDwarfLabelEntry *Entry = - new MCGenDwarfLabelEntry(Name, FileNumber, LineNumber, Label); - MCOS->getContext().addMCGenDwarfLabelEntry(Entry); + MCOS->getContext().addMCGenDwarfLabelEntry( + MCGenDwarfLabelEntry(Name, FileNumber, LineNumber, Label)); } static int getDataAlignmentFactor(MCStreamer &streamer) { @@ -841,7 +975,7 @@ static unsigned getSizeForEncoding(MCStreamer &streamer, static void EmitFDESymbol(MCStreamer &streamer, const MCSymbol &symbol, unsigned symbolEncoding, bool isEH, - const char *comment = 0) { + const char *comment = nullptr) { MCContext &context = streamer.getContext(); const MCAsmInfo *asmInfo = context.getAsmInfo(); const MCExpr *v = asmInfo->getExprForFDESymbol(&symbol, @@ -870,13 +1004,11 @@ namespace { class FrameEmitterImpl { int CFAOffset; int CIENum; - bool UsingCFI; bool IsEH; const MCSymbol *SectionStart; public: - FrameEmitterImpl(bool usingCFI, bool isEH) - : CFAOffset(0), CIENum(0), UsingCFI(usingCFI), IsEH(isEH), - SectionStart(0) {} + FrameEmitterImpl(bool isEH) + : CFAOffset(0), CIENum(0), IsEH(isEH), SectionStart(nullptr) {} void setSectionStart(const MCSymbol *Label) { SectionStart = Label; } @@ -884,19 +1016,20 @@ namespace { void EmitCompactUnwind(MCStreamer &streamer, const MCDwarfFrameInfo &frame); - const MCSymbol &EmitCIE(MCStreamer &streamer, + const MCSymbol &EmitCIE(MCObjectStreamer &streamer, const MCSymbol *personality, unsigned personalityEncoding, const MCSymbol *lsda, bool IsSignalFrame, - unsigned lsdaEncoding); - MCSymbol *EmitFDE(MCStreamer &streamer, + unsigned lsdaEncoding, + bool IsSimple); + MCSymbol *EmitFDE(MCObjectStreamer &streamer, const MCSymbol &cieStart, const MCDwarfFrameInfo &frame); - void EmitCFIInstructions(MCStreamer &streamer, + void EmitCFIInstructions(MCObjectStreamer &streamer, ArrayRef<MCCFIInstruction> Instrs, MCSymbol *BaseLabel); - void EmitCFIInstruction(MCStreamer &Streamer, + void EmitCFIInstruction(MCObjectStreamer &Streamer, const MCCFIInstruction &Instr); }; @@ -947,7 +1080,7 @@ static void EmitEncodingByte(MCStreamer &Streamer, unsigned Encoding, Streamer.EmitIntValue(Encoding, 1); } -void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer, +void FrameEmitterImpl::EmitCFIInstruction(MCObjectStreamer &Streamer, const MCCFIInstruction &Instr) { int dataAlignmentFactor = getDataAlignmentFactor(Streamer); bool VerboseAsm = Streamer.isVerboseAsm(); @@ -1099,7 +1232,7 @@ void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer, /// EmitFrameMoves - Emit frame instructions to describe the layout of the /// frame. -void FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer, +void FrameEmitterImpl::EmitCFIInstructions(MCObjectStreamer &streamer, ArrayRef<MCCFIInstruction> Instrs, MCSymbol *BaseLabel) { for (unsigned i = 0, N = Instrs.size(); i < N; ++i) { @@ -1160,10 +1293,10 @@ void FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, Encoding |= 0x40000000; // Range Start - unsigned FDEEncoding = MOFI->getFDEEncoding(UsingCFI); + unsigned FDEEncoding = MOFI->getFDEEncoding(); unsigned Size = getSizeForEncoding(Streamer, FDEEncoding); if (VerboseAsm) Streamer.AddComment("Range Start"); - Streamer.EmitSymbolValue(Frame.Function, Size); + Streamer.EmitSymbolValue(Frame.Begin, Size); // Range Length const MCExpr *Range = MakeStartMinusEndExpr(Streamer, *Frame.Begin, @@ -1194,23 +1327,19 @@ void FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, Streamer.EmitIntValue(0, Size); // No LSDA } -const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, +const MCSymbol &FrameEmitterImpl::EmitCIE(MCObjectStreamer &streamer, const MCSymbol *personality, unsigned personalityEncoding, const MCSymbol *lsda, bool IsSignalFrame, - unsigned lsdaEncoding) { + unsigned lsdaEncoding, + bool IsSimple) { MCContext &context = streamer.getContext(); const MCRegisterInfo *MRI = context.getRegisterInfo(); const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); bool verboseAsm = streamer.isVerboseAsm(); - MCSymbol *sectionStart; - if (MOFI->isFunctionEHFrameSymbolPrivate() || !IsEH) - sectionStart = context.CreateTempSymbol(); - else - sectionStart = context.GetOrCreateSymbol(Twine("EH_frame") + Twine(CIENum)); - + MCSymbol *sectionStart = context.CreateTempSymbol(); streamer.EmitLabel(sectionStart); CIENum++; @@ -1229,7 +1358,10 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, // Version if (verboseAsm) streamer.AddComment("DW_CIE_VERSION"); - streamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1); + // For DWARF2, we use CIE version 1 + // For DWARF3+, we use CIE version 3 + uint8_t CIEVersion = context.getDwarfVersion() <= 2 ? 1 : 3; + streamer.EmitIntValue(CIEVersion, 1); // Augmentation String SmallString<8> Augmentation; @@ -1257,7 +1389,14 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, // Return Address Register if (verboseAsm) streamer.AddComment("CIE Return Address Column"); - streamer.EmitULEB128IntValue(MRI->getDwarfRegNum(MRI->getRARegister(), true)); + if (CIEVersion == 1) { + assert(MRI->getRARegister() <= 255 && + "DWARF 2 encodes return_address_register in one byte"); + streamer.EmitIntValue(MRI->getDwarfRegNum(MRI->getRARegister(), true), 1); + } else { + streamer.EmitULEB128IntValue( + MRI->getDwarfRegNum(MRI->getRARegister(), true)); + } // Augmentation Data Length (optional) @@ -1291,16 +1430,17 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, EmitEncodingByte(streamer, lsdaEncoding, "LSDA Encoding"); // Encoding of the FDE pointers - EmitEncodingByte(streamer, MOFI->getFDEEncoding(UsingCFI), - "FDE Encoding"); + EmitEncodingByte(streamer, MOFI->getFDEEncoding(), "FDE Encoding"); } // Initial Instructions const MCAsmInfo *MAI = context.getAsmInfo(); - const std::vector<MCCFIInstruction> &Instructions = - MAI->getInitialFrameState(); - EmitCFIInstructions(streamer, Instructions, NULL); + if (!IsSimple) { + const std::vector<MCCFIInstruction> &Instructions = + MAI->getInitialFrameState(); + EmitCFIInstructions(streamer, Instructions, nullptr); + } // Padding streamer.EmitValueToAlignment(IsEH ? 4 : MAI->getPointerSize()); @@ -1309,7 +1449,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, return *sectionStart; } -MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, +MCSymbol *FrameEmitterImpl::EmitFDE(MCObjectStreamer &streamer, const MCSymbol &cieStart, const MCDwarfFrameInfo &frame) { MCContext &context = streamer.getContext(); @@ -1318,13 +1458,6 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); bool verboseAsm = streamer.isVerboseAsm(); - if (IsEH && frame.Function && !MOFI->isFunctionEHFrameSymbolPrivate()) { - MCSymbol *EHSym = - context.GetOrCreateSymbol(frame.Function->getName() + Twine(".eh")); - streamer.EmitEHSymAttributes(frame.Function, EHSym); - streamer.EmitLabel(EHSym); - } - // Length const MCExpr *Length = MakeStartMinusEndExpr(streamer, *fdeStart, *fdeEnd, 0); if (verboseAsm) streamer.AddComment("FDE Length"); @@ -1348,8 +1481,8 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, } // PC Begin - unsigned PCEncoding = IsEH ? MOFI->getFDEEncoding(UsingCFI) - : (unsigned)dwarf::DW_EH_PE_absptr; + unsigned PCEncoding = + IsEH ? MOFI->getFDEEncoding() : (unsigned)dwarf::DW_EH_PE_absptr; unsigned PCSize = getSizeForEncoding(streamer, PCEncoding); EmitFDESymbol(streamer, *frame.Begin, PCEncoding, IsEH, "FDE initial location"); @@ -1386,18 +1519,23 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, namespace { struct CIEKey { - static const CIEKey getEmptyKey() { return CIEKey(0, 0, -1, false); } - static const CIEKey getTombstoneKey() { return CIEKey(0, -1, 0, false); } - - CIEKey(const MCSymbol* Personality_, unsigned PersonalityEncoding_, - unsigned LsdaEncoding_, bool IsSignalFrame_) : - Personality(Personality_), PersonalityEncoding(PersonalityEncoding_), - LsdaEncoding(LsdaEncoding_), IsSignalFrame(IsSignalFrame_) { + static const CIEKey getEmptyKey() { + return CIEKey(nullptr, 0, -1, false, false); + } + static const CIEKey getTombstoneKey() { + return CIEKey(nullptr, -1, 0, false, false); } - const MCSymbol* Personality; + + CIEKey(const MCSymbol *Personality_, unsigned PersonalityEncoding_, + unsigned LsdaEncoding_, bool IsSignalFrame_, bool IsSimple_) + : Personality(Personality_), PersonalityEncoding(PersonalityEncoding_), + LsdaEncoding(LsdaEncoding_), IsSignalFrame(IsSignalFrame_), + IsSimple(IsSimple_) {} + const MCSymbol *Personality; unsigned PersonalityEncoding; unsigned LsdaEncoding; bool IsSignalFrame; + bool IsSimple; }; } @@ -1414,28 +1552,31 @@ namespace llvm { return static_cast<unsigned>(hash_combine(Key.Personality, Key.PersonalityEncoding, Key.LsdaEncoding, - Key.IsSignalFrame)); + Key.IsSignalFrame, + Key.IsSimple)); } static bool isEqual(const CIEKey &LHS, const CIEKey &RHS) { return LHS.Personality == RHS.Personality && LHS.PersonalityEncoding == RHS.PersonalityEncoding && LHS.LsdaEncoding == RHS.LsdaEncoding && - LHS.IsSignalFrame == RHS.IsSignalFrame; + LHS.IsSignalFrame == RHS.IsSignalFrame && + LHS.IsSimple == RHS.IsSimple; } }; } -void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, MCAsmBackend *MAB, - bool UsingCFI, bool IsEH) { +void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB, + bool IsEH) { Streamer.generateCompactUnwindEncodings(MAB); MCContext &Context = Streamer.getContext(); const MCObjectFileInfo *MOFI = Context.getObjectFileInfo(); - FrameEmitterImpl Emitter(UsingCFI, IsEH); - ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getFrameInfos(); + FrameEmitterImpl Emitter(IsEH); + ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getDwarfFrameInfos(); // Emit the compact unwind info if available. + bool NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame(); if (IsEH && MOFI->getCompactUnwindSection()) { bool SectionEmitted = false; for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) { @@ -1446,37 +1587,55 @@ void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, MCAsmBackend *MAB, Streamer.EmitValueToAlignment(Context.getAsmInfo()->getPointerSize()); SectionEmitted = true; } + NeedsEHFrameSection |= + Frame.CompactUnwindEncoding == + MOFI->getCompactUnwindDwarfEHFrameOnly(); Emitter.EmitCompactUnwind(Streamer, Frame); } } + if (!NeedsEHFrameSection) return; + const MCSection &Section = IsEH ? *const_cast<MCObjectFileInfo*>(MOFI)->getEHFrameSection() : *MOFI->getDwarfFrameSection(); + Streamer.SwitchSection(&Section); MCSymbol *SectionStart = Context.CreateTempSymbol(); Streamer.EmitLabel(SectionStart); Emitter.setSectionStart(SectionStart); - MCSymbol *FDEEnd = NULL; - DenseMap<CIEKey, const MCSymbol*> CIEStarts; + MCSymbol *FDEEnd = nullptr; + DenseMap<CIEKey, const MCSymbol *> CIEStarts; - const MCSymbol *DummyDebugKey = NULL; + const MCSymbol *DummyDebugKey = nullptr; + NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame(); for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) { const MCDwarfFrameInfo &Frame = FrameArray[i]; + + // Emit the label from the previous iteration + if (FDEEnd) { + Streamer.EmitLabel(FDEEnd); + FDEEnd = nullptr; + } + + if (!NeedsEHFrameSection && Frame.CompactUnwindEncoding != + MOFI->getCompactUnwindDwarfEHFrameOnly()) + // Don't generate an EH frame if we don't need one. I.e., it's taken care + // of by the compact unwind encoding. + continue; + CIEKey Key(Frame.Personality, Frame.PersonalityEncoding, - Frame.LsdaEncoding, Frame.IsSignalFrame); + Frame.LsdaEncoding, Frame.IsSignalFrame, Frame.IsSimple); const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey; if (!CIEStart) CIEStart = &Emitter.EmitCIE(Streamer, Frame.Personality, Frame.PersonalityEncoding, Frame.Lsda, Frame.IsSignalFrame, - Frame.LsdaEncoding); + Frame.LsdaEncoding, + Frame.IsSimple); FDEEnd = Emitter.EmitFDE(Streamer, *CIEStart, Frame); - - if (i != n - 1) - Streamer.EmitLabel(FDEEnd); } Streamer.EmitValueToAlignment(Context.getAsmInfo()->getPointerSize()); @@ -1484,7 +1643,7 @@ void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, MCAsmBackend *MAB, Streamer.EmitLabel(FDEEnd); } -void MCDwarfFrameEmitter::EmitAdvanceLoc(MCStreamer &Streamer, +void MCDwarfFrameEmitter::EmitAdvanceLoc(MCObjectStreamer &Streamer, uint64_t AddrDelta) { MCContext &Context = Streamer.getContext(); SmallString<256> Tmp; diff --git a/contrib/llvm/lib/MC/MCELF.cpp b/contrib/llvm/lib/MC/MCELF.cpp index ebb189e..386c209 100644 --- a/contrib/llvm/lib/MC/MCELF.cpp +++ b/contrib/llvm/lib/MC/MCELF.cpp @@ -61,7 +61,7 @@ void MCELF::SetVisibility(MCSymbolData &SD, unsigned Visibility) { SD.setFlags(OtherFlags | (Visibility << ELF_STV_Shift)); } -unsigned MCELF::GetVisibility(MCSymbolData &SD) { +unsigned MCELF::GetVisibility(const MCSymbolData &SD) { unsigned Visibility = (SD.getFlags() & (0x3 << ELF_STV_Shift)) >> ELF_STV_Shift; assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL || @@ -72,13 +72,13 @@ unsigned MCELF::GetVisibility(MCSymbolData &SD) { // Other is stored in the last six bits of st_other // st_other values are stored in the second byte of get/setFlags void MCELF::setOther(MCSymbolData &SD, unsigned Other) { - uint32_t OtherFlags = SD.getFlags() & ~(0x3f << ELF_Other_Shift); - SD.setFlags(OtherFlags | (Other << ELF_Other_Shift)); + uint32_t OtherFlags = SD.getFlags() & ~(0x3f << ELF_STO_Shift); + SD.setFlags(OtherFlags | (Other << ELF_STO_Shift)); } -unsigned MCELF::getOther(MCSymbolData &SD) { +unsigned MCELF::getOther(const MCSymbolData &SD) { unsigned Other = - (SD.getFlags() & (0x3f << ELF_Other_Shift)) >> ELF_Other_Shift; + (SD.getFlags() & (0x3f << ELF_STO_Shift)) >> ELF_STO_Shift; return Other; } diff --git a/contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp b/contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp index 0c39e4a..84176dc 100644 --- a/contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp +++ b/contrib/llvm/lib/MC/MCELFObjectTargetWriter.cpp @@ -24,38 +24,7 @@ MCELFObjectTargetWriter::MCELFObjectTargetWriter(bool Is64Bit_, IsN64(IsN64_){ } -const MCSymbol *MCELFObjectTargetWriter::ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const { - return NULL; -} - -const MCSymbol *MCELFObjectTargetWriter::undefinedExplicitRelSym(const MCValue &Target, - const MCFixup &Fixup, - bool IsPCRel) const { - const MCSymbol &Symbol = Target.getSymA()->getSymbol(); - return &Symbol.AliasedSymbol(); -} - -// ELF doesn't require relocations to be in any order. We sort by the r_offset, -// just to match gnu as for easier comparison. The use type and index is an -// arbitrary way of making the sort deterministic. -static int cmpRel(const ELFRelocationEntry *AP, const ELFRelocationEntry *BP) { - const ELFRelocationEntry &A = *AP; - const ELFRelocationEntry &B = *BP; - if (A.r_offset != B.r_offset) - return B.r_offset - A.r_offset; - if (B.Type != A.Type) - return A.Type - B.Type; - if (B.Index != A.Index) - return B.Index - A.Index; - llvm_unreachable("ELFRelocs might be unstable!"); -} - -void -MCELFObjectTargetWriter::sortRelocs(const MCAssembler &Asm, - std::vector<ELFRelocationEntry> &Relocs) { - array_pod_sort(Relocs.begin(), Relocs.end(), cmpRel); +bool MCELFObjectTargetWriter::needsRelocateWithSymbol(const MCSymbolData &SD, + unsigned Type) const { + return false; } diff --git a/contrib/llvm/lib/MC/MCELFStreamer.cpp b/contrib/llvm/lib/MC/MCELFStreamer.cpp index e806cb9..7c70540 100644 --- a/contrib/llvm/lib/MC/MCELFStreamer.cpp +++ b/contrib/llvm/lib/MC/MCELFStreamer.cpp @@ -12,16 +12,17 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCELFStreamer.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/MC/MCAssembler.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCELF.h" #include "llvm/MC/MCELFSymbolFlags.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionELF.h" @@ -34,50 +35,22 @@ using namespace llvm; - -inline void MCELFStreamer::SetSection(StringRef Section, unsigned Type, - unsigned Flags, SectionKind Kind) { - SwitchSection(getContext().getELFSection(Section, Type, Flags, Kind)); -} - -inline void MCELFStreamer::SetSectionData() { - SetSection(".data", - ELF::SHT_PROGBITS, - ELF::SHF_WRITE | ELF::SHF_ALLOC, - SectionKind::getDataRel()); - EmitCodeAlignment(4, 0); -} - -inline void MCELFStreamer::SetSectionText() { - SetSection(".text", - ELF::SHT_PROGBITS, - ELF::SHF_EXECINSTR | ELF::SHF_ALLOC, - SectionKind::getText()); - EmitCodeAlignment(4, 0); -} - -inline void MCELFStreamer::SetSectionBss() { - SetSection(".bss", - ELF::SHT_NOBITS, - ELF::SHF_WRITE | ELF::SHF_ALLOC, - SectionKind::getBSS()); - EmitCodeAlignment(4, 0); -} - MCELFStreamer::~MCELFStreamer() { } -void MCELFStreamer::InitToTextSection() { - SetSectionText(); -} - void MCELFStreamer::InitSections() { // This emulates the same behavior of GNU as. This makes it easier // to compare the output as the major sections are in the same order. - SetSectionText(); - SetSectionData(); - SetSectionBss(); - SetSectionText(); + SwitchSection(getContext().getObjectFileInfo()->getTextSection()); + EmitCodeAlignment(4); + + SwitchSection(getContext().getObjectFileInfo()->getDataSection()); + EmitCodeAlignment(4); + + SwitchSection(getContext().getObjectFileInfo()->getBSSSection()); + EmitCodeAlignment(4); + + SwitchSection(getContext().getObjectFileInfo()->getTextSection()); } void MCELFStreamer::EmitLabel(MCSymbol *Symbol) { @@ -92,10 +65,6 @@ void MCELFStreamer::EmitLabel(MCSymbol *Symbol) { MCELF::SetType(SD, ELF::STT_TLS); } -void MCELFStreamer::EmitDebugLabel(MCSymbol *Symbol) { - EmitLabel(Symbol); -} - void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { // Let the target do whatever target specific stuff it needs to do. getAssembler().getBackend().handleAssemblerFlag(Flag); @@ -126,9 +95,8 @@ void MCELFStreamer::ChangeSection(const MCSection *Section, void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { getAssembler().getOrCreateSymbolData(*Symbol); - MCSymbolData &AliasSD = getAssembler().getOrCreateSymbolData(*Alias); - AliasSD.setFlags(AliasSD.getFlags() | ELF_Other_Weakref); - const MCExpr *Value = MCSymbolRefExpr::Create(Symbol, getContext()); + const MCExpr *Value = MCSymbolRefExpr::Create( + Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext()); Alias->setVariableValue(Value); } @@ -303,11 +271,12 @@ void MCELFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, EmitCommonSymbol(Symbol, Size, ByteAlignment); } -void MCELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size) { +void MCELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, + const SMLoc &Loc) { if (getCurrentSectionData()->isBundleLocked()) report_fatal_error("Emitting values inside a locked bundle is forbidden"); fixSymbolsInTLSFixups(Value); - MCObjectStreamer::EmitValueImpl(Value, Size); + MCObjectStreamer::EmitValueImpl(Value, Size, Loc); } void MCELFStreamer::EmitValueToAlignment(unsigned ByteAlignment, @@ -371,9 +340,6 @@ void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { case MCSymbolRefExpr::VK_TLSLDM: case MCSymbolRefExpr::VK_TPOFF: case MCSymbolRefExpr::VK_DTPOFF: - case MCSymbolRefExpr::VK_ARM_TLSGD: - case MCSymbolRefExpr::VK_ARM_TPOFF: - case MCSymbolRefExpr::VK_ARM_GOTTPOFF: case MCSymbolRefExpr::VK_Mips_TLSGD: case MCSymbolRefExpr::VK_Mips_GOTTPREL: case MCSymbolRefExpr::VK_Mips_TPREL_HI: @@ -427,20 +393,22 @@ void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { } } -void MCELFStreamer::EmitInstToFragment(const MCInst &Inst) { - this->MCObjectStreamer::EmitInstToFragment(Inst); +void MCELFStreamer::EmitInstToFragment(const MCInst &Inst, + const MCSubtargetInfo &STI) { + this->MCObjectStreamer::EmitInstToFragment(Inst, STI); MCRelaxableFragment &F = *cast<MCRelaxableFragment>(getCurrentFragment()); for (unsigned i = 0, e = F.getFixups().size(); i != e; ++i) fixSymbolsInTLSFixups(F.getFixups()[i].getValue()); } -void MCELFStreamer::EmitInstToData(const MCInst &Inst) { +void MCELFStreamer::EmitInstToData(const MCInst &Inst, + const MCSubtargetInfo &STI) { MCAssembler &Assembler = getAssembler(); SmallVector<MCFixup, 4> Fixups; SmallString<256> Code; raw_svector_ostream VecOS(Code); - Assembler.getEmitter().EncodeInstruction(Inst, VecOS, Fixups); + Assembler.getEmitter().EncodeInstruction(Inst, VecOS, Fixups, STI); VecOS.flush(); for (unsigned i = 0, e = Fixups.size(); i != e; ++i) @@ -566,19 +534,17 @@ void MCELFStreamer::Flush() { } void MCELFStreamer::FinishImpl() { - EmitFrames(NULL, true); + EmitFrames(nullptr); Flush(); this->MCObjectStreamer::FinishImpl(); } -MCStreamer *llvm::createELFStreamer(MCContext &Context, - MCTargetStreamer *Streamer, - MCAsmBackend &MAB, raw_ostream &OS, - MCCodeEmitter *CE, bool RelaxAll, - bool NoExecStack) { - MCELFStreamer *S = new MCELFStreamer(Context, Streamer, MAB, OS, CE); +MCStreamer *llvm::createELFStreamer(MCContext &Context, MCAsmBackend &MAB, + raw_ostream &OS, MCCodeEmitter *CE, + bool RelaxAll, bool NoExecStack) { + MCELFStreamer *S = new MCELFStreamer(Context, MAB, OS, CE); if (RelaxAll) S->getAssembler().setRelaxAll(true); if (NoExecStack) @@ -590,10 +556,6 @@ void MCELFStreamer::EmitThumbFunc(MCSymbol *Func) { llvm_unreachable("Generic ELF doesn't support this directive"); } -MCSymbolData &MCELFStreamer::getOrCreateSymbolData(MCSymbol *Symbol) { - return getAssembler().getOrCreateSymbolData(*Symbol); -} - void MCELFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { llvm_unreachable("ELF doesn't support this directive"); } diff --git a/contrib/llvm/lib/MC/MCExpr.cpp b/contrib/llvm/lib/MC/MCExpr.cpp index c777e64..f724716 100644 --- a/contrib/llvm/lib/MC/MCExpr.cpp +++ b/contrib/llvm/lib/MC/MCExpr.cpp @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "mcexpr" #include "llvm/MC/MCExpr.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" @@ -22,6 +22,8 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; +#define DEBUG_TYPE "mcexpr" + namespace { namespace stats { STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations"); @@ -47,19 +49,12 @@ void MCExpr::print(raw_ostream &OS) const { else OS << Sym; - if (SRE.getKind() == MCSymbolRefExpr::VK_ARM_NONE || - SRE.getKind() == MCSymbolRefExpr::VK_ARM_PLT || - SRE.getKind() == MCSymbolRefExpr::VK_ARM_TLSGD || - SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOT || - SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTOFF || - SRE.getKind() == MCSymbolRefExpr::VK_ARM_TPOFF || - SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTTPOFF || - SRE.getKind() == MCSymbolRefExpr::VK_ARM_TARGET1 || - SRE.getKind() == MCSymbolRefExpr::VK_ARM_TARGET2 || - SRE.getKind() == MCSymbolRefExpr::VK_ARM_PREL31) - OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); - else if (SRE.getKind() != MCSymbolRefExpr::VK_None) - OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); + if (SRE.getKind() != MCSymbolRefExpr::VK_None) { + if (SRE.getMCAsmInfo().useParensForSymbolVariant()) + OS << '(' << MCSymbolRefExpr::getVariantKindName(SRE.getKind()) << ')'; + else + OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); + } return; } @@ -158,7 +153,7 @@ const MCConstantExpr *MCConstantExpr::Create(int64_t Value, MCContext &Ctx) { const MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym, VariantKind Kind, MCContext &Ctx) { - return new (Ctx) MCSymbolRefExpr(Sym, Kind); + return new (Ctx) MCSymbolRefExpr(Sym, Kind, Ctx.getAsmInfo()); } const MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, VariantKind Kind, @@ -185,17 +180,22 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_TPOFF: return "TPOFF"; case VK_DTPOFF: return "DTPOFF"; case VK_TLVP: return "TLVP"; + case VK_TLVPPAGE: return "TLVPPAGE"; + case VK_TLVPPAGEOFF: return "TLVPPAGEOFF"; + case VK_PAGE: return "PAGE"; + case VK_PAGEOFF: return "PAGEOFF"; + case VK_GOTPAGE: return "GOTPAGE"; + case VK_GOTPAGEOFF: return "GOTPAGEOFF"; case VK_SECREL: return "SECREL32"; - case VK_ARM_NONE: return "(NONE)"; - case VK_ARM_PLT: return "(PLT)"; - case VK_ARM_GOT: return "(GOT)"; - case VK_ARM_GOTOFF: return "(GOTOFF)"; - case VK_ARM_TPOFF: return "(tpoff)"; - case VK_ARM_GOTTPOFF: return "(gottpoff)"; - case VK_ARM_TLSGD: return "(tlsgd)"; - case VK_ARM_TARGET1: return "(target1)"; - case VK_ARM_TARGET2: return "(target2)"; - case VK_ARM_PREL31: return "(prel31)"; + case VK_WEAKREF: return "WEAKREF"; + case VK_ARM_NONE: return "none"; + case VK_ARM_TARGET1: return "target1"; + case VK_ARM_TARGET2: return "target2"; + case VK_ARM_PREL31: return "prel31"; + 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"; case VK_PPC_HA: return "ha"; @@ -271,6 +271,8 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { 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 "IMGREL32"; } llvm_unreachable("Invalid variant kind"); @@ -285,6 +287,8 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) { .Case("gotoff", VK_GOTOFF) .Case("GOTPCREL", VK_GOTPCREL) .Case("gotpcrel", VK_GOTPCREL) + .Case("GOT_PREL", VK_GOTPCREL) + .Case("got_prel", VK_GOTPCREL) .Case("GOTTPOFF", VK_GOTTPOFF) .Case("gottpoff", VK_GOTTPOFF) .Case("INDNTPOFF", VK_INDNTPOFF) @@ -307,6 +311,18 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) { .Case("dtpoff", VK_DTPOFF) .Case("TLVP", VK_TLVP) .Case("tlvp", VK_TLVP) + .Case("TLVPPAGE", VK_TLVPPAGE) + .Case("tlvppage", VK_TLVPPAGE) + .Case("TLVPPAGEOFF", VK_TLVPPAGEOFF) + .Case("tlvppageoff", VK_TLVPPAGEOFF) + .Case("PAGE", VK_PAGE) + .Case("page", VK_PAGE) + .Case("PAGEOFF", VK_PAGEOFF) + .Case("pageoff", VK_PAGEOFF) + .Case("GOTPAGE", VK_GOTPAGE) + .Case("gotpage", VK_GOTPAGE) + .Case("GOTPAGEOFF", VK_GOTPAGEOFF) + .Case("gotpageoff", VK_GOTPAGEOFF) .Case("IMGREL", VK_COFF_IMGREL32) .Case("imgrel", VK_COFF_IMGREL32) .Case("SECREL32", VK_SECREL) @@ -409,6 +425,20 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) { .Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI) .Case("GOT@TLSLD@HA", VK_PPC_GOT_TLSLD_HA) .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA) + .Case("NONE", VK_ARM_NONE) + .Case("none", VK_ARM_NONE) + .Case("TARGET1", VK_ARM_TARGET1) + .Case("target1", VK_ARM_TARGET1) + .Case("TARGET2", VK_ARM_TARGET2) + .Case("target2", VK_ARM_TARGET2) + .Case("PREL31", VK_ARM_PREL31) + .Case("prel31", VK_ARM_PREL31) + .Case("TLSLDO", VK_ARM_TLSLDO) + .Case("tlsldo", VK_ARM_TLSLDO) + .Case("TLSCALL", VK_ARM_TLSCALL) + .Case("tlscall", VK_ARM_TLSCALL) + .Case("TLSDESC", VK_ARM_TLSDESC) + .Case("tlsdesc", VK_ARM_TLSDESC) .Default(VK_Invalid); } @@ -419,12 +449,12 @@ void MCTargetExpr::anchor() {} /* *** */ bool MCExpr::EvaluateAsAbsolute(int64_t &Res) const { - return EvaluateAsAbsolute(Res, 0, 0, 0); + return EvaluateAsAbsolute(Res, nullptr, nullptr, nullptr); } bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const { - return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, 0); + return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr); } bool MCExpr::EvaluateAsAbsolute(int64_t &Res, @@ -434,7 +464,7 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, } bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const { - return EvaluateAsAbsolute(Res, &Asm, 0, 0); + return EvaluateAsAbsolute(Res, &Asm, nullptr, nullptr); } bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, @@ -452,7 +482,8 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, // absolutize differences across sections and that is what the MachO writer // uses Addrs for. bool IsRelocatable = - EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, /*InSet*/ Addrs); + EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, /*InSet*/ Addrs, + /*ForceVarExpansion*/ false); // Record the current value. Res = Value.getConstant(); @@ -480,8 +511,8 @@ static void AttemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, if (!Asm->getWriter().IsSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet)) return; - MCSymbolData &AD = Asm->getSymbolData(SA); - MCSymbolData &BD = Asm->getSymbolData(SB); + const MCSymbolData &AD = Asm->getSymbolData(SA); + const MCSymbolData &BD = Asm->getSymbolData(SB); if (AD.getFragment() == BD.getFragment()) { Addend += (AD.getOffset() - BD.getOffset()); @@ -493,7 +524,7 @@ static void AttemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, // Clear the symbol expr pointers to indicate we have folded these // operands. - A = B = 0; + A = B = nullptr; return; } @@ -519,7 +550,7 @@ static void AttemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, // Clear the symbol expr pointers to indicate we have folded these // operands. - A = B = 0; + A = B = nullptr; } /// \brief Evaluate the result of an add between (conceptually) two MCValues. @@ -601,16 +632,22 @@ static bool EvaluateSymbolicAdd(const MCAssembler *Asm, } bool MCExpr::EvaluateAsRelocatable(MCValue &Res, - const MCAsmLayout &Layout) const { - return EvaluateAsRelocatableImpl(Res, &Layout.getAssembler(), &Layout, - 0, false); + const MCAsmLayout *Layout) const { + MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr; + return EvaluateAsRelocatableImpl(Res, Assembler, Layout, nullptr, false, + /*ForceVarExpansion*/ false); } -bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, - const MCAssembler *Asm, +bool MCExpr::EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout) const { + MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr; + return EvaluateAsRelocatableImpl(Res, Assembler, Layout, nullptr, false, + /*ForceVarExpansion*/ true); +} + +bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, - const SectionAddrMap *Addrs, - bool InSet) const { + const SectionAddrMap *Addrs, bool InSet, + bool ForceVarExpansion) const { ++stats::MCExprEvaluate; switch (getKind()) { @@ -624,20 +661,35 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, case SymbolRef: { const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); const MCSymbol &Sym = SRE->getSymbol(); + const MCAsmInfo &MCAsmInfo = SRE->getMCAsmInfo(); // Evaluate recursively if this is a variable. if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) { - bool Ret = Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Asm, - Layout, - Addrs, - true); - // If we failed to simplify this to a constant, let the target - // handle it. - if (Ret && !Res.getSymA() && !Res.getSymB()) - return true; + if (Sym.getVariableValue()->EvaluateAsRelocatableImpl( + Res, Asm, Layout, Addrs, true, ForceVarExpansion)) { + const MCSymbolRefExpr *A = Res.getSymA(); + const MCSymbolRefExpr *B = Res.getSymB(); + + if (MCAsmInfo.hasSubsectionsViaSymbols()) { + // FIXME: This is small hack. Given + // a = b + 4 + // .long a + // the OS X assembler will completely drop the 4. We should probably + // include it in the relocation or produce an error if that is not + // possible. + if (!A && !B) + return true; + } else { + if (ForceVarExpansion) + return true; + bool IsSymbol = A && A->getSymbol().isDefined(); + if (!IsSymbol) + return true; + } + } } - Res = MCValue::get(SRE, 0, 0); + Res = MCValue::get(SRE, nullptr, 0); return true; } @@ -645,8 +697,8 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this); MCValue Value; - if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout, - Addrs, InSet)) + if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, + InSet, ForceVarExpansion)) return false; switch (AUE->getOpcode()) { @@ -679,10 +731,10 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this); MCValue LHSValue, RHSValue; - if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout, - Addrs, InSet) || - !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout, - Addrs, InSet)) + if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout, Addrs, + InSet, ForceVarExpansion) || + !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout, Addrs, + InSet, ForceVarExpansion)) return false; // We only support a few operations on non-constant expressions, handle @@ -756,7 +808,7 @@ const MCSection *MCExpr::FindAssociatedSection() const { if (Sym.isDefined()) return &Sym.getSection(); - return 0; + return nullptr; } case Unary: diff --git a/contrib/llvm/lib/MC/MCExternalSymbolizer.cpp b/contrib/llvm/lib/MC/MCExternalSymbolizer.cpp index ca368b2..7c3073a 100644 --- a/contrib/llvm/lib/MC/MCExternalSymbolizer.cpp +++ b/contrib/llvm/lib/MC/MCExternalSymbolizer.cpp @@ -43,8 +43,19 @@ bool MCExternalSymbolizer::tryAddingSymbolicOperand(MCInst &MI, !GetOpInfo(DisInfo, Address, Offset, InstSize, 1, &SymbolicOp)) { // Clear SymbolicOp.Value from above and also all other fields. std::memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1)); - if (!SymbolLookUp) + + // At this point, GetOpInfo() did not find any relocation information about + // this operand and we are left to use the SymbolLookUp() call back to guess + // if the Value is the address of a symbol. In the case this is a branch + // that always makes sense to guess. But in the case of an immediate it is + // a bit more questionable if it is an address of a symbol or some other + // reference. So if the immediate Value comes from a width of 1 byte, + // InstSize, we will not guess it is an address of a symbol. Because in + // object files assembled starting at address 0 this usually leads to + // incorrect symbolication. + if (!SymbolLookUp || (InstSize == 1 && !IsBranch)) return false; + uint64_t ReferenceType; if (IsBranch) ReferenceType = LLVMDisassembler_ReferenceType_In_Branch; @@ -56,6 +67,9 @@ bool MCExternalSymbolizer::tryAddingSymbolicOperand(MCInst &MI, if (Name) { SymbolicOp.AddSymbol.Name = Name; SymbolicOp.AddSymbol.Present = true; + // If Name is a C++ symbol name put the human readable name in a comment. + if(ReferenceType == LLVMDisassembler_ReferenceType_DeMangled_Name) + cStream << ReferenceName; } // For branches always create an MCExpr so it gets printed as hex address. else if (IsBranch) { @@ -69,7 +83,7 @@ bool MCExternalSymbolizer::tryAddingSymbolicOperand(MCInst &MI, return false; } - const MCExpr *Add = NULL; + const MCExpr *Add = nullptr; if (SymbolicOp.AddSymbol.Present) { if (SymbolicOp.AddSymbol.Name) { StringRef Name(SymbolicOp.AddSymbol.Name); @@ -80,7 +94,7 @@ bool MCExternalSymbolizer::tryAddingSymbolicOperand(MCInst &MI, } } - const MCExpr *Sub = NULL; + const MCExpr *Sub = nullptr; if (SymbolicOp.SubtractSymbol.Present) { if (SymbolicOp.SubtractSymbol.Name) { StringRef Name(SymbolicOp.SubtractSymbol.Name); @@ -91,7 +105,7 @@ bool MCExternalSymbolizer::tryAddingSymbolicOperand(MCInst &MI, } } - const MCExpr *Off = NULL; + const MCExpr *Off = nullptr; if (SymbolicOp.Value != 0) Off = MCConstantExpr::Create(SymbolicOp.Value, Ctx); @@ -102,17 +116,17 @@ bool MCExternalSymbolizer::tryAddingSymbolicOperand(MCInst &MI, LHS = MCBinaryExpr::CreateSub(Add, Sub, Ctx); else LHS = MCUnaryExpr::CreateMinus(Sub, Ctx); - if (Off != 0) + if (Off) Expr = MCBinaryExpr::CreateAdd(LHS, Off, Ctx); else Expr = LHS; } else if (Add) { - if (Off != 0) + if (Off) Expr = MCBinaryExpr::CreateAdd(Add, Off, Ctx); else Expr = Add; } else { - if (Off != 0) + if (Off) Expr = Off; else Expr = MCConstantExpr::Create(0, Ctx); @@ -146,8 +160,11 @@ void MCExternalSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream, if(ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr) cStream << "literal pool symbol address: " << ReferenceName; else if(ReferenceType == - LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr) - cStream << "literal pool for: \"" << ReferenceName << "\""; + LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr) { + cStream << "literal pool for: \""; + cStream.write_escaped(ReferenceName); + cStream << "\""; + } else if(ReferenceType == LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref) cStream << "Objc cfstring ref: @\"" << ReferenceName << "\""; @@ -172,10 +189,10 @@ MCSymbolizer *createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo, void *DisInfo, MCContext *Ctx, MCRelocationInfo *RelInfo) { - assert(Ctx != 0 && "No MCContext given for symbolic disassembly"); + assert(Ctx && "No MCContext given for symbolic disassembly"); - OwningPtr<MCRelocationInfo> RelInfoOwingPtr(RelInfo); - return new MCExternalSymbolizer(*Ctx, RelInfoOwingPtr, GetOpInfo, - SymbolLookUp, DisInfo); + return new MCExternalSymbolizer(*Ctx, + std::unique_ptr<MCRelocationInfo>(RelInfo), + GetOpInfo, SymbolLookUp, DisInfo); } } diff --git a/contrib/llvm/lib/MC/MCInst.cpp b/contrib/llvm/lib/MC/MCInst.cpp index 124cc14..d7b80f5 100644 --- a/contrib/llvm/lib/MC/MCInst.cpp +++ b/contrib/llvm/lib/MC/MCInst.cpp @@ -34,7 +34,7 @@ void MCOperand::print(raw_ostream &OS, const MCAsmInfo *MAI) const { #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void MCOperand::dump() const { - print(dbgs(), 0); + print(dbgs(), nullptr); dbgs() << "\n"; } #endif @@ -66,7 +66,7 @@ void MCInst::dump_pretty(raw_ostream &OS, const MCAsmInfo *MAI, #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void MCInst::dump() const { - print(dbgs(), 0); + print(dbgs(), nullptr); dbgs() << "\n"; } #endif diff --git a/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp b/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp new file mode 100644 index 0000000..3f8d620 --- /dev/null +++ b/contrib/llvm/lib/MC/MCLinkerOptimizationHint.cpp @@ -0,0 +1,35 @@ +//===-- llvm/MC/MCLinkerOptimizationHint.cpp ----- LOH handling -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCLinkerOptimizationHint.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/Support/LEB128.h" +#include "llvm/MC/MCStreamer.h" + +using namespace llvm; + +// Each LOH is composed by, in this order (each field is encoded using ULEB128): +// - Its kind. +// - Its number of arguments (let say N). +// - Its arg1. +// - ... +// - Its argN. +// <arg1> to <argN> are absolute addresses in the object file, i.e., +// relative addresses from the beginning of the object file. +void MCLOHDirective::Emit_impl(raw_ostream &OutStream, + const MachObjectWriter &ObjWriter, + const MCAsmLayout &Layout) const { + const MCAssembler &Asm = Layout.getAssembler(); + encodeULEB128(Kind, OutStream); + encodeULEB128(Args.size(), OutStream); + for (LOHArgs::const_iterator It = Args.begin(), EndIt = Args.end(); + It != EndIt; ++It) + encodeULEB128(ObjWriter.getSymbolAddress(&Asm.getSymbolData(**It), Layout), + OutStream); +} diff --git a/contrib/llvm/lib/MC/MCMachOStreamer.cpp b/contrib/llvm/lib/MC/MCMachOStreamer.cpp index 2924dcd..9e8bc94 100644 --- a/contrib/llvm/lib/MC/MCMachOStreamer.cpp +++ b/contrib/llvm/lib/MC/MCMachOStreamer.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCStreamer.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCCodeEmitter.h" @@ -15,7 +17,9 @@ #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCLinkerOptimizationHint.h" #include "llvm/MC/MCMachOSymbolFlags.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionMachO.h" @@ -30,79 +34,96 @@ namespace { class MCMachOStreamer : public MCObjectStreamer { private: - virtual void EmitInstToData(const MCInst &Inst); + /// LabelSections - true if each section change should emit a linker local + /// label for use in relocations for assembler local references. Obviates the + /// need for local relocations. False by default. + bool LabelSections; + + /// HasSectionLabel - map of which sections have already had a non-local + /// label emitted to them. Used so we don't emit extraneous linker local + /// labels in the middle of the section. + DenseMap<const MCSection*, bool> HasSectionLabel; + + void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) override; void EmitDataRegion(DataRegionData::KindTy Kind); void EmitDataRegionEnd(); + public: MCMachOStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, - MCCodeEmitter *Emitter) - : MCObjectStreamer(Context, 0, MAB, OS, Emitter) {} + MCCodeEmitter *Emitter, bool label) + : MCObjectStreamer(Context, MAB, OS, Emitter), + LabelSections(label) {} /// @name MCStreamer Interface /// @{ - virtual void InitSections(); - virtual void InitToTextSection(); - virtual void EmitLabel(MCSymbol *Symbol); - virtual void EmitDebugLabel(MCSymbol *Symbol); - virtual void EmitEHSymAttributes(const MCSymbol *Symbol, - MCSymbol *EHSymbol); - virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); - virtual void EmitLinkerOptions(ArrayRef<std::string> Options); - virtual void EmitDataRegion(MCDataRegionType Kind); - virtual void EmitThumbFunc(MCSymbol *Func); - virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); - virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); - virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment); - virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) { + void ChangeSection(const MCSection *Sect, const MCExpr *Subsect) override; + void EmitLabel(MCSymbol *Symbol) override; + void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) override; + void EmitAssemblerFlag(MCAssemblerFlag Flag) override; + void EmitLinkerOptions(ArrayRef<std::string> Options) override; + void EmitDataRegion(MCDataRegionType Kind) override; + void EmitVersionMin(MCVersionMinType Kind, unsigned Major, + unsigned Minor, unsigned Update) override; + void EmitThumbFunc(MCSymbol *Func) override; + bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; + void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; + void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + void BeginCOFFSymbolDef(const MCSymbol *Symbol) override { llvm_unreachable("macho doesn't support this directive"); } - virtual void EmitCOFFSymbolStorageClass(int StorageClass) { + void EmitCOFFSymbolStorageClass(int StorageClass) override { llvm_unreachable("macho doesn't support this directive"); } - virtual void EmitCOFFSymbolType(int Type) { + void EmitCOFFSymbolType(int Type) override { llvm_unreachable("macho doesn't support this directive"); } - virtual void EndCOFFSymbolDef() { + void EndCOFFSymbolDef() override { llvm_unreachable("macho doesn't support this directive"); } - virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { + void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) override { llvm_unreachable("macho doesn't support this directive"); } - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment); - virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, - uint64_t Size = 0, unsigned ByteAlignment = 0); + void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = nullptr, + uint64_t Size = 0, unsigned ByteAlignment = 0) override; virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment = 0); + uint64_t Size, unsigned ByteAlignment = 0) override; - virtual void EmitFileDirective(StringRef Filename) { + void EmitFileDirective(StringRef Filename) override { // FIXME: Just ignore the .file; it isn't important enough to fail the // entire assembly. // report_fatal_error("unsupported directive: '.file'"); } - virtual void EmitIdent(StringRef IdentString) { + void EmitIdent(StringRef IdentString) override { llvm_unreachable("macho doesn't support this directive"); } - virtual void FinishImpl(); + void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override { + getAssembler().getLOHContainer().addDirective(Kind, Args); + } + + void FinishImpl() override; }; } // end anonymous namespace. -void MCMachOStreamer::InitSections() { - InitToTextSection(); -} - -void MCMachOStreamer::InitToTextSection() { - SwitchSection(getContext().getMachOSection( - "__TEXT", "__text", - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 0, - SectionKind::getText())); +void MCMachOStreamer::ChangeSection(const MCSection *Section, + const MCExpr *Subsection) { + // Change the section normally. + MCObjectStreamer::ChangeSection(Section, Subsection); + // Output a linker-local symbol so we don't need section-relative local + // relocations. The linker hates us when we do that. + if (LabelSections && !HasSectionLabel[Section]) { + MCSymbol *Label = getContext().CreateLinkerPrivateTempSymbol(); + EmitLabel(Label); + HasSectionLabel[Section] = true; + } } void MCMachOStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, @@ -140,9 +161,6 @@ void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { SD.setFlags(SD.getFlags() & ~SF_ReferenceTypeMask); } -void MCMachOStreamer::EmitDebugLabel(MCSymbol *Symbol) { - EmitLabel(Symbol); -} void MCMachOStreamer::EmitDataRegion(DataRegionData::KindTy Kind) { if (!getAssembler().getBackend().hasDataInCodeSupport()) return; @@ -150,7 +168,7 @@ void MCMachOStreamer::EmitDataRegion(DataRegionData::KindTy Kind) { MCSymbol *Start = getContext().CreateTempSymbol(); EmitLabel(Start); // Record the region for the object writer to use. - DataRegionData Data = { Kind, Start, NULL }; + DataRegionData Data = { Kind, Start, nullptr }; std::vector<DataRegionData> &Regions = getAssembler().getDataRegions(); Regions.push_back(Data); } @@ -161,7 +179,7 @@ void MCMachOStreamer::EmitDataRegionEnd() { std::vector<DataRegionData> &Regions = getAssembler().getDataRegions(); assert(Regions.size() && "Mismatched .end_data_region!"); DataRegionData &Data = Regions.back(); - assert(Data.End == NULL && "Mismatched .end_data_region!"); + assert(!Data.End && "Mismatched .end_data_region!"); // Create a temporary label to mark the end of the data region. Data.End = getContext().CreateTempSymbol(); EmitLabel(Data.End); @@ -206,14 +224,15 @@ void MCMachOStreamer::EmitDataRegion(MCDataRegionType Kind) { } } +void MCMachOStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major, + unsigned Minor, unsigned Update) { + getAssembler().setVersionMinInfo(Kind, Major, Minor, Update); +} + void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) { // Remember that the function is a thumb function. Fixup and relocation // values will need adjusted. getAssembler().setIsThumbFunc(Symbol); - - // Mark the thumb bit on the symbol. - MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); - SD.setFlags(SD.getFlags() | SF_ThumbFunc); } bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, @@ -325,7 +344,7 @@ void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, // FIXME: Darwin 'as' does appear to allow redef of a .comm by itself. assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - AssignSection(Symbol, NULL); + AssignSection(Symbol, nullptr); MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); SD.setExternal(true); @@ -335,9 +354,7 @@ void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, void MCMachOStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { // '.lcomm' is equivalent to '.zerofill'. - return EmitZerofill(getContext().getMachOSection("__DATA", "__bss", - MCSectionMachO::S_ZEROFILL, - 0, SectionKind::getBSS()), + return EmitZerofill(getContext().getObjectFileInfo()->getDataBSSSection(), Symbol, Size, ByteAlignment); } @@ -378,13 +395,14 @@ void MCMachOStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, return; } -void MCMachOStreamer::EmitInstToData(const MCInst &Inst) { +void MCMachOStreamer::EmitInstToData(const MCInst &Inst, + const MCSubtargetInfo &STI) { MCDataFragment *DF = getOrCreateDataFragment(); SmallVector<MCFixup, 4> Fixups; SmallString<256> Code; raw_svector_ostream VecOS(Code); - getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups); + getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups, STI); VecOS.flush(); // Add the fixups and data. @@ -396,7 +414,7 @@ void MCMachOStreamer::EmitInstToData(const MCInst &Inst) { } void MCMachOStreamer::FinishImpl() { - EmitFrames(&getAssembler().getBackend(), true); + EmitFrames(&getAssembler().getBackend()); // We have to set the fragment atom associations so we can relax properly for // Mach-O. @@ -404,13 +422,12 @@ void MCMachOStreamer::FinishImpl() { // First, scan the symbol table to build a lookup table from fragments to // defining symbols. DenseMap<const MCFragment*, MCSymbolData*> DefiningSymbolMap; - for (MCAssembler::symbol_iterator it = getAssembler().symbol_begin(), - ie = getAssembler().symbol_end(); it != ie; ++it) { - if (getAssembler().isSymbolLinkerVisible(it->getSymbol()) && - it->getFragment()) { + for (MCSymbolData &SD : getAssembler().symbols()) { + if (getAssembler().isSymbolLinkerVisible(SD.getSymbol()) && + SD.getFragment()) { // An atom defining symbol should never be internal to a fragment. - assert(it->getOffset() == 0 && "Invalid offset in atom defining symbol!"); - DefiningSymbolMap[it->getFragment()] = it; + assert(SD.getOffset() == 0 && "Invalid offset in atom defining symbol!"); + DefiningSymbolMap[SD.getFragment()] = &SD; } } @@ -418,7 +435,7 @@ void MCMachOStreamer::FinishImpl() { // symbol. for (MCAssembler::iterator it = getAssembler().begin(), ie = getAssembler().end(); it != ie; ++it) { - MCSymbolData *CurrentAtom = 0; + MCSymbolData *CurrentAtom = nullptr; for (MCSectionData::iterator it2 = it->begin(), ie2 = it->end(); it2 != ie2; ++it2) { if (MCSymbolData *SD = DefiningSymbolMap.lookup(it2)) @@ -432,8 +449,9 @@ void MCMachOStreamer::FinishImpl() { MCStreamer *llvm::createMachOStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll) { - MCMachOStreamer *S = new MCMachOStreamer(Context, MAB, OS, CE); + bool RelaxAll, + bool LabelSections) { + MCMachOStreamer *S = new MCMachOStreamer(Context, MAB, OS, CE, LabelSections); if (RelaxAll) S->getAssembler().setRelaxAll(true); return S; diff --git a/contrib/llvm/lib/MC/MCNullStreamer.cpp b/contrib/llvm/lib/MC/MCNullStreamer.cpp index 9b9c4aa..d543402 100644 --- a/contrib/llvm/lib/MC/MCNullStreamer.cpp +++ b/contrib/llvm/lib/MC/MCNullStreamer.cpp @@ -19,96 +19,22 @@ namespace { class MCNullStreamer : public MCStreamer { public: - MCNullStreamer(MCContext &Context) : MCStreamer(Context, 0) {} + MCNullStreamer(MCContext &Context) : MCStreamer(Context) {} /// @name MCStreamer Interface /// @{ - virtual void InitToTextSection() { - } - - virtual void InitSections() { - } - - virtual void ChangeSection(const MCSection *Section, - const MCExpr *Subsection) { - } - - virtual void EmitLabel(MCSymbol *Symbol) { - assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - assert(getCurrentSection().first &&"Cannot emit before setting section!"); - AssignSection(Symbol, getCurrentSection().first); - } - virtual void EmitDebugLabel(MCSymbol *Symbol) { - EmitLabel(Symbol); - } - virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {} - virtual void EmitThumbFunc(MCSymbol *Func) {} - - virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {} - virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol){} - virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, - const MCSymbol *LastLabel, - const MCSymbol *Label, - unsigned PointerSize) {} - - virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute){ + bool EmitSymbolAttribute(MCSymbol *Symbol, + MCSymbolAttr Attribute) override { return true; } - virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {} - - virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) {} - virtual void EmitCOFFSymbolStorageClass(int StorageClass) {} - virtual void EmitCOFFSymbolType(int Type) {} - virtual void EndCOFFSymbolDef() {} - virtual void EmitCOFFSecRel32(MCSymbol const *Symbol) {} - - virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {} - virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) {} - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) {} - virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, - uint64_t Size = 0, unsigned ByteAlignment = 0) {} - virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment) {} - virtual void EmitBytes(StringRef Data) {} - - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size) {} - virtual void EmitULEB128Value(const MCExpr *Value) {} - virtual void EmitSLEB128Value(const MCExpr *Value) {} - virtual void EmitGPRel32Value(const MCExpr *Value) {} - virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, - unsigned ValueSize = 1, - unsigned MaxBytesToEmit = 0) {} - - virtual void EmitCodeAlignment(unsigned ByteAlignment, - unsigned MaxBytesToEmit = 0) {} - - virtual bool EmitValueToOffset(const MCExpr *Offset, - unsigned char Value = 0) { return false; } - - virtual void EmitFileDirective(StringRef Filename) {} - virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, - StringRef Filename, unsigned CUID = 0) { - return false; - } - virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, - unsigned Column, unsigned Flags, - unsigned Isa, unsigned Discriminator, - StringRef FileName) {} - virtual void EmitInstruction(const MCInst &Inst) {} - - virtual void EmitBundleAlignMode(unsigned AlignPow2) {} - virtual void EmitBundleLock(bool AlignToEnd) {} - virtual void EmitBundleUnlock() {} - - virtual void FinishImpl() {} - - virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { - RecordProcEnd(Frame); - } + void EmitCOFFSecRel32(MCSymbol const *Symbol) override {} + void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override {} + void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = nullptr, + uint64_t Size = 0, unsigned ByteAlignment = 0) override {} + void EmitGPRel32Value(const MCExpr *Value) override {} }; } diff --git a/contrib/llvm/lib/MC/MCObjectFileInfo.cpp b/contrib/llvm/lib/MC/MCObjectFileInfo.cpp index 799e061..d490ef3 100644 --- a/contrib/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/contrib/llvm/lib/MC/MCObjectFileInfo.cpp @@ -8,7 +8,9 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionCOFF.h" @@ -16,14 +18,38 @@ #include "llvm/MC/MCSectionMachO.h" using namespace llvm; +static bool useCompactUnwind(const Triple &T) { + // Only on darwin. + if (!T.isOSDarwin()) + return false; + + // aarch64 always has it. + if (T.getArch() == Triple::arm64 || T.getArch() == Triple::aarch64) + return true; + + // Use it on newer version of OS X. + if (T.isMacOSX() && !T.isMacOSXVersionLT(10, 6)) + return true; + + // And the iOS simulator. + if (T.isiOS() && + (T.getArch() == Triple::x86_64 || T.getArch() == Triple::x86)) + return true; + + return false; +} + void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { // MachO - IsFunctionEHFrameSymbolPrivate = false; SupportsWeakOmittedEHFrame = false; + if (T.isOSDarwin() && + (T.getArch() == Triple::arm64 || T.getArch() == Triple::aarch64)) + SupportsCompactUnwindWithoutEHFrame = true; + PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; - LSDAEncoding = FDEEncoding = FDECFIEncoding = dwarf::DW_EH_PE_pcrel; + LSDAEncoding = FDECFIEncoding = dwarf::DW_EH_PE_pcrel; TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; @@ -33,61 +59,55 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { TextSection // .text = Ctx->getMachOSection("__TEXT", "__text", - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + MachO::S_ATTR_PURE_INSTRUCTIONS, SectionKind::getText()); DataSection // .data = Ctx->getMachOSection("__DATA", "__data", 0, SectionKind::getDataRel()); // BSSSection might not be expected initialized on msvc. - BSSSection = 0; + BSSSection = nullptr; TLSDataSection // .tdata = Ctx->getMachOSection("__DATA", "__thread_data", - MCSectionMachO::S_THREAD_LOCAL_REGULAR, + MachO::S_THREAD_LOCAL_REGULAR, SectionKind::getDataRel()); TLSBSSSection // .tbss = Ctx->getMachOSection("__DATA", "__thread_bss", - MCSectionMachO::S_THREAD_LOCAL_ZEROFILL, + MachO::S_THREAD_LOCAL_ZEROFILL, SectionKind::getThreadBSS()); // TODO: Verify datarel below. TLSTLVSection // .tlv = Ctx->getMachOSection("__DATA", "__thread_vars", - MCSectionMachO::S_THREAD_LOCAL_VARIABLES, + MachO::S_THREAD_LOCAL_VARIABLES, SectionKind::getDataRel()); TLSThreadInitSection = Ctx->getMachOSection("__DATA", "__thread_init", - MCSectionMachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS, + MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS, SectionKind::getDataRel()); CStringSection // .cstring = Ctx->getMachOSection("__TEXT", "__cstring", - MCSectionMachO::S_CSTRING_LITERALS, + MachO::S_CSTRING_LITERALS, SectionKind::getMergeable1ByteCString()); UStringSection = Ctx->getMachOSection("__TEXT","__ustring", 0, SectionKind::getMergeable2ByteCString()); FourByteConstantSection // .literal4 = Ctx->getMachOSection("__TEXT", "__literal4", - MCSectionMachO::S_4BYTE_LITERALS, + MachO::S_4BYTE_LITERALS, SectionKind::getMergeableConst4()); EightByteConstantSection // .literal8 = Ctx->getMachOSection("__TEXT", "__literal8", - MCSectionMachO::S_8BYTE_LITERALS, + MachO::S_8BYTE_LITERALS, SectionKind::getMergeableConst8()); - // ld_classic doesn't support .literal16 in 32-bit mode, and ld64 falls back - // to using it in -static mode. - SixteenByteConstantSection = 0; - if (RelocM != Reloc::Static && - T.getArch() != Triple::x86_64 && T.getArch() != Triple::ppc64 && - T.getArch() != Triple::ppc64le) - SixteenByteConstantSection = // .literal16 - Ctx->getMachOSection("__TEXT", "__literal16", - MCSectionMachO::S_16BYTE_LITERALS, - SectionKind::getMergeableConst16()); + SixteenByteConstantSection // .literal16 + = Ctx->getMachOSection("__TEXT", "__literal16", + MachO::S_16BYTE_LITERALS, + SectionKind::getMergeableConst16()); ReadOnlySection // .const = Ctx->getMachOSection("__TEXT", "__const", 0, @@ -95,36 +115,36 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { TextCoalSection = Ctx->getMachOSection("__TEXT", "__textcoal_nt", - MCSectionMachO::S_COALESCED | - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + MachO::S_COALESCED | + MachO::S_ATTR_PURE_INSTRUCTIONS, SectionKind::getText()); ConstTextCoalSection = Ctx->getMachOSection("__TEXT", "__const_coal", - MCSectionMachO::S_COALESCED, + MachO::S_COALESCED, SectionKind::getReadOnly()); ConstDataSection // .const_data = Ctx->getMachOSection("__DATA", "__const", 0, SectionKind::getReadOnlyWithRel()); DataCoalSection = Ctx->getMachOSection("__DATA","__datacoal_nt", - MCSectionMachO::S_COALESCED, + MachO::S_COALESCED, SectionKind::getDataRel()); DataCommonSection = Ctx->getMachOSection("__DATA","__common", - MCSectionMachO::S_ZEROFILL, + MachO::S_ZEROFILL, SectionKind::getBSS()); DataBSSSection - = Ctx->getMachOSection("__DATA","__bss", MCSectionMachO::S_ZEROFILL, + = Ctx->getMachOSection("__DATA","__bss", MachO::S_ZEROFILL, SectionKind::getBSS()); LazySymbolPointerSection = Ctx->getMachOSection("__DATA", "__la_symbol_ptr", - MCSectionMachO::S_LAZY_SYMBOL_POINTERS, + MachO::S_LAZY_SYMBOL_POINTERS, SectionKind::getMetadata()); NonLazySymbolPointerSection = Ctx->getMachOSection("__DATA", "__nl_symbol_ptr", - MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, + MachO::S_NON_LAZY_SYMBOL_POINTERS, SectionKind::getMetadata()); if (RelocM == Reloc::Static) { @@ -137,11 +157,11 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { } else { StaticCtorSection = Ctx->getMachOSection("__DATA", "__mod_init_func", - MCSectionMachO::S_MOD_INIT_FUNC_POINTERS, + MachO::S_MOD_INIT_FUNC_POINTERS, SectionKind::getDataRel()); StaticDtorSection = Ctx->getMachOSection("__DATA", "__mod_term_func", - MCSectionMachO::S_MOD_TERM_FUNC_POINTERS, + MachO::S_MOD_TERM_FUNC_POINTERS, SectionKind::getDataRel()); } @@ -149,90 +169,93 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { LSDASection = Ctx->getMachOSection("__TEXT", "__gcc_except_tab", 0, SectionKind::getReadOnlyWithRel()); - if (T.isMacOSX() && !T.isMacOSXVersionLT(10, 6)) { + COFFDebugSymbolsSection = nullptr; + + if (useCompactUnwind(T)) { CompactUnwindSection = - Ctx->getMachOSection("__LD", "__compact_unwind", - MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getReadOnly()); + Ctx->getMachOSection("__LD", "__compact_unwind", MachO::S_ATTR_DEBUG, + SectionKind::getReadOnly()); if (T.getArch() == Triple::x86_64 || T.getArch() == Triple::x86) CompactUnwindDwarfEHFrameOnly = 0x04000000; + else if (T.getArch() == Triple::arm64 || T.getArch() == Triple::aarch64) + CompactUnwindDwarfEHFrameOnly = 0x03000000; } // Debug Information. DwarfAccelNamesSection = Ctx->getMachOSection("__DWARF", "__apple_names", - MCSectionMachO::S_ATTR_DEBUG, + MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfAccelObjCSection = Ctx->getMachOSection("__DWARF", "__apple_objc", - MCSectionMachO::S_ATTR_DEBUG, + MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); // 16 character section limit... DwarfAccelNamespaceSection = Ctx->getMachOSection("__DWARF", "__apple_namespac", - MCSectionMachO::S_ATTR_DEBUG, + MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfAccelTypesSection = Ctx->getMachOSection("__DWARF", "__apple_types", - MCSectionMachO::S_ATTR_DEBUG, + MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfAbbrevSection = Ctx->getMachOSection("__DWARF", "__debug_abbrev", - MCSectionMachO::S_ATTR_DEBUG, + MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfInfoSection = Ctx->getMachOSection("__DWARF", "__debug_info", - MCSectionMachO::S_ATTR_DEBUG, + MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfLineSection = Ctx->getMachOSection("__DWARF", "__debug_line", - MCSectionMachO::S_ATTR_DEBUG, + MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfFrameSection = Ctx->getMachOSection("__DWARF", "__debug_frame", - MCSectionMachO::S_ATTR_DEBUG, + MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfPubNamesSection = Ctx->getMachOSection("__DWARF", "__debug_pubnames", - MCSectionMachO::S_ATTR_DEBUG, + MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfPubTypesSection = Ctx->getMachOSection("__DWARF", "__debug_pubtypes", - MCSectionMachO::S_ATTR_DEBUG, + MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfGnuPubNamesSection = Ctx->getMachOSection("__DWARF", "__debug_gnu_pubn", - MCSectionMachO::S_ATTR_DEBUG, + MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfGnuPubTypesSection = Ctx->getMachOSection("__DWARF", "__debug_gnu_pubt", - MCSectionMachO::S_ATTR_DEBUG, + MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfStrSection = Ctx->getMachOSection("__DWARF", "__debug_str", - MCSectionMachO::S_ATTR_DEBUG, + MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfLocSection = Ctx->getMachOSection("__DWARF", "__debug_loc", - MCSectionMachO::S_ATTR_DEBUG, + MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfARangesSection = Ctx->getMachOSection("__DWARF", "__debug_aranges", - MCSectionMachO::S_ATTR_DEBUG, + MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfRangesSection = Ctx->getMachOSection("__DWARF", "__debug_ranges", - MCSectionMachO::S_ATTR_DEBUG, + MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfMacroInfoSection = Ctx->getMachOSection("__DWARF", "__debug_macinfo", - MCSectionMachO::S_ATTR_DEBUG, + MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); DwarfDebugInlineSection = Ctx->getMachOSection("__DWARF", "__debug_inlined", - MCSectionMachO::S_ATTR_DEBUG, + MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); StackMapSection = Ctx->getMachOSection("__LLVM_STACKMAPS", "__llvm_stackmaps", 0, @@ -242,29 +265,40 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { } void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { - if (T.getArch() == Triple::mips || - T.getArch() == Triple::mipsel) + switch (T.getArch()) { + case Triple::mips: + case Triple::mipsel: FDECFIEncoding = dwarf::DW_EH_PE_sdata4; - else if (T.getArch() == Triple::mips64 || - T.getArch() == Triple::mips64el) + break; + case Triple::mips64: + case Triple::mips64el: FDECFIEncoding = dwarf::DW_EH_PE_sdata8; - else + break; + default: FDECFIEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + break; + } - if (T.getArch() == Triple::x86) { + switch (T.getArch()) { + case Triple::arm: + case Triple::armeb: + case Triple::thumb: + case Triple::thumbeb: + if (Ctx->getAsmInfo()->getExceptionHandlingType() == ExceptionHandling::ARM) + break; + // Fallthrough if not using EHABI + 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; - FDEEncoding = (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; - } else if (T.getArch() == Triple::x86_64) { + break; + case Triple::x86_64: if (RelocM == Reloc::PIC_) { PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | ((CMModel == CodeModel::Small || CMModel == CodeModel::Medium) @@ -272,7 +306,6 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { LSDAEncoding = dwarf::DW_EH_PE_pcrel | (CMModel == CodeModel::Small ? dwarf::DW_EH_PE_sdata4 : dwarf::DW_EH_PE_sdata8); - FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; TTypeEncoding = 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); @@ -282,11 +315,14 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_absptr; LSDAEncoding = (CMModel == CodeModel::Small) ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_absptr; - FDEEncoding = dwarf::DW_EH_PE_udata4; TTypeEncoding = (CMModel == CodeModel::Small) ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_absptr; } - } else if (T.getArch() == Triple::aarch64) { + break; + case Triple::aarch64: + case Triple::aarch64_be: + case Triple::arm64: + case Triple::arm64_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. @@ -294,65 +330,71 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { 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; - FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8; } else { PersonalityEncoding = dwarf::DW_EH_PE_absptr; LSDAEncoding = dwarf::DW_EH_PE_absptr; - FDEEncoding = dwarf::DW_EH_PE_udata4; TTypeEncoding = dwarf::DW_EH_PE_absptr; } - } else if (T.getArch() == Triple::ppc64 || T.getArch() == Triple::ppc64le) { + break; + case Triple::mips: + case Triple::mipsel: + // MIPS uses indirect pointer to refer personality functions, so that the + // eh_frame section can be read-only. DW.ref.personality will be generated + // for relocation. + PersonalityEncoding = dwarf::DW_EH_PE_indirect; + break; + case Triple::ppc64: + case Triple::ppc64le: PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8; LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8; - FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8; TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8; - } else if (T.getArch() == Triple::sparc) { + break; + case Triple::sparc: if (RelocM == Reloc::PIC_) { 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; - FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; } else { LSDAEncoding = dwarf::DW_EH_PE_absptr; PersonalityEncoding = dwarf::DW_EH_PE_absptr; - FDEEncoding = dwarf::DW_EH_PE_udata4; TTypeEncoding = dwarf::DW_EH_PE_absptr; } - } else if (T.getArch() == Triple::sparcv9) { + break; + case Triple::sparcv9: LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; if (RelocM == Reloc::PIC_) { PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; - FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; } else { PersonalityEncoding = dwarf::DW_EH_PE_absptr; - FDEEncoding = dwarf::DW_EH_PE_udata4; TTypeEncoding = dwarf::DW_EH_PE_absptr; } - } else if (T.getArch() == Triple::systemz) { + break; + case Triple::systemz: // All currently-defined code models guarantee that 4-byte PC-relative // values will be in range. if (RelocM == Reloc::PIC_) { 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; - FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; } else { PersonalityEncoding = dwarf::DW_EH_PE_absptr; LSDAEncoding = dwarf::DW_EH_PE_absptr; - FDEEncoding = dwarf::DW_EH_PE_absptr; TTypeEncoding = dwarf::DW_EH_PE_absptr; } + break; + default: + break; } // Solaris requires different flags for .eh_frame to seemingly every other @@ -457,6 +499,8 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { ELF::SHF_ALLOC, SectionKind::getReadOnly()); + COFFDebugSymbolsSection = nullptr; + // Debug Info Sections. DwarfAbbrevSection = Ctx->getELFSection(".debug_abbrev", ELF::SHT_PROGBITS, 0, @@ -542,6 +586,12 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { + bool IsWoA = T.getArch() == Triple::arm || T.getArch() == Triple::thumb; + + // The object file format cannot represent common symbols with explicit + // alignments. + CommDirectiveSupportsAlignment = false; + // COFF BSSSection = Ctx->getCOFFSection(".bss", @@ -551,6 +601,8 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { SectionKind::getBSS()); TextSection = Ctx->getCOFFSection(".text", + (IsWoA ? COFF::IMAGE_SCN_MEM_16BIT + : (COFF::SectionCharacteristics)0) | COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE | COFF::IMAGE_SCN_MEM_READ, @@ -566,12 +618,18 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ, SectionKind::getReadOnly()); - if (T.getOS() == Triple::Win32) { + + if (T.isKnownWindowsMSVCEnvironment() || T.isWindowsItaniumEnvironment()) { StaticCtorSection = Ctx->getCOFFSection(".CRT$XCU", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ, SectionKind::getReadOnly()); + StaticDtorSection = + Ctx->getCOFFSection(".CRT$XTX", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getReadOnly()); } else { StaticCtorSection = Ctx->getCOFFSection(".ctors", @@ -579,16 +637,6 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE, SectionKind::getDataRel()); - } - - - if (T.getOS() == Triple::Win32) { - StaticDtorSection = - Ctx->getCOFFSection(".CRT$XTX", - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getReadOnly()); - } else { StaticDtorSection = Ctx->getCOFFSection(".dtors", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | @@ -601,13 +649,25 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { // though it contains relocatable pointers. In PIC mode, this is probably a // big runtime hit for C++ apps. Either the contents of the LSDA need to be // adjusted or this should be a data section. - LSDASection = - Ctx->getCOFFSection(".gcc_except_table", + assert(T.isOSWindows() && "Windows is the only supported COFF target"); + if (T.getArch() == Triple::x86_64) { + // On Windows 64 with SEH, the LSDA is emitted into the .xdata section + LSDASection = 0; + } else { + LSDASection = Ctx->getCOFFSection(".gcc_except_table", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getReadOnly()); + } + + // Debug info. + COFFDebugSymbolsSection = + Ctx->getCOFFSection(".debug$S", + COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ, - SectionKind::getReadOnly()); + SectionKind::getMetadata()); - // Debug info. DwarfAbbrevSection = Ctx->getCOFFSection(".debug_abbrev", COFF::IMAGE_SCN_MEM_DISCARDABLE | @@ -673,10 +733,47 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_MEM_READ, SectionKind::getMetadata()); + DwarfInfoDWOSection = + Ctx->getCOFFSection(".debug_info.dwo", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfAbbrevDWOSection = + Ctx->getCOFFSection(".debug_abbrev.dwo", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfStrDWOSection = + Ctx->getCOFFSection(".debug_str.dwo", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfLineDWOSection = + Ctx->getCOFFSection(".debug_line.dwo", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfLocDWOSection = + Ctx->getCOFFSection(".debug_loc.dwo", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfStrOffDWOSection = + Ctx->getCOFFSection(".debug_str_offsets.dwo", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + + DwarfAddrSection = + Ctx->getCOFFSection(".debug_addr", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); DrectveSection = Ctx->getCOFFSection(".drectve", - COFF::IMAGE_SCN_LNK_INFO, + COFF::IMAGE_SCN_LNK_INFO | + COFF::IMAGE_SCN_LNK_REMOVE, SectionKind::getMetadata()); PDataSection = @@ -690,6 +787,7 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ, SectionKind::getDataRel()); + TLSDataSection = Ctx->getCOFFSection(".tls$", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | @@ -698,7 +796,7 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { SectionKind::getDataRel()); } -void MCObjectFileInfo::InitMCObjectFileInfo(StringRef TT, Reloc::Model relocm, +void MCObjectFileInfo::InitMCObjectFileInfo(StringRef T, Reloc::Model relocm, CodeModel::Model cm, MCContext &ctx) { RelocM = relocm; @@ -708,51 +806,64 @@ void MCObjectFileInfo::InitMCObjectFileInfo(StringRef TT, Reloc::Model relocm, // Common. CommDirectiveSupportsAlignment = true; SupportsWeakOmittedEHFrame = true; - IsFunctionEHFrameSymbolPrivate = true; + SupportsCompactUnwindWithoutEHFrame = false; - PersonalityEncoding = LSDAEncoding = FDEEncoding = FDECFIEncoding = - TTypeEncoding = dwarf::DW_EH_PE_absptr; + PersonalityEncoding = LSDAEncoding = FDECFIEncoding = TTypeEncoding = + dwarf::DW_EH_PE_absptr; CompactUnwindDwarfEHFrameOnly = 0; - EHFrameSection = 0; // Created on demand. - CompactUnwindSection = 0; // Used only by selected targets. - DwarfAccelNamesSection = 0; // Used only by selected targets. - DwarfAccelObjCSection = 0; // Used only by selected targets. - DwarfAccelNamespaceSection = 0; // Used only by selected targets. - DwarfAccelTypesSection = 0; // Used only by selected targets. + EHFrameSection = nullptr; // Created on demand. + CompactUnwindSection = nullptr; // Used only by selected targets. + DwarfAccelNamesSection = nullptr; // Used only by selected targets. + DwarfAccelObjCSection = nullptr; // Used only by selected targets. + DwarfAccelNamespaceSection = nullptr; // Used only by selected targets. + DwarfAccelTypesSection = nullptr; // Used only by selected targets. - Triple T(TT); - Triple::ArchType Arch = T.getArch(); + TT = Triple(T); + + Triple::ArchType Arch = TT.getArch(); // FIXME: Checking for Arch here to filter out bogus triples such as // cellspu-apple-darwin. Perhaps we should fix in Triple? if ((Arch == Triple::x86 || Arch == Triple::x86_64 || Arch == Triple::arm || Arch == Triple::thumb || + Arch == Triple::arm64 || Arch == Triple::aarch64 || Arch == Triple::ppc || Arch == Triple::ppc64 || Arch == Triple::UnknownArch) && - (T.isOSDarwin() || T.getEnvironment() == Triple::MachO)) { + (TT.isOSDarwin() || TT.isOSBinFormatMachO())) { Env = IsMachO; - InitMachOMCObjectFileInfo(T); - } else if ((Arch == Triple::x86 || Arch == Triple::x86_64) && - (T.getEnvironment() != Triple::ELF) && - (T.getOS() == Triple::MinGW32 || T.getOS() == Triple::Cygwin || - T.getOS() == Triple::Win32)) { + InitMachOMCObjectFileInfo(TT); + } else if ((Arch == Triple::x86 || Arch == Triple::x86_64 || + Arch == Triple::arm || Arch == Triple::thumb) && + (TT.isOSWindows() && TT.getObjectFormat() == Triple::COFF)) { Env = IsCOFF; - InitCOFFMCObjectFileInfo(T); + InitCOFFMCObjectFileInfo(TT); } else { Env = IsELF; - InitELFMCObjectFileInfo(T); + InitELFMCObjectFileInfo(TT); } } +const MCSection *MCObjectFileInfo::getDwarfTypesSection(uint64_t Hash) const { + return Ctx->getELFSection(".debug_types", ELF::SHT_PROGBITS, ELF::SHF_GROUP, + SectionKind::getMetadata(), 0, utostr(Hash)); +} + +const MCSection * +MCObjectFileInfo::getDwarfTypesDWOSection(uint64_t Hash) const { + return Ctx->getELFSection(".debug_types.dwo", ELF::SHT_PROGBITS, + ELF::SHF_GROUP, SectionKind::getMetadata(), 0, + utostr(Hash)); +} + void MCObjectFileInfo::InitEHFrameSection() { if (Env == IsMachO) EHFrameSection = Ctx->getMachOSection("__TEXT", "__eh_frame", - MCSectionMachO::S_COALESCED | - MCSectionMachO::S_ATTR_NO_TOC | - MCSectionMachO::S_ATTR_STRIP_STATIC_SYMS | - MCSectionMachO::S_ATTR_LIVE_SUPPORT, + MachO::S_COALESCED | + MachO::S_ATTR_NO_TOC | + MachO::S_ATTR_STRIP_STATIC_SYMS | + MachO::S_ATTR_LIVE_SUPPORT, SectionKind::getReadOnly()); else if (Env == IsELF) EHFrameSection = diff --git a/contrib/llvm/lib/MC/MCObjectStreamer.cpp b/contrib/llvm/lib/MC/MCObjectStreamer.cpp index bc14c2a..a721b59 100644 --- a/contrib/llvm/lib/MC/MCObjectStreamer.cpp +++ b/contrib/llvm/lib/MC/MCObjectStreamer.cpp @@ -17,27 +17,23 @@ #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Support/ErrorHandling.h" using namespace llvm; -MCObjectStreamer::MCObjectStreamer(MCContext &Context, - MCTargetStreamer *TargetStreamer, - MCAsmBackend &TAB, raw_ostream &OS, - MCCodeEmitter *Emitter_) - : MCStreamer(Context, TargetStreamer), +MCObjectStreamer::MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter_) + : MCStreamer(Context), Assembler(new MCAssembler(Context, TAB, *Emitter_, *TAB.createObjectWriter(OS), OS)), - CurSectionData(0) {} + CurSectionData(nullptr), EmitEHFrame(true), EmitDebugFrame(false) {} -MCObjectStreamer::MCObjectStreamer(MCContext &Context, - MCTargetStreamer *TargetStreamer, - MCAsmBackend &TAB, raw_ostream &OS, - MCCodeEmitter *Emitter_, +MCObjectStreamer::MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter_, MCAssembler *_Assembler) - : MCStreamer(Context, TargetStreamer), Assembler(_Assembler), - CurSectionData(0) {} + : MCStreamer(Context), Assembler(_Assembler), CurSectionData(nullptr), + EmitEHFrame(true), EmitDebugFrame(false) {} MCObjectStreamer::~MCObjectStreamer() { delete &Assembler->getBackend(); @@ -49,18 +45,31 @@ MCObjectStreamer::~MCObjectStreamer() { void MCObjectStreamer::reset() { if (Assembler) Assembler->reset(); - CurSectionData = 0; + CurSectionData = nullptr; CurInsertionPoint = MCSectionData::iterator(); + EmitEHFrame = true; + EmitDebugFrame = false; MCStreamer::reset(); } +void MCObjectStreamer::EmitFrames(MCAsmBackend *MAB) { + if (!getNumFrameInfos()) + return; + + if (EmitEHFrame) + MCDwarfFrameEmitter::Emit(*this, MAB, true); + + if (EmitDebugFrame) + MCDwarfFrameEmitter::Emit(*this, MAB, false); +} + MCFragment *MCObjectStreamer::getCurrentFragment() const { assert(getCurrentSectionData() && "No current section!"); if (CurInsertionPoint != getCurrentSectionData()->getFragmentList().begin()) - return prior(CurInsertionPoint); + return std::prev(CurInsertionPoint); - return 0; + return nullptr; } MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() const { @@ -74,57 +83,44 @@ MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() const { return F; } -const MCExpr *MCObjectStreamer::AddValueSymbols(const MCExpr *Value) { - switch (Value->getKind()) { - case MCExpr::Target: - cast<MCTargetExpr>(Value)->AddValueSymbols(Assembler); - break; - - case MCExpr::Constant: - break; - - case MCExpr::Binary: { - const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value); - AddValueSymbols(BE->getLHS()); - AddValueSymbols(BE->getRHS()); - break; - } - - case MCExpr::SymbolRef: - Assembler->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol()); - break; - - case MCExpr::Unary: - AddValueSymbols(cast<MCUnaryExpr>(Value)->getSubExpr()); - break; - } +void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) { + Assembler->getOrCreateSymbolData(Sym); +} - return Value; +void MCObjectStreamer::EmitCFISections(bool EH, bool Debug) { + MCStreamer::EmitCFISections(EH, Debug); + EmitEHFrame = EH; + EmitDebugFrame = Debug; } -void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size) { +void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, + const SMLoc &Loc) { + MCStreamer::EmitValueImpl(Value, Size, Loc); MCDataFragment *DF = getOrCreateDataFragment(); MCLineEntry::Make(this, getCurrentSection().first); // Avoid fixups when possible. int64_t AbsValue; - if (AddValueSymbols(Value)->EvaluateAsAbsolute(AbsValue, getAssembler())) { + if (Value->EvaluateAsAbsolute(AbsValue, getAssembler())) { EmitIntValue(AbsValue, Size); return; } DF->getFixups().push_back( MCFixup::Create(DF->getContents().size(), Value, - MCFixup::getKindForSize(Size, false))); + MCFixup::getKindForSize(Size, false), Loc)); DF->getContents().resize(DF->getContents().size() + Size, 0); } void MCObjectStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { - RecordProcStart(Frame); + // We need to create a local symbol to avoid relocations. + Frame.Begin = getContext().CreateTempSymbol(); + EmitLabel(Frame.Begin); } void MCObjectStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { - RecordProcEnd(Frame); + Frame.End = getContext().CreateTempSymbol(); + EmitLabel(Frame.End); } void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) { @@ -142,10 +138,6 @@ void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) { SD.setOffset(F->getContents().size()); } -void MCObjectStreamer::EmitDebugLabel(MCSymbol *Symbol) { - EmitLabel(Symbol); -} - void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) { int64_t IntValue; if (Value->EvaluateAsAbsolute(IntValue, getAssembler())) { @@ -189,14 +181,12 @@ void MCObjectStreamer::ChangeSection(const MCSection *Section, void MCObjectStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { getAssembler().getOrCreateSymbolData(*Symbol); - Symbol->setVariableValue(AddValueSymbols(Value)); + MCStreamer::EmitAssignment(Symbol, Value); } -void MCObjectStreamer::EmitInstruction(const MCInst &Inst) { - // Scan for values. - for (unsigned i = Inst.getNumOperands(); i--; ) - if (Inst.getOperand(i).isExpr()) - AddValueSymbols(Inst.getOperand(i).getExpr()); +void MCObjectStreamer::EmitInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI) { + MCStreamer::EmitInstruction(Inst, STI); MCSectionData *SD = getCurrentSectionData(); SD->setHasInstructions(true); @@ -208,7 +198,7 @@ void MCObjectStreamer::EmitInstruction(const MCInst &Inst) { // If this instruction doesn't need relaxation, just emit it as data. MCAssembler &Assembler = getAssembler(); if (!Assembler.getBackend().mayNeedRelaxation(Inst)) { - EmitInstToData(Inst); + EmitInstToData(Inst, STI); return; } @@ -223,23 +213,25 @@ void MCObjectStreamer::EmitInstruction(const MCInst &Inst) { getAssembler().getBackend().relaxInstruction(Inst, Relaxed); while (getAssembler().getBackend().mayNeedRelaxation(Relaxed)) getAssembler().getBackend().relaxInstruction(Relaxed, Relaxed); - EmitInstToData(Relaxed); + EmitInstToData(Relaxed, STI); return; } // Otherwise emit to a separate fragment. - EmitInstToFragment(Inst); + EmitInstToFragment(Inst, STI); } -void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst) { +void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst, + const MCSubtargetInfo &STI) { // Always create a new, separate fragment here, because its size can change // during relaxation. - MCRelaxableFragment *IF = new MCRelaxableFragment(Inst); + MCRelaxableFragment *IF = new MCRelaxableFragment(Inst, STI); insert(IF); SmallString<128> Code; raw_svector_ostream VecOS(Code); - getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, IF->getFixups()); + getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, IF->getFixups(), + STI); VecOS.flush(); IF->getContents().append(Code.begin(), Code.end()); } @@ -380,14 +372,12 @@ void MCObjectStreamer::EmitZeros(uint64_t NumBytes) { } void MCObjectStreamer::FinishImpl() { - // Dump out the dwarf file & directory tables and line tables. - const MCSymbol *LineSectionSymbol = NULL; - if (getContext().hasDwarfFiles()) - LineSectionSymbol = MCDwarfFileTable::Emit(this); - // If we are generating dwarf for assembly source files dump out the sections. if (getContext().getGenDwarfForAssembly()) - MCGenDwarfInfo::Emit(this, LineSectionSymbol); + MCGenDwarfInfo::Emit(this); + + // Dump out the dwarf file & directory tables and line tables. + MCDwarfLineTable::Emit(this); getAssembler().Finish(); } diff --git a/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp b/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp index b49dd01..145ad4a 100644 --- a/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp +++ b/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp @@ -22,23 +22,23 @@ using namespace llvm; AsmLexer::AsmLexer(const MCAsmInfo &_MAI) : MAI(_MAI) { - CurBuf = NULL; - CurPtr = NULL; + CurPtr = nullptr; isAtStartOfLine = true; + AllowAtInIdentifier = !StringRef(MAI.getCommentString()).startswith("@"); } AsmLexer::~AsmLexer() { } -void AsmLexer::setBuffer(const MemoryBuffer *buf, const char *ptr) { - CurBuf = buf; +void AsmLexer::setBuffer(StringRef Buf, const char *ptr) { + CurBuf = Buf; if (ptr) CurPtr = ptr; else - CurPtr = CurBuf->getBufferStart(); + CurPtr = CurBuf.begin(); - TokStart = 0; + TokStart = nullptr; } /// ReturnError - Set the error to the specified string at the specified @@ -57,7 +57,7 @@ int AsmLexer::getNextChar() { 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->getBufferEnd()) + if (CurPtr - 1 != CurBuf.end()) return 0; // Just whitespace. // Otherwise, return end of file. @@ -139,8 +139,9 @@ AsmToken AsmLexer::LexHexFloatLiteral(bool NoIntDigits) { } /// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@?]* -static bool IsIdentifierChar(char c) { - return isalnum(c) || c == '_' || c == '$' || c == '.' || c == '@' || c == '?'; +static bool IsIdentifierChar(char c, bool AllowAt) { + return isalnum(c) || c == '_' || c == '$' || c == '.' || + (c == '@' && AllowAt) || c == '?'; } AsmToken AsmLexer::LexIdentifier() { // Check for floating point literals. @@ -148,11 +149,12 @@ AsmToken AsmLexer::LexIdentifier() { // Disambiguate a .1243foo identifier from a floating literal. while (isdigit(*CurPtr)) ++CurPtr; - if (*CurPtr == 'e' || *CurPtr == 'E' || !IsIdentifierChar(*CurPtr)) + if (*CurPtr == 'e' || *CurPtr == 'E' || + !IsIdentifierChar(*CurPtr, AllowAtInIdentifier)) return LexFloatLiteral(); } - while (IsIdentifierChar(*CurPtr)) + while (IsIdentifierChar(*CurPtr, AllowAtInIdentifier)) ++CurPtr; // Handle . as a special case. @@ -198,8 +200,8 @@ AsmToken AsmLexer::LexLineComment() { CurChar = getNextChar(); if (CurChar == EOF) - return AsmToken(AsmToken::Eof, StringRef(CurPtr, 0)); - return AsmToken(AsmToken::EndOfStatement, StringRef(CurPtr, 0)); + return AsmToken(AsmToken::Eof, StringRef(TokStart, 0)); + return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 0)); } static void SkipIgnoredIntegerSuffix(const char *&CurPtr) { @@ -215,7 +217,7 @@ static void SkipIgnoredIntegerSuffix(const char *&CurPtr) { // Look ahead to search for first non-hex digit, if it's [hH], then we treat the // integer as a hexadecimal, possibly with leading zeroes. static unsigned doLookAhead(const char *&CurPtr, unsigned DefaultRadix) { - const char *FirstHex = 0; + const char *FirstHex = nullptr; const char *LookAhead = CurPtr; while (1) { if (isdigit(*LookAhead)) { @@ -235,6 +237,13 @@ static unsigned doLookAhead(const char *&CurPtr, unsigned DefaultRadix) { return DefaultRadix; } +static AsmToken intToken(StringRef Ref, APInt &Value) +{ + if (Value.isIntN(64)) + return AsmToken(AsmToken::Integer, Ref, Value); + return AsmToken(AsmToken::BigNum, Ref, Value); +} + /// LexDigit: First character is [0-9]. /// Local Label: [0-9][:] /// Forward/Backward Label: [0-9][fb] @@ -255,16 +264,10 @@ AsmToken AsmLexer::LexDigit() { StringRef Result(TokStart, CurPtr - TokStart); - long long Value; - if (Result.getAsInteger(Radix, Value)) { - // Allow positive values that are too large to fit into a signed 64-bit - // integer, but that do fit in an unsigned one, we just convert them over. - unsigned long long UValue; - if (Result.getAsInteger(Radix, UValue)) - return ReturnError(TokStart, !isHex ? "invalid decimal number" : + APInt Value(128, 0, true); + if (Result.getAsInteger(Radix, Value)) + return ReturnError(TokStart, !isHex ? "invalid decimal number" : "invalid hexdecimal number"); - Value = (long long)UValue; - } // Consume the [bB][hH]. if (Radix == 2 || Radix == 16) @@ -274,7 +277,7 @@ AsmToken AsmLexer::LexDigit() { // suffices on integer literals. SkipIgnoredIntegerSuffix(CurPtr); - return AsmToken(AsmToken::Integer, Result, Value); + return intToken(Result, Value); } if (*CurPtr == 'b') { @@ -295,7 +298,7 @@ AsmToken AsmLexer::LexDigit() { StringRef Result(TokStart, CurPtr - TokStart); - long long Value; + APInt Value(128, 0, true); if (Result.substr(2).getAsInteger(2, Value)) return ReturnError(TokStart, "invalid binary number"); @@ -303,7 +306,7 @@ AsmToken AsmLexer::LexDigit() { // suffixes on integer literals. SkipIgnoredIntegerSuffix(CurPtr); - return AsmToken(AsmToken::Integer, Result, Value); + return intToken(Result, Value); } if (*CurPtr == 'x') { @@ -321,7 +324,7 @@ AsmToken AsmLexer::LexDigit() { if (CurPtr == NumStart) return ReturnError(CurPtr-2, "invalid hexadecimal number"); - unsigned long long Result; + APInt Result(128, 0); if (StringRef(TokStart, CurPtr - TokStart).getAsInteger(0, Result)) return ReturnError(TokStart, "invalid hexadecimal number"); @@ -333,12 +336,11 @@ AsmToken AsmLexer::LexDigit() { // suffixes on integer literals. SkipIgnoredIntegerSuffix(CurPtr); - return AsmToken(AsmToken::Integer, StringRef(TokStart, CurPtr - TokStart), - (int64_t)Result); + return intToken(StringRef(TokStart, CurPtr - TokStart), Result); } // Either octal or hexadecimal. - long long Value; + APInt Value(128, 0, true); unsigned Radix = doLookAhead(CurPtr, 8); bool isHex = Radix == 16; StringRef Result(TokStart, CurPtr - TokStart); @@ -354,7 +356,7 @@ AsmToken AsmLexer::LexDigit() { // suffixes on integer literals. SkipIgnoredIntegerSuffix(CurPtr); - return AsmToken(AsmToken::Integer, Result, Value); + return intToken(Result, Value); } /// LexSingleQuote: Integer: 'b' @@ -417,9 +419,8 @@ StringRef AsmLexer::LexUntilEndOfStatement() { while (!isAtStartOfComment(*CurPtr) && // Start of line comment. !isAtStatementSeparator(CurPtr) && // End of statement marker. - *CurPtr != '\n' && - *CurPtr != '\r' && - (*CurPtr != 0 || CurPtr != CurBuf->getBufferEnd())) { + *CurPtr != '\n' && *CurPtr != '\r' && + (*CurPtr != 0 || CurPtr != CurBuf.end())) { ++CurPtr; } return StringRef(TokStart, CurPtr-TokStart); @@ -428,14 +429,35 @@ StringRef AsmLexer::LexUntilEndOfStatement() { StringRef AsmLexer::LexUntilEndOfLine() { TokStart = CurPtr; - while (*CurPtr != '\n' && - *CurPtr != '\r' && - (*CurPtr != 0 || CurPtr != CurBuf->getBufferEnd())) { + while (*CurPtr != '\n' && *CurPtr != '\r' && + (*CurPtr != 0 || CurPtr != CurBuf.end())) { ++CurPtr; } return StringRef(TokStart, CurPtr-TokStart); } +const AsmToken AsmLexer::peekTok(bool ShouldSkipSpace) { + const char *SavedTokStart = TokStart; + const char *SavedCurPtr = CurPtr; + bool SavedAtStartOfLine = isAtStartOfLine; + bool SavedSkipSpace = SkipSpace; + + std::string SavedErr = getErr(); + SMLoc SavedErrLoc = getErrLoc(); + + SkipSpace = ShouldSkipSpace; + AsmToken Token = LexToken(); + + SetError(SavedErrLoc, SavedErr); + + SkipSpace = SavedSkipSpace; + isAtStartOfLine = SavedAtStartOfLine; + CurPtr = SavedCurPtr; + TokStart = SavedTokStart; + + return Token; +} + bool AsmLexer::isAtStartOfComment(char Char) { // FIXME: This won't work for multi-character comment indicators like "//". return Char == *MAI.getCommentString(); diff --git a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp index 7f8e9df..ed1d704 100644 --- a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/APFloat.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAsmInfo.h" @@ -22,6 +22,7 @@ #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCParser/AsmCond.h" #include "llvm/MC/MCParser/AsmLexer.h" #include "llvm/MC/MCParser/MCAsmParser.h" @@ -38,6 +39,7 @@ #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" #include <cctype> +#include <deque> #include <set> #include <string> #include <vector> @@ -50,11 +52,19 @@ FatalAssemblerWarnings("fatal-assembler-warnings", MCAsmParserSemaCallback::~MCAsmParserSemaCallback() {} namespace { - /// \brief Helper types for tracking macro definitions. typedef std::vector<AsmToken> MCAsmMacroArgument; typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments; -typedef std::pair<StringRef, MCAsmMacroArgument> MCAsmMacroParameter; + +struct MCAsmMacroParameter { + StringRef Name; + MCAsmMacroArgument Value; + bool Required; + bool Vararg; + + MCAsmMacroParameter() : Required(false), Vararg(false) {} +}; + typedef std::vector<MCAsmMacroParameter> MCAsmMacroParameters; struct MCAsmMacro { @@ -63,11 +73,8 @@ struct MCAsmMacro { MCAsmMacroParameters Parameters; public: - MCAsmMacro(StringRef N, StringRef B, const MCAsmMacroParameters &P) : + MCAsmMacro(StringRef N, StringRef B, ArrayRef<MCAsmMacroParameter> P) : Name(N), Body(B), Parameters(P) {} - - MCAsmMacro(const MCAsmMacro& Other) - : Name(Other.Name), Body(Other.Body), Parameters(Other.Parameters) {} }; /// \brief Helper class for storing information about an active macro @@ -95,7 +102,7 @@ public: struct ParseStatementInfo { /// \brief The parsed operands from the last parsed statement. - SmallVector<MCParsedAsmOperand*, 8> ParsedOperands; + SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands; /// \brief The opcode from the last parsed instruction. unsigned Opcode; @@ -105,16 +112,9 @@ struct ParseStatementInfo { SmallVectorImpl<AsmRewrite> *AsmRewrites; - ParseStatementInfo() : Opcode(~0U), ParseError(false), AsmRewrites(0) {} + ParseStatementInfo() : Opcode(~0U), ParseError(false), AsmRewrites(nullptr) {} ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites) : Opcode(~0), ParseError(false), AsmRewrites(rewrites) {} - - ~ParseStatementInfo() { - // Free any parsed operands. - for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i) - delete ParsedOperands[i]; - ParsedOperands.clear(); - } }; /// \brief The concrete assembly parser instance. @@ -133,7 +133,7 @@ private: /// This is the current buffer index we're lexing from as managed by the /// SourceMgr object. - int CurBuffer; + unsigned CurBuffer; AsmCond TheCondState; std::vector<AsmCond> TheCondStack; @@ -162,13 +162,13 @@ private: StringRef CppHashFilename; int64_t CppHashLineNumber; SMLoc CppHashLoc; - int CppHashBuf; + unsigned CppHashBuf; /// 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 /// cache we save the last info we queried with SrcMgr.FindLineNumber(). SMLoc LastQueryIDLoc; - int LastQueryBuffer; + unsigned LastQueryBuffer; unsigned LastQueryLine; /// AssemblerDialect. ~OU means unset value and use value provided by MAI. @@ -185,10 +185,10 @@ public: const MCAsmInfo &MAI); virtual ~AsmParser(); - virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false); + bool Run(bool NoInitialTextSection, bool NoFinalize = false) override; - virtual void addDirectiveHandler(StringRef Directive, - ExtensionDirectiveHandler Handler) { + void addDirectiveHandler(StringRef Directive, + ExtensionDirectiveHandler Handler) override { ExtensionDirectiveMap[Directive] = Handler; } @@ -196,51 +196,52 @@ public: /// @name MCAsmParser Interface /// { - virtual SourceMgr &getSourceManager() { return SrcMgr; } - virtual MCAsmLexer &getLexer() { return Lexer; } - virtual MCContext &getContext() { return Ctx; } - virtual MCStreamer &getStreamer() { return Out; } - virtual unsigned getAssemblerDialect() { + SourceMgr &getSourceManager() override { return SrcMgr; } + MCAsmLexer &getLexer() override { return Lexer; } + MCContext &getContext() override { return Ctx; } + MCStreamer &getStreamer() override { return Out; } + unsigned getAssemblerDialect() override { if (AssemblerDialect == ~0U) return MAI.getAssemblerDialect(); else return AssemblerDialect; } - virtual void setAssemblerDialect(unsigned i) { + void setAssemblerDialect(unsigned i) override { AssemblerDialect = i; } - virtual bool Warning(SMLoc L, const Twine &Msg, - ArrayRef<SMRange> Ranges = None); - virtual bool Error(SMLoc L, const Twine &Msg, - ArrayRef<SMRange> Ranges = None); + void Note(SMLoc L, const Twine &Msg, + ArrayRef<SMRange> Ranges = None) override; + bool Warning(SMLoc L, const Twine &Msg, + ArrayRef<SMRange> Ranges = None) override; + bool Error(SMLoc L, const Twine &Msg, + ArrayRef<SMRange> Ranges = None) override; - virtual const AsmToken &Lex(); + const AsmToken &Lex() override; - void setParsingInlineAsm(bool V) { ParsingInlineAsm = V; } - bool isParsingInlineAsm() { return ParsingInlineAsm; } + void setParsingInlineAsm(bool V) override { ParsingInlineAsm = V; } + bool isParsingInlineAsm() override { return ParsingInlineAsm; } bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, SmallVectorImpl<std::pair<void *,bool> > &OpDecls, SmallVectorImpl<std::string> &Constraints, SmallVectorImpl<std::string> &Clobbers, - const MCInstrInfo *MII, - const MCInstPrinter *IP, - MCAsmParserSemaCallback &SI); + const MCInstrInfo *MII, const MCInstPrinter *IP, + MCAsmParserSemaCallback &SI) override; bool parseExpression(const MCExpr *&Res); - virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc); - virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc); - virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc); - virtual bool parseAbsoluteExpression(int64_t &Res); + bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override; + bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override; + bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override; + bool parseAbsoluteExpression(int64_t &Res) override; /// \brief Parse an identifier or string (as a quoted identifier) /// and set \p Res to the identifier contents. - virtual bool parseIdentifier(StringRef &Res); - virtual void eatToEndOfStatement(); + bool parseIdentifier(StringRef &Res) override; + void eatToEndOfStatement() override; - virtual void checkForValidSection(); + void checkForValidSection() override; /// } private: @@ -250,10 +251,10 @@ private: bool parseCppHashLineFilenameComment(const SMLoc &L); void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body, - MCAsmMacroParameters Parameters); + ArrayRef<MCAsmMacroParameter> Parameters); bool expandMacro(raw_svector_ostream &OS, StringRef Body, - const MCAsmMacroParameters &Parameters, - const MCAsmMacroArguments &A, + ArrayRef<MCAsmMacroParameter> Parameters, + ArrayRef<MCAsmMacroArgument> A, const SMLoc &L); /// \brief Are macros enabled in the parser? @@ -285,11 +286,8 @@ private: /// \brief Handle exit from macro instantiation. void handleMacroExit(); - /// \brief Extract AsmTokens for a macro argument. If the argument delimiter - /// is initially unknown, set it to AsmToken::Eof. It will be set to the - /// correct delimiter by the method. - bool parseMacroArgument(MCAsmMacroArgument &MA, - AsmToken::TokenKind &ArgumentDelimiter); + /// \brief Extract AsmTokens for a macro argument. + bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg); /// \brief Parse all macro arguments for a given macro. bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A); @@ -312,14 +310,14 @@ private: /// current token is not set; clients should ensure Lex() is called /// subsequently. /// - /// \param InBuffer If not -1, should be the known buffer id that contains the + /// \param InBuffer If not 0, should be the known buffer id that contains the /// location. - void jumpToLoc(SMLoc Loc, int InBuffer=-1); + void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0); /// \brief Parse up to the end of statement and a return the contents from the /// current token until the end of the statement; the current token on exit /// will be either the EndOfStatement or EOF. - virtual StringRef parseStringToEndOfStatement(); + StringRef parseStringToEndOfStatement() override; /// \brief Parse until the end of a statement or a comma is encountered, /// return the contents from the current token up to the end or comma. @@ -338,8 +336,8 @@ private: enum DirectiveKind { DK_NO_DIRECTIVE, // Placeholder DK_SET, DK_EQU, DK_EQUIV, DK_ASCII, DK_ASCIZ, DK_STRING, DK_BYTE, DK_SHORT, - DK_VALUE, DK_2BYTE, DK_LONG, DK_INT, DK_4BYTE, DK_QUAD, DK_8BYTE, DK_SINGLE, - DK_FLOAT, DK_DOUBLE, DK_ALIGN, DK_ALIGN32, DK_BALIGN, DK_BALIGNW, + DK_VALUE, DK_2BYTE, DK_LONG, DK_INT, DK_4BYTE, DK_QUAD, DK_8BYTE, DK_OCTA, + DK_SINGLE, DK_FLOAT, DK_DOUBLE, DK_ALIGN, DK_ALIGN32, DK_BALIGN, DK_BALIGNW, DK_BALIGNL, DK_P2ALIGN, DK_P2ALIGNW, DK_P2ALIGNL, DK_ORG, DK_FILL, DK_ENDR, DK_BUNDLE_ALIGN_MODE, DK_BUNDLE_LOCK, DK_BUNDLE_UNLOCK, DK_ZERO, DK_EXTERN, DK_GLOBL, DK_GLOBAL, @@ -347,7 +345,8 @@ private: 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_IFB, DK_IFNB, DK_IFC, DK_IFNC, DK_IFDEF, DK_IFNDEF, DK_IFNOTDEF, + 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_IFDEF, DK_IFNDEF, DK_IFNOTDEF, DK_ELSEIF, DK_ELSE, DK_ENDIF, DK_SPACE, DK_SKIP, DK_FILE, DK_LINE, DK_LOC, DK_STABS, DK_CFI_SECTIONS, DK_CFI_STARTPROC, DK_CFI_ENDPROC, DK_CFI_DEF_CFA, @@ -357,7 +356,9 @@ private: DK_CFI_RESTORE, DK_CFI_ESCAPE, DK_CFI_SIGNAL_FRAME, DK_CFI_UNDEFINED, DK_CFI_REGISTER, DK_CFI_WINDOW_SAVE, DK_MACROS_ON, DK_MACROS_OFF, DK_MACRO, DK_ENDM, DK_ENDMACRO, DK_PURGEM, - DK_SLEB128, DK_ULEB128 + DK_SLEB128, DK_ULEB128, + DK_ERR, DK_ERROR, + DK_END }; /// \brief Maps directive name --> DirectiveKind enum, for @@ -367,6 +368,7 @@ private: // ".ascii", ".asciz", ".string" bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated); bool parseDirectiveValue(unsigned Size); // ".byte", ".long", ... + bool parseDirectiveOctaValue(); // ".octa" bool parseDirectiveRealValue(const fltSemantics &); // ".single", ... bool parseDirectiveFill(); // ".fill" bool parseDirectiveZero(); // ".zero" @@ -432,17 +434,20 @@ private: bool parseDirectiveInclude(); // ".include" bool parseDirectiveIncbin(); // ".incbin" - bool parseDirectiveIf(SMLoc DirectiveLoc); // ".if" + // ".if", ".ifeq", ".ifge", ".ifgt" , ".ifle", ".iflt" or ".ifne" + bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind); // ".ifb" or ".ifnb", depending on ExpectBlank. bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank); // ".ifc" or ".ifnc", depending on ExpectEqual. bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual); + // ".ifeqs" + bool parseDirectiveIfeqs(SMLoc DirectiveLoc); // ".ifdef" or ".ifndef", depending on expect_defined bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined); bool parseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif" bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else" bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif - virtual bool parseEscapedString(std::string &Data); + bool parseEscapedString(std::string &Data) override; const MCExpr *applyModifierToExpr(const MCExpr *E, MCSymbolRefExpr::VariantKind Variant); @@ -451,7 +456,7 @@ private: MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc); void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, raw_svector_ostream &OS); - bool parseDirectiveRept(SMLoc DirectiveLoc); // ".rept" + bool parseDirectiveRept(SMLoc DirectiveLoc, StringRef Directive); bool parseDirectiveIrp(SMLoc DirectiveLoc); // ".irp" bool parseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc" bool parseDirectiveEndr(SMLoc DirectiveLoc); // ".endr" @@ -463,6 +468,12 @@ private: // "align" bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info); + // "end" + bool parseDirectiveEnd(SMLoc DirectiveLoc); + + // ".err" or ".error" + bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage); + void initializeDirectiveKindMap(); }; } @@ -480,37 +491,39 @@ enum { DEFAULT_ADDRSPACE = 0 }; AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out, const MCAsmInfo &_MAI) : Lexer(_MAI), Ctx(_Ctx), Out(_Out), MAI(_MAI), SrcMgr(_SM), - PlatformParser(0), CurBuffer(0), MacrosEnabledFlag(true), - CppHashLineNumber(0), AssemblerDialect(~0U), IsDarwin(false), - ParsingInlineAsm(false) { + PlatformParser(nullptr), CurBuffer(_SM.getMainFileID()), + MacrosEnabledFlag(true), HadError(false), CppHashLineNumber(0), + AssemblerDialect(~0U), IsDarwin(false), ParsingInlineAsm(false) { // Save the old handler. SavedDiagHandler = SrcMgr.getDiagHandler(); SavedDiagContext = SrcMgr.getDiagContext(); // Set our own handler which calls the saved handler. SrcMgr.setDiagHandler(DiagHandler, this); - Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); // Initialize the platform / file format parser. - // - // FIXME: This is a hack, we need to (majorly) cleanup how these objects are - // created. - if (_MAI.hasMicrosoftFastStdCallMangling()) { - PlatformParser = createCOFFAsmParser(); - PlatformParser->Initialize(*this); - } else if (_MAI.hasSubsectionsViaSymbols()) { - PlatformParser = createDarwinAsmParser(); - PlatformParser->Initialize(*this); - IsDarwin = true; - } else { - PlatformParser = createELFAsmParser(); - PlatformParser->Initialize(*this); + switch (_Ctx.getObjectFileInfo()->getObjectFileType()) { + case MCObjectFileInfo::IsCOFF: + PlatformParser = createCOFFAsmParser(); + PlatformParser->Initialize(*this); + break; + case MCObjectFileInfo::IsMachO: + PlatformParser = createDarwinAsmParser(); + PlatformParser->Initialize(*this); + IsDarwin = true; + break; + case MCObjectFileInfo::IsELF: + PlatformParser = createELFAsmParser(); + PlatformParser->Initialize(*this); + break; } initializeDirectiveKindMap(); } AsmParser::~AsmParser() { - assert(ActiveMacros.empty() && "Unexpected active macro instantiation!"); + assert((HadError || ActiveMacros.empty()) && + "Unexpected active macro instantiation!"); // Destroy any macros. for (StringMap<MCAsmMacro *>::iterator it = MacroMap.begin(), @@ -531,6 +544,11 @@ void AsmParser::printMacroInstantiations() { "while in macro instantiation"); } +void AsmParser::Note(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) { + printMessage(L, SourceMgr::DK_Note, Msg, Ranges); + printMacroInstantiations(); +} + bool AsmParser::Warning(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) { if (FatalAssemblerWarnings) return Error(L, Msg, Ranges); @@ -548,14 +566,13 @@ bool AsmParser::Error(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) { bool AsmParser::enterIncludeFile(const std::string &Filename) { std::string IncludedFile; - int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); - if (NewBuf == -1) + unsigned NewBuf = + SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); + if (!NewBuf) return true; CurBuffer = NewBuf; - - Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); - + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); return false; } @@ -564,8 +581,9 @@ bool AsmParser::enterIncludeFile(const std::string &Filename) { /// returns true on failure. bool AsmParser::processIncbinFile(const std::string &Filename) { std::string IncludedFile; - int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); - if (NewBuf == -1) + unsigned NewBuf = + SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); + if (!NewBuf) return true; // Pick up the bytes from the file and emit them. @@ -573,13 +591,10 @@ bool AsmParser::processIncbinFile(const std::string &Filename) { return false; } -void AsmParser::jumpToLoc(SMLoc Loc, int InBuffer) { - if (InBuffer != -1) { - CurBuffer = InBuffer; - } else { - CurBuffer = SrcMgr.FindBufferContainingLoc(Loc); - } - Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer), Loc.getPointer()); +void AsmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) { + CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc); + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), + Loc.getPointer()); } const AsmToken &AsmParser::Lex() { @@ -615,13 +630,14 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // If we are generating dwarf for assembly source files save the initial text // section and generate a .file directive. if (getContext().getGenDwarfForAssembly()) { - getContext().setGenDwarfSection(getStreamer().getCurrentSection().first); MCSymbol *SectionStartSym = getContext().CreateTempSymbol(); getStreamer().EmitLabel(SectionStartSym); - getContext().setGenDwarfSectionStartSym(SectionStartSym); - getStreamer().EmitDwarfFileDirective(getContext().nextGenDwarfFileNumber(), - StringRef(), - getContext().getMainFileName()); + auto InsertResult = getContext().addGenDwarfSection( + getStreamer().getCurrentSection().first); + assert(InsertResult.second && ".text section should not have debug info yet"); + InsertResult.first->second.first = SectionStartSym; + getContext().setGenDwarfFileNumber(getStreamer().EmitDwarfFileDirective( + 0, StringRef(), getContext().getMainFileName())); } // While we have input, parse each statement. @@ -641,11 +657,15 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { return TokError("unmatched .ifs or .elses"); // Check to see there are no empty DwarfFile slots. - const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles = - getContext().getMCDwarfFiles(); - for (unsigned i = 1; i < MCDwarfFiles.size(); i++) { - if (!MCDwarfFiles[i]) - TokError("unassigned file number: " + Twine(i) + " for .file directives"); + const auto &LineTables = getContext().getMCDwarfLineTables(); + if (!LineTables.empty()) { + unsigned Index = 0; + for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) { + if (File.Name.empty() && Index != 0) + TokError("unassigned file number: " + Twine(Index) + + " for .file directives"); + ++Index; + } } // Check to see that all assembler local symbols were actually defined. @@ -682,7 +702,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { void AsmParser::checkForValidSection() { if (!ParsingInlineAsm && !getStreamer().getCurrentSection().first) { TokError("expected section directive before assembly directive"); - Out.InitToTextSection(); + Out.InitSections(); } } @@ -784,29 +804,54 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { getContext()); EndLoc = FirstTokenLoc; return false; - } else - return Error(FirstTokenLoc, "invalid token in expression"); - return true; + } + return Error(FirstTokenLoc, "invalid token in expression"); } } + // Parse symbol variant + std::pair<StringRef, StringRef> Split; + if (!MAI.useParensForSymbolVariant()) { + if (FirstTokenKind == AsmToken::String) { + if (Lexer.is(AsmToken::At)) { + Lexer.Lex(); // eat @ + SMLoc AtLoc = getLexer().getLoc(); + StringRef VName; + if (parseIdentifier(VName)) + return Error(AtLoc, "expected symbol variant after '@'"); + + Split = std::make_pair(Identifier, VName); + } + } else { + Split = Identifier.split('@'); + } + } else if (Lexer.is(AsmToken::LParen)) { + Lexer.Lex(); // eat ( + StringRef VName; + parseIdentifier(VName); + if (Lexer.isNot(AsmToken::RParen)) { + return Error(Lexer.getTok().getLoc(), + "unexpected token in variant, expected ')'"); + } + Lexer.Lex(); // eat ) + Split = std::make_pair(Identifier, VName); + } EndLoc = SMLoc::getFromPointer(Identifier.end()); // This is a symbol reference. StringRef SymbolName = Identifier; MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; - std::pair<StringRef, StringRef> Split = Identifier.split('@'); // Lookup the symbol variant if used. - if (Split.first.size() != Identifier.size()) { + if (Split.second.size()) { Variant = MCSymbolRefExpr::getVariantKindForName(Split.second); if (Variant != MCSymbolRefExpr::VK_Invalid) { SymbolName = Split.first; - } else if (MAI.doesAllowAtInName()) { + } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) { Variant = MCSymbolRefExpr::VK_None; } else { - Variant = MCSymbolRefExpr::VK_None; - return TokError("invalid variant '" + Split.second + "'"); + return Error(SMLoc::getFromPointer(Split.second.begin()), + "invalid variant '" + Split.second + "'"); } } @@ -826,6 +871,8 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { Res = MCSymbolRefExpr::Create(Sym, Variant, getContext()); return false; } + case AsmToken::BigNum: + return TokError("literal value out of range for directive"); case AsmToken::Integer: { SMLoc Loc = getTok().getLoc(); int64_t IntVal = getTok().getIntVal(); @@ -840,15 +887,13 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; if (Split.first.size() != IDVal.size()) { Variant = MCSymbolRefExpr::getVariantKindForName(Split.second); - if (Variant == MCSymbolRefExpr::VK_Invalid) { - Variant = MCSymbolRefExpr::VK_None; + if (Variant == MCSymbolRefExpr::VK_Invalid) return TokError("invalid variant '" + Split.second + "'"); - } IDVal = Split.first; } if (IDVal == "f" || IDVal == "b") { MCSymbol *Sym = - Ctx.GetDirectionalLocalSymbol(IntVal, IDVal == "f" ? 1 : 0); + Ctx.GetDirectionalLocalSymbol(IntVal, IDVal == "b"); Res = MCSymbolRefExpr::Create(Sym, Variant, getContext()); if (IDVal == "b" && Sym->isUndefined()) return Error(Loc, "invalid reference to undefined symbol"); @@ -922,7 +967,7 @@ AsmParser::applyModifierToExpr(const MCExpr *E, switch (E->getKind()) { case MCExpr::Target: case MCExpr::Constant: - return 0; + return nullptr; case MCExpr::SymbolRef: { const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E); @@ -940,7 +985,7 @@ AsmParser::applyModifierToExpr(const MCExpr *E, const MCUnaryExpr *UE = cast<MCUnaryExpr>(E); const MCExpr *Sub = applyModifierToExpr(UE->getSubExpr(), Variant); if (!Sub) - return 0; + return nullptr; return MCUnaryExpr::Create(UE->getOpcode(), Sub, getContext()); } @@ -950,7 +995,7 @@ AsmParser::applyModifierToExpr(const MCExpr *E, const MCExpr *RHS = applyModifierToExpr(BE->getRHS(), Variant); if (!LHS && !RHS) - return 0; + return nullptr; if (!LHS) LHS = BE->getLHS(); @@ -976,7 +1021,7 @@ AsmParser::applyModifierToExpr(const MCExpr *E, /// bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) { // Parse the expression. - Res = 0; + Res = nullptr; if (parsePrimaryExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc)) return true; @@ -1013,7 +1058,7 @@ bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) { } bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) { - Res = 0; + Res = nullptr; return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc); } @@ -1196,13 +1241,21 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) { default: break; case DK_IF: - return parseDirectiveIf(IDLoc); + case DK_IFEQ: + case DK_IFGE: + case DK_IFGT: + case DK_IFLE: + case DK_IFLT: + case DK_IFNE: + return parseDirectiveIf(IDLoc, DirKind); case DK_IFB: return parseDirectiveIfb(IDLoc, true); case DK_IFNB: return parseDirectiveIfb(IDLoc, false); case DK_IFC: return parseDirectiveIfc(IDLoc, true); + case DK_IFEQS: + return parseDirectiveIfeqs(IDLoc); case DK_IFNC: return parseDirectiveIfc(IDLoc, false); case DK_IFDEF: @@ -1311,7 +1364,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) { if (!getTargetParser().ParseDirective(ID)) return false; - // Next, check the extention directive map to see if any extension has + // Next, check the extension directive map to see if any extension has // registered itself to parse this directive. std::pair<MCAsmParserExtension *, DirectiveHandler> Handler = ExtensionDirectiveMap.lookup(IDVal); @@ -1346,6 +1399,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) { case DK_QUAD: case DK_8BYTE: return parseDirectiveValue(8); + case DK_OCTA: + return parseDirectiveOctaValue(); case DK_SINGLE: case DK_FLOAT: return parseDirectiveRealValue(APFloat::IEEEsingle); @@ -1414,7 +1469,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) { case DK_CODE16GCC: return TokError(Twine(IDVal) + " not supported yet"); case DK_REPT: - return parseDirectiveRept(IDLoc); + return parseDirectiveRept(IDLoc, IDVal); case DK_IRP: return parseDirectiveIrp(IDLoc); case DK_IRPC: @@ -1492,6 +1547,12 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) { return parseDirectiveEndMacro(IDVal); case DK_PURGEM: return parseDirectivePurgeMacro(IDLoc); + case DK_END: + return parseDirectiveEnd(IDLoc); + case DK_ERR: + return parseDirectiveError(IDLoc, false); + case DK_ERROR: + return parseDirectiveError(IDLoc, true); } return Error(IDLoc, "unknown directive"); @@ -1530,26 +1591,21 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) { printMessage(IDLoc, SourceMgr::DK_Note, OS.str()); } - // If we are generating dwarf for assembly source files and the current - // section is the initial text section then generate a .loc directive for - // the instruction. + // If we are generating dwarf for the current section then generate a .loc + // directive for the instruction. if (!HadError && getContext().getGenDwarfForAssembly() && - getContext().getGenDwarfSection() == - getStreamer().getCurrentSection().first) { + getContext().getGenDwarfSectionSyms().count( + getStreamer().getCurrentSection().first)) { unsigned Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer); // 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. - const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles = - getContext().getMCDwarfFiles(); if (CppHashFilename.size() != 0) { - if (MCDwarfFiles[getContext().getGenDwarfFileNumber()]->getName() != - CppHashFilename) - getStreamer().EmitDwarfFileDirective( - getContext().nextGenDwarfFileNumber(), StringRef(), - CppHashFilename); + unsigned FileNumber = getStreamer().EmitDwarfFileDirective( + 0, StringRef(), CppHashFilename); + 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 @@ -1575,9 +1631,9 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) { // If parsing succeeded, match the instruction. if (!HadError) { unsigned ErrorInfo; - HadError = getTargetParser().MatchAndEmitInstruction( - IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo, - ParsingInlineAsm); + getTargetParser().MatchAndEmitInstruction(IDLoc, Info.Opcode, + Info.ParsedOperands, Out, + ErrorInfo, ParsingInlineAsm); } // Don't skip the rest of the line, the instruction parser is responsible for @@ -1638,13 +1694,15 @@ void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr(); const SMLoc &DiagLoc = Diag.getLoc(); - int DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); - int CppHashBuf = Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashLoc); + unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); + unsigned CppHashBuf = + Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashLoc); // Like SourceMgr::printMessage() we need to print the include stack if any // before printing the message. - int DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); - if (!Parser->SavedDiagHandler && DiagCurBuffer > 0) { + unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); + if (!Parser->SavedDiagHandler && DiagCurBuffer && + DiagCurBuffer != DiagSrcMgr.getMainFileID()) { SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer); DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS); } @@ -1657,7 +1715,7 @@ void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { if (Parser->SavedDiagHandler) Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext); else - Diag.print(0, OS); + Diag.print(nullptr, OS); return; } @@ -1679,7 +1737,7 @@ void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { if (Parser->SavedDiagHandler) Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext); else - NewDiag.print(0, OS); + NewDiag.print(nullptr, OS); } // FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The @@ -1692,9 +1750,10 @@ static bool isIdentifierChar(char c) { } bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, - const MCAsmMacroParameters &Parameters, - const MCAsmMacroArguments &A, const SMLoc &L) { + ArrayRef<MCAsmMacroParameter> Parameters, + ArrayRef<MCAsmMacroArgument> A, const SMLoc &L) { unsigned NParameters = Parameters.size(); + bool HasVararg = NParameters ? Parameters.back().Vararg : false; if ((!IsDarwin || NParameters != 0) && NParameters != A.size()) return Error(L, "Wrong number of arguments"); @@ -1765,7 +1824,7 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, StringRef Argument(Begin, I - (Pos + 1)); unsigned Index = 0; for (; Index < NParameters; ++Index) - if (Parameters[Index].first == Argument) + if (Parameters[Index].Name == Argument) break; if (Index == NParameters) { @@ -1776,13 +1835,16 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, Pos = I; } } else { + bool VarargParameter = HasVararg && Index == (NParameters - 1); for (MCAsmMacroArgument::const_iterator it = A[Index].begin(), ie = A[Index].end(); it != ie; ++it) - if (it->getKind() == AsmToken::String) - OS << it->getStringContents(); - else + // We expect no quotes around the string's contents when + // parsing for varargs. + if (it->getKind() != AsmToken::String || VarargParameter) OS << it->getString(); + else + OS << it->getStringContents(); Pos += 1 + Argument.size(); } @@ -1830,31 +1892,44 @@ static bool isOperator(AsmToken::TokenKind kind) { } } -bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, - AsmToken::TokenKind &ArgumentDelimiter) { +namespace { +class AsmLexerSkipSpaceRAII { +public: + AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) { + Lexer.setSkipSpace(SkipSpace); + } + + ~AsmLexerSkipSpaceRAII() { + Lexer.setSkipSpace(true); + } + +private: + AsmLexer &Lexer; +}; +} + +bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) { + + if (Vararg) { + if (Lexer.isNot(AsmToken::EndOfStatement)) { + StringRef Str = parseStringToEndOfStatement(); + MA.push_back(AsmToken(AsmToken::String, Str)); + } + return false; + } + unsigned ParenLevel = 0; unsigned AddTokens = 0; - // gas accepts arguments separated by whitespace, except on Darwin - if (!IsDarwin) - Lexer.setSkipSpace(false); + // Darwin doesn't use spaces to delmit arguments. + AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin); for (;;) { - if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal)) { - Lexer.setSkipSpace(true); + if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal)) return TokError("unexpected token in macro instantiation"); - } - if (ParenLevel == 0 && Lexer.is(AsmToken::Comma)) { - // Spaces and commas cannot be mixed to delimit parameters - if (ArgumentDelimiter == AsmToken::Eof) - ArgumentDelimiter = AsmToken::Comma; - else if (ArgumentDelimiter != AsmToken::Comma) { - Lexer.setSkipSpace(true); - return TokError("expected ' ' for macro argument separator"); - } + if (ParenLevel == 0 && Lexer.is(AsmToken::Comma)) break; - } if (Lexer.is(AsmToken::Space)) { Lex(); // Eat spaces @@ -1862,8 +1937,7 @@ bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, // 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 (ArgumentDelimiter == AsmToken::Space || - ArgumentDelimiter == AsmToken::Eof) { + if (!IsDarwin) { if (isOperator(Lexer.getKind())) { // Check to see whether the token is used as an operator, // or part of an identifier @@ -1873,9 +1947,6 @@ bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, } if (!AddTokens && ParenLevel == 0) { - if (ArgumentDelimiter == AsmToken::Eof && - !isOperator(Lexer.getKind())) - ArgumentDelimiter = AsmToken::Space; break; } } @@ -1899,7 +1970,6 @@ bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, Lex(); } - Lexer.setSkipSpace(true); if (ParenLevel != 0) return TokError("unbalanced parentheses in macro argument"); return false; @@ -1909,51 +1979,107 @@ bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool AsmParser::parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A) { const unsigned NParameters = M ? M->Parameters.size() : 0; - // Argument delimiter is initially unknown. It will be set by - // parseMacroArgument() - AsmToken::TokenKind ArgumentDelimiter = AsmToken::Eof; + bool NamedParametersFound = false; + SmallVector<SMLoc, 4> FALocs; + + A.resize(NParameters); + FALocs.resize(NParameters); // Parse two kinds of macro invocations: // - macros defined without any parameters accept an arbitrary number of them // - macros defined with parameters accept at most that many of them + bool HasVararg = NParameters ? M->Parameters.back().Vararg : false; for (unsigned Parameter = 0; !NParameters || Parameter < NParameters; ++Parameter) { - MCAsmMacroArgument MA; + SMLoc IDLoc = Lexer.getLoc(); + MCAsmMacroParameter FA; + + if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) { + if (parseIdentifier(FA.Name)) { + Error(IDLoc, "invalid argument identifier for formal argument"); + eatToEndOfStatement(); + return true; + } + + if (!Lexer.is(AsmToken::Equal)) { + TokError("expected '=' after formal parameter identifier"); + eatToEndOfStatement(); + return true; + } + Lex(); + + NamedParametersFound = true; + } + + if (NamedParametersFound && FA.Name.empty()) { + Error(IDLoc, "cannot mix positional and keyword arguments"); + eatToEndOfStatement(); + return true; + } - if (parseMacroArgument(MA, ArgumentDelimiter)) + bool Vararg = HasVararg && Parameter == (NParameters - 1); + if (parseMacroArgument(FA.Value, Vararg)) return true; - if (!MA.empty() || !NParameters) - A.push_back(MA); - else if (NParameters) { - if (!M->Parameters[Parameter].second.empty()) - A.push_back(M->Parameters[Parameter].second); + unsigned PI = Parameter; + if (!FA.Name.empty()) { + unsigned FAI = 0; + for (FAI = 0; FAI < NParameters; ++FAI) + if (M->Parameters[FAI].Name == FA.Name) + break; + + if (FAI >= NParameters) { + assert(M && "expected macro to be defined"); + Error(IDLoc, + "parameter named '" + FA.Name + "' does not exist for macro '" + + M->Name + "'"); + return true; + } + PI = FAI; + } + + if (!FA.Value.empty()) { + if (A.size() <= PI) + A.resize(PI + 1); + A[PI] = FA.Value; + + if (FALocs.size() <= PI) + FALocs.resize(PI + 1); + + FALocs[PI] = Lexer.getLoc(); } // At the end of the statement, fill in remaining arguments that have // default values. If there aren't any, then the next argument is // required but missing if (Lexer.is(AsmToken::EndOfStatement)) { - if (NParameters && Parameter < NParameters - 1) { - if (M->Parameters[Parameter + 1].second.empty()) - return TokError("macro argument '" + - Twine(M->Parameters[Parameter + 1].first) + - "' is missing"); - else - continue; + bool Failure = false; + for (unsigned FAI = 0; FAI < NParameters; ++FAI) { + if (A[FAI].empty()) { + if (M->Parameters[FAI].Required) { + Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(), + "missing value for required parameter " + "'" + M->Parameters[FAI].Name + "' in macro '" + M->Name + "'"); + Failure = true; + } + + if (!M->Parameters[FAI].Value.empty()) + A[FAI] = M->Parameters[FAI].Value; + } } - return false; + return Failure; } if (Lexer.is(AsmToken::Comma)) Lex(); } - return TokError("Too many arguments"); + + return TokError("too many positional arguments"); } const MCAsmMacro *AsmParser::lookupMacro(StringRef Name) { StringMap<MCAsmMacro *>::iterator I = MacroMap.find(Name); - return (I == MacroMap.end()) ? NULL : I->getValue(); + return (I == MacroMap.end()) ? nullptr : I->getValue(); } void AsmParser::defineMacro(StringRef Name, const MCAsmMacro &Macro) { @@ -1978,12 +2104,6 @@ bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) { if (parseMacroArguments(M, A)) return true; - // Remove any trailing empty arguments. Do this after-the-fact as we have - // to keep empty arguments in the middle of the list or positionality - // gets off. e.g., "foo 1, , 2" vs. "foo 1, 2," - while (!A.empty() && A.back().empty()) - A.pop_back(); - // Macro instantiation is lexical, unfortunately. We construct a new buffer // to hold the macro body with substitutions. SmallString<256> Buf; @@ -2008,7 +2128,7 @@ bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) { // Jump to the macro instantiation and prime the lexer. CurBuffer = SrcMgr.AddNewSourceBuffer(MI->Instantiation, SMLoc()); - Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); Lex(); return false; @@ -2063,12 +2183,6 @@ bool AsmParser::parseAssignment(StringRef Name, bool allow_redef, if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in assignment"); - // Error on assignment to '.'. - if (Name == ".") { - return Error(EqualLoc, ("assignment to pseudo-symbol '.' is unsupported " - "(use '.space' or '.org').)")); - } - // Eat the end of statement marker. Lex(); @@ -2096,11 +2210,15 @@ bool AsmParser::parseAssignment(StringRef Name, bool allow_redef, // Don't count these checks as uses. Sym->setUsed(false); + } else if (Name == ".") { + if (Out.EmitValueToOffset(Value, 0)) { + Error(EqualLoc, "expected absolute expression"); + eatToEndOfStatement(); + } + return false; } else Sym = getContext().GetOrCreateSymbol(Name); - // FIXME: Handle '.'. - // Do the assignment. Out.EmitAssignment(Sym, Value); if (NoDeadStrip) @@ -2275,7 +2393,57 @@ bool AsmParser::parseDirectiveValue(unsigned Size) { return Error(ExprLoc, "literal value out of range for directive"); getStreamer().EmitIntValue(IntValue, Size); } else - getStreamer().EmitValue(Value, Size); + getStreamer().EmitValue(Value, Size, ExprLoc); + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + // FIXME: Improve diagnostic. + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + } + } + + Lex(); + return false; +} + +/// ParseDirectiveOctaValue +/// ::= .octa [ hexconstant (, hexconstant)* ] +bool AsmParser::parseDirectiveOctaValue() { + if (getLexer().isNot(AsmToken::EndOfStatement)) { + checkForValidSection(); + + for (;;) { + if (Lexer.getKind() == AsmToken::Error) + return true; + if (Lexer.getKind() != AsmToken::Integer && + Lexer.getKind() != AsmToken::BigNum) + return TokError("unknown token in expression"); + + SMLoc ExprLoc = getLexer().getLoc(); + APInt IntValue = getTok().getAPIntVal(); + Lex(); + + uint64_t hi, lo; + if (IntValue.isIntN(64)) { + hi = 0; + lo = IntValue.getZExtValue(); + } else if (IntValue.isIntN(128)) { + // It might actually have more than 128 bits, but the top ones are zero. + hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue(); + lo = IntValue.getLoBits(64).getZExtValue(); + } else + return Error(ExprLoc, "literal value out of range for directive"); + + if (MAI.isLittleEndian()) { + getStreamer().EmitIntValue(lo, 8); + getStreamer().EmitIntValue(hi, 8); + } else { + getStreamer().EmitIntValue(hi, 8); + getStreamer().EmitIntValue(lo, 8); + } if (getLexer().is(AsmToken::EndOfStatement)) break; @@ -2380,18 +2548,27 @@ bool AsmParser::parseDirectiveZero() { bool AsmParser::parseDirectiveFill() { checkForValidSection(); + SMLoc RepeatLoc = getLexer().getLoc(); int64_t NumValues; if (parseAbsoluteExpression(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)) return true; @@ -2400,6 +2577,7 @@ bool AsmParser::parseDirectiveFill() { return TokError("unexpected token in '.fill' directive"); Lex(); + ExprLoc = getLexer().getLoc(); if (parseAbsoluteExpression(FillExpr)) return true; @@ -2410,11 +2588,25 @@ bool AsmParser::parseDirectiveFill() { } } - if (FillSize != 1 && FillSize != 2 && FillSize != 4 && FillSize != 8) - return TokError("invalid '.fill' size, expected 1, 2, 4, or 8"); + if (FillSize < 0) { + Warning(SizeLoc, "'.fill' directive with negative size has no effect"); + NumValues = 0; + } + if (FillSize > 8) { + Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8"); + FillSize = 8; + } - for (uint64_t i = 0, e = NumValues; i != e; ++i) - getStreamer().EmitIntValue(FillExpr, FillSize); + if (!isUInt<32>(FillExpr) && FillSize > 4) + Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits"); + + 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); + getStreamer().EmitIntValue(0, FillSize - NonZeroFillSize); + } return false; } @@ -2533,7 +2725,9 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) { // Check whether we should use optimal code alignment for this .align // directive. - bool UseCodeAlign = getStreamer().getCurrentSection().first->UseCodeAlign(); + const MCSection *Section = getStreamer().getCurrentSection().first; + assert(Section && "must have section to emit alignment"); + bool UseCodeAlign = Section->UseCodeAlign(); if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) && ValueSize == 1 && UseCodeAlign) { getStreamer().EmitCodeAlignment(Alignment, MaxBytesToFill); @@ -2597,7 +2791,8 @@ bool AsmParser::parseDirectiveFile(SMLoc 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)) + if (getStreamer().EmitDwarfFileDirective(FileNumber, Directory, Filename) == + 0) Error(FileNumberLoc, "file number already allocated"); } @@ -2763,9 +2958,14 @@ bool AsmParser::parseDirectiveCFISections() { } /// parseDirectiveCFIStartProc -/// ::= .cfi_startproc +/// ::= .cfi_startproc [simple] bool AsmParser::parseDirectiveCFIStartProc() { - getStreamer().EmitCFIStartProc(); + StringRef Simple; + if (getLexer().isNot(AsmToken::EndOfStatement)) + if (parseIdentifier(Simple) || Simple != "simple") + return TokError("unexpected token in .cfi_startproc directive"); + + getStreamer().EmitCFIStartProc(!Simple.empty()); return false; } @@ -3058,41 +3258,72 @@ bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) { } /// parseDirectiveMacro -/// ::= .macro name [parameters] +/// ::= .macro name[,] [parameters] bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) { StringRef Name; if (parseIdentifier(Name)) return TokError("expected identifier in '.macro' directive"); + if (getLexer().is(AsmToken::Comma)) + Lex(); + MCAsmMacroParameters Parameters; - // Argument delimiter is initially unknown. It will be set by - // parseMacroArgument() - AsmToken::TokenKind ArgumentDelimiter = AsmToken::Eof; - if (getLexer().isNot(AsmToken::EndOfStatement)) { - for (;;) { - MCAsmMacroParameter Parameter; - if (parseIdentifier(Parameter.first)) - return TokError("expected identifier in '.macro' directive"); + while (getLexer().isNot(AsmToken::EndOfStatement)) { + + if (Parameters.size() && Parameters.back().Vararg) + return Error(Lexer.getLoc(), + "Vararg parameter '" + Parameters.back().Name + + "' should be last one in the list of parameters."); + + MCAsmMacroParameter Parameter; + if (parseIdentifier(Parameter.Name)) + return TokError("expected identifier in '.macro' directive"); + + if (Lexer.is(AsmToken::Colon)) { + Lex(); // consume ':' + + SMLoc QualLoc; + StringRef Qualifier; + + QualLoc = Lexer.getLoc(); + if (parseIdentifier(Qualifier)) + return Error(QualLoc, "missing parameter qualifier for " + "'" + Parameter.Name + "' in macro '" + Name + "'"); + + if (Qualifier == "req") + Parameter.Required = true; + else if (Qualifier == "vararg" && !IsDarwin) + Parameter.Vararg = true; + else + return Error(QualLoc, Qualifier + " is not a valid parameter qualifier " + "for '" + Parameter.Name + "' in macro '" + Name + "'"); + } - if (getLexer().is(AsmToken::Equal)) { - Lex(); - if (parseMacroArgument(Parameter.second, ArgumentDelimiter)) - return true; - } + if (getLexer().is(AsmToken::Equal)) { + Lex(); - Parameters.push_back(Parameter); + SMLoc ParamLoc; - if (getLexer().is(AsmToken::Comma)) - Lex(); - else if (getLexer().is(AsmToken::EndOfStatement)) - break; + ParamLoc = Lexer.getLoc(); + if (parseMacroArgument(Parameter.Value, /*Vararg=*/false )) + return true; + + if (Parameter.Required) + Warning(ParamLoc, "pointless default value for required parameter " + "'" + Parameter.Name + "' in macro '" + Name + "'"); } + + Parameters.push_back(Parameter); + + if (getLexer().is(AsmToken::Comma)) + Lex(); } // Eat the end of statement. Lex(); AsmToken EndToken, StartToken = getTok(); + unsigned MacroDepth = 0; // Lex the macro definition. for (;;) { @@ -3101,15 +3332,25 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) { return Error(DirectiveLoc, "no matching '.endmacro' in definition"); // Otherwise, check whether we have reach the .endmacro. - if (getLexer().is(AsmToken::Identifier) && - (getTok().getIdentifier() == ".endm" || - getTok().getIdentifier() == ".endmacro")) { - EndToken = getTok(); - Lex(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '" + EndToken.getIdentifier() + - "' directive"); - break; + if (getLexer().is(AsmToken::Identifier)) { + if (getTok().getIdentifier() == ".endm" || + getTok().getIdentifier() == ".endmacro") { + if (MacroDepth == 0) { // Outermost macro. + EndToken = getTok(); + Lex(); + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '" + EndToken.getIdentifier() + + "' directive"); + break; + } else { + // Otherwise we just found the end of an inner macro. + --MacroDepth; + } + } else if (getTok().getIdentifier() == ".macro") { + // We allow nested macros. Those aren't instantiated until the outermost + // macro is expanded so just ignore them for now. + ++MacroDepth; + } } // Otherwise, scan til the end of the statement. @@ -3132,19 +3373,19 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) { /// /// With the support added for named parameters there may be code out there that /// is transitioning from positional parameters. In versions of gas that did -/// not support named parameters they would be ignored on the macro defintion. +/// not support named parameters they would be ignored on the macro definition. /// But to support both styles of parameters this is not possible so if a macro -/// defintion has named parameters but does not use them and has what appears +/// definition has named parameters but does not use them and has what appears /// to be positional parameters, strings like $1, $2, ... and $n, then issue a /// warning that the positional parameter found in body which have no effect. /// Hoping the developer will either remove the named parameters from the macro -/// definiton so the positional parameters get used if that was what was +/// definition so the positional parameters get used if that was what was /// intended or change the macro to use the named parameters. It is possible /// this warning will trigger when the none of the named parameters are used /// and the strings like $1 are infact to simply to be passed trough unchanged. void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body, - MCAsmMacroParameters Parameters) { + ArrayRef<MCAsmMacroParameter> Parameters) { // If this macro is not defined with named parameters the warning we are // checking for here doesn't apply. unsigned NParameters = Parameters.size(); @@ -3206,7 +3447,7 @@ void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Argument(Begin, I - (Pos + 1)); unsigned Index = 0; for (; Index < NParameters; ++Index) - if (Parameters[Index].first == Argument) + if (Parameters[Index].Name == Argument) break; if (Index == NParameters) { @@ -3569,8 +3810,8 @@ bool AsmParser::parseDirectiveIncbin() { } /// parseDirectiveIf -/// ::= .if expression -bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc) { +/// ::= .if{,eq,ge,gt,le,lt,ne} expression +bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) { TheCondStack.push_back(TheCondState); TheCondState.TheCond = AsmCond::IfCond; if (TheCondState.Ignore) { @@ -3585,6 +3826,29 @@ bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc) { Lex(); + switch (DirKind) { + default: + llvm_unreachable("unsupported directive"); + case DK_IF: + case DK_IFNE: + break; + case DK_IFEQ: + ExprValue = ExprValue == 0; + break; + case DK_IFGE: + ExprValue = ExprValue >= 0; + break; + case DK_IFGT: + ExprValue = ExprValue > 0; + break; + case DK_IFLE: + ExprValue = ExprValue <= 0; + break; + case DK_IFLT: + ExprValue = ExprValue < 0; + break; + } + TheCondState.CondMet = ExprValue; TheCondState.Ignore = !TheCondState.CondMet; } @@ -3617,6 +3881,7 @@ bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) { /// parseDirectiveIfc /// ::= .ifc string1, string2 +/// ::= .ifnc string1, string2 bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) { TheCondStack.push_back(TheCondState); TheCondState.TheCond = AsmCond::IfCond; @@ -3638,13 +3903,50 @@ bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) { Lex(); - TheCondState.CondMet = ExpectEqual == (Str1 == Str2); + TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim()); TheCondState.Ignore = !TheCondState.CondMet; } return false; } +/// parseDirectiveIfeqs +/// ::= .ifeqs string1, string2 +bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc) { + if (Lexer.isNot(AsmToken::String)) { + TokError("expected string parameter for '.ifeqs' directive"); + eatToEndOfStatement(); + return true; + } + + StringRef String1 = getTok().getStringContents(); + Lex(); + + if (Lexer.isNot(AsmToken::Comma)) { + TokError("expected comma after first string for '.ifeqs' directive"); + eatToEndOfStatement(); + return true; + } + + Lex(); + + if (Lexer.isNot(AsmToken::String)) { + TokError("expected string parameter for '.ifeqs' directive"); + eatToEndOfStatement(); + return true; + } + + StringRef String2 = getTok().getStringContents(); + Lex(); + + TheCondStack.push_back(TheCondState); + TheCondState.TheCond = AsmCond::IfCond; + TheCondState.CondMet = String1 == String2; + TheCondState.Ignore = !TheCondState.CondMet; + + return false; +} + /// parseDirectiveIfdef /// ::= .ifdef symbol bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { @@ -3663,9 +3965,9 @@ bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { MCSymbol *Sym = getContext().LookupSymbol(Name); if (expect_defined) - TheCondState.CondMet = (Sym != NULL && !Sym->isUndefined()); + TheCondState.CondMet = (Sym && !Sym->isUndefined()); else - TheCondState.CondMet = (Sym == NULL || Sym->isUndefined()); + TheCondState.CondMet = (!Sym || Sym->isUndefined()); TheCondState.Ignore = !TheCondState.CondMet; } @@ -3727,6 +4029,50 @@ bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) { return false; } +/// parseDirectiveEnd +/// ::= .end +bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.end' directive"); + + Lex(); + + while (Lexer.isNot(AsmToken::Eof)) + Lex(); + + return false; +} + +/// parseDirectiveError +/// ::= .err +/// ::= .error [string] +bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) { + if (!TheCondStack.empty()) { + if (TheCondStack.back().Ignore) { + eatToEndOfStatement(); + return false; + } + } + + if (!WithMessage) + return Error(L, ".err encountered"); + + StringRef Message = ".error directive invoked in source file"; + if (Lexer.isNot(AsmToken::EndOfStatement)) { + if (Lexer.isNot(AsmToken::String)) { + TokError(".error argument must be a string"); + eatToEndOfStatement(); + return true; + } + + Message = getTok().getStringContents(); + Lex(); + } + + Error(L, Message); + return true; +} + /// parseDirectiveEndIf /// ::= .endif bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) { @@ -3762,6 +4108,7 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".4byte"] = DK_4BYTE; DirectiveKindMap[".quad"] = DK_QUAD; DirectiveKindMap[".8byte"] = DK_8BYTE; + DirectiveKindMap[".octa"] = DK_OCTA; DirectiveKindMap[".single"] = DK_SINGLE; DirectiveKindMap[".float"] = DK_FLOAT; DirectiveKindMap[".double"] = DK_DOUBLE; @@ -3796,6 +4143,7 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".code16"] = DK_CODE16; DirectiveKindMap[".code16gcc"] = DK_CODE16GCC; DirectiveKindMap[".rept"] = DK_REPT; + DirectiveKindMap[".rep"] = DK_REPT; DirectiveKindMap[".irp"] = DK_IRP; DirectiveKindMap[".irpc"] = DK_IRPC; DirectiveKindMap[".endr"] = DK_ENDR; @@ -3803,15 +4151,23 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK; DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK; DirectiveKindMap[".if"] = DK_IF; + DirectiveKindMap[".ifeq"] = DK_IFEQ; + DirectiveKindMap[".ifge"] = DK_IFGE; + DirectiveKindMap[".ifgt"] = DK_IFGT; + DirectiveKindMap[".ifle"] = DK_IFLE; + DirectiveKindMap[".iflt"] = DK_IFLT; + DirectiveKindMap[".ifne"] = DK_IFNE; DirectiveKindMap[".ifb"] = DK_IFB; DirectiveKindMap[".ifnb"] = DK_IFNB; DirectiveKindMap[".ifc"] = DK_IFC; + DirectiveKindMap[".ifeqs"] = DK_IFEQS; DirectiveKindMap[".ifnc"] = DK_IFNC; DirectiveKindMap[".ifdef"] = DK_IFDEF; DirectiveKindMap[".ifndef"] = DK_IFNDEF; DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF; DirectiveKindMap[".elseif"] = DK_ELSEIF; DirectiveKindMap[".else"] = DK_ELSE; + DirectiveKindMap[".end"] = DK_END; DirectiveKindMap[".endif"] = DK_ENDIF; DirectiveKindMap[".skip"] = DK_SKIP; DirectiveKindMap[".space"] = DK_SPACE; @@ -3847,6 +4203,8 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".endm"] = DK_ENDM; DirectiveKindMap[".endmacro"] = DK_ENDMACRO; DirectiveKindMap[".purgem"] = DK_PURGEM; + DirectiveKindMap[".err"] = DK_ERR; + DirectiveKindMap[".error"] = DK_ERROR; } MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { @@ -3857,7 +4215,7 @@ MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { // Check whether we have reached the end of the file. if (getLexer().is(AsmToken::Eof)) { Error(DirectiveLoc, "no matching '.endr' in definition"); - return 0; + return nullptr; } if (Lexer.is(AsmToken::Identifier) && @@ -3872,7 +4230,7 @@ MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { Lex(); if (Lexer.isNot(AsmToken::EndOfStatement)) { TokError("unexpected token in '.endr' directive"); - return 0; + return nullptr; } break; } @@ -3888,9 +4246,7 @@ MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart); // We Are Anonymous. - StringRef Name; - MCAsmMacroParameters Parameters; - MacroLikeBodies.push_back(MCAsmMacro(Name, Body, Parameters)); + MacroLikeBodies.push_back(MCAsmMacro(StringRef(), Body, None)); return &MacroLikeBodies.back(); } @@ -3909,20 +4265,29 @@ void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, // Jump to the macro instantiation and prime the lexer. CurBuffer = SrcMgr.AddNewSourceBuffer(MI->Instantiation, SMLoc()); - Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); Lex(); } -bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc) { +/// parseDirectiveRept +/// ::= .rep | .rept count +bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) { + const MCExpr *CountExpr; + SMLoc CountLoc = getTok().getLoc(); + if (parseExpression(CountExpr)) + return true; + int64_t Count; - if (parseAbsoluteExpression(Count)) - return TokError("unexpected token in '.rept' directive"); + if (!CountExpr->EvaluateAsAbsolute(Count)) { + eatToEndOfStatement(); + return Error(CountLoc, "unexpected token in '" + Dir + "' directive"); + } if (Count < 0) - return TokError("Count is negative"); + return Error(CountLoc, "Count is negative"); if (Lexer.isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.rept' directive"); + return TokError("unexpected token in '" + Dir + "' directive"); // Eat the end of statement. Lex(); @@ -3935,11 +4300,9 @@ bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc) { // Macro instantiation is lexical, unfortunately. We construct a new buffer // to hold the macro body with substitutions. SmallString<256> Buf; - MCAsmMacroParameters Parameters; - MCAsmMacroArguments A; raw_svector_ostream OS(Buf); while (Count--) { - if (expandMacro(OS, M->Body, Parameters, A, getTok().getLoc())) + if (expandMacro(OS, M->Body, None, None, getTok().getLoc())) return true; } instantiateMacroLikeBody(M, DirectiveLoc, OS); @@ -3950,21 +4313,18 @@ bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc) { /// parseDirectiveIrp /// ::= .irp symbol,values bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) { - MCAsmMacroParameters Parameters; MCAsmMacroParameter Parameter; - if (parseIdentifier(Parameter.first)) + if (parseIdentifier(Parameter.Name)) return TokError("expected identifier in '.irp' directive"); - Parameters.push_back(Parameter); - if (Lexer.isNot(AsmToken::Comma)) return TokError("expected comma in '.irp' directive"); Lex(); MCAsmMacroArguments A; - if (parseMacroArguments(0, A)) + if (parseMacroArguments(nullptr, A)) return true; // Eat the end of statement. @@ -3981,10 +4341,7 @@ bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) { raw_svector_ostream OS(Buf); for (MCAsmMacroArguments::iterator i = A.begin(), e = A.end(); i != e; ++i) { - MCAsmMacroArguments Args; - Args.push_back(*i); - - if (expandMacro(OS, M->Body, Parameters, Args, getTok().getLoc())) + if (expandMacro(OS, M->Body, Parameter, *i, getTok().getLoc())) return true; } @@ -3996,21 +4353,18 @@ bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) { /// parseDirectiveIrpc /// ::= .irpc symbol,values bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) { - MCAsmMacroParameters Parameters; MCAsmMacroParameter Parameter; - if (parseIdentifier(Parameter.first)) + if (parseIdentifier(Parameter.Name)) return TokError("expected identifier in '.irpc' directive"); - Parameters.push_back(Parameter); - if (Lexer.isNot(AsmToken::Comma)) return TokError("expected comma in '.irpc' directive"); Lex(); MCAsmMacroArguments A; - if (parseMacroArguments(0, A)) + if (parseMacroArguments(nullptr, A)) return true; if (A.size() != 1 || A.front().size() != 1) @@ -4030,15 +4384,11 @@ bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) { raw_svector_ostream OS(Buf); StringRef Values = A.front().front().getString(); - std::size_t I, End = Values.size(); - for (I = 0; I < End; ++I) { + for (std::size_t I = 0, End = Values.size(); I != End; ++I) { MCAsmMacroArgument Arg; Arg.push_back(AsmToken(AsmToken::Identifier, Values.slice(I, I + 1))); - MCAsmMacroArguments Args; - Args.push_back(Arg); - - if (expandMacro(OS, M->Body, Parameters, Args, getTok().getLoc())) + if (expandMacro(OS, M->Body, Parameter, Arg, getTok().getLoc())) return true; } @@ -4153,27 +4503,28 @@ bool AsmParser::parseMSInlineAsm( // Build the list of clobbers, outputs and inputs. for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) { - MCParsedAsmOperand *Operand = Info.ParsedOperands[i]; + MCParsedAsmOperand &Operand = *Info.ParsedOperands[i]; // Immediate. - if (Operand->isImm()) + if (Operand.isImm()) continue; // Register operand. - if (Operand->isReg() && !Operand->needAddressOf()) { + if (Operand.isReg() && !Operand.needAddressOf() && + !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) { unsigned NumDefs = Desc.getNumDefs(); // Clobber. - if (NumDefs && Operand->getMCOperandNum() < NumDefs) - ClobberRegs.push_back(Operand->getReg()); + if (NumDefs && Operand.getMCOperandNum() < NumDefs) + ClobberRegs.push_back(Operand.getReg()); continue; } // Expr/Input or Output. - StringRef SymName = Operand->getSymName(); + StringRef SymName = Operand.getSymName(); if (SymName.empty()) continue; - void *OpDecl = Operand->getOpDecl(); + void *OpDecl = Operand.getOpDecl(); if (!OpDecl) continue; @@ -4182,21 +4533,21 @@ bool AsmParser::parseMSInlineAsm( if (isOutput) { ++InputIdx; OutputDecls.push_back(OpDecl); - OutputDeclsAddressOf.push_back(Operand->needAddressOf()); - OutputConstraints.push_back('=' + Operand->getConstraint().str()); + OutputDeclsAddressOf.push_back(Operand.needAddressOf()); + OutputConstraints.push_back('=' + Operand.getConstraint().str()); AsmStrRewrites.push_back(AsmRewrite(AOK_Output, Start, SymName.size())); } else { InputDecls.push_back(OpDecl); - InputDeclsAddressOf.push_back(Operand->needAddressOf()); - InputConstraints.push_back(Operand->getConstraint().str()); + InputDeclsAddressOf.push_back(Operand.needAddressOf()); + InputConstraints.push_back(Operand.getConstraint().str()); AsmStrRewrites.push_back(AsmRewrite(AOK_Input, Start, SymName.size())); } } // Consider implicit defs to be clobbers. Think of cpuid and push. - const uint16_t *ImpDefs = Desc.getImplicitDefs(); - for (unsigned I = 0, E = Desc.getNumImplicitDefs(); I != E; ++I) - ClobberRegs.push_back(ImpDefs[I]); + ArrayRef<uint16_t> ImpDefs(Desc.getImplicitDefs(), + Desc.getNumImplicitDefs()); + ClobberRegs.insert(ClobberRegs.end(), ImpDefs.begin(), ImpDefs.end()); } // Set the number of Outputs and Inputs. @@ -4231,27 +4582,26 @@ bool AsmParser::parseMSInlineAsm( // Build the IR assembly string. std::string AsmStringIR; raw_string_ostream OS(AsmStringIR); - const char *AsmStart = SrcMgr.getMemoryBuffer(0)->getBufferStart(); - const char *AsmEnd = SrcMgr.getMemoryBuffer(0)->getBufferEnd(); + StringRef ASMString = + SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer(); + const char *AsmStart = ASMString.begin(); + const char *AsmEnd = ASMString.end(); array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort); - for (SmallVectorImpl<AsmRewrite>::iterator I = AsmStrRewrites.begin(), - E = AsmStrRewrites.end(); - I != E; ++I) { - AsmRewriteKind Kind = (*I).Kind; + for (const AsmRewrite &AR : AsmStrRewrites) { + AsmRewriteKind Kind = AR.Kind; if (Kind == AOK_Delete) continue; - const char *Loc = (*I).Loc.getPointer(); + const char *Loc = AR.Loc.getPointer(); assert(Loc >= AsmStart && "Expected Loc to be at or after Start!"); // Emit everything up to the immediate/expression. - unsigned Len = Loc - AsmStart; - if (Len) + if (unsigned Len = Loc - AsmStart) OS << StringRef(AsmStart, Len); // Skip the original expression. if (Kind == AOK_Skip) { - AsmStart = Loc + (*I).Len; + AsmStart = Loc + AR.Len; continue; } @@ -4261,7 +4611,7 @@ bool AsmParser::parseMSInlineAsm( default: break; case AOK_Imm: - OS << "$$" << (*I).Val; + OS << "$$" << AR.Val; break; case AOK_ImmPrefix: OS << "$$"; @@ -4273,7 +4623,7 @@ bool AsmParser::parseMSInlineAsm( OS << '$' << OutputIdx++; break; case AOK_SizeDirective: - switch ((*I).Val) { + switch (AR.Val) { default: break; case 8: OS << "byte ptr "; break; case 16: OS << "word ptr "; break; @@ -4288,7 +4638,7 @@ bool AsmParser::parseMSInlineAsm( OS << ".byte"; break; case AOK_Align: { - unsigned Val = (*I).Val; + unsigned Val = AR.Val; OS << ".align " << Val; // Skip the original immediate. @@ -4299,14 +4649,14 @@ bool AsmParser::parseMSInlineAsm( case AOK_DotOperator: // Insert the dot if the user omitted it. OS.flush(); - if (AsmStringIR.at(AsmStringIR.size() - 1) != '.') + if (AsmStringIR.back() != '.') OS << '.'; - OS << (*I).Val; + OS << AR.Val; break; } // Skip the original expression. - AsmStart = Loc + (*I).Len + AdditionalSkip; + AsmStart = Loc + AR.Len + AdditionalSkip; } // Emit the remainder of the asm string. diff --git a/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp index d8343a3..5ecf9e5 100644 --- a/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp @@ -13,6 +13,7 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSectionCOFF.h" @@ -37,12 +38,12 @@ class COFFAsmParser : public MCAsmParserExtension { bool ParseSectionSwitch(StringRef Section, unsigned Characteristics, SectionKind Kind, StringRef COMDATSymName, - COFF::COMDATType Type, const MCSectionCOFF *Assoc); + COFF::COMDATType Type); bool ParseSectionName(StringRef &SectionName); bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags); - virtual void Initialize(MCAsmParser &Parser) { + void Initialize(MCAsmParser &Parser) override { // Call the base implementation. MCAsmParserExtension::Initialize(Parser); @@ -55,6 +56,7 @@ class COFFAsmParser : public MCAsmParserExtension { addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type"); addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef"); addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx"); addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce"); // Win64 EH directives. @@ -115,8 +117,8 @@ class COFFAsmParser : public MCAsmParserExtension { bool ParseDirectiveType(StringRef, SMLoc); bool ParseDirectiveEndef(StringRef, SMLoc); bool ParseDirectiveSecRel32(StringRef, SMLoc); - bool parseCOMDATTypeAndAssoc(COFF::COMDATType &Type, - const MCSectionCOFF *&Assoc); + bool ParseDirectiveSecIdx(StringRef, SMLoc); + bool parseCOMDATType(COFF::COMDATType &Type); bool ParseDirectiveLinkOnce(StringRef, SMLoc); // Win64 EH directives. @@ -168,8 +170,8 @@ bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) { bool ReadOnlyRemoved = false; unsigned SecFlags = None; - for (unsigned i = 0; i < FlagsString.size(); ++i) { - switch (FlagsString[i]) { + for (char FlagChar : FlagsString) { + switch (FlagChar) { case 'a': // Ignored. break; @@ -290,22 +292,20 @@ bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { bool COFFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Characteristics, SectionKind Kind) { - return ParseSectionSwitch(Section, Characteristics, Kind, "", - COFF::IMAGE_COMDAT_SELECT_ANY, 0); + return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0); } bool COFFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Characteristics, SectionKind Kind, StringRef COMDATSymName, - COFF::COMDATType Type, - const MCSectionCOFF *Assoc) { + COFF::COMDATType Type) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in section switching directive"); Lex(); getStreamer().SwitchSection(getContext().getCOFFSection( - Section, Characteristics, Kind, COMDATSymName, Type, Assoc)); + Section, Characteristics, Kind, COMDATSymName, Type)); return false; } @@ -356,15 +356,15 @@ bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { return true; } - COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; - const MCSectionCOFF *Assoc = 0; + COFF::COMDATType Type = (COFF::COMDATType)0; StringRef COMDATSymName; if (getLexer().is(AsmToken::Comma)) { + Type = COFF::IMAGE_COMDAT_SELECT_ANY;; Lex(); Flags |= COFF::IMAGE_SCN_LNK_COMDAT; - if (parseCOMDATTypeAndAssoc(Type, Assoc)) + if (parseCOMDATType(Type)) return true; if (getLexer().isNot(AsmToken::Comma)) @@ -379,7 +379,12 @@ bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { return TokError("unexpected token in directive"); SectionKind Kind = computeSectionKind(Flags); - ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type, Assoc); + if (Kind.isText()) { + const Triple &T = getContext().getObjectFileInfo()->getTargetTriple(); + if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb) + Flags |= COFF::IMAGE_SCN_MEM_16BIT; + } + ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type); return false; } @@ -432,7 +437,7 @@ bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) { bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) { StringRef SymbolID; if (getParser().parseIdentifier(SymbolID)) - return true; + return TokError("expected identifier in directive"); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); @@ -444,9 +449,23 @@ bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) { return false; } -/// ::= [ identifier [ identifier ] ] -bool COFFAsmParser::parseCOMDATTypeAndAssoc(COFF::COMDATType &Type, - const MCSectionCOFF *&Assoc) { +bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) { + StringRef SymbolID; + if (getParser().parseIdentifier(SymbolID)) + return TokError("expected identifier in directive"); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID); + + Lex(); + getStreamer().EmitCOFFSectionIndex(Symbol); + return false; +} + +/// ::= [ identifier ] +bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) { StringRef TypeId = getTok().getIdentifier(); Type = StringSwitch<COFF::COMDATType>(TypeId) @@ -464,48 +483,28 @@ bool COFFAsmParser::parseCOMDATTypeAndAssoc(COFF::COMDATType &Type, Lex(); - if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { - SMLoc Loc = getTok().getLoc(); - StringRef AssocName; - if (ParseSectionName(AssocName)) - return TokError("expected associated section name"); - - Assoc = static_cast<const MCSectionCOFF*>( - getContext().getCOFFSection(AssocName)); - if (!Assoc) - return Error(Loc, "cannot associate unknown section '" + AssocName + "'"); - if (!(Assoc->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)) - return Error(Loc, "associated section must be a COMDAT section"); - if (Assoc->getSelection() == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) - return Error(Loc, "associated section cannot be itself associative"); - } - return false; } /// ParseDirectiveLinkOnce -/// ::= .linkonce [ identifier [ identifier ] ] +/// ::= .linkonce [ identifier ] bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) { COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; - const MCSectionCOFF *Assoc = 0; if (getLexer().is(AsmToken::Identifier)) - if (parseCOMDATTypeAndAssoc(Type, Assoc)) + if (parseCOMDATType(Type)) return true; const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>( getStreamer().getCurrentSection().first); - - if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { - if (Assoc == Current) - return Error(Loc, "cannot associate a section with itself"); - } + if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) + return Error(Loc, "cannot make section associative with .linkonce"); if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) return Error(Loc, Twine("section '") + Current->getSectionName() + "' is already linkonce"); - Current->setSelection(Type, Assoc); + Current->setSelection(Type); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); @@ -524,25 +523,25 @@ bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) { MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID); Lex(); - getStreamer().EmitWin64EHStartProc(Symbol); + getStreamer().EmitWinCFIStartProc(Symbol); return false; } bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) { Lex(); - getStreamer().EmitWin64EHEndProc(); + getStreamer().EmitWinCFIEndProc(); return false; } bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) { Lex(); - getStreamer().EmitWin64EHStartChained(); + getStreamer().EmitWinCFIStartChained(); return false; } bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) { Lex(); - getStreamer().EmitWin64EHEndChained(); + getStreamer().EmitWinCFIEndChained(); return false; } @@ -568,13 +567,13 @@ bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) { MCSymbol *handler = getContext().GetOrCreateSymbol(SymbolID); Lex(); - getStreamer().EmitWin64EHHandler(handler, unwind, except); + getStreamer().EmitWinEHHandler(handler, unwind, except); return false; } bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) { Lex(); - getStreamer().EmitWin64EHHandlerData(); + getStreamer().EmitWinEHHandlerData(); return false; } @@ -587,7 +586,7 @@ bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) { return TokError("unexpected token in directive"); Lex(); - getStreamer().EmitWin64EHPushReg(Reg); + getStreamer().EmitWinCFIPushReg(Reg); return false; } @@ -611,7 +610,7 @@ bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) { return TokError("unexpected token in directive"); Lex(); - getStreamer().EmitWin64EHSetFrame(Reg, Off); + getStreamer().EmitWinCFISetFrame(Reg, Off); return false; } @@ -628,7 +627,7 @@ bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) { return TokError("unexpected token in directive"); Lex(); - getStreamer().EmitWin64EHAllocStack(Size); + getStreamer().EmitWinCFIAllocStack(Size); return false; } @@ -653,7 +652,7 @@ bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) { Lex(); // FIXME: Err on %xmm* registers - getStreamer().EmitWin64EHSaveReg(Reg, Off); + getStreamer().EmitWinCFISaveReg(Reg, Off); return false; } @@ -680,7 +679,7 @@ bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) { Lex(); // FIXME: Err on non-%xmm* registers - getStreamer().EmitWin64EHSaveXMM(Reg, Off); + getStreamer().EmitWinCFISaveXMM(Reg, Off); return false; } @@ -701,13 +700,13 @@ bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) { return TokError("unexpected token in directive"); Lex(); - getStreamer().EmitWin64EHPushFrame(Code); + getStreamer().EmitWinCFIPushFrame(Code); return false; } bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) { Lex(); - getStreamer().EmitWin64EHEndProlog(); + getStreamer().EmitWinCFIEndProlog(); return false; } diff --git a/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp index 4c9bafa..b2a6785 100644 --- a/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/DarwinAsmParser.cpp @@ -17,6 +17,7 @@ #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" using namespace llvm; @@ -33,339 +34,343 @@ class DarwinAsmParser : public MCAsmParserExtension { getParser().addDirectiveHandler(Directive, Handler); } - bool ParseSectionSwitch(const char *Segment, const char *Section, + bool parseSectionSwitch(const char *Segment, const char *Section, unsigned TAA = 0, unsigned ImplicitAlign = 0, unsigned StubSize = 0); public: DarwinAsmParser() {} - virtual void Initialize(MCAsmParser &Parser) { + void Initialize(MCAsmParser &Parser) override { // Call the base implementation. this->MCAsmParserExtension::Initialize(Parser); - addDirectiveHandler<&DarwinAsmParser::ParseDirectiveDesc>(".desc"); - addDirectiveHandler<&DarwinAsmParser::ParseDirectiveIndirectSymbol>( + addDirectiveHandler<&DarwinAsmParser::parseDirectiveDesc>(".desc"); + addDirectiveHandler<&DarwinAsmParser::parseDirectiveIndirectSymbol>( ".indirect_symbol"); - addDirectiveHandler<&DarwinAsmParser::ParseDirectiveLsym>(".lsym"); - addDirectiveHandler<&DarwinAsmParser::ParseDirectiveSubsectionsViaSymbols>( + addDirectiveHandler<&DarwinAsmParser::parseDirectiveLsym>(".lsym"); + addDirectiveHandler<&DarwinAsmParser::parseDirectiveSubsectionsViaSymbols>( ".subsections_via_symbols"); - addDirectiveHandler<&DarwinAsmParser::ParseDirectiveDumpOrLoad>(".dump"); - addDirectiveHandler<&DarwinAsmParser::ParseDirectiveDumpOrLoad>(".load"); - addDirectiveHandler<&DarwinAsmParser::ParseDirectiveSection>(".section"); - addDirectiveHandler<&DarwinAsmParser::ParseDirectivePushSection>( + addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(".dump"); + addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(".load"); + addDirectiveHandler<&DarwinAsmParser::parseDirectiveSection>(".section"); + addDirectiveHandler<&DarwinAsmParser::parseDirectivePushSection>( ".pushsection"); - addDirectiveHandler<&DarwinAsmParser::ParseDirectivePopSection>( + addDirectiveHandler<&DarwinAsmParser::parseDirectivePopSection>( ".popsection"); - addDirectiveHandler<&DarwinAsmParser::ParseDirectivePrevious>(".previous"); - addDirectiveHandler<&DarwinAsmParser::ParseDirectiveSecureLogUnique>( + addDirectiveHandler<&DarwinAsmParser::parseDirectivePrevious>(".previous"); + addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogUnique>( ".secure_log_unique"); - addDirectiveHandler<&DarwinAsmParser::ParseDirectiveSecureLogReset>( + addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogReset>( ".secure_log_reset"); - addDirectiveHandler<&DarwinAsmParser::ParseDirectiveTBSS>(".tbss"); - addDirectiveHandler<&DarwinAsmParser::ParseDirectiveZerofill>(".zerofill"); + addDirectiveHandler<&DarwinAsmParser::parseDirectiveTBSS>(".tbss"); + addDirectiveHandler<&DarwinAsmParser::parseDirectiveZerofill>(".zerofill"); - addDirectiveHandler<&DarwinAsmParser::ParseDirectiveDataRegion>( + addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegion>( ".data_region"); - addDirectiveHandler<&DarwinAsmParser::ParseDirectiveDataRegionEnd>( + addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegionEnd>( ".end_data_region"); // Special section directives. - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveBss>(".bss"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConst>(".const"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConstData>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveBss>(".bss"); + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConst>(".const"); + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstData>( ".const_data"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConstructor>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstructor>( ".constructor"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveCString>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveCString>( ".cstring"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveData>(".data"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveDestructor>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveData>(".data"); + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDestructor>( ".destructor"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveDyld>(".dyld"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveFVMLibInit0>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDyld>(".dyld"); + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit0>( ".fvmlib_init0"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveFVMLibInit1>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit1>( ".fvmlib_init1"); addDirectiveHandler< - &DarwinAsmParser::ParseSectionDirectiveLazySymbolPointers>( + &DarwinAsmParser::parseSectionDirectiveLazySymbolPointers>( ".lazy_symbol_pointer"); - addDirectiveHandler<&DarwinAsmParser::ParseDirectiveLinkerOption>( + addDirectiveHandler<&DarwinAsmParser::parseDirectiveLinkerOption>( ".linker_option"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveLiteral16>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral16>( ".literal16"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveLiteral4>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral4>( ".literal4"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveLiteral8>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral8>( ".literal8"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveModInitFunc>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModInitFunc>( ".mod_init_func"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveModTermFunc>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModTermFunc>( ".mod_term_func"); addDirectiveHandler< - &DarwinAsmParser::ParseSectionDirectiveNonLazySymbolPointers>( + &DarwinAsmParser::parseSectionDirectiveNonLazySymbolPointers>( ".non_lazy_symbol_pointer"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCCatClsMeth>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatClsMeth>( ".objc_cat_cls_meth"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCCatInstMeth>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatInstMeth>( ".objc_cat_inst_meth"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCCategory>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCategory>( ".objc_category"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClass>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClass>( ".objc_class"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClassNames>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassNames>( ".objc_class_names"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClassVars>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassVars>( ".objc_class_vars"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClsMeth>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsMeth>( ".objc_cls_meth"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClsRefs>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsRefs>( ".objc_cls_refs"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCInstMeth>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCInstMeth>( ".objc_inst_meth"); addDirectiveHandler< - &DarwinAsmParser::ParseSectionDirectiveObjCInstanceVars>( + &DarwinAsmParser::parseSectionDirectiveObjCInstanceVars>( ".objc_instance_vars"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCMessageRefs>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMessageRefs>( ".objc_message_refs"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCMetaClass>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMetaClass>( ".objc_meta_class"); addDirectiveHandler< - &DarwinAsmParser::ParseSectionDirectiveObjCMethVarNames>( + &DarwinAsmParser::parseSectionDirectiveObjCMethVarNames>( ".objc_meth_var_names"); addDirectiveHandler< - &DarwinAsmParser::ParseSectionDirectiveObjCMethVarTypes>( + &DarwinAsmParser::parseSectionDirectiveObjCMethVarTypes>( ".objc_meth_var_types"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCModuleInfo>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCModuleInfo>( ".objc_module_info"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCProtocol>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCProtocol>( ".objc_protocol"); addDirectiveHandler< - &DarwinAsmParser::ParseSectionDirectiveObjCSelectorStrs>( + &DarwinAsmParser::parseSectionDirectiveObjCSelectorStrs>( ".objc_selector_strs"); addDirectiveHandler< - &DarwinAsmParser::ParseSectionDirectiveObjCStringObject>( + &DarwinAsmParser::parseSectionDirectiveObjCStringObject>( ".objc_string_object"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCSymbols>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCSymbols>( ".objc_symbols"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectivePICSymbolStub>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectivePICSymbolStub>( ".picsymbol_stub"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveStaticConst>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticConst>( ".static_const"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveStaticData>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticData>( ".static_data"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveSymbolStub>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveSymbolStub>( ".symbol_stub"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveTData>(".tdata"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveText>(".text"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveThreadInitFunc>( + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTData>(".tdata"); + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveText>(".text"); + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveThreadInitFunc>( ".thread_init_func"); - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveTLV>(".tlv"); - - addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveIdent>(".ident"); - } - - bool ParseDirectiveDesc(StringRef, SMLoc); - bool ParseDirectiveIndirectSymbol(StringRef, SMLoc); - bool ParseDirectiveDumpOrLoad(StringRef, SMLoc); - bool ParseDirectiveLsym(StringRef, SMLoc); - bool ParseDirectiveLinkerOption(StringRef, SMLoc); - bool ParseDirectiveSection(StringRef, SMLoc); - bool ParseDirectivePushSection(StringRef, SMLoc); - bool ParseDirectivePopSection(StringRef, SMLoc); - bool ParseDirectivePrevious(StringRef, SMLoc); - bool ParseDirectiveSecureLogReset(StringRef, SMLoc); - bool ParseDirectiveSecureLogUnique(StringRef, SMLoc); - bool ParseDirectiveSubsectionsViaSymbols(StringRef, SMLoc); - bool ParseDirectiveTBSS(StringRef, SMLoc); - bool ParseDirectiveZerofill(StringRef, SMLoc); - bool ParseDirectiveDataRegion(StringRef, SMLoc); - bool ParseDirectiveDataRegionEnd(StringRef, SMLoc); + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTLV>(".tlv"); + + addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveIdent>(".ident"); + addDirectiveHandler<&DarwinAsmParser::parseVersionMin>(".ios_version_min"); + addDirectiveHandler<&DarwinAsmParser::parseVersionMin>( + ".macosx_version_min"); + } + + bool parseDirectiveDesc(StringRef, SMLoc); + bool parseDirectiveIndirectSymbol(StringRef, SMLoc); + bool parseDirectiveDumpOrLoad(StringRef, SMLoc); + bool parseDirectiveLsym(StringRef, SMLoc); + bool parseDirectiveLinkerOption(StringRef, SMLoc); + bool parseDirectiveSection(StringRef, SMLoc); + bool parseDirectivePushSection(StringRef, SMLoc); + bool parseDirectivePopSection(StringRef, SMLoc); + bool parseDirectivePrevious(StringRef, SMLoc); + bool parseDirectiveSecureLogReset(StringRef, SMLoc); + bool parseDirectiveSecureLogUnique(StringRef, SMLoc); + bool parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc); + bool parseDirectiveTBSS(StringRef, SMLoc); + bool parseDirectiveZerofill(StringRef, SMLoc); + bool parseDirectiveDataRegion(StringRef, SMLoc); + bool parseDirectiveDataRegionEnd(StringRef, SMLoc); // Named Section Directive - bool ParseSectionDirectiveBss(StringRef, SMLoc) { - return ParseSectionSwitch("__DATA", "__bss"); + bool parseSectionDirectiveBss(StringRef, SMLoc) { + return parseSectionSwitch("__DATA", "__bss"); } - bool ParseSectionDirectiveConst(StringRef, SMLoc) { - return ParseSectionSwitch("__TEXT", "__const"); + bool parseSectionDirectiveConst(StringRef, SMLoc) { + return parseSectionSwitch("__TEXT", "__const"); } - bool ParseSectionDirectiveStaticConst(StringRef, SMLoc) { - return ParseSectionSwitch("__TEXT", "__static_const"); + bool parseSectionDirectiveStaticConst(StringRef, SMLoc) { + return parseSectionSwitch("__TEXT", "__static_const"); } - bool ParseSectionDirectiveCString(StringRef, SMLoc) { - return ParseSectionSwitch("__TEXT","__cstring", - MCSectionMachO::S_CSTRING_LITERALS); + bool parseSectionDirectiveCString(StringRef, SMLoc) { + return parseSectionSwitch("__TEXT","__cstring", + MachO::S_CSTRING_LITERALS); } - bool ParseSectionDirectiveLiteral4(StringRef, SMLoc) { - return ParseSectionSwitch("__TEXT", "__literal4", - MCSectionMachO::S_4BYTE_LITERALS, 4); + bool parseSectionDirectiveLiteral4(StringRef, SMLoc) { + return parseSectionSwitch("__TEXT", "__literal4", + MachO::S_4BYTE_LITERALS, 4); } - bool ParseSectionDirectiveLiteral8(StringRef, SMLoc) { - return ParseSectionSwitch("__TEXT", "__literal8", - MCSectionMachO::S_8BYTE_LITERALS, 8); + bool parseSectionDirectiveLiteral8(StringRef, SMLoc) { + return parseSectionSwitch("__TEXT", "__literal8", + MachO::S_8BYTE_LITERALS, 8); } - bool ParseSectionDirectiveLiteral16(StringRef, SMLoc) { - return ParseSectionSwitch("__TEXT","__literal16", - MCSectionMachO::S_16BYTE_LITERALS, 16); + bool parseSectionDirectiveLiteral16(StringRef, SMLoc) { + return parseSectionSwitch("__TEXT","__literal16", + MachO::S_16BYTE_LITERALS, 16); } - bool ParseSectionDirectiveConstructor(StringRef, SMLoc) { - return ParseSectionSwitch("__TEXT","__constructor"); + bool parseSectionDirectiveConstructor(StringRef, SMLoc) { + return parseSectionSwitch("__TEXT","__constructor"); } - bool ParseSectionDirectiveDestructor(StringRef, SMLoc) { - return ParseSectionSwitch("__TEXT","__destructor"); + bool parseSectionDirectiveDestructor(StringRef, SMLoc) { + return parseSectionSwitch("__TEXT","__destructor"); } - bool ParseSectionDirectiveFVMLibInit0(StringRef, SMLoc) { - return ParseSectionSwitch("__TEXT","__fvmlib_init0"); + bool parseSectionDirectiveFVMLibInit0(StringRef, SMLoc) { + return parseSectionSwitch("__TEXT","__fvmlib_init0"); } - bool ParseSectionDirectiveFVMLibInit1(StringRef, SMLoc) { - return ParseSectionSwitch("__TEXT","__fvmlib_init1"); + bool parseSectionDirectiveFVMLibInit1(StringRef, SMLoc) { + return parseSectionSwitch("__TEXT","__fvmlib_init1"); } - bool ParseSectionDirectiveSymbolStub(StringRef, SMLoc) { - return ParseSectionSwitch("__TEXT","__symbol_stub", - MCSectionMachO::S_SYMBOL_STUBS | - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + bool parseSectionDirectiveSymbolStub(StringRef, SMLoc) { + return parseSectionSwitch("__TEXT","__symbol_stub", + MachO::S_SYMBOL_STUBS | + MachO::S_ATTR_PURE_INSTRUCTIONS, // FIXME: Different on PPC and ARM. 0, 16); } - bool ParseSectionDirectivePICSymbolStub(StringRef, SMLoc) { - return ParseSectionSwitch("__TEXT","__picsymbol_stub", - MCSectionMachO::S_SYMBOL_STUBS | - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 0, 26); + bool parseSectionDirectivePICSymbolStub(StringRef, SMLoc) { + return parseSectionSwitch("__TEXT","__picsymbol_stub", + MachO::S_SYMBOL_STUBS | + MachO::S_ATTR_PURE_INSTRUCTIONS, 0, 26); } - bool ParseSectionDirectiveData(StringRef, SMLoc) { - return ParseSectionSwitch("__DATA", "__data"); + bool parseSectionDirectiveData(StringRef, SMLoc) { + return parseSectionSwitch("__DATA", "__data"); } - bool ParseSectionDirectiveStaticData(StringRef, SMLoc) { - return ParseSectionSwitch("__DATA", "__static_data"); + bool parseSectionDirectiveStaticData(StringRef, SMLoc) { + return parseSectionSwitch("__DATA", "__static_data"); } - bool ParseSectionDirectiveNonLazySymbolPointers(StringRef, SMLoc) { - return ParseSectionSwitch("__DATA", "__nl_symbol_ptr", - MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, 4); + bool parseSectionDirectiveNonLazySymbolPointers(StringRef, SMLoc) { + return parseSectionSwitch("__DATA", "__nl_symbol_ptr", + MachO::S_NON_LAZY_SYMBOL_POINTERS, 4); } - bool ParseSectionDirectiveLazySymbolPointers(StringRef, SMLoc) { - return ParseSectionSwitch("__DATA", "__la_symbol_ptr", - MCSectionMachO::S_LAZY_SYMBOL_POINTERS, 4); + bool parseSectionDirectiveLazySymbolPointers(StringRef, SMLoc) { + return parseSectionSwitch("__DATA", "__la_symbol_ptr", + MachO::S_LAZY_SYMBOL_POINTERS, 4); } - bool ParseSectionDirectiveDyld(StringRef, SMLoc) { - return ParseSectionSwitch("__DATA", "__dyld"); + bool parseSectionDirectiveDyld(StringRef, SMLoc) { + return parseSectionSwitch("__DATA", "__dyld"); } - bool ParseSectionDirectiveModInitFunc(StringRef, SMLoc) { - return ParseSectionSwitch("__DATA", "__mod_init_func", - MCSectionMachO::S_MOD_INIT_FUNC_POINTERS, 4); + bool parseSectionDirectiveModInitFunc(StringRef, SMLoc) { + return parseSectionSwitch("__DATA", "__mod_init_func", + MachO::S_MOD_INIT_FUNC_POINTERS, 4); } - bool ParseSectionDirectiveModTermFunc(StringRef, SMLoc) { - return ParseSectionSwitch("__DATA", "__mod_term_func", - MCSectionMachO::S_MOD_TERM_FUNC_POINTERS, 4); + bool parseSectionDirectiveModTermFunc(StringRef, SMLoc) { + return parseSectionSwitch("__DATA", "__mod_term_func", + MachO::S_MOD_TERM_FUNC_POINTERS, 4); } - bool ParseSectionDirectiveConstData(StringRef, SMLoc) { - return ParseSectionSwitch("__DATA", "__const"); + bool parseSectionDirectiveConstData(StringRef, SMLoc) { + return parseSectionSwitch("__DATA", "__const"); } - bool ParseSectionDirectiveObjCClass(StringRef, SMLoc) { - return ParseSectionSwitch("__OBJC", "__class", - MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + bool parseSectionDirectiveObjCClass(StringRef, SMLoc) { + return parseSectionSwitch("__OBJC", "__class", + MachO::S_ATTR_NO_DEAD_STRIP); } - bool ParseSectionDirectiveObjCMetaClass(StringRef, SMLoc) { - return ParseSectionSwitch("__OBJC", "__meta_class", - MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + bool parseSectionDirectiveObjCMetaClass(StringRef, SMLoc) { + return parseSectionSwitch("__OBJC", "__meta_class", + MachO::S_ATTR_NO_DEAD_STRIP); } - bool ParseSectionDirectiveObjCCatClsMeth(StringRef, SMLoc) { - return ParseSectionSwitch("__OBJC", "__cat_cls_meth", - MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + bool parseSectionDirectiveObjCCatClsMeth(StringRef, SMLoc) { + return parseSectionSwitch("__OBJC", "__cat_cls_meth", + MachO::S_ATTR_NO_DEAD_STRIP); } - bool ParseSectionDirectiveObjCCatInstMeth(StringRef, SMLoc) { - return ParseSectionSwitch("__OBJC", "__cat_inst_meth", - MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + bool parseSectionDirectiveObjCCatInstMeth(StringRef, SMLoc) { + return parseSectionSwitch("__OBJC", "__cat_inst_meth", + MachO::S_ATTR_NO_DEAD_STRIP); } - bool ParseSectionDirectiveObjCProtocol(StringRef, SMLoc) { - return ParseSectionSwitch("__OBJC", "__protocol", - MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + bool parseSectionDirectiveObjCProtocol(StringRef, SMLoc) { + return parseSectionSwitch("__OBJC", "__protocol", + MachO::S_ATTR_NO_DEAD_STRIP); } - bool ParseSectionDirectiveObjCStringObject(StringRef, SMLoc) { - return ParseSectionSwitch("__OBJC", "__string_object", - MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + bool parseSectionDirectiveObjCStringObject(StringRef, SMLoc) { + return parseSectionSwitch("__OBJC", "__string_object", + MachO::S_ATTR_NO_DEAD_STRIP); } - bool ParseSectionDirectiveObjCClsMeth(StringRef, SMLoc) { - return ParseSectionSwitch("__OBJC", "__cls_meth", - MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + bool parseSectionDirectiveObjCClsMeth(StringRef, SMLoc) { + return parseSectionSwitch("__OBJC", "__cls_meth", + MachO::S_ATTR_NO_DEAD_STRIP); } - bool ParseSectionDirectiveObjCInstMeth(StringRef, SMLoc) { - return ParseSectionSwitch("__OBJC", "__inst_meth", - MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + bool parseSectionDirectiveObjCInstMeth(StringRef, SMLoc) { + return parseSectionSwitch("__OBJC", "__inst_meth", + MachO::S_ATTR_NO_DEAD_STRIP); } - bool ParseSectionDirectiveObjCClsRefs(StringRef, SMLoc) { - return ParseSectionSwitch("__OBJC", "__cls_refs", - MCSectionMachO::S_ATTR_NO_DEAD_STRIP | - MCSectionMachO::S_LITERAL_POINTERS, 4); + bool parseSectionDirectiveObjCClsRefs(StringRef, SMLoc) { + return parseSectionSwitch("__OBJC", "__cls_refs", + MachO::S_ATTR_NO_DEAD_STRIP | + MachO::S_LITERAL_POINTERS, 4); } - bool ParseSectionDirectiveObjCMessageRefs(StringRef, SMLoc) { - return ParseSectionSwitch("__OBJC", "__message_refs", - MCSectionMachO::S_ATTR_NO_DEAD_STRIP | - MCSectionMachO::S_LITERAL_POINTERS, 4); + bool parseSectionDirectiveObjCMessageRefs(StringRef, SMLoc) { + return parseSectionSwitch("__OBJC", "__message_refs", + MachO::S_ATTR_NO_DEAD_STRIP | + MachO::S_LITERAL_POINTERS, 4); } - bool ParseSectionDirectiveObjCSymbols(StringRef, SMLoc) { - return ParseSectionSwitch("__OBJC", "__symbols", - MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + bool parseSectionDirectiveObjCSymbols(StringRef, SMLoc) { + return parseSectionSwitch("__OBJC", "__symbols", + MachO::S_ATTR_NO_DEAD_STRIP); } - bool ParseSectionDirectiveObjCCategory(StringRef, SMLoc) { - return ParseSectionSwitch("__OBJC", "__category", - MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + bool parseSectionDirectiveObjCCategory(StringRef, SMLoc) { + return parseSectionSwitch("__OBJC", "__category", + MachO::S_ATTR_NO_DEAD_STRIP); } - bool ParseSectionDirectiveObjCClassVars(StringRef, SMLoc) { - return ParseSectionSwitch("__OBJC", "__class_vars", - MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + bool parseSectionDirectiveObjCClassVars(StringRef, SMLoc) { + return parseSectionSwitch("__OBJC", "__class_vars", + MachO::S_ATTR_NO_DEAD_STRIP); } - bool ParseSectionDirectiveObjCInstanceVars(StringRef, SMLoc) { - return ParseSectionSwitch("__OBJC", "__instance_vars", - MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + bool parseSectionDirectiveObjCInstanceVars(StringRef, SMLoc) { + return parseSectionSwitch("__OBJC", "__instance_vars", + MachO::S_ATTR_NO_DEAD_STRIP); } - bool ParseSectionDirectiveObjCModuleInfo(StringRef, SMLoc) { - return ParseSectionSwitch("__OBJC", "__module_info", - MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + bool parseSectionDirectiveObjCModuleInfo(StringRef, SMLoc) { + return parseSectionSwitch("__OBJC", "__module_info", + MachO::S_ATTR_NO_DEAD_STRIP); } - bool ParseSectionDirectiveObjCClassNames(StringRef, SMLoc) { - return ParseSectionSwitch("__TEXT", "__cstring", - MCSectionMachO::S_CSTRING_LITERALS); + bool parseSectionDirectiveObjCClassNames(StringRef, SMLoc) { + return parseSectionSwitch("__TEXT", "__cstring", + MachO::S_CSTRING_LITERALS); } - bool ParseSectionDirectiveObjCMethVarTypes(StringRef, SMLoc) { - return ParseSectionSwitch("__TEXT", "__cstring", - MCSectionMachO::S_CSTRING_LITERALS); + bool parseSectionDirectiveObjCMethVarTypes(StringRef, SMLoc) { + return parseSectionSwitch("__TEXT", "__cstring", + MachO::S_CSTRING_LITERALS); } - bool ParseSectionDirectiveObjCMethVarNames(StringRef, SMLoc) { - return ParseSectionSwitch("__TEXT", "__cstring", - MCSectionMachO::S_CSTRING_LITERALS); + bool parseSectionDirectiveObjCMethVarNames(StringRef, SMLoc) { + return parseSectionSwitch("__TEXT", "__cstring", + MachO::S_CSTRING_LITERALS); } - bool ParseSectionDirectiveObjCSelectorStrs(StringRef, SMLoc) { - return ParseSectionSwitch("__OBJC", "__selector_strs", - MCSectionMachO::S_CSTRING_LITERALS); + bool parseSectionDirectiveObjCSelectorStrs(StringRef, SMLoc) { + return parseSectionSwitch("__OBJC", "__selector_strs", + MachO::S_CSTRING_LITERALS); } - bool ParseSectionDirectiveTData(StringRef, SMLoc) { - return ParseSectionSwitch("__DATA", "__thread_data", - MCSectionMachO::S_THREAD_LOCAL_REGULAR); + bool parseSectionDirectiveTData(StringRef, SMLoc) { + return parseSectionSwitch("__DATA", "__thread_data", + MachO::S_THREAD_LOCAL_REGULAR); } - bool ParseSectionDirectiveText(StringRef, SMLoc) { - return ParseSectionSwitch("__TEXT", "__text", - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS); + bool parseSectionDirectiveText(StringRef, SMLoc) { + return parseSectionSwitch("__TEXT", "__text", + MachO::S_ATTR_PURE_INSTRUCTIONS); } - bool ParseSectionDirectiveTLV(StringRef, SMLoc) { - return ParseSectionSwitch("__DATA", "__thread_vars", - MCSectionMachO::S_THREAD_LOCAL_VARIABLES); + bool parseSectionDirectiveTLV(StringRef, SMLoc) { + return parseSectionSwitch("__DATA", "__thread_vars", + MachO::S_THREAD_LOCAL_VARIABLES); } - bool ParseSectionDirectiveIdent(StringRef, SMLoc) { + bool parseSectionDirectiveIdent(StringRef, SMLoc) { // Darwin silently ignores the .ident directive. getParser().eatToEndOfStatement(); return false; } - bool ParseSectionDirectiveThreadInitFunc(StringRef, SMLoc) { - return ParseSectionSwitch("__DATA", "__thread_init", - MCSectionMachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS); + bool parseSectionDirectiveThreadInitFunc(StringRef, SMLoc) { + return parseSectionSwitch("__DATA", "__thread_init", + MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS); } + bool parseVersionMin(StringRef, SMLoc); }; } // end anonymous namespace -bool DarwinAsmParser::ParseSectionSwitch(const char *Segment, +bool DarwinAsmParser::parseSectionSwitch(const char *Segment, const char *Section, unsigned TAA, unsigned Align, unsigned StubSize) { @@ -374,7 +379,7 @@ bool DarwinAsmParser::ParseSectionSwitch(const char *Segment, Lex(); // FIXME: Arch specific. - bool isText = TAA & MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS; + bool isText = TAA & MachO::S_ATTR_PURE_INSTRUCTIONS; getStreamer().SwitchSection(getContext().getMachOSection( Segment, Section, TAA, StubSize, isText ? SectionKind::getText() @@ -389,14 +394,14 @@ bool DarwinAsmParser::ParseSectionSwitch(const char *Segment, // is no good reason for someone to intentionally emit incorrectly sized // values into the implicitly aligned sections. if (Align) - getStreamer().EmitValueToAlignment(Align, 0, 1, 0); + getStreamer().EmitValueToAlignment(Align); return false; } -/// ParseDirectiveDesc +/// parseDirectiveDesc /// ::= .desc identifier , expression -bool DarwinAsmParser::ParseDirectiveDesc(StringRef, SMLoc) { +bool DarwinAsmParser::parseDirectiveDesc(StringRef, SMLoc) { StringRef Name; if (getParser().parseIdentifier(Name)) return TokError("expected identifier in directive"); @@ -423,15 +428,15 @@ bool DarwinAsmParser::ParseDirectiveDesc(StringRef, SMLoc) { return false; } -/// ParseDirectiveIndirectSymbol +/// parseDirectiveIndirectSymbol /// ::= .indirect_symbol identifier -bool DarwinAsmParser::ParseDirectiveIndirectSymbol(StringRef, SMLoc Loc) { +bool DarwinAsmParser::parseDirectiveIndirectSymbol(StringRef, SMLoc Loc) { const MCSectionMachO *Current = static_cast<const MCSectionMachO*>( getStreamer().getCurrentSection().first); - unsigned SectionType = Current->getType(); - if (SectionType != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS && - SectionType != MCSectionMachO::S_LAZY_SYMBOL_POINTERS && - SectionType != MCSectionMachO::S_SYMBOL_STUBS) + MachO::SectionType SectionType = Current->getType(); + if (SectionType != MachO::S_NON_LAZY_SYMBOL_POINTERS && + SectionType != MachO::S_LAZY_SYMBOL_POINTERS && + SectionType != MachO::S_SYMBOL_STUBS) return Error(Loc, "indirect symbol not in a symbol pointer or stub " "section"); @@ -456,9 +461,9 @@ bool DarwinAsmParser::ParseDirectiveIndirectSymbol(StringRef, SMLoc Loc) { return false; } -/// ParseDirectiveDumpOrLoad +/// parseDirectiveDumpOrLoad /// ::= ( .dump | .load ) "filename" -bool DarwinAsmParser::ParseDirectiveDumpOrLoad(StringRef Directive, +bool DarwinAsmParser::parseDirectiveDumpOrLoad(StringRef Directive, SMLoc IDLoc) { bool IsDump = Directive == ".dump"; if (getLexer().isNot(AsmToken::String)) @@ -481,7 +486,7 @@ bool DarwinAsmParser::ParseDirectiveDumpOrLoad(StringRef Directive, /// ParseDirectiveLinkerOption /// ::= .linker_option "string" ( , "string" )* -bool DarwinAsmParser::ParseDirectiveLinkerOption(StringRef IDVal, SMLoc) { +bool DarwinAsmParser::parseDirectiveLinkerOption(StringRef IDVal, SMLoc) { SmallVector<std::string, 4> Args; for (;;) { if (getLexer().isNot(AsmToken::String)) @@ -506,9 +511,9 @@ bool DarwinAsmParser::ParseDirectiveLinkerOption(StringRef IDVal, SMLoc) { return false; } -/// ParseDirectiveLsym +/// parseDirectiveLsym /// ::= .lsym identifier , expression -bool DarwinAsmParser::ParseDirectiveLsym(StringRef, SMLoc) { +bool DarwinAsmParser::parseDirectiveLsym(StringRef, SMLoc) { StringRef Name; if (getParser().parseIdentifier(Name)) return TokError("expected identifier in directive"); @@ -536,9 +541,9 @@ bool DarwinAsmParser::ParseDirectiveLsym(StringRef, SMLoc) { return TokError("directive '.lsym' is unsupported"); } -/// ParseDirectiveSection: +/// parseDirectiveSection: /// ::= .section identifier (',' identifier)* -bool DarwinAsmParser::ParseDirectiveSection(StringRef, SMLoc) { +bool DarwinAsmParser::parseDirectiveSection(StringRef, SMLoc) { SMLoc Loc = getLexer().getLoc(); StringRef SectionName; @@ -585,10 +590,10 @@ bool DarwinAsmParser::ParseDirectiveSection(StringRef, SMLoc) { /// ParseDirectivePushSection: /// ::= .pushsection identifier (',' identifier)* -bool DarwinAsmParser::ParseDirectivePushSection(StringRef S, SMLoc Loc) { +bool DarwinAsmParser::parseDirectivePushSection(StringRef S, SMLoc Loc) { getStreamer().PushSection(); - if (ParseDirectiveSection(S, Loc)) { + if (parseDirectiveSection(S, Loc)) { getStreamer().PopSection(); return true; } @@ -598,7 +603,7 @@ bool DarwinAsmParser::ParseDirectivePushSection(StringRef S, SMLoc Loc) { /// ParseDirectivePopSection: /// ::= .popsection -bool DarwinAsmParser::ParseDirectivePopSection(StringRef, SMLoc) { +bool DarwinAsmParser::parseDirectivePopSection(StringRef, SMLoc) { if (!getStreamer().PopSection()) return TokError(".popsection without corresponding .pushsection"); return false; @@ -606,17 +611,17 @@ bool DarwinAsmParser::ParseDirectivePopSection(StringRef, SMLoc) { /// ParseDirectivePrevious: /// ::= .previous -bool DarwinAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { +bool DarwinAsmParser::parseDirectivePrevious(StringRef DirName, SMLoc) { MCSectionSubPair PreviousSection = getStreamer().getPreviousSection(); - if (PreviousSection.first == NULL) - return TokError(".previous without corresponding .section"); + if (!PreviousSection.first) + return TokError(".previous without corresponding .section"); getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second); return false; } /// ParseDirectiveSecureLogUnique /// ::= .secure_log_unique ... message ... -bool DarwinAsmParser::ParseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) { +bool DarwinAsmParser::parseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) { StringRef LogMessage = getParser().parseStringToEndOfStatement(); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.secure_log_unique' directive"); @@ -626,15 +631,16 @@ bool DarwinAsmParser::ParseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) { // Get the secure log path. const char *SecureLogFile = getContext().getSecureLogFile(); - if (SecureLogFile == NULL) + if (!SecureLogFile) return Error(IDLoc, ".secure_log_unique used but AS_SECURE_LOG_FILE " "environment variable unset."); // Open the secure log file if we haven't already. raw_ostream *OS = getContext().getSecureLog(); - if (OS == NULL) { + if (!OS) { std::string Err; - OS = new raw_fd_ostream(SecureLogFile, Err, sys::fs::F_Append); + OS = new raw_fd_ostream(SecureLogFile, Err, + sys::fs::F_Append | sys::fs::F_Text); if (!Err.empty()) { delete OS; return Error(IDLoc, Twine("can't open secure log file: ") + @@ -644,7 +650,7 @@ bool DarwinAsmParser::ParseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) { } // Write the message. - int CurBuf = getSourceManager().FindBufferContainingLoc(IDLoc); + unsigned CurBuf = getSourceManager().FindBufferContainingLoc(IDLoc); *OS << getSourceManager().getBufferInfo(CurBuf).Buffer->getBufferIdentifier() << ":" << getSourceManager().FindLineNumber(IDLoc, CurBuf) << ":" << LogMessage + "\n"; @@ -656,7 +662,7 @@ bool DarwinAsmParser::ParseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) { /// ParseDirectiveSecureLogReset /// ::= .secure_log_reset -bool DarwinAsmParser::ParseDirectiveSecureLogReset(StringRef, SMLoc IDLoc) { +bool DarwinAsmParser::parseDirectiveSecureLogReset(StringRef, SMLoc IDLoc) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.secure_log_reset' directive"); @@ -667,9 +673,9 @@ bool DarwinAsmParser::ParseDirectiveSecureLogReset(StringRef, SMLoc IDLoc) { return false; } -/// ParseDirectiveSubsectionsViaSymbols +/// parseDirectiveSubsectionsViaSymbols /// ::= .subsections_via_symbols -bool DarwinAsmParser::ParseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) { +bool DarwinAsmParser::parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.subsections_via_symbols' directive"); @@ -682,7 +688,7 @@ bool DarwinAsmParser::ParseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) { /// ParseDirectiveTBSS /// ::= .tbss identifier, size, align -bool DarwinAsmParser::ParseDirectiveTBSS(StringRef, SMLoc) { +bool DarwinAsmParser::parseDirectiveTBSS(StringRef, SMLoc) { SMLoc IDLoc = getLexer().getLoc(); StringRef Name; if (getParser().parseIdentifier(Name)) @@ -728,7 +734,7 @@ bool DarwinAsmParser::ParseDirectiveTBSS(StringRef, SMLoc) { getStreamer().EmitTBSSSymbol(getContext().getMachOSection( "__DATA", "__thread_bss", - MCSectionMachO::S_THREAD_LOCAL_ZEROFILL, + MachO::S_THREAD_LOCAL_ZEROFILL, 0, SectionKind::getThreadBSS()), Sym, Size, 1 << Pow2Alignment); @@ -738,7 +744,7 @@ bool DarwinAsmParser::ParseDirectiveTBSS(StringRef, SMLoc) { /// ParseDirectiveZerofill /// ::= .zerofill segname , sectname [, identifier , size_expression [ /// , align_expression ]] -bool DarwinAsmParser::ParseDirectiveZerofill(StringRef, SMLoc) { +bool DarwinAsmParser::parseDirectiveZerofill(StringRef, SMLoc) { StringRef Segment; if (getParser().parseIdentifier(Segment)) return TokError("expected segment name after '.zerofill' directive"); @@ -757,7 +763,7 @@ bool DarwinAsmParser::ParseDirectiveZerofill(StringRef, SMLoc) { if (getLexer().is(AsmToken::EndOfStatement)) { // Create the zerofill section but no symbol getStreamer().EmitZerofill(getContext().getMachOSection( - Segment, Section, MCSectionMachO::S_ZEROFILL, + Segment, Section, MachO::S_ZEROFILL, 0, SectionKind::getBSS())); return false; } @@ -815,7 +821,7 @@ bool DarwinAsmParser::ParseDirectiveZerofill(StringRef, SMLoc) { // // FIXME: Arch specific. getStreamer().EmitZerofill(getContext().getMachOSection( - Segment, Section, MCSectionMachO::S_ZEROFILL, + Segment, Section, MachO::S_ZEROFILL, 0, SectionKind::getBSS()), Sym, Size, 1 << Pow2Alignment); @@ -824,7 +830,7 @@ bool DarwinAsmParser::ParseDirectiveZerofill(StringRef, SMLoc) { /// ParseDirectiveDataRegion /// ::= .data_region [ ( jt8 | jt16 | jt32 ) ] -bool DarwinAsmParser::ParseDirectiveDataRegion(StringRef, SMLoc) { +bool DarwinAsmParser::parseDirectiveDataRegion(StringRef, SMLoc) { if (getLexer().is(AsmToken::EndOfStatement)) { Lex(); getStreamer().EmitDataRegion(MCDR_DataRegion); @@ -849,7 +855,7 @@ bool DarwinAsmParser::ParseDirectiveDataRegion(StringRef, SMLoc) { /// ParseDirectiveDataRegionEnd /// ::= .end_data_region -bool DarwinAsmParser::ParseDirectiveDataRegionEnd(StringRef, SMLoc) { +bool DarwinAsmParser::parseDirectiveDataRegionEnd(StringRef, SMLoc) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.end_data_region' directive"); @@ -858,6 +864,50 @@ bool DarwinAsmParser::ParseDirectiveDataRegionEnd(StringRef, SMLoc) { return false; } +/// parseVersionMin +/// ::= .ios_version_min major,minor[,update] +/// ::= .macosx_version_min major,minor[,update] +bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc) { + int64_t Major = 0, Minor = 0, Update = 0; + int Kind = StringSwitch<int>(Directive) + .Case(".ios_version_min", MCVM_IOSVersionMin) + .Case(".macosx_version_min", MCVM_OSXVersionMin); + // Get the major version number. + if (getLexer().isNot(AsmToken::Integer)) + return TokError("invalid OS major version number"); + Major = getLexer().getTok().getIntVal(); + if (Major > 65535 || Major <= 0) + return TokError("invalid OS major version number"); + Lex(); + if (getLexer().isNot(AsmToken::Comma)) + return TokError("minor OS version number required, comma expected"); + Lex(); + // Get the minor version number. + if (getLexer().isNot(AsmToken::Integer)) + return TokError("invalid OS minor version number"); + Minor = getLexer().getTok().getIntVal(); + if (Minor > 255 || Minor < 0) + return TokError("invalid OS minor version number"); + Lex(); + // Get the update level, if specified + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getLexer().isNot(AsmToken::Comma)) + return TokError("invalid update specifier, comma expected"); + Lex(); + 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"); + Lex(); + } + + // We've parsed a correct version specifier, so send it to the streamer. + getStreamer().EmitVersionMin((MCVersionMinType)Kind, Major, Minor, Update); + + return false; +} + namespace llvm { MCAsmParserExtension *createDarwinAsmParser() { diff --git a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp index 8807975..e302004 100644 --- a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp @@ -37,7 +37,7 @@ class ELFAsmParser : public MCAsmParserExtension { public: ELFAsmParser() { BracketExpressionsSupported = true; } - virtual void Initialize(MCAsmParser &Parser) { + void Initialize(MCAsmParser &Parser) override { // Call the base implementation. this->MCAsmParserExtension::Initialize(Parser); @@ -150,7 +150,8 @@ public: private: bool ParseSectionName(StringRef &SectionName); - bool ParseSectionArguments(bool IsPush); + bool ParseSectionArguments(bool IsPush, SMLoc loc); + unsigned parseSunStyleSectionFlags(); }; } @@ -192,7 +193,7 @@ bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags, SectionKind Kind) { - const MCExpr *Subsection = 0; + const MCExpr *Subsection = nullptr; if (getLexer().isNot(AsmToken::EndOfStatement)) { if (getParser().parseExpression(Subsection)) return true; @@ -268,11 +269,37 @@ bool ELFAsmParser::ParseSectionName(StringRef &SectionName) { return false; } -static SectionKind computeSectionKind(unsigned Flags) { +static SectionKind computeSectionKind(unsigned Flags, unsigned ElemSize) { if (Flags & ELF::SHF_EXECINSTR) return SectionKind::getText(); if (Flags & ELF::SHF_TLS) return SectionKind::getThreadData(); + if (Flags & ELF::SHF_MERGE) { + if (Flags & ELF::SHF_STRINGS) { + switch (ElemSize) { + default: + break; + case 1: + return SectionKind::getMergeable1ByteCString(); + case 2: + return SectionKind::getMergeable2ByteCString(); + case 4: + return SectionKind::getMergeable4ByteCString(); + } + } else { + switch (ElemSize) { + default: + break; + case 4: + return SectionKind::getMergeableConst4(); + case 8: + return SectionKind::getMergeableConst8(); + case 16: + return SectionKind::getMergeableConst16(); + } + } + } + return SectionKind::getDataRel(); } @@ -322,10 +349,40 @@ static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) { return flags; } +unsigned ELFAsmParser::parseSunStyleSectionFlags() { + unsigned flags = 0; + while (getLexer().is(AsmToken::Hash)) { + Lex(); // Eat the #. + + if (!getLexer().is(AsmToken::Identifier)) + return -1U; + + StringRef flagId = getTok().getIdentifier(); + if (flagId == "alloc") + flags |= ELF::SHF_ALLOC; + else if (flagId == "execinstr") + flags |= ELF::SHF_EXECINSTR; + else if (flagId == "write") + flags |= ELF::SHF_WRITE; + else if (flagId == "tls") + flags |= ELF::SHF_TLS; + else + return -1U; + + Lex(); // Eat the flag. + + if (!getLexer().is(AsmToken::Comma)) + break; + Lex(); // Eat the comma. + } + return flags; +} + + bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) { getStreamer().PushSection(); - if (ParseSectionArguments(/*IsPush=*/true)) { + if (ParseSectionArguments(/*IsPush=*/true, loc)) { getStreamer().PopSection(); return true; } @@ -340,11 +397,11 @@ bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) { } // FIXME: This is a work in progress. -bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { - return ParseSectionArguments(/*IsPush=*/false); +bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) { + return ParseSectionArguments(/*IsPush=*/false, loc); } -bool ELFAsmParser::ParseSectionArguments(bool IsPush) { +bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) { StringRef SectionName; if (ParseSectionName(SectionName)) @@ -354,7 +411,7 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush) { int64_t Size = 0; StringRef GroupName; unsigned Flags = 0; - const MCExpr *Subsection = 0; + const MCExpr *Subsection = nullptr; bool UseLastGroup = false; // Set the defaults first. @@ -374,14 +431,20 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush) { goto EndStmt; Lex(); } - - if (getLexer().isNot(AsmToken::String)) - return TokError("expected string in directive"); - StringRef FlagsStr = getTok().getStringContents(); - Lex(); + unsigned extraFlags; + + if (getLexer().isNot(AsmToken::String)) { + if (!getContext().getAsmInfo()->usesSunStyleELFSectionSwitchSyntax() + || getLexer().isNot(AsmToken::Hash)) + return TokError("expected string in directive"); + extraFlags = parseSunStyleSectionFlags(); + } else { + StringRef FlagsStr = getTok().getStringContents(); + Lex(); + extraFlags = parseSectionFlags(FlagsStr, &UseLastGroup); + } - unsigned extraFlags = parseSectionFlags(FlagsStr, &UseLastGroup); if (extraFlags == -1U) return TokError("unknown flag"); Flags |= extraFlags; @@ -481,23 +544,50 @@ EndStmt: } } - SectionKind Kind = computeSectionKind(Flags); - getStreamer().SwitchSection(getContext().getELFSection(SectionName, Type, - Flags, Kind, Size, - GroupName), - Subsection); + SectionKind Kind = computeSectionKind(Flags, Size); + const MCSection *ELFSection = getContext().getELFSection( + SectionName, Type, Flags, Kind, Size, GroupName); + getStreamer().SwitchSection(ELFSection, Subsection); + + if (getContext().getGenDwarfForAssembly()) { + auto &Sections = getContext().getGenDwarfSectionSyms(); + auto InsertResult = Sections.insert( + std::make_pair(ELFSection, std::make_pair(nullptr, nullptr))); + if (InsertResult.second) { + if (getContext().getDwarfVersion() <= 2) + Warning(loc, "DWARF2 only supports one section per compilation unit"); + + MCSymbol *SectionStartSymbol = getContext().CreateTempSymbol(); + getStreamer().EmitLabel(SectionStartSymbol); + InsertResult.first->second.first = SectionStartSymbol; + } + } + return false; } bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { MCSectionSubPair PreviousSection = getStreamer().getPreviousSection(); - if (PreviousSection.first == NULL) + if (PreviousSection.first == nullptr) return TokError(".previous without corresponding .section"); getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second); return false; } +static MCSymbolAttr MCAttrForString(StringRef Type) { + return StringSwitch<MCSymbolAttr>(Type) + .Cases("STT_FUNC", "function", MCSA_ELF_TypeFunction) + .Cases("STT_OBJECT", "object", MCSA_ELF_TypeObject) + .Cases("STT_TLS", "tls_object", MCSA_ELF_TypeTLS) + .Cases("STT_COMMON", "common", MCSA_ELF_TypeCommon) + .Cases("STT_NOTYPE", "notype", MCSA_ELF_TypeNoType) + .Cases("STT_GNU_IFUNC", "gnu_indirect_function", + MCSA_ELF_TypeIndFunction) + .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject) + .Default(MCSA_Invalid); +} + /// ParseDirectiveELFType /// ::= .type identifier , STT_<TYPE_IN_UPPER_CASE> /// ::= .type identifier , #attribute @@ -512,53 +602,36 @@ bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) { // Handle the identifier as the key symbol. MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '.type' directive"); - Lex(); - - StringRef Type; - SMLoc TypeLoc; - MCSymbolAttr Attr; - if (getLexer().is(AsmToken::Identifier)) { - TypeLoc = getLexer().getLoc(); - if (getParser().parseIdentifier(Type)) - return TokError("expected symbol type in directive"); - Attr = StringSwitch<MCSymbolAttr>(Type) - .Case("STT_FUNC", MCSA_ELF_TypeFunction) - .Case("STT_OBJECT", MCSA_ELF_TypeObject) - .Case("STT_TLS", MCSA_ELF_TypeTLS) - .Case("STT_COMMON", MCSA_ELF_TypeCommon) - .Case("STT_NOTYPE", MCSA_ELF_TypeNoType) - .Case("STT_GNU_IFUNC", MCSA_ELF_TypeIndFunction) - .Default(MCSA_Invalid); - } else if (getLexer().is(AsmToken::Hash) || getLexer().is(AsmToken::At) || - getLexer().is(AsmToken::Percent) || - getLexer().is(AsmToken::String)) { - if (!getLexer().is(AsmToken::String)) - Lex(); + // NOTE the comma is optional in all cases. It is only documented as being + // optional in the first case, however, GAS will silently treat the comma as + // optional in all cases. Furthermore, although the documentation states that + // the first form only accepts STT_<TYPE_IN_UPPER_CASE>, in reality, GAS + // accepts both the upper case name as well as the lower case aliases. + if (getLexer().is(AsmToken::Comma)) + Lex(); - TypeLoc = getLexer().getLoc(); - if (getParser().parseIdentifier(Type)) - return TokError("expected symbol type in directive"); - Attr = StringSwitch<MCSymbolAttr>(Type) - .Case("function", MCSA_ELF_TypeFunction) - .Case("object", MCSA_ELF_TypeObject) - .Case("tls_object", MCSA_ELF_TypeTLS) - .Case("common", MCSA_ELF_TypeCommon) - .Case("notype", MCSA_ELF_TypeNoType) - .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject) - .Case("gnu_indirect_function", MCSA_ELF_TypeIndFunction) - .Default(MCSA_Invalid); - } else + if (getLexer().isNot(AsmToken::Identifier) && + getLexer().isNot(AsmToken::Hash) && getLexer().isNot(AsmToken::At) && + getLexer().isNot(AsmToken::Percent) && getLexer().isNot(AsmToken::String)) return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', " "'%<type>' or \"<type>\""); + if (getLexer().isNot(AsmToken::String) && + getLexer().isNot(AsmToken::Identifier)) + Lex(); + + SMLoc TypeLoc = getLexer().getLoc(); + + StringRef Type; + if (getParser().parseIdentifier(Type)) + return TokError("expected symbol type in directive"); + + MCSymbolAttr Attr = MCAttrForString(Type); if (Attr == MCSA_Invalid) return Error(TypeLoc, "unsupported attribute in '.type' directive"); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.type' directive"); - Lex(); getStreamer().EmitSymbolAttribute(Sym, Attr); @@ -590,7 +663,14 @@ bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) { if (getLexer().isNot(AsmToken::Comma)) return TokError("expected a comma"); + // ARM assembly uses @ for a comment... + // except when parsing the second parameter of the .symver directive. + // Force the next symbol to allow @ in the identifier, which is + // required for this directive and then reset it to its initial state. + const bool AllowAtInIdentifier = getLexer().getAllowAtInIdentifier(); + getLexer().setAllowAtInIdentifier(true); Lex(); + getLexer().setAllowAtInIdentifier(AllowAtInIdentifier); StringRef AliasName; if (getParser().parseIdentifier(AliasName)) @@ -660,7 +740,7 @@ bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) { } bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) { - const MCExpr *Subsection = 0; + const MCExpr *Subsection = nullptr; if (getLexer().isNot(AsmToken::EndOfStatement)) { if (getParser().parseExpression(Subsection)) return true; diff --git a/contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp b/contrib/llvm/lib/MC/MCParser/MCAsmLexer.cpp index 3867691..530814b 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() : CurTok(AsmToken::Error, StringRef()), - TokStart(0), SkipSpace(true) { + TokStart(nullptr), SkipSpace(true) { } MCAsmLexer::~MCAsmLexer() { diff --git a/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp index 6e1ebad..e417aa9 100644 --- a/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp @@ -17,7 +17,7 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; -MCAsmParser::MCAsmParser() : TargetParser(0), ShowParsedOperands(0) { +MCAsmParser::MCAsmParser() : TargetParser(nullptr), ShowParsedOperands(0) { } MCAsmParser::~MCAsmParser() { diff --git a/contrib/llvm/lib/MC/MCPureStreamer.cpp b/contrib/llvm/lib/MC/MCPureStreamer.cpp deleted file mode 100644 index f7bf002..0000000 --- a/contrib/llvm/lib/MC/MCPureStreamer.cpp +++ /dev/null @@ -1,235 +0,0 @@ -//===- lib/MC/MCPureStreamer.cpp - MC "Pure" Object Output ----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCCodeEmitter.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCObjectStreamer.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Support/ErrorHandling.h" - -using namespace llvm; - -namespace { - -class MCPureStreamer : public MCObjectStreamer { -private: - virtual void EmitInstToFragment(const MCInst &Inst); - virtual void EmitInstToData(const MCInst &Inst); - -public: - MCPureStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, - MCCodeEmitter *Emitter) - : MCObjectStreamer(Context, 0, TAB, OS, Emitter) {} - - /// @name MCStreamer Interface - /// @{ - - virtual void InitSections(); - virtual void InitToTextSection(); - virtual void EmitLabel(MCSymbol *Symbol); - virtual void EmitDebugLabel(MCSymbol *Symbol); - virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, - uint64_t Size = 0, unsigned ByteAlignment = 0); - virtual void EmitBytes(StringRef Data); - virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, - unsigned ValueSize = 1, - unsigned MaxBytesToEmit = 0); - virtual void EmitCodeAlignment(unsigned ByteAlignment, - unsigned MaxBytesToEmit = 0); - virtual bool EmitValueToOffset(const MCExpr *Offset, - unsigned char Value = 0); - virtual void FinishImpl(); - - - virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { - report_fatal_error("unsupported directive in pure streamer"); - return false; - } - virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) { - report_fatal_error("unsupported directive in pure streamer"); - } - virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment = 0) { - report_fatal_error("unsupported directive in pure streamer"); - } - virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { - report_fatal_error("unsupported directive in pure streamer"); - } - virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) { - report_fatal_error("unsupported directive in pure streamer"); - } - virtual void EmitThumbFunc(MCSymbol *Func) { - report_fatal_error("unsupported directive in pure streamer"); - } - virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) { - report_fatal_error("unsupported directive in pure streamer"); - } - virtual void EmitCOFFSymbolStorageClass(int StorageClass) { - report_fatal_error("unsupported directive in pure streamer"); - } - virtual void EmitCOFFSymbolType(int Type) { - report_fatal_error("unsupported directive in pure streamer"); - } - virtual void EndCOFFSymbolDef() { - report_fatal_error("unsupported directive in pure streamer"); - } - virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { - report_fatal_error("unsupported directive in pure streamer"); - } - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) { - report_fatal_error("unsupported directive in pure streamer"); - } - virtual void EmitFileDirective(StringRef Filename) { - report_fatal_error("unsupported directive in pure streamer"); - } - virtual void EmitIdent(StringRef IdentString) { - report_fatal_error("unsupported directive in pure streamer"); - } - virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, - StringRef Filename, unsigned CUID = 0) { - report_fatal_error("unsupported directive in pure streamer"); - } -}; - -} // end anonymous namespace. - -void MCPureStreamer::InitSections() { - InitToTextSection(); -} - -void MCPureStreamer::InitToTextSection() { - SwitchSection(getContext().getObjectFileInfo()->getTextSection()); -} - -void MCPureStreamer::EmitLabel(MCSymbol *Symbol) { - assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); - assert(getCurrentSection().first && "Cannot emit before setting section!"); - - AssignSection(Symbol, getCurrentSection().first); - - MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); - - // We have to create a new fragment if this is an atom defining symbol, - // fragments cannot span atoms. - if (getAssembler().isSymbolLinkerVisible(SD.getSymbol())) - insert(new MCDataFragment()); - - // FIXME: This is wasteful, we don't necessarily need to create a data - // fragment. Instead, we should mark the symbol as pointing into the data - // fragment if it exists, otherwise we should just queue the label and set its - // fragment pointer when we emit the next fragment. - MCDataFragment *F = getOrCreateDataFragment(); - assert(!SD.getFragment() && "Unexpected fragment on symbol data!"); - SD.setFragment(F); - SD.setOffset(F->getContents().size()); -} - - -void MCPureStreamer::EmitDebugLabel(MCSymbol *Symbol) { - EmitLabel(Symbol); -} - -void MCPureStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment) { - report_fatal_error("not yet implemented in pure streamer"); -} - -void MCPureStreamer::EmitBytes(StringRef Data) { - // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into - // MCObjectStreamer. - getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end()); -} - -void MCPureStreamer::EmitValueToAlignment(unsigned ByteAlignment, - int64_t Value, unsigned ValueSize, - unsigned MaxBytesToEmit) { - // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into - // MCObjectStreamer. - if (MaxBytesToEmit == 0) - MaxBytesToEmit = ByteAlignment; - insert(new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit)); - - // Update the maximum alignment on the current section if necessary. - if (ByteAlignment > getCurrentSectionData()->getAlignment()) - getCurrentSectionData()->setAlignment(ByteAlignment); -} - -void MCPureStreamer::EmitCodeAlignment(unsigned ByteAlignment, - unsigned MaxBytesToEmit) { - // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into - // MCObjectStreamer. - if (MaxBytesToEmit == 0) - MaxBytesToEmit = ByteAlignment; - MCAlignFragment *F = new MCAlignFragment(ByteAlignment, 0, 1, MaxBytesToEmit); - insert(F); - F->setEmitNops(true); - - // Update the maximum alignment on the current section if necessary. - if (ByteAlignment > getCurrentSectionData()->getAlignment()) - getCurrentSectionData()->setAlignment(ByteAlignment); -} - -bool MCPureStreamer::EmitValueToOffset(const MCExpr *Offset, - unsigned char Value) { - insert(new MCOrgFragment(*Offset, Value)); - return false; -} - -void MCPureStreamer::EmitInstToFragment(const MCInst &Inst) { - MCRelaxableFragment *IF = new MCRelaxableFragment(Inst); - insert(IF); - - // Add the fixups and data. - // - // FIXME: Revisit this design decision when relaxation is done, we may be - // able to get away with not storing any extra data in the MCInst. - SmallVector<MCFixup, 4> Fixups; - SmallString<256> Code; - raw_svector_ostream VecOS(Code); - getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups); - VecOS.flush(); - - IF->getContents() = Code; - IF->getFixups() = Fixups; -} - -void MCPureStreamer::EmitInstToData(const MCInst &Inst) { - MCDataFragment *DF = getOrCreateDataFragment(); - - SmallVector<MCFixup, 4> Fixups; - SmallString<256> Code; - raw_svector_ostream VecOS(Code); - getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups); - VecOS.flush(); - - // Add the fixups and data. - for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { - Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); - DF->getFixups().push_back(Fixups[i]); - } - DF->getContents().append(Code.begin(), Code.end()); -} - -void MCPureStreamer::FinishImpl() { - // FIXME: Handle DWARF tables? - - this->MCObjectStreamer::FinishImpl(); -} - -MCStreamer *llvm::createPureStreamer(MCContext &Context, MCAsmBackend &MAB, - raw_ostream &OS, MCCodeEmitter *CE) { - return new MCPureStreamer(Context, MAB, OS, CE); -} diff --git a/contrib/llvm/lib/MC/MCRelocationInfo.cpp b/contrib/llvm/lib/MC/MCRelocationInfo.cpp index 53c48ded..a00c009 100644 --- a/contrib/llvm/lib/MC/MCRelocationInfo.cpp +++ b/contrib/llvm/lib/MC/MCRelocationInfo.cpp @@ -8,9 +8,9 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCRelocationInfo.h" +#include "llvm-c/Disassembler.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/TargetRegistry.h" -#include "llvm-c/Disassembler.h" using namespace llvm; @@ -23,14 +23,14 @@ MCRelocationInfo::~MCRelocationInfo() { const MCExpr * MCRelocationInfo::createExprForRelocation(object::RelocationRef Rel) { - return 0; + return nullptr; } const MCExpr * MCRelocationInfo::createExprForCAPIVariantKind(const MCExpr *SubExpr, unsigned VariantKind) { if (VariantKind != LLVMDisassembler_VariantKind_None) - return 0; + return nullptr; return SubExpr; } diff --git a/contrib/llvm/lib/MC/MCSectionCOFF.cpp b/contrib/llvm/lib/MC/MCSectionCOFF.cpp index 64aa2c5..fc2bd36 100644 --- a/contrib/llvm/lib/MC/MCSectionCOFF.cpp +++ b/contrib/llvm/lib/MC/MCSectionCOFF.cpp @@ -20,6 +20,8 @@ MCSectionCOFF::~MCSectionCOFF() {} // anchor. // should be printed before the section name bool MCSectionCOFF::ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const { + if (COMDATSymbol) + return false; // FIXME: Does .section .bss/.data/.text work everywhere?? if (Name == ".text" || Name == ".data" || Name == ".bss") @@ -28,14 +30,9 @@ bool MCSectionCOFF::ShouldOmitSectionDirective(StringRef Name, return false; } -void MCSectionCOFF::setSelection(int Selection, - const MCSectionCOFF *Assoc) const { +void MCSectionCOFF::setSelection(int Selection) const { assert(Selection != 0 && "invalid COMDAT selection type"); - assert((Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) == - (Assoc != 0) && - "associative COMDAT section must have an associated section"); this->Selection = Selection; - this->Assoc = Assoc; Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; } @@ -52,42 +49,50 @@ void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, OS << "\t.section\t" << getSectionName() << ",\""; if (getKind().isText()) OS << 'x'; + else if (getKind().isBSS()) + OS << 'b'; if (getKind().isWriteable()) OS << 'w'; else OS << 'r'; if (getCharacteristics() & COFF::IMAGE_SCN_MEM_DISCARDABLE) OS << 'n'; - OS << "\"\n"; + if (getCharacteristics() & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) + OS << 'd'; + OS << '"'; if (getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) { + OS << ","; switch (Selection) { case COFF::IMAGE_COMDAT_SELECT_NODUPLICATES: - OS << "\t.linkonce one_only\n"; + OS << "one_only,"; break; case COFF::IMAGE_COMDAT_SELECT_ANY: - OS << "\t.linkonce discard\n"; + OS << "discard,"; break; case COFF::IMAGE_COMDAT_SELECT_SAME_SIZE: - OS << "\t.linkonce same_size\n"; + OS << "same_size,"; break; case COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH: - OS << "\t.linkonce same_contents\n"; + OS << "same_contents,"; break; case COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE: - OS << "\t.linkonce associative " << Assoc->getSectionName() << "\n"; + OS << "associative,"; break; case COFF::IMAGE_COMDAT_SELECT_LARGEST: - OS << "\t.linkonce largest\n"; + OS << "largest,"; break; case COFF::IMAGE_COMDAT_SELECT_NEWEST: - OS << "\t.linkonce newest\n"; + OS << "newest,"; break; default: assert (0 && "unsupported COFF selection type"); break; } + assert(COMDATSymbol); + OS << *COMDATSymbol; } + OS << '\n'; } bool MCSectionCOFF::UseCodeAlign() const { diff --git a/contrib/llvm/lib/MC/MCSectionMachO.cpp b/contrib/llvm/lib/MC/MCSectionMachO.cpp index 8704513..46beda4 100644 --- a/contrib/llvm/lib/MC/MCSectionMachO.cpp +++ b/contrib/llvm/lib/MC/MCSectionMachO.cpp @@ -18,9 +18,9 @@ using namespace llvm; /// section type list. static const struct { const char *AssemblerName, *EnumName; -} SectionTypeDescriptors[MCSectionMachO::LAST_KNOWN_SECTION_TYPE+1] = { +} SectionTypeDescriptors[MachO::LAST_KNOWN_SECTION_TYPE+1] = { { "regular", "S_REGULAR" }, // 0x00 - { 0, "S_ZEROFILL" }, // 0x01 + { nullptr, "S_ZEROFILL" }, // 0x01 { "cstring_literals", "S_CSTRING_LITERALS" }, // 0x02 { "4byte_literals", "S_4BYTE_LITERALS" }, // 0x03 { "8byte_literals", "S_8BYTE_LITERALS" }, // 0x04 @@ -31,11 +31,11 @@ static const struct { { "mod_init_funcs", "S_MOD_INIT_FUNC_POINTERS" }, // 0x09 { "mod_term_funcs", "S_MOD_TERM_FUNC_POINTERS" }, // 0x0A { "coalesced", "S_COALESCED" }, // 0x0B - { 0, /*FIXME??*/ "S_GB_ZEROFILL" }, // 0x0C + { nullptr, /*FIXME??*/ "S_GB_ZEROFILL" }, // 0x0C { "interposing", "S_INTERPOSING" }, // 0x0D { "16byte_literals", "S_16BYTE_LITERALS" }, // 0x0E - { 0, /*FIXME??*/ "S_DTRACE_DOF" }, // 0x0F - { 0, /*FIXME??*/ "S_LAZY_DYLIB_SYMBOL_POINTERS" }, // 0x10 + { nullptr, /*FIXME??*/ "S_DTRACE_DOF" }, // 0x0F + { nullptr, /*FIXME??*/ "S_LAZY_DYLIB_SYMBOL_POINTERS" }, // 0x10 { "thread_local_regular", "S_THREAD_LOCAL_REGULAR" }, // 0x11 { "thread_local_zerofill", "S_THREAD_LOCAL_ZEROFILL" }, // 0x12 { "thread_local_variables", "S_THREAD_LOCAL_VARIABLES" }, // 0x13 @@ -48,14 +48,13 @@ static const struct { /// SectionAttrDescriptors - This is an array of descriptors for section /// attributes. Unlike the SectionTypeDescriptors, this is not directly indexed -/// by attribute, instead it is searched. The last entry has an AttrFlagEnd -/// AttrFlag value. +/// by attribute, instead it is searched. static const struct { unsigned AttrFlag; const char *AssemblerName, *EnumName; } SectionAttrDescriptors[] = { #define ENTRY(ASMNAME, ENUM) \ - { MCSectionMachO::ENUM, ASMNAME, #ENUM }, + { MachO::ENUM, ASMNAME, #ENUM }, ENTRY("pure_instructions", S_ATTR_PURE_INSTRUCTIONS) ENTRY("no_toc", S_ATTR_NO_TOC) ENTRY("strip_static_syms", S_ATTR_STRIP_STATIC_SYMS) @@ -63,13 +62,11 @@ ENTRY("no_dead_strip", S_ATTR_NO_DEAD_STRIP) ENTRY("live_support", S_ATTR_LIVE_SUPPORT) ENTRY("self_modifying_code", S_ATTR_SELF_MODIFYING_CODE) ENTRY("debug", S_ATTR_DEBUG) -ENTRY(0 /*FIXME*/, S_ATTR_SOME_INSTRUCTIONS) -ENTRY(0 /*FIXME*/, S_ATTR_EXT_RELOC) -ENTRY(0 /*FIXME*/, S_ATTR_LOC_RELOC) +ENTRY(nullptr /*FIXME*/, S_ATTR_SOME_INSTRUCTIONS) +ENTRY(nullptr /*FIXME*/, S_ATTR_EXT_RELOC) +ENTRY(nullptr /*FIXME*/, S_ATTR_LOC_RELOC) #undef ENTRY - { 0, "none", 0 }, // used if section has no attributes but has a stub size -#define AttrFlagEnd 0xffffffff // non legal value, multiple attribute bits set - { AttrFlagEnd, 0, 0 } + { 0, "none", nullptr }, // used if section has no attributes but has a stub size }; MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section, @@ -102,8 +99,8 @@ void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI, return; } - unsigned SectionType = TAA & MCSectionMachO::SECTION_TYPE; - assert(SectionType <= MCSectionMachO::LAST_KNOWN_SECTION_TYPE && + MachO::SectionType SectionType = getType(); + assert(SectionType <= MachO::LAST_KNOWN_SECTION_TYPE && "Invalid SectionType specified!"); if (SectionTypeDescriptors[SectionType].AssemblerName) { @@ -116,7 +113,7 @@ void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI, } // If we don't have any attributes, we're done. - unsigned SectionAttrs = TAA & MCSectionMachO::SECTION_ATTRIBUTES; + unsigned SectionAttrs = TAA & MachO::SECTION_ATTRIBUTES; if (SectionAttrs == 0) { // If we have a S_SYMBOL_STUBS size specified, print it along with 'none' as // the attribute specifier. @@ -155,21 +152,13 @@ void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI, } bool MCSectionMachO::UseCodeAlign() const { - return hasAttribute(MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS); + return hasAttribute(MachO::S_ATTR_PURE_INSTRUCTIONS); } bool MCSectionMachO::isVirtualSection() const { - return (getType() == MCSectionMachO::S_ZEROFILL || - getType() == MCSectionMachO::S_GB_ZEROFILL || - getType() == MCSectionMachO::S_THREAD_LOCAL_ZEROFILL); -} - -/// StripSpaces - This removes leading and trailing spaces from the StringRef. -static void StripSpaces(StringRef &Str) { - while (!Str.empty() && isspace(static_cast<unsigned char>(Str[0]))) - Str = Str.substr(1); - while (!Str.empty() && isspace(static_cast<unsigned char>(Str.back()))) - Str = Str.substr(0, Str.size()-1); + return (getType() == MachO::S_ZEROFILL || + getType() == MachO::S_GB_ZEROFILL || + getType() == MachO::S_THREAD_LOCAL_ZEROFILL); } /// ParseSectionSpecifier - Parse the section specifier indicated by "Spec". @@ -184,118 +173,95 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In. bool &TAAParsed, // Out. unsigned &StubSize) { // Out. TAAParsed = false; - // Find the first comma. - std::pair<StringRef, StringRef> Comma = Spec.split(','); - - // If there is no comma, we fail. - if (Comma.second.empty()) - return "mach-o section specifier requires a segment and section " - "separated by a comma"; - // Capture segment, remove leading and trailing whitespace. - Segment = Comma.first; - StripSpaces(Segment); + SmallVector<StringRef, 5> SplitSpec; + Spec.split(SplitSpec, ","); + // Remove leading and trailing whitespace. + auto GetEmptyOrTrim = [&SplitSpec](size_t Idx) -> StringRef { + return SplitSpec.size() > Idx ? SplitSpec[Idx].trim() : StringRef(); + }; + Segment = GetEmptyOrTrim(0); + Section = GetEmptyOrTrim(1); + StringRef SectionType = GetEmptyOrTrim(2); + StringRef Attrs = GetEmptyOrTrim(3); + StringRef StubSizeStr = GetEmptyOrTrim(4); // Verify that the segment is present and not too long. if (Segment.empty() || Segment.size() > 16) return "mach-o section specifier requires a segment whose length is " "between 1 and 16 characters"; - // Split the section name off from any attributes if present. - Comma = Comma.second.split(','); - - // Capture section, remove leading and trailing whitespace. - Section = Comma.first; - StripSpaces(Section); - // Verify that the section is present and not too long. - if (Section.empty() || Section.size() > 16) + if (Section.empty()) + return "mach-o section specifier requires a segment and section " + "separated by a comma"; + + if (Section.size() > 16) return "mach-o section specifier requires a section whose length is " "between 1 and 16 characters"; // If there is no comma after the section, we're done. TAA = 0; StubSize = 0; - if (Comma.second.empty()) + if (SectionType.empty()) return ""; - // Otherwise, we need to parse the section type and attributes. - Comma = Comma.second.split(','); - - // Get the section type. - StringRef SectionType = Comma.first; - StripSpaces(SectionType); - // Figure out which section type it is. - unsigned TypeID; - for (TypeID = 0; TypeID !=MCSectionMachO::LAST_KNOWN_SECTION_TYPE+1; ++TypeID) - if (SectionTypeDescriptors[TypeID].AssemblerName && - SectionType == SectionTypeDescriptors[TypeID].AssemblerName) - break; + auto TypeDescriptor = std::find_if( + std::begin(SectionTypeDescriptors), std::end(SectionTypeDescriptors), + [&](decltype(*SectionTypeDescriptors) &Descriptor) { + return Descriptor.AssemblerName && + SectionType == Descriptor.AssemblerName; + }); // If we didn't find the section type, reject it. - if (TypeID > MCSectionMachO::LAST_KNOWN_SECTION_TYPE) + if (TypeDescriptor == std::end(SectionTypeDescriptors)) return "mach-o section specifier uses an unknown section type"; // Remember the TypeID. - TAA = TypeID; + TAA = TypeDescriptor - std::begin(SectionTypeDescriptors); TAAParsed = true; // If we have no comma after the section type, there are no attributes. - if (Comma.second.empty()) { + if (Attrs.empty()) { // S_SYMBOL_STUBS always require a symbol stub size specifier. - if (TAA == MCSectionMachO::S_SYMBOL_STUBS) + if (TAA == MachO::S_SYMBOL_STUBS) return "mach-o section specifier of type 'symbol_stubs' requires a size " "specifier"; return ""; } - // Otherwise, we do have some attributes. Split off the size specifier if - // present. - Comma = Comma.second.split(','); - StringRef Attrs = Comma.first; - // The attribute list is a '+' separated list of attributes. - std::pair<StringRef, StringRef> Plus = Attrs.split('+'); - - while (1) { - StringRef Attr = Plus.first; - StripSpaces(Attr); - - // Look up the attribute. - for (unsigned i = 0; ; ++i) { - if (SectionAttrDescriptors[i].AttrFlag == AttrFlagEnd) - return "mach-o section specifier has invalid attribute"; - - if (SectionAttrDescriptors[i].AssemblerName && - Attr == SectionAttrDescriptors[i].AssemblerName) { - TAA |= SectionAttrDescriptors[i].AttrFlag; - break; - } - } - - if (Plus.second.empty()) break; - Plus = Plus.second.split('+'); - }; + SmallVector<StringRef, 1> SectionAttrs; + Attrs.split(SectionAttrs, "+", /*MaxSplit=*/-1, /*KeepEmpty=*/false); + + for (StringRef &SectionAttr : SectionAttrs) { + auto AttrDescriptorI = std::find_if( + std::begin(SectionAttrDescriptors), std::end(SectionAttrDescriptors), + [&](decltype(*SectionAttrDescriptors) &Descriptor) { + return Descriptor.AssemblerName && + SectionAttr.trim() == Descriptor.AssemblerName; + }); + if (AttrDescriptorI == std::end(SectionAttrDescriptors)) + return "mach-o section specifier has invalid attribute"; + + TAA |= AttrDescriptorI->AttrFlag; + } // Okay, we've parsed the section attributes, see if we have a stub size spec. - if (Comma.second.empty()) { + if (StubSizeStr.empty()) { // S_SYMBOL_STUBS always require a symbol stub size specifier. - if (TAA == MCSectionMachO::S_SYMBOL_STUBS) + if (TAA == MachO::S_SYMBOL_STUBS) return "mach-o section specifier of type 'symbol_stubs' requires a size " "specifier"; return ""; } // If we have a stub size spec, we must have a sectiontype of S_SYMBOL_STUBS. - if ((TAA & MCSectionMachO::SECTION_TYPE) != MCSectionMachO::S_SYMBOL_STUBS) + if ((TAA & MachO::SECTION_TYPE) != MachO::S_SYMBOL_STUBS) return "mach-o section specifier cannot have a stub size specified because " "it does not have type 'symbol_stubs'"; - // Okay, if we do, it must be a number. - StringRef StubSizeStr = Comma.second; - StripSpaces(StubSizeStr); - // Convert the stub size from a string to an integer. if (StubSizeStr.getAsInteger(0, StubSize)) return "mach-o section specifier has a malformed stub size"; diff --git a/contrib/llvm/lib/MC/MCStreamer.cpp b/contrib/llvm/lib/MC/MCStreamer.cpp index 2e1d69b..46e80cc 100644 --- a/contrib/llvm/lib/MC/MCStreamer.cpp +++ b/contrib/llvm/lib/MC/MCStreamer.cpp @@ -14,8 +14,10 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCWin64EH.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/raw_ostream.h" @@ -24,30 +26,32 @@ using namespace llvm; // Pin the vtables to this file. MCTargetStreamer::~MCTargetStreamer() {} -void ARMTargetStreamer::anchor() {} -MCStreamer::MCStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer) - : Context(Ctx), TargetStreamer(TargetStreamer), EmitEHFrame(true), - EmitDebugFrame(false), CurrentW64UnwindInfo(0), LastSymbol(0), - AutoInitSections(false) { +MCTargetStreamer::MCTargetStreamer(MCStreamer &S) : Streamer(S) { + S.setTargetStreamer(this); +} + +void MCTargetStreamer::emitLabel(MCSymbol *Symbol) {} + +void MCTargetStreamer::finish() {} + +void MCTargetStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {} + +MCStreamer::MCStreamer(MCContext &Ctx) + : Context(Ctx), CurrentWinFrameInfo(nullptr) { SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>()); - if (TargetStreamer) - TargetStreamer->setStreamer(this); } MCStreamer::~MCStreamer() { - for (unsigned i = 0; i < getNumW64UnwindInfos(); ++i) - delete W64UnwindInfos[i]; + for (unsigned i = 0; i < getNumWinFrameInfos(); ++i) + delete WinFrameInfos[i]; } void MCStreamer::reset() { - for (unsigned i = 0; i < getNumW64UnwindInfos(); ++i) - delete W64UnwindInfos[i]; - W64UnwindInfos.clear(); - EmitEHFrame = true; - EmitDebugFrame = false; - CurrentW64UnwindInfo = 0; - LastSymbol = 0; + for (unsigned i = 0; i < getNumWinFrameInfos(); ++i) + delete WinFrameInfos[i]; + WinFrameInfos.clear(); + CurrentWinFrameInfo = nullptr; SectionStack.clear(); SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>()); } @@ -66,8 +70,8 @@ const MCExpr *MCStreamer::BuildSymbolDiff(MCContext &Context, } const MCExpr *MCStreamer::ForceExpAbs(const MCExpr* Expr) { - if (Context.getAsmInfo()->hasAggressiveSymbolFolding() || - isa<MCSymbolRefExpr>(Expr)) + assert(!isa<MCSymbolRefExpr>(Expr)); + if (Context.getAsmInfo()->hasAggressiveSymbolFolding()) return Expr; MCSymbol *ABS = Context.CreateTempSymbol(); @@ -80,11 +84,12 @@ raw_ostream &MCStreamer::GetCommentOS() { return nulls(); } +void MCStreamer::emitRawComment(const Twine &T, bool TabPrefix) {} + void MCStreamer::generateCompactUnwindEncodings(MCAsmBackend *MAB) { - for (std::vector<MCDwarfFrameInfo>::iterator I = FrameInfos.begin(), - E = FrameInfos.end(); I != E; ++I) - I->CompactUnwindEncoding = - (MAB ? MAB->generateCompactUnwindEncoding(I->Instructions) : 0); + for (auto &FI : DwarfFrameInfos) + FI.CompactUnwindEncoding = + (MAB ? MAB->generateCompactUnwindEncoding(FI.Instructions) : 0); } void MCStreamer::EmitDwarfSetLineAddr(int64_t LineDelta, @@ -138,12 +143,20 @@ void MCStreamer::EmitAbsValue(const MCExpr *Value, unsigned Size) { } -void MCStreamer::EmitValue(const MCExpr *Value, unsigned Size) { - EmitValueImpl(Value, Size); +void MCStreamer::EmitValue(const MCExpr *Value, unsigned Size, + const SMLoc &Loc) { + EmitValueImpl(Value, Size, Loc); } -void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size) { - EmitValueImpl(MCSymbolRefExpr::Create(Sym, getContext()), Size); +void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size, + bool IsSectionRelative) { + assert((!IsSectionRelative || Size == 4) && + "SectionRelative value requires 4-bytes"); + + if (!IsSectionRelative) + EmitValueImpl(MCSymbolRefExpr::Create(Sym, getContext()), Size); + else + EmitCOFFSecRel32(Sym); } void MCStreamer::EmitGPRel64Value(const MCExpr *Value) { @@ -167,10 +180,10 @@ void MCStreamer::EmitZeros(uint64_t NumBytes) { EmitFill(NumBytes, 0); } -bool MCStreamer::EmitDwarfFileDirective(unsigned FileNo, - StringRef Directory, - StringRef Filename, unsigned CUID) { - return getContext().GetDwarfFile(Directory, Filename, FileNo, CUID) == 0; +unsigned MCStreamer::EmitDwarfFileDirective(unsigned FileNo, + StringRef Directory, + StringRef Filename, unsigned CUID) { + return getContext().GetDwarfFile(Directory, Filename, FileNo, CUID); } void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, @@ -182,14 +195,24 @@ void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, Discriminator); } -MCDwarfFrameInfo *MCStreamer::getCurrentFrameInfo() { - if (FrameInfos.empty()) - return 0; - return &FrameInfos.back(); +MCSymbol *MCStreamer::getDwarfLineTableSymbol(unsigned CUID) { + MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID); + if (!Table.getLabel()) { + StringRef Prefix = Context.getAsmInfo()->getPrivateGlobalPrefix(); + Table.setLabel( + Context.GetOrCreateSymbol(Prefix + "line_table_start" + Twine(CUID))); + } + return Table.getLabel(); +} + +MCDwarfFrameInfo *MCStreamer::getCurrentDwarfFrameInfo() { + if (DwarfFrameInfos.empty()) + return nullptr; + return &DwarfFrameInfos.back(); } -void MCStreamer::EnsureValidFrame() { - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); +void MCStreamer::EnsureValidDwarfFrame() { + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); if (!CurFrame || CurFrame->End) report_fatal_error("No open frame"); } @@ -198,6 +221,10 @@ void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) { } +void MCStreamer::InitSections() { + SwitchSection(getContext().getObjectFileInfo()->getTextSection()); +} + void MCStreamer::AssignSection(MCSymbol *Symbol, const MCSection *Section) { if (Section) Symbol->setSection(*Section); @@ -213,71 +240,51 @@ void MCStreamer::EmitLabel(MCSymbol *Symbol) { assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); assert(getCurrentSection().first && "Cannot emit before setting section!"); AssignSection(Symbol, getCurrentSection().first); - LastSymbol = Symbol; -} -void MCStreamer::EmitDebugLabel(MCSymbol *Symbol) { - assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); - assert(getCurrentSection().first && "Cannot emit before setting section!"); - AssignSection(Symbol, getCurrentSection().first); - LastSymbol = Symbol; + MCTargetStreamer *TS = getTargetStreamer(); + if (TS) + TS->emitLabel(Symbol); } void MCStreamer::EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding) { - EnsureValidFrame(); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + EnsureValidDwarfFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->CompactUnwindEncoding = CompactUnwindEncoding; } void MCStreamer::EmitCFISections(bool EH, bool Debug) { assert(EH || Debug); - EmitEHFrame = EH; - EmitDebugFrame = Debug; } -void MCStreamer::EmitCFIStartProc() { - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); +void MCStreamer::EmitCFIStartProc(bool IsSimple) { + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); if (CurFrame && !CurFrame->End) report_fatal_error("Starting a frame before finishing the previous one!"); MCDwarfFrameInfo Frame; + Frame.IsSimple = IsSimple; EmitCFIStartProcImpl(Frame); - FrameInfos.push_back(Frame); + DwarfFrameInfos.push_back(Frame); } void MCStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { } -void MCStreamer::RecordProcStart(MCDwarfFrameInfo &Frame) { - Frame.Function = LastSymbol; - // If the function is externally visible, we need to create a local - // symbol to avoid relocations. - StringRef Prefix = getContext().getAsmInfo()->getPrivateGlobalPrefix(); - if (LastSymbol && LastSymbol->getName().startswith(Prefix)) { - Frame.Begin = LastSymbol; - } else { - Frame.Begin = getContext().CreateTempSymbol(); - EmitLabel(Frame.Begin); - } -} - void MCStreamer::EmitCFIEndProc() { - EnsureValidFrame(); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + EnsureValidDwarfFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); EmitCFIEndProcImpl(*CurFrame); } void MCStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { -} - -void MCStreamer::RecordProcEnd(MCDwarfFrameInfo &Frame) { - Frame.End = getContext().CreateTempSymbol(); - EmitLabel(Frame.End); + // Put a dummy non-null value in Frame.End to mark that this frame has been + // closed. + Frame.End = (MCSymbol *) 1; } MCSymbol *MCStreamer::EmitCFICommon() { - EnsureValidFrame(); + EnsureValidDwarfFrame(); MCSymbol *Label = getContext().CreateTempSymbol(); EmitLabel(Label); return Label; @@ -287,7 +294,7 @@ void MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { MCSymbol *Label = EmitCFICommon(); MCCFIInstruction Instruction = MCCFIInstruction::createDefCfa(Label, Register, Offset); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); } @@ -295,7 +302,7 @@ void MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) { MCSymbol *Label = EmitCFICommon(); MCCFIInstruction Instruction = MCCFIInstruction::createDefCfaOffset(Label, Offset); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); } @@ -303,7 +310,7 @@ void MCStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) { MCSymbol *Label = EmitCFICommon(); MCCFIInstruction Instruction = MCCFIInstruction::createAdjustCfaOffset(Label, Adjustment); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); } @@ -311,7 +318,7 @@ void MCStreamer::EmitCFIDefCfaRegister(int64_t Register) { MCSymbol *Label = EmitCFICommon(); MCCFIInstruction Instruction = MCCFIInstruction::createDefCfaRegister(Label, Register); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); } @@ -319,7 +326,7 @@ void MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { MCSymbol *Label = EmitCFICommon(); MCCFIInstruction Instruction = MCCFIInstruction::createOffset(Label, Register, Offset); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); } @@ -327,21 +334,21 @@ void MCStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) { MCSymbol *Label = EmitCFICommon(); MCCFIInstruction Instruction = MCCFIInstruction::createRelOffset(Label, Register, Offset); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); } void MCStreamer::EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) { - EnsureValidFrame(); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + EnsureValidDwarfFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Personality = Sym; CurFrame->PersonalityEncoding = Encoding; } void MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { - EnsureValidFrame(); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + EnsureValidDwarfFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Lsda = Sym; CurFrame->LsdaEncoding = Encoding; } @@ -349,7 +356,7 @@ void MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { void MCStreamer::EmitCFIRememberState() { MCSymbol *Label = EmitCFICommon(); MCCFIInstruction Instruction = MCCFIInstruction::createRememberState(Label); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); } @@ -357,7 +364,7 @@ void MCStreamer::EmitCFIRestoreState() { // FIXME: Error if there is no matching cfi_remember_state. MCSymbol *Label = EmitCFICommon(); MCCFIInstruction Instruction = MCCFIInstruction::createRestoreState(Label); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); } @@ -365,7 +372,7 @@ void MCStreamer::EmitCFISameValue(int64_t Register) { MCSymbol *Label = EmitCFICommon(); MCCFIInstruction Instruction = MCCFIInstruction::createSameValue(Label, Register); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); } @@ -373,20 +380,20 @@ void MCStreamer::EmitCFIRestore(int64_t Register) { MCSymbol *Label = EmitCFICommon(); MCCFIInstruction Instruction = MCCFIInstruction::createRestore(Label, Register); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); } void MCStreamer::EmitCFIEscape(StringRef Values) { MCSymbol *Label = EmitCFICommon(); MCCFIInstruction Instruction = MCCFIInstruction::createEscape(Label, Values); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); } void MCStreamer::EmitCFISignalFrame() { - EnsureValidFrame(); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + EnsureValidDwarfFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->IsSignalFrame = true; } @@ -394,7 +401,7 @@ void MCStreamer::EmitCFIUndefined(int64_t Register) { MCSymbol *Label = EmitCFICommon(); MCCFIInstruction Instruction = MCCFIInstruction::createUndefined(Label, Register); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); } @@ -402,7 +409,7 @@ void MCStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) { MCSymbol *Label = EmitCFICommon(); MCCFIInstruction Instruction = MCCFIInstruction::createRegister(Label, Register1, Register2); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); } @@ -410,164 +417,164 @@ void MCStreamer::EmitCFIWindowSave() { MCSymbol *Label = EmitCFICommon(); MCCFIInstruction Instruction = MCCFIInstruction::createWindowSave(Label); - MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); } -void MCStreamer::setCurrentW64UnwindInfo(MCWin64EHUnwindInfo *Frame) { - W64UnwindInfos.push_back(Frame); - CurrentW64UnwindInfo = W64UnwindInfos.back(); -} - -void MCStreamer::EnsureValidW64UnwindInfo() { - MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; - if (!CurFrame || CurFrame->End) +void MCStreamer::EnsureValidWinFrameInfo() { + if (!CurrentWinFrameInfo || CurrentWinFrameInfo->End) report_fatal_error("No open Win64 EH frame function!"); } -void MCStreamer::EmitWin64EHStartProc(const MCSymbol *Symbol) { - MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; - if (CurFrame && !CurFrame->End) +void MCStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) { + if (CurrentWinFrameInfo && !CurrentWinFrameInfo->End) report_fatal_error("Starting a function before ending the previous one!"); - MCWin64EHUnwindInfo *Frame = new MCWin64EHUnwindInfo; + MCWinFrameInfo *Frame = new MCWinFrameInfo; Frame->Begin = getContext().CreateTempSymbol(); Frame->Function = Symbol; EmitLabel(Frame->Begin); - setCurrentW64UnwindInfo(Frame); + WinFrameInfos.push_back(Frame); + CurrentWinFrameInfo = WinFrameInfos.back(); } -void MCStreamer::EmitWin64EHEndProc() { - EnsureValidW64UnwindInfo(); - MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; - if (CurFrame->ChainedParent) +void MCStreamer::EmitWinCFIEndProc() { + EnsureValidWinFrameInfo(); + if (CurrentWinFrameInfo->ChainedParent) report_fatal_error("Not all chained regions terminated!"); - CurFrame->End = getContext().CreateTempSymbol(); - EmitLabel(CurFrame->End); + CurrentWinFrameInfo->End = getContext().CreateTempSymbol(); + EmitLabel(CurrentWinFrameInfo->End); } -void MCStreamer::EmitWin64EHStartChained() { - EnsureValidW64UnwindInfo(); - MCWin64EHUnwindInfo *Frame = new MCWin64EHUnwindInfo; - MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; +void MCStreamer::EmitWinCFIStartChained() { + EnsureValidWinFrameInfo(); + MCWinFrameInfo *Frame = new MCWinFrameInfo; Frame->Begin = getContext().CreateTempSymbol(); - Frame->Function = CurFrame->Function; - Frame->ChainedParent = CurFrame; + Frame->Function = CurrentWinFrameInfo->Function; + Frame->ChainedParent = CurrentWinFrameInfo; EmitLabel(Frame->Begin); - setCurrentW64UnwindInfo(Frame); + WinFrameInfos.push_back(Frame); + CurrentWinFrameInfo = WinFrameInfos.back(); } -void MCStreamer::EmitWin64EHEndChained() { - EnsureValidW64UnwindInfo(); - MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; - if (!CurFrame->ChainedParent) +void MCStreamer::EmitWinCFIEndChained() { + EnsureValidWinFrameInfo(); + if (!CurrentWinFrameInfo->ChainedParent) report_fatal_error("End of a chained region outside a chained region!"); - CurFrame->End = getContext().CreateTempSymbol(); - EmitLabel(CurFrame->End); - CurrentW64UnwindInfo = CurFrame->ChainedParent; + CurrentWinFrameInfo->End = getContext().CreateTempSymbol(); + EmitLabel(CurrentWinFrameInfo->End); + CurrentWinFrameInfo = CurrentWinFrameInfo->ChainedParent; } -void MCStreamer::EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, - bool Except) { - EnsureValidW64UnwindInfo(); - MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; - if (CurFrame->ChainedParent) +void MCStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, + bool Except) { + EnsureValidWinFrameInfo(); + if (CurrentWinFrameInfo->ChainedParent) report_fatal_error("Chained unwind areas can't have handlers!"); - CurFrame->ExceptionHandler = Sym; + CurrentWinFrameInfo->ExceptionHandler = Sym; if (!Except && !Unwind) report_fatal_error("Don't know what kind of handler this is!"); if (Unwind) - CurFrame->HandlesUnwind = true; + CurrentWinFrameInfo->HandlesUnwind = true; if (Except) - CurFrame->HandlesExceptions = true; + CurrentWinFrameInfo->HandlesExceptions = true; } -void MCStreamer::EmitWin64EHHandlerData() { - EnsureValidW64UnwindInfo(); - MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; - if (CurFrame->ChainedParent) +void MCStreamer::EmitWinEHHandlerData() { + EnsureValidWinFrameInfo(); + if (CurrentWinFrameInfo->ChainedParent) report_fatal_error("Chained unwind areas can't have handlers!"); } -void MCStreamer::EmitWin64EHPushReg(unsigned Register) { - EnsureValidW64UnwindInfo(); - MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; +void MCStreamer::EmitWinCFIPushReg(unsigned Register) { + EnsureValidWinFrameInfo(); + MCSymbol *Label = getContext().CreateTempSymbol(); - MCWin64EHInstruction Inst(Win64EH::UOP_PushNonVol, Label, Register); EmitLabel(Label); - CurFrame->Instructions.push_back(Inst); + + WinEH::Instruction Inst = Win64EH::Instruction::PushNonVol(Label, Register); + CurrentWinFrameInfo->Instructions.push_back(Inst); } -void MCStreamer::EmitWin64EHSetFrame(unsigned Register, unsigned Offset) { - EnsureValidW64UnwindInfo(); - MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; - if (CurFrame->LastFrameInst >= 0) +void MCStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset) { + EnsureValidWinFrameInfo(); + if (CurrentWinFrameInfo->LastFrameInst >= 0) report_fatal_error("Frame register and offset already specified!"); if (Offset & 0x0F) report_fatal_error("Misaligned frame pointer offset!"); + if (Offset > 240) + report_fatal_error("Frame offset must be less than or equal to 240!"); + MCSymbol *Label = getContext().CreateTempSymbol(); - MCWin64EHInstruction Inst(Win64EH::UOP_SetFPReg, Label, Register, Offset); EmitLabel(Label); - CurFrame->LastFrameInst = CurFrame->Instructions.size(); - CurFrame->Instructions.push_back(Inst); + + WinEH::Instruction Inst = + Win64EH::Instruction::SetFPReg(Label, Register, Offset); + CurrentWinFrameInfo->LastFrameInst = CurrentWinFrameInfo->Instructions.size(); + CurrentWinFrameInfo->Instructions.push_back(Inst); } -void MCStreamer::EmitWin64EHAllocStack(unsigned Size) { - EnsureValidW64UnwindInfo(); +void MCStreamer::EmitWinCFIAllocStack(unsigned Size) { + EnsureValidWinFrameInfo(); + if (Size == 0) + report_fatal_error("Allocation size must be non-zero!"); if (Size & 7) report_fatal_error("Misaligned stack allocation!"); - MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; + MCSymbol *Label = getContext().CreateTempSymbol(); - MCWin64EHInstruction Inst(Label, Size); EmitLabel(Label); - CurFrame->Instructions.push_back(Inst); + + WinEH::Instruction Inst = Win64EH::Instruction::Alloc(Label, Size); + CurrentWinFrameInfo->Instructions.push_back(Inst); } -void MCStreamer::EmitWin64EHSaveReg(unsigned Register, unsigned Offset) { - EnsureValidW64UnwindInfo(); +void MCStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset) { + EnsureValidWinFrameInfo(); if (Offset & 7) report_fatal_error("Misaligned saved register offset!"); - MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; + MCSymbol *Label = getContext().CreateTempSymbol(); - MCWin64EHInstruction Inst( - Offset > 512*1024-8 ? Win64EH::UOP_SaveNonVolBig : Win64EH::UOP_SaveNonVol, - Label, Register, Offset); EmitLabel(Label); - CurFrame->Instructions.push_back(Inst); + + WinEH::Instruction Inst = + Win64EH::Instruction::SaveNonVol(Label, Register, Offset); + CurrentWinFrameInfo->Instructions.push_back(Inst); } -void MCStreamer::EmitWin64EHSaveXMM(unsigned Register, unsigned Offset) { - EnsureValidW64UnwindInfo(); +void MCStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) { + EnsureValidWinFrameInfo(); if (Offset & 0x0F) report_fatal_error("Misaligned saved vector register offset!"); - MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; + MCSymbol *Label = getContext().CreateTempSymbol(); - MCWin64EHInstruction Inst( - Offset > 512*1024-16 ? Win64EH::UOP_SaveXMM128Big : Win64EH::UOP_SaveXMM128, - Label, Register, Offset); EmitLabel(Label); - CurFrame->Instructions.push_back(Inst); + + WinEH::Instruction Inst = + Win64EH::Instruction::SaveXMM(Label, Register, Offset); + CurrentWinFrameInfo->Instructions.push_back(Inst); } -void MCStreamer::EmitWin64EHPushFrame(bool Code) { - EnsureValidW64UnwindInfo(); - MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; - if (CurFrame->Instructions.size() > 0) +void MCStreamer::EmitWinCFIPushFrame(bool Code) { + EnsureValidWinFrameInfo(); + if (CurrentWinFrameInfo->Instructions.size() > 0) report_fatal_error("If present, PushMachFrame must be the first UOP"); + MCSymbol *Label = getContext().CreateTempSymbol(); - MCWin64EHInstruction Inst(Win64EH::UOP_PushMachFrame, Label, Code); EmitLabel(Label); - CurFrame->Instructions.push_back(Inst); + + WinEH::Instruction Inst = Win64EH::Instruction::PushMachFrame(Label, Code); + CurrentWinFrameInfo->Instructions.push_back(Inst); +} + +void MCStreamer::EmitWinCFIEndProlog() { + EnsureValidWinFrameInfo(); + CurrentWinFrameInfo->PrologEnd = getContext().CreateTempSymbol(); + EmitLabel(CurrentWinFrameInfo->PrologEnd); } -void MCStreamer::EmitWin64EHEndProlog() { - EnsureValidW64UnwindInfo(); - MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; - CurFrame->PrologEnd = getContext().CreateTempSymbol(); - EmitLabel(CurFrame->PrologEnd); +void MCStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { } void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) { - llvm_unreachable("This file format doesn't support this directive"); } /// EmitRawText - If this file is backed by an assembly streamer, this dumps @@ -584,32 +591,101 @@ void MCStreamer::EmitRawText(const Twine &T) { EmitRawTextImpl(T.toStringRef(Str)); } -void MCStreamer::EmitFrames(MCAsmBackend *MAB, bool usingCFI) { - if (!getNumFrameInfos()) - return; - - if (EmitEHFrame) - MCDwarfFrameEmitter::Emit(*this, MAB, usingCFI, true); - - if (EmitDebugFrame) - MCDwarfFrameEmitter::Emit(*this, MAB, usingCFI, false); -} - -void MCStreamer::EmitW64Tables() { - if (!getNumW64UnwindInfos()) +void MCStreamer::EmitWindowsUnwindTables() { + if (!getNumWinFrameInfos()) return; MCWin64EHUnwindEmitter::Emit(*this); } void MCStreamer::Finish() { - if (!FrameInfos.empty() && !FrameInfos.back().End) + if (!DwarfFrameInfos.empty() && !DwarfFrameInfos.back().End) report_fatal_error("Unfinished frame!"); + MCTargetStreamer *TS = getTargetStreamer(); + if (TS) + TS->finish(); + FinishImpl(); } -MCSymbolData &MCStreamer::getOrCreateSymbolData(MCSymbol *Symbol) { - report_fatal_error("Not supported!"); - return *(static_cast<MCSymbolData*>(0)); +void MCStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { + visitUsedExpr(*Value); + Symbol->setVariableValue(Value); + + MCTargetStreamer *TS = getTargetStreamer(); + if (TS) + TS->emitAssignment(Symbol, Value); +} + +void MCStreamer::visitUsedSymbol(const MCSymbol &Sym) { +} + +void MCStreamer::visitUsedExpr(const MCExpr &Expr) { + switch (Expr.getKind()) { + case MCExpr::Target: + cast<MCTargetExpr>(Expr).visitUsedExpr(*this); + break; + + case MCExpr::Constant: + break; + + case MCExpr::Binary: { + const MCBinaryExpr &BE = cast<MCBinaryExpr>(Expr); + visitUsedExpr(*BE.getLHS()); + visitUsedExpr(*BE.getRHS()); + break; + } + + case MCExpr::SymbolRef: + visitUsedSymbol(cast<MCSymbolRefExpr>(Expr).getSymbol()); + break; + + case MCExpr::Unary: + visitUsedExpr(*cast<MCUnaryExpr>(Expr).getSubExpr()); + break; + } } + +void MCStreamer::EmitInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI) { + // Scan for values. + for (unsigned i = Inst.getNumOperands(); i--;) + if (Inst.getOperand(i).isExpr()) + visitUsedExpr(*Inst.getOperand(i).getExpr()); +} + +void MCStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {} +void MCStreamer::EmitThumbFunc(MCSymbol *Func) {} +void MCStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {} +void MCStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) {} +void MCStreamer::EndCOFFSymbolDef() {} +void MCStreamer::EmitFileDirective(StringRef Filename) {} +void MCStreamer::EmitCOFFSymbolStorageClass(int StorageClass) {} +void MCStreamer::EmitCOFFSymbolType(int Type) {} +void MCStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {} +void MCStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) {} +void MCStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment) {} +void MCStreamer::ChangeSection(const MCSection *, const MCExpr *) {} +void MCStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {} +void MCStreamer::EmitBytes(StringRef Data) {} +void MCStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, + const SMLoc &Loc) { + visitUsedExpr(*Value); +} +void MCStreamer::EmitULEB128Value(const MCExpr *Value) {} +void MCStreamer::EmitSLEB128Value(const MCExpr *Value) {} +void MCStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, + unsigned ValueSize, + unsigned MaxBytesToEmit) {} +void MCStreamer::EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit) {} +bool MCStreamer::EmitValueToOffset(const MCExpr *Offset, unsigned char Value) { + return false; +} +void MCStreamer::EmitBundleAlignMode(unsigned AlignPow2) {} +void MCStreamer::EmitBundleLock(bool AlignToEnd) {} +void MCStreamer::FinishImpl() {} +void MCStreamer::EmitBundleUnlock() {} diff --git a/contrib/llvm/lib/MC/MCSubtargetInfo.cpp b/contrib/llvm/lib/MC/MCSubtargetInfo.cpp index 8d8e290..4424c91 100644 --- a/contrib/llvm/lib/MC/MCSubtargetInfo.cpp +++ b/contrib/llvm/lib/MC/MCSubtargetInfo.cpp @@ -24,9 +24,7 @@ MCSchedModel MCSchedModel::DefaultSchedModel; // For unknown processors. void MCSubtargetInfo::InitMCProcessorInfo(StringRef CPU, StringRef FS) { SubtargetFeatures Features(FS); - FeatureBits = Features.getFeatureBits(CPU, ProcDesc, NumProcs, - ProcFeatures, NumFeatures); - + FeatureBits = Features.getFeatureBits(CPU, ProcDesc, ProcFeatures); InitCPUSchedModel(CPU); } @@ -40,16 +38,15 @@ MCSubtargetInfo::InitCPUSchedModel(StringRef CPU) { void MCSubtargetInfo::InitMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS, - const SubtargetFeatureKV *PF, - const SubtargetFeatureKV *PD, + ArrayRef<SubtargetFeatureKV> PF, + ArrayRef<SubtargetFeatureKV> PD, const SubtargetInfoKV *ProcSched, const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA, const InstrStage *IS, const unsigned *OC, - const unsigned *FP, - unsigned NF, unsigned NP) { + const unsigned *FP) { TargetTriple = TT; ProcFeatures = PF; ProcDesc = PD; @@ -61,8 +58,6 @@ MCSubtargetInfo::InitMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS, Stages = IS; OperandCycles = OC; ForwardingPaths = FP; - NumFeatures = NF; - NumProcs = NP; InitMCProcessorInfo(CPU, FS); } @@ -78,8 +73,7 @@ uint64_t MCSubtargetInfo::ToggleFeature(uint64_t FB) { /// bits. This version will also change all implied bits. uint64_t MCSubtargetInfo::ToggleFeature(StringRef FS) { SubtargetFeatures Features; - FeatureBits = Features.ToggleFeature(FeatureBits, FS, - ProcFeatures, NumFeatures); + FeatureBits = Features.ToggleFeature(FeatureBits, FS, ProcFeatures); return FeatureBits; } @@ -88,6 +82,7 @@ const MCSchedModel * MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const { assert(ProcSchedModels && "Processor machine model not available!"); + unsigned NumProcs = ProcDesc.size(); #ifndef NDEBUG for (size_t i = 1; i < NumProcs; i++) { assert(strcmp(ProcSchedModels[i - 1].Key, ProcSchedModels[i].Key) < 0 && diff --git a/contrib/llvm/lib/MC/MCSymbolizer.cpp b/contrib/llvm/lib/MC/MCSymbolizer.cpp index 1020b74..4080e40 100644 --- a/contrib/llvm/lib/MC/MCSymbolizer.cpp +++ b/contrib/llvm/lib/MC/MCSymbolizer.cpp @@ -8,13 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCSymbolizer.h" -#include "llvm/MC/MCRelocationInfo.h" using namespace llvm; -MCSymbolizer::MCSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo) - : Ctx(Ctx), RelInfo(RelInfo.take()) { -} - MCSymbolizer::~MCSymbolizer() { } diff --git a/contrib/llvm/lib/MC/MCTargetOptions.cpp b/contrib/llvm/lib/MC/MCTargetOptions.cpp new file mode 100644 index 0000000..efd724a --- /dev/null +++ b/contrib/llvm/lib/MC/MCTargetOptions.cpp @@ -0,0 +1,20 @@ +//===- lib/MC/MCTargetOptions.cpp - MC Target Options --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCTargetOptions.h" + +namespace llvm { + +MCTargetOptions::MCTargetOptions() + : SanitizeAddress(false), MCRelaxAll(false), MCNoExecStack(false), + MCSaveTempLabels(false), MCUseDwarfDirectory(false), + ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false), + DwarfVersion(0) {} + +} // end namespace llvm diff --git a/contrib/llvm/lib/MC/MCValue.cpp b/contrib/llvm/lib/MC/MCValue.cpp index 4393777..9dfc56e 100644 --- a/contrib/llvm/lib/MC/MCValue.cpp +++ b/contrib/llvm/lib/MC/MCValue.cpp @@ -10,6 +10,7 @@ #include "llvm/MC/MCValue.h" #include "llvm/MC/MCExpr.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -20,6 +21,11 @@ void MCValue::print(raw_ostream &OS, const MCAsmInfo *MAI) const { return; } + // FIXME: prints as a number, which isn't ideal. But the meaning will be + // target-specific anyway. + if (getRefKind()) + OS << ':' << getRefKind() << ':'; + getSymA()->print(OS); if (getSymB()) { @@ -33,6 +39,23 @@ void MCValue::print(raw_ostream &OS, const MCAsmInfo *MAI) const { #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void MCValue::dump() const { - print(dbgs(), 0); + print(dbgs(), nullptr); } #endif + +MCSymbolRefExpr::VariantKind MCValue::getAccessVariant() const { + const MCSymbolRefExpr *B = getSymB(); + if (B) { + if (B->getKind() != MCSymbolRefExpr::VK_None) + llvm_unreachable("unsupported"); + } + + const MCSymbolRefExpr *A = getSymA(); + if (!A) + return MCSymbolRefExpr::VK_None; + + MCSymbolRefExpr::VariantKind Kind = A->getKind(); + if (Kind == MCSymbolRefExpr::VK_WEAKREF) + return MCSymbolRefExpr::VK_None; + return Kind; +} diff --git a/contrib/llvm/lib/MC/MCWin64EH.cpp b/contrib/llvm/lib/MC/MCWin64EH.cpp index b8b07d3..95e1983 100644 --- a/contrib/llvm/lib/MC/MCWin64EH.cpp +++ b/contrib/llvm/lib/MC/MCWin64EH.cpp @@ -15,114 +15,108 @@ #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Support/Win64EH.h" namespace llvm { // NOTE: All relocations generated here are 4-byte image-relative. -static uint8_t CountOfUnwindCodes(std::vector<MCWin64EHInstruction> &instArray){ - uint8_t count = 0; - for (std::vector<MCWin64EHInstruction>::const_iterator I = instArray.begin(), - E = instArray.end(); I != E; ++I) { - switch (I->getOperation()) { +static uint8_t CountOfUnwindCodes(std::vector<WinEH::Instruction> &Insns) { + uint8_t Count = 0; + for (const auto &I : Insns) { + switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) { case Win64EH::UOP_PushNonVol: case Win64EH::UOP_AllocSmall: case Win64EH::UOP_SetFPReg: case Win64EH::UOP_PushMachFrame: - count += 1; + Count += 1; break; case Win64EH::UOP_SaveNonVol: case Win64EH::UOP_SaveXMM128: - count += 2; + Count += 2; break; case Win64EH::UOP_SaveNonVolBig: case Win64EH::UOP_SaveXMM128Big: - count += 3; + Count += 3; break; case Win64EH::UOP_AllocLarge: - if (I->getSize() > 512*1024-8) - count += 3; - else - count += 2; + Count += (I.Offset > 512 * 1024 - 8) ? 3 : 2; break; } } - return count; + return Count; } -static void EmitAbsDifference(MCStreamer &streamer, MCSymbol *lhs, - MCSymbol *rhs) { - MCContext &context = streamer.getContext(); - const MCExpr *diff = MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create( - lhs, context), - MCSymbolRefExpr::Create( - rhs, context), - context); - streamer.EmitAbsValue(diff, 1); - +static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, + const MCSymbol *RHS) { + MCContext &Context = Streamer.getContext(); + const MCExpr *Diff = + MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(LHS, Context), + MCSymbolRefExpr::Create(RHS, Context), Context); + Streamer.EmitAbsValue(Diff, 1); } static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin, - MCWin64EHInstruction &inst) { + WinEH::Instruction &inst) { uint8_t b2; uint16_t w; - b2 = (inst.getOperation() & 0x0F); - switch (inst.getOperation()) { + b2 = (inst.Operation & 0x0F); + switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) { case Win64EH::UOP_PushNonVol: - EmitAbsDifference(streamer, inst.getLabel(), begin); - b2 |= (inst.getRegister() & 0x0F) << 4; + EmitAbsDifference(streamer, inst.Label, begin); + b2 |= (inst.Register & 0x0F) << 4; streamer.EmitIntValue(b2, 1); break; case Win64EH::UOP_AllocLarge: - EmitAbsDifference(streamer, inst.getLabel(), begin); - if (inst.getSize() > 512*1024-8) { + EmitAbsDifference(streamer, inst.Label, begin); + if (inst.Offset > 512 * 1024 - 8) { b2 |= 0x10; streamer.EmitIntValue(b2, 1); - w = inst.getSize() & 0xFFF8; + w = inst.Offset & 0xFFF8; streamer.EmitIntValue(w, 2); - w = inst.getSize() >> 16; + w = inst.Offset >> 16; } else { streamer.EmitIntValue(b2, 1); - w = inst.getSize() >> 3; + w = inst.Offset >> 3; } streamer.EmitIntValue(w, 2); break; case Win64EH::UOP_AllocSmall: - b2 |= (((inst.getSize()-8) >> 3) & 0x0F) << 4; - EmitAbsDifference(streamer, inst.getLabel(), begin); + b2 |= (((inst.Offset - 8) >> 3) & 0x0F) << 4; + EmitAbsDifference(streamer, inst.Label, begin); streamer.EmitIntValue(b2, 1); break; case Win64EH::UOP_SetFPReg: - EmitAbsDifference(streamer, inst.getLabel(), begin); + EmitAbsDifference(streamer, inst.Label, begin); streamer.EmitIntValue(b2, 1); break; case Win64EH::UOP_SaveNonVol: case Win64EH::UOP_SaveXMM128: - b2 |= (inst.getRegister() & 0x0F) << 4; - EmitAbsDifference(streamer, inst.getLabel(), begin); + b2 |= (inst.Register & 0x0F) << 4; + EmitAbsDifference(streamer, inst.Label, begin); streamer.EmitIntValue(b2, 1); - w = inst.getOffset() >> 3; - if (inst.getOperation() == Win64EH::UOP_SaveXMM128) + w = inst.Offset >> 3; + if (inst.Operation == Win64EH::UOP_SaveXMM128) w >>= 1; streamer.EmitIntValue(w, 2); break; case Win64EH::UOP_SaveNonVolBig: case Win64EH::UOP_SaveXMM128Big: - b2 |= (inst.getRegister() & 0x0F) << 4; - EmitAbsDifference(streamer, inst.getLabel(), begin); + b2 |= (inst.Register & 0x0F) << 4; + EmitAbsDifference(streamer, inst.Label, begin); streamer.EmitIntValue(b2, 1); - if (inst.getOperation() == Win64EH::UOP_SaveXMM128Big) - w = inst.getOffset() & 0xFFF0; + if (inst.Operation == Win64EH::UOP_SaveXMM128Big) + w = inst.Offset & 0xFFF0; else - w = inst.getOffset() & 0xFFF8; + w = inst.Offset & 0xFFF8; streamer.EmitIntValue(w, 2); - w = inst.getOffset() >> 16; + w = inst.Offset >> 16; streamer.EmitIntValue(w, 2); break; case Win64EH::UOP_PushMachFrame: - if (inst.isPushCodeFrame()) + if (inst.Offset == 1) b2 |= 0x10; - EmitAbsDifference(streamer, inst.getLabel(), begin); + EmitAbsDifference(streamer, inst.Label, begin); streamer.EmitIntValue(b2, 1); break; } @@ -142,7 +136,7 @@ static void EmitSymbolRefWithOfs(MCStreamer &streamer, } static void EmitRuntimeFunction(MCStreamer &streamer, - const MCWin64EHUnwindInfo *info) { + const MCWinFrameInfo *info) { MCContext &context = streamer.getContext(); streamer.EmitValueToAlignment(4); @@ -153,7 +147,7 @@ static void EmitRuntimeFunction(MCStreamer &streamer, context), 4); } -static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) { +static void EmitUnwindInfo(MCStreamer &streamer, MCWinFrameInfo *info) { // If this UNWIND_INFO already has a symbol, it's already been emitted. if (info->Symbol) return; @@ -184,17 +178,16 @@ static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) { uint8_t frame = 0; if (info->LastFrameInst >= 0) { - MCWin64EHInstruction &frameInst = info->Instructions[info->LastFrameInst]; - assert(frameInst.getOperation() == Win64EH::UOP_SetFPReg); - frame = (frameInst.getRegister() & 0x0F) | - (frameInst.getOffset() & 0xF0); + WinEH::Instruction &frameInst = info->Instructions[info->LastFrameInst]; + assert(frameInst.Operation == Win64EH::UOP_SetFPReg); + frame = (frameInst.Register & 0x0F) | (frameInst.Offset & 0xF0); } streamer.EmitIntValue(frame, 1); // Emit unwind instructions (in reverse order). uint8_t numInst = info->Instructions.size(); for (uint8_t c = 0; c < numInst; ++c) { - MCWin64EHInstruction inst = info->Instructions.back(); + WinEH::Instruction inst = info->Instructions.back(); info->Instructions.pop_back(); EmitUnwindCode(streamer, info->Begin, inst); } @@ -263,7 +256,7 @@ static const MCSection *getWin64EHFuncTableSection(StringRef suffix, } void MCWin64EHUnwindEmitter::EmitUnwindInfo(MCStreamer &streamer, - MCWin64EHUnwindInfo *info) { + MCWinFrameInfo *info) { // Switch sections (the static function above is meant to be called from // here and from Emit(). MCContext &context = streamer.getContext(); @@ -274,23 +267,23 @@ void MCWin64EHUnwindEmitter::EmitUnwindInfo(MCStreamer &streamer, llvm::EmitUnwindInfo(streamer, info); } -void MCWin64EHUnwindEmitter::Emit(MCStreamer &streamer) { - MCContext &context = streamer.getContext(); +void MCWin64EHUnwindEmitter::Emit(MCStreamer &Streamer) { + MCContext &Context = Streamer.getContext(); + // Emit the unwind info structs first. - for (unsigned i = 0; i < streamer.getNumW64UnwindInfos(); ++i) { - MCWin64EHUnwindInfo &info = streamer.getW64UnwindInfo(i); - const MCSection *xdataSect = - getWin64EHTableSection(GetSectionSuffix(info.Function), context); - streamer.SwitchSection(xdataSect); - llvm::EmitUnwindInfo(streamer, &info); + for (const auto &CFI : Streamer.getWinFrameInfos()) { + const MCSection *XData = + getWin64EHTableSection(GetSectionSuffix(CFI->Function), Context); + Streamer.SwitchSection(XData); + EmitUnwindInfo(Streamer, CFI); } + // Now emit RUNTIME_FUNCTION entries. - for (unsigned i = 0; i < streamer.getNumW64UnwindInfos(); ++i) { - MCWin64EHUnwindInfo &info = streamer.getW64UnwindInfo(i); - const MCSection *pdataSect = - getWin64EHFuncTableSection(GetSectionSuffix(info.Function), context); - streamer.SwitchSection(pdataSect); - EmitRuntimeFunction(streamer, &info); + for (const auto &CFI : Streamer.getWinFrameInfos()) { + const MCSection *PData = + getWin64EHFuncTableSection(GetSectionSuffix(CFI->Function), Context); + Streamer.SwitchSection(PData); + EmitRuntimeFunction(Streamer, CFI); } } diff --git a/contrib/llvm/lib/MC/MachObjectWriter.cpp b/contrib/llvm/lib/MC/MachObjectWriter.cpp index 8234aff..5214398 100644 --- a/contrib/llvm/lib/MC/MachObjectWriter.cpp +++ b/contrib/llvm/lib/MC/MachObjectWriter.cpp @@ -26,6 +26,8 @@ #include <vector> using namespace llvm; +#define DEBUG_TYPE "mc" + void MachObjectWriter::reset() { Relocations.clear(); IndirectSymBase.clear(); @@ -82,7 +84,7 @@ uint64_t MachObjectWriter::getSymbolAddress(const MCSymbolData* SD, MCValue Target; - if (!S.getVariableValue()->EvaluateAsRelocatable(Target, Layout)) + if (!S.getVariableValue()->EvaluateAsRelocatable(Target, &Layout)) report_fatal_error("unable to evaluate offset for variable '" + S.getName() + "'"); @@ -229,7 +231,7 @@ void MachObjectWriter::WriteSection(const MCAssembler &Asm, unsigned Flags = Section.getTypeAndAttributes(); if (SD.hasInstructions()) - Flags |= MCSectionMachO::S_ATTR_SOME_INSTRUCTIONS; + Flags |= MachO::S_ATTR_SOME_INSTRUCTIONS; assert(isPowerOf2_32(SD.getAlignment()) && "Invalid alignment!"); Write32(Log2_32(SD.getAlignment())); @@ -301,20 +303,50 @@ void MachObjectWriter::WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol, assert(OS.tell() - Start == sizeof(MachO::dysymtab_command)); } +MachObjectWriter::MachSymbolData * +MachObjectWriter::findSymbolData(const MCSymbol &Sym) { + for (auto &Entry : LocalSymbolData) + if (&Entry.SymbolData->getSymbol() == &Sym) + return &Entry; + + for (auto &Entry : ExternalSymbolData) + if (&Entry.SymbolData->getSymbol() == &Sym) + return &Entry; + + for (auto &Entry : UndefinedSymbolData) + if (&Entry.SymbolData->getSymbol() == &Sym) + return &Entry; + + return nullptr; +} + void MachObjectWriter::WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout) { MCSymbolData &Data = *MSD.SymbolData; - const MCSymbol &Symbol = Data.getSymbol(); + const MCSymbol *Symbol = &Data.getSymbol(); + const MCSymbol *AliasedSymbol = &Symbol->AliasedSymbol(); + uint8_t SectionIndex = MSD.SectionIndex; uint8_t Type = 0; uint16_t Flags = Data.getFlags(); uint64_t Address = 0; + bool IsAlias = Symbol != AliasedSymbol; + + MachSymbolData *AliaseeInfo; + if (IsAlias) { + AliaseeInfo = findSymbolData(*AliasedSymbol); + if (AliaseeInfo) + SectionIndex = AliaseeInfo->SectionIndex; + Symbol = AliasedSymbol; + } // Set the N_TYPE bits. See <mach-o/nlist.h>. // // FIXME: Are the prebound or indirect fields possible here? - if (Symbol.isUndefined()) + if (IsAlias && Symbol->isUndefined()) + Type = MachO::N_INDR; + else if (Symbol->isUndefined()) Type = MachO::N_UNDF; - else if (Symbol.isAbsolute()) + else if (Symbol->isAbsolute()) Type = MachO::N_ABS; else Type = MachO::N_SECT; @@ -325,13 +357,15 @@ void MachObjectWriter::WriteNlist(MachSymbolData &MSD, Type |= MachO::N_PEXT; // Set external bit. - if (Data.isExternal() || Symbol.isUndefined()) + if (Data.isExternal() || (!IsAlias && Symbol->isUndefined())) Type |= MachO::N_EXT; // Compute the symbol address. - if (Symbol.isDefined()) { + if (IsAlias && Symbol->isUndefined()) + Address = AliaseeInfo->StringIndex; + else if (Symbol->isDefined()) Address = getSymbolAddress(&Data, Layout); - } else if (Data.isCommon()) { + else if (Data.isCommon()) { // Common symbols are encoded with the size in the address // field, and their alignment in the flags. Address = Data.getCommonSize(); @@ -342,18 +376,21 @@ void MachObjectWriter::WriteNlist(MachSymbolData &MSD, assert((1U << Log2Size) == Align && "Invalid 'common' alignment!"); if (Log2Size > 15) report_fatal_error("invalid 'common' alignment '" + - Twine(Align) + "' for '" + Symbol.getName() + "'", + Twine(Align) + "' for '" + Symbol->getName() + "'", false); // FIXME: Keep this mask with the SymbolFlags enumeration. Flags = (Flags & 0xF0FF) | (Log2Size << 8); } } + if (Layout.getAssembler().isThumbFunc(Symbol)) + Flags |= SF_ThumbFunc; + // struct nlist (12 bytes) Write32(MSD.StringIndex); Write8(Type); - Write8(MSD.SectionIndex); + Write8(SectionIndex); // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc' // value. @@ -417,6 +454,7 @@ void MachObjectWriter::RecordRelocation(const MCAssembler &Asm, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, + bool &IsPCRel, uint64_t &FixedValue) { TargetObjectWriter->RecordRelocation(this, Asm, Layout, Fragment, Fixup, Target, FixedValue); @@ -437,23 +475,23 @@ void MachObjectWriter::BindIndirectSymbols(MCAssembler &Asm) { const MCSectionMachO &Section = cast<MCSectionMachO>(it->SectionData->getSection()); - if (Section.getType() != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS && - Section.getType() != MCSectionMachO::S_LAZY_SYMBOL_POINTERS && - Section.getType() != MCSectionMachO::S_SYMBOL_STUBS) { + if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS && + Section.getType() != MachO::S_LAZY_SYMBOL_POINTERS && + Section.getType() != MachO::S_SYMBOL_STUBS) { MCSymbol &Symbol = *it->Symbol; report_fatal_error("indirect symbol '" + Symbol.getName() + "' not in a symbol pointer or stub section"); } } - // Bind non lazy symbol pointers first. + // Bind non-lazy symbol pointers first. unsigned IndirectIndex = 0; for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(), ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) { const MCSectionMachO &Section = cast<MCSectionMachO>(it->SectionData->getSection()); - if (Section.getType() != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) + if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS) continue; // Initialize the section indirect symbol base, if necessary. @@ -469,8 +507,8 @@ void MachObjectWriter::BindIndirectSymbols(MCAssembler &Asm) { const MCSectionMachO &Section = cast<MCSectionMachO>(it->SectionData->getSection()); - if (Section.getType() != MCSectionMachO::S_LAZY_SYMBOL_POINTERS && - Section.getType() != MCSectionMachO::S_SYMBOL_STUBS) + if (Section.getType() != MachO::S_LAZY_SYMBOL_POINTERS && + Section.getType() != MachO::S_SYMBOL_STUBS) continue; // Initialize the section indirect symbol base, if necessary. @@ -515,15 +553,14 @@ ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, // table, then sort the symbols is chosen to match 'as'. Even though it // doesn't matter for correctness, this is important for letting us diff .o // files. - for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), - ie = Asm.symbol_end(); it != ie; ++it) { - const MCSymbol &Symbol = it->getSymbol(); + for (MCSymbolData &SD : Asm.symbols()) { + const MCSymbol &Symbol = SD.getSymbol(); // Ignore non-linker visible symbols. - if (!Asm.isSymbolLinkerVisible(it->getSymbol())) + if (!Asm.isSymbolLinkerVisible(SD.getSymbol())) continue; - if (!it->isExternal() && !Symbol.isUndefined()) + if (!SD.isExternal() && !Symbol.isUndefined()) continue; uint64_t &Entry = StringIndexMap[Symbol.getName()]; @@ -534,7 +571,7 @@ ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, } MachSymbolData MSD; - MSD.SymbolData = it; + MSD.SymbolData = &SD; MSD.StringIndex = Entry; if (Symbol.isUndefined()) { @@ -551,15 +588,14 @@ ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, } // Now add the data for local symbols. - for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), - ie = Asm.symbol_end(); it != ie; ++it) { - const MCSymbol &Symbol = it->getSymbol(); + for (MCSymbolData &SD : Asm.symbols()) { + const MCSymbol &Symbol = SD.getSymbol(); // Ignore non-linker visible symbols. - if (!Asm.isSymbolLinkerVisible(it->getSymbol())) + if (!Asm.isSymbolLinkerVisible(SD.getSymbol())) continue; - if (it->isExternal() || Symbol.isUndefined()) + if (SD.isExternal() || Symbol.isUndefined()) continue; uint64_t &Entry = StringIndexMap[Symbol.getName()]; @@ -570,7 +606,7 @@ ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, } MachSymbolData MSD; - MSD.SymbolData = it; + MSD.SymbolData = &SD; MSD.StringIndex = Entry; if (Symbol.isAbsolute()) { @@ -620,10 +656,7 @@ void MachObjectWriter::computeSectionAddresses(const MCAssembler &Asm, void MachObjectWriter::markAbsoluteVariableSymbols(MCAssembler &Asm, const MCAsmLayout &Layout) { - for (MCAssembler::symbol_iterator i = Asm.symbol_begin(), - e = Asm.symbol_end(); - i != e; ++i) { - MCSymbolData &SD = *i; + for (MCSymbolData &SD : Asm.symbols()) { if (!SD.getSymbol().isVariable()) continue; @@ -631,7 +664,7 @@ void MachObjectWriter::markAbsoluteVariableSymbols(MCAssembler &Asm, // and neither symbol is external, mark the variable as absolute. const MCExpr *Expr = SD.getSymbol().getVariableValue(); MCValue Value; - if (Expr->EvaluateAsRelocatable(Value, Layout)) { + if (Expr->EvaluateAsRelocatable(Value, &Layout)) { if (Value.getSymA() && Value.getSymB()) const_cast<MCSymbol*>(&SD.getSymbol())->setAbsolute(); } @@ -668,7 +701,7 @@ IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, // - addr(atom(B)) - offset(B) // and the offsets are not relocatable, so the fixup is fully resolved when // addr(atom(A)) - addr(atom(B)) == 0. - const MCSymbolData *A_Base = 0, *B_Base = 0; + const MCSymbolData *A_Base = nullptr, *B_Base = nullptr; const MCSymbol &SA = DataA.getSymbol().AliasedSymbol(); const MCSection &SecA = SA.getSection(); @@ -688,7 +721,8 @@ IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, // same assumptions about any symbol that we normally make about // assembler locals. - if (!Asm.getBackend().hasReliableSymbolDifference()) { + bool hasReliableSymbolDifference = isX86_64(); + if (!hasReliableSymbolDifference) { if (!SA.isInSection() || &SecA != &SecB || (!SA.isTemporary() && FB.getAtom() != Asm.getSymbolData(SA).getFragment()->getAtom() && @@ -736,6 +770,8 @@ IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, void MachObjectWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { unsigned NumSections = Asm.size(); + const MCAssembler::VersionMinInfoType &VersionInfo = + Layout.getAssembler().getVersionMinInfo(); // The section data starts after the header, the segment load command (and // section headers) and the symbol table. @@ -744,6 +780,12 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, sizeof(MachO::segment_command_64) + NumSections * sizeof(MachO::section_64): sizeof(MachO::segment_command) + NumSections * sizeof(MachO::section); + // Add the deployment target version info load command size, if used. + if (VersionInfo.Major != 0) { + ++NumLoadCommands; + LoadCommandsSize += sizeof(MachO::version_min_command); + } + // Add the data-in-code load command size, if used. unsigned NumDataRegions = Asm.getDataRegions().size(); if (NumDataRegions) { @@ -751,6 +793,14 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, LoadCommandsSize += sizeof(MachO::linkedit_data_command); } + // Add the loh load command size, if used. + uint64_t LOHRawSize = Asm.getLOHContainer().getEmitSize(*this, Layout); + uint64_t LOHSize = RoundUpToAlignment(LOHRawSize, is64Bit() ? 8 : 4); + if (LOHSize) { + ++NumLoadCommands; + LoadCommandsSize += sizeof(MachO::linkedit_data_command); + } + // Add the symbol table load command sizes, if used. unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() + UndefinedSymbolData.size(); @@ -816,6 +866,20 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, RelocTableEnd += NumRelocs * sizeof(MachO::any_relocation_info); } + // Write out the deployment target information, if it's available. + if (VersionInfo.Major != 0) { + assert(VersionInfo.Update < 256 && "unencodable update target version"); + assert(VersionInfo.Minor < 256 && "unencodable minor target version"); + assert(VersionInfo.Major < 65536 && "unencodable major target version"); + uint32_t EncodedVersion = VersionInfo.Update | (VersionInfo.Minor << 8) | + (VersionInfo.Major << 16); + Write32(VersionInfo.Kind == MCVM_OSXVersionMin ? MachO::LC_VERSION_MIN_MACOSX : + MachO::LC_VERSION_MIN_IPHONEOS); + Write32(sizeof(MachO::version_min_command)); + Write32(EncodedVersion); + Write32(0); // reserved. + } + // Write the data-in-code load command, if used. uint64_t DataInCodeTableEnd = RelocTableEnd + NumDataRegions * 8; if (NumDataRegions) { @@ -825,6 +889,12 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, DataRegionsSize); } + // Write the loh load command, if used. + uint64_t LOHTableEnd = DataInCodeTableEnd + LOHSize; + if (LOHSize) + WriteLinkeditLoadCommand(MachO::LC_LINKER_OPTIMIZATION_HINT, + DataInCodeTableEnd, LOHSize); + // Write the symbol table load command, if used. if (NumSymbols) { unsigned FirstLocalSymbol = 0; @@ -841,10 +911,10 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, // If used, the indirect symbols are written after the section data. if (NumIndirectSymbols) - IndirectSymbolOffset = DataInCodeTableEnd; + IndirectSymbolOffset = LOHTableEnd; // The symbol table is written after the indirect symbol data. - uint64_t SymbolTableOffset = DataInCodeTableEnd + IndirectSymbolSize; + uint64_t SymbolTableOffset = LOHTableEnd + IndirectSymbolSize; // The string table is written after symbol table. uint64_t StringTableOffset = @@ -911,17 +981,28 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, Write16(Data->Kind); } + // Write out the loh commands, if there is one. + if (LOHSize) { +#ifndef NDEBUG + unsigned Start = OS.tell(); +#endif + Asm.getLOHContainer().Emit(*this, Layout); + // Pad to a multiple of the pointer size. + WriteBytes("", OffsetToAlignment(LOHRawSize, is64Bit() ? 8 : 4)); + assert(OS.tell() - Start == LOHSize); + } + // Write the symbol table data, if used. if (NumSymbols) { // Write the indirect symbol entries. for (MCAssembler::const_indirect_symbol_iterator it = Asm.indirect_symbol_begin(), ie = Asm.indirect_symbol_end(); it != ie; ++it) { - // Indirect symbols in the non lazy symbol pointer section have some + // Indirect symbols in the non-lazy symbol pointer section have some // special handling. const MCSectionMachO &Section = static_cast<const MCSectionMachO&>(it->SectionData->getSection()); - if (Section.getType() == MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) { + if (Section.getType() == MachO::S_NON_LAZY_SYMBOL_POINTERS) { // If this symbol is defined and internal, mark it as such. if (it->Symbol->isDefined() && !Asm.getSymbolData(*it->Symbol).isExternal()) { diff --git a/contrib/llvm/lib/MC/StringTableBuilder.cpp b/contrib/llvm/lib/MC/StringTableBuilder.cpp new file mode 100644 index 0000000..db58ece --- /dev/null +++ b/contrib/llvm/lib/MC/StringTableBuilder.cpp @@ -0,0 +1,51 @@ +//===-- StringTableBuilder.cpp - String table building utility ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/StringTableBuilder.h" +#include "llvm/ADT/SmallVector.h" + +using namespace llvm; + +static bool compareBySuffix(StringRef a, StringRef b) { + size_t sizeA = a.size(); + size_t sizeB = b.size(); + size_t len = std::min(sizeA, sizeB); + for (size_t i = 0; i < len; ++i) { + char ca = a[sizeA - i - 1]; + char cb = b[sizeB - i - 1]; + if (ca != cb) + return ca > cb; + } + return sizeA > sizeB; +} + +void StringTableBuilder::finalize() { + SmallVector<StringRef, 8> Strings; + for (auto i = StringIndexMap.begin(), e = StringIndexMap.end(); i != e; ++i) + Strings.push_back(i->getKey()); + + std::sort(Strings.begin(), Strings.end(), compareBySuffix); + + // FIXME: Starting with a null byte is ELF specific. Generalize this so we + // can use the class with other object formats. + StringTable += '\x00'; + + StringRef Previous; + for (StringRef s : Strings) { + if (Previous.endswith(s)) { + StringIndexMap[s] = StringTable.size() - 1 - s.size(); + continue; + } + + StringIndexMap[s] = StringTable.size(); + StringTable += s; + StringTable += '\x00'; + Previous = s; + } +} diff --git a/contrib/llvm/lib/MC/SubtargetFeature.cpp b/contrib/llvm/lib/MC/SubtargetFeature.cpp index 2fb91f2..27525c7 100644 --- a/contrib/llvm/lib/MC/SubtargetFeature.cpp +++ b/contrib/llvm/lib/MC/SubtargetFeature.cpp @@ -51,40 +51,12 @@ static inline bool isEnabled(const StringRef Feature) { return Ch == '+'; } -/// PrependFlag - Return a string with a prepended flag; '+' or '-'. -/// -static inline std::string PrependFlag(const StringRef Feature, - bool IsEnabled) { - assert(!Feature.empty() && "Empty string"); - if (hasFlag(Feature)) - return Feature; - std::string Prefix = IsEnabled ? "+" : "-"; - Prefix += Feature; - return Prefix; -} - /// Split - Splits a string of comma separated items in to a vector of strings. /// static void Split(std::vector<std::string> &V, const StringRef S) { - if (S.empty()) - return; - - // Start at beginning of string. - size_t Pos = 0; - while (true) { - // Find the next comma - size_t Comma = S.find(',', Pos); - // If no comma found then the rest of the string is used - if (Comma == std::string::npos) { - // Add string to vector - V.push_back(S.substr(Pos)); - break; - } - // Otherwise add substring to vector - V.push_back(S.substr(Pos, Comma - Pos)); - // Advance to next item - Pos = Comma + 1; - } + SmallVector<StringRef, 2> Tmp; + S.split(Tmp, ",", -1, false /* KeepEmpty */); + V.assign(Tmp.begin(), Tmp.end()); } /// Join a vector of strings to a string with a comma separating each element. @@ -109,63 +81,55 @@ static std::string Join(const std::vector<std::string> &V) { } /// Adding features. -void SubtargetFeatures::AddFeature(const StringRef String, - bool IsEnabled) { - // Don't add empty features - if (!String.empty()) { - // Convert to lowercase, prepend flag and add to vector - Features.push_back(PrependFlag(String.lower(), IsEnabled)); - } +void SubtargetFeatures::AddFeature(const StringRef String) { + // Don't add empty features or features we already have. + if (!String.empty()) + // Convert to lowercase, prepend flag if we don't already have a flag. + Features.push_back(hasFlag(String) ? String.str() : "+" + String.lower()); } /// Find KV in array using binary search. -static const SubtargetFeatureKV *Find(StringRef S, const SubtargetFeatureKV *A, - size_t L) { - // Determine the end of the array - const SubtargetFeatureKV *Hi = A + L; +static const SubtargetFeatureKV *Find(StringRef S, + ArrayRef<SubtargetFeatureKV> A) { // Binary search the array - const SubtargetFeatureKV *F = std::lower_bound(A, Hi, S); + auto F = std::lower_bound(A.begin(), A.end(), S); // If not found then return NULL - if (F == Hi || StringRef(F->Key) != S) return NULL; + if (F == A.end() || StringRef(F->Key) != S) return nullptr; // Return the found array item return F; } /// getLongestEntryLength - Return the length of the longest entry in the table. /// -static size_t getLongestEntryLength(const SubtargetFeatureKV *Table, - size_t Size) { +static size_t getLongestEntryLength(ArrayRef<SubtargetFeatureKV> Table) { size_t MaxLen = 0; - for (size_t i = 0; i < Size; i++) - MaxLen = std::max(MaxLen, std::strlen(Table[i].Key)); + for (auto &I : Table) + MaxLen = std::max(MaxLen, std::strlen(I.Key)); return MaxLen; } /// Display help for feature choices. /// -static void Help(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize, - const SubtargetFeatureKV *FeatTable, size_t FeatTableSize) { +static void Help(ArrayRef<SubtargetFeatureKV> CPUTable, + ArrayRef<SubtargetFeatureKV> FeatTable) { // Determine the length of the longest CPU and Feature entries. - unsigned MaxCPULen = getLongestEntryLength(CPUTable, CPUTableSize); - unsigned MaxFeatLen = getLongestEntryLength(FeatTable, FeatTableSize); + unsigned MaxCPULen = getLongestEntryLength(CPUTable); + unsigned MaxFeatLen = getLongestEntryLength(FeatTable); // Print the CPU table. errs() << "Available CPUs for this target:\n\n"; - for (size_t i = 0; i != CPUTableSize; i++) - errs() << format(" %-*s - %s.\n", - MaxCPULen, CPUTable[i].Key, CPUTable[i].Desc); + for (auto &CPU : CPUTable) + errs() << format(" %-*s - %s.\n", MaxCPULen, CPU.Key, CPU.Desc); errs() << '\n'; // Print the Feature table. errs() << "Available features for this target:\n\n"; - for (size_t i = 0; i != FeatTableSize; i++) - errs() << format(" %-*s - %s.\n", - MaxFeatLen, FeatTable[i].Key, FeatTable[i].Desc); + for (auto &Feature : FeatTable) + errs() << format(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc); errs() << '\n'; errs() << "Use +feature to enable a feature, or -feature to disable it.\n" "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n"; - std::exit(1); } //===----------------------------------------------------------------------===// @@ -187,16 +151,13 @@ std::string SubtargetFeatures::getString() const { /// static void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize) { - for (size_t i = 0; i < FeatureTableSize; ++i) { - const SubtargetFeatureKV &FE = FeatureTable[i]; - + ArrayRef<SubtargetFeatureKV> FeatureTable) { + for (auto &FE : FeatureTable) { if (FeatureEntry->Value == FE.Value) continue; if (FeatureEntry->Implies & FE.Value) { Bits |= FE.Value; - SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); + SetImpliedBits(Bits, &FE, FeatureTable); } } } @@ -206,16 +167,13 @@ void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, /// static void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize) { - for (size_t i = 0; i < FeatureTableSize; ++i) { - const SubtargetFeatureKV &FE = FeatureTable[i]; - + ArrayRef<SubtargetFeatureKV> FeatureTable) { + for (auto &FE : FeatureTable) { if (FeatureEntry->Value == FE.Value) continue; if (FE.Implies & FeatureEntry->Value) { Bits &= ~FE.Value; - ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); + ClearImpliedBits(Bits, &FE, FeatureTable); } } } @@ -224,23 +182,23 @@ void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, /// bits. uint64_t SubtargetFeatures::ToggleFeature(uint64_t Bits, const StringRef Feature, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize) { + ArrayRef<SubtargetFeatureKV> FeatureTable) { + // Find feature in table. const SubtargetFeatureKV *FeatureEntry = - Find(StripFlag(Feature), FeatureTable, FeatureTableSize); + Find(StripFlag(Feature), FeatureTable); // If there is a match if (FeatureEntry) { if ((Bits & FeatureEntry->Value) == FeatureEntry->Value) { Bits &= ~FeatureEntry->Value; // For each feature that implies this, clear it. - ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); + ClearImpliedBits(Bits, FeatureEntry, FeatureTable); } else { Bits |= FeatureEntry->Value; // For each feature that this implies, set it. - SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); + SetImpliedBits(Bits, FeatureEntry, FeatureTable); } } else { errs() << "'" << Feature @@ -254,20 +212,20 @@ SubtargetFeatures::ToggleFeature(uint64_t Bits, const StringRef Feature, /// getFeatureBits - Get feature bits a CPU. /// -uint64_t SubtargetFeatures::getFeatureBits(const StringRef CPU, - const SubtargetFeatureKV *CPUTable, - size_t CPUTableSize, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize) { - if (!FeatureTableSize || !CPUTableSize) +uint64_t +SubtargetFeatures::getFeatureBits(const StringRef CPU, + ArrayRef<SubtargetFeatureKV> CPUTable, + ArrayRef<SubtargetFeatureKV> FeatureTable) { + + if (CPUTable.empty() || FeatureTable.empty()) return 0; #ifndef NDEBUG - for (size_t i = 1; i < CPUTableSize; i++) { + for (size_t i = 1, e = CPUTable.size(); i != e; ++i) { assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 && "CPU table is not sorted"); } - for (size_t i = 1; i < FeatureTableSize; i++) { + for (size_t i = 1, e = FeatureTable.size(); i != e; ++i) { assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 && "CPU features table is not sorted"); } @@ -276,21 +234,21 @@ uint64_t SubtargetFeatures::getFeatureBits(const StringRef CPU, // Check if help is needed if (CPU == "help") - Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); + Help(CPUTable, FeatureTable); // Find CPU entry if CPU name is specified. - if (!CPU.empty()) { - const SubtargetFeatureKV *CPUEntry = Find(CPU, CPUTable, CPUTableSize); + else if (!CPU.empty()) { + const SubtargetFeatureKV *CPUEntry = Find(CPU, CPUTable); + // If there is a match if (CPUEntry) { // Set base feature bits Bits = CPUEntry->Value; // Set the feature implied by this CPU feature, if any. - for (size_t i = 0; i < FeatureTableSize; ++i) { - const SubtargetFeatureKV &FE = FeatureTable[i]; + for (auto &FE : FeatureTable) { if (CPUEntry->Value & FE.Value) - SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); + SetImpliedBits(Bits, &FE, FeatureTable); } } else { errs() << "'" << CPU @@ -300,16 +258,14 @@ uint64_t SubtargetFeatures::getFeatureBits(const StringRef CPU, } // Iterate through each feature - for (size_t i = 0, E = Features.size(); i < E; i++) { - const StringRef Feature = Features[i]; - + for (auto &Feature : Features) { // Check for help if (Feature == "+help") - Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize); + Help(CPUTable, FeatureTable); // Find feature in table. const SubtargetFeatureKV *FeatureEntry = - Find(StripFlag(Feature), FeatureTable, FeatureTableSize); + Find(StripFlag(Feature), FeatureTable); // If there is a match if (FeatureEntry) { // Enable/disable feature in bits @@ -317,12 +273,12 @@ uint64_t SubtargetFeatures::getFeatureBits(const StringRef CPU, Bits |= FeatureEntry->Value; // For each feature that this implies, set it. - SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); + SetImpliedBits(Bits, FeatureEntry, FeatureTable); } else { Bits &= ~FeatureEntry->Value; // For each feature that implies this, clear it. - ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); + ClearImpliedBits(Bits, FeatureEntry, FeatureTable); } } else { errs() << "'" << Feature @@ -337,8 +293,8 @@ uint64_t SubtargetFeatures::getFeatureBits(const StringRef CPU, /// print - Print feature string. /// void SubtargetFeatures::print(raw_ostream &OS) const { - for (size_t i = 0, e = Features.size(); i != e; ++i) - OS << Features[i] << " "; + for (auto &F : Features) + OS << F << " "; OS << "\n"; } diff --git a/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp b/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp index d9ca86d..824895b 100644 --- a/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -11,13 +11,11 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "WinCOFFObjectWriter" - #include "llvm/MC/MCWinCOFFObjectWriter.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCAssembler.h" @@ -36,6 +34,8 @@ using namespace llvm; +#define DEBUG_TYPE "WinCOFFObjectWriter" + namespace { typedef SmallString<COFF::NameSize> name; @@ -82,7 +82,7 @@ struct COFFRelocation { COFF::relocation Data; COFFSymbol *Symb; - COFFRelocation() : Symb(NULL) {} + COFFRelocation() : Symb(nullptr) {} static size_t size() { return COFF::RelocationSize; } }; @@ -119,13 +119,13 @@ public: class WinCOFFObjectWriter : public MCObjectWriter { public: - typedef std::vector<COFFSymbol*> symbols; - typedef std::vector<COFFSection*> sections; + typedef std::vector<std::unique_ptr<COFFSymbol>> symbols; + typedef std::vector<std::unique_ptr<COFFSection>> sections; typedef DenseMap<MCSymbol const *, COFFSymbol *> symbol_map; typedef DenseMap<MCSection const *, COFFSection *> section_map; - llvm::OwningPtr<MCWinCOFFObjectTargetWriter> TargetObjectWriter; + std::unique_ptr<MCWinCOFFObjectTargetWriter> TargetObjectWriter; // Root level file contents. COFF::header Header; @@ -138,7 +138,6 @@ public: symbol_map SymbolMap; WinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW, raw_ostream &OS); - virtual ~WinCOFFObjectWriter(); COFFSymbol *createSymbol(StringRef Name); COFFSymbol *GetOrCreateCOFFSymbol(const MCSymbol * Symbol); @@ -154,30 +153,29 @@ public: void MakeSymbolReal(COFFSymbol &S, size_t Index); void MakeSectionReal(COFFSection &S, size_t Number); - bool ExportSymbol(MCSymbolData const &SymbolData, MCAssembler &Asm); + bool ExportSymbol(const MCSymbol &Symbol, MCAssembler &Asm); bool IsPhysicalSection(COFFSection *S); // Entity writing methods. void WriteFileHeader(const COFF::header &Header); - void WriteSymbol(const COFFSymbol *S); + void WriteSymbol(const COFFSymbol &S); void WriteAuxiliarySymbols(const COFFSymbol::AuxiliarySymbols &S); void WriteSectionHeader(const COFF::section &S); void WriteRelocation(const COFF::relocation &R); // MCObjectWriter interface implementation. - void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout); + void ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) override; - void RecordRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, - uint64_t &FixedValue); + void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, bool &IsPCRel, + uint64_t &FixedValue) override; - void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); + void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; }; } @@ -194,10 +192,10 @@ static inline void write_uint32_le(void *Data, uint32_t const &Value) { COFFSymbol::COFFSymbol(StringRef name) : Name(name.begin(), name.end()) - , Other(NULL) - , Section(NULL) + , Other(nullptr) + , Section(nullptr) , Relocations(0) - , MCData(NULL) { + , MCData(nullptr) { memset(&Data, 0, sizeof(Data)); } @@ -216,7 +214,7 @@ void COFFSymbol::set_name_offset(uint32_t Offset) { /// logic to decide if the symbol should be reported in the symbol table bool COFFSymbol::should_keep() const { // no section means its external, keep it - if (Section == NULL) + if (!Section) return true; // if it has relocations pointing at it, keep it @@ -246,8 +244,8 @@ bool COFFSymbol::should_keep() const { COFFSection::COFFSection(StringRef name) : Name(name) - , MCData(NULL) - , Symbol(NULL) { + , MCData(nullptr) + , Symbol(nullptr) { memset(&Header, 0, sizeof(Header)); } @@ -310,13 +308,6 @@ WinCOFFObjectWriter::WinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW, Header.Machine = TargetObjectWriter->getMachine(); } -WinCOFFObjectWriter::~WinCOFFObjectWriter() { - for (symbols::iterator I = Symbols.begin(), E = Symbols.end(); I != E; ++I) - delete *I; - for (sections::iterator I = Sections.begin(), E = Sections.end(); I != E; ++I) - delete *I; -} - COFFSymbol *WinCOFFObjectWriter::createSymbol(StringRef Name) { return createCOFFEntity<COFFSymbol>(Name, Symbols); } @@ -340,24 +331,30 @@ COFFSection *WinCOFFObjectWriter::createSection(StringRef Name) { template <typename object_t, typename list_t> object_t *WinCOFFObjectWriter::createCOFFEntity(StringRef Name, list_t &List) { - object_t *Object = new object_t(Name); - - List.push_back(Object); + List.push_back(make_unique<object_t>(Name)); - return Object; + return List.back().get(); } /// This function takes a section data object from the assembler /// and creates the associated COFF section staging object. void WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) { assert(SectionData.getSection().getVariant() == MCSection::SV_COFF - && "Got non COFF section in the COFF backend!"); + && "Got non-COFF section in the COFF backend!"); // FIXME: Not sure how to verify this (at least in a debug build). MCSectionCOFF const &Sec = static_cast<MCSectionCOFF const &>(SectionData.getSection()); COFFSection *coff_section = createSection(Sec.getSectionName()); COFFSymbol *coff_symbol = createSymbol(Sec.getSectionName()); + if (Sec.getSelection() != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { + if (const MCSymbol *S = Sec.getCOMDATSymbol()) { + COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(S); + if (COMDATSymbol->Section) + report_fatal_error("two sections have the same comdat"); + COMDATSymbol->Section = coff_section; + } + } coff_section->Symbol = coff_symbol; coff_symbol->Section = coff_section; @@ -396,7 +393,19 @@ void WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) { SectionMap[&SectionData.getSection()] = coff_section; } -/// This function takes a section data object from the assembler +static uint64_t getSymbolValue(const MCSymbolData &Data, + const MCAsmLayout &Layout) { + if (Data.isCommon() && Data.isExternal()) + return Data.getCommonSize(); + + uint64_t Res; + if (!Layout.getSymbolOffset(&Data, Res)) + return 0; + + return Res; +} + +/// This function takes a symbol data object from the assembler /// and creates the associated COFF symbol staging object. void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData, MCAssembler &Assembler, @@ -438,54 +447,89 @@ void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData, coff_symbol->MCData = &SymbolData; } else { - const MCSymbolData &ResSymData = - Assembler.getSymbolData(Symbol.AliasedSymbol()); - - if (Symbol.isVariable()) { - int64_t Addr; - if (Symbol.getVariableValue()->EvaluateAsAbsolute(Addr, Layout)) - coff_symbol->Data.Value = Addr; - } + const MCSymbolData &ResSymData = Assembler.getSymbolData(Symbol); + const MCSymbol *Base = Layout.getBaseSymbol(Symbol); + coff_symbol->Data.Value = getSymbolValue(ResSymData, Layout); coff_symbol->Data.Type = (ResSymData.getFlags() & 0x0000FFFF) >> 0; coff_symbol->Data.StorageClass = (ResSymData.getFlags() & 0x00FF0000) >> 16; // If no storage class was specified in the streamer, define it here. if (coff_symbol->Data.StorageClass == 0) { - bool external = ResSymData.isExternal() || (ResSymData.Fragment == NULL); + bool IsExternal = + ResSymData.isExternal() || + (!ResSymData.getFragment() && !ResSymData.getSymbol().isVariable()); - coff_symbol->Data.StorageClass = - external ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC; + coff_symbol->Data.StorageClass = IsExternal + ? COFF::IMAGE_SYM_CLASS_EXTERNAL + : COFF::IMAGE_SYM_CLASS_STATIC; } - if (Symbol.isAbsolute() || Symbol.AliasedSymbol().isVariable()) + if (!Base) { coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; - else if (ResSymData.Fragment != NULL) - coff_symbol->Section = - SectionMap[&ResSymData.Fragment->getParent()->getSection()]; + } else { + const MCSymbolData &BaseData = Assembler.getSymbolData(*Base); + if (BaseData.Fragment) { + COFFSection *Sec = + SectionMap[&BaseData.Fragment->getParent()->getSection()]; + + if (coff_symbol->Section && coff_symbol->Section != Sec) + report_fatal_error("conflicting sections for symbol"); + + coff_symbol->Section = Sec; + } + } coff_symbol->MCData = &ResSymData; } } +// 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 + +// Encode a string table entry offset in base 64, padded to 6 chars, and +// prefixed with a double slash: '//AAAAAA', '//AAAAAB', ... +// Buffer must be at least 8 bytes large. No terminating null appended. +static void encodeBase64StringEntry(char* Buffer, uint64_t Value) { + assert(Value > Max7DecimalOffset && Value <= MaxBase64Offset && + "Illegal section name encoding for value"); + + static const char Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + + Buffer[0] = '/'; + Buffer[1] = '/'; + + char* Ptr = Buffer + 7; + for (unsigned i = 0; i < 6; ++i) { + unsigned Rem = Value % 64; + Value /= 64; + *(Ptr--) = Alphabet[Rem]; + } +} + /// making a section real involves assigned it a number and putting /// name into the string table if needed void WinCOFFObjectWriter::MakeSectionReal(COFFSection &S, size_t Number) { if (S.Name.size() > COFF::NameSize) { - const unsigned Max6DecimalSize = 999999; - const unsigned Max7DecimalSize = 9999999; uint64_t StringTableEntry = Strings.insert(S.Name.c_str()); - if (StringTableEntry <= Max6DecimalSize) { + if (StringTableEntry <= Max6DecimalOffset) { std::sprintf(S.Header.Name, "/%d", unsigned(StringTableEntry)); - } else if (StringTableEntry <= Max7DecimalSize) { + } 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); + } 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 9,999,999 bytes."); + report_fatal_error("COFF string table is greater than 64 GB."); } } else std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size()); @@ -505,16 +549,24 @@ void WinCOFFObjectWriter::MakeSymbolReal(COFFSymbol &S, size_t Index) { S.Index = Index; } -bool WinCOFFObjectWriter::ExportSymbol(MCSymbolData const &SymbolData, +bool WinCOFFObjectWriter::ExportSymbol(const MCSymbol &Symbol, MCAssembler &Asm) { // This doesn't seem to be right. Strings referred to from the .data section // need symbols so they can be linked to code in the .text section right? - // return Asm.isSymbolLinkerVisible (&SymbolData); + // return Asm.isSymbolLinkerVisible(Symbol); + + // Non-temporary labels should always be visible to the linker. + if (!Symbol.isTemporary()) + return true; + + // Absolute temporary labels are never visible. + if (!Symbol.isInSection()) + return false; // For now, all non-variable symbols are exported, // the linker will sort the rest out for us. - return SymbolData.isExternal() || !SymbolData.getSymbol().isVariable(); + return !Symbol.isVariable(); } bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) { @@ -535,14 +587,14 @@ void WinCOFFObjectWriter::WriteFileHeader(const COFF::header &Header) { WriteLE16(Header.Characteristics); } -void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol *S) { - WriteBytes(StringRef(S->Data.Name, COFF::NameSize)); - WriteLE32(S->Data.Value); - WriteLE16(S->Data.SectionNumber); - WriteLE16(S->Data.Type); - Write8(S->Data.StorageClass); - Write8(S->Data.NumberOfAuxSymbols); - WriteAuxiliarySymbols(S->Aux); +void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol &S) { + WriteBytes(StringRef(S.Data.Name, COFF::NameSize)); + WriteLE32(S.Data.Value); + WriteLE16(S.Data.SectionNumber); + WriteLE16(S.Data.Type); + Write8(S.Data.StorageClass); + Write8(S.Data.NumberOfAuxSymbols); + WriteAuxiliarySymbols(S.Aux); } void WinCOFFObjectWriter::WriteAuxiliarySymbols( @@ -614,16 +666,42 @@ void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, // "Define" each section & symbol. This creates section & symbol // entries in the staging area. - for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e; i++) - DefineSection(*i); + static_assert(sizeof(((COFF::AuxiliaryFile *)nullptr)->FileName) == COFF::SymbolSize, + "size mismatch for COFF::AuxiliaryFile::FileName"); + for (auto FI = Asm.file_names_begin(), FE = Asm.file_names_end(); + FI != FE; ++FI) { + // round up to calculate the number of auxiliary symbols required + unsigned Count = (FI->size() + COFF::SymbolSize - 1) / COFF::SymbolSize; + + COFFSymbol *file = createSymbol(".file"); + file->Data.SectionNumber = COFF::IMAGE_SYM_DEBUG; + file->Data.StorageClass = COFF::IMAGE_SYM_CLASS_FILE; + file->Aux.resize(Count); + + unsigned Offset = 0; + unsigned Length = FI->size(); + for (auto & Aux : file->Aux) { + Aux.AuxType = ATFile; + + if (Length > COFF::SymbolSize) { + memcpy(Aux.Aux.File.FileName, FI->c_str() + Offset, COFF::SymbolSize); + Length = Length - COFF::SymbolSize; + } else { + memcpy(Aux.Aux.File.FileName, FI->c_str() + Offset, Length); + memset(&Aux.Aux.File.FileName[Length], 0, COFF::SymbolSize - Length); + Length = 0; + } - for (MCAssembler::const_symbol_iterator i = Asm.symbol_begin(), - e = Asm.symbol_end(); - i != e; i++) { - if (ExportSymbol(*i, Asm)) { - DefineSymbol(*i, Asm, Layout); + Offset = Offset + COFF::SymbolSize; } } + + for (const auto & Section : Asm) + DefineSection(Section); + + for (MCSymbolData &SD : Asm.symbols()) + if (ExportSymbol(SD.getSymbol(), Asm)) + DefineSymbol(SD, Asm, Layout); } void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, @@ -631,12 +709,18 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, + bool &IsPCRel, uint64_t &FixedValue) { - assert(Target.getSymA() != NULL && "Relocation must reference a symbol!"); + assert(Target.getSymA() && "Relocation must reference a symbol!"); const MCSymbol &Symbol = Target.getSymA()->getSymbol(); const MCSymbol &A = Symbol.AliasedSymbol(); - MCSymbolData &A_SD = Asm.getSymbolData(A); + if (!Asm.hasSymbolData(A)) + Asm.getContext().FatalError( + Fixup.getLoc(), + Twine("symbol '") + A.getName() + "' can not be undefined"); + + const MCSymbolData &A_SD = Asm.getSymbolData(A); MCSectionData const *SectionData = Fragment->getParent(); @@ -648,14 +732,25 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, COFFSection *coff_section = SectionMap[&SectionData->getSection()]; COFFSymbol *coff_symbol = SymbolMap[&A_SD.getSymbol()]; - const MCSymbolRefExpr *SymA = Target.getSymA(); const MCSymbolRefExpr *SymB = Target.getSymB(); - const bool CrossSection = SymB && - &SymA->getSymbol().getSection() != &SymB->getSymbol().getSection(); + bool CrossSection = false; - if (Target.getSymB()) { - const MCSymbol *B = &Target.getSymB()->getSymbol(); - MCSymbolData &B_SD = Asm.getSymbolData(*B); + if (SymB) { + const MCSymbol *B = &SymB->getSymbol(); + const MCSymbolData &B_SD = Asm.getSymbolData(*B); + if (!B_SD.getFragment()) + Asm.getContext().FatalError( + Fixup.getLoc(), + Twine("symbol '") + B->getName() + + "' can not be undefined in a subtraction expression"); + + if (!A_SD.getFragment()) + Asm.getContext().FatalError( + Fixup.getLoc(), + Twine("symbol '") + Symbol.getName() + + "' can not be undefined in a subtraction expression"); + + CrossSection = &Symbol.getSection() != &B->getSection(); // Offset of the symbol in the section int64_t a = Layout.getSymbolOffset(&B_SD); @@ -694,11 +789,52 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, // FIXME: Can anyone explain what this does other than adjust for the size // of the offset? - if (Reloc.Data.Type == COFF::IMAGE_REL_AMD64_REL32 || - Reloc.Data.Type == COFF::IMAGE_REL_I386_REL32) + if ((Header.Machine == COFF::IMAGE_FILE_MACHINE_AMD64 && + Reloc.Data.Type == COFF::IMAGE_REL_AMD64_REL32) || + (Header.Machine == COFF::IMAGE_FILE_MACHINE_I386 && + Reloc.Data.Type == COFF::IMAGE_REL_I386_REL32)) FixedValue += 4; - coff_section->Relocations.push_back(Reloc); + if (Header.Machine == COFF::IMAGE_FILE_MACHINE_ARMNT) { + switch (Reloc.Data.Type) { + case COFF::IMAGE_REL_ARM_ABSOLUTE: + case COFF::IMAGE_REL_ARM_ADDR32: + case COFF::IMAGE_REL_ARM_ADDR32NB: + case COFF::IMAGE_REL_ARM_TOKEN: + case COFF::IMAGE_REL_ARM_SECTION: + case COFF::IMAGE_REL_ARM_SECREL: + break; + case COFF::IMAGE_REL_ARM_BRANCH11: + case COFF::IMAGE_REL_ARM_BLX11: + // IMAGE_REL_ARM_BRANCH11 and IMAGE_REL_ARM_BLX11 are only used for + // pre-ARMv7, which implicitly rules it out of ARMNT (it would be valid + // for Windows CE). + case COFF::IMAGE_REL_ARM_BRANCH24: + case COFF::IMAGE_REL_ARM_BLX24: + case COFF::IMAGE_REL_ARM_MOV32A: + // IMAGE_REL_ARM_BRANCH24, IMAGE_REL_ARM_BLX24, IMAGE_REL_ARM_MOV32A are + // only used for ARM mode code, which is documented as being unsupported + // by Windows on ARM. Empirical proof indicates that masm is able to + // generate the relocations however the rest of the MSVC toolchain is + // unable to handle it. + llvm_unreachable("unsupported relocation"); + break; + case COFF::IMAGE_REL_ARM_MOV32T: + break; + case COFF::IMAGE_REL_ARM_BRANCH20T: + case COFF::IMAGE_REL_ARM_BRANCH24T: + case COFF::IMAGE_REL_ARM_BLX23T: + // IMAGE_REL_BRANCH20T, IMAGE_REL_ARM_BRANCH24T, IMAGE_REL_ARM_BLX23T all + // perform a 4 byte adjustment to the relocation. Relative branches are + // offset by 4 on ARM, however, because there is no RELA relocations, all + // branches are offset by 4. + FixedValue = FixedValue + 4; + break; + } + } + + if (TargetObjectWriter->recordRelocation(Fixup)) + coff_section->Relocations.push_back(Reloc); } void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, @@ -707,77 +843,64 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, Header.NumberOfSections = 0; DenseMap<COFFSection *, uint16_t> SectionIndices; - for (sections::iterator i = Sections.begin(), - e = Sections.end(); i != e; i++) { - if (Layout.getSectionAddressSize((*i)->MCData) > 0) { - size_t Number = ++Header.NumberOfSections; - SectionIndices[*i] = Number; - MakeSectionReal(**i, Number); - } else { - (*i)->Number = -1; - } + for (auto & Section : Sections) { + size_t Number = ++Header.NumberOfSections; + SectionIndices[Section.get()] = Number; + MakeSectionReal(*Section, Number); } Header.NumberOfSymbols = 0; - for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) { - COFFSymbol *coff_symbol = *i; - MCSymbolData const *SymbolData = coff_symbol->MCData; - + for (auto & Symbol : Symbols) { // Update section number & offset for symbols that have them. - if ((SymbolData != NULL) && (SymbolData->Fragment != NULL)) { - assert(coff_symbol->Section != NULL); + if (Symbol->Section) + Symbol->Data.SectionNumber = Symbol->Section->Number; - coff_symbol->Data.SectionNumber = coff_symbol->Section->Number; - coff_symbol->Data.Value = Layout.getFragmentOffset(SymbolData->Fragment) - + SymbolData->Offset; - } - - if (coff_symbol->should_keep()) { - MakeSymbolReal(*coff_symbol, Header.NumberOfSymbols++); + if (Symbol->should_keep()) { + MakeSymbolReal(*Symbol, Header.NumberOfSymbols++); // Update auxiliary symbol info. - coff_symbol->Data.NumberOfAuxSymbols = coff_symbol->Aux.size(); - Header.NumberOfSymbols += coff_symbol->Data.NumberOfAuxSymbols; + Symbol->Data.NumberOfAuxSymbols = Symbol->Aux.size(); + Header.NumberOfSymbols += Symbol->Data.NumberOfAuxSymbols; } else - coff_symbol->Index = -1; + Symbol->Index = -1; } // Fixup weak external references. - for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) { - COFFSymbol *coff_symbol = *i; - if (coff_symbol->Other != NULL) { - assert(coff_symbol->Index != -1); - assert(coff_symbol->Aux.size() == 1 && - "Symbol must contain one aux symbol!"); - assert(coff_symbol->Aux[0].AuxType == ATWeakExternal && + for (auto & Symbol : Symbols) { + if (Symbol->Other) { + assert(Symbol->Index != -1); + assert(Symbol->Aux.size() == 1 && "Symbol must contain one aux symbol!"); + assert(Symbol->Aux[0].AuxType == ATWeakExternal && "Symbol's aux symbol must be a Weak External!"); - coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = coff_symbol->Other->Index; + Symbol->Aux[0].Aux.WeakExternal.TagIndex = Symbol->Other->Index; } } // Fixup associative COMDAT sections. - for (sections::iterator i = Sections.begin(), - e = Sections.end(); i != e; i++) { - if ((*i)->Symbol->Aux[0].Aux.SectionDefinition.Selection != + for (auto & Section : Sections) { + if (Section->Symbol->Aux[0].Aux.SectionDefinition.Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) continue; - const MCSectionCOFF &MCSec = static_cast<const MCSectionCOFF &>( - (*i)->MCData->getSection()); + const MCSectionCOFF &MCSec = + static_cast<const MCSectionCOFF &>(Section->MCData->getSection()); - COFFSection *Assoc = SectionMap.lookup(MCSec.getAssocSection()); - if (!Assoc) { - report_fatal_error(Twine("Missing associated COMDAT section ") + - MCSec.getAssocSection()->getSectionName() + - " for section " + MCSec.getSectionName()); - } + const MCSymbol *COMDAT = MCSec.getCOMDATSymbol(); + assert(COMDAT); + COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(COMDAT); + assert(COMDATSymbol); + COFFSection *Assoc = COMDATSymbol->Section; + if (!Assoc) + report_fatal_error( + Twine("Missing associated COMDAT section for section ") + + MCSec.getSectionName()); // Skip this section if the associated section is unused. if (Assoc->Number == -1) continue; - (*i)->Symbol->Aux[0].Aux.SectionDefinition.Number = SectionIndices[Assoc]; + Section->Symbol->Aux[0].Aux.SectionDefinition.Number = SectionIndices[Assoc]; } @@ -788,15 +911,13 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, offset += COFF::HeaderSize; offset += COFF::SectionSize * Header.NumberOfSections; - for (MCAssembler::const_iterator i = Asm.begin(), - e = Asm.end(); - i != e; i++) { - COFFSection *Sec = SectionMap[&i->getSection()]; + for (const auto & Section : Asm) { + COFFSection *Sec = SectionMap[&Section.getSection()]; if (Sec->Number == -1) continue; - Sec->Header.SizeOfRawData = Layout.getSectionAddressSize(i); + Sec->Header.SizeOfRawData = Layout.getSectionAddressSize(&Section); if (IsPhysicalSection(Sec)) { Sec->Header.PointerToRawData = offset; @@ -823,16 +944,14 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, offset += COFF::RelocationSize * Sec->Relocations.size(); - for (relocations::iterator cr = Sec->Relocations.begin(), - er = Sec->Relocations.end(); - cr != er; ++cr) { - assert((*cr).Symb->Index != -1); - (*cr).Data.SymbolTableIndex = (*cr).Symb->Index; + for (auto & Relocation : Sec->Relocations) { + assert(Relocation.Symb->Index != -1); + Relocation.Data.SymbolTableIndex = Relocation.Symb->Index; } } - assert(Sec->Symbol->Aux.size() == 1 - && "Section's symbol must have one aux!"); + assert(Sec->Symbol->Aux.size() == 1 && + "Section's symbol must have one aux!"); AuxSymbol &Aux = Sec->Symbol->Aux[0]; assert(Aux.AuxType == ATSectionDefinition && "Section's symbol's aux symbol must be a Section Definition!"); @@ -845,7 +964,8 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, Header.PointerToSymbolTable = offset; - Header.TimeDateStamp = sys::TimeValue::now().toEpochTime(); + // We want a deterministic output. It looks like GNU as also writes 0 in here. + Header.TimeDateStamp = 0; // Write it all to disk... WriteFileHeader(Header); @@ -854,13 +974,13 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, sections::iterator i, ie; MCAssembler::const_iterator j, je; - for (i = Sections.begin(), ie = Sections.end(); i != ie; i++) - if ((*i)->Number != -1) { - if ((*i)->Relocations.size() >= 0xffff) { - (*i)->Header.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL; - } - WriteSectionHeader((*i)->Header); + for (auto & Section : Sections) { + if (Section->Number != -1) { + if (Section->Relocations.size() >= 0xffff) + Section->Header.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL; + WriteSectionHeader(Section->Header); } + } for (i = Sections.begin(), ie = Sections.end(), j = Asm.begin(), je = Asm.end(); @@ -890,11 +1010,8 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, WriteRelocation(r); } - for (relocations::const_iterator k = (*i)->Relocations.begin(), - ke = (*i)->Relocations.end(); - k != ke; k++) { - WriteRelocation(k->Data); - } + for (const auto & Relocation : (*i)->Relocations) + WriteRelocation(Relocation.Data); } else assert((*i)->Header.PointerToRelocations == 0 && "Section::PointerToRelocations is insane!"); @@ -904,9 +1021,9 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, assert(OS.tell() == Header.PointerToSymbolTable && "Header::PointerToSymbolTable is insane!"); - for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) - if ((*i)->Index != -1) - WriteSymbol(*i); + for (auto & Symbol : Symbols) + if (Symbol->Index != -1) + WriteSymbol(*Symbol); OS.write((char const *)&Strings.Data.front(), Strings.Data.size()); } diff --git a/contrib/llvm/lib/MC/WinCOFFStreamer.cpp b/contrib/llvm/lib/MC/WinCOFFStreamer.cpp index 5b5aad7..d391a3f 100644 --- a/contrib/llvm/lib/MC/WinCOFFStreamer.cpp +++ b/contrib/llvm/lib/MC/WinCOFFStreamer.cpp @@ -7,12 +7,11 @@ // //===----------------------------------------------------------------------===// // -// This file contains an implementation of a Win32 COFF object file streamer. +// This file contains an implementation of a Windows COFF object file streamer. // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "WinCOFFStreamer" - +#include "llvm/ADT/StringExtras.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmLayout.h" @@ -20,12 +19,14 @@ #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" #include "llvm/MC/MCWin64EH.h" +#include "llvm/MC/MCWinCOFFStreamer.h" #include "llvm/Support/COFF.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -34,308 +35,220 @@ using namespace llvm; -namespace { -class WinCOFFStreamer : public MCObjectStreamer { -public: - MCSymbol const *CurSymbol; - - WinCOFFStreamer(MCContext &Context, - MCAsmBackend &MAB, - MCCodeEmitter &CE, - raw_ostream &OS); - - void AddCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment, bool External); - - // MCStreamer interface - - virtual void InitSections(); - virtual void InitToTextSection(); - virtual void EmitLabel(MCSymbol *Symbol); - virtual void EmitDebugLabel(MCSymbol *Symbol); - virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); - virtual void EmitThumbFunc(MCSymbol *Func); - virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); - virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); - virtual void BeginCOFFSymbolDef(MCSymbol const *Symbol); - virtual void EmitCOFFSymbolStorageClass(int StorageClass); - virtual void EmitCOFFSymbolType(int Type); - virtual void EndCOFFSymbolDef(); - virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); - virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); - virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment); - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment); - virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size,unsigned ByteAlignment); - virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment); - virtual void EmitFileDirective(StringRef Filename); - virtual void EmitIdent(StringRef IdentString); - virtual void EmitWin64EHHandlerData(); - virtual void FinishImpl(); - -private: - virtual void EmitInstToData(const MCInst &Inst) { - MCDataFragment *DF = getOrCreateDataFragment(); - - SmallVector<MCFixup, 4> Fixups; - SmallString<256> Code; - raw_svector_ostream VecOS(Code); - getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups); - VecOS.flush(); - - // Add the fixups and data. - for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { - Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); - DF->getFixups().push_back(Fixups[i]); - } - DF->getContents().append(Code.begin(), Code.end()); - } +#define DEBUG_TYPE "WinCOFFStreamer" - void SetSection(StringRef Section, - unsigned Characteristics, - SectionKind Kind) { - SwitchSection(getContext().getCOFFSection(Section, Characteristics, Kind)); - } +namespace llvm { +MCWinCOFFStreamer::MCWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, + MCCodeEmitter &CE, raw_ostream &OS) + : MCObjectStreamer(Context, MAB, OS, &CE), CurSymbol(nullptr) {} - void SetSectionText() { - SetSection(".text", - COFF::IMAGE_SCN_CNT_CODE - | COFF::IMAGE_SCN_MEM_EXECUTE - | COFF::IMAGE_SCN_MEM_READ, - SectionKind::getText()); - EmitCodeAlignment(4, 0); - } +void MCWinCOFFStreamer::EmitInstToData(const MCInst &Inst, + const MCSubtargetInfo &STI) { + MCDataFragment *DF = getOrCreateDataFragment(); - void SetSectionData() { - SetSection(".data", - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA - | COFF::IMAGE_SCN_MEM_READ - | COFF::IMAGE_SCN_MEM_WRITE, - SectionKind::getDataRel()); - EmitCodeAlignment(4, 0); - } + SmallVector<MCFixup, 4> Fixups; + SmallString<256> Code; + raw_svector_ostream VecOS(Code); + getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups, STI); + VecOS.flush(); - void SetSectionBSS() { - SetSection(".bss", - COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA - | COFF::IMAGE_SCN_MEM_READ - | COFF::IMAGE_SCN_MEM_WRITE, - SectionKind::getBSS()); - EmitCodeAlignment(4, 0); + // Add the fixups and data. + for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { + Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); + DF->getFixups().push_back(Fixups[i]); } -}; -} // end anonymous namespace. - -WinCOFFStreamer::WinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, - MCCodeEmitter &CE, raw_ostream &OS) - : MCObjectStreamer(Context, 0, MAB, OS, &CE), CurSymbol(NULL) {} - -void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment, bool External) { - assert(!Symbol->isInSection() && "Symbol must not already have a section!"); - - std::string SectionName(".bss$linkonce"); - SectionName.append(Symbol->getName().begin(), Symbol->getName().end()); - - MCSymbolData &SymbolData = getAssembler().getOrCreateSymbolData(*Symbol); - - unsigned Characteristics = - COFF::IMAGE_SCN_LNK_COMDAT | - COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ | - COFF::IMAGE_SCN_MEM_WRITE; - - int Selection = COFF::IMAGE_COMDAT_SELECT_LARGEST; - - const MCSection *Section = MCStreamer::getContext().getCOFFSection( - SectionName, Characteristics, SectionKind::getBSS(), Symbol->getName(), - Selection); - MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section); - - if (SectionData.getAlignment() < ByteAlignment) - SectionData.setAlignment(ByteAlignment); - - SymbolData.setExternal(External); - - AssignSection(Symbol, Section); - - if (ByteAlignment != 1) - new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, &SectionData); - - SymbolData.setFragment(new MCFillFragment(0, 0, Size, &SectionData)); + DF->getContents().append(Code.begin(), Code.end()); } -// MCStreamer interface +void MCWinCOFFStreamer::InitSections() { + // FIXME: this is identical to the ELF one. + // This emulates the same behavior of GNU as. This makes it easier + // to compare the output as the major sections are in the same order. + SwitchSection(getContext().getObjectFileInfo()->getTextSection()); + EmitCodeAlignment(4); -void WinCOFFStreamer::InitToTextSection() { - SetSectionText(); -} + SwitchSection(getContext().getObjectFileInfo()->getDataSection()); + EmitCodeAlignment(4); + + SwitchSection(getContext().getObjectFileInfo()->getBSSSection()); + EmitCodeAlignment(4); -void WinCOFFStreamer::InitSections() { - SetSectionText(); - SetSectionData(); - SetSectionBSS(); - SetSectionText(); + SwitchSection(getContext().getObjectFileInfo()->getTextSection()); } -void WinCOFFStreamer::EmitLabel(MCSymbol *Symbol) { +void MCWinCOFFStreamer::EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); MCObjectStreamer::EmitLabel(Symbol); } -void WinCOFFStreamer::EmitDebugLabel(MCSymbol *Symbol) { - EmitLabel(Symbol); -} -void WinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { +void MCWinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { llvm_unreachable("not implemented"); } -void WinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) { +void MCWinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) { llvm_unreachable("not implemented"); } -bool WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, - MCSymbolAttr Attribute) { +bool MCWinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, + MCSymbolAttr Attribute) { assert(Symbol && "Symbol must be non-null!"); - assert((Symbol->isInSection() - ? Symbol->getSection().getVariant() == MCSection::SV_COFF - : true) && "Got non COFF section in the COFF backend!"); + assert((!Symbol->isInSection() || + Symbol->getSection().getVariant() == MCSection::SV_COFF) && + "Got non-COFF section in the COFF backend!"); + + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + switch (Attribute) { + default: return false; case MCSA_WeakReference: - case MCSA_Weak: { - MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); - SD.modifyFlags(COFF::SF_WeakExternal, COFF::SF_WeakExternal); - SD.setExternal(true); - } + case MCSA_Weak: + SD.modifyFlags(COFF::SF_WeakExternal, COFF::SF_WeakExternal); + SD.setExternal(true); break; - case MCSA_Global: - getAssembler().getOrCreateSymbolData(*Symbol).setExternal(true); + SD.setExternal(true); break; - - default: - return false; } return true; } -void WinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { +void MCWinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { llvm_unreachable("not implemented"); } -void WinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *Symbol) { - assert((Symbol->isInSection() - ? Symbol->getSection().getVariant() == MCSection::SV_COFF - : true) && "Got non COFF section in the COFF backend!"); - assert(CurSymbol == NULL && "EndCOFFSymbolDef must be called between calls " - "to BeginCOFFSymbolDef!"); +void MCWinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *Symbol) { + assert((!Symbol->isInSection() || + Symbol->getSection().getVariant() == MCSection::SV_COFF) && + "Got non-COFF section in the COFF backend!"); + + if (CurSymbol) + FatalError("starting a new symbol definition without completing the " + "previous one"); CurSymbol = Symbol; } -void WinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { - assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); - assert((StorageClass & ~0xFF) == 0 && "StorageClass must only have data in " - "the first byte!"); +void MCWinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { + if (!CurSymbol) + FatalError("storage class specified outside of symbol definition"); + + if (StorageClass & ~0xff) + FatalError(Twine("storage class value '") + itostr(StorageClass) + + "' out of range"); - getAssembler().getOrCreateSymbolData(*CurSymbol).modifyFlags( - StorageClass << COFF::SF_ClassShift, - COFF::SF_ClassMask); + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*CurSymbol); + SD.modifyFlags(StorageClass << COFF::SF_ClassShift, COFF::SF_ClassMask); } -void WinCOFFStreamer::EmitCOFFSymbolType(int Type) { - assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); - assert((Type & ~0xFFFF) == 0 && "Type must only have data in the first 2 " - "bytes"); +void MCWinCOFFStreamer::EmitCOFFSymbolType(int Type) { + if (!CurSymbol) + FatalError("symbol type specified outside of a symbol definition"); - getAssembler().getOrCreateSymbolData(*CurSymbol).modifyFlags( - Type << COFF::SF_TypeShift, - COFF::SF_TypeMask); + if (Type & ~0xffff) + FatalError(Twine("type value '") + itostr(Type) + "' out of range"); + + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*CurSymbol); + SD.modifyFlags(Type << COFF::SF_TypeShift, COFF::SF_TypeMask); } -void WinCOFFStreamer::EndCOFFSymbolDef() { - assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); - CurSymbol = NULL; +void MCWinCOFFStreamer::EndCOFFSymbolDef() { + if (!CurSymbol) + FatalError("ending symbol definition without starting one"); + CurSymbol = nullptr; } -void WinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) -{ +void MCWinCOFFStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { MCDataFragment *DF = getOrCreateDataFragment(); + const MCSymbolRefExpr *SRE = MCSymbolRefExpr::Create(Symbol, getContext()); + MCFixup Fixup = MCFixup::Create(DF->getContents().size(), SRE, FK_SecRel_2); + DF->getFixups().push_back(Fixup); + DF->getContents().resize(DF->getContents().size() + 4, 0); +} - DF->getFixups().push_back( - MCFixup::Create(DF->getContents().size(), - MCSymbolRefExpr::Create (Symbol, getContext ()), - FK_SecRel_4)); +void MCWinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) { + MCDataFragment *DF = getOrCreateDataFragment(); + const MCSymbolRefExpr *SRE = MCSymbolRefExpr::Create(Symbol, getContext()); + MCFixup Fixup = MCFixup::Create(DF->getContents().size(), SRE, FK_SecRel_4); + DF->getFixups().push_back(Fixup); DF->getContents().resize(DF->getContents().size() + 4, 0); } -void WinCOFFStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { - llvm_unreachable("not implemented"); +void MCWinCOFFStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { + llvm_unreachable("not supported"); } -void WinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) { - assert((Symbol->isInSection() - ? Symbol->getSection().getVariant() == MCSection::SV_COFF - : true) && "Got non COFF section in the COFF backend!"); - AddCommonSymbol(Symbol, Size, ByteAlignment, true); +void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { + assert((!Symbol->isInSection() || + Symbol->getSection().getVariant() == MCSection::SV_COFF) && + "Got non-COFF section in the COFF backend!"); + + if (ByteAlignment > 32) + report_fatal_error("alignment is limited to 32-bytes"); + + AssignSection(Symbol, nullptr); + + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + SD.setExternal(true); + SD.setCommon(Size, ByteAlignment); } -void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) { - assert((Symbol->isInSection() - ? Symbol->getSection().getVariant() == MCSection::SV_COFF - : true) && "Got non COFF section in the COFF backend!"); - AddCommonSymbol(Symbol, Size, ByteAlignment, false); +void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { + assert(!Symbol->isInSection() && "Symbol must not already have a section!"); + + const MCSection *Section = getContext().getObjectFileInfo()->getBSSSection(); + MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section); + if (SectionData.getAlignment() < ByteAlignment) + SectionData.setAlignment(ByteAlignment); + + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + SD.setExternal(false); + + AssignSection(Symbol, Section); + + if (ByteAlignment != 1) + new MCAlignFragment(ByteAlignment, /*_Value=*/0, /*_ValueSize=*/0, + ByteAlignment, &SectionData); + + MCFillFragment *Fragment = + new MCFillFragment(/*_Value=*/0, /*_ValueSize=*/0, Size, &SectionData); + SD.setFragment(Fragment); } -void WinCOFFStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size,unsigned ByteAlignment) { +void MCWinCOFFStreamer::EmitZerofill(const MCSection *Section, + MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { llvm_unreachable("not implemented"); } -void WinCOFFStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment) { +void MCWinCOFFStreamer::EmitTBSSSymbol(const MCSection *Section, + MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { llvm_unreachable("not implemented"); } -void WinCOFFStreamer::EmitFileDirective(StringRef Filename) { - // Ignore for now, linkers don't care, and proper debug - // info will be a much large effort. +void MCWinCOFFStreamer::EmitFileDirective(StringRef Filename) { + getAssembler().addFileName(Filename); } // TODO: Implement this if you want to emit .comment section in COFF obj files. -void WinCOFFStreamer::EmitIdent(StringRef IdentString) { - llvm_unreachable("unsupported directive"); +void MCWinCOFFStreamer::EmitIdent(StringRef IdentString) { + llvm_unreachable("not implemented"); } -void WinCOFFStreamer::EmitWin64EHHandlerData() { - MCStreamer::EmitWin64EHHandlerData(); - - // We have to emit the unwind info now, because this directive - // actually switches to the .xdata section! - MCWin64EHUnwindEmitter::EmitUnwindInfo(*this, getCurrentW64UnwindInfo()); +void MCWinCOFFStreamer::EmitWinEHHandlerData() { + llvm_unreachable("not implemented"); } -void WinCOFFStreamer::FinishImpl() { - EmitFrames(NULL, true); - EmitW64Tables(); +void MCWinCOFFStreamer::FinishImpl() { MCObjectStreamer::FinishImpl(); } -namespace llvm -{ - MCStreamer *createWinCOFFStreamer(MCContext &Context, - MCAsmBackend &MAB, - MCCodeEmitter &CE, - raw_ostream &OS, - bool RelaxAll) { - WinCOFFStreamer *S = new WinCOFFStreamer(Context, MAB, CE, OS); - S->getAssembler().setRelaxAll(RelaxAll); - return S; - } +LLVM_ATTRIBUTE_NORETURN +void MCWinCOFFStreamer::FatalError(const Twine &Msg) const { + getContext().FatalError(SMLoc(), Msg); +} } + diff --git a/contrib/llvm/lib/MC/YAML.cpp b/contrib/llvm/lib/MC/YAML.cpp new file mode 100644 index 0000000..067e91a --- /dev/null +++ b/contrib/llvm/lib/MC/YAML.cpp @@ -0,0 +1,65 @@ +//===- 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); + } +} |