diff options
author | Stephen Hines <srhines@google.com> | 2014-02-11 20:01:10 -0800 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-02-11 20:01:10 -0800 |
commit | ce9904c6ea8fd669978a8eefb854b330eb9828ff (patch) | |
tree | 2418ee2e96ea220977c8fb74959192036ab5b133 /lib/MC | |
parent | c27b10b198c1d9e9b51f2303994313ec2778edd7 (diff) | |
parent | dbb832b83351cec97b025b61c26536ef50c3181c (diff) | |
download | external_llvm-ce9904c6ea8fd669978a8eefb854b330eb9828ff.zip external_llvm-ce9904c6ea8fd669978a8eefb854b330eb9828ff.tar.gz external_llvm-ce9904c6ea8fd669978a8eefb854b330eb9828ff.tar.bz2 |
Merge remote-tracking branch 'upstream/release_34' into merge-20140211
Conflicts:
lib/Linker/LinkModules.cpp
lib/Support/Unix/Signals.inc
Change-Id: Ia54f291fa5dc828052d2412736e8495c1282aa64
Diffstat (limited to 'lib/MC')
41 files changed, 2940 insertions, 1473 deletions
diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt index 89e2aaf..fa844ef 100644 --- a/lib/MC/CMakeLists.txt +++ b/lib/MC/CMakeLists.txt @@ -4,6 +4,7 @@ add_llvm_library(LLVMMC MCAsmInfo.cpp MCAsmInfoCOFF.cpp MCAsmInfoDarwin.cpp + MCAsmInfoELF.cpp MCAsmStreamer.cpp MCAssembler.cpp MCAtom.cpp @@ -25,6 +26,7 @@ add_llvm_library(LLVMMC MCMachOStreamer.cpp MCMachObjectTargetWriter.cpp MCModule.cpp + MCModuleYAML.cpp MCNullStreamer.cpp MCObjectFileInfo.cpp MCObjectDisassembler.cpp diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 2db59ac..9899bb2 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -73,10 +73,6 @@ class ELFObjectWriter : public MCObjectWriter { // Support lexicographic sorting. bool operator<(const ELFSymbolData &RHS) const { - if (MCELF::GetType(*SymbolData) == ELF::STT_FILE) - return true; - if (MCELF::GetType(*RHS.SymbolData) == ELF::STT_FILE) - return false; return SymbolData->getSymbol().getName() < RHS.SymbolData->getSymbol().getName(); } @@ -98,6 +94,7 @@ class ELFObjectWriter : public MCObjectWriter { /// @{ SmallString<256> StringTable; + std::vector<uint64_t> FileSymbolData; std::vector<ELFSymbolData> LocalSymbolData; std::vector<ELFSymbolData> ExternalSymbolData; std::vector<ELFSymbolData> UndefinedSymbolData; @@ -551,7 +548,7 @@ void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF, uint8_t Type = MCELF::GetType(Data); uint8_t Info = (Binding << ELF_STB_Shift) | (Type << ELF_STT_Shift); - // Other and Visibility share the same byte with Visability using the lower + // 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) << @@ -590,8 +587,15 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, // The first entry is the undefined symbol entry. WriteSymbolEntry(SymtabF, ShndxF, 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); + } + // Write the symbol table entries. - LastLocalSymbolIndex = LocalSymbolData.size() + 1; + LastLocalSymbolIndex = FileSymbolData.size() + LocalSymbolData.size() + 1; + for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) { ELFSymbolData &MSD = LocalSymbolData[i]; WriteSymbol(SymtabF, ShndxF, MSD, Layout); @@ -880,6 +884,20 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, // 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) { @@ -964,7 +982,7 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, // Set the symbol indices. Local symbols must come before all other // symbols with non-local bindings. - unsigned Index = 1; + unsigned Index = FileSymbolData.size() + 1; for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) LocalSymbolData[i].SymbolData->setIndex(Index++); @@ -1005,8 +1023,8 @@ void ELFObjectWriter::CreateRelocationSections(MCAssembler &Asm, unsigned Flags = 0; StringRef Group = ""; if (Section.getFlags() & ELF::SHF_GROUP) { - Flags = ELF::SHF_GROUP; - Group = Section.getGroup()->getName(); + Flags = ELF::SHF_GROUP; + Group = Section.getGroup()->getName(); } const MCSectionELF *RelaSection = @@ -1073,7 +1091,7 @@ void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm, else if (entry.Index < 0) entry.Index = getSymbolIndexInSymbolTable(Asm, entry.Symbol); else - entry.Index += LocalSymbolData.size(); + entry.Index += FileSymbolData.size() + LocalSymbolData.size(); if (is64Bit()) { String64(*F, entry.r_offset); if (TargetObjectWriter->isN64()) { @@ -1104,11 +1122,10 @@ void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm, } } -static int compareBySuffix(const void *a, const void *b) { - const MCSectionELF *secA = *static_cast<const MCSectionELF* const *>(a); - const MCSectionELF *secB = *static_cast<const MCSectionELF* const *>(b); - const StringRef &NameA = secA->getSectionName(); - const StringRef &NameB = secB->getSectionName(); +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); @@ -1299,10 +1316,12 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, // Remove ".rel" and ".rela" prefixes. unsigned SecNameLen = (Section.getType() == ELF::SHT_REL) ? 4 : 5; StringRef SectionName = Section.getSectionName().substr(SecNameLen); + StringRef GroupName = + Section.getGroup() ? Section.getGroup()->getName() : ""; - InfoSection = Asm.getContext().getELFSection(SectionName, - ELF::SHT_PROGBITS, 0, - SectionKind::getReadOnly()); + InfoSection = Asm.getContext().getELFSection(SectionName, ELF::SHT_PROGBITS, + 0, SectionKind::getReadOnly(), + 0, GroupName); sh_info = SectionIndexMap.lookup(InfoSection); break; } @@ -1352,11 +1371,12 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, ELF::SHF_EXECINSTR | ELF::SHF_ALLOC, SectionKind::getText())); } else if (SecName.startswith(".ARM.exidx")) { - sh_link = SectionIndexMap.lookup( - Asm.getContext().getELFSection(SecName.substr(sizeof(".ARM.exidx") - 1), - ELF::SHT_PROGBITS, - ELF::SHF_EXECINSTR | ELF::SHF_ALLOC, - SectionKind::getText())); + StringRef GroupName = + Section.getGroup() ? Section.getGroup()->getName() : ""; + sh_link = SectionIndexMap.lookup(Asm.getContext().getELFSection( + SecName.substr(sizeof(".ARM.exidx") - 1), ELF::SHT_PROGBITS, + ELF::SHF_EXECINSTR | ELF::SHF_ALLOC, SectionKind::getText(), 0, + GroupName)); } } diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index 84e4075..28f1c95 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -35,7 +35,7 @@ MCAsmInfo::MCAsmInfo() { LinkerRequiresNonEmptyDwarfLines = false; MaxInstLength = 4; MinInstAlignment = 1; - PCSymbol = "$"; + DollarIsPC = false; SeparatorString = ";"; CommentColumn = 40; CommentString = "#"; @@ -50,10 +50,7 @@ MCAsmInfo::MCAsmInfo() { Code32Directive = ".code32"; Code64Directive = ".code64"; AssemblerDialect = 0; - AllowQuotesInName = false; - AllowNameToStartWithDigit = false; - AllowPeriodsInName = true; - AllowUTF8 = true; + AllowAtInName = false; UseDataRegionDirectives = false; ZeroDirective = "\t.zero\t"; AsciiDirective = "\t.ascii\t"; @@ -76,8 +73,8 @@ MCAsmInfo::MCAsmInfo() { LCOMMDirectiveAlignmentType = LCOMM::NoAlignment; HasDotTypeDotSizeDirective = true; HasSingleParameterDotFile = true; + HasIdentDirective = false; HasNoDeadStrip = false; - HasSymbolResolver = false; WeakRefDirective = 0; WeakDefDirective = 0; LinkOnceDirective = 0; @@ -87,7 +84,6 @@ MCAsmInfo::MCAsmInfo() { HasLEB128 = false; SupportsDebugInformation = false; ExceptionsType = ExceptionHandling::None; - DwarfUsesInlineInfoSection = false; DwarfUsesRelocationsAcrossSections = true; DwarfRegNumForCFI = false; HasMicrosoftFastStdCallMangling = false; diff --git a/lib/MC/MCAsmInfoCOFF.cpp b/lib/MC/MCAsmInfoCOFF.cpp index 33350d9..9d9f98e 100644 --- a/lib/MC/MCAsmInfoCOFF.cpp +++ b/lib/MC/MCAsmInfoCOFF.cpp @@ -43,7 +43,6 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() { void MCAsmInfoMicrosoft::anchor() { } MCAsmInfoMicrosoft::MCAsmInfoMicrosoft() { - AllowQuotesInName = true; } void MCAsmInfoGNUCOFF::anchor() { } diff --git a/lib/MC/MCAsmInfoDarwin.cpp b/lib/MC/MCAsmInfoDarwin.cpp index a0e3eba..704c816 100644 --- a/lib/MC/MCAsmInfoDarwin.cpp +++ b/lib/MC/MCAsmInfoDarwin.cpp @@ -26,7 +26,6 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { GlobalPrefix = "_"; PrivateGlobalPrefix = "L"; LinkerPrivateGlobalPrefix = "l"; - AllowQuotesInName = true; HasSingleParameterDotFile = false; HasSubsectionsViaSymbols = true; @@ -58,7 +57,6 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { HasDotTypeDotSizeDirective = false; HasNoDeadStrip = true; - HasSymbolResolver = true; DwarfUsesRelocationsAcrossSections = false; } diff --git a/lib/MC/MCAsmInfoELF.cpp b/lib/MC/MCAsmInfoELF.cpp new file mode 100644 index 0000000..8cf4e4f --- /dev/null +++ b/lib/MC/MCAsmInfoELF.cpp @@ -0,0 +1,23 @@ +//===-- MCAsmInfoELF.cpp - ELF asm properties -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines target asm properties related what form asm statements +// should take in general on ELF-based targets +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCAsmInfoELF.h" +using namespace llvm; + +void MCAsmInfoELF::anchor() { } + +MCAsmInfoELF::MCAsmInfoELF() { + HasIdentDirective = true; + WeakRefDirective = "\t.weak\t"; +} diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 781e400..ca49f8f 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -25,6 +25,7 @@ #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" @@ -65,17 +66,15 @@ private: virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame); public: - MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os, - bool isVerboseAsm, bool useLoc, bool useCFI, - bool useDwarfDirectory, - MCInstPrinter *printer, MCCodeEmitter *emitter, - MCAsmBackend *asmbackend, - bool showInst) - : MCStreamer(SK_AsmStreamer, Context), OS(os), MAI(Context.getAsmInfo()), - InstPrinter(printer), Emitter(emitter), AsmBackend(asmbackend), - CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm), - ShowInst(showInst), UseLoc(useLoc), UseCFI(useCFI), - UseDwarfDirectory(useDwarfDirectory) { + 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()), + InstPrinter(printer), Emitter(emitter), AsmBackend(asmbackend), + CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm), + ShowInst(showInst), UseLoc(useLoc), UseCFI(useCFI), + UseDwarfDirectory(useDwarfDirectory) { if (InstPrinter && IsVerboseAsm) InstPrinter->setCommentStream(CommentStream); } @@ -154,7 +153,7 @@ public: virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, const MCSymbol *Label); - virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); + virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol); @@ -214,6 +213,7 @@ public: 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); @@ -229,6 +229,7 @@ public: 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(); @@ -245,17 +246,6 @@ public: virtual void EmitWin64EHPushFrame(bool Code); virtual void EmitWin64EHEndProlog(); - virtual void EmitFnStart(); - virtual void EmitFnEnd(); - virtual void EmitCantUnwind(); - virtual void EmitPersonality(const MCSymbol *Personality); - virtual void EmitHandlerData(); - virtual void EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0); - virtual void EmitPad(int64_t Offset); - virtual void EmitRegSave(const SmallVectorImpl<unsigned> &RegList, bool); - - virtual void EmitTCEntry(const MCSymbol &S); - virtual void EmitInstruction(const MCInst &Inst); virtual void EmitBundleAlignMode(unsigned AlignPow2); @@ -265,15 +255,9 @@ public: /// 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 EmitRawText(StringRef String); + virtual void EmitRawTextImpl(StringRef String); virtual void FinishImpl(); - - /// @} - - static bool classof(const MCStreamer *S) { - return S->getKind() == SK_AsmStreamer; - } }; } // end anonymous namespace. @@ -436,7 +420,7 @@ void MCAsmStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, } -void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, +bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { switch (Attribute) { case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute"); @@ -447,11 +431,12 @@ void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype case MCSA_ELF_TypeGnuUniqueObject: /// .type _foo, @gnu_unique_object - assert(MAI->hasDotTypeDotSizeDirective() && "Symbol Attr not supported"); + if (!MAI->hasDotTypeDotSizeDirective()) + return false; // Symbol attribute not supported OS << "\t.type\t" << *Symbol << ',' << ((MAI->getCommentString()[0] != '@') ? '@' : '%'); switch (Attribute) { - default: llvm_unreachable("Unknown ELF .type"); + default: return false; case MCSA_ELF_TypeFunction: OS << "function"; break; case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break; case MCSA_ELF_TypeObject: OS << "object"; break; @@ -461,7 +446,7 @@ void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break; } EmitEOL(); - return; + return true; case MCSA_Global: // .globl/.global OS << MAI->getGlobalDirective(); FlagMap[Symbol] |= EHGlobal; @@ -491,6 +476,8 @@ void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, OS << *Symbol; EmitEOL(); + + return true; } void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { @@ -530,6 +517,9 @@ 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); + OS << "\t.comm\t" << *Symbol << ',' << Size; if (ByteAlignment != 0) { if (MAI->getCOMMDirectiveAlignmentIsInBytes()) @@ -546,6 +536,9 @@ void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, /// @param Size - The size of the common symbol. void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlign) { + // Common symbols do not belong to any actual section. + AssignSection(Symbol, NULL); + OS << "\t.lcomm\t" << *Symbol << ',' << Size; if (ByteAlign > 1) { switch (MAI->getLCOMMDirectiveAlignmentType()) { @@ -565,6 +558,9 @@ void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { + if (Symbol) + AssignSection(Symbol, Section); + // Note: a .zerofill directive does not switch sections. OS << ".zerofill "; @@ -585,6 +581,8 @@ void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, // e.g. _a. void MCAsmStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { + AssignSection(Symbol, Section); + assert(Symbol != NULL && "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. @@ -654,7 +652,6 @@ void MCAsmStreamer::EmitBytes(StringRef Data) { OS << MAI->getAsciiDirective(); } - OS << ' '; PrintQuotedString(Data, OS); EmitEOL(); } @@ -884,6 +881,13 @@ void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, EmitEOL(); } +void MCAsmStreamer::EmitIdent(StringRef IdentString) { + assert(MAI->hasIdentDirective() && ".ident directive not supported"); + OS << "\t.ident\t"; + PrintQuotedString(IdentString, OS); + EmitEOL(); +} + void MCAsmStreamer::EmitCFISections(bool EH, bool Debug) { MCStreamer::EmitCFISections(EH, Debug); @@ -1085,6 +1089,16 @@ void MCAsmStreamer::EmitCFIRegister(int64_t Register1, int64_t 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); @@ -1290,73 +1304,6 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { } } -void MCAsmStreamer::EmitFnStart() { - OS << "\t.fnstart"; - EmitEOL(); -} - -void MCAsmStreamer::EmitFnEnd() { - OS << "\t.fnend"; - EmitEOL(); -} - -void MCAsmStreamer::EmitCantUnwind() { - OS << "\t.cantunwind"; - EmitEOL(); -} - -void MCAsmStreamer::EmitHandlerData() { - OS << "\t.handlerdata"; - EmitEOL(); -} - -void MCAsmStreamer::EmitPersonality(const MCSymbol *Personality) { - OS << "\t.personality " << Personality->getName(); - EmitEOL(); -} - -void MCAsmStreamer::EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset) { - OS << "\t.setfp\t"; - InstPrinter->printRegName(OS, FpReg); - OS << ", "; - InstPrinter->printRegName(OS, SpReg); - if (Offset) - OS << ", #" << Offset; - EmitEOL(); -} - -void MCAsmStreamer::EmitPad(int64_t Offset) { - OS << "\t.pad\t#" << Offset; - EmitEOL(); -} - -void MCAsmStreamer::EmitRegSave(const SmallVectorImpl<unsigned> &RegList, - bool isVector) { - assert(RegList.size() && "RegList should not be empty"); - if (isVector) - OS << "\t.vsave\t{"; - else - OS << "\t.save\t{"; - - InstPrinter->printRegName(OS, RegList[0]); - - for (unsigned i = 1, e = RegList.size(); i != e; ++i) { - OS << ", "; - InstPrinter->printRegName(OS, RegList[i]); - } - - OS << "}"; - EmitEOL(); -} - -void MCAsmStreamer::EmitTCEntry(const MCSymbol &S) { - OS << "\t.tc "; - OS << S.getName(); - OS << "[TC],"; - OS << S.getName(); - EmitEOL(); -} - void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { assert(getCurrentSection().first && "Cannot emit contents before setting section!"); @@ -1399,7 +1346,7 @@ void MCAsmStreamer::EmitBundleUnlock() { /// 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. -void MCAsmStreamer::EmitRawText(StringRef String) { +void MCAsmStreamer::EmitRawTextImpl(StringRef String) { if (!String.empty() && String.back() == '\n') String = String.substr(0, String.size()-1); OS << String; @@ -1418,14 +1365,16 @@ void MCAsmStreamer::FinishImpl() { MCGenDwarfInfo::Emit(this, LineSectionSymbol); if (!UseCFI) - EmitFrames(false); + EmitFrames(AsmBackend.get(), false); } + 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, OS, isVerboseAsm, useLoc, useCFI, - useDwarfDirectory, IP, CE, MAB, ShowInst); + 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); } diff --git a/lib/MC/MCAtom.cpp b/lib/MC/MCAtom.cpp index 2626b39..bc353cd 100644 --- a/lib/MC/MCAtom.cpp +++ b/lib/MC/MCAtom.cpp @@ -14,6 +14,9 @@ using namespace llvm; +// Pin the vtable to this file. +void MCAtom::anchor() {} + void MCAtom::remap(uint64_t NewBegin, uint64_t NewEnd) { Parent->remap(this, NewBegin, NewEnd); } @@ -44,7 +47,7 @@ void MCAtom::remapForSplit(uint64_t SplitPt, void MCDataAtom::addData(const MCData &D) { Data.push_back(D); - if (Data.size() > Begin - End) + if (Data.size() > End + 1 - Begin) remap(Begin, End + 1); } @@ -72,8 +75,8 @@ MCDataAtom *MCDataAtom::split(uint64_t SplitPt) { // MCTextAtom void MCTextAtom::addInst(const MCInst &I, uint64_t Size) { - if (NextInstAddress > End) - remap(Begin, NextInstAddress); + if (NextInstAddress + Size - 1 > End) + remap(Begin, NextInstAddress + Size - 1); Insts.push_back(MCDecodedInst(I, NextInstAddress, Size)); NextInstAddress += Size; } @@ -106,5 +109,6 @@ MCTextAtom *MCTextAtom::split(uint64_t SplitPt) { std::copy(I, Insts.end(), std::back_inserter(RightAtom->Insts)); Insts.erase(I, Insts.end()); + Parent->splitBasicBlocksForAtom(this, RightAtom); return RightAtom; } diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp index 6e4d82b..3b45d16 100644 --- a/lib/MC/MCContext.cpp +++ b/lib/MC/MCContext.cpp @@ -25,12 +25,16 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Signals.h" #include "llvm/Support/SourceMgr.h" + +#include <map> + using namespace llvm; -typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy; -typedef StringMap<const MCSectionELF*> ELFUniqueMapTy; -typedef StringMap<const MCSectionCOFF*> COFFUniqueMapTy; +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, @@ -249,8 +253,9 @@ getELFSection(StringRef Section, unsigned Type, unsigned Flags, ELFUniqueMapTy &Map = *(ELFUniqueMapTy*)ELFUniquingMap; // Do the lookup, if we have a hit, return it. - StringMapEntry<const MCSectionELF*> &Entry = Map.GetOrCreateValue(Section); - if (Entry.getValue()) return Entry.getValue(); + std::pair<ELFUniqueMapTy::iterator, bool> Entry = Map.insert( + std::make_pair(SectionGroupPair(Section, Group), (MCSectionELF *)0)); + if (!Entry.second) return Entry.first->second; // Possibly refine the entry size first. if (!EntrySize) { @@ -261,9 +266,9 @@ getELFSection(StringRef Section, unsigned Type, unsigned Flags, if (!Group.empty()) GroupSym = GetOrCreateSymbol(Group); - MCSectionELF *Result = new (*this) MCSectionELF(Entry.getKey(), Type, Flags, - Kind, EntrySize, GroupSym); - Entry.setValue(Result); + MCSectionELF *Result = new (*this) MCSectionELF( + Entry.first->first.first, Type, Flags, Kind, EntrySize, GroupSym); + Entry.first->second = Result; return Result; } @@ -274,32 +279,51 @@ const MCSectionELF *MCContext::CreateELFGroupSection() { return Result; } -const MCSectionCOFF *MCContext::getCOFFSection(StringRef Section, - unsigned Characteristics, - SectionKind Kind, int Selection, - const MCSectionCOFF *Assoc) { +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; // Do the lookup, if we have a hit, return it. - StringMapEntry<const MCSectionCOFF*> &Entry = Map.GetOrCreateValue(Section); - if (Entry.getValue()) return Entry.getValue(); - MCSectionCOFF *Result = new (*this) MCSectionCOFF(Entry.getKey(), - Characteristics, - Selection, Assoc, Kind); + 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) + return Iter->second; - Entry.setValue(Result); + const MCSymbol *COMDATSymbol = NULL; + if (!COMDATSymName.empty()) + COMDATSymbol = GetOrCreateSymbol(COMDATSymName); + + MCSectionCOFF *Result = + new (*this) MCSectionCOFF(Iter->first.first, Characteristics, + COMDATSymbol, Selection, Assoc, Kind); + + Iter->second = Result; return Result; } +const MCSectionCOFF * +MCContext::getCOFFSection(StringRef Section, unsigned Characteristics, + SectionKind Kind) { + return getCOFFSection(Section, Characteristics, Kind, "", 0); +} + const MCSectionCOFF *MCContext::getCOFFSection(StringRef Section) { if (COFFUniquingMap == 0) COFFUniquingMap = new COFFUniqueMapTy(); COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)COFFUniquingMap; - return Map.lookup(Section); + SectionGroupPair P(Section, ""); + COFFUniqueMapTy::iterator Iter = Map.find(P); + if (Iter == Map.end()) + return 0; + return Iter->second; } //===----------------------------------------------------------------------===// diff --git a/lib/MC/MCDisassembler/Disassembler.cpp b/lib/MC/MCDisassembler/Disassembler.cpp index ecc7aff..a0066c8 100644 --- a/lib/MC/MCDisassembler/Disassembler.cpp +++ b/lib/MC/MCDisassembler/Disassembler.cpp @@ -20,6 +20,7 @@ #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbolizer.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/Support/MemoryObject.h" #include "llvm/Support/TargetRegistry.h" @@ -101,6 +102,7 @@ LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, if (!DC) return 0; + DC->setCPU(CPU); return DC; } @@ -143,6 +145,112 @@ public: }; } // end anonymous namespace +/// \brief Emits the comments that are stored in \p DC comment stream. +/// Each comment in the comment stream must end with a newline. +static void emitComments(LLVMDisasmContext *DC, + formatted_raw_ostream &FormattedOS) { + // Flush the stream before taking its content. + DC->CommentStream.flush(); + StringRef Comments = DC->CommentsToEmit.str(); + // Get the default information for printing a comment. + const MCAsmInfo *MAI = DC->getAsmInfo(); + const char *CommentBegin = MAI->getCommentString(); + unsigned CommentColumn = MAI->getCommentColumn(); + bool IsFirst = true; + while (!Comments.empty()) { + if (!IsFirst) + FormattedOS << '\n'; + // Emit a line of comments. + FormattedOS.PadToColumn(CommentColumn); + size_t Position = Comments.find('\n'); + FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position); + // Move after the newline character. + Comments = Comments.substr(Position+1); + IsFirst = false; + } + FormattedOS.flush(); + + // Tell the comment stream that the vector changed underneath it. + DC->CommentsToEmit.clear(); + DC->CommentStream.resync(); +} + +/// \brief Gets latency information for \p Inst form the itinerary +/// scheduling model, based on \p DC information. +/// \return The maximum expected latency over all the operands or -1 +/// if no information are available. +static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) { + const int NoInformationAvailable = -1; + + // Check if we have a CPU to get the itinerary information. + if (DC->getCPU().empty()) + return NoInformationAvailable; + + // Get itinerary information. + const MCSubtargetInfo *STI = DC->getSubtargetInfo(); + InstrItineraryData IID = STI->getInstrItineraryForCPU(DC->getCPU()); + // Get the scheduling class of the requested instruction. + const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode()); + unsigned SCClass = Desc.getSchedClass(); + + int Latency = 0; + for (unsigned OpIdx = 0, OpIdxEnd = Inst.getNumOperands(); OpIdx != OpIdxEnd; + ++OpIdx) + Latency = std::max(Latency, IID.getOperandCycle(SCClass, OpIdx)); + + return Latency; +} + +/// \brief Gets latency information for \p Inst, based on \p DC information. +/// \return The maximum expected latency over all the definitions or -1 +/// if no information are available. +static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) { + // Try to compute scheduling information. + const MCSubtargetInfo *STI = DC->getSubtargetInfo(); + const MCSchedModel *SCModel = STI->getSchedModel(); + const int NoInformationAvailable = -1; + + // Check if we have a scheduling model for instructions. + if (!SCModel || !SCModel->hasInstrSchedModel()) + // Try to fall back to the itinerary model if we do not have a + // scheduling model. + return getItineraryLatency(DC, Inst); + + // Get the scheduling class of the requested instruction. + const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode()); + unsigned SCClass = Desc.getSchedClass(); + const MCSchedClassDesc *SCDesc = SCModel->getSchedClassDesc(SCClass); + // Resolving the variant SchedClass requires an MI to pass to + // SubTargetInfo::resolveSchedClass. + if (!SCDesc || !SCDesc->isValid() || SCDesc->isVariant()) + return NoInformationAvailable; + + // Compute output latency. + int Latency = 0; + for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries; + DefIdx != DefEnd; ++DefIdx) { + // Lookup the definition's write latency in SubtargetInfo. + const MCWriteLatencyEntry *WLEntry = STI->getWriteLatencyEntry(SCDesc, + DefIdx); + Latency = std::max(Latency, WLEntry->Cycles); + } + + return Latency; +} + + +/// \brief Emits latency information in DC->CommentStream for \p Inst, based +/// on the information available in \p DC. +static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) { + int Latency = getLatency(DC, Inst); + + // Report only interesting latency. + if (Latency < 2) + return; + + DC->CommentStream << "Latency: " << Latency << '\n'; +} + // // LLVMDisasmInstruction() disassembles a single instruction using the // disassembler context specified in the parameter DC. The bytes of the @@ -167,8 +275,10 @@ size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes, const MCDisassembler *DisAsm = DC->getDisAsm(); MCInstPrinter *IP = DC->getIP(); MCDisassembler::DecodeStatus S; + SmallVector<char, 64> InsnStr; + raw_svector_ostream Annotations(InsnStr); S = DisAsm->getInstruction(Inst, Size, MemoryObject, PC, - /*REMOVE*/ nulls(), DC->CommentStream); + /*REMOVE*/ nulls(), Annotations); switch (S) { case MCDisassembler::Fail: case MCDisassembler::SoftFail: @@ -176,17 +286,18 @@ size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes, return 0; case MCDisassembler::Success: { - DC->CommentStream.flush(); - StringRef Comments = DC->CommentsToEmit.str(); + Annotations.flush(); + StringRef AnnotationsStr = Annotations.str(); SmallVector<char, 64> InsnStr; raw_svector_ostream OS(InsnStr); - IP->printInst(&Inst, OS, Comments); - OS.flush(); + formatted_raw_ostream FormattedOS(OS); + IP->printInst(&Inst, FormattedOS, AnnotationsStr); - // Tell the comment stream that the vector changed underneath it. - DC->CommentsToEmit.clear(); - DC->CommentStream.resync(); + if (DC->getOptions() & LLVMDisassembler_Option_PrintLatency) + emitLatency(DC, Inst); + + emitComments(DC, FormattedOS); assert(OutStringSize != 0 && "Output buffer cannot be zero size"); size_t OutputSize = std::min(OutStringSize-1, InsnStr.size()); @@ -208,12 +319,14 @@ int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR; MCInstPrinter *IP = DC->getIP(); IP->setUseMarkup(1); + DC->addOptions(LLVMDisassembler_Option_UseMarkup); Options &= ~LLVMDisassembler_Option_UseMarkup; } if (Options & LLVMDisassembler_Option_PrintImmHex){ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR; MCInstPrinter *IP = DC->getIP(); IP->setPrintImmHex(1); + DC->addOptions(LLVMDisassembler_Option_PrintImmHex); Options &= ~LLVMDisassembler_Option_PrintImmHex; } if (Options & LLVMDisassembler_Option_AsmPrinterVariant){ @@ -229,8 +342,21 @@ int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){ AsmPrinterVariant, *MAI, *MII, *MRI, *STI); if (IP) { DC->setIP(IP); + DC->addOptions(LLVMDisassembler_Option_AsmPrinterVariant); Options &= ~LLVMDisassembler_Option_AsmPrinterVariant; } } + if (Options & LLVMDisassembler_Option_SetInstrComments) { + LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR; + MCInstPrinter *IP = DC->getIP(); + IP->setCommentStream(DC->CommentStream); + DC->addOptions(LLVMDisassembler_Option_SetInstrComments); + Options &= ~LLVMDisassembler_Option_SetInstrComments; + } + if (Options & LLVMDisassembler_Option_PrintLatency) { + LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR; + DC->addOptions(LLVMDisassembler_Option_PrintLatency); + Options &= ~LLVMDisassembler_Option_PrintLatency; + } return (Options == 0); } diff --git a/lib/MC/MCDisassembler/Disassembler.h b/lib/MC/MCDisassembler/Disassembler.h index 6eb59d0..4855af2 100644 --- a/lib/MC/MCDisassembler/Disassembler.h +++ b/lib/MC/MCDisassembler/Disassembler.h @@ -73,6 +73,10 @@ private: llvm::OwningPtr<const llvm::MCDisassembler> DisAsm; // The instruction printer for the target architecture. llvm::OwningPtr<llvm::MCInstPrinter> IP; + // The options used to set up the disassembler. + uint64_t Options; + // The CPU string. + std::string CPU; public: // Comment stream and backing vector. @@ -90,6 +94,7 @@ public: MCInstPrinter *iP) : TripleName(tripleName), DisInfo(disInfo), TagType(tagType), GetOpInfo(getOpInfo), SymbolLookUp(symbolLookUp), TheTarget(theTarget), + Options(0), CommentStream(CommentsToEmit) { MAI.reset(mAI); MRI.reset(mRI); @@ -114,6 +119,10 @@ public: const MCSubtargetInfo *getSubtargetInfo() const { return MSI.get(); } MCInstPrinter *getIP() { return IP.get(); } void setIP(MCInstPrinter *NewIP) { IP.reset(NewIP); } + uint64_t getOptions() const { return Options; } + void addOptions(uint64_t Options) { this->Options |= Options; } + StringRef getCPU() const { return CPU; } + void setCPU(const char *CPU) { this->CPU = CPU; } }; } // namespace llvm diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index 195bbfe..1e5c2e3 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -873,9 +873,7 @@ namespace { void setSectionStart(const MCSymbol *Label) { SectionStart = Label; } - /// EmitCompactUnwind - Emit the unwind information in a compact way. If - /// we're successful, return 'true'. Otherwise, return 'false' and it will - /// emit the normal CIE and FDE. + /// EmitCompactUnwind - Emit the unwind information in a compact way. void EmitCompactUnwind(MCStreamer &streamer, const MCDwarfFrameInfo &frame); @@ -889,7 +887,7 @@ namespace { const MCSymbol &cieStart, const MCDwarfFrameInfo &frame); void EmitCFIInstructions(MCStreamer &streamer, - const std::vector<MCCFIInstruction> &Instrs, + ArrayRef<MCCFIInstruction> Instrs, MCSymbol *BaseLabel); void EmitCFIInstruction(MCStreamer &Streamer, const MCCFIInstruction &Instr); @@ -961,6 +959,10 @@ void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer, Streamer.EmitULEB128IntValue(Reg2); return; } + case MCCFIInstruction::OpWindowSave: { + Streamer.EmitIntValue(dwarf::DW_CFA_GNU_window_save, 1); + return; + } case MCCFIInstruction::OpUndefined: { unsigned Reg = Instr.getRegister(); if (VerboseAsm) { @@ -1091,7 +1093,7 @@ void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer, /// EmitFrameMoves - Emit frame instructions to describe the layout of the /// frame. void FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer, - const std::vector<MCCFIInstruction> &Instrs, + ArrayRef<MCCFIInstruction> Instrs, MCSymbol *BaseLabel) { for (unsigned i = 0, N = Instrs.size(); i < N; ++i) { const MCCFIInstruction &Instr = Instrs[i]; @@ -1113,9 +1115,7 @@ void FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer, } } -/// EmitCompactUnwind - Emit the unwind information in a compact way. If we're -/// successful, return 'true'. Otherwise, return 'false' and it will emit the -/// normal CIE and FDE. +/// EmitCompactUnwind - Emit the unwind information in a compact way. void FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, const MCDwarfFrameInfo &Frame) { MCContext &Context = Streamer.getContext(); @@ -1419,9 +1419,10 @@ namespace llvm { }; } -void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, - bool UsingCFI, - bool IsEH) { +void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, MCAsmBackend *MAB, + bool UsingCFI, bool IsEH) { + Streamer.generateCompactUnwindEncodings(MAB); + MCContext &Context = Streamer.getContext(); const MCObjectFileInfo *MOFI = Context.getObjectFileInfo(); FrameEmitterImpl Emitter(UsingCFI, IsEH); diff --git a/lib/MC/MCELF.cpp b/lib/MC/MCELF.cpp index 560cdbc..ebb189e 100644 --- a/lib/MC/MCELF.cpp +++ b/lib/MC/MCELF.cpp @@ -36,8 +36,8 @@ unsigned MCELF::GetBinding(const MCSymbolData &SD) { void MCELF::SetType(MCSymbolData &SD, unsigned Type) { assert(Type == ELF::STT_NOTYPE || Type == ELF::STT_OBJECT || Type == ELF::STT_FUNC || Type == ELF::STT_SECTION || - Type == ELF::STT_FILE || Type == ELF::STT_COMMON || - Type == ELF::STT_TLS || Type == ELF::STT_GNU_IFUNC); + Type == ELF::STT_COMMON || Type == ELF::STT_TLS || + Type == ELF::STT_GNU_IFUNC); uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STT_Shift); SD.setFlags(OtherFlags | (Type << ELF_STT_Shift)); @@ -47,8 +47,7 @@ unsigned MCELF::GetType(const MCSymbolData &SD) { uint32_t Type = (SD.getFlags() & (0xf << ELF_STT_Shift)) >> ELF_STT_Shift; assert(Type == ELF::STT_NOTYPE || Type == ELF::STT_OBJECT || Type == ELF::STT_FUNC || Type == ELF::STT_SECTION || - Type == ELF::STT_FILE || Type == ELF::STT_COMMON || - Type == ELF::STT_TLS || Type == ELF::STT_GNU_IFUNC); + Type == ELF::STT_COMMON || Type == ELF::STT_TLS || Type == ELF::STT_GNU_IFUNC); return Type; } diff --git a/lib/MC/MCELFObjectTargetWriter.cpp b/lib/MC/MCELFObjectTargetWriter.cpp index ec7397d..0c39e4a 100644 --- a/lib/MC/MCELFObjectTargetWriter.cpp +++ b/lib/MC/MCELFObjectTargetWriter.cpp @@ -42,9 +42,9 @@ const MCSymbol *MCELFObjectTargetWriter::undefinedExplicitRelSym(const MCValue & // 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 void *AP, const void *BP) { - const ELFRelocationEntry &A = *(const ELFRelocationEntry *)AP; - const ELFRelocationEntry &B = *(const ELFRelocationEntry *)BP; +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) diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 6e5ff50..e806cb9 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -15,6 +15,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCELF.h" @@ -96,6 +97,9 @@ void MCELFStreamer::EmitDebugLabel(MCSymbol *Symbol) { } void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { + // Let the target do whatever target specific stuff it needs to do. + getAssembler().getBackend().handleAssemblerFlag(Flag); + // Do any generic stuff we need to do. switch (Flag) { case MCAF_SyntaxUnified: return; // no-op here. case MCAF_Code16: return; // Change parsing mode; no-op here. @@ -148,8 +152,8 @@ static unsigned CombineSymbolTypes(unsigned T1, unsigned T2) { return T2; } -void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, - MCSymbolAttr Attribute) { +bool MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, + MCSymbolAttr Attribute) { // Indirect symbols are handled differently, to match how 'as' handles // them. This makes writing matching .o files easier. if (Attribute == MCSA_IndirectSymbol) { @@ -159,7 +163,7 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, ISD.Symbol = Symbol; ISD.SectionData = getCurrentSectionData(); getAssembler().getIndirectSymbols().push_back(ISD); - return; + return true; } // Adding a symbol attribute always introduces the symbol, note that an @@ -182,7 +186,7 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, case MCSA_WeakDefAutoPrivate: case MCSA_Invalid: case MCSA_IndirectSymbol: - llvm_unreachable("Invalid symbol attribute for ELF!"); + return false; case MCSA_NoDeadStrip: case MCSA_ELF_TypeGnuUniqueObject: @@ -251,6 +255,8 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, MCELF::SetVisibility(SD, ELF::STV_INTERNAL); break; } + + return true; } void MCELFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, @@ -270,7 +276,8 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, ELF::SHF_WRITE | ELF::SHF_ALLOC, SectionKind::getBSS()); - Symbol->setSection(*Section); + + AssignSection(Symbol, Section); struct LocalCommon L = {&SD, Size, ByteAlignment}; LocalCommons.push_back(L); @@ -313,20 +320,29 @@ void MCELFStreamer::EmitValueToAlignment(unsigned ByteAlignment, ValueSize, MaxBytesToEmit); } - -// Add a symbol for the file name of this module. This is the second -// entry in the module's symbol table (the first being the null symbol). +// Add a symbol for the file name of this module. They start after the +// null symbol and don't count as normal symbol, i.e. a non-STT_FILE symbol +// with the same name may appear. void MCELFStreamer::EmitFileDirective(StringRef Filename) { - MCSymbol *Symbol = getAssembler().getContext().GetOrCreateSymbol(Filename); - Symbol->setSection(*getCurrentSection().first); - Symbol->setAbsolute(); - - MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); - - SD.setFlags(ELF_STT_File | ELF_STB_Local | ELF_STV_Default); + getAssembler().addFileName(Filename); +} + +void MCELFStreamer::EmitIdent(StringRef IdentString) { + const MCSection *Comment = getAssembler().getContext().getELFSection( + ".comment", ELF::SHT_PROGBITS, ELF::SHF_MERGE | ELF::SHF_STRINGS, + SectionKind::getReadOnly(), 1, ""); + PushSection(); + SwitchSection(Comment); + if (!SeenIdent) { + EmitIntValue(0, 1); + SeenIdent = true; + } + EmitBytes(IdentString); + EmitIntValue(0, 1); + PopSection(); } -void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { +void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { switch (expr->getKind()) { case MCExpr::Target: cast<MCTargetExpr>(expr)->fixELFSymbolsInTLSFixups(getAssembler()); @@ -525,9 +541,7 @@ void MCELFStreamer::EmitBundleUnlock() { SD->setBundleLockState(MCSectionData::NotBundleLocked); } -void MCELFStreamer::FinishImpl() { - EmitFrames(true); - +void MCELFStreamer::Flush() { for (std::vector<LocalCommon>::const_iterator i = LocalCommons.begin(), e = LocalCommons.end(); i != e; ++i) { @@ -548,17 +562,23 @@ void MCELFStreamer::FinishImpl() { SectData.setAlignment(ByteAlignment); } - this->MCObjectStreamer::FinishImpl(); + LocalCommons.clear(); } -void MCELFStreamer::EmitTCEntry(const MCSymbol &S) { - // Creates a R_PPC64_TOC relocation - MCObjectStreamer::EmitSymbolValue(&S, 8); + +void MCELFStreamer::FinishImpl() { + EmitFrames(NULL, true); + + Flush(); + + this->MCObjectStreamer::FinishImpl(); } -MCStreamer *llvm::createELFStreamer(MCContext &Context, MCAsmBackend &MAB, - raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll, bool NoExecStack) { - MCELFStreamer *S = new MCELFStreamer(Context, MAB, OS, CE); +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); if (RelaxAll) S->getAssembler().setRelaxAll(true); if (NoExecStack) diff --git a/lib/MC/MCExternalSymbolizer.cpp b/lib/MC/MCExternalSymbolizer.cpp index 47ef6c4..ca368b2 100644 --- a/lib/MC/MCExternalSymbolizer.cpp +++ b/lib/MC/MCExternalSymbolizer.cpp @@ -63,6 +63,8 @@ bool MCExternalSymbolizer::tryAddingSymbolicOperand(MCInst &MI, } if(ReferenceType == LLVMDisassembler_ReferenceType_Out_SymbolStub) cStream << "symbol stub for: " << ReferenceName; + else if(ReferenceType == LLVMDisassembler_ReferenceType_Out_Objc_Message) + cStream << "Objc message: " << ReferenceName; if (!Name && !IsBranch) return false; } @@ -132,6 +134,8 @@ bool MCExternalSymbolizer::tryAddingSymbolicOperand(MCInst &MI, // literal pool's entry if the referenced address is that of a symbol. Or it // will return a pointer to a literal 'C' string if the referenced address of // the literal pool's entry is an address into a section with C string literals. +// Or if the reference is to an Objective-C data structure it will return a +// specific reference type for it and a string. void MCExternalSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream, int64_t Value, uint64_t Address) { @@ -139,9 +143,26 @@ void MCExternalSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream, uint64_t ReferenceType = LLVMDisassembler_ReferenceType_In_PCrel_Load; const char *ReferenceName; (void)SymbolLookUp(DisInfo, Value, &ReferenceType, Address, &ReferenceName); - if(ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr || - ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr) - cStream << "literal pool for: " << ReferenceName; + 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 << "\""; + else if(ReferenceType == + LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref) + cStream << "Objc cfstring ref: @\"" << ReferenceName << "\""; + else if(ReferenceType == + LLVMDisassembler_ReferenceType_Out_Objc_Message) + cStream << "Objc message: " << ReferenceName; + else if(ReferenceType == + LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref) + cStream << "Objc message ref: " << ReferenceName; + else if(ReferenceType == + LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref) + cStream << "Objc selector ref: " << ReferenceName; + else if(ReferenceType == + LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref) + cStream << "Objc class ref: " << ReferenceName; } } diff --git a/lib/MC/MCFunction.cpp b/lib/MC/MCFunction.cpp index 2665d3e..767e1e0 100644 --- a/lib/MC/MCFunction.cpp +++ b/lib/MC/MCFunction.cpp @@ -9,15 +9,15 @@ #include "llvm/MC/MCFunction.h" #include "llvm/MC/MCAtom.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/MC/MCModule.h" #include <algorithm> using namespace llvm; // MCFunction -MCFunction::MCFunction(StringRef Name) - : Name(Name) +MCFunction::MCFunction(StringRef Name, MCModule *Parent) + : Name(Name), ParentModule(Parent) {} MCFunction::~MCFunction() { @@ -26,18 +26,32 @@ MCFunction::~MCFunction() { } MCBasicBlock &MCFunction::createBlock(const MCTextAtom &TA) { - Blocks.push_back(new MCBasicBlock(TA, this)); - return *Blocks.back(); + MCBasicBlock *MCBB = new MCBasicBlock(TA, this); + Blocks.push_back(MCBB); + return *MCBB; +} + +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; +} + +const MCBasicBlock *MCFunction::find(uint64_t StartAddr) const { + return const_cast<MCFunction *>(this)->find(StartAddr); } // MCBasicBlock MCBasicBlock::MCBasicBlock(const MCTextAtom &Insts, MCFunction *Parent) - : Insts(&Insts), Parent(Parent) -{} + : Insts(&Insts), Parent(Parent) { + getParent()->getParent()->trackBBForAtom(&Insts, this); +} void MCBasicBlock::addSuccessor(const MCBasicBlock *MCBB) { - Successors.push_back(MCBB); + if (!isSuccessor(MCBB)) + Successors.push_back(MCBB); } bool MCBasicBlock::isSuccessor(const MCBasicBlock *MCBB) const { @@ -46,10 +60,22 @@ bool MCBasicBlock::isSuccessor(const MCBasicBlock *MCBB) const { } void MCBasicBlock::addPredecessor(const MCBasicBlock *MCBB) { - Predecessors.push_back(MCBB); + if (!isPredecessor(MCBB)) + Predecessors.push_back(MCBB); } bool MCBasicBlock::isPredecessor(const MCBasicBlock *MCBB) const { return std::find(Predecessors.begin(), Predecessors.end(), MCBB) != Predecessors.end(); } + +void MCBasicBlock::splitBasicBlock(MCBasicBlock *SplitBB) { + assert(Insts->getEndAddr() + 1 == SplitBB->Insts->getBeginAddr() && + "Splitting unrelated basic blocks!"); + SplitBB->addPredecessor(this); + assert(SplitBB->Successors.empty() && + "Split basic block shouldn't already have successors!"); + SplitBB->Successors = Successors; + Successors.clear(); + addSuccessor(SplitBB); +} diff --git a/lib/MC/MCInstPrinter.cpp b/lib/MC/MCInstPrinter.cpp index 6a452c8..ba71245 100644 --- a/lib/MC/MCInstPrinter.cpp +++ b/lib/MC/MCInstPrinter.cpp @@ -31,9 +31,13 @@ void MCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { void MCInstPrinter::printAnnotation(raw_ostream &OS, StringRef Annot) { if (!Annot.empty()) { - if (CommentStream) + if (CommentStream) { (*CommentStream) << Annot; - else + // By definition (see MCInstPrinter.h), CommentStream must end with + // a newline after each comment. + if (Annot.back() != '\n') + (*CommentStream) << '\n'; + } else OS << " " << MAI.getCommentString() << " " << Annot; } } diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 0729b7a..2924dcd 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -1,3 +1,4 @@ +//===-- MCMachOStreamer.cpp - MachO Streamer ------------------------------===// // // The LLVM Compiler Infrastructure // @@ -36,7 +37,7 @@ private: public: MCMachOStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(SK_MachOStreamer, Context, MAB, OS, Emitter) {} + : MCObjectStreamer(Context, 0, MAB, OS, Emitter) {} /// @name MCStreamer Interface /// @{ @@ -51,7 +52,7 @@ public: virtual void EmitLinkerOptions(ArrayRef<std::string> Options); virtual void EmitDataRegion(MCDataRegionType Kind); virtual void EmitThumbFunc(MCSymbol *Func); - virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); + virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment); @@ -81,16 +82,14 @@ public: // FIXME: Just ignore the .file; it isn't important enough to fail the // entire assembly. - //report_fatal_error("unsupported directive: '.file'"); + // report_fatal_error("unsupported directive: '.file'"); } - virtual void FinishImpl(); - - /// @} - - static bool classof(const MCStreamer *S) { - return S->getKind() == SK_MachOStreamer; + virtual void EmitIdent(StringRef IdentString) { + llvm_unreachable("macho doesn't support this directive"); } + + virtual void FinishImpl(); }; } // end anonymous namespace. @@ -122,7 +121,7 @@ void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); // isSymbolLinkerVisible uses the section. - Symbol->setSection(*getCurrentSection().first); + AssignSection(Symbol, getCurrentSection().first); // We have to create a new fragment if this is an atom defining symbol, // fragments cannot span atoms. if (getAssembler().isSymbolLinkerVisible(*Symbol)) @@ -217,7 +216,7 @@ void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) { SD.setFlags(SD.getFlags() | SF_ThumbFunc); } -void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, +bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { // Indirect symbols are handled differently, to match how 'as' handles // them. This makes writing matching .o files easier. @@ -228,7 +227,7 @@ void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, ISD.Symbol = Symbol; ISD.SectionData = getCurrentSectionData(); getAssembler().getIndirectSymbols().push_back(ISD); - return; + return true; } // Adding a symbol attribute always introduces the symbol, note that an @@ -257,7 +256,7 @@ void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, case MCSA_Protected: case MCSA_Weak: case MCSA_Local: - llvm_unreachable("Invalid symbol attribute for Mach-O!"); + return false; case MCSA_Global: SD.setExternal(true); @@ -309,6 +308,8 @@ void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, SD.setFlags(SD.getFlags() | SF_WeakDefinition | SF_WeakReference); break; } + + return true; } void MCMachOStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { @@ -324,6 +325,8 @@ 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); + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); SD.setExternal(true); SD.setCommon(Size, ByteAlignment); @@ -360,7 +363,7 @@ void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, MCFragment *F = new MCFillFragment(0, 0, Size, &SectData); SD.setFragment(F); - Symbol->setSection(*Section); + AssignSection(Symbol, Section); // Update the maximum alignment on the zero fill section if necessary. if (ByteAlignment > SectData.getAlignment()) @@ -393,7 +396,7 @@ void MCMachOStreamer::EmitInstToData(const MCInst &Inst) { } void MCMachOStreamer::FinishImpl() { - EmitFrames(true); + EmitFrames(&getAssembler().getBackend(), true); // We have to set the fragment atom associations so we can relax properly for // Mach-O. diff --git a/lib/MC/MCModule.cpp b/lib/MC/MCModule.cpp index 5890b4b..7e9e18a 100644 --- a/lib/MC/MCModule.cpp +++ b/lib/MC/MCModule.cpp @@ -18,6 +18,10 @@ static bool AtomComp(const MCAtom *L, uint64_t Addr) { return L->getEndAddr() < Addr; } +static bool AtomCompInv(uint64_t Addr, const MCAtom *R) { + return Addr < R->getEndAddr(); +} + void MCModule::map(MCAtom *NewAtom) { uint64_t Begin = NewAtom->Begin; @@ -54,9 +58,13 @@ void MCModule::remap(MCAtom *Atom, uint64_t NewBegin, uint64_t NewEnd) { assert(*I == Atom && "Previous atom mapping was invalid!"); Atoms.erase(I); + // FIXME: special case NewBegin == Atom->Begin + // Insert the new mapping. AtomListTy::iterator NewI = std::lower_bound(atom_begin(), atom_end(), NewBegin, AtomComp); + assert((NewI == atom_end() || (*NewI)->getBeginAddr() > Atom->End) + && "Offset range already occupied!"); Atoms.insert(NewI, Atom); // Update the atom internal bounds. @@ -73,18 +81,55 @@ const MCAtom *MCModule::findAtomContaining(uint64_t Addr) const { } MCAtom *MCModule::findAtomContaining(uint64_t Addr) { - AtomListTy::iterator I = std::lower_bound(atom_begin(), atom_end(), - Addr, AtomComp); - if (I != atom_end() && (*I)->getBeginAddr() <= Addr) + return const_cast<MCAtom*>( + const_cast<const MCModule *>(this)->findAtomContaining(Addr)); +} + +const MCAtom *MCModule::findFirstAtomAfter(uint64_t Addr) const { + AtomListTy::const_iterator I = std::upper_bound(atom_begin(), atom_end(), + Addr, AtomCompInv); + if (I != atom_end()) return *I; return 0; } -MCFunction *MCModule::createFunction(const StringRef &Name) { - Functions.push_back(new MCFunction(Name)); +MCAtom *MCModule::findFirstAtomAfter(uint64_t Addr) { + return const_cast<MCAtom*>( + const_cast<const MCModule *>(this)->findFirstAtomAfter(Addr)); +} + +MCFunction *MCModule::createFunction(StringRef Name) { + Functions.push_back(new MCFunction(Name, this)); return Functions.back(); } +static bool CompBBToAtom(MCBasicBlock *BB, const MCTextAtom *Atom) { + return BB->getInsts() < Atom; +} + +void MCModule::splitBasicBlocksForAtom(const MCTextAtom *TA, + const MCTextAtom *NewTA) { + BBsByAtomTy::iterator + I = std::lower_bound(BBsByAtom.begin(), BBsByAtom.end(), + TA, CompBBToAtom); + for (; I != BBsByAtom.end() && (*I)->getInsts() == TA; ++I) { + MCBasicBlock *BB = *I; + MCBasicBlock *NewBB = &BB->getParent()->createBlock(*NewTA); + BB->splitBasicBlock(NewBB); + } +} + +void MCModule::trackBBForAtom(const MCTextAtom *Atom, MCBasicBlock *BB) { + assert(Atom == BB->getInsts() && "Text atom doesn't back the basic block!"); + BBsByAtomTy::iterator I = std::lower_bound(BBsByAtom.begin(), + BBsByAtom.end(), + Atom, CompBBToAtom); + for (; I != BBsByAtom.end() && (*I)->getInsts() == Atom; ++I) + if (*I == BB) + return; + BBsByAtom.insert(I, BB); +} + MCModule::~MCModule() { for (AtomListTy::iterator AI = atom_begin(), AE = atom_end(); diff --git a/lib/MC/MCModuleYAML.cpp b/lib/MC/MCModuleYAML.cpp new file mode 100644 index 0000000..e2de578 --- /dev/null +++ b/lib/MC/MCModuleYAML.cpp @@ -0,0 +1,461 @@ +//===- MCModuleYAML.cpp - MCModule YAMLIO implementation ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines classes for handling the YAML representation of MCModule. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCModuleYAML.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/MC/MCAtom.h" +#include "llvm/MC/MCFunction.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/Object/YAML.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/YAMLTraits.h" +#include <vector> + +namespace llvm { + +namespace { + +// This class is used to map opcode and register names to enum values. +// +// There are at least 3 obvious ways to do this: +// 1- Generate an MII/MRI method using a tablegen StringMatcher +// 2- Write an MII/MRI method using std::lower_bound and the assumption that +// the enums are sorted (starting at a fixed value). +// 3- Do the matching manually as is done here. +// +// Why 3? +// 1- A StringMatcher function for thousands of entries would incur +// a non-negligible binary size overhead. +// 2- The lower_bound comparators would be somewhat involved and aren't +// obviously reusable (see LessRecordRegister in llvm/TableGen/Record.h) +// 3- This isn't actually something useful outside tests (but the same argument +// can be made against having {MII,MRI}::getName). +// +// If this becomes useful outside this specific situation, feel free to do +// the Right Thing (tm) and move the functionality to MII/MRI. +// +class InstrRegInfoHolder { + typedef StringMap<unsigned, BumpPtrAllocator> EnumValByNameTy; + EnumValByNameTy InstEnumValueByName; + EnumValByNameTy RegEnumValueByName; + +public: + const MCInstrInfo &MII; + const MCRegisterInfo &MRI; + InstrRegInfoHolder(const MCInstrInfo &MII, const MCRegisterInfo &MRI) + : InstEnumValueByName(NextPowerOf2(MII.getNumOpcodes())), + RegEnumValueByName(NextPowerOf2(MRI.getNumRegs())), MII(MII), MRI(MRI) { + for (int i = 0, e = MII.getNumOpcodes(); i != e; ++i) + InstEnumValueByName[MII.getName(i)] = i; + for (int i = 0, e = MRI.getNumRegs(); i != e; ++i) + RegEnumValueByName[MRI.getName(i)] = i; + } + + bool matchRegister(StringRef Name, unsigned &Reg) { + EnumValByNameTy::const_iterator It = RegEnumValueByName.find(Name); + if (It == RegEnumValueByName.end()) + return false; + Reg = It->getValue(); + return true; + } + bool matchOpcode(StringRef Name, unsigned &Opc) { + EnumValByNameTy::const_iterator It = InstEnumValueByName.find(Name); + if (It == InstEnumValueByName.end()) + return false; + Opc = It->getValue(); + return true; + } +}; + +} // end unnamed namespace + +namespace MCModuleYAML { + +LLVM_YAML_STRONG_TYPEDEF(unsigned, OpcodeEnum) + +struct Operand { + MCOperand MCOp; +}; + +struct Inst { + OpcodeEnum Opcode; + std::vector<Operand> Operands; + uint64_t Size; +}; + +struct Atom { + MCAtom::AtomKind Type; + yaml::Hex64 StartAddress; + uint64_t Size; + + std::vector<Inst> Insts; + object::yaml::BinaryRef Data; +}; + +struct BasicBlock { + yaml::Hex64 Address; + std::vector<yaml::Hex64> Preds; + std::vector<yaml::Hex64> Succs; +}; + +struct Function { + StringRef Name; + std::vector<BasicBlock> BasicBlocks; +}; + +struct Module { + std::vector<Atom> Atoms; + std::vector<Function> Functions; +}; + +} // end namespace MCModuleYAML +} // end namespace llvm + +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex64) +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::MCModuleYAML::Operand) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::Inst) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::Atom) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::BasicBlock) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::Function) + +namespace llvm { + +namespace yaml { + +template <> struct ScalarEnumerationTraits<MCAtom::AtomKind> { + static void enumeration(IO &IO, MCAtom::AtomKind &Kind); +}; + +template <> struct MappingTraits<MCModuleYAML::Atom> { + static void mapping(IO &IO, MCModuleYAML::Atom &A); +}; + +template <> struct MappingTraits<MCModuleYAML::Inst> { + static void mapping(IO &IO, MCModuleYAML::Inst &I); +}; + +template <> struct MappingTraits<MCModuleYAML::BasicBlock> { + static void mapping(IO &IO, MCModuleYAML::BasicBlock &BB); +}; + +template <> struct MappingTraits<MCModuleYAML::Function> { + static void mapping(IO &IO, MCModuleYAML::Function &Fn); +}; + +template <> struct MappingTraits<MCModuleYAML::Module> { + static void mapping(IO &IO, MCModuleYAML::Module &M); +}; + +template <> struct ScalarTraits<MCModuleYAML::Operand> { + static void output(const MCModuleYAML::Operand &, void *, + llvm::raw_ostream &); + static StringRef input(StringRef, void *, MCModuleYAML::Operand &); +}; + +template <> struct ScalarTraits<MCModuleYAML::OpcodeEnum> { + static void output(const MCModuleYAML::OpcodeEnum &, void *, + llvm::raw_ostream &); + static StringRef input(StringRef, void *, MCModuleYAML::OpcodeEnum &); +}; + +void ScalarEnumerationTraits<MCAtom::AtomKind>::enumeration( + IO &IO, MCAtom::AtomKind &Value) { + IO.enumCase(Value, "Text", MCAtom::TextAtom); + IO.enumCase(Value, "Data", MCAtom::DataAtom); +} + +void MappingTraits<MCModuleYAML::Atom>::mapping(IO &IO, MCModuleYAML::Atom &A) { + IO.mapRequired("StartAddress", A.StartAddress); + IO.mapRequired("Size", A.Size); + IO.mapRequired("Type", A.Type); + if (A.Type == MCAtom::TextAtom) + IO.mapRequired("Content", A.Insts); + else if (A.Type == MCAtom::DataAtom) + IO.mapRequired("Content", A.Data); +} + +void MappingTraits<MCModuleYAML::Inst>::mapping(IO &IO, MCModuleYAML::Inst &I) { + IO.mapRequired("Inst", I.Opcode); + IO.mapRequired("Size", I.Size); + IO.mapRequired("Ops", I.Operands); +} + +void +MappingTraits<MCModuleYAML::BasicBlock>::mapping(IO &IO, + MCModuleYAML::BasicBlock &BB) { + IO.mapRequired("Address", BB.Address); + IO.mapRequired("Preds", BB.Preds); + IO.mapRequired("Succs", BB.Succs); +} + +void MappingTraits<MCModuleYAML::Function>::mapping(IO &IO, + MCModuleYAML::Function &F) { + IO.mapRequired("Name", F.Name); + IO.mapRequired("BasicBlocks", F.BasicBlocks); +} + +void MappingTraits<MCModuleYAML::Module>::mapping(IO &IO, + MCModuleYAML::Module &M) { + IO.mapRequired("Atoms", M.Atoms); + IO.mapOptional("Functions", M.Functions); +} + +void +ScalarTraits<MCModuleYAML::Operand>::output(const MCModuleYAML::Operand &Val, + void *Ctx, raw_ostream &Out) { + InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx; + + // FIXME: Doesn't support FPImm and expr/inst, but do these make sense? + if (Val.MCOp.isImm()) + Out << "I" << Val.MCOp.getImm(); + else if (Val.MCOp.isReg()) + Out << "R" << IRI->MRI.getName(Val.MCOp.getReg()); + else + llvm_unreachable("Trying to output invalid MCOperand!"); +} + +StringRef +ScalarTraits<MCModuleYAML::Operand>::input(StringRef Scalar, void *Ctx, + MCModuleYAML::Operand &Val) { + InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx; + char Type = 0; + if (Scalar.size() >= 1) + Type = Scalar.front(); + if (Type != 'R' && Type != 'I') + return "Operand must start with 'R' (register) or 'I' (immediate)."; + if (Type == 'R') { + unsigned Reg; + if (!IRI->matchRegister(Scalar.substr(1), Reg)) + return "Invalid register name."; + Val.MCOp = MCOperand::CreateReg(Reg); + } else if (Type == 'I') { + int64_t RIVal; + if (Scalar.substr(1).getAsInteger(10, RIVal)) + return "Invalid immediate value."; + Val.MCOp = MCOperand::CreateImm(RIVal); + } else { + Val.MCOp = MCOperand(); + } + return StringRef(); +} + +void ScalarTraits<MCModuleYAML::OpcodeEnum>::output( + const MCModuleYAML::OpcodeEnum &Val, void *Ctx, raw_ostream &Out) { + InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx; + Out << IRI->MII.getName(Val); +} + +StringRef +ScalarTraits<MCModuleYAML::OpcodeEnum>::input(StringRef Scalar, void *Ctx, + MCModuleYAML::OpcodeEnum &Val) { + InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx; + unsigned Opc; + if (!IRI->matchOpcode(Scalar, Opc)) + return "Invalid instruction opcode."; + Val = Opc; + return ""; +} + +} // end namespace yaml + +namespace { + +class MCModule2YAML { + const MCModule &MCM; + MCModuleYAML::Module YAMLModule; + void dumpAtom(const MCAtom *MCA); + void dumpFunction(const MCFunction *MCF); + void dumpBasicBlock(const MCBasicBlock *MCBB); + +public: + MCModule2YAML(const MCModule &MCM); + MCModuleYAML::Module &getYAMLModule(); +}; + +class YAML2MCModule { + MCModule &MCM; + +public: + YAML2MCModule(MCModule &MCM); + StringRef parse(const MCModuleYAML::Module &YAMLModule); +}; + +} // end unnamed namespace + +MCModule2YAML::MCModule2YAML(const MCModule &MCM) : MCM(MCM), YAMLModule() { + for (MCModule::const_atom_iterator AI = MCM.atom_begin(), AE = MCM.atom_end(); + AI != AE; ++AI) + dumpAtom(*AI); + for (MCModule::const_func_iterator FI = MCM.func_begin(), FE = MCM.func_end(); + FI != FE; ++FI) + dumpFunction(*FI); +} + +void MCModule2YAML::dumpAtom(const MCAtom *MCA) { + YAMLModule.Atoms.resize(YAMLModule.Atoms.size() + 1); + MCModuleYAML::Atom &A = YAMLModule.Atoms.back(); + A.Type = MCA->getKind(); + A.StartAddress = MCA->getBeginAddr(); + A.Size = MCA->getEndAddr() - MCA->getBeginAddr() + 1; + if (const MCTextAtom *TA = dyn_cast<MCTextAtom>(MCA)) { + const size_t InstCount = TA->size(); + A.Insts.resize(InstCount); + for (size_t i = 0; i != InstCount; ++i) { + const MCDecodedInst &MCDI = TA->at(i); + A.Insts[i].Opcode = MCDI.Inst.getOpcode(); + A.Insts[i].Size = MCDI.Size; + const unsigned OpCount = MCDI.Inst.getNumOperands(); + A.Insts[i].Operands.resize(OpCount); + for (unsigned oi = 0; oi != OpCount; ++oi) + A.Insts[i].Operands[oi].MCOp = MCDI.Inst.getOperand(oi); + } + } else if (const MCDataAtom *DA = dyn_cast<MCDataAtom>(MCA)) { + A.Data = DA->getData(); + } else { + llvm_unreachable("Unknown atom type."); + } +} + +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(); + BBI != BBE; ++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(); + PI != PE; ++PI) + BB.Preds.push_back((*PI)->getInsts()->getBeginAddr()); + for (MCBasicBlock::succ_const_iterator SI = MCBB->succ_begin(), + SE = MCBB->succ_end(); + SI != SE; ++SI) + BB.Succs.push_back((*SI)->getInsts()->getBeginAddr()); + } +} + +MCModuleYAML::Module &MCModule2YAML::getYAMLModule() { return YAMLModule; } + +YAML2MCModule::YAML2MCModule(MCModule &MCM) : MCM(MCM) {} + +StringRef YAML2MCModule::parse(const MCModuleYAML::Module &YAMLModule) { + typedef std::vector<MCModuleYAML::Atom>::const_iterator AtomIt; + typedef std::vector<MCModuleYAML::Inst>::const_iterator InstIt; + typedef std::vector<MCModuleYAML::Operand>::const_iterator OpIt; + + typedef DenseMap<uint64_t, MCTextAtom *> AddrToTextAtomTy; + AddrToTextAtomTy TAByAddr; + + for (AtomIt AI = YAMLModule.Atoms.begin(), AE = YAMLModule.Atoms.end(); + AI != AE; ++AI) { + uint64_t StartAddress = AI->StartAddress; + if (AI->Size == 0) + return "Atoms can't be empty!"; + uint64_t EndAddress = StartAddress + AI->Size - 1; + switch (AI->Type) { + case MCAtom::TextAtom: { + MCTextAtom *TA = MCM.createTextAtom(StartAddress, EndAddress); + TAByAddr[StartAddress] = TA; + for (InstIt II = AI->Insts.begin(), IE = AI->Insts.end(); II != IE; + ++II) { + MCInst MI; + MI.setOpcode(II->Opcode); + for (OpIt OI = II->Operands.begin(), OE = II->Operands.end(); OI != OE; + ++OI) + MI.addOperand(OI->MCOp); + TA->addInst(MI, II->Size); + } + break; + } + case MCAtom::DataAtom: { + MCDataAtom *DA = MCM.createDataAtom(StartAddress, EndAddress); + SmallVector<char, 64> Data; + raw_svector_ostream OS(Data); + AI->Data.writeAsBinary(OS); + OS.flush(); + for (size_t i = 0, e = Data.size(); i != e; ++i) + DA->addData((uint8_t)Data[i]); + break; + } + } + } + + typedef std::vector<MCModuleYAML::Function>::const_iterator FuncIt; + typedef std::vector<MCModuleYAML::BasicBlock>::const_iterator BBIt; + typedef std::vector<yaml::Hex64>::const_iterator AddrIt; + for (FuncIt FI = YAMLModule.Functions.begin(), + FE = YAMLModule.Functions.end(); + FI != FE; ++FI) { + MCFunction *MCFN = MCM.createFunction(FI->Name); + for (BBIt BBI = FI->BasicBlocks.begin(), BBE = FI->BasicBlocks.end(); + BBI != BBE; ++BBI) { + AddrToTextAtomTy::const_iterator It = TAByAddr.find(BBI->Address); + if (It == TAByAddr.end()) + return "Basic block start address doesn't match any text atom!"; + MCFN->createBlock(*It->second); + } + for (BBIt BBI = FI->BasicBlocks.begin(), BBE = FI->BasicBlocks.end(); + BBI != BBE; ++BBI) { + MCBasicBlock *MCBB = MCFN->find(BBI->Address); + if (!MCBB) + return "Couldn't find matching basic block in function."; + for (AddrIt PI = BBI->Preds.begin(), PE = BBI->Preds.end(); PI != PE; + ++PI) { + MCBasicBlock *Pred = MCFN->find(*PI); + if (!Pred) + return "Couldn't find predecessor basic block."; + MCBB->addPredecessor(Pred); + } + for (AddrIt SI = BBI->Succs.begin(), SE = BBI->Succs.end(); SI != SE; + ++SI) { + MCBasicBlock *Succ = MCFN->find(*SI); + if (!Succ) + return "Couldn't find predecessor basic block."; + MCBB->addSuccessor(Succ); + } + } + } + return ""; +} + +StringRef mcmodule2yaml(raw_ostream &OS, const MCModule &MCM, + const MCInstrInfo &MII, const MCRegisterInfo &MRI) { + MCModule2YAML Dumper(MCM); + InstrRegInfoHolder IRI(MII, MRI); + yaml::Output YOut(OS, (void *)&IRI); + YOut << Dumper.getYAMLModule(); + return ""; +} + +StringRef yaml2mcmodule(OwningPtr<MCModule> &MCM, StringRef YamlContent, + const MCInstrInfo &MII, const MCRegisterInfo &MRI) { + MCM.reset(new MCModule); + YAML2MCModule Parser(*MCM); + MCModuleYAML::Module YAMLModule; + InstrRegInfoHolder IRI(MII, MRI); + yaml::Input YIn(YamlContent, (void *)&IRI); + YIn >> YAMLModule; + if (error_code ec = YIn.error()) + return ec.message(); + StringRef err = Parser.parse(YAMLModule); + if (!err.empty()) + return err; + return ""; +} + +} // end namespace llvm diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp index 530c646..9b9c4aa 100644 --- a/lib/MC/MCNullStreamer.cpp +++ b/lib/MC/MCNullStreamer.cpp @@ -19,7 +19,7 @@ namespace { class MCNullStreamer : public MCStreamer { public: - MCNullStreamer(MCContext &Context) : MCStreamer(SK_NullStreamer, Context) {} + MCNullStreamer(MCContext &Context) : MCStreamer(Context, 0) {} /// @name MCStreamer Interface /// @{ @@ -37,7 +37,7 @@ namespace { virtual void EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); assert(getCurrentSection().first &&"Cannot emit before setting section!"); - Symbol->setSection(*getCurrentSection().first); + AssignSection(Symbol, getCurrentSection().first); } virtual void EmitDebugLabel(MCSymbol *Symbol) { EmitLabel(Symbol); @@ -52,7 +52,9 @@ namespace { const MCSymbol *Label, unsigned PointerSize) {} - virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute){} + virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute){ + return true; + } virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {} @@ -107,13 +109,6 @@ namespace { virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { RecordProcEnd(Frame); } - - /// @} - - static bool classof(const MCStreamer *S) { - return S->getKind() == SK_NullStreamer; - } - }; } diff --git a/lib/MC/MCObjectDisassembler.cpp b/lib/MC/MCObjectDisassembler.cpp index 1ea6eed..16a110f 100644 --- a/lib/MC/MCObjectDisassembler.cpp +++ b/lib/MC/MCObjectDisassembler.cpp @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCObjectDisassembler.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" @@ -18,12 +18,15 @@ #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" +#include "llvm/Support/Debug.h" +#include "llvm/Support/MachO.h" #include "llvm/Support/MemoryObject.h" #include "llvm/Support/StringRefMemoryObject.h" #include "llvm/Support/raw_ostream.h" #include <map> -#include <set> using namespace llvm; using namespace object; @@ -31,10 +34,55 @@ using namespace object; MCObjectDisassembler::MCObjectDisassembler(const ObjectFile &Obj, const MCDisassembler &Dis, const MCInstrAnalysis &MIA) - : Obj(Obj), Dis(Dis), MIA(MIA) {} + : Obj(Obj), Dis(Dis), MIA(MIA), MOS(0) {} -MCModule *MCObjectDisassembler::buildModule(bool withCFG) { +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; + StringRef Name; + SI->getName(Name); + if (Name == "main" || Name == "_main") { + uint64_t Entrypoint; + SI->getAddress(Entrypoint); + return getEffectiveLoadAddr(Entrypoint); + } + } + return 0; +} + +ArrayRef<uint64_t> MCObjectDisassembler::getStaticInitFunctions() { + return ArrayRef<uint64_t>(); +} + +ArrayRef<uint64_t> MCObjectDisassembler::getStaticExitFunctions() { + return ArrayRef<uint64_t>(); +} + +MemoryObject *MCObjectDisassembler::getRegionFor(uint64_t Addr) { + // FIXME: Keep track of object sections. + return FallbackRegion.get(); +} + +uint64_t MCObjectDisassembler::getEffectiveLoadAddr(uint64_t Addr) { + return Addr; +} + +uint64_t MCObjectDisassembler::getOriginalLoadAddr(uint64_t Addr) { + return Addr; +} + +MCModule *MCObjectDisassembler::buildEmptyModule() { MCModule *Module = new MCModule; + Module->Entrypoint = getEntrypoint(); + return Module; +} + +MCModule *MCObjectDisassembler::buildModule(bool withCFG) { + MCModule *Module = buildEmptyModule(); + buildSectionAtoms(Module); if (withCFG) buildCFG(Module); @@ -58,9 +106,10 @@ void MCObjectDisassembler::buildSectionAtoms(MCModule *Module) { uint64_t SecSize; SI->getSize(SecSize); if (StartAddr == UnknownAddressOrSize || SecSize == UnknownAddressOrSize) continue; + StartAddr = getEffectiveLoadAddr(StartAddr); StringRef Contents; SI->getContents(Contents); - StringRefMemoryObject memoryObject(Contents); + StringRefMemoryObject memoryObject(Contents, StartAddr); // We don't care about things like non-file-backed sections yet. if (Contents.size() != SecSize || !SecSize) @@ -70,19 +119,31 @@ void MCObjectDisassembler::buildSectionAtoms(MCModule *Module) { StringRef SecName; SI->getName(SecName); if (isText) { - MCTextAtom *Text = Module->createTextAtom(StartAddr, EndAddr); - Text->setName(SecName); + MCTextAtom *Text = 0; + MCDataAtom *InvalidData = 0; + uint64_t InstSize; for (uint64_t Index = 0; Index < SecSize; Index += InstSize) { + const uint64_t CurAddr = StartAddr + Index; MCInst Inst; - if (Dis.getInstruction(Inst, InstSize, memoryObject, Index, - nulls(), nulls())) + if (Dis.getInstruction(Inst, InstSize, memoryObject, CurAddr, nulls(), + nulls())) { + if (!Text) { + Text = Module->createTextAtom(CurAddr, CurAddr); + Text->setName(SecName); + } Text->addInst(Inst, InstSize); - else - // We don't care about splitting mixed atoms either. - llvm_unreachable("Couldn't disassemble instruction in atom."); + InvalidData = 0; + } else { + assert(InstSize && "getInstruction() consumed no bytes"); + if (!InvalidData) { + Text = 0; + InvalidData = Module->createDataAtom(CurAddr, CurAddr+InstSize - 1); + } + for (uint64_t I = 0; I < InstSize; ++I) + InvalidData->addData(Contents[Index+I]); + } } - } else { MCDataAtom *Data = Module->createDataAtom(StartAddr, EndAddr); Data->setName(SecName); @@ -94,13 +155,16 @@ void MCObjectDisassembler::buildSectionAtoms(MCModule *Module) { namespace { struct BBInfo; - typedef std::set<BBInfo*> BBInfoSetTy; + typedef SmallPtrSet<BBInfo*, 2> BBInfoSetTy; struct BBInfo { MCTextAtom *Atom; MCBasicBlock *BB; BBInfoSetTy Succs; BBInfoSetTy Preds; + MCObjectDisassembler::AddressSetTy SuccAddrs; + + BBInfo() : Atom(0), BB(0) {} void addSucc(BBInfo &Succ) { Succs.insert(&Succ); @@ -109,13 +173,33 @@ namespace { }; } +static void RemoveDupsFromAddressVector(MCObjectDisassembler::AddressSetTy &V) { + std::sort(V.begin(), V.end()); + V.erase(std::unique(V.begin(), V.end()), V.end()); +} + void MCObjectDisassembler::buildCFG(MCModule *Module) { typedef std::map<uint64_t, BBInfo> BBInfoByAddrTy; BBInfoByAddrTy BBInfos; - typedef std::set<uint64_t> AddressSetTy; 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; + SymbolRef::Type SymType; + SI->getType(SymType); + if (SymType == SymbolRef::ST_Function) { + uint64_t SymAddr; + SI->getAddress(SymAddr); + SymAddr = getEffectiveLoadAddr(SymAddr); + Calls.push_back(SymAddr); + Splits.push_back(SymAddr); + } + } + assert(Module->func_begin() == Module->func_end() && "Module already has a CFG!"); @@ -125,21 +209,24 @@ void MCObjectDisassembler::buildCFG(MCModule *Module) { AI != AE; ++AI) { MCTextAtom *TA = dyn_cast<MCTextAtom>(*AI); if (!TA) continue; - Calls.insert(TA->getBeginAddr()); + Calls.push_back(TA->getBeginAddr()); BBInfos[TA->getBeginAddr()].Atom = TA; for (MCTextAtom::const_iterator II = TA->begin(), IE = TA->end(); II != IE; ++II) { if (MIA.isTerminator(II->Inst)) - Splits.insert(II->Address + II->Size); + Splits.push_back(II->Address + II->Size); uint64_t Target; if (MIA.evaluateBranch(II->Inst, II->Address, II->Size, Target)) { if (MIA.isCall(II->Inst)) - Calls.insert(Target); - Splits.insert(Target); + Calls.push_back(Target); + Splits.push_back(Target); } } } + RemoveDupsFromAddressVector(Splits); + RemoveDupsFromAddressVector(Calls); + // Split text atoms into basic block atoms. for (AddressSetTy::const_iterator SI = Splits.begin(), SE = Splits.end(); SI != SE; ++SI) { @@ -185,8 +272,8 @@ void MCObjectDisassembler::buildCFG(MCModule *Module) { // Create MCBBs. SmallSetVector<BBInfo*, 16> Worklist; Worklist.insert(&BBI); - for (size_t WI = 0; WI < Worklist.size(); ++WI) { - BBInfo *BBI = Worklist[WI]; + for (size_t wi = 0; wi < Worklist.size(); ++wi) { + BBInfo *BBI = Worklist[wi]; if (!BBI->Atom) continue; BBI->BB = &MCFN.createBlock(*BBI->Atom); @@ -200,17 +287,298 @@ void MCObjectDisassembler::buildCFG(MCModule *Module) { } // Set preds/succs. - for (size_t WI = 0; WI < Worklist.size(); ++WI) { - BBInfo *BBI = Worklist[WI]; + for (size_t wi = 0; wi < Worklist.size(); ++wi) { + BBInfo *BBI = Worklist[wi]; MCBasicBlock *MCBB = BBI->BB; if (!MCBB) continue; for (BBInfoSetTy::iterator SI = BBI->Succs.begin(), SE = BBI->Succs.end(); - SI != SE; ++SI) - MCBB->addSuccessor((*SI)->BB); + SI != SE; ++SI) + if ((*SI)->BB) + MCBB->addSuccessor((*SI)->BB); for (BBInfoSetTy::iterator PI = BBI->Preds.begin(), PE = BBI->Preds.end(); - PI != PE; ++PI) - MCBB->addPredecessor((*PI)->BB); + PI != PE; ++PI) + if ((*PI)->BB) + MCBB->addPredecessor((*PI)->BB); + } + } +} + +// Basic idea of the disassembly + discovery: +// +// start with the wanted address, insert it in the worklist +// while worklist not empty, take next address in the worklist: +// - check if atom exists there +// - if middle of atom: +// - split basic blocks referencing the atom +// - look for an already encountered BBInfo (using a map<atom, bbinfo>) +// - if there is, split it (new one, fallthrough, move succs, etc..) +// - if start of atom: nothing else to do +// - if no atom: create new atom and new bbinfo +// - look at the last instruction in the atom, add succs to worklist +// for all elements in the worklist: +// - create basic block, update preds/succs, etc.. +// +MCBasicBlock *MCObjectDisassembler::getBBAt(MCModule *Module, MCFunction *MCFN, + uint64_t BBBeginAddr, + AddressSetTy &CallTargets, + AddressSetTy &TailCallTargets) { + typedef std::map<uint64_t, BBInfo> BBInfoByAddrTy; + typedef SmallSetVector<uint64_t, 16> AddrWorklistTy; + BBInfoByAddrTy BBInfos; + AddrWorklistTy Worklist; + + Worklist.insert(BBBeginAddr); + for (size_t wi = 0; wi < Worklist.size(); ++wi) { + const uint64_t BeginAddr = Worklist[wi]; + BBInfo *BBI = &BBInfos[BeginAddr]; + + MCTextAtom *&TA = BBI->Atom; + assert(!TA && "Discovered basic block already has an associated atom!"); + + // Look for an atom at BeginAddr. + if (MCAtom *A = Module->findAtomContaining(BeginAddr)) { + // FIXME: We don't care about mixed atoms, see above. + TA = cast<MCTextAtom>(A); + + // The found atom doesn't begin at BeginAddr, we have to split it. + if (TA->getBeginAddr() != BeginAddr) { + // FIXME: Handle overlapping atoms: middle-starting instructions, etc.. + MCTextAtom *NewTA = TA->split(BeginAddr); + + // Look for an already encountered basic block that needs splitting + BBInfoByAddrTy::iterator It = BBInfos.find(TA->getBeginAddr()); + if (It != BBInfos.end() && It->second.Atom) { + BBI->SuccAddrs = It->second.SuccAddrs; + It->second.SuccAddrs.clear(); + It->second.SuccAddrs.push_back(BeginAddr); + } + TA = NewTA; + } + BBI->Atom = TA; + } else { + // If we didn't find an atom, then we have to disassemble to create one! + + MemoryObject *Region = getRegionFor(BeginAddr); + if (!Region) + llvm_unreachable(("Couldn't find suitable region for disassembly at " + + utostr(BeginAddr)).c_str()); + + uint64_t InstSize; + uint64_t EndAddr = Region->getBase() + Region->getExtent(); + + // We want to stop before the next atom and have a fallthrough to it. + if (MCTextAtom *NextAtom = + cast_or_null<MCTextAtom>(Module->findFirstAtomAfter(BeginAddr))) + EndAddr = std::min(EndAddr, NextAtom->getBeginAddr()); + + for (uint64_t Addr = BeginAddr; Addr < EndAddr; Addr += InstSize) { + MCInst Inst; + if (Dis.getInstruction(Inst, InstSize, *Region, Addr, nulls(), + nulls())) { + if (!TA) + TA = Module->createTextAtom(Addr, Addr); + TA->addInst(Inst, InstSize); + } else { + // We don't care about splitting mixed atoms either. + llvm_unreachable("Couldn't disassemble instruction in atom."); + } + + uint64_t BranchTarget; + if (MIA.evaluateBranch(Inst, Addr, InstSize, BranchTarget)) { + if (MIA.isCall(Inst)) + CallTargets.push_back(BranchTarget); + } + + if (MIA.isTerminator(Inst)) + break; + } + BBI->Atom = TA; + } + + assert(TA && "Couldn't disassemble atom, none was created!"); + assert(TA->begin() != TA->end() && "Empty atom!"); + + MemoryObject *Region = getRegionFor(TA->getBeginAddr()); + assert(Region && "Couldn't find region for already disassembled code!"); + uint64_t EndRegion = Region->getBase() + Region->getExtent(); + + // Now we have a basic block atom, add successors. + // Add the fallthrough block. + if ((MIA.isConditionalBranch(TA->back().Inst) || + !MIA.isTerminator(TA->back().Inst)) && + (TA->getEndAddr() + 1 < EndRegion)) { + BBI->SuccAddrs.push_back(TA->getEndAddr() + 1); + Worklist.insert(TA->getEndAddr() + 1); + } + + // If the terminator is a branch, add the target block. + if (MIA.isBranch(TA->back().Inst)) { + uint64_t BranchTarget; + if (MIA.evaluateBranch(TA->back().Inst, TA->back().Address, + TA->back().Size, BranchTarget)) { + StringRef ExtFnName; + if (MOS) + ExtFnName = + MOS->findExternalFunctionAt(getOriginalLoadAddr(BranchTarget)); + if (!ExtFnName.empty()) { + TailCallTargets.push_back(BranchTarget); + CallTargets.push_back(BranchTarget); + } else { + BBI->SuccAddrs.push_back(BranchTarget); + Worklist.insert(BranchTarget); + } + } + } + } + + for (size_t wi = 0, we = Worklist.size(); wi != we; ++wi) { + const uint64_t BeginAddr = Worklist[wi]; + BBInfo *BBI = &BBInfos[BeginAddr]; + + assert(BBI->Atom && "Found a basic block without an associated atom!"); + + // Look for a basic block at BeginAddr. + BBI->BB = MCFN->find(BeginAddr); + if (BBI->BB) { + // FIXME: check that the succs/preds are the same + continue; + } + // If there was none, we have to create one from the atom. + BBI->BB = &MCFN->createBlock(*BBI->Atom); + } + + for (size_t wi = 0, we = Worklist.size(); wi != we; ++wi) { + const uint64_t BeginAddr = Worklist[wi]; + BBInfo *BBI = &BBInfos[BeginAddr]; + MCBasicBlock *BB = BBI->BB; + + RemoveDupsFromAddressVector(BBI->SuccAddrs); + for (AddressSetTy::const_iterator SI = BBI->SuccAddrs.begin(), + SE = BBI->SuccAddrs.end(); + SE != SE; ++SI) { + MCBasicBlock *Succ = BBInfos[*SI].BB; + BB->addSuccessor(Succ); + Succ->addPredecessor(BB); + } + } + + assert(BBInfos[Worklist[0]].BB && + "No basic block created at requested address?"); + + return BBInfos[Worklist[0]].BB; +} + +MCFunction * +MCObjectDisassembler::createFunction(MCModule *Module, uint64_t BeginAddr, + AddressSetTy &CallTargets, + AddressSetTy &TailCallTargets) { + // First, check if this is an external function. + StringRef ExtFnName; + if (MOS) + ExtFnName = MOS->findExternalFunctionAt(getOriginalLoadAddr(BeginAddr)); + if (!ExtFnName.empty()) + return Module->createFunction(ExtFnName); + + // If it's not, look for an existing function. + for (MCModule::func_iterator FI = Module->func_begin(), + FE = Module->func_end(); + FI != FE; ++FI) { + if ((*FI)->empty()) + continue; + // FIXME: MCModule should provide a findFunctionByAddr() + if ((*FI)->getEntryBlock()->getInsts()->getBeginAddr() == BeginAddr) + return *FI; + } + + // Finally, just create a new one. + MCFunction *MCFN = Module->createFunction(""); + getBBAt(Module, MCFN, BeginAddr, CallTargets, TailCallTargets); + return MCFN; +} + +// MachO MCObjectDisassembler implementation. + +MCMachOObjectDisassembler::MCMachOObjectDisassembler( + const MachOObjectFile &MOOF, const MCDisassembler &Dis, + const MCInstrAnalysis &MIA, uint64_t VMAddrSlide, + uint64_t HeaderLoadAddress) + : 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; + StringRef Name; + SI->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); + } else if (Name == "__mod_exit_func") { + DEBUG(dbgs() << "Found __mod_exit_func section!\n"); + SI->getContents(ModExitContents); + } + } +} + +// FIXME: Only do the translations for addresses actually inside the object. +uint64_t MCMachOObjectDisassembler::getEffectiveLoadAddr(uint64_t Addr) { + return Addr + VMAddrSlide; +} + +uint64_t +MCMachOObjectDisassembler::getOriginalLoadAddr(uint64_t EffectiveAddr) { + return EffectiveAddr - VMAddrSlide; +} + +uint64_t MCMachOObjectDisassembler::getEntrypoint() { + uint64_t EntryFileOffset = 0; + + // Look for LC_MAIN. + { + uint32_t LoadCommandCount = MOOF.getHeader().ncmds; + MachOObjectFile::LoadCommandInfo Load = MOOF.getFirstLoadCommandInfo(); + for (unsigned I = 0;; ++I) { + if (Load.C.cmd == MachO::LC_MAIN) { + EntryFileOffset = + ((const MachO::entry_point_command *)Load.Ptr)->entryoff; + break; + } + + if (I == LoadCommandCount - 1) + break; + else + Load = MOOF.getNextLoadCommandInfo(Load); } } + + // If we didn't find anything, default to the common implementation. + // FIXME: Maybe we could also look at LC_UNIXTHREAD and friends? + if (EntryFileOffset) + return MCObjectDisassembler::getEntrypoint(); + + return EntryFileOffset + HeaderLoadAddress; +} + +ArrayRef<uint64_t> MCMachOObjectDisassembler::getStaticInitFunctions() { + // FIXME: We only handle 64bit mach-o + assert(MOOF.is64Bit()); + + size_t EntrySize = 8; + size_t EntryCount = ModInitContents.size() / EntrySize; + return ArrayRef<uint64_t>( + reinterpret_cast<const uint64_t *>(ModInitContents.data()), EntryCount); +} + +ArrayRef<uint64_t> MCMachOObjectDisassembler::getStaticExitFunctions() { + // FIXME: We only handle 64bit mach-o + assert(MOOF.is64Bit()); + + size_t EntrySize = 8; + size_t EntryCount = ModExitContents.size() / EntrySize; + return ArrayRef<uint64_t>( + reinterpret_cast<const uint64_t *>(ModExitContents.data()), EntryCount); } diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp index bcf52d2..8ef4a0a 100644 --- a/lib/MC/MCObjectFileInfo.cpp +++ b/lib/MC/MCObjectFileInfo.cpp @@ -39,6 +39,9 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { = Ctx->getMachOSection("__DATA", "__data", 0, SectionKind::getDataRel()); + // BSSSection might not be expected initialized on msvc. + BSSSection = 0; + TLSDataSection // .tdata = Ctx->getMachOSection("__DATA", "__thread_data", MCSectionMachO::S_THREAD_LOCAL_REGULAR, @@ -199,6 +202,14 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { Ctx->getMachOSection("__DWARF", "__debug_pubtypes", MCSectionMachO::S_ATTR_DEBUG, SectionKind::getMetadata()); + DwarfGnuPubNamesSection = + Ctx->getMachOSection("__DWARF", "__debug_gnu_pubn", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfGnuPubTypesSection = + Ctx->getMachOSection("__DWARF", "__debug_gnu_pubt", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); DwarfStrSection = Ctx->getMachOSection("__DWARF", "__debug_str", MCSectionMachO::S_ATTR_DEBUG, @@ -223,6 +234,9 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { Ctx->getMachOSection("__DWARF", "__debug_inlined", MCSectionMachO::S_ATTR_DEBUG, SectionKind::getMetadata()); + StackMapSection = + Ctx->getMachOSection("__LLVM_STACKMAPS", "__llvm_stackmaps", 0, + SectionKind::getMetadata()); TLSExtraDataSection = TLSTLVSection; } @@ -435,6 +449,12 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { DwarfPubTypesSection = Ctx->getELFSection(".debug_pubtypes", ELF::SHT_PROGBITS, 0, SectionKind::getMetadata()); + DwarfGnuPubNamesSection = + Ctx->getELFSection(".debug_gnu_pubnames", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfGnuPubTypesSection = + Ctx->getELFSection(".debug_gnu_pubtypes", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); DwarfStrSection = Ctx->getELFSection(".debug_str", ELF::SHT_PROGBITS, ELF::SHF_MERGE | ELF::SHF_STRINGS, @@ -496,6 +516,12 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { // COFF + BSSSection = + Ctx->getCOFFSection(".bss", + COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getBSS()); TextSection = Ctx->getCOFFSection(".text", COFF::IMAGE_SCN_CNT_CODE | @@ -585,6 +611,16 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_MEM_READ, SectionKind::getMetadata()); + DwarfGnuPubNamesSection = + Ctx->getCOFFSection(".debug_gnu_pubnames", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfGnuPubTypesSection = + Ctx->getCOFFSection(".debug_gnu_pubtypes", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); DwarfStrSection = Ctx->getCOFFSection(".debug_str", COFF::IMAGE_SCN_MEM_DISCARDABLE | diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index 36a923a..bc14c2a 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -22,19 +22,22 @@ #include "llvm/Support/ErrorHandling.h" using namespace llvm; -MCObjectStreamer::MCObjectStreamer(StreamerKind Kind, MCContext &Context, +MCObjectStreamer::MCObjectStreamer(MCContext &Context, + MCTargetStreamer *TargetStreamer, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter_) - : MCStreamer(Kind, Context), + : MCStreamer(Context, TargetStreamer), Assembler(new MCAssembler(Context, TAB, *Emitter_, *TAB.createObjectWriter(OS), OS)), CurSectionData(0) {} -MCObjectStreamer::MCObjectStreamer(StreamerKind Kind, MCContext &Context, +MCObjectStreamer::MCObjectStreamer(MCContext &Context, + MCTargetStreamer *TargetStreamer, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter_, MCAssembler *_Assembler) - : MCStreamer(Kind, Context), Assembler(_Assembler), CurSectionData(0) {} + : MCStreamer(Context, TargetStreamer), Assembler(_Assembler), + CurSectionData(0) {} MCObjectStreamer::~MCObjectStreamer() { delete &Assembler->getBackend(); @@ -302,6 +305,7 @@ void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, } void MCObjectStreamer::EmitBytes(StringRef Data) { + MCLineEntry::Make(this, getCurrentSection().first); getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end()); } diff --git a/lib/MC/MCObjectSymbolizer.cpp b/lib/MC/MCObjectSymbolizer.cpp index aa7648e..b9131d1 100644 --- a/lib/MC/MCObjectSymbolizer.cpp +++ b/lib/MC/MCObjectSymbolizer.cpp @@ -15,7 +15,7 @@ #include "llvm/MC/MCRelocationInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Object/MachO.h" -#include "llvm/Object/ELF.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -26,100 +26,127 @@ using namespace object; namespace { class MCMachObjectSymbolizer : public MCObjectSymbolizer { + const MachOObjectFile *MOOF; + // __TEXT;__stubs support. + uint64_t StubsStart; + uint64_t StubsCount; + uint64_t StubSize; + uint64_t StubsIndSymIndex; + public: MCMachObjectSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo, - const object::MachOObjectFile *MachOOF) - : MCObjectSymbolizer(Ctx, RelInfo, MachOOF) - {} + const MachOObjectFile *MOOF); + + StringRef findExternalFunctionAt(uint64_t Addr) LLVM_OVERRIDE; void tryAddingPcLoadReferenceComment(raw_ostream &cStream, - int64_t Value, uint64_t Address) { - AddrToRelocMap::iterator RI = AddrToReloc.find(Address); - if (RI != AddrToReloc.end()) { - const MCExpr *RelExpr = RelInfo->createExprForRelocation(RI->second); - if (!RelExpr || RelExpr->EvaluateAsAbsolute(Value) == false) - return; - } - uint64_t Addr = Value; - SortedSectionList::const_iterator SI = findSectionContaining(Addr); - if (SI != SortedSections.end()) { - const SectionRef &S = *SI; - StringRef Name; S.getName(Name); - uint64_t SAddr; S.getAddress(SAddr); - if (Name == "__cstring") { - StringRef Contents; - S.getContents(Contents); - Contents = Contents.substr(Addr - SAddr); - cStream << " ## literal pool for: " - << Contents.substr(0, Contents.find_first_of(0)); - } - } - } + int64_t Value, + uint64_t Address) LLVM_OVERRIDE; }; } // End unnamed namespace -//===- MCObjectSymbolizer -------------------------------------------------===// -MCObjectSymbolizer::MCObjectSymbolizer(MCContext &Ctx, - OwningPtr<MCRelocationInfo> &RelInfo, - const ObjectFile *Obj) - : MCSymbolizer(Ctx, RelInfo), Obj(Obj), SortedSections(), AddrToReloc() { +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 = Obj->begin_sections(), - SE = Obj->end_sections(); - SI != SE; - SI.increment(ec)) { + for (section_iterator SI = MOOF->begin_sections(), SE = MOOF->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; - insertSection(*SI); - 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->getElfHeader()->e_type == ELF::ET_REL) { - RI->getOffset(Offset); - Offset += StartAddr; - } else { - RI->getAddress(Offset); - } + StringRef Name; SI->getName(Name); + if (Name == "__stubs") { + SectionRef StubsSec = *SI; + if (MOOF->is64Bit()) { + MachO::section_64 S = MOOF->getSection64(StubsSec.getRawDataRefImpl()); + StubsIndSymIndex = S.reserved1; + StubSize = S.reserved2; } else { - RI->getOffset(Offset); - Offset += StartAddr; + MachO::section S = MOOF->getSection(StubsSec.getRawDataRefImpl()); + StubsIndSymIndex = S.reserved1; + StubSize = S.reserved2; } - // At a specific address, only keep the first relocation. - if (AddrToReloc.find(Offset) == AddrToReloc.end()) - AddrToReloc[Offset] = *RI; + assert(StubSize && "Mach-O stub entry size can't be zero!"); + StubsSec.getAddress(StubsStart); + StubsSec.getSize(StubsCount); + StubsCount /= StubSize; + } + } +} + +StringRef MCMachObjectSymbolizer::findExternalFunctionAt(uint64_t Addr) { + // FIXME: also, this can all be done at the very beginning, by iterating over + // all stubs and creating the calls to outside functions. Is it worth it + // though? + if (!StubSize) + return StringRef(); + uint64_t StubIdx = (Addr - StubsStart) / StubSize; + if (StubIdx >= StubsCount) + return StringRef(); + + uint32_t SymtabIdx = + 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); + } + SI->getName(SymName); + assert(SI != MOOF->end_symbols() && "Stub wasn't found in the symbol table!"); + assert(SymName.front() == '_' && "Mach-O symbol doesn't start with '_'!"); + return SymName.substr(1); +} + +void MCMachObjectSymbolizer:: +tryAddingPcLoadReferenceComment(raw_ostream &cStream, int64_t Value, + uint64_t Address) { + if (const RelocationRef *R = findRelocationAt(Address)) { + const MCExpr *RelExpr = RelInfo->createExprForRelocation(*R); + if (!RelExpr || RelExpr->EvaluateAsAbsolute(Value) == false) + return; + } + uint64_t Addr = Value; + if (const SectionRef *S = findSectionContaining(Addr)) { + StringRef Name; S->getName(Name); + uint64_t SAddr; S->getAddress(SAddr); + if (Name == "__cstring") { + StringRef Contents; + S->getContents(Contents); + Contents = Contents.substr(Addr - SAddr); + cStream << " ## literal pool for: " + << Contents.substr(0, Contents.find_first_of(0)); } } } +//===- MCObjectSymbolizer -------------------------------------------------===// + +MCObjectSymbolizer::MCObjectSymbolizer(MCContext &Ctx, + OwningPtr<MCRelocationInfo> &RelInfo, + const ObjectFile *Obj) + : MCSymbolizer(Ctx, RelInfo), Obj(Obj), SortedSections(), AddrToReloc() { +} + bool MCObjectSymbolizer:: tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream, int64_t Value, uint64_t Address, bool IsBranch, uint64_t Offset, uint64_t InstSize) { - AddrToRelocMap::iterator RI = AddrToReloc.find(Address + Offset); - if (RI != AddrToReloc.end()) { - if (const MCExpr *RelExpr = RelInfo->createExprForRelocation(RI->second)) { + if (IsBranch) { + StringRef ExtFnName = findExternalFunctionAt((uint64_t)Value); + if (!ExtFnName.empty()) { + MCSymbol *Sym = Ctx.GetOrCreateSymbol(ExtFnName); + const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx); + MI.addOperand(MCOperand::CreateExpr(Expr)); + return true; + } + } + + if (const RelocationRef *R = findRelocationAt(Address + Offset)) { + if (const MCExpr *RelExpr = RelInfo->createExprForRelocation(*R)) { MI.addOperand(MCOperand::CreateExpr(RelExpr)); return true; } @@ -133,10 +160,8 @@ tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream, 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)) { + 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); @@ -166,13 +191,16 @@ tryAddingPcLoadReferenceComment(raw_ostream &cStream, int64_t Value, uint64_t Address) { } +StringRef MCObjectSymbolizer::findExternalFunctionAt(uint64_t Addr) { + return StringRef(); +} + MCObjectSymbolizer * MCObjectSymbolizer::createObjectSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo, const ObjectFile *Obj) { - if (const MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(Obj)) { - return new MCMachObjectSymbolizer(Ctx, RelInfo, MachOOF); - } + if (const MachOObjectFile *MOOF = dyn_cast<MachOObjectFile>(Obj)) + return new MCMachObjectSymbolizer(Ctx, RelInfo, MOOF); return new MCObjectSymbolizer(Ctx, RelInfo, Obj); } @@ -183,32 +211,100 @@ static bool SectionStartsBefore(const SectionRef &S, uint64_t Addr) { return SAddr < Addr; } -MCObjectSymbolizer::SortedSectionList::const_iterator -MCObjectSymbolizer::findSectionContaining(uint64_t Addr) const { - SortedSectionList::const_iterator +const SectionRef *MCObjectSymbolizer::findSectionContaining(uint64_t Addr) { + if (SortedSections.empty()) + buildSectionList(); + + SortedSectionList::iterator EndIt = SortedSections.end(), It = std::lower_bound(SortedSections.begin(), EndIt, Addr, SectionStartsBefore); if (It == EndIt) - return It; + return 0; uint64_t SAddr; It->getAddress(SAddr); uint64_t SSize; It->getSize(SSize); if (Addr >= SAddr + SSize) - return EndIt; - return It; + return 0; + return &*It; +} + +const RelocationRef *MCObjectSymbolizer::findRelocationAt(uint64_t Addr) { + if (AddrToReloc.empty()) + buildRelocationByAddrMap(); + + AddrToRelocMap::const_iterator RI = AddrToReloc.find(Addr); + if (RI == AddrToReloc.end()) + return 0; + 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); + 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); + if (It != SortedSections.end()) { + uint64_t FoundSAddr; It->getAddress(FoundSAddr); + if (FoundSAddr < SAddr + SSize) + llvm_unreachable("Inserting overlapping sections"); + } + SortedSections.insert(It, *SI); + } } -void MCObjectSymbolizer::insertSection(SectionRef Sec) { - uint64_t SAddr; Sec.getAddress(SAddr); - uint64_t SSize; Sec.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"); +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; + } + // At a specific address, only keep the first relocation. + if (AddrToReloc.find(Offset) == AddrToReloc.end()) + AddrToReloc[Offset] = *RI; + } } - SortedSections.insert(It, Sec); } diff --git a/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp index c1c594a..b49dd01 100644 --- a/lib/MC/MCParser/AsmLexer.cpp +++ b/lib/MC/MCParser/AsmLexer.cpp @@ -91,9 +91,56 @@ AsmToken AsmLexer::LexFloatLiteral() { StringRef(TokStart, CurPtr - TokStart)); } -/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@]* +/// LexHexFloatLiteral matches essentially (.[0-9a-fA-F]*)?[pP][+-]?[0-9a-fA-F]+ +/// while making sure there are enough actual digits around for the constant to +/// be valid. +/// +/// The leading "0x[0-9a-fA-F]*" (i.e. integer part) has already been consumed +/// before we get here. +AsmToken AsmLexer::LexHexFloatLiteral(bool NoIntDigits) { + assert((*CurPtr == 'p' || *CurPtr == 'P' || *CurPtr == '.') && + "unexpected parse state in floating hex"); + bool NoFracDigits = true; + + // Skip the fractional part if there is one + if (*CurPtr == '.') { + ++CurPtr; + + const char *FracStart = CurPtr; + while (isxdigit(*CurPtr)) + ++CurPtr; + + NoFracDigits = CurPtr == FracStart; + } + + if (NoIntDigits && NoFracDigits) + return ReturnError(TokStart, "invalid hexadecimal floating-point constant: " + "expected at least one significand digit"); + + // Make sure we do have some kind of proper exponent part + if (*CurPtr != 'p' && *CurPtr != 'P') + return ReturnError(TokStart, "invalid hexadecimal floating-point constant: " + "expected exponent part 'p'"); + ++CurPtr; + + if (*CurPtr == '+' || *CurPtr == '-') + ++CurPtr; + + // N.b. exponent digits are *not* hex + const char *ExpStart = CurPtr; + while (isdigit(*CurPtr)) + ++CurPtr; + + if (CurPtr == ExpStart) + return ReturnError(TokStart, "invalid hexadecimal floating-point constant: " + "expected at least one exponent digit"); + + return AsmToken(AsmToken::Real, StringRef(TokStart, CurPtr - TokStart)); +} + +/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@?]* static bool IsIdentifierChar(char c) { - return isalnum(c) || c == '_' || c == '$' || c == '.' || c == '@'; + return isalnum(c) || c == '_' || c == '$' || c == '.' || c == '@' || c == '?'; } AsmToken AsmLexer::LexIdentifier() { // Check for floating point literals. @@ -265,7 +312,12 @@ AsmToken AsmLexer::LexDigit() { while (isxdigit(CurPtr[0])) ++CurPtr; - // Requires at least one hex digit. + // "0x.0p0" is valid, and "0x0p0" (but not "0xp0" for example, which will be + // diagnosed by LexHexFloatLiteral). + if (CurPtr[0] == '.' || CurPtr[0] == 'p' || CurPtr[0] == 'P') + return LexHexFloatLiteral(NumStart == CurPtr); + + // Otherwise requires at least one hex digit. if (CurPtr == NumStart) return ReturnError(CurPtr-2, "invalid hexadecimal number"); diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index dd0d181..a91bd93 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -94,13 +94,13 @@ public: }; struct ParseStatementInfo { - /// ParsedOperands - The parsed operands from the last parsed statement. + /// \brief The parsed operands from the last parsed statement. SmallVector<MCParsedAsmOperand*, 8> ParsedOperands; - /// Opcode - The opcode from the last parsed instruction. + /// \brief The opcode from the last parsed instruction. unsigned Opcode; - /// Error - Was there an error parsing the inline assembly? + /// \brief Was there an error parsing the inline assembly? bool ParseError; SmallVectorImpl<AsmRewrite> *AsmRewrites; @@ -138,18 +138,18 @@ private: AsmCond TheCondState; std::vector<AsmCond> TheCondStack; - /// ExtensionDirectiveMap - maps directive names to handler methods in parser + /// \brief maps directive names to handler methods in parser /// extensions. Extensions register themselves in this map by calling /// addDirectiveHandler. StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap; - /// MacroMap - Map of currently defined macros. + /// \brief Map of currently defined macros. StringMap<MCAsmMacro*> MacroMap; - /// ActiveMacros - Stack of active macro instantiations. + /// \brief Stack of active macro instantiations. std::vector<MacroInstantiation*> ActiveMacros; - /// MacroLikeBodies - List of bodies of anonymous macros. + /// \brief List of bodies of anonymous macros. std::deque<MCAsmMacro> MacroLikeBodies; /// Boolean tracking whether macro substitution is enabled. @@ -165,7 +165,7 @@ private: int 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 + /// 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; @@ -174,10 +174,10 @@ private: /// AssemblerDialect. ~OU means unset value and use value provided by MAI. unsigned AssemblerDialect; - /// IsDarwin - is Darwin compatibility enabled? + /// \brief is Darwin compatibility enabled? bool IsDarwin; - /// ParsingInlineAsm - Are we parsing ms-style inline assembly? + /// \brief Are we parsing ms-style inline assembly? bool ParsingInlineAsm; public: @@ -235,7 +235,7 @@ public: virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc); virtual bool parseAbsoluteExpression(int64_t &Res); - /// parseIdentifier - Parse an identifier or string (as a quoted identifier) + /// \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(); @@ -245,11 +245,11 @@ public: private: - bool ParseStatement(ParseStatementInfo &Info); - void EatToEndOfLine(); - bool ParseCppHashLineFilenameComment(const SMLoc &L); + bool parseStatement(ParseStatementInfo &Info); + void eatToEndOfLine(); + bool parseCppHashLineFilenameComment(const SMLoc &L); - void CheckForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body, + void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body, MCAsmMacroParameters Parameters); bool expandMacro(raw_svector_ostream &OS, StringRef Body, const MCAsmMacroParameters &Parameters, @@ -257,55 +257,56 @@ private: const SMLoc &L); /// \brief Are macros enabled in the parser? - bool MacrosEnabled() {return MacrosEnabledFlag;} + bool areMacrosEnabled() {return MacrosEnabledFlag;} /// \brief Control a flag in the parser that enables or disables macros. - void SetMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;} + void setMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;} /// \brief Lookup a previously defined macro. /// \param Name Macro name. /// \returns Pointer to macro. NULL if no such macro was defined. - const MCAsmMacro* LookupMacro(StringRef Name); + const MCAsmMacro* lookupMacro(StringRef Name); /// \brief Define a new macro with the given name and information. - void DefineMacro(StringRef Name, const MCAsmMacro& Macro); + void defineMacro(StringRef Name, const MCAsmMacro& Macro); /// \brief Undefine a macro. If no such macro was defined, it's a no-op. - void UndefineMacro(StringRef Name); + void undefineMacro(StringRef Name); /// \brief Are we inside a macro instantiation? - bool InsideMacroInstantiation() {return !ActiveMacros.empty();} + bool isInsideMacroInstantiation() {return !ActiveMacros.empty();} - /// \brief Handle entry to macro instantiation. + /// \brief Handle entry to macro instantiation. /// /// \param M The macro. /// \param NameLoc Instantiation location. - bool HandleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc); + bool handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc); /// \brief Handle exit from macro instantiation. - void HandleMacroExit(); + 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, + bool parseMacroArgument(MCAsmMacroArgument &MA, AsmToken::TokenKind &ArgumentDelimiter); /// \brief Parse all macro arguments for a given macro. - bool ParseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A); + bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A); - void PrintMacroInstantiations(); - void PrintMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg, + void printMacroInstantiations(); + void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg, ArrayRef<SMRange> Ranges = None) const { SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges); } static void DiagHandler(const SMDiagnostic &Diag, void *Context); - /// EnterIncludeFile - Enter the specified file. This returns true on failure. - bool EnterIncludeFile(const std::string &Filename); - /// ProcessIncbinFile - Process the specified file for the .incbin directive. + /// \brief Enter the specified file. This returns true on failure. + bool enterIncludeFile(const std::string &Filename); + + /// \brief Process the specified file for the .incbin directive. /// This returns true on failure. - bool ProcessIncbinFile(const std::string &Filename); + bool processIncbinFile(const std::string &Filename); /// \brief Reset the current lexer position to that given by \p Loc. The /// current token is not set; clients should ensure Lex() is called @@ -313,7 +314,7 @@ private: /// /// \param InBuffer If not -1, should be the known buffer id that contains the /// location. - void JumpToLoc(SMLoc Loc, int InBuffer=-1); + void jumpToLoc(SMLoc Loc, int InBuffer=-1); /// \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 @@ -322,17 +323,16 @@ private: /// \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. - StringRef ParseStringToComma(); + StringRef parseStringToComma(); - bool ParseAssignment(StringRef Name, bool allow_redef, + bool parseAssignment(StringRef Name, bool allow_redef, bool NoDeadStrip = false); - bool ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc); - bool ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc); - bool ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc); - bool ParseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc); + bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc); + bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc); + bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc); - bool ParseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc); + bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc); // Generic (target and platform independent) directive parsing. enum DirectiveKind { @@ -342,7 +342,7 @@ private: 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, DK_INDIRECT_SYMBOL, + DK_ZERO, DK_EXTERN, DK_GLOBL, DK_GLOBAL, DK_LAZY_REFERENCE, DK_NO_DEAD_STRIP, DK_SYMBOL_RESOLVER, DK_PRIVATE_EXTERN, DK_REFERENCE, DK_WEAK_DEFINITION, DK_WEAK_REFERENCE, DK_WEAK_DEF_CAN_BE_HIDDEN, DK_COMM, DK_COMMON, DK_LCOMM, DK_ABORT, @@ -355,112 +355,113 @@ private: DK_CFI_OFFSET, DK_CFI_REL_OFFSET, DK_CFI_PERSONALITY, DK_CFI_LSDA, DK_CFI_REMEMBER_STATE, DK_CFI_RESTORE_STATE, DK_CFI_SAME_VALUE, DK_CFI_RESTORE, DK_CFI_ESCAPE, DK_CFI_SIGNAL_FRAME, DK_CFI_UNDEFINED, - DK_CFI_REGISTER, + DK_CFI_REGISTER, DK_CFI_WINDOW_SAVE, DK_MACROS_ON, DK_MACROS_OFF, DK_MACRO, DK_ENDM, DK_ENDMACRO, DK_PURGEM, DK_SLEB128, DK_ULEB128 }; - /// DirectiveKindMap - Maps directive name --> DirectiveKind enum, for + /// \brief Maps directive name --> DirectiveKind enum, for /// directives parsed by this class. StringMap<DirectiveKind> DirectiveKindMap; // ".ascii", ".asciz", ".string" - bool ParseDirectiveAscii(StringRef IDVal, bool ZeroTerminated); - bool ParseDirectiveValue(unsigned Size); // ".byte", ".long", ... - bool ParseDirectiveRealValue(const fltSemantics &); // ".single", ... - bool ParseDirectiveFill(); // ".fill" - bool ParseDirectiveZero(); // ".zero" + bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated); + bool parseDirectiveValue(unsigned Size); // ".byte", ".long", ... + bool parseDirectiveRealValue(const fltSemantics &); // ".single", ... + bool parseDirectiveFill(); // ".fill" + bool parseDirectiveZero(); // ".zero" // ".set", ".equ", ".equiv" - bool ParseDirectiveSet(StringRef IDVal, bool allow_redef); - bool ParseDirectiveOrg(); // ".org" + bool parseDirectiveSet(StringRef IDVal, bool allow_redef); + bool parseDirectiveOrg(); // ".org" // ".align{,32}", ".p2align{,w,l}" - bool ParseDirectiveAlign(bool IsPow2, unsigned ValueSize); + bool parseDirectiveAlign(bool IsPow2, unsigned ValueSize); // ".file", ".line", ".loc", ".stabs" - bool ParseDirectiveFile(SMLoc DirectiveLoc); - bool ParseDirectiveLine(); - bool ParseDirectiveLoc(); - bool ParseDirectiveStabs(); + bool parseDirectiveFile(SMLoc DirectiveLoc); + bool parseDirectiveLine(); + bool parseDirectiveLoc(); + bool parseDirectiveStabs(); // .cfi directives - bool ParseDirectiveCFIRegister(SMLoc DirectiveLoc); - bool ParseDirectiveCFISections(); - bool ParseDirectiveCFIStartProc(); - bool ParseDirectiveCFIEndProc(); - bool ParseDirectiveCFIDefCfaOffset(); - bool ParseDirectiveCFIDefCfa(SMLoc DirectiveLoc); - bool ParseDirectiveCFIAdjustCfaOffset(); - bool ParseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc); - bool ParseDirectiveCFIOffset(SMLoc DirectiveLoc); - bool ParseDirectiveCFIRelOffset(SMLoc DirectiveLoc); - bool ParseDirectiveCFIPersonalityOrLsda(bool IsPersonality); - bool ParseDirectiveCFIRememberState(); - bool ParseDirectiveCFIRestoreState(); - bool ParseDirectiveCFISameValue(SMLoc DirectiveLoc); - bool ParseDirectiveCFIRestore(SMLoc DirectiveLoc); - bool ParseDirectiveCFIEscape(); - bool ParseDirectiveCFISignalFrame(); - bool ParseDirectiveCFIUndefined(SMLoc DirectiveLoc); + bool parseDirectiveCFIRegister(SMLoc DirectiveLoc); + bool parseDirectiveCFIWindowSave(); + bool parseDirectiveCFISections(); + bool parseDirectiveCFIStartProc(); + bool parseDirectiveCFIEndProc(); + bool parseDirectiveCFIDefCfaOffset(); + bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc); + bool parseDirectiveCFIAdjustCfaOffset(); + bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc); + bool parseDirectiveCFIOffset(SMLoc DirectiveLoc); + bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc); + bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality); + bool parseDirectiveCFIRememberState(); + bool parseDirectiveCFIRestoreState(); + bool parseDirectiveCFISameValue(SMLoc DirectiveLoc); + bool parseDirectiveCFIRestore(SMLoc DirectiveLoc); + bool parseDirectiveCFIEscape(); + bool parseDirectiveCFISignalFrame(); + bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc); // macro directives - bool ParseDirectivePurgeMacro(SMLoc DirectiveLoc); - bool ParseDirectiveEndMacro(StringRef Directive); - bool ParseDirectiveMacro(SMLoc DirectiveLoc); - bool ParseDirectiveMacrosOnOff(StringRef Directive); + bool parseDirectivePurgeMacro(SMLoc DirectiveLoc); + bool parseDirectiveEndMacro(StringRef Directive); + bool parseDirectiveMacro(SMLoc DirectiveLoc); + bool parseDirectiveMacrosOnOff(StringRef Directive); // ".bundle_align_mode" - bool ParseDirectiveBundleAlignMode(); + bool parseDirectiveBundleAlignMode(); // ".bundle_lock" - bool ParseDirectiveBundleLock(); + bool parseDirectiveBundleLock(); // ".bundle_unlock" - bool ParseDirectiveBundleUnlock(); + bool parseDirectiveBundleUnlock(); // ".space", ".skip" - bool ParseDirectiveSpace(StringRef IDVal); + bool parseDirectiveSpace(StringRef IDVal); // .sleb128 (Signed=true) and .uleb128 (Signed=false) - bool ParseDirectiveLEB128(bool Signed); + bool parseDirectiveLEB128(bool Signed); - /// ParseDirectiveSymbolAttribute - Parse a directive like ".globl" which + /// \brief Parse a directive like ".globl" which /// accepts a single symbol (which should be a label or an external). - bool ParseDirectiveSymbolAttribute(MCSymbolAttr Attr); + bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr); - bool ParseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm" + bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm" - bool ParseDirectiveAbort(); // ".abort" - bool ParseDirectiveInclude(); // ".include" - bool ParseDirectiveIncbin(); // ".incbin" + bool parseDirectiveAbort(); // ".abort" + bool parseDirectiveInclude(); // ".include" + bool parseDirectiveIncbin(); // ".incbin" - bool ParseDirectiveIf(SMLoc DirectiveLoc); // ".if" + bool parseDirectiveIf(SMLoc DirectiveLoc); // ".if" // ".ifb" or ".ifnb", depending on ExpectBlank. - bool ParseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank); + bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank); // ".ifc" or ".ifnc", depending on ExpectEqual. - bool ParseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual); + bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual); // ".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 + 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); - const MCExpr *ApplyModifierToExpr(const MCExpr *E, + const MCExpr *applyModifierToExpr(const MCExpr *E, MCSymbolRefExpr::VariantKind Variant); // Macro-like directives - MCAsmMacro *ParseMacroLikeBody(SMLoc DirectiveLoc); - void InstantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, + MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc); + void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, raw_svector_ostream &OS); - bool ParseDirectiveRept(SMLoc DirectiveLoc); // ".rept" - bool ParseDirectiveIrp(SMLoc DirectiveLoc); // ".irp" - bool ParseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc" - bool ParseDirectiveEndr(SMLoc DirectiveLoc); // ".endr" + bool parseDirectiveRept(SMLoc DirectiveLoc); // ".rept" + bool parseDirectiveIrp(SMLoc DirectiveLoc); // ".irp" + bool parseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc" + bool parseDirectiveEndr(SMLoc DirectiveLoc); // ".endr" // "_emit" or "__emit" - bool ParseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info, + bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info, size_t Len); // "align" - bool ParseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info); + bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info); void initializeDirectiveKindMap(); }; @@ -476,12 +477,12 @@ extern MCAsmParserExtension *createCOFFAsmParser(); 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) { +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) { // Save the old handler. SavedDiagHandler = SrcMgr.getDiagHandler(); SavedDiagContext = SrcMgr.getDiagContext(); @@ -512,37 +513,40 @@ AsmParser::~AsmParser() { assert(ActiveMacros.empty() && "Unexpected active macro instantiation!"); // Destroy any macros. - for (StringMap<MCAsmMacro*>::iterator it = MacroMap.begin(), - ie = MacroMap.end(); it != ie; ++it) + for (StringMap<MCAsmMacro *>::iterator it = MacroMap.begin(), + ie = MacroMap.end(); + it != ie; ++it) delete it->getValue(); delete PlatformParser; } -void AsmParser::PrintMacroInstantiations() { +void AsmParser::printMacroInstantiations() { // Print the active macro instantiation stack. - for (std::vector<MacroInstantiation*>::const_reverse_iterator - it = ActiveMacros.rbegin(), ie = ActiveMacros.rend(); it != ie; ++it) - PrintMessage((*it)->InstantiationLoc, SourceMgr::DK_Note, + for (std::vector<MacroInstantiation *>::const_reverse_iterator + it = ActiveMacros.rbegin(), + ie = ActiveMacros.rend(); + it != ie; ++it) + printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note, "while in macro instantiation"); } bool AsmParser::Warning(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) { if (FatalAssemblerWarnings) return Error(L, Msg, Ranges); - PrintMessage(L, SourceMgr::DK_Warning, Msg, Ranges); - PrintMacroInstantiations(); + printMessage(L, SourceMgr::DK_Warning, Msg, Ranges); + printMacroInstantiations(); return false; } bool AsmParser::Error(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) { HadError = true; - PrintMessage(L, SourceMgr::DK_Error, Msg, Ranges); - PrintMacroInstantiations(); + printMessage(L, SourceMgr::DK_Error, Msg, Ranges); + printMacroInstantiations(); return true; } -bool AsmParser::EnterIncludeFile(const std::string &Filename) { +bool AsmParser::enterIncludeFile(const std::string &Filename) { std::string IncludedFile; int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); if (NewBuf == -1) @@ -558,7 +562,7 @@ bool AsmParser::EnterIncludeFile(const std::string &Filename) { /// Process the specified .incbin file by searching for it in the include paths /// then just emitting the byte contents of the file to the streamer. This /// returns true on failure. -bool AsmParser::ProcessIncbinFile(const std::string &Filename) { +bool AsmParser::processIncbinFile(const std::string &Filename) { std::string IncludedFile; int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); if (NewBuf == -1) @@ -569,7 +573,7 @@ bool AsmParser::ProcessIncbinFile(const std::string &Filename) { return false; } -void AsmParser::JumpToLoc(SMLoc Loc, int InBuffer) { +void AsmParser::jumpToLoc(SMLoc Loc, int InBuffer) { if (InBuffer != -1) { CurBuffer = InBuffer; } else { @@ -586,7 +590,7 @@ const AsmToken &AsmParser::Lex() { // include stack. SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); if (ParentIncludeLoc != SMLoc()) { - JumpToLoc(ParentIncludeLoc); + jumpToLoc(ParentIncludeLoc); tok = &Lexer.Lex(); } } @@ -623,7 +627,8 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // While we have input, parse each statement. while (Lexer.isNot(AsmToken::Eof)) { ParseStatementInfo Info; - if (!ParseStatement(Info)) continue; + if (!parseStatement(Info)) + continue; // We had an error, validate that one was emitted and recover by skipping to // the next line. @@ -637,7 +642,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // Check to see there are no empty DwarfFile slots. const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles = - getContext().getMCDwarfFiles(); + getContext().getMCDwarfFiles(); for (unsigned i = 1; i < MCDwarfFiles.size(); i++) { if (!MCDwarfFiles[i]) TokError("unassigned file number: " + Twine(i) + " for .file directives"); @@ -650,7 +655,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { if (!NoFinalize && MAI.hasSubsectionsViaSymbols()) { const MCContext::SymbolTable &Symbols = getContext().getSymbols(); for (MCContext::SymbolTable::const_iterator i = Symbols.begin(), - e = Symbols.end(); + e = Symbols.end(); i != e; ++i) { MCSymbol *Sym = i->getValue(); // Variable symbols may not be marked as defined, so check those @@ -660,13 +665,12 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // FIXME: We would really like to refer back to where the symbol was // first referenced for a source location. We need to add something // to track that. Currently, we just point to the end of the file. - PrintMessage(getLexer().getLoc(), SourceMgr::DK_Error, - "assembler local symbol '" + Sym->getName() + - "' not defined"); + printMessage( + getLexer().getLoc(), SourceMgr::DK_Error, + "assembler local symbol '" + Sym->getName() + "' not defined"); } } - // Finalize the output stream if there are no errors and if the client wants // us to. if (!HadError && !NoFinalize) @@ -682,10 +686,9 @@ void AsmParser::checkForValidSection() { } } -/// eatToEndOfStatement - Throw away the rest of the line for testing purposes. +/// \brief Throw away the rest of the line for testing purposes. void AsmParser::eatToEndOfStatement() { - while (Lexer.isNot(AsmToken::EndOfStatement) && - Lexer.isNot(AsmToken::Eof)) + while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof)) Lex(); // Eat EOL. @@ -696,33 +699,32 @@ void AsmParser::eatToEndOfStatement() { StringRef AsmParser::parseStringToEndOfStatement() { const char *Start = getTok().getLoc().getPointer(); - while (Lexer.isNot(AsmToken::EndOfStatement) && - Lexer.isNot(AsmToken::Eof)) + while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof)) Lex(); const char *End = getTok().getLoc().getPointer(); return StringRef(Start, End - Start); } -StringRef AsmParser::ParseStringToComma() { +StringRef AsmParser::parseStringToComma() { const char *Start = getTok().getLoc().getPointer(); while (Lexer.isNot(AsmToken::EndOfStatement) && - Lexer.isNot(AsmToken::Comma) && - Lexer.isNot(AsmToken::Eof)) + Lexer.isNot(AsmToken::Comma) && Lexer.isNot(AsmToken::Eof)) Lex(); const char *End = getTok().getLoc().getPointer(); return StringRef(Start, End - Start); } -/// ParseParenExpr - Parse a paren expression and return it. +/// \brief Parse a paren expression and return it. /// NOTE: This assumes the leading '(' has already been consumed. /// /// parenexpr ::= expr) /// -bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) { - if (parseExpression(Res)) return true; +bool AsmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) { + if (parseExpression(Res)) + return true; if (Lexer.isNot(AsmToken::RParen)) return TokError("expected ')' in parentheses expression"); EndLoc = Lexer.getTok().getEndLoc(); @@ -730,13 +732,14 @@ bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) { return false; } -/// ParseBracketExpr - Parse a bracket expression and return it. +/// \brief Parse a bracket expression and return it. /// NOTE: This assumes the leading '[' has already been consumed. /// /// bracketexpr ::= expr] /// -bool AsmParser::ParseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) { - if (parseExpression(Res)) return true; +bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) { + if (parseExpression(Res)) + return true; if (Lexer.isNot(AsmToken::RBrac)) return TokError("expected ']' in brackets expression"); EndLoc = Lexer.getTok().getEndLoc(); @@ -744,13 +747,13 @@ bool AsmParser::ParseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) { return false; } -/// ParsePrimaryExpr - Parse a primary expression and return it. +/// \brief Parse a primary expression and return it. /// primaryexpr ::= (parenexpr /// primaryexpr ::= symbol /// primaryexpr ::= number /// primaryexpr ::= '.' /// primaryexpr ::= ~,+,- primaryexpr -bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { +bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { SMLoc FirstTokenLoc = getLexer().getLoc(); AsmToken::TokenKind FirstTokenKind = Lexer.getKind(); switch (FirstTokenKind) { @@ -761,36 +764,54 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { return true; case AsmToken::Exclaim: Lex(); // Eat the operator. - if (ParsePrimaryExpr(Res, EndLoc)) + if (parsePrimaryExpr(Res, EndLoc)) return true; Res = MCUnaryExpr::CreateLNot(Res, getContext()); return false; case AsmToken::Dollar: + case AsmToken::At: case AsmToken::String: case AsmToken::Identifier: { StringRef Identifier; if (parseIdentifier(Identifier)) { - if (FirstTokenKind == AsmToken::Dollar) - return Error(FirstTokenLoc, "invalid token in expression"); - return true; + if (FirstTokenKind == AsmToken::Dollar) { + if (Lexer.getMAI().getDollarIsPC()) { + // This is a '$' reference, which references the current PC. Emit a + // temporary label to the streamer and refer to it. + MCSymbol *Sym = Ctx.CreateTempSymbol(); + Out.EmitLabel(Sym); + Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, + getContext()); + EndLoc = FirstTokenLoc; + return false; + } else + return Error(FirstTokenLoc, "invalid token in expression"); + return true; + } } 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('@'); - MCSymbol *Sym = getContext().GetOrCreateSymbol(Split.first); // Lookup the symbol variant if used. - MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; if (Split.first.size() != Identifier.size()) { Variant = MCSymbolRefExpr::getVariantKindForName(Split.second); - if (Variant == MCSymbolRefExpr::VK_Invalid) { + if (Variant != MCSymbolRefExpr::VK_Invalid) { + SymbolName = Split.first; + } else if (MAI.doesAllowAtInName()) { + Variant = MCSymbolRefExpr::VK_None; + } else { Variant = MCSymbolRefExpr::VK_None; return TokError("invalid variant '" + Split.second + "'"); } } + MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName); + // If this is an absolute variable reference, substitute it now to preserve // semantics in the face of reassignment. if (Sym->isVariable() && isa<MCConstantExpr>(Sym->getVariableValue())) { @@ -823,11 +844,11 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { Variant = MCSymbolRefExpr::VK_None; return TokError("invalid variant '" + Split.second + "'"); } - IDVal = Split.first; + IDVal = Split.first; } - if (IDVal == "f" || IDVal == "b"){ - MCSymbol *Sym = Ctx.GetDirectionalLocalSymbol(IntVal, - IDVal == "f" ? 1 : 0); + if (IDVal == "f" || IDVal == "b") { + MCSymbol *Sym = + Ctx.GetDirectionalLocalSymbol(IntVal, IDVal == "f" ? 1 : 0); Res = MCSymbolRefExpr::Create(Sym, Variant, getContext()); if (IDVal == "b" && Sym->isUndefined()) return Error(Loc, "invalid reference to undefined symbol"); @@ -857,27 +878,27 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { } case AsmToken::LParen: Lex(); // Eat the '('. - return ParseParenExpr(Res, EndLoc); + return parseParenExpr(Res, EndLoc); case AsmToken::LBrac: if (!PlatformParser->HasBracketExpressions()) return TokError("brackets expression not supported on this target"); Lex(); // Eat the '['. - return ParseBracketExpr(Res, EndLoc); + return parseBracketExpr(Res, EndLoc); case AsmToken::Minus: Lex(); // Eat the operator. - if (ParsePrimaryExpr(Res, EndLoc)) + if (parsePrimaryExpr(Res, EndLoc)) return true; Res = MCUnaryExpr::CreateMinus(Res, getContext()); return false; case AsmToken::Plus: Lex(); // Eat the operator. - if (ParsePrimaryExpr(Res, EndLoc)) + if (parsePrimaryExpr(Res, EndLoc)) return true; Res = MCUnaryExpr::CreatePlus(Res, getContext()); return false; case AsmToken::Tilde: Lex(); // Eat the operator. - if (ParsePrimaryExpr(Res, EndLoc)) + if (parsePrimaryExpr(Res, EndLoc)) return true; Res = MCUnaryExpr::CreateNot(Res, getContext()); return false; @@ -889,13 +910,13 @@ bool AsmParser::parseExpression(const MCExpr *&Res) { return parseExpression(Res, EndLoc); } -bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { - return ParsePrimaryExpr(Res, EndLoc); -} - const MCExpr * -AsmParser::ApplyModifierToExpr(const MCExpr *E, +AsmParser::applyModifierToExpr(const MCExpr *E, MCSymbolRefExpr::VariantKind Variant) { + // Ask the target implementation about this expression first. + const MCExpr *NewE = getTargetParser().applyModifierToExpr(E, Variant, Ctx); + if (NewE) + return NewE; // Recurse over the given expression, rebuilding it to apply the given variant // if there is exactly one symbol. switch (E->getKind()) { @@ -907,8 +928,8 @@ AsmParser::ApplyModifierToExpr(const MCExpr *E, const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E); if (SRE->getKind() != MCSymbolRefExpr::VK_None) { - TokError("invalid variant on expression '" + - getTok().getIdentifier() + "' (already modified)"); + TokError("invalid variant on expression '" + getTok().getIdentifier() + + "' (already modified)"); return E; } @@ -917,7 +938,7 @@ AsmParser::ApplyModifierToExpr(const MCExpr *E, case MCExpr::Unary: { const MCUnaryExpr *UE = cast<MCUnaryExpr>(E); - const MCExpr *Sub = ApplyModifierToExpr(UE->getSubExpr(), Variant); + const MCExpr *Sub = applyModifierToExpr(UE->getSubExpr(), Variant); if (!Sub) return 0; return MCUnaryExpr::Create(UE->getOpcode(), Sub, getContext()); @@ -925,14 +946,16 @@ AsmParser::ApplyModifierToExpr(const MCExpr *E, case MCExpr::Binary: { const MCBinaryExpr *BE = cast<MCBinaryExpr>(E); - const MCExpr *LHS = ApplyModifierToExpr(BE->getLHS(), Variant); - const MCExpr *RHS = ApplyModifierToExpr(BE->getRHS(), Variant); + const MCExpr *LHS = applyModifierToExpr(BE->getLHS(), Variant); + const MCExpr *RHS = applyModifierToExpr(BE->getRHS(), Variant); if (!LHS && !RHS) return 0; - if (!LHS) LHS = BE->getLHS(); - if (!RHS) RHS = BE->getRHS(); + if (!LHS) + LHS = BE->getLHS(); + if (!RHS) + RHS = BE->getRHS(); return MCBinaryExpr::Create(BE->getOpcode(), LHS, RHS, getContext()); } @@ -941,7 +964,7 @@ AsmParser::ApplyModifierToExpr(const MCExpr *E, llvm_unreachable("Invalid expression kind!"); } -/// parseExpression - Parse an expression and return it. +/// \brief Parse an expression and return it. /// /// expr ::= expr &&,|| expr -> lowest. /// expr ::= expr |,^,&,! expr @@ -954,7 +977,7 @@ AsmParser::ApplyModifierToExpr(const MCExpr *E, bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) { // Parse the expression. Res = 0; - if (ParsePrimaryExpr(Res, EndLoc) || ParseBinOpRHS(1, Res, EndLoc)) + if (parsePrimaryExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc)) return true; // As a special case, we support 'a op b @ modifier' by rewriting the @@ -967,11 +990,11 @@ bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) { return TokError("unexpected symbol modifier following '@'"); MCSymbolRefExpr::VariantKind Variant = - MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier()); + MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier()); if (Variant == MCSymbolRefExpr::VK_Invalid) return TokError("invalid variant '" + getTok().getIdentifier() + "'"); - const MCExpr *ModifiedRes = ApplyModifierToExpr(Res, Variant); + const MCExpr *ModifiedRes = applyModifierToExpr(Res, Variant); if (!ModifiedRes) { return TokError("invalid modifier '" + getTok().getIdentifier() + "' (no symbols present)"); @@ -991,8 +1014,7 @@ bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) { bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) { Res = 0; - return ParseParenExpr(Res, EndLoc) || - ParseBinOpRHS(1, Res, EndLoc); + return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc); } bool AsmParser::parseAbsoluteExpression(int64_t &Res) { @@ -1012,9 +1034,9 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K, MCBinaryExpr::Opcode &Kind) { switch (K) { default: - return 0; // not a binop. + return 0; // not a binop. - // Lowest Precedence: &&, || + // Lowest Precedence: &&, || case AsmToken::AmpAmp: Kind = MCBinaryExpr::LAnd; return 1; @@ -1022,10 +1044,9 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K, Kind = MCBinaryExpr::LOr; return 1; - - // Low Precedence: |, &, ^ - // - // FIXME: gas seems to support '!' as an infix operator? + // Low Precedence: |, &, ^ + // + // FIXME: gas seems to support '!' as an infix operator? case AsmToken::Pipe: Kind = MCBinaryExpr::Or; return 2; @@ -1036,7 +1057,7 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K, Kind = MCBinaryExpr::And; return 2; - // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >= + // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >= case AsmToken::EqualEqual: Kind = MCBinaryExpr::EQ; return 3; @@ -1057,7 +1078,7 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K, Kind = MCBinaryExpr::GTE; return 3; - // Intermediate Precedence: <<, >> + // Intermediate Precedence: <<, >> case AsmToken::LessLess: Kind = MCBinaryExpr::Shl; return 4; @@ -1065,7 +1086,7 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K, Kind = MCBinaryExpr::Shr; return 4; - // High Intermediate Precedence: +, - + // High Intermediate Precedence: +, - case AsmToken::Plus: Kind = MCBinaryExpr::Add; return 5; @@ -1073,7 +1094,7 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K, Kind = MCBinaryExpr::Sub; return 5; - // Highest Precedence: *, /, % + // Highest Precedence: *, /, % case AsmToken::Star: Kind = MCBinaryExpr::Mul; return 6; @@ -1086,10 +1107,9 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K, } } - -/// ParseBinOpRHS - Parse all binary operators with precedence >= 'Precedence'. +/// \brief Parse all binary operators with precedence >= 'Precedence'. /// Res contains the LHS of the expression on input. -bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res, +bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc) { while (1) { MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add; @@ -1104,15 +1124,15 @@ bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res, // Eat the next primary expression. const MCExpr *RHS; - if (ParsePrimaryExpr(RHS, EndLoc)) return true; + if (parsePrimaryExpr(RHS, EndLoc)) + return true; // If BinOp binds less tightly with RHS than the operator after RHS, let // the pending operator take RHS as its LHS. MCBinaryExpr::Opcode Dummy; unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy); - if (TokPrec < NextTokPrec) { - if (ParseBinOpRHS(TokPrec+1, RHS, EndLoc)) return true; - } + if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc)) + return true; // Merge LHS and RHS according to operator. Res = MCBinaryExpr::Create(Kind, Res, RHS, getContext()); @@ -1123,7 +1143,7 @@ bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res, /// ::= EndOfStatement /// ::= Label* Directive ...Operands... EndOfStatement /// ::= Label* Identifier OperandList* EndOfStatement -bool AsmParser::ParseStatement(ParseStatementInfo &Info) { +bool AsmParser::parseStatement(ParseStatementInfo &Info) { if (Lexer.is(AsmToken::EndOfStatement)) { Out.AddBlankLine(); Lex(); @@ -1137,7 +1157,7 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { int64_t LocalLabelVal = -1; // A full line comment is a '#' as the first token. if (Lexer.is(AsmToken::Hash)) - return ParseCppHashLineFilenameComment(IDLoc); + return parseCppHashLineFilenameComment(IDLoc); // Allow an integer followed by a ':' as a directional local label. if (Lexer.is(AsmToken::Integer)) { @@ -1168,34 +1188,34 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { // have to do this so that .endif isn't skipped in a ".if 0" block for // example. StringMap<DirectiveKind>::const_iterator DirKindIt = - DirectiveKindMap.find(IDVal); - DirectiveKind DirKind = - (DirKindIt == DirectiveKindMap.end()) ? DK_NO_DIRECTIVE : - DirKindIt->getValue(); + DirectiveKindMap.find(IDVal); + DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end()) + ? DK_NO_DIRECTIVE + : DirKindIt->getValue(); switch (DirKind) { - default: - break; - case DK_IF: - return ParseDirectiveIf(IDLoc); - case DK_IFB: - return ParseDirectiveIfb(IDLoc, true); - case DK_IFNB: - return ParseDirectiveIfb(IDLoc, false); - case DK_IFC: - return ParseDirectiveIfc(IDLoc, true); - case DK_IFNC: - return ParseDirectiveIfc(IDLoc, false); - case DK_IFDEF: - return ParseDirectiveIfdef(IDLoc, true); - case DK_IFNDEF: - case DK_IFNOTDEF: - return ParseDirectiveIfdef(IDLoc, false); - case DK_ELSEIF: - return ParseDirectiveElseIf(IDLoc); - case DK_ELSE: - return ParseDirectiveElse(IDLoc); - case DK_ENDIF: - return ParseDirectiveEndIf(IDLoc); + default: + break; + case DK_IF: + return parseDirectiveIf(IDLoc); + case DK_IFB: + return parseDirectiveIfb(IDLoc, true); + case DK_IFNB: + return parseDirectiveIfb(IDLoc, false); + case DK_IFC: + return parseDirectiveIfc(IDLoc, true); + case DK_IFNC: + return parseDirectiveIfc(IDLoc, false); + case DK_IFDEF: + return parseDirectiveIfdef(IDLoc, true); + case DK_IFNDEF: + case DK_IFNOTDEF: + return parseDirectiveIfdef(IDLoc, false); + case DK_ELSEIF: + return parseDirectiveElseIf(IDLoc); + case DK_ELSE: + return parseDirectiveElse(IDLoc); + case DK_ENDIF: + return parseDirectiveEndIf(IDLoc); } // Ignore the statement if in the middle of inactive conditional @@ -1242,6 +1262,8 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(), IDLoc); + getTargetParser().onLabelParsed(Sym); + // Consume any end of statement token, if present, to avoid spurious // AddBlankLine calls(). if (Lexer.is(AsmToken::EndOfStatement)) { @@ -1257,24 +1279,24 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { // identifier '=' ... -> assignment statement Lex(); - return ParseAssignment(IDVal, true); + return parseAssignment(IDVal, true); default: // Normal instruction or directive. break; } // If macros are enabled, check to see if this is a macro instantiation. - if (MacrosEnabled()) - if (const MCAsmMacro *M = LookupMacro(IDVal)) { - return HandleMacroEntry(M, IDLoc); + if (areMacrosEnabled()) + if (const MCAsmMacro *M = lookupMacro(IDVal)) { + return handleMacroEntry(M, IDLoc); } // Otherwise, we have a normal instruction or directive. - + // Directives start with "." if (IDVal[0] == '.' && IDVal != ".") { // There are several entities interested in parsing directives: - // + // // 1. The target-specific assembly parser. Some directives are target // specific or may potentially behave differently on certain targets. // 2. Asm parser extensions. For example, platform-specific parsers @@ -1291,185 +1313,185 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { // Next, check the extention directive map to see if any extension has // registered itself to parse this directive. - std::pair<MCAsmParserExtension*, DirectiveHandler> Handler = - ExtensionDirectiveMap.lookup(IDVal); + std::pair<MCAsmParserExtension *, DirectiveHandler> Handler = + ExtensionDirectiveMap.lookup(IDVal); if (Handler.first) return (*Handler.second)(Handler.first, IDVal, IDLoc); // Finally, if no one else is interested in this directive, it must be // generic and familiar to this class. switch (DirKind) { - default: - break; - case DK_SET: - case DK_EQU: - return ParseDirectiveSet(IDVal, true); - case DK_EQUIV: - return ParseDirectiveSet(IDVal, false); - case DK_ASCII: - return ParseDirectiveAscii(IDVal, false); - case DK_ASCIZ: - case DK_STRING: - return ParseDirectiveAscii(IDVal, true); - case DK_BYTE: - return ParseDirectiveValue(1); - case DK_SHORT: - case DK_VALUE: - case DK_2BYTE: - return ParseDirectiveValue(2); - case DK_LONG: - case DK_INT: - case DK_4BYTE: - return ParseDirectiveValue(4); - case DK_QUAD: - case DK_8BYTE: - return ParseDirectiveValue(8); - case DK_SINGLE: - case DK_FLOAT: - return ParseDirectiveRealValue(APFloat::IEEEsingle); - case DK_DOUBLE: - return ParseDirectiveRealValue(APFloat::IEEEdouble); - case DK_ALIGN: { - bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes(); - return ParseDirectiveAlign(IsPow2, /*ExprSize=*/1); - } - case DK_ALIGN32: { - bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes(); - return ParseDirectiveAlign(IsPow2, /*ExprSize=*/4); - } - case DK_BALIGN: - return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1); - case DK_BALIGNW: - return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2); - case DK_BALIGNL: - return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4); - case DK_P2ALIGN: - return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1); - case DK_P2ALIGNW: - return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2); - case DK_P2ALIGNL: - return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4); - case DK_ORG: - return ParseDirectiveOrg(); - case DK_FILL: - return ParseDirectiveFill(); - case DK_ZERO: - return ParseDirectiveZero(); - case DK_EXTERN: - eatToEndOfStatement(); // .extern is the default, ignore it. - return false; - case DK_GLOBL: - case DK_GLOBAL: - return ParseDirectiveSymbolAttribute(MCSA_Global); - case DK_INDIRECT_SYMBOL: - return ParseDirectiveSymbolAttribute(MCSA_IndirectSymbol); - case DK_LAZY_REFERENCE: - return ParseDirectiveSymbolAttribute(MCSA_LazyReference); - case DK_NO_DEAD_STRIP: - return ParseDirectiveSymbolAttribute(MCSA_NoDeadStrip); - case DK_SYMBOL_RESOLVER: - return ParseDirectiveSymbolAttribute(MCSA_SymbolResolver); - case DK_PRIVATE_EXTERN: - return ParseDirectiveSymbolAttribute(MCSA_PrivateExtern); - case DK_REFERENCE: - return ParseDirectiveSymbolAttribute(MCSA_Reference); - case DK_WEAK_DEFINITION: - return ParseDirectiveSymbolAttribute(MCSA_WeakDefinition); - case DK_WEAK_REFERENCE: - return ParseDirectiveSymbolAttribute(MCSA_WeakReference); - case DK_WEAK_DEF_CAN_BE_HIDDEN: - return ParseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate); - case DK_COMM: - case DK_COMMON: - return ParseDirectiveComm(/*IsLocal=*/false); - case DK_LCOMM: - return ParseDirectiveComm(/*IsLocal=*/true); - case DK_ABORT: - return ParseDirectiveAbort(); - case DK_INCLUDE: - return ParseDirectiveInclude(); - case DK_INCBIN: - return ParseDirectiveIncbin(); - case DK_CODE16: - case DK_CODE16GCC: - return TokError(Twine(IDVal) + " not supported yet"); - case DK_REPT: - return ParseDirectiveRept(IDLoc); - case DK_IRP: - return ParseDirectiveIrp(IDLoc); - case DK_IRPC: - return ParseDirectiveIrpc(IDLoc); - case DK_ENDR: - return ParseDirectiveEndr(IDLoc); - case DK_BUNDLE_ALIGN_MODE: - return ParseDirectiveBundleAlignMode(); - case DK_BUNDLE_LOCK: - return ParseDirectiveBundleLock(); - case DK_BUNDLE_UNLOCK: - return ParseDirectiveBundleUnlock(); - case DK_SLEB128: - return ParseDirectiveLEB128(true); - case DK_ULEB128: - return ParseDirectiveLEB128(false); - case DK_SPACE: - case DK_SKIP: - return ParseDirectiveSpace(IDVal); - case DK_FILE: - return ParseDirectiveFile(IDLoc); - case DK_LINE: - return ParseDirectiveLine(); - case DK_LOC: - return ParseDirectiveLoc(); - case DK_STABS: - return ParseDirectiveStabs(); - case DK_CFI_SECTIONS: - return ParseDirectiveCFISections(); - case DK_CFI_STARTPROC: - return ParseDirectiveCFIStartProc(); - case DK_CFI_ENDPROC: - return ParseDirectiveCFIEndProc(); - case DK_CFI_DEF_CFA: - return ParseDirectiveCFIDefCfa(IDLoc); - case DK_CFI_DEF_CFA_OFFSET: - return ParseDirectiveCFIDefCfaOffset(); - case DK_CFI_ADJUST_CFA_OFFSET: - return ParseDirectiveCFIAdjustCfaOffset(); - case DK_CFI_DEF_CFA_REGISTER: - return ParseDirectiveCFIDefCfaRegister(IDLoc); - case DK_CFI_OFFSET: - return ParseDirectiveCFIOffset(IDLoc); - case DK_CFI_REL_OFFSET: - return ParseDirectiveCFIRelOffset(IDLoc); - case DK_CFI_PERSONALITY: - return ParseDirectiveCFIPersonalityOrLsda(true); - case DK_CFI_LSDA: - return ParseDirectiveCFIPersonalityOrLsda(false); - case DK_CFI_REMEMBER_STATE: - return ParseDirectiveCFIRememberState(); - case DK_CFI_RESTORE_STATE: - return ParseDirectiveCFIRestoreState(); - case DK_CFI_SAME_VALUE: - return ParseDirectiveCFISameValue(IDLoc); - case DK_CFI_RESTORE: - return ParseDirectiveCFIRestore(IDLoc); - case DK_CFI_ESCAPE: - return ParseDirectiveCFIEscape(); - case DK_CFI_SIGNAL_FRAME: - return ParseDirectiveCFISignalFrame(); - case DK_CFI_UNDEFINED: - return ParseDirectiveCFIUndefined(IDLoc); - case DK_CFI_REGISTER: - return ParseDirectiveCFIRegister(IDLoc); - case DK_MACROS_ON: - case DK_MACROS_OFF: - return ParseDirectiveMacrosOnOff(IDVal); - case DK_MACRO: - return ParseDirectiveMacro(IDLoc); - case DK_ENDM: - case DK_ENDMACRO: - return ParseDirectiveEndMacro(IDVal); - case DK_PURGEM: - return ParseDirectivePurgeMacro(IDLoc); + default: + break; + case DK_SET: + case DK_EQU: + return parseDirectiveSet(IDVal, true); + case DK_EQUIV: + return parseDirectiveSet(IDVal, false); + case DK_ASCII: + return parseDirectiveAscii(IDVal, false); + case DK_ASCIZ: + case DK_STRING: + return parseDirectiveAscii(IDVal, true); + case DK_BYTE: + return parseDirectiveValue(1); + case DK_SHORT: + case DK_VALUE: + case DK_2BYTE: + return parseDirectiveValue(2); + case DK_LONG: + case DK_INT: + case DK_4BYTE: + return parseDirectiveValue(4); + case DK_QUAD: + case DK_8BYTE: + return parseDirectiveValue(8); + case DK_SINGLE: + case DK_FLOAT: + return parseDirectiveRealValue(APFloat::IEEEsingle); + case DK_DOUBLE: + return parseDirectiveRealValue(APFloat::IEEEdouble); + case DK_ALIGN: { + bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes(); + return parseDirectiveAlign(IsPow2, /*ExprSize=*/1); + } + case DK_ALIGN32: { + bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes(); + return parseDirectiveAlign(IsPow2, /*ExprSize=*/4); + } + case DK_BALIGN: + return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1); + case DK_BALIGNW: + return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2); + case DK_BALIGNL: + return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4); + case DK_P2ALIGN: + return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1); + case DK_P2ALIGNW: + return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2); + case DK_P2ALIGNL: + return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4); + case DK_ORG: + return parseDirectiveOrg(); + case DK_FILL: + return parseDirectiveFill(); + case DK_ZERO: + return parseDirectiveZero(); + case DK_EXTERN: + eatToEndOfStatement(); // .extern is the default, ignore it. + return false; + case DK_GLOBL: + case DK_GLOBAL: + return parseDirectiveSymbolAttribute(MCSA_Global); + case DK_LAZY_REFERENCE: + return parseDirectiveSymbolAttribute(MCSA_LazyReference); + case DK_NO_DEAD_STRIP: + return parseDirectiveSymbolAttribute(MCSA_NoDeadStrip); + case DK_SYMBOL_RESOLVER: + return parseDirectiveSymbolAttribute(MCSA_SymbolResolver); + case DK_PRIVATE_EXTERN: + return parseDirectiveSymbolAttribute(MCSA_PrivateExtern); + case DK_REFERENCE: + return parseDirectiveSymbolAttribute(MCSA_Reference); + case DK_WEAK_DEFINITION: + return parseDirectiveSymbolAttribute(MCSA_WeakDefinition); + case DK_WEAK_REFERENCE: + return parseDirectiveSymbolAttribute(MCSA_WeakReference); + case DK_WEAK_DEF_CAN_BE_HIDDEN: + return parseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate); + case DK_COMM: + case DK_COMMON: + return parseDirectiveComm(/*IsLocal=*/false); + case DK_LCOMM: + return parseDirectiveComm(/*IsLocal=*/true); + case DK_ABORT: + return parseDirectiveAbort(); + case DK_INCLUDE: + return parseDirectiveInclude(); + case DK_INCBIN: + return parseDirectiveIncbin(); + case DK_CODE16: + case DK_CODE16GCC: + return TokError(Twine(IDVal) + " not supported yet"); + case DK_REPT: + return parseDirectiveRept(IDLoc); + case DK_IRP: + return parseDirectiveIrp(IDLoc); + case DK_IRPC: + return parseDirectiveIrpc(IDLoc); + case DK_ENDR: + return parseDirectiveEndr(IDLoc); + case DK_BUNDLE_ALIGN_MODE: + return parseDirectiveBundleAlignMode(); + case DK_BUNDLE_LOCK: + return parseDirectiveBundleLock(); + case DK_BUNDLE_UNLOCK: + return parseDirectiveBundleUnlock(); + case DK_SLEB128: + return parseDirectiveLEB128(true); + case DK_ULEB128: + return parseDirectiveLEB128(false); + case DK_SPACE: + case DK_SKIP: + return parseDirectiveSpace(IDVal); + case DK_FILE: + return parseDirectiveFile(IDLoc); + case DK_LINE: + return parseDirectiveLine(); + case DK_LOC: + return parseDirectiveLoc(); + case DK_STABS: + return parseDirectiveStabs(); + case DK_CFI_SECTIONS: + return parseDirectiveCFISections(); + case DK_CFI_STARTPROC: + return parseDirectiveCFIStartProc(); + case DK_CFI_ENDPROC: + return parseDirectiveCFIEndProc(); + case DK_CFI_DEF_CFA: + return parseDirectiveCFIDefCfa(IDLoc); + case DK_CFI_DEF_CFA_OFFSET: + return parseDirectiveCFIDefCfaOffset(); + case DK_CFI_ADJUST_CFA_OFFSET: + return parseDirectiveCFIAdjustCfaOffset(); + case DK_CFI_DEF_CFA_REGISTER: + return parseDirectiveCFIDefCfaRegister(IDLoc); + case DK_CFI_OFFSET: + return parseDirectiveCFIOffset(IDLoc); + case DK_CFI_REL_OFFSET: + return parseDirectiveCFIRelOffset(IDLoc); + case DK_CFI_PERSONALITY: + return parseDirectiveCFIPersonalityOrLsda(true); + case DK_CFI_LSDA: + return parseDirectiveCFIPersonalityOrLsda(false); + case DK_CFI_REMEMBER_STATE: + return parseDirectiveCFIRememberState(); + case DK_CFI_RESTORE_STATE: + return parseDirectiveCFIRestoreState(); + case DK_CFI_SAME_VALUE: + return parseDirectiveCFISameValue(IDLoc); + case DK_CFI_RESTORE: + return parseDirectiveCFIRestore(IDLoc); + case DK_CFI_ESCAPE: + return parseDirectiveCFIEscape(); + case DK_CFI_SIGNAL_FRAME: + return parseDirectiveCFISignalFrame(); + case DK_CFI_UNDEFINED: + return parseDirectiveCFIUndefined(IDLoc); + case DK_CFI_REGISTER: + return parseDirectiveCFIRegister(IDLoc); + case DK_CFI_WINDOW_SAVE: + return parseDirectiveCFIWindowSave(); + case DK_MACROS_ON: + case DK_MACROS_OFF: + return parseDirectiveMacrosOnOff(IDVal); + case DK_MACRO: + return parseDirectiveMacro(IDLoc); + case DK_ENDM: + case DK_ENDMACRO: + return parseDirectiveEndMacro(IDVal); + case DK_PURGEM: + return parseDirectivePurgeMacro(IDLoc); } return Error(IDLoc, "unknown directive"); @@ -1478,19 +1500,19 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { // __asm _emit or __asm __emit if (ParsingInlineAsm && (IDVal == "_emit" || IDVal == "__emit" || IDVal == "_EMIT" || IDVal == "__EMIT")) - return ParseDirectiveMSEmit(IDLoc, Info, IDVal.size()); + return parseDirectiveMSEmit(IDLoc, Info, IDVal.size()); // __asm align if (ParsingInlineAsm && (IDVal == "align" || IDVal == "ALIGN")) - return ParseDirectiveMSAlign(IDLoc, Info); + return parseDirectiveMSAlign(IDLoc, Info); checkForValidSection(); // Canonicalize the opcode to lower case. std::string OpcodeStr = IDVal.lower(); ParseInstructionInfo IInfo(Info.AsmRewrites); - bool HadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, - IDLoc, Info.ParsedOperands); + bool HadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, IDLoc, + Info.ParsedOperands); Info.ParseError = HadError; // Dump the parsed representation, if requested. @@ -1505,7 +1527,7 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { } OS << "]"; - PrintMessage(IDLoc, SourceMgr::DK_Note, OS.str()); + printMessage(IDLoc, SourceMgr::DK_Note, OS.str()); } // If we are generating dwarf for assembly source files and the current @@ -1513,49 +1535,49 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { // the instruction. if (!HadError && getContext().getGenDwarfForAssembly() && getContext().getGenDwarfSection() == - getStreamer().getCurrentSection().first) { + 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(); + const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles = + getContext().getMCDwarfFiles(); if (CppHashFilename.size() != 0) { if (MCDwarfFiles[getContext().getGenDwarfFileNumber()]->getName() != CppHashFilename) getStreamer().EmitDwarfFileDirective( - getContext().nextGenDwarfFileNumber(), StringRef(), CppHashFilename); - - // Since SrcMgr.FindLineNumber() is slow and messes up the SourceMgr's - // cache with the different Loc from the call above we save the last - // info we queried here with SrcMgr.FindLineNumber(). - unsigned CppHashLocLineNo; - if (LastQueryIDLoc == CppHashLoc && LastQueryBuffer == CppHashBuf) - CppHashLocLineNo = LastQueryLine; - else { - CppHashLocLineNo = SrcMgr.FindLineNumber(CppHashLoc, CppHashBuf); - LastQueryLine = CppHashLocLineNo; - LastQueryIDLoc = CppHashLoc; - LastQueryBuffer = CppHashBuf; - } - Line = CppHashLineNumber - 1 + (Line - CppHashLocLineNo); + getContext().nextGenDwarfFileNumber(), StringRef(), + CppHashFilename); + + // Since SrcMgr.FindLineNumber() is slow and messes up the SourceMgr's + // cache with the different Loc from the call above we save the last + // info we queried here with SrcMgr.FindLineNumber(). + unsigned CppHashLocLineNo; + if (LastQueryIDLoc == CppHashLoc && LastQueryBuffer == CppHashBuf) + CppHashLocLineNo = LastQueryLine; + else { + CppHashLocLineNo = SrcMgr.FindLineNumber(CppHashLoc, CppHashBuf); + LastQueryLine = CppHashLocLineNo; + LastQueryIDLoc = CppHashLoc; + LastQueryBuffer = CppHashBuf; + } + Line = CppHashLineNumber - 1 + (Line - CppHashLocLineNo); } - getStreamer().EmitDwarfLocDirective(getContext().getGenDwarfFileNumber(), - Line, 0, DWARF2_LINE_DEFAULT_IS_STMT ? - DWARF2_FLAG_IS_STMT : 0, 0, 0, - StringRef()); + getStreamer().EmitDwarfLocDirective( + getContext().getGenDwarfFileNumber(), Line, 0, + DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0, + StringRef()); } // If parsing succeeded, match the instruction. if (!HadError) { unsigned ErrorInfo; - HadError = getTargetParser().MatchAndEmitInstruction(IDLoc, Info.Opcode, - Info.ParsedOperands, - Out, ErrorInfo, - ParsingInlineAsm); + HadError = getTargetParser().MatchAndEmitInstruction( + IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo, + ParsingInlineAsm); } // Don't skip the rest of the line, the instruction parser is responsible for @@ -1563,25 +1585,25 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { return false; } -/// EatToEndOfLine uses the Lexer to eat the characters to the end of the line +/// eatToEndOfLine uses the Lexer to eat the characters to the end of the line /// since they may not be able to be tokenized to get to the end of line token. -void AsmParser::EatToEndOfLine() { +void AsmParser::eatToEndOfLine() { if (!Lexer.is(AsmToken::EndOfStatement)) Lexer.LexUntilEndOfLine(); - // Eat EOL. - Lex(); + // Eat EOL. + Lex(); } -/// ParseCppHashLineFilenameComment as this: +/// parseCppHashLineFilenameComment as this: /// ::= # number "filename" /// or just as a full line comment if it doesn't have a number and a string. -bool AsmParser::ParseCppHashLineFilenameComment(const SMLoc &L) { +bool AsmParser::parseCppHashLineFilenameComment(const SMLoc &L) { Lex(); // Eat the hash token. if (getLexer().isNot(AsmToken::Integer)) { // Consume the line since in cases it is not a well-formed line directive, // as if were simply a full line comment. - EatToEndOfLine(); + eatToEndOfLine(); return false; } @@ -1589,13 +1611,13 @@ bool AsmParser::ParseCppHashLineFilenameComment(const SMLoc &L) { Lex(); if (getLexer().isNot(AsmToken::String)) { - EatToEndOfLine(); + eatToEndOfLine(); return false; } StringRef Filename = getTok().getString(); // Get rid of the enclosing quotes. - Filename = Filename.substr(1, Filename.size()-2); + Filename = Filename.substr(1, Filename.size() - 2); // Save the SMLoc, Filename and LineNumber for later use by diagnostics. CppHashLoc = L; @@ -1604,14 +1626,14 @@ bool AsmParser::ParseCppHashLineFilenameComment(const SMLoc &L) { CppHashBuf = CurBuffer; // Ignore any trailing characters, they're just comment. - EatToEndOfLine(); + eatToEndOfLine(); return false; } -/// DiagHandler - will use the last parsed cpp hash line filename comment +/// \brief will use the last parsed cpp hash line filename comment /// for the Filename and LineNo if any in the diagnostic. void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { - const AsmParser *Parser = static_cast<const AsmParser*>(Context); + const AsmParser *Parser = static_cast<const AsmParser *>(Context); raw_ostream &OS = errs(); const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr(); @@ -1619,19 +1641,18 @@ void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { int DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); int CppHashBuf = Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashLoc); - // Like SourceMgr::PrintMessage() we need to print the include stack if any + // 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) { - SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer); - DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS); + SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer); + DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS); } // If we have not parsed a cpp hash line filename comment or the source // manager changed or buffer changed (like in a nested include) then just // print the normal diagnostic using its Filename and LineNo. - if (!Parser->CppHashLineNumber || - &DiagSrcMgr != &Parser->SrcMgr || + if (!Parser->CppHashLineNumber || &DiagSrcMgr != &Parser->SrcMgr || DiagBuf != CppHashBuf) { if (Parser->SavedDiagHandler) Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext); @@ -1643,17 +1664,16 @@ void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { // Use the CppHashFilename and calculate a line number based on the // CppHashLoc and CppHashLineNumber relative to this Diag's SMLoc for // the diagnostic. - const std::string Filename = Parser->CppHashFilename; + const std::string &Filename = Parser->CppHashFilename; int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf); int CppHashLocLineNo = Parser->SrcMgr.FindLineNumber(Parser->CppHashLoc, CppHashBuf); - int LineNo = Parser->CppHashLineNumber - 1 + - (DiagLocLineNo - CppHashLocLineNo); + int LineNo = + Parser->CppHashLineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo); - SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), - Filename, LineNo, Diag.getColumnNo(), - Diag.getKind(), Diag.getMessage(), + SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo, + Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(), Diag.getLineContents(), Diag.getRanges()); if (Parser->SavedDiagHandler) @@ -1673,8 +1693,7 @@ static bool isIdentifierChar(char c) { bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, const MCAsmMacroParameters &Parameters, - const MCAsmMacroArguments &A, - const SMLoc &L) { + const MCAsmMacroArguments &A, const SMLoc &L) { unsigned NParameters = Parameters.size(); if (NParameters != 0 && NParameters != A.size()) return Error(L, "Wrong number of arguments"); @@ -1710,27 +1729,28 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, break; if (!NParameters) { - switch (Body[Pos+1]) { - // $$ => $ + switch (Body[Pos + 1]) { + // $$ => $ case '$': OS << '$'; break; - // $n => number of arguments + // $n => number of arguments case 'n': OS << A.size(); break; - // $[0-9] => argument + // $[0-9] => argument default: { // Missing arguments are ignored. - unsigned Index = Body[Pos+1] - '0'; + unsigned Index = Body[Pos + 1] - '0'; if (Index >= A.size()) break; // Otherwise substitute with the token values, with spaces eliminated. for (MCAsmMacroArgument::const_iterator it = A[Index].begin(), - ie = A[Index].end(); it != ie; ++it) + ie = A[Index].end(); + it != ie; ++it) OS << it->getString(); break; } @@ -1741,23 +1761,24 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, while (isIdentifierChar(Body[I]) && I + 1 != End) ++I; - const char *Begin = Body.data() + Pos +1; - StringRef Argument(Begin, I - (Pos +1)); + const char *Begin = Body.data() + Pos + 1; + StringRef Argument(Begin, I - (Pos + 1)); unsigned Index = 0; for (; Index < NParameters; ++Index) if (Parameters[Index].first == Argument) break; if (Index == NParameters) { - if (Body[Pos+1] == '(' && Body[Pos+2] == ')') - Pos += 3; - else { - OS << '\\' << Argument; - Pos = I; - } + if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')') + Pos += 3; + else { + OS << '\\' << Argument; + Pos = I; + } } else { for (MCAsmMacroArgument::const_iterator it = A[Index].begin(), - ie = A[Index].end(); it != ie; ++it) + ie = A[Index].end(); + it != ie; ++it) if (it->getKind() == AsmToken::String) OS << it->getStringContents(); else @@ -1773,48 +1794,43 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, return false; } -MacroInstantiation::MacroInstantiation(const MCAsmMacro *M, SMLoc IL, - int EB, SMLoc EL, - MemoryBuffer *I) - : TheMacro(M), Instantiation(I), InstantiationLoc(IL), ExitBuffer(EB), - ExitLoc(EL) -{ -} +MacroInstantiation::MacroInstantiation(const MCAsmMacro *M, SMLoc IL, int EB, + SMLoc EL, MemoryBuffer *I) + : TheMacro(M), Instantiation(I), InstantiationLoc(IL), ExitBuffer(EB), + ExitLoc(EL) {} -static bool IsOperator(AsmToken::TokenKind kind) -{ - switch (kind) - { - default: - return false; - case AsmToken::Plus: - case AsmToken::Minus: - case AsmToken::Tilde: - case AsmToken::Slash: - case AsmToken::Star: - case AsmToken::Dot: - case AsmToken::Equal: - case AsmToken::EqualEqual: - case AsmToken::Pipe: - case AsmToken::PipePipe: - case AsmToken::Caret: - case AsmToken::Amp: - case AsmToken::AmpAmp: - case AsmToken::Exclaim: - case AsmToken::ExclaimEqual: - case AsmToken::Percent: - case AsmToken::Less: - case AsmToken::LessEqual: - case AsmToken::LessLess: - case AsmToken::LessGreater: - case AsmToken::Greater: - case AsmToken::GreaterEqual: - case AsmToken::GreaterGreater: - return true; +static bool isOperator(AsmToken::TokenKind kind) { + switch (kind) { + default: + return false; + case AsmToken::Plus: + case AsmToken::Minus: + case AsmToken::Tilde: + case AsmToken::Slash: + case AsmToken::Star: + case AsmToken::Dot: + case AsmToken::Equal: + case AsmToken::EqualEqual: + case AsmToken::Pipe: + case AsmToken::PipePipe: + case AsmToken::Caret: + case AsmToken::Amp: + case AsmToken::AmpAmp: + case AsmToken::Exclaim: + case AsmToken::ExclaimEqual: + case AsmToken::Percent: + case AsmToken::Less: + case AsmToken::LessEqual: + case AsmToken::LessLess: + case AsmToken::LessGreater: + case AsmToken::Greater: + case AsmToken::GreaterEqual: + case AsmToken::GreaterGreater: + return true; } } -bool AsmParser::ParseMacroArgument(MCAsmMacroArgument &MA, +bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, AsmToken::TokenKind &ArgumentDelimiter) { unsigned ParenLevel = 0; unsigned AddTokens = 0; @@ -1848,7 +1864,7 @@ bool AsmParser::ParseMacroArgument(MCAsmMacroArgument &MA, // one into this argument if (ArgumentDelimiter == AsmToken::Space || ArgumentDelimiter == AsmToken::Eof) { - if (IsOperator(Lexer.getKind())) { + if (isOperator(Lexer.getKind())) { // Check to see whether the token is used as an operator, // or part of an identifier const char *NextChar = getTok().getEndLoc().getPointer(); @@ -1858,14 +1874,14 @@ bool AsmParser::ParseMacroArgument(MCAsmMacroArgument &MA, if (!AddTokens && ParenLevel == 0) { if (ArgumentDelimiter == AsmToken::Eof && - !IsOperator(Lexer.getKind())) + !isOperator(Lexer.getKind())) ArgumentDelimiter = AsmToken::Space; break; } } } - // HandleMacroEntry relies on not advancing the lexer here + // handleMacroEntry relies on not advancing the lexer here // to be able to fill in the remaining default parameter values if (Lexer.is(AsmToken::EndOfStatement)) break; @@ -1890,10 +1906,11 @@ bool AsmParser::ParseMacroArgument(MCAsmMacroArgument &MA, } // Parse the macro instantiation arguments. -bool AsmParser::ParseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A) { +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() + // parseMacroArgument() AsmToken::TokenKind ArgumentDelimiter = AsmToken::Eof; // Parse two kinds of macro invocations: @@ -1903,7 +1920,7 @@ bool AsmParser::ParseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A) ++Parameter) { MCAsmMacroArgument MA; - if (ParseMacroArgument(MA, ArgumentDelimiter)) + if (parseMacroArgument(MA, ArgumentDelimiter)) return true; if (!MA.empty() || !NParameters) @@ -1934,31 +1951,31 @@ bool AsmParser::ParseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A) return TokError("Too many arguments"); } -const MCAsmMacro* AsmParser::LookupMacro(StringRef Name) { - StringMap<MCAsmMacro*>::iterator I = MacroMap.find(Name); +const MCAsmMacro *AsmParser::lookupMacro(StringRef Name) { + StringMap<MCAsmMacro *>::iterator I = MacroMap.find(Name); return (I == MacroMap.end()) ? NULL : I->getValue(); } -void AsmParser::DefineMacro(StringRef Name, const MCAsmMacro& Macro) { +void AsmParser::defineMacro(StringRef Name, const MCAsmMacro &Macro) { MacroMap[Name] = new MCAsmMacro(Macro); } -void AsmParser::UndefineMacro(StringRef Name) { - StringMap<MCAsmMacro*>::iterator I = MacroMap.find(Name); +void AsmParser::undefineMacro(StringRef Name) { + StringMap<MCAsmMacro *>::iterator I = MacroMap.find(Name); if (I != MacroMap.end()) { delete I->getValue(); MacroMap.erase(I); } } -bool AsmParser::HandleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) { +bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) { // Arbitrarily limit macro nesting depth, to match 'as'. We can eliminate // this, although we should protect against infinite loops. if (ActiveMacros.size() == 20) return TokError("macros cannot be nested more than 20 levels deep"); MCAsmMacroArguments A; - if (ParseMacroArguments(M, A)) + if (parseMacroArguments(M, A)) return true; // Remove any trailing empty arguments. Do this after-the-fact as we have @@ -1981,14 +1998,12 @@ bool AsmParser::HandleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) { OS << ".endmacro\n"; MemoryBuffer *Instantiation = - MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>"); + MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>"); // Create the macro instantiation object and add to the current macro // instantiation stack. - MacroInstantiation *MI = new MacroInstantiation(M, NameLoc, - CurBuffer, - getTok().getLoc(), - Instantiation); + MacroInstantiation *MI = new MacroInstantiation( + M, NameLoc, CurBuffer, getTok().getLoc(), Instantiation); ActiveMacros.push_back(MI); // Jump to the macro instantiation and prime the lexer. @@ -1999,9 +2014,9 @@ bool AsmParser::HandleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) { return false; } -void AsmParser::HandleMacroExit() { +void AsmParser::handleMacroExit() { // Jump to the EndOfStatement we should return to, and consume it. - JumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer); + jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer); Lex(); // Pop the instantiation entry. @@ -2009,29 +2024,30 @@ void AsmParser::HandleMacroExit() { ActiveMacros.pop_back(); } -static bool IsUsedIn(const MCSymbol *Sym, const MCExpr *Value) { +static bool isUsedIn(const MCSymbol *Sym, const MCExpr *Value) { switch (Value->getKind()) { case MCExpr::Binary: { - const MCBinaryExpr *BE = static_cast<const MCBinaryExpr*>(Value); - return IsUsedIn(Sym, BE->getLHS()) || IsUsedIn(Sym, BE->getRHS()); + const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Value); + return isUsedIn(Sym, BE->getLHS()) || isUsedIn(Sym, BE->getRHS()); } case MCExpr::Target: case MCExpr::Constant: return false; case MCExpr::SymbolRef: { - const MCSymbol &S = static_cast<const MCSymbolRefExpr*>(Value)->getSymbol(); + const MCSymbol &S = + static_cast<const MCSymbolRefExpr *>(Value)->getSymbol(); if (S.isVariable()) - return IsUsedIn(Sym, S.getVariableValue()); + return isUsedIn(Sym, S.getVariableValue()); return &S == Sym; } case MCExpr::Unary: - return IsUsedIn(Sym, static_cast<const MCUnaryExpr*>(Value)->getSubExpr()); + return isUsedIn(Sym, static_cast<const MCUnaryExpr *>(Value)->getSubExpr()); } llvm_unreachable("Unknown expr kind!"); } -bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef, +bool AsmParser::parseAssignment(StringRef Name, bool allow_redef, bool NoDeadStrip) { // FIXME: Use better location, we should use proper tokens. SMLoc EqualLoc = Lexer.getLoc(); @@ -2064,7 +2080,7 @@ bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef, // // FIXME: Diagnostics. Note the location of the definition as a label. // FIXME: Diagnose assignment to protected identifier (e.g., register name). - if (IsUsedIn(Sym, Value)) + if (isUsedIn(Sym, Value)) return Error(EqualLoc, "Recursive use of '" + Name + "'"); else if (Sym->isUndefined() && !Sym->isUsed() && !Sym->isVariable()) ; // Allow redefinitions of undefined symbols only used in directives. @@ -2076,7 +2092,7 @@ bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef, return Error(EqualLoc, "invalid assignment to '" + Name + "'"); else if (!isa<MCConstantExpr>(Sym->getVariableValue())) return Error(EqualLoc, "invalid reassignment of non-absolute variable '" + - Name + "'"); + Name + "'"); // Don't count these checks as uses. Sym->setUsed(false); @@ -2090,7 +2106,6 @@ bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef, if (NoDeadStrip) Out.EmitSymbolAttribute(Sym, MCSA_NoDeadStrip); - return false; } @@ -2099,31 +2114,30 @@ bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef, /// ::= string bool AsmParser::parseIdentifier(StringRef &Res) { // The assembler has relaxed rules for accepting identifiers, in particular we - // allow things like '.globl $foo', which would normally be separate - // tokens. At this level, we have already lexed so we cannot (currently) + // allow things like '.globl $foo' and '.def @feat.00', which would normally be + // separate tokens. At this level, we have already lexed so we cannot (currently) // handle this as a context dependent token, instead we detect adjacent tokens // and return the combined identifier. - if (Lexer.is(AsmToken::Dollar)) { - SMLoc DollarLoc = getLexer().getLoc(); + if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) { + SMLoc PrefixLoc = getLexer().getLoc(); - // Consume the dollar sign, and check for a following identifier. + // Consume the prefix character, and check for a following identifier. Lex(); if (Lexer.isNot(AsmToken::Identifier)) return true; - // We have a '$' followed by an identifier, make sure they are adjacent. - if (DollarLoc.getPointer() + 1 != getTok().getLoc().getPointer()) + // We have a '$' or '@' followed by an identifier, make sure they are adjacent. + if (PrefixLoc.getPointer() + 1 != getTok().getLoc().getPointer()) return true; // Construct the joined identifier and consume the token. - Res = StringRef(DollarLoc.getPointer(), - getTok().getIdentifier().size() + 1); + Res = + StringRef(PrefixLoc.getPointer(), getTok().getIdentifier().size() + 1); Lex(); return false; } - if (Lexer.isNot(AsmToken::Identifier) && - Lexer.isNot(AsmToken::String)) + if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String)) return true; Res = getTok().getIdentifier(); @@ -2133,11 +2147,11 @@ bool AsmParser::parseIdentifier(StringRef &Res) { return false; } -/// ParseDirectiveSet: +/// parseDirectiveSet: /// ::= .equ identifier ',' expression /// ::= .equiv identifier ',' expression /// ::= .set identifier ',' expression -bool AsmParser::ParseDirectiveSet(StringRef IDVal, bool allow_redef) { +bool AsmParser::parseDirectiveSet(StringRef IDVal, bool allow_redef) { StringRef Name; if (parseIdentifier(Name)) @@ -2147,7 +2161,7 @@ bool AsmParser::ParseDirectiveSet(StringRef IDVal, bool allow_redef) { return TokError("unexpected token in '" + Twine(IDVal) + "'"); Lex(); - return ParseAssignment(Name, allow_redef, true); + return parseAssignment(Name, allow_redef, true); } bool AsmParser::parseEscapedString(std::string &Data) { @@ -2168,15 +2182,15 @@ bool AsmParser::parseEscapedString(std::string &Data) { return TokError("unexpected backslash at end of string"); // Recognize octal sequences. - if ((unsigned) (Str[i] - '0') <= 7) { + if ((unsigned)(Str[i] - '0') <= 7) { // Consume up to three octal characters. unsigned Value = Str[i] - '0'; - if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) { + if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) { ++i; Value = Value * 8 + (Str[i] - '0'); - if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) { + if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) { ++i; Value = Value * 8 + (Str[i] - '0'); } @@ -2185,7 +2199,7 @@ bool AsmParser::parseEscapedString(std::string &Data) { if (Value > 255) return TokError("invalid octal escape sequence (out of range)"); - Data += (unsigned char) Value; + Data += (unsigned char)Value; continue; } @@ -2208,9 +2222,9 @@ bool AsmParser::parseEscapedString(std::string &Data) { return false; } -/// ParseDirectiveAscii: +/// parseDirectiveAscii: /// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ] -bool AsmParser::ParseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) { +bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) { if (getLexer().isNot(AsmToken::EndOfStatement)) { checkForValidSection(); @@ -2241,9 +2255,9 @@ bool AsmParser::ParseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) { return false; } -/// ParseDirectiveValue +/// parseDirectiveValue /// ::= (.byte | .short | ... ) [ expression (, expression)* ] -bool AsmParser::ParseDirectiveValue(unsigned Size) { +bool AsmParser::parseDirectiveValue(unsigned Size) { if (getLexer().isNot(AsmToken::EndOfStatement)) { checkForValidSection(); @@ -2277,9 +2291,9 @@ bool AsmParser::ParseDirectiveValue(unsigned Size) { return false; } -/// ParseDirectiveRealValue +/// parseDirectiveRealValue /// ::= (.single | .double) [ expression (, expression)* ] -bool AsmParser::ParseDirectiveRealValue(const fltSemantics &Semantics) { +bool AsmParser::parseDirectiveRealValue(const fltSemantics &Semantics) { if (getLexer().isNot(AsmToken::EndOfStatement)) { checkForValidSection(); @@ -2309,7 +2323,7 @@ bool AsmParser::ParseDirectiveRealValue(const fltSemantics &Semantics) { else return TokError("invalid floating point literal"); } else if (Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) == - APFloat::opInvalidOp) + APFloat::opInvalidOp) return TokError("invalid floating point literal"); if (IsNeg) Value.changeSign(); @@ -2335,9 +2349,9 @@ bool AsmParser::ParseDirectiveRealValue(const fltSemantics &Semantics) { return false; } -/// ParseDirectiveZero +/// parseDirectiveZero /// ::= .zero expression -bool AsmParser::ParseDirectiveZero() { +bool AsmParser::parseDirectiveZero() { checkForValidSection(); int64_t NumBytes; @@ -2361,35 +2375,40 @@ bool AsmParser::ParseDirectiveZero() { return false; } -/// ParseDirectiveFill -/// ::= .fill expression , expression , expression -bool AsmParser::ParseDirectiveFill() { +/// parseDirectiveFill +/// ::= .fill expression [ , expression [ , expression ] ] +bool AsmParser::parseDirectiveFill() { checkForValidSection(); int64_t NumValues; if (parseAbsoluteExpression(NumValues)) return true; - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '.fill' directive"); - Lex(); + int64_t FillSize = 1; + int64_t FillExpr = 0; - int64_t FillSize; - if (parseAbsoluteExpression(FillSize)) - return true; + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in '.fill' directive"); + Lex(); - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '.fill' directive"); - Lex(); + if (parseAbsoluteExpression(FillSize)) + return true; - int64_t FillExpr; - if (parseAbsoluteExpression(FillExpr)) - return true; + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in '.fill' directive"); + Lex(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.fill' directive"); + if (parseAbsoluteExpression(FillExpr)) + return true; - Lex(); + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.fill' directive"); + + Lex(); + } + } if (FillSize != 1 && FillSize != 2 && FillSize != 4 && FillSize != 8) return TokError("invalid '.fill' size, expected 1, 2, 4, or 8"); @@ -2400,9 +2419,9 @@ bool AsmParser::ParseDirectiveFill() { return false; } -/// ParseDirectiveOrg +/// parseDirectiveOrg /// ::= .org expression [ , expression ] -bool AsmParser::ParseDirectiveOrg() { +bool AsmParser::parseDirectiveOrg() { checkForValidSection(); const MCExpr *Offset; @@ -2435,9 +2454,9 @@ bool AsmParser::ParseDirectiveOrg() { return false; } -/// ParseDirectiveAlign +/// parseDirectiveAlign /// ::= {.align, ...} expression [ , expression [ , expression ]] -bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { +bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) { checkForValidSection(); SMLoc AlignmentLoc = getLexer().getLoc(); @@ -2501,13 +2520,13 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { if (MaxBytesLoc.isValid()) { if (MaxBytesToFill < 1) { Error(MaxBytesLoc, "alignment directive can never be satisfied in this " - "many bytes, ignoring maximum bytes expression"); + "many bytes, ignoring maximum bytes expression"); MaxBytesToFill = 0; } if (MaxBytesToFill >= Alignment) { Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and " - "has no effect"); + "has no effect"); MaxBytesToFill = 0; } } @@ -2527,10 +2546,10 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { return false; } -/// ParseDirectiveFile +/// parseDirectiveFile /// ::= .file [number] filename /// ::= .file number directory filename -bool AsmParser::ParseDirectiveFile(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) { // FIXME: I'm not sure what this is. int64_t FileNumber = -1; SMLoc FileNumberLoc = getLexer().getLoc(); @@ -2546,17 +2565,21 @@ bool AsmParser::ParseDirectiveFile(SMLoc DirectiveLoc) { return TokError("unexpected token in '.file' directive"); // Usually the directory and filename together, otherwise just the directory. - StringRef Path = getTok().getString(); - Path = Path.substr(1, Path.size()-2); + // Allow the strings to have escaped octal character sequence. + std::string Path = getTok().getString(); + if (parseEscapedString(Path)) + return true; Lex(); StringRef Directory; StringRef Filename; + std::string FilenameData; if (getLexer().is(AsmToken::String)) { if (FileNumber == -1) return TokError("explicit path specified, but no file number"); - Filename = getTok().getString(); - Filename = Filename.substr(1, Filename.size()-2); + if (parseEscapedString(FilenameData)) + return true; + Filename = FilenameData; Directory = Path; Lex(); } else { @@ -2570,8 +2593,9 @@ bool AsmParser::ParseDirectiveFile(SMLoc DirectiveLoc) { getStreamer().EmitFileDirective(Filename); else { if (getContext().getGenDwarfForAssembly() == true) - Error(DirectiveLoc, "input can't have .file dwarf directives when -g is " - "used to generate dwarf debug info for assembly code"); + Error(DirectiveLoc, + "input can't have .file dwarf directives when -g is " + "used to generate dwarf debug info for assembly code"); if (getStreamer().EmitDwarfFileDirective(FileNumber, Directory, Filename)) Error(FileNumberLoc, "file number already allocated"); @@ -2580,15 +2604,15 @@ bool AsmParser::ParseDirectiveFile(SMLoc DirectiveLoc) { return false; } -/// ParseDirectiveLine +/// parseDirectiveLine /// ::= .line [number] -bool AsmParser::ParseDirectiveLine() { +bool AsmParser::parseDirectiveLine() { if (getLexer().isNot(AsmToken::EndOfStatement)) { if (getLexer().isNot(AsmToken::Integer)) return TokError("unexpected token in '.line' directive"); int64_t LineNumber = getTok().getIntVal(); - (void) LineNumber; + (void)LineNumber; Lex(); // FIXME: Do something with the .line. @@ -2600,14 +2624,14 @@ bool AsmParser::ParseDirectiveLine() { return false; } -/// ParseDirectiveLoc +/// parseDirectiveLoc /// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end] /// [epilogue_begin] [is_stmt VALUE] [isa VALUE] /// The first number is a file number, must have been previously assigned with /// a .file directive, the second number is the line number and optionally the /// third number is a column position (zero if not specified). The remaining /// optional items are .loc sub-directives. -bool AsmParser::ParseDirectiveLoc() { +bool AsmParser::parseDirectiveLoc() { if (getLexer().isNot(AsmToken::Integer)) return TokError("unexpected token in '.loc' directive"); int64_t FileNumber = getTok().getIntVal(); @@ -2620,8 +2644,8 @@ bool AsmParser::ParseDirectiveLoc() { int64_t LineNumber = 0; if (getLexer().is(AsmToken::Integer)) { LineNumber = getTok().getIntVal(); - if (LineNumber < 1) - return TokError("line number less than one in '.loc' directive"); + if (LineNumber < 0) + return TokError("line number less than zero in '.loc' directive"); Lex(); } @@ -2701,15 +2725,15 @@ bool AsmParser::ParseDirectiveLoc() { return false; } -/// ParseDirectiveStabs +/// parseDirectiveStabs /// ::= .stabs string, number, number, number -bool AsmParser::ParseDirectiveStabs() { +bool AsmParser::parseDirectiveStabs() { return TokError("unsupported directive '.stabs'"); } -/// ParseDirectiveCFISections +/// parseDirectiveCFISections /// ::= .cfi_sections section [, section] -bool AsmParser::ParseDirectiveCFISections() { +bool AsmParser::parseDirectiveCFISections() { StringRef Name; bool EH = false; bool Debug = false; @@ -2738,22 +2762,22 @@ bool AsmParser::ParseDirectiveCFISections() { return false; } -/// ParseDirectiveCFIStartProc +/// parseDirectiveCFIStartProc /// ::= .cfi_startproc -bool AsmParser::ParseDirectiveCFIStartProc() { +bool AsmParser::parseDirectiveCFIStartProc() { getStreamer().EmitCFIStartProc(); return false; } -/// ParseDirectiveCFIEndProc +/// parseDirectiveCFIEndProc /// ::= .cfi_endproc -bool AsmParser::ParseDirectiveCFIEndProc() { +bool AsmParser::parseDirectiveCFIEndProc() { getStreamer().EmitCFIEndProc(); return false; } -/// ParseRegisterOrRegisterNumber - parse register name or number. -bool AsmParser::ParseRegisterOrRegisterNumber(int64_t &Register, +/// \brief parse register name or number. +bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc) { unsigned RegNo; @@ -2767,11 +2791,11 @@ bool AsmParser::ParseRegisterOrRegisterNumber(int64_t &Register, return false; } -/// ParseDirectiveCFIDefCfa +/// parseDirectiveCFIDefCfa /// ::= .cfi_def_cfa register, offset -bool AsmParser::ParseDirectiveCFIDefCfa(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) { int64_t Register = 0; - if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; if (getLexer().isNot(AsmToken::Comma)) @@ -2786,9 +2810,9 @@ bool AsmParser::ParseDirectiveCFIDefCfa(SMLoc DirectiveLoc) { return false; } -/// ParseDirectiveCFIDefCfaOffset +/// parseDirectiveCFIDefCfaOffset /// ::= .cfi_def_cfa_offset offset -bool AsmParser::ParseDirectiveCFIDefCfaOffset() { +bool AsmParser::parseDirectiveCFIDefCfaOffset() { int64_t Offset = 0; if (parseAbsoluteExpression(Offset)) return true; @@ -2797,11 +2821,11 @@ bool AsmParser::ParseDirectiveCFIDefCfaOffset() { return false; } -/// ParseDirectiveCFIRegister +/// parseDirectiveCFIRegister /// ::= .cfi_register register, register -bool AsmParser::ParseDirectiveCFIRegister(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) { int64_t Register1 = 0; - if (ParseRegisterOrRegisterNumber(Register1, DirectiveLoc)) + if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc)) return true; if (getLexer().isNot(AsmToken::Comma)) @@ -2809,16 +2833,23 @@ bool AsmParser::ParseDirectiveCFIRegister(SMLoc DirectiveLoc) { Lex(); int64_t Register2 = 0; - if (ParseRegisterOrRegisterNumber(Register2, DirectiveLoc)) + if (parseRegisterOrRegisterNumber(Register2, DirectiveLoc)) return true; getStreamer().EmitCFIRegister(Register1, Register2); return false; } -/// ParseDirectiveCFIAdjustCfaOffset +/// parseDirectiveCFIWindowSave +/// ::= .cfi_window_save +bool AsmParser::parseDirectiveCFIWindowSave() { + getStreamer().EmitCFIWindowSave(); + return false; +} + +/// parseDirectiveCFIAdjustCfaOffset /// ::= .cfi_adjust_cfa_offset adjustment -bool AsmParser::ParseDirectiveCFIAdjustCfaOffset() { +bool AsmParser::parseDirectiveCFIAdjustCfaOffset() { int64_t Adjustment = 0; if (parseAbsoluteExpression(Adjustment)) return true; @@ -2827,24 +2858,24 @@ bool AsmParser::ParseDirectiveCFIAdjustCfaOffset() { return false; } -/// ParseDirectiveCFIDefCfaRegister +/// parseDirectiveCFIDefCfaRegister /// ::= .cfi_def_cfa_register register -bool AsmParser::ParseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) { int64_t Register = 0; - if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; getStreamer().EmitCFIDefCfaRegister(Register); return false; } -/// ParseDirectiveCFIOffset +/// parseDirectiveCFIOffset /// ::= .cfi_offset register, offset -bool AsmParser::ParseDirectiveCFIOffset(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) { int64_t Register = 0; int64_t Offset = 0; - if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; if (getLexer().isNot(AsmToken::Comma)) @@ -2858,12 +2889,12 @@ bool AsmParser::ParseDirectiveCFIOffset(SMLoc DirectiveLoc) { return false; } -/// ParseDirectiveCFIRelOffset +/// parseDirectiveCFIRelOffset /// ::= .cfi_rel_offset register, offset -bool AsmParser::ParseDirectiveCFIRelOffset(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) { int64_t Register = 0; - if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; if (getLexer().isNot(AsmToken::Comma)) @@ -2900,11 +2931,11 @@ static bool isValidEncoding(int64_t Encoding) { return true; } -/// ParseDirectiveCFIPersonalityOrLsda +/// parseDirectiveCFIPersonalityOrLsda /// IsPersonality true for cfi_personality, false for cfi_lsda /// ::= .cfi_personality encoding, [symbol_name] /// ::= .cfi_lsda encoding, [symbol_name] -bool AsmParser::ParseDirectiveCFIPersonalityOrLsda(bool IsPersonality) { +bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) { int64_t Encoding = 0; if (parseAbsoluteExpression(Encoding)) return true; @@ -2931,46 +2962,46 @@ bool AsmParser::ParseDirectiveCFIPersonalityOrLsda(bool IsPersonality) { return false; } -/// ParseDirectiveCFIRememberState +/// parseDirectiveCFIRememberState /// ::= .cfi_remember_state -bool AsmParser::ParseDirectiveCFIRememberState() { +bool AsmParser::parseDirectiveCFIRememberState() { getStreamer().EmitCFIRememberState(); return false; } -/// ParseDirectiveCFIRestoreState +/// parseDirectiveCFIRestoreState /// ::= .cfi_remember_state -bool AsmParser::ParseDirectiveCFIRestoreState() { +bool AsmParser::parseDirectiveCFIRestoreState() { getStreamer().EmitCFIRestoreState(); return false; } -/// ParseDirectiveCFISameValue +/// parseDirectiveCFISameValue /// ::= .cfi_same_value register -bool AsmParser::ParseDirectiveCFISameValue(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) { int64_t Register = 0; - if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; getStreamer().EmitCFISameValue(Register); return false; } -/// ParseDirectiveCFIRestore +/// parseDirectiveCFIRestore /// ::= .cfi_restore register -bool AsmParser::ParseDirectiveCFIRestore(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) { int64_t Register = 0; - if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; getStreamer().EmitCFIRestore(Register); return false; } -/// ParseDirectiveCFIEscape +/// parseDirectiveCFIEscape /// ::= .cfi_escape expression[,...] -bool AsmParser::ParseDirectiveCFIEscape() { +bool AsmParser::parseDirectiveCFIEscape() { std::string Values; int64_t CurrValue; if (parseAbsoluteExpression(CurrValue)) @@ -2991,9 +3022,9 @@ bool AsmParser::ParseDirectiveCFIEscape() { return false; } -/// ParseDirectiveCFISignalFrame +/// parseDirectiveCFISignalFrame /// ::= .cfi_signal_frame -bool AsmParser::ParseDirectiveCFISignalFrame() { +bool AsmParser::parseDirectiveCFISignalFrame() { if (getLexer().isNot(AsmToken::EndOfStatement)) return Error(getLexer().getLoc(), "unexpected token in '.cfi_signal_frame'"); @@ -3002,40 +3033,40 @@ bool AsmParser::ParseDirectiveCFISignalFrame() { return false; } -/// ParseDirectiveCFIUndefined +/// parseDirectiveCFIUndefined /// ::= .cfi_undefined register -bool AsmParser::ParseDirectiveCFIUndefined(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) { int64_t Register = 0; - if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; getStreamer().EmitCFIUndefined(Register); return false; } -/// ParseDirectiveMacrosOnOff +/// parseDirectiveMacrosOnOff /// ::= .macros_on /// ::= .macros_off -bool AsmParser::ParseDirectiveMacrosOnOff(StringRef Directive) { +bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) { if (getLexer().isNot(AsmToken::EndOfStatement)) return Error(getLexer().getLoc(), "unexpected token in '" + Directive + "' directive"); - SetMacrosEnabled(Directive == ".macros_on"); + setMacrosEnabled(Directive == ".macros_on"); return false; } -/// ParseDirectiveMacro +/// parseDirectiveMacro /// ::= .macro name [parameters] -bool AsmParser::ParseDirectiveMacro(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) { StringRef Name; if (parseIdentifier(Name)) return TokError("expected identifier in '.macro' directive"); MCAsmMacroParameters Parameters; // Argument delimiter is initially unknown. It will be set by - // ParseMacroArgument() + // parseMacroArgument() AsmToken::TokenKind ArgumentDelimiter = AsmToken::Eof; if (getLexer().isNot(AsmToken::EndOfStatement)) { for (;;) { @@ -3045,7 +3076,7 @@ bool AsmParser::ParseDirectiveMacro(SMLoc DirectiveLoc) { if (getLexer().is(AsmToken::Equal)) { Lex(); - if (ParseMacroArgument(Parameter.second, ArgumentDelimiter)) + if (parseMacroArgument(Parameter.second, ArgumentDelimiter)) return true; } @@ -3085,19 +3116,19 @@ bool AsmParser::ParseDirectiveMacro(SMLoc DirectiveLoc) { eatToEndOfStatement(); } - if (LookupMacro(Name)) { + if (lookupMacro(Name)) { return Error(DirectiveLoc, "macro '" + Name + "' is already defined"); } const char *BodyStart = StartToken.getLoc().getPointer(); const char *BodyEnd = EndToken.getLoc().getPointer(); StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart); - CheckForBadMacro(DirectiveLoc, Name, Body, Parameters); - DefineMacro(Name, MCAsmMacro(Name, Body, Parameters)); + checkForBadMacro(DirectiveLoc, Name, Body, Parameters); + defineMacro(Name, MCAsmMacro(Name, Body, Parameters)); return false; } -/// CheckForBadMacro +/// checkForBadMacro /// /// 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 @@ -3111,7 +3142,7 @@ bool AsmParser::ParseDirectiveMacro(SMLoc DirectiveLoc) { /// 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, +void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body, MCAsmMacroParameters Parameters) { // If this macro is not defined with named parameters the warning we are @@ -3149,21 +3180,21 @@ void AsmParser::CheckForBadMacro(SMLoc DirectiveLoc, StringRef Name, break; if (Body[Pos] == '$') { - switch (Body[Pos+1]) { - // $$ => $ + switch (Body[Pos + 1]) { + // $$ => $ case '$': break; - // $n => number of arguments + // $n => number of arguments case 'n': PositionalParametersFound = true; break; - // $[0-9] => argument + // $[0-9] => argument default: { PositionalParametersFound = true; break; - } + } } Pos += 2; } else { @@ -3171,19 +3202,19 @@ void AsmParser::CheckForBadMacro(SMLoc DirectiveLoc, StringRef Name, while (isIdentifierChar(Body[I]) && I + 1 != End) ++I; - const char *Begin = Body.data() + Pos +1; - StringRef Argument(Begin, I - (Pos +1)); + const char *Begin = Body.data() + Pos + 1; + StringRef Argument(Begin, I - (Pos + 1)); unsigned Index = 0; for (; Index < NParameters; ++Index) if (Parameters[Index].first == Argument) break; if (Index == NParameters) { - if (Body[Pos+1] == '(' && Body[Pos+2] == ')') - Pos += 3; - else { - Pos = I; - } + if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')') + Pos += 3; + else { + Pos = I; + } } else { NamedParametersFound = true; Pos += 1 + Argument.size(); @@ -3199,29 +3230,29 @@ void AsmParser::CheckForBadMacro(SMLoc DirectiveLoc, StringRef Name, "found in body which will have no effect"); } -/// ParseDirectiveEndMacro +/// parseDirectiveEndMacro /// ::= .endm /// ::= .endmacro -bool AsmParser::ParseDirectiveEndMacro(StringRef Directive) { +bool AsmParser::parseDirectiveEndMacro(StringRef Directive) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '" + Directive + "' directive"); // If we are inside a macro instantiation, terminate the current // instantiation. - if (InsideMacroInstantiation()) { - HandleMacroExit(); + if (isInsideMacroInstantiation()) { + handleMacroExit(); return false; } // Otherwise, this .endmacro is a stray entry in the file; well formed // .endmacro directives are handled during the macro definition parsing. return TokError("unexpected '" + Directive + "' in file, " - "no current macro definition"); + "no current macro definition"); } -/// ParseDirectivePurgeMacro +/// parseDirectivePurgeMacro /// ::= .purgem -bool AsmParser::ParseDirectivePurgeMacro(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) { StringRef Name; if (parseIdentifier(Name)) return TokError("expected identifier in '.purgem' directive"); @@ -3229,16 +3260,16 @@ bool AsmParser::ParseDirectivePurgeMacro(SMLoc DirectiveLoc) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.purgem' directive"); - if (!LookupMacro(Name)) + if (!lookupMacro(Name)) return Error(DirectiveLoc, "macro '" + Name + "' is not defined"); - UndefineMacro(Name); + undefineMacro(Name); return false; } -/// ParseDirectiveBundleAlignMode +/// parseDirectiveBundleAlignMode /// ::= {.bundle_align_mode} expression -bool AsmParser::ParseDirectiveBundleAlignMode() { +bool AsmParser::parseDirectiveBundleAlignMode() { checkForValidSection(); // Expect a single argument: an expression that evaluates to a constant @@ -3262,9 +3293,9 @@ bool AsmParser::ParseDirectiveBundleAlignMode() { return false; } -/// ParseDirectiveBundleLock +/// parseDirectiveBundleLock /// ::= {.bundle_lock} [align_to_end] -bool AsmParser::ParseDirectiveBundleLock() { +bool AsmParser::parseDirectiveBundleLock() { checkForValidSection(); bool AlignToEnd = false; @@ -3272,7 +3303,7 @@ bool AsmParser::ParseDirectiveBundleLock() { StringRef Option; SMLoc Loc = getTok().getLoc(); const char *kInvalidOptionError = - "invalid option for '.bundle_lock' directive"; + "invalid option for '.bundle_lock' directive"; if (parseIdentifier(Option)) return Error(Loc, kInvalidOptionError); @@ -3291,9 +3322,9 @@ bool AsmParser::ParseDirectiveBundleLock() { return false; } -/// ParseDirectiveBundleLock +/// parseDirectiveBundleLock /// ::= {.bundle_lock} -bool AsmParser::ParseDirectiveBundleUnlock() { +bool AsmParser::parseDirectiveBundleUnlock() { checkForValidSection(); if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -3304,9 +3335,9 @@ bool AsmParser::ParseDirectiveBundleUnlock() { return false; } -/// ParseDirectiveSpace +/// parseDirectiveSpace /// ::= (.skip | .space) expression [ , expression ] -bool AsmParser::ParseDirectiveSpace(StringRef IDVal) { +bool AsmParser::parseDirectiveSpace(StringRef IDVal) { checkForValidSection(); int64_t NumBytes; @@ -3329,8 +3360,8 @@ bool AsmParser::ParseDirectiveSpace(StringRef IDVal) { Lex(); if (NumBytes <= 0) - return TokError("invalid number of bytes in '" + - Twine(IDVal) + "' directive"); + return TokError("invalid number of bytes in '" + Twine(IDVal) + + "' directive"); // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0. getStreamer().EmitFill(NumBytes, FillExpr); @@ -3338,9 +3369,9 @@ bool AsmParser::ParseDirectiveSpace(StringRef IDVal) { return false; } -/// ParseDirectiveLEB128 +/// parseDirectiveLEB128 /// ::= (.sleb128 | .uleb128) expression -bool AsmParser::ParseDirectiveLEB128(bool Signed) { +bool AsmParser::parseDirectiveLEB128(bool Signed) { checkForValidSection(); const MCExpr *Value; @@ -3358,9 +3389,9 @@ bool AsmParser::ParseDirectiveLEB128(bool Signed) { return false; } -/// ParseDirectiveSymbolAttribute +/// parseDirectiveSymbolAttribute /// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ] -bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) { +bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) { if (getLexer().isNot(AsmToken::EndOfStatement)) { for (;;) { StringRef Name; @@ -3375,7 +3406,8 @@ bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) { if (Sym->isTemporary()) return Error(Loc, "non-local symbol required in directive"); - getStreamer().EmitSymbolAttribute(Sym, Attr); + if (!getStreamer().EmitSymbolAttribute(Sym, Attr)) + return Error(Loc, "unable to emit symbol attribute"); if (getLexer().is(AsmToken::EndOfStatement)) break; @@ -3390,9 +3422,9 @@ bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) { return false; } -/// ParseDirectiveComm +/// parseDirectiveComm /// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ] -bool AsmParser::ParseDirectiveComm(bool IsLocal) { +bool AsmParser::parseDirectiveComm(bool IsLocal) { checkForValidSection(); SMLoc IDLoc = getLexer().getLoc(); @@ -3442,14 +3474,14 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) { // but a size of .lcomm creates a bss symbol of size zero. if (Size < 0) return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't " - "be less than zero"); + "be less than zero"); // NOTE: The alignment in the directive is a power of 2 value, the assembler // may internally end up wanting an alignment in bytes. // FIXME: Diagnose overflow. if (Pow2Alignment < 0) return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive " - "alignment, can't be less than zero"); + "alignment, can't be less than zero"); if (!Sym->isUndefined()) return Error(IDLoc, "invalid symbol redefinition"); @@ -3464,9 +3496,9 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) { return false; } -/// ParseDirectiveAbort +/// parseDirectiveAbort /// ::= .abort [... message ...] -bool AsmParser::ParseDirectiveAbort() { +bool AsmParser::parseDirectiveAbort() { // FIXME: Use loc from directive. SMLoc Loc = getLexer().getLoc(); @@ -3485,25 +3517,25 @@ bool AsmParser::ParseDirectiveAbort() { return false; } -/// ParseDirectiveInclude +/// parseDirectiveInclude /// ::= .include "filename" -bool AsmParser::ParseDirectiveInclude() { +bool AsmParser::parseDirectiveInclude() { if (getLexer().isNot(AsmToken::String)) return TokError("expected string in '.include' directive"); - std::string Filename = getTok().getString(); + // Allow the strings to have escaped octal character sequence. + std::string Filename; + if (parseEscapedString(Filename)) + return true; SMLoc IncludeLoc = getLexer().getLoc(); Lex(); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.include' directive"); - // Strip the quotes. - Filename = Filename.substr(1, Filename.size()-2); - // Attempt to switch the lexer to the included file before consuming the end // of statement to avoid losing it when we switch. - if (EnterIncludeFile(Filename)) { + if (enterIncludeFile(Filename)) { Error(IncludeLoc, "Could not find include file '" + Filename + "'"); return true; } @@ -3511,24 +3543,24 @@ bool AsmParser::ParseDirectiveInclude() { return false; } -/// ParseDirectiveIncbin +/// parseDirectiveIncbin /// ::= .incbin "filename" -bool AsmParser::ParseDirectiveIncbin() { +bool AsmParser::parseDirectiveIncbin() { if (getLexer().isNot(AsmToken::String)) return TokError("expected string in '.incbin' directive"); - std::string Filename = getTok().getString(); + // Allow the strings to have escaped octal character sequence. + std::string Filename; + if (parseEscapedString(Filename)) + return true; SMLoc IncbinLoc = getLexer().getLoc(); Lex(); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.incbin' directive"); - // Strip the quotes. - Filename = Filename.substr(1, Filename.size()-2); - // Attempt to process the included file. - if (ProcessIncbinFile(Filename)) { + if (processIncbinFile(Filename)) { Error(IncbinLoc, "Could not find incbin file '" + Filename + "'"); return true; } @@ -3536,9 +3568,9 @@ bool AsmParser::ParseDirectiveIncbin() { return false; } -/// ParseDirectiveIf +/// parseDirectiveIf /// ::= .if expression -bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc) { TheCondStack.push_back(TheCondState); TheCondState.TheCond = AsmCond::IfCond; if (TheCondState.Ignore) { @@ -3560,9 +3592,9 @@ bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) { return false; } -/// ParseDirectiveIfb +/// parseDirectiveIfb /// ::= .ifb string -bool AsmParser::ParseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) { +bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) { TheCondStack.push_back(TheCondState); TheCondState.TheCond = AsmCond::IfCond; @@ -3583,16 +3615,16 @@ bool AsmParser::ParseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) { return false; } -/// ParseDirectiveIfc +/// parseDirectiveIfc /// ::= .ifc string1, string2 -bool AsmParser::ParseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) { +bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) { TheCondStack.push_back(TheCondState); TheCondState.TheCond = AsmCond::IfCond; if (TheCondState.Ignore) { eatToEndOfStatement(); } else { - StringRef Str1 = ParseStringToComma(); + StringRef Str1 = parseStringToComma(); if (getLexer().isNot(AsmToken::Comma)) return TokError("unexpected token in '.ifc' directive"); @@ -3613,9 +3645,9 @@ bool AsmParser::ParseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) { return false; } -/// ParseDirectiveIfdef +/// parseDirectiveIfdef /// ::= .ifdef symbol -bool AsmParser::ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { +bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { StringRef Name; TheCondStack.push_back(TheCondState); TheCondState.TheCond = AsmCond::IfCond; @@ -3640,9 +3672,9 @@ bool AsmParser::ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { return false; } -/// ParseDirectiveElseIf +/// parseDirectiveElseIf /// ::= .elseif expression -bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) { if (TheCondState.TheCond != AsmCond::IfCond && TheCondState.TheCond != AsmCond::ElseIfCond) Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or " @@ -3671,9 +3703,9 @@ bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) { return false; } -/// ParseDirectiveElse +/// parseDirectiveElse /// ::= .else -bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.else' directive"); @@ -3695,16 +3727,15 @@ bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) { return false; } -/// ParseDirectiveEndIf +/// parseDirectiveEndIf /// ::= .endif -bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.endif' directive"); Lex(); - if ((TheCondState.TheCond == AsmCond::NoCond) || - TheCondStack.empty()) + if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty()) Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or " ".else"); if (!TheCondStack.empty()) { @@ -3748,7 +3779,6 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".extern"] = DK_EXTERN; DirectiveKindMap[".globl"] = DK_GLOBL; DirectiveKindMap[".global"] = DK_GLOBAL; - DirectiveKindMap[".indirect_symbol"] = DK_INDIRECT_SYMBOL; DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE; DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP; DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER; @@ -3810,6 +3840,7 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME; DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED; DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER; + DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE; DirectiveKindMap[".macros_on"] = DK_MACROS_ON; DirectiveKindMap[".macros_off"] = DK_MACROS_OFF; DirectiveKindMap[".macro"] = DK_MACRO; @@ -3818,8 +3849,7 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".purgem"] = DK_PURGEM; } - -MCAsmMacro *AsmParser::ParseMacroLikeBody(SMLoc DirectiveLoc) { +MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { AsmToken EndToken, StartToken = getTok(); unsigned NestLevel = 0; @@ -3836,8 +3866,7 @@ MCAsmMacro *AsmParser::ParseMacroLikeBody(SMLoc DirectiveLoc) { } // Otherwise, check whether we have reached the .endr. - if (Lexer.is(AsmToken::Identifier) && - getTok().getIdentifier() == ".endr") { + if (Lexer.is(AsmToken::Identifier) && getTok().getIdentifier() == ".endr") { if (NestLevel == 0) { EndToken = getTok(); Lex(); @@ -3865,19 +3894,17 @@ MCAsmMacro *AsmParser::ParseMacroLikeBody(SMLoc DirectiveLoc) { return &MacroLikeBodies.back(); } -void AsmParser::InstantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, +void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, raw_svector_ostream &OS) { OS << ".endr\n"; MemoryBuffer *Instantiation = - MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>"); + MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>"); // Create the macro instantiation object and add to the current macro // instantiation stack. - MacroInstantiation *MI = new MacroInstantiation(M, DirectiveLoc, - CurBuffer, - getTok().getLoc(), - Instantiation); + MacroInstantiation *MI = new MacroInstantiation( + M, DirectiveLoc, CurBuffer, getTok().getLoc(), Instantiation); ActiveMacros.push_back(MI); // Jump to the macro instantiation and prime the lexer. @@ -3886,7 +3913,7 @@ void AsmParser::InstantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, Lex(); } -bool AsmParser::ParseDirectiveRept(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc) { int64_t Count; if (parseAbsoluteExpression(Count)) return TokError("unexpected token in '.rept' directive"); @@ -3901,7 +3928,7 @@ bool AsmParser::ParseDirectiveRept(SMLoc DirectiveLoc) { Lex(); // Lex the rept definition. - MCAsmMacro *M = ParseMacroLikeBody(DirectiveLoc); + MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); if (!M) return true; @@ -3915,14 +3942,14 @@ bool AsmParser::ParseDirectiveRept(SMLoc DirectiveLoc) { if (expandMacro(OS, M->Body, Parameters, A, getTok().getLoc())) return true; } - InstantiateMacroLikeBody(M, DirectiveLoc, OS); + instantiateMacroLikeBody(M, DirectiveLoc, OS); return false; } -/// ParseDirectiveIrp +/// parseDirectiveIrp /// ::= .irp symbol,values -bool AsmParser::ParseDirectiveIrp(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) { MCAsmMacroParameters Parameters; MCAsmMacroParameter Parameter; @@ -3937,14 +3964,14 @@ bool AsmParser::ParseDirectiveIrp(SMLoc DirectiveLoc) { Lex(); MCAsmMacroArguments A; - if (ParseMacroArguments(0, A)) + if (parseMacroArguments(0, A)) return true; // Eat the end of statement. Lex(); // Lex the irp definition. - MCAsmMacro *M = ParseMacroLikeBody(DirectiveLoc); + MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); if (!M) return true; @@ -3961,14 +3988,14 @@ bool AsmParser::ParseDirectiveIrp(SMLoc DirectiveLoc) { return true; } - InstantiateMacroLikeBody(M, DirectiveLoc, OS); + instantiateMacroLikeBody(M, DirectiveLoc, OS); return false; } -/// ParseDirectiveIrpc +/// parseDirectiveIrpc /// ::= .irpc symbol,values -bool AsmParser::ParseDirectiveIrpc(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) { MCAsmMacroParameters Parameters; MCAsmMacroParameter Parameter; @@ -3983,7 +4010,7 @@ bool AsmParser::ParseDirectiveIrpc(SMLoc DirectiveLoc) { Lex(); MCAsmMacroArguments A; - if (ParseMacroArguments(0, A)) + if (parseMacroArguments(0, A)) return true; if (A.size() != 1 || A.front().size() != 1) @@ -3993,7 +4020,7 @@ bool AsmParser::ParseDirectiveIrpc(SMLoc DirectiveLoc) { Lex(); // Lex the irpc definition. - MCAsmMacro *M = ParseMacroLikeBody(DirectiveLoc); + MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); if (!M) return true; @@ -4006,7 +4033,7 @@ bool AsmParser::ParseDirectiveIrpc(SMLoc DirectiveLoc) { std::size_t I, End = Values.size(); for (I = 0; I < End; ++I) { MCAsmMacroArgument Arg; - Arg.push_back(AsmToken(AsmToken::Identifier, Values.slice(I, I+1))); + Arg.push_back(AsmToken(AsmToken::Identifier, Values.slice(I, I + 1))); MCAsmMacroArguments Args; Args.push_back(Arg); @@ -4015,24 +4042,24 @@ bool AsmParser::ParseDirectiveIrpc(SMLoc DirectiveLoc) { return true; } - InstantiateMacroLikeBody(M, DirectiveLoc, OS); + instantiateMacroLikeBody(M, DirectiveLoc, OS); return false; } -bool AsmParser::ParseDirectiveEndr(SMLoc DirectiveLoc) { +bool AsmParser::parseDirectiveEndr(SMLoc DirectiveLoc) { if (ActiveMacros.empty()) return TokError("unmatched '.endr' directive"); // The only .repl that should get here are the ones created by - // InstantiateMacroLikeBody. + // instantiateMacroLikeBody. assert(getLexer().is(AsmToken::EndOfStatement)); - HandleMacroExit(); + handleMacroExit(); return false; } -bool AsmParser::ParseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info, +bool AsmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info, size_t Len) { const MCExpr *Value; SMLoc ExprLoc = getLexer().getLoc(); @@ -4049,7 +4076,7 @@ bool AsmParser::ParseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info, return false; } -bool AsmParser::ParseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) { +bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) { const MCExpr *Value; SMLoc ExprLoc = getLexer().getLoc(); if (parseExpression(Value)) @@ -4061,16 +4088,15 @@ bool AsmParser::ParseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) { if (!isPowerOf2_64(IntValue)) return Error(ExprLoc, "literal value not a power of two greater then zero"); - Info.AsmRewrites->push_back(AsmRewrite(AOK_Align, IDLoc, 5, - Log2_64(IntValue))); + Info.AsmRewrites->push_back( + AsmRewrite(AOK_Align, IDLoc, 5, Log2_64(IntValue))); return false; } // We are comparing pointers, but the pointers are relative to a single string. // Thus, this should always be deterministic. -static int RewritesSort(const void *A, const void *B) { - const AsmRewrite *AsmRewriteA = static_cast<const AsmRewrite *>(A); - const AsmRewrite *AsmRewriteB = static_cast<const AsmRewrite *>(B); +static int rewritesSort(const AsmRewrite *AsmRewriteA, + const AsmRewrite *AsmRewriteB) { if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer()) return -1; if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer()) @@ -4080,25 +4106,22 @@ static int RewritesSort(const void *A, const void *B) { // rewrite to the same location. Make sure the SizeDirective rewrite is // performed first, then the Imm/ImmPrefix and finally the Input/Output. This // ensures the sort algorithm is stable. - if (AsmRewritePrecedence [AsmRewriteA->Kind] > - AsmRewritePrecedence [AsmRewriteB->Kind]) + if (AsmRewritePrecedence[AsmRewriteA->Kind] > + AsmRewritePrecedence[AsmRewriteB->Kind]) return -1; - if (AsmRewritePrecedence [AsmRewriteA->Kind] < - AsmRewritePrecedence [AsmRewriteB->Kind]) + if (AsmRewritePrecedence[AsmRewriteA->Kind] < + AsmRewritePrecedence[AsmRewriteB->Kind]) return 1; - llvm_unreachable ("Unstable rewrite sort."); + llvm_unreachable("Unstable rewrite sort."); } -bool -AsmParser::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) { +bool AsmParser::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) { SmallVector<void *, 4> InputDecls; SmallVector<void *, 4> OutputDecls; SmallVector<bool, 4> InputDeclsAddressOf; @@ -4117,7 +4140,7 @@ AsmParser::parseMSInlineAsm(void *AsmLoc, std::string &AsmString, unsigned OutputIdx = 0; while (getLexer().isNot(AsmToken::Eof)) { ParseStatementInfo Info(&AsmStrRewrites); - if (ParseStatement(Info)) + if (parseStatement(Info)) return true; if (Info.ParseError) @@ -4205,7 +4228,7 @@ AsmParser::parseMSInlineAsm(void *AsmLoc, std::string &AsmString, raw_string_ostream OS(AsmStringIR); const char *AsmStart = SrcMgr.getMemoryBuffer(0)->getBufferStart(); const char *AsmEnd = SrcMgr.getMemoryBuffer(0)->getBufferEnd(); - array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), RewritesSort); + array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort); for (SmallVectorImpl<AsmRewrite>::iterator I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) { @@ -4230,7 +4253,8 @@ AsmParser::parseMSInlineAsm(void *AsmLoc, std::string &AsmString, unsigned AdditionalSkip = 0; // Rewrite expressions in $N notation. switch (Kind) { - default: break; + default: + break; case AOK_Imm: OS << "$$" << (*I).Val; break; @@ -4285,8 +4309,7 @@ AsmParser::parseMSInlineAsm(void *AsmLoc, std::string &AsmString, } /// \brief Create an MCAsmParser instance. -MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, - MCContext &C, MCStreamer &Out, - const MCAsmInfo &MAI) { +MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C, + MCStreamer &Out, const MCAsmInfo &MAI) { return new AsmParser(SM, C, Out, MAI); } diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp index df1794c..d8343a3 100644 --- a/lib/MC/MCParser/COFFAsmParser.cpp +++ b/lib/MC/MCParser/COFFAsmParser.cpp @@ -35,6 +35,10 @@ class COFFAsmParser : public MCAsmParserExtension { unsigned Characteristics, SectionKind Kind); + bool ParseSectionSwitch(StringRef Section, unsigned Characteristics, + SectionKind Kind, StringRef COMDATSymName, + COFF::COMDATType Type, const MCSectionCOFF *Assoc); + bool ParseSectionName(StringRef &SectionName); bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags); @@ -111,6 +115,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 ParseDirectiveLinkOnce(StringRef, SMLoc); // Win64 EH directives. @@ -284,12 +290,22 @@ 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); +} + +bool COFFAsmParser::ParseSectionSwitch(StringRef Section, + unsigned Characteristics, + SectionKind Kind, + StringRef COMDATSymName, + COFF::COMDATType Type, + const MCSectionCOFF *Assoc) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in section switching directive"); Lex(); getStreamer().SwitchSection(getContext().getCOFFSection( - Section, Characteristics, Kind)); + Section, Characteristics, Kind, COMDATSymName, Type, Assoc)); return false; } @@ -303,7 +319,7 @@ bool COFFAsmParser::ParseSectionName(StringRef &SectionName) { return false; } -// .section name [, "flags"] +// .section name [, "flags"] [, identifier [ identifier ], identifier] // // Supported flags: // a: Ignored. @@ -340,11 +356,30 @@ bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { return true; } + COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; + const MCSectionCOFF *Assoc = 0; + StringRef COMDATSymName; + if (getLexer().is(AsmToken::Comma)) { + Lex(); + + Flags |= COFF::IMAGE_SCN_LNK_COMDAT; + + if (parseCOMDATTypeAndAssoc(Type, Assoc)) + return true; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("expected comma in directive"); + Lex(); + + if (getParser().parseIdentifier(COMDATSymName)) + return TokError("expected identifier in directive"); + } + if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); SectionKind Kind = computeSectionKind(Flags); - ParseSectionSwitch(SectionName, Flags, Kind); + ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type, Assoc); return false; } @@ -409,37 +444,29 @@ bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) { return false; } -/// ParseDirectiveLinkOnce -/// ::= .linkonce [ identifier [ identifier ] ] -bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) { - COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; - - if (getLexer().is(AsmToken::Identifier)) { - StringRef TypeId = getTok().getIdentifier(); +/// ::= [ identifier [ identifier ] ] +bool COFFAsmParser::parseCOMDATTypeAndAssoc(COFF::COMDATType &Type, + const MCSectionCOFF *&Assoc) { + StringRef TypeId = getTok().getIdentifier(); - Type = StringSwitch<COFF::COMDATType>(TypeId) - .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) - .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY) - .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE) - .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH) - .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) - .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST) - .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST) - .Default((COFF::COMDATType)0); + Type = StringSwitch<COFF::COMDATType>(TypeId) + .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) + .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY) + .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE) + .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH) + .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) + .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST) + .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST) + .Default((COFF::COMDATType)0); - if (Type == 0) - return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'")); + if (Type == 0) + return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'")); - Lex(); - } - - const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>( - getStreamer().getCurrentSection().first); + Lex(); - const MCSectionCOFF *Assoc = 0; if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { - StringRef AssocName; SMLoc Loc = getTok().getLoc(); + StringRef AssocName; if (ParseSectionName(AssocName)) return TokError("expected associated section name"); @@ -447,14 +474,33 @@ bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) { getContext().getCOFFSection(AssocName)); if (!Assoc) return Error(Loc, "cannot associate unknown section '" + AssocName + "'"); - if (Assoc == Current) - return Error(Loc, "cannot associate a section with itself"); 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 ] ] +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)) + 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 (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) return Error(Loc, Twine("section '") + Current->getSectionName() + "' is already linkonce"); diff --git a/lib/MC/MCParser/DarwinAsmParser.cpp b/lib/MC/MCParser/DarwinAsmParser.cpp index 0aeeaf6..4c9bafa 100644 --- a/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/lib/MC/MCParser/DarwinAsmParser.cpp @@ -45,6 +45,8 @@ public: this->MCAsmParserExtension::Initialize(Parser); addDirectiveHandler<&DarwinAsmParser::ParseDirectiveDesc>(".desc"); + addDirectiveHandler<&DarwinAsmParser::ParseDirectiveIndirectSymbol>( + ".indirect_symbol"); addDirectiveHandler<&DarwinAsmParser::ParseDirectiveLsym>(".lsym"); addDirectiveHandler<&DarwinAsmParser::ParseDirectiveSubsectionsViaSymbols>( ".subsections_via_symbols"); @@ -69,6 +71,7 @@ public: ".end_data_region"); // Special section directives. + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveBss>(".bss"); addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConst>(".const"); addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConstData>( ".const_data"); @@ -163,6 +166,7 @@ public: } bool ParseDirectiveDesc(StringRef, SMLoc); + bool ParseDirectiveIndirectSymbol(StringRef, SMLoc); bool ParseDirectiveDumpOrLoad(StringRef, SMLoc); bool ParseDirectiveLsym(StringRef, SMLoc); bool ParseDirectiveLinkerOption(StringRef, SMLoc); @@ -179,6 +183,10 @@ public: bool ParseDirectiveDataRegionEnd(StringRef, SMLoc); // Named Section Directive + bool ParseSectionDirectiveBss(StringRef, SMLoc) { + return ParseSectionSwitch("__DATA", "__bss"); + } + bool ParseSectionDirectiveConst(StringRef, SMLoc) { return ParseSectionSwitch("__TEXT", "__const"); } @@ -415,6 +423,39 @@ bool DarwinAsmParser::ParseDirectiveDesc(StringRef, SMLoc) { return false; } +/// ParseDirectiveIndirectSymbol +/// ::= .indirect_symbol identifier +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) + return Error(Loc, "indirect symbol not in a symbol pointer or stub " + "section"); + + StringRef Name; + if (getParser().parseIdentifier(Name)) + return TokError("expected identifier in .indirect_symbol directive"); + + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + + // Assembler local symbols don't make any sense here. Complain loudly. + if (Sym->isTemporary()) + return TokError("non-local symbol required in directive"); + + if (!getStreamer().EmitSymbolAttribute(Sym, MCSA_IndirectSymbol)) + return TokError("unable to emit indirect symbol attribute for: " + Name); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.indirect_symbol' directive"); + + Lex(); + + return false; +} + /// ParseDirectiveDumpOrLoad /// ::= ( .dump | .load ) "filename" bool DarwinAsmParser::ParseDirectiveDumpOrLoad(StringRef Directive, diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp index 3134fc3..8807975 100644 --- a/lib/MC/MCParser/ELFAsmParser.cpp +++ b/lib/MC/MCParser/ELFAsmParser.cpp @@ -16,6 +16,7 @@ #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Support/ELF.h" using namespace llvm; @@ -30,14 +31,11 @@ class ELFAsmParser : public MCAsmParserExtension { getParser().addDirectiveHandler(Directive, Handler); } - bool ParseSectionSwitch(StringRef Section, unsigned Type, - unsigned Flags, SectionKind Kind); - bool SeenIdent; + bool ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags, + SectionKind Kind); public: - ELFAsmParser() : SeenIdent(false) { - BracketExpressionsSupported = true; - } + ELFAsmParser() { BracketExpressionsSupported = true; } virtual void Initialize(MCAsmParser &Parser) { // Call the base implementation. @@ -241,7 +239,6 @@ bool ELFAsmParser::ParseSectionName(StringRef &SectionName) { } for (;;) { - StringRef Tmp; unsigned CurSize; SMLoc PrevLoc = getLexer().getLoc(); @@ -279,14 +276,17 @@ static SectionKind computeSectionKind(unsigned Flags) { return SectionKind::getDataRel(); } -static int parseSectionFlags(StringRef flagsStr) { - int flags = 0; +static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) { + unsigned flags = 0; for (unsigned i = 0; i < flagsStr.size(); i++) { switch (flagsStr[i]) { case 'a': flags |= ELF::SHF_ALLOC; break; + case 'e': + flags |= ELF::SHF_EXCLUDE; + break; case 'x': flags |= ELF::SHF_EXECINSTR; break; @@ -311,8 +311,11 @@ static int parseSectionFlags(StringRef flagsStr) { case 'G': flags |= ELF::SHF_GROUP; break; + case '?': + *UseLastGroup = true; + break; default: - return -1; + return -1U; } } @@ -352,6 +355,7 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush) { StringRef GroupName; unsigned Flags = 0; const MCExpr *Subsection = 0; + bool UseLastGroup = false; // Set the defaults first. if (SectionName == ".fini" || SectionName == ".init" || @@ -377,13 +381,16 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush) { StringRef FlagsStr = getTok().getStringContents(); Lex(); - int extraFlags = parseSectionFlags(FlagsStr); - if (extraFlags < 0) + unsigned extraFlags = parseSectionFlags(FlagsStr, &UseLastGroup); + if (extraFlags == -1U) return TokError("unknown flag"); Flags |= extraFlags; bool Mergeable = Flags & ELF::SHF_MERGE; bool Group = Flags & ELF::SHF_GROUP; + if (Group && UseLastGroup) + return TokError("Section cannot specifiy a group name while also acting " + "as a member of the last group"); if (getLexer().isNot(AsmToken::Comma)) { if (Mergeable) @@ -392,10 +399,13 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush) { return TokError("Group section must specify the type"); } else { Lex(); - if (getLexer().isNot(AsmToken::Percent) && getLexer().isNot(AsmToken::At)) - return TokError("expected '@' or '%' before type"); + if (getLexer().is(AsmToken::At) || getLexer().is(AsmToken::Percent) || + getLexer().is(AsmToken::String)) { + if (!getLexer().is(AsmToken::String)) + Lex(); + } else + return TokError("expected '@<type>', '%<type>' or \"<type>\""); - Lex(); if (getParser().parseIdentifier(TypeName)) return TokError("expected identifier in directive"); @@ -461,6 +471,16 @@ EndStmt: return TokError("unknown section type"); } + if (UseLastGroup) { + MCSectionSubPair CurrentSection = getStreamer().getCurrentSection(); + if (const MCSectionELF *Section = + cast_or_null<MCSectionELF>(CurrentSection.first)) + if (const MCSymbol *Group = Section->getGroup()) { + GroupName = Group->getName(); + Flags |= ELF::SHF_GROUP; + } + } + SectionKind Kind = computeSectionKind(Flags); getStreamer().SwitchSection(getContext().getELFSection(SectionName, Type, Flags, Kind, Size, @@ -479,7 +499,11 @@ bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { } /// ParseDirectiveELFType +/// ::= .type identifier , STT_<TYPE_IN_UPPER_CASE> +/// ::= .type identifier , #attribute /// ::= .type identifier , @attribute +/// ::= .type identifier , %attribute +/// ::= .type identifier , "attribute" bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) { StringRef Name; if (getParser().parseIdentifier(Name)) @@ -492,26 +516,42 @@ bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) { return TokError("unexpected token in '.type' directive"); Lex(); - if (getLexer().isNot(AsmToken::Percent) && getLexer().isNot(AsmToken::At)) - return TokError("expected '@' or '%' before type"); - 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(); - TypeLoc = getLexer().getLoc(); - if (getParser().parseIdentifier(Type)) - return TokError("expected symbol type in directive"); - - MCSymbolAttr 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); + 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 + return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', " + "'%<type>' or \"<type>\""); if (Attr == MCSA_Invalid) return Error(TypeLoc, "unsupported attribute in '.type' directive"); @@ -536,22 +576,7 @@ bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) { Lex(); - const MCSection *Comment = - getContext().getELFSection(".comment", ELF::SHT_PROGBITS, - ELF::SHF_MERGE | - ELF::SHF_STRINGS, - SectionKind::getReadOnly(), - 1, ""); - - getStreamer().PushSection(); - getStreamer().SwitchSection(Comment); - if (!SeenIdent) { - getStreamer().EmitIntValue(0, 1); - SeenIdent = true; - } - getStreamer().EmitBytes(Data); - getStreamer().EmitIntValue(0, 1); - getStreamer().PopSection(); + getStreamer().EmitIdent(Data); return false; } diff --git a/lib/MC/MCPureStreamer.cpp b/lib/MC/MCPureStreamer.cpp index c5c3bb7..f7bf002 100644 --- a/lib/MC/MCPureStreamer.cpp +++ b/lib/MC/MCPureStreamer.cpp @@ -29,7 +29,7 @@ private: public: MCPureStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(SK_PureStreamer, Context, TAB, OS, Emitter) {} + : MCObjectStreamer(Context, 0, TAB, OS, Emitter) {} /// @name MCStreamer Interface /// @{ @@ -51,8 +51,9 @@ public: virtual void FinishImpl(); - virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { + 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"); @@ -93,16 +94,13 @@ public: 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"); } - - /// @} - - static bool classof(const MCStreamer *S) { - return S->getKind() == SK_PureStreamer; - } }; } // end anonymous namespace. @@ -120,7 +118,7 @@ void MCPureStreamer::EmitLabel(MCSymbol *Symbol) { assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); assert(getCurrentSection().first && "Cannot emit before setting section!"); - Symbol->setSection(*getCurrentSection().first); + AssignSection(Symbol, getCurrentSection().first); MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); diff --git a/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp index bf1a984..09eb3e7 100644 --- a/lib/MC/MCSectionELF.cpp +++ b/lib/MC/MCSectionELF.cpp @@ -32,6 +32,29 @@ bool MCSectionELF::ShouldOmitSectionDirective(StringRef Name, return false; } +static void printName(raw_ostream &OS, StringRef Name) { + if (Name.find_first_not_of("0123456789_." + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == Name.npos) { + OS << Name; + return; + } + OS << '"'; + for (const char *B = Name.begin(), *E = Name.end(); B < E; ++B) { + if (*B == '"') // Unquoted " + OS << "\\\""; + else if (*B != '\\') // Neither " or backslash + OS << *B; + else if (B + 1 == E) // Trailing backslash + OS << "\\\\"; + else { + OS << B[0] << B[1]; // Quoted character + ++B; + } + } + OS << '"'; +} + void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS, const MCExpr *Subsection) const { @@ -44,27 +67,8 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, return; } - StringRef name = getSectionName(); - if (name.find_first_not_of("0123456789_." - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == name.npos) { - OS << "\t.section\t" << name; - } else { - OS << "\t.section\t\""; - for (const char *b = name.begin(), *e = name.end(); b < e; ++b) { - if (*b == '"') // Unquoted " - OS << "\\\""; - else if (*b != '\\') // Neither " or backslash - OS << *b; - else if (b + 1 == e) // Trailing backslash - OS << "\\\\"; - else { - OS << b[0] << b[1]; // Quoted character - ++b; - } - } - OS << '"'; - } + OS << "\t.section\t"; + printName(OS, getSectionName()); // Handle the weird solaris syntax if desired. if (MAI.usesSunStyleELFSectionSwitchSyntax() && @@ -75,6 +79,8 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, OS << ",#execinstr"; if (Flags & ELF::SHF_WRITE) OS << ",#write"; + if (Flags & ELF::SHF_EXCLUDE) + OS << ",#exclude"; if (Flags & ELF::SHF_TLS) OS << ",#tls"; OS << '\n'; @@ -84,6 +90,8 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, OS << ",\""; if (Flags & ELF::SHF_ALLOC) OS << 'a'; + if (Flags & ELF::SHF_EXCLUDE) + OS << 'e'; if (Flags & ELF::SHF_EXECINSTR) OS << 'x'; if (Flags & ELF::SHF_GROUP) @@ -131,8 +139,11 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, OS << "," << EntrySize; } - if (Flags & ELF::SHF_GROUP) - OS << "," << Group->getName() << ",comdat"; + if (Flags & ELF::SHF_GROUP) { + OS << ","; + printName(OS, Group->getName()); + OS << ",comdat"; + } OS << '\n'; if (Subsection) diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 6542f42..2e1d69b 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -10,6 +10,7 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" @@ -21,10 +22,17 @@ #include <cstdlib> using namespace llvm; -MCStreamer::MCStreamer(StreamerKind Kind, MCContext &Ctx) - : Kind(Kind), Context(Ctx), EmitEHFrame(true), EmitDebugFrame(false), - CurrentW64UnwindInfo(0), LastSymbol(0), AutoInitSections(false) { +// 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) { SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>()); + if (TargetStreamer) + TargetStreamer->setStreamer(this); } MCStreamer::~MCStreamer() { @@ -72,6 +80,13 @@ raw_ostream &MCStreamer::GetCommentOS() { return nulls(); } +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); +} + void MCStreamer::EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label, int PointerSize) { // emit the sequence to set the address @@ -183,17 +198,28 @@ void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) { } +void MCStreamer::AssignSection(MCSymbol *Symbol, const MCSection *Section) { + if (Section) + Symbol->setSection(*Section); + else + Symbol->setUndefined(); + + // As we emit symbols into a section, track the order so that they can + // be sorted upon later. Zero is reserved to mean 'unemitted'. + SymbolOrdering[Symbol] = 1 + SymbolOrdering.size(); +} + void MCStreamer::EmitLabel(MCSymbol *Symbol) { assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); assert(getCurrentSection().first && "Cannot emit before setting section!"); - Symbol->setSection(*getCurrentSection().first); + 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!"); - Symbol->setSection(*getCurrentSection().first); + AssignSection(Symbol, getCurrentSection().first); LastSymbol = Symbol; } @@ -380,6 +406,14 @@ void MCStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) { CurFrame->Instructions.push_back(Instruction); } +void MCStreamer::EmitCFIWindowSave() { + MCSymbol *Label = EmitCFICommon(); + MCCFIInstruction Instruction = + MCCFIInstruction::createWindowSave(Label); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + CurFrame->Instructions.push_back(Instruction); +} + void MCStreamer::setCurrentW64UnwindInfo(MCWin64EHUnwindInfo *Frame) { W64UnwindInfos.push_back(Frame); CurrentW64UnwindInfo = W64UnwindInfos.back(); @@ -470,7 +504,9 @@ void MCStreamer::EmitWin64EHSetFrame(unsigned Register, unsigned Offset) { report_fatal_error("Frame register and offset already specified!"); if (Offset & 0x0F) report_fatal_error("Misaligned frame pointer offset!"); - MCWin64EHInstruction Inst(Win64EH::UOP_SetFPReg, 0, Register, Offset); + MCSymbol *Label = getContext().CreateTempSymbol(); + MCWin64EHInstruction Inst(Win64EH::UOP_SetFPReg, Label, Register, Offset); + EmitLabel(Label); CurFrame->LastFrameInst = CurFrame->Instructions.size(); CurFrame->Instructions.push_back(Inst); } @@ -534,54 +570,10 @@ void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) { llvm_unreachable("This file format doesn't support this directive"); } -void MCStreamer::EmitFnStart() { - errs() << "Not implemented yet\n"; - abort(); -} - -void MCStreamer::EmitFnEnd() { - errs() << "Not implemented yet\n"; - abort(); -} - -void MCStreamer::EmitCantUnwind() { - errs() << "Not implemented yet\n"; - abort(); -} - -void MCStreamer::EmitHandlerData() { - errs() << "Not implemented yet\n"; - abort(); -} - -void MCStreamer::EmitPersonality(const MCSymbol *Personality) { - errs() << "Not implemented yet\n"; - abort(); -} - -void MCStreamer::EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset) { - errs() << "Not implemented yet\n"; - abort(); -} - -void MCStreamer::EmitPad(int64_t Offset) { - errs() << "Not implemented yet\n"; - abort(); -} - -void MCStreamer::EmitRegSave(const SmallVectorImpl<unsigned> &RegList, bool) { - errs() << "Not implemented yet\n"; - abort(); -} - -void MCStreamer::EmitTCEntry(const MCSymbol &S) { - llvm_unreachable("Unsupported method"); -} - /// 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. -void MCStreamer::EmitRawText(StringRef String) { +void MCStreamer::EmitRawTextImpl(StringRef String) { errs() << "EmitRawText called on an MCStreamer that doesn't support it, " " something must not be fully mc'ized\n"; abort(); @@ -589,19 +581,18 @@ void MCStreamer::EmitRawText(StringRef String) { void MCStreamer::EmitRawText(const Twine &T) { SmallString<128> Str; - T.toVector(Str); - EmitRawText(Str.str()); + EmitRawTextImpl(T.toStringRef(Str)); } -void MCStreamer::EmitFrames(bool usingCFI) { +void MCStreamer::EmitFrames(MCAsmBackend *MAB, bool usingCFI) { if (!getNumFrameInfos()) return; if (EmitEHFrame) - MCDwarfFrameEmitter::Emit(*this, usingCFI, true); + MCDwarfFrameEmitter::Emit(*this, MAB, usingCFI, true); if (EmitDebugFrame) - MCDwarfFrameEmitter::Emit(*this, usingCFI, false); + MCDwarfFrameEmitter::Emit(*this, MAB, usingCFI, false); } void MCStreamer::EmitW64Tables() { diff --git a/lib/MC/MCSubtargetInfo.cpp b/lib/MC/MCSubtargetInfo.cpp index f18828d..8d8e290 100644 --- a/lib/MC/MCSubtargetInfo.cpp +++ b/lib/MC/MCSubtargetInfo.cpp @@ -27,6 +27,11 @@ MCSubtargetInfo::InitMCProcessorInfo(StringRef CPU, StringRef FS) { FeatureBits = Features.getFeatureBits(CPU, ProcDesc, NumProcs, ProcFeatures, NumFeatures); + InitCPUSchedModel(CPU); +} + +void +MCSubtargetInfo::InitCPUSchedModel(StringRef CPU) { if (!CPU.empty()) CPUSchedModel = getSchedModelForCPU(CPU); else @@ -91,10 +96,8 @@ MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const { #endif // Find entry - SubtargetInfoKV KV; - KV.Key = CPU.data(); const SubtargetInfoKV *Found = - std::lower_bound(ProcSchedModels, ProcSchedModels+NumProcs, KV); + std::lower_bound(ProcSchedModels, ProcSchedModels+NumProcs, CPU); if (Found == ProcSchedModels+NumProcs || StringRef(Found->Key) != CPU) { errs() << "'" << CPU << "' is not a recognized processor for this target" diff --git a/lib/MC/MCSymbol.cpp b/lib/MC/MCSymbol.cpp index b973c57..2416525 100644 --- a/lib/MC/MCSymbol.cpp +++ b/lib/MC/MCSymbol.cpp @@ -68,12 +68,23 @@ void MCSymbol::print(raw_ostream &OS) const { // The name for this MCSymbol is required to be a valid target name. However, // some targets support quoting names with funny characters. If the name // contains a funny character, then print it quoted. - if (!NameNeedsQuoting(getName())) { - OS << getName(); + StringRef Name = getName(); + if (!NameNeedsQuoting(Name)) { + OS << Name; return; } - OS << '"' << getName() << '"'; + OS << '"'; + for (unsigned I = 0, E = Name.size(); I != E; ++I) { + char C = Name[I]; + if (C == '\n') + OS << "\\n"; + else if (C == '"') + OS << "\\\""; + else + OS << C; + } + OS << '"'; } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) diff --git a/lib/MC/MCWin64EH.cpp b/lib/MC/MCWin64EH.cpp index c5b637c..b8b07d3 100644 --- a/lib/MC/MCWin64EH.cpp +++ b/lib/MC/MCWin64EH.cpp @@ -64,7 +64,7 @@ static void EmitAbsDifference(MCStreamer &streamer, MCSymbol *lhs, static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin, MCWin64EHInstruction &inst) { - uint8_t b1, b2; + uint8_t b2; uint16_t w; b2 = (inst.getOperation() & 0x0F); switch (inst.getOperation()) { @@ -93,8 +93,7 @@ static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin, streamer.EmitIntValue(b2, 1); break; case Win64EH::UOP_SetFPReg: - b1 = inst.getOffset() & 0xF0; - streamer.EmitIntValue(b1, 1); + EmitAbsDifference(streamer, inst.getLabel(), begin); streamer.EmitIntValue(b2, 1); break; case Win64EH::UOP_SaveNonVol: @@ -129,14 +128,29 @@ static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin, } } +static void EmitSymbolRefWithOfs(MCStreamer &streamer, + const MCSymbol *Base, + const MCSymbol *Other) { + MCContext &Context = streamer.getContext(); + const MCSymbolRefExpr *BaseRef = MCSymbolRefExpr::Create(Base, Context); + const MCSymbolRefExpr *OtherRef = MCSymbolRefExpr::Create(Other, Context); + const MCExpr *Ofs = MCBinaryExpr::CreateSub(OtherRef, BaseRef, Context); + const MCSymbolRefExpr *BaseRefRel = MCSymbolRefExpr::Create(Base, + MCSymbolRefExpr::VK_COFF_IMGREL32, + Context); + streamer.EmitValue(MCBinaryExpr::CreateAdd(BaseRefRel, Ofs, Context), 4); +} + static void EmitRuntimeFunction(MCStreamer &streamer, const MCWin64EHUnwindInfo *info) { MCContext &context = streamer.getContext(); streamer.EmitValueToAlignment(4); - streamer.EmitValue(MCSymbolRefExpr::Create(info->Begin, context), 4); - streamer.EmitValue(MCSymbolRefExpr::Create(info->End, context), 4); - streamer.EmitValue(MCSymbolRefExpr::Create(info->Symbol, context), 4); + EmitSymbolRefWithOfs(streamer, info->Function, info->Begin); + EmitSymbolRefWithOfs(streamer, info->Function, info->End); + streamer.EmitValue(MCSymbolRefExpr::Create(info->Symbol, + MCSymbolRefExpr::VK_COFF_IMGREL32, + context), 4); } static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) { @@ -145,11 +159,11 @@ static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) { MCContext &context = streamer.getContext(); streamer.EmitValueToAlignment(4); - // Upper 3 bits are the version number (currently 1). - uint8_t flags = 0x01; info->Symbol = context.CreateTempSymbol(); streamer.EmitLabel(info->Symbol); + // Upper 3 bits are the version number (currently 1). + uint8_t flags = 0x01; if (info->ChainedParent) flags |= Win64EH::UNW_ChainInfo << 3; else { @@ -185,20 +199,26 @@ static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) { EmitUnwindCode(streamer, info->Begin, inst); } + // For alignment purposes, the instruction array will always have an even + // number of entries, with the final entry potentially unused (in which case + // the array will be one longer than indicated by the count of unwind codes + // field). + if (numCodes & 1) { + streamer.EmitIntValue(0, 2); + } + if (flags & (Win64EH::UNW_ChainInfo << 3)) EmitRuntimeFunction(streamer, info->ChainedParent); else if (flags & ((Win64EH::UNW_TerminateHandler|Win64EH::UNW_ExceptionHandler) << 3)) - streamer.EmitValue(MCSymbolRefExpr::Create(info->ExceptionHandler, context), - 4); - else if (numCodes < 2) { + streamer.EmitValue(MCSymbolRefExpr::Create(info->ExceptionHandler, + MCSymbolRefExpr::VK_COFF_IMGREL32, + context), 4); + else if (numCodes == 0) { // The minimum size of an UNWIND_INFO struct is 8 bytes. If we're not // a chained unwind info, if there is no handler, and if there are fewer // than 2 slots used in the unwind code array, we have to pad to 8 bytes. - if (numCodes == 1) - streamer.EmitIntValue(0, 2); - else - streamer.EmitIntValue(0, 4); + streamer.EmitIntValue(0, 4); } } diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index a5ba3c3..8234aff 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -20,12 +20,11 @@ #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" -#include "llvm/Object/MachOFormat.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MachO.h" #include <vector> using namespace llvm; -using namespace llvm::object; void MachObjectWriter::reset() { Relocations.clear(); @@ -128,7 +127,7 @@ void MachObjectWriter::WriteHeader(unsigned NumLoadCommands, uint32_t Flags = 0; if (SubsectionsViaSymbols) - Flags |= macho::HF_SubsectionsViaSymbols; + Flags |= MachO::MH_SUBSECTIONS_VIA_SYMBOLS; // struct mach_header (28 bytes) or // struct mach_header_64 (32 bytes) @@ -136,12 +135,12 @@ void MachObjectWriter::WriteHeader(unsigned NumLoadCommands, uint64_t Start = OS.tell(); (void) Start; - Write32(is64Bit() ? macho::HM_Object64 : macho::HM_Object32); + Write32(is64Bit() ? MachO::MH_MAGIC_64 : MachO::MH_MAGIC); Write32(TargetObjectWriter->getCPUType()); Write32(TargetObjectWriter->getCPUSubtype()); - Write32(macho::HFT_Object); + Write32(MachO::MH_OBJECT); Write32(NumLoadCommands); Write32(LoadCommandsSize); Write32(Flags); @@ -149,7 +148,7 @@ void MachObjectWriter::WriteHeader(unsigned NumLoadCommands, Write32(0); // reserved assert(OS.tell() - Start == - (is64Bit() ? macho::Header64Size : macho::Header32Size)); + (is64Bit()?sizeof(MachO::mach_header_64): sizeof(MachO::mach_header))); } /// WriteSegmentLoadCommand - Write a segment load command. @@ -167,12 +166,12 @@ void MachObjectWriter::WriteSegmentLoadCommand(unsigned NumSections, (void) Start; unsigned SegmentLoadCommandSize = - is64Bit() ? macho::SegmentLoadCommand64Size: - macho::SegmentLoadCommand32Size; - Write32(is64Bit() ? macho::LCT_Segment64 : macho::LCT_Segment); + is64Bit() ? sizeof(MachO::segment_command_64): + sizeof(MachO::segment_command); + Write32(is64Bit() ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT); Write32(SegmentLoadCommandSize + - NumSections * (is64Bit() ? macho::Section64Size : - macho::Section32Size)); + NumSections * (is64Bit() ? sizeof(MachO::section_64) : + sizeof(MachO::section))); WriteBytes("", 16); if (is64Bit()) { @@ -186,8 +185,10 @@ void MachObjectWriter::WriteSegmentLoadCommand(unsigned NumSections, Write32(SectionDataStartOffset); // file offset Write32(SectionDataSize); // file size } - Write32(0x7); // maxprot - Write32(0x7); // initprot + // maxprot + Write32(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE); + // initprot + Write32(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE); Write32(NumSections); Write32(0); // flags @@ -240,8 +241,8 @@ void MachObjectWriter::WriteSection(const MCAssembler &Asm, if (is64Bit()) Write32(0); // reserved3 - assert(OS.tell() - Start == (is64Bit() ? macho::Section64Size : - macho::Section32Size)); + assert(OS.tell() - Start == (is64Bit() ? sizeof(MachO::section_64) : + sizeof(MachO::section))); } void MachObjectWriter::WriteSymtabLoadCommand(uint32_t SymbolOffset, @@ -253,14 +254,14 @@ void MachObjectWriter::WriteSymtabLoadCommand(uint32_t SymbolOffset, uint64_t Start = OS.tell(); (void) Start; - Write32(macho::LCT_Symtab); - Write32(macho::SymtabLoadCommandSize); + Write32(MachO::LC_SYMTAB); + Write32(sizeof(MachO::symtab_command)); Write32(SymbolOffset); Write32(NumSymbols); Write32(StringTableOffset); Write32(StringTableSize); - assert(OS.tell() - Start == macho::SymtabLoadCommandSize); + assert(OS.tell() - Start == sizeof(MachO::symtab_command)); } void MachObjectWriter::WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol, @@ -276,8 +277,8 @@ void MachObjectWriter::WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol, uint64_t Start = OS.tell(); (void) Start; - Write32(macho::LCT_Dysymtab); - Write32(macho::DysymtabLoadCommandSize); + Write32(MachO::LC_DYSYMTAB); + Write32(sizeof(MachO::dysymtab_command)); Write32(FirstLocalSymbol); Write32(NumLocalSymbols); Write32(FirstExternalSymbol); @@ -297,7 +298,7 @@ void MachObjectWriter::WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol, Write32(0); // locreloff Write32(0); // nlocrel - assert(OS.tell() - Start == macho::DysymtabLoadCommandSize); + assert(OS.tell() - Start == sizeof(MachO::dysymtab_command)); } void MachObjectWriter::WriteNlist(MachSymbolData &MSD, @@ -312,20 +313,20 @@ void MachObjectWriter::WriteNlist(MachSymbolData &MSD, // // FIXME: Are the prebound or indirect fields possible here? if (Symbol.isUndefined()) - Type = macho::STT_Undefined; + Type = MachO::N_UNDF; else if (Symbol.isAbsolute()) - Type = macho::STT_Absolute; + Type = MachO::N_ABS; else - Type = macho::STT_Section; + Type = MachO::N_SECT; // FIXME: Set STAB bits. if (Data.isPrivateExtern()) - Type |= macho::STF_PrivateExtern; + Type |= MachO::N_PEXT; // Set external bit. if (Data.isExternal() || Symbol.isUndefined()) - Type |= macho::STF_External; + Type |= MachO::N_EXT; // Compute the symbol address. if (Symbol.isDefined()) { @@ -341,7 +342,8 @@ void MachObjectWriter::WriteNlist(MachSymbolData &MSD, assert((1U << Log2Size) == Align && "Invalid 'common' alignment!"); if (Log2Size > 15) report_fatal_error("invalid 'common' alignment '" + - Twine(Align) + "'"); + Twine(Align) + "' for '" + Symbol.getName() + "'", + false); // FIXME: Keep this mask with the SymbolFlags enumeration. Flags = (Flags & 0xF0FF) | (Log2Size << 8); } @@ -369,17 +371,17 @@ void MachObjectWriter::WriteLinkeditLoadCommand(uint32_t Type, (void) Start; Write32(Type); - Write32(macho::LinkeditLoadCommandSize); + Write32(sizeof(MachO::linkedit_data_command)); Write32(DataOffset); Write32(DataSize); - assert(OS.tell() - Start == macho::LinkeditLoadCommandSize); + assert(OS.tell() - Start == sizeof(MachO::linkedit_data_command)); } static unsigned ComputeLinkerOptionsLoadCommandSize( const std::vector<std::string> &Options, bool is64Bit) { - unsigned Size = sizeof(macho::LinkerOptionsLoadCommand); + unsigned Size = sizeof(MachO::linker_options_command); for (unsigned i = 0, e = Options.size(); i != e; ++i) Size += Options[i].size() + 1; return RoundUpToAlignment(Size, is64Bit ? 8 : 4); @@ -392,10 +394,10 @@ void MachObjectWriter::WriteLinkerOptionsLoadCommand( uint64_t Start = OS.tell(); (void) Start; - Write32(macho::LCT_LinkerOptions); + Write32(MachO::LC_LINKER_OPTIONS); Write32(Size); Write32(Options.size()); - uint64_t BytesWritten = sizeof(macho::LinkerOptionsLoadCommand); + uint64_t BytesWritten = sizeof(MachO::linker_options_command); for (unsigned i = 0, e = Options.size(); i != e; ++i) { // Write each string, including the null byte. const std::string &Option = Options[i]; @@ -428,6 +430,22 @@ void MachObjectWriter::BindIndirectSymbols(MCAssembler &Asm) { // // FIXME: Revisit this when the dust settles. + // Report errors for use of .indirect_symbol not in a symbol pointer section + // or stub section. + for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(), + ie = Asm.indirect_symbol_end(); it != ie; ++it) { + 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) { + 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. unsigned IndirectIndex = 0; for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(), @@ -723,14 +741,14 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, // section headers) and the symbol table. unsigned NumLoadCommands = 1; uint64_t LoadCommandsSize = is64Bit() ? - macho::SegmentLoadCommand64Size + NumSections * macho::Section64Size : - macho::SegmentLoadCommand32Size + NumSections * macho::Section32Size; + sizeof(MachO::segment_command_64) + NumSections * sizeof(MachO::section_64): + sizeof(MachO::segment_command) + NumSections * sizeof(MachO::section); // Add the data-in-code load command size, if used. unsigned NumDataRegions = Asm.getDataRegions().size(); if (NumDataRegions) { ++NumLoadCommands; - LoadCommandsSize += macho::LinkeditLoadCommandSize; + LoadCommandsSize += sizeof(MachO::linkedit_data_command); } // Add the symbol table load command sizes, if used. @@ -738,8 +756,8 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, UndefinedSymbolData.size(); if (NumSymbols) { NumLoadCommands += 2; - LoadCommandsSize += (macho::SymtabLoadCommandSize + - macho::DysymtabLoadCommandSize); + LoadCommandsSize += (sizeof(MachO::symtab_command) + + sizeof(MachO::dysymtab_command)); } // Add the linker option load commands sizes. @@ -753,8 +771,8 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, // Compute the total size of the section data, as well as its file size and vm // size. - uint64_t SectionDataStart = (is64Bit() ? macho::Header64Size : - macho::Header32Size) + LoadCommandsSize; + uint64_t SectionDataStart = (is64Bit() ? sizeof(MachO::mach_header_64) : + sizeof(MachO::mach_header)) + LoadCommandsSize; uint64_t SectionDataSize = 0; uint64_t SectionDataFileSize = 0; uint64_t VMSize = 0; @@ -791,11 +809,11 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize; for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { - std::vector<macho::RelocationEntry> &Relocs = Relocations[it]; + std::vector<MachO::any_relocation_info> &Relocs = Relocations[it]; unsigned NumRelocs = Relocs.size(); uint64_t SectionStart = SectionDataStart + getSectionAddress(it); WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs); - RelocTableEnd += NumRelocs * macho::RelocationInfoSize; + RelocTableEnd += NumRelocs * sizeof(MachO::any_relocation_info); } // Write the data-in-code load command, if used. @@ -803,7 +821,7 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, if (NumDataRegions) { uint64_t DataRegionsOffset = RelocTableEnd; uint64_t DataRegionsSize = NumDataRegions * 8; - WriteLinkeditLoadCommand(macho::LCT_DataInCode, DataRegionsOffset, + WriteLinkeditLoadCommand(MachO::LC_DATA_IN_CODE, DataRegionsOffset, DataRegionsSize); } @@ -830,8 +848,9 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, // The string table is written after symbol table. uint64_t StringTableOffset = - SymbolTableOffset + NumSymTabSymbols * (is64Bit() ? macho::Nlist64Size : - macho::Nlist32Size); + SymbolTableOffset + NumSymTabSymbols * (is64Bit() ? + sizeof(MachO::nlist_64) : + sizeof(MachO::nlist)); WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols, StringTableOffset, StringTable.size()); @@ -864,10 +883,10 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, ie = Asm.end(); it != ie; ++it) { // Write the section relocation entries, in reverse order to match 'as' // (approximately, the exact algorithm is more complicated than this). - std::vector<macho::RelocationEntry> &Relocs = Relocations[it]; + std::vector<MachO::any_relocation_info> &Relocs = Relocations[it]; for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { - Write32(Relocs[e - i - 1].Word0); - Write32(Relocs[e - i - 1].Word1); + Write32(Relocs[e - i - 1].r_word0); + Write32(Relocs[e - i - 1].r_word1); } } @@ -906,9 +925,9 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, // If this symbol is defined and internal, mark it as such. if (it->Symbol->isDefined() && !Asm.getSymbolData(*it->Symbol).isExternal()) { - uint32_t Flags = macho::ISF_Local; + uint32_t Flags = MachO::INDIRECT_SYMBOL_LOCAL; if (it->Symbol->isAbsolute()) - Flags |= macho::ISF_Absolute; + Flags |= MachO::INDIRECT_SYMBOL_ABS; Write32(Flags); continue; } diff --git a/lib/MC/SubtargetFeature.cpp b/lib/MC/SubtargetFeature.cpp index 7625abd..2fb91f2 100644 --- a/lib/MC/SubtargetFeature.cpp +++ b/lib/MC/SubtargetFeature.cpp @@ -121,13 +121,10 @@ void SubtargetFeatures::AddFeature(const StringRef String, /// Find KV in array using binary search. static const SubtargetFeatureKV *Find(StringRef S, const SubtargetFeatureKV *A, size_t L) { - // Make the lower bound element we're looking for - SubtargetFeatureKV KV; - KV.Key = S.data(); // Determine the end of the array const SubtargetFeatureKV *Hi = A + L; // Binary search the array - const SubtargetFeatureKV *F = std::lower_bound(A, Hi, KV); + const SubtargetFeatureKV *F = std::lower_bound(A, Hi, S); // If not found then return NULL if (F == Hi || StringRef(F->Key) != S) return NULL; // Return the found array item @@ -353,8 +350,7 @@ void SubtargetFeatures::dump() const { } #endif -/// getDefaultSubtargetFeatures - Return a string listing the features -/// associated with the target triple. +/// Adds the default features for the specified target triple. /// /// FIXME: This is an inelegant way of specifying the features of a /// subtarget. It would be better if we could encode this information diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp index 4e26934..d9ca86d 100644 --- a/lib/MC/WinCOFFObjectWriter.cpp +++ b/lib/MC/WinCOFFObjectWriter.cpp @@ -138,7 +138,7 @@ public: symbol_map SymbolMap; WinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW, raw_ostream &OS); - ~WinCOFFObjectWriter(); + virtual ~WinCOFFObjectWriter(); COFFSymbol *createSymbol(StringRef Name); COFFSymbol *GetOrCreateCOFFSymbol(const MCSymbol * Symbol); @@ -148,13 +148,12 @@ public: object_t *createCOFFEntity(StringRef Name, list_t &List); void DefineSection(MCSectionData const &SectionData); - void DefineSymbol(MCSymbolData const &SymbolData, - MCAssembler &Assembler); + void DefineSymbol(MCSymbolData const &SymbolData, MCAssembler &Assembler, + const MCAsmLayout &Layout); void MakeSymbolReal(COFFSymbol &S, size_t Index); void MakeSectionReal(COFFSection &S, size_t Number); - bool ExportSection(COFFSection const *S); bool ExportSymbol(MCSymbolData const &SymbolData, MCAssembler &Asm); bool IsPhysicalSection(COFFSection *S); @@ -190,17 +189,6 @@ static inline void write_uint32_le(void *Data, uint32_t const &Value) { Ptr[3] = (Value & 0xFF000000) >> 24; } -static inline void write_uint16_le(void *Data, uint16_t const &Value) { - uint8_t *Ptr = reinterpret_cast<uint8_t *>(Data); - Ptr[0] = (Value & 0x00FF) >> 0; - Ptr[1] = (Value & 0xFF00) >> 8; -} - -static inline void write_uint8_le(void *Data, uint8_t const &Value) { - uint8_t *Ptr = reinterpret_cast<uint8_t *>(Data); - Ptr[0] = (Value & 0xFF) >> 0; -} - //------------------------------------------------------------------------------ // Symbol class implementation @@ -411,7 +399,8 @@ void WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) { /// This function takes a section data object from the assembler /// and creates the associated COFF symbol staging object. void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData, - MCAssembler &Assembler) { + MCAssembler &Assembler, + const MCAsmLayout &Layout) { MCSymbol const &Symbol = SymbolData.getSymbol(); COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&Symbol); SymbolMap[&Symbol] = coff_symbol; @@ -452,6 +441,12 @@ void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData, const MCSymbolData &ResSymData = Assembler.getSymbolData(Symbol.AliasedSymbol()); + if (Symbol.isVariable()) { + int64_t Addr; + if (Symbol.getVariableValue()->EvaluateAsAbsolute(Addr, Layout)) + coff_symbol->Data.Value = Addr; + } + coff_symbol->Data.Type = (ResSymData.getFlags() & 0x0000FFFF) >> 0; coff_symbol->Data.StorageClass = (ResSymData.getFlags() & 0x00FF0000) >> 16; @@ -463,7 +458,9 @@ void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData, external ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC; } - if (ResSymData.Fragment != NULL) + if (Symbol.isAbsolute() || Symbol.AliasedSymbol().isVariable()) + coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; + else if (ResSymData.Fragment != NULL) coff_symbol->Section = SectionMap[&ResSymData.Fragment->getParent()->getSection()]; @@ -508,10 +505,6 @@ void WinCOFFObjectWriter::MakeSymbolReal(COFFSymbol &S, size_t Index) { S.Index = Index; } -bool WinCOFFObjectWriter::ExportSection(COFFSection const *S) { - return !S->MCData->getFragmentList().empty(); -} - bool WinCOFFObjectWriter::ExportSymbol(MCSymbolData const &SymbolData, MCAssembler &Asm) { // This doesn't seem to be right. Strings referred to from the .data section @@ -625,9 +618,10 @@ void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, DefineSection(*i); for (MCAssembler::const_symbol_iterator i = Asm.symbol_begin(), - e = Asm.symbol_end(); i != e; i++) { + e = Asm.symbol_end(); + i != e; i++) { if (ExportSymbol(*i, Asm)) { - DefineSymbol(*i, Asm); + DefineSymbol(*i, Asm, Layout); } } } @@ -921,6 +915,9 @@ MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_) : Machine(Machine_) { } +// Pin the vtable to this file. +void MCWinCOFFObjectTargetWriter::anchor() {} + //------------------------------------------------------------------------------ // WinCOFFObjectWriter factory function diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp index 04bfeb4..5b5aad7 100644 --- a/lib/MC/WinCOFFStreamer.cpp +++ b/lib/MC/WinCOFFStreamer.cpp @@ -55,7 +55,7 @@ public: virtual void EmitDebugLabel(MCSymbol *Symbol); virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); virtual void EmitThumbFunc(MCSymbol *Func); - virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); + 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); @@ -72,13 +72,10 @@ public: 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(); - static bool classof(const MCStreamer *S) { - return S->getKind() == SK_WinCOFFStreamer; - } - private: virtual void EmitInstToData(const MCInst &Inst) { MCDataFragment *DF = getOrCreateDataFragment(); @@ -134,8 +131,7 @@ private: WinCOFFStreamer::WinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, MCCodeEmitter &CE, raw_ostream &OS) - : MCObjectStreamer(SK_WinCOFFStreamer, Context, MAB, OS, &CE), - CurSymbol(NULL) {} + : MCObjectStreamer(Context, 0, MAB, OS, &CE), CurSymbol(NULL) {} void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment, bool External) { @@ -155,7 +151,8 @@ void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size, int Selection = COFF::IMAGE_COMDAT_SELECT_LARGEST; const MCSection *Section = MCStreamer::getContext().getCOFFSection( - SectionName, Characteristics, SectionKind::getBSS(), Selection); + SectionName, Characteristics, SectionKind::getBSS(), Symbol->getName(), + Selection); MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section); @@ -164,7 +161,7 @@ void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size, SymbolData.setExternal(External); - Symbol->setSection(*Section); + AssignSection(Symbol, Section); if (ByteAlignment != 1) new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, &SectionData); @@ -201,7 +198,7 @@ void WinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) { llvm_unreachable("not implemented"); } -void WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, +bool WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { assert(Symbol && "Symbol must be non-null!"); assert((Symbol->isInSection() @@ -221,8 +218,10 @@ void WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, break; default: - llvm_unreachable("unsupported attribute"); + return false; } + + return true; } void WinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { @@ -309,6 +308,11 @@ void WinCOFFStreamer::EmitFileDirective(StringRef Filename) { // info will be a much large effort. } +// TODO: Implement this if you want to emit .comment section in COFF obj files. +void WinCOFFStreamer::EmitIdent(StringRef IdentString) { + llvm_unreachable("unsupported directive"); +} + void WinCOFFStreamer::EmitWin64EHHandlerData() { MCStreamer::EmitWin64EHHandlerData(); @@ -318,6 +322,7 @@ void WinCOFFStreamer::EmitWin64EHHandlerData() { } void WinCOFFStreamer::FinishImpl() { + EmitFrames(NULL, true); EmitW64Tables(); MCObjectStreamer::FinishImpl(); } |