diff options
author | Eli Bendersky <eliben@chromium.org> | 2013-03-11 15:16:37 -0700 |
---|---|---|
committer | Eli Bendersky <eliben@chromium.org> | 2013-03-11 15:16:37 -0700 |
commit | 23c00401dad33ca247d2818e71540079bed63c5b (patch) | |
tree | df9f25d60f9538fbde84b78cf3c4e4a00eb6c3db /lib/MC | |
parent | 79da56afe68a0c5b2c2227681014dd13705d78cc (diff) | |
parent | 279b9184c2ff4fea93b198a3519b8cb3a1d8d195 (diff) |
Merge commit '279b9184c2ff4fea93b198a3519b8cb3a1d8d195'
Conflicts:
include/llvm/CodeGen/LexicalScopes.h
include/llvm/MC/MCAsmInfo.h
lib/Linker/LinkArchives.cpp
lib/Linker/LinkItems.cpp
lib/MC/MCAsmInfo.cpp
lib/MC/MCDwarf.cpp
lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/ARMSubtarget.cpp
lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
lib/Target/Mips/MipsAsmPrinter.cpp
lib/Target/Mips/MipsDelaySlotFiller.cpp
lib/Target/Mips/MipsISelDAGToDAG.cpp
lib/Target/Mips/MipsSubtarget.cpp
lib/Target/Mips/MipsSubtarget.h
lib/Target/Mips/MipsTargetObjectFile.cpp
lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
lib/Target/X86/X86FastISel.cpp
lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86TargetMachine.cpp
lib/Transforms/CMakeLists.txt
lib/Transforms/LLVMBuild.txt
lib/Transforms/Makefile
test/MC/ARM/arm_instructions.s
test/MC/X86/AlignedBundling/pad-align-to-bundle-end.s
Diffstat (limited to 'lib/MC')
-rw-r--r-- | lib/MC/ELFObjectWriter.cpp | 48 | ||||
-rw-r--r-- | lib/MC/MCAsmInfo.cpp | 3 | ||||
-rw-r--r-- | lib/MC/MCAsmStreamer.cpp | 17 | ||||
-rw-r--r-- | lib/MC/MCAssembler.cpp | 20 | ||||
-rw-r--r-- | lib/MC/MCContext.cpp | 4 | ||||
-rw-r--r-- | lib/MC/MCDwarf.cpp | 70 | ||||
-rw-r--r-- | lib/MC/MCELF.cpp | 15 | ||||
-rw-r--r-- | lib/MC/MCELFObjectTargetWriter.cpp | 5 | ||||
-rw-r--r-- | lib/MC/MCELFStreamer.cpp | 21 | ||||
-rw-r--r-- | lib/MC/MCMachOStreamer.cpp | 15 | ||||
-rw-r--r-- | lib/MC/MCNullStreamer.cpp | 7 | ||||
-rw-r--r-- | lib/MC/MCObjectFileInfo.cpp | 34 | ||||
-rw-r--r-- | lib/MC/MCObjectStreamer.cpp | 31 | ||||
-rw-r--r-- | lib/MC/MCParser/AsmLexer.cpp | 80 | ||||
-rw-r--r-- | lib/MC/MCParser/AsmParser.cpp | 698 | ||||
-rw-r--r-- | lib/MC/MCParser/COFFAsmParser.cpp | 81 | ||||
-rw-r--r-- | lib/MC/MCParser/DarwinAsmParser.cpp | 239 | ||||
-rw-r--r-- | lib/MC/MCParser/ELFAsmParser.cpp | 99 | ||||
-rw-r--r-- | lib/MC/MCParser/MCAsmParser.cpp | 4 | ||||
-rw-r--r-- | lib/MC/MCPureStreamer.cpp | 10 | ||||
-rw-r--r-- | lib/MC/MCSectionMachO.cpp | 4 | ||||
-rw-r--r-- | lib/MC/MCStreamer.cpp | 16 | ||||
-rw-r--r-- | lib/MC/MachObjectWriter.cpp | 57 | ||||
-rw-r--r-- | lib/MC/WinCOFFObjectWriter.cpp | 29 | ||||
-rw-r--r-- | lib/MC/WinCOFFStreamer.cpp | 54 |
25 files changed, 1087 insertions, 574 deletions
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 00724465f6..0b97f2700b 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -135,16 +135,14 @@ class ELFObjectWriter : public MCObjectWriter { const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const { - return TargetObjectWriter->undefinedExplicitRelSym(Target, Fixup, IsPCRel); + return TargetObjectWriter->undefinedExplicitRelSym(Target, Fixup, + IsPCRel); } bool is64Bit() const { return TargetObjectWriter->is64Bit(); } bool hasRelocationAddend() const { return TargetObjectWriter->hasRelocationAddend(); } - unsigned getEFlags() const { - return TargetObjectWriter->getEFlags(); - } unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel, bool IsRelocWithSymbol, int64_t Addend) const { @@ -152,7 +150,6 @@ class ELFObjectWriter : public MCObjectWriter { IsRelocWithSymbol, Addend); } - public: ELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_ostream &_OS, bool IsLittleEndian) @@ -233,7 +230,8 @@ class ELFObjectWriter : public MCObjectWriter { F.getContents().append(&buf[0], &buf[8]); } - void WriteHeader(uint64_t SectionDataSize, + void WriteHeader(const MCAssembler &Asm, + uint64_t SectionDataSize, unsigned NumberOfSections); void WriteSymbolEntry(MCDataFragment *SymtabF, @@ -373,7 +371,8 @@ ELFObjectWriter::~ELFObjectWriter() {} // Emit the ELF header. -void ELFObjectWriter::WriteHeader(uint64_t SectionDataSize, +void ELFObjectWriter::WriteHeader(const MCAssembler &Asm, + uint64_t SectionDataSize, unsigned NumberOfSections) { // ELF Header // ---------- @@ -411,7 +410,7 @@ void ELFObjectWriter::WriteHeader(uint64_t SectionDataSize, sizeof(ELF::Elf32_Ehdr))); // e_shoff = sec hdr table off in bytes // e_flags = whatever the target wants - Write32(getEFlags()); + Write32(Asm.getELFHeaderEFlags()); // e_ehsize = ELF header size Write16(is64Bit() ? sizeof(ELF::Elf64_Ehdr) : sizeof(ELF::Elf32_Ehdr)); @@ -547,12 +546,17 @@ void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF, bool IsReserved = Data.isCommon() || Data.getSymbol().isAbsolute() || Data.getSymbol().isVariable(); + // Binding and Type share the same byte as upper and lower nibbles uint8_t Binding = MCELF::GetBinding(OrigData); - uint8_t Visibility = MCELF::GetVisibility(OrigData); uint8_t Type = MCELF::GetType(Data); - uint8_t Info = (Binding << ELF_STB_Shift) | (Type << ELF_STT_Shift); - uint8_t Other = Visibility; + + // Other and Visibility share the same byte with Visability using the lower + // 2 bits + uint8_t Visibility = MCELF::GetVisibility(OrigData); + uint8_t Other = MCELF::getOther(OrigData) << + (ELF_Other_Shift - ELF_STV_Shift); + Other |= Visibility; uint64_t Value = SymbolValue(Data, Layout); uint64_t Size = 0; @@ -1319,6 +1323,8 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, case ELF::SHT_FINI_ARRAY: case ELF::SHT_PREINIT_ARRAY: case ELF::SHT_X86_64_UNWIND: + case ELF::SHT_MIPS_REGINFO: + case ELF::SHT_MIPS_OPTIONS: // Nothing to do. break; @@ -1332,6 +1338,24 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, break; } + if (TargetObjectWriter->getEMachine() == ELF::EM_ARM && + Section.getType() == ELF::SHT_ARM_EXIDX) { + StringRef SecName(Section.getSectionName()); + if (SecName == ".ARM.exidx") { + sh_link = SectionIndexMap.lookup( + Asm.getContext().getELFSection(".text", + ELF::SHT_PROGBITS, + 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())); + } + } + WriteSecHdrEntry(SectionStringTableIndex[&Section], Section.getType(), Section.getFlags(), 0, Offset, Size, sh_link, sh_info, Alignment, Section.getEntrySize()); @@ -1532,7 +1556,7 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, } // Write out the ELF header ... - WriteHeader(SectionHeaderOffset, NumSections + 1); + WriteHeader(Asm, SectionHeaderOffset, NumSections + 1); // ... then the regular sections ... // + because of .shstrtab diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index ffe1b0c50d..51bb435710 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -24,7 +24,8 @@ using namespace llvm; MCAsmInfo::MCAsmInfo() { PointerSize = 4; - StackSlotSize = 4; // @LOCALMOD + CalleeSaveStackSlotSize = 4; + IsLittleEndian = true; StackGrowsUp = false; HasSubsectionsViaSymbols = false; diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index dd5112c771..7eb7202332 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -71,7 +71,7 @@ public: MCInstPrinter *printer, MCCodeEmitter *emitter, MCAsmBackend *asmbackend, bool showInst) - : MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()), + : 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), @@ -145,6 +145,7 @@ public: virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); + virtual void EmitLinkerOptions(ArrayRef<std::string> Options); virtual void EmitDataRegion(MCDataRegionType Kind); virtual void EmitThumbFunc(MCSymbol *Func); @@ -276,6 +277,10 @@ public: virtual void FinishImpl(); /// @} + + static bool classof(const MCStreamer *S) { + return S->getKind() == SK_AsmStreamer; + } }; } // end anonymous namespace. @@ -375,6 +380,16 @@ void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { EmitEOL(); } +void MCAsmStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) { + assert(!Options.empty() && "At least one option is required!"); + OS << "\t.linker_option \"" << Options[0] << '"'; + for (ArrayRef<std::string>::iterator it = Options.begin() + 1, + ie = Options.end(); it != ie; ++it) { + OS << ", " << '"' << *it << '"'; + } + OS << "\n"; +} + void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) { MCContext &Ctx = getContext(); const MCAsmInfo &MAI = Ctx.getAsmInfo(); diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 416af8b46f..a394d532d6 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -88,7 +88,8 @@ void MCAsmLayout::invalidateFragmentsFrom(MCFragment *F) { if (!isFragmentValid(F)) return; - // Otherwise, reset the last valid fragment to this fragment. + // Otherwise, reset the last valid fragment to the previous fragment + // (if this is the first fragment, it will be NULL). const MCSectionData &SD = *F->getParent(); LastValidFragment[&SD] = F->getPrevNode(); } @@ -273,7 +274,7 @@ MCAssembler::MCAssembler(MCContext &Context_, MCAsmBackend &Backend_, raw_ostream &OS_) : Context(Context_), Backend(Backend_), Emitter(Emitter_), Writer(Writer_), OS(OS_), BundleAlignSize(0), RelaxAll(false), NoExecStack(false), - SubsectionsViaSymbols(false) { + SubsectionsViaSymbols(false), ELFHeaderEFlags(0) { } MCAssembler::~MCAssembler() { @@ -290,6 +291,7 @@ void MCAssembler::reset() { RelaxAll = false; NoExecStack = false; SubsectionsViaSymbols = false; + ELFHeaderEFlags = 0; // reset objects owned by us getBackend().reset(); @@ -428,7 +430,7 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, } case MCFragment::FT_Org: { - MCOrgFragment &OF = cast<MCOrgFragment>(F); + const MCOrgFragment &OF = cast<MCOrgFragment>(F); int64_t TargetLocation; if (!OF.getOffset().EvaluateAsAbsolute(TargetLocation, Layout)) report_fatal_error("expected assembly-time absolute expression"); @@ -505,7 +507,7 @@ void MCAsmLayout::layoutFragment(MCFragment *F) { /// \brief Write the contents of a fragment to the given object writer. Expects /// a MCEncodedFragment. static void writeFragmentContents(const MCFragment &F, MCObjectWriter *OW) { - MCEncodedFragment &EF = cast<MCEncodedFragment>(F); + const MCEncodedFragment &EF = cast<MCEncodedFragment>(F); OW->WriteBytes(EF.getContents()); } @@ -556,7 +558,7 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, switch (F.getKind()) { case MCFragment::FT_Align: { ++stats::EmittedAlignFragments; - MCAlignFragment &AF = cast<MCAlignFragment>(F); + const MCAlignFragment &AF = cast<MCAlignFragment>(F); uint64_t Count = FragmentSize / AF.getValueSize(); assert(AF.getValueSize() && "Invalid virtual align in concrete fragment!"); @@ -611,7 +613,7 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, case MCFragment::FT_Fill: { ++stats::EmittedFillFragments; - MCFillFragment &FF = cast<MCFillFragment>(F); + const MCFillFragment &FF = cast<MCFillFragment>(F); assert(FF.getValueSize() && "Invalid virtual align in concrete fragment!"); @@ -628,14 +630,14 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, } case MCFragment::FT_LEB: { - MCLEBFragment &LF = cast<MCLEBFragment>(F); + const MCLEBFragment &LF = cast<MCLEBFragment>(F); OW->WriteBytes(LF.getContents().str()); break; } case MCFragment::FT_Org: { ++stats::EmittedOrgFragments; - MCOrgFragment &OF = cast<MCOrgFragment>(F); + const MCOrgFragment &OF = cast<MCOrgFragment>(F); for (uint64_t i = 0, e = FragmentSize; i != e; ++i) OW->Write8(uint8_t(OF.getValue())); @@ -674,7 +676,7 @@ void MCAssembler::writeSectionData(const MCSectionData *SD, // Check that we aren't trying to write a non-zero contents (or fixups) // into a virtual section. This is to support clients which use standard // directives to fill the contents of virtual sections. - MCDataFragment &DF = cast<MCDataFragment>(*it); + const MCDataFragment &DF = cast<MCDataFragment>(*it); assert(DF.fixup_begin() == DF.fixup_end() && "Cannot have fixups in virtual section!"); for (unsigned i = 0, e = DF.getContents().size(); i != e; ++i) diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp index aa52b49047..1a7df6041e 100644 --- a/lib/MC/MCContext.cpp +++ b/lib/MC/MCContext.cpp @@ -40,7 +40,7 @@ MCContext::MCContext(const MCAsmInfo &mai, const MCRegisterInfo &mri, CompilationDir(llvm::sys::Path::GetCurrentDirectory().str()), CurrentDwarfLoc(0,0,0,DWARF2_FLAG_IS_STMT,0,0), DwarfLocSeen(false), GenDwarfForAssembly(false), GenDwarfFileNumber(0), - AllowTemporaryLabels(true), AutoReset(DoAutoReset) { + AllowTemporaryLabels(true), DwarfCompileUnitID(0), AutoReset(DoAutoReset) { MachOUniquingMap = 0; ELFUniquingMap = 0; @@ -83,6 +83,8 @@ void MCContext::reset() { DwarfDebugFlags = StringRef(); MCLineSections.clear(); MCLineSectionOrder.clear(); + DwarfCompileUnitID = 0; + MCLineTableSymbols.clear(); CurrentDwarfLoc = MCDwarfLoc(0,0,0,DWARF2_FLAG_IS_STMT,0,0); // If we have the MachO uniquing map, free it. diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index a28d3525f9..fea057af3e 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -101,7 +101,8 @@ void MCLineEntry::Make(MCStreamer *MCOS, const MCSection *Section) { } // Add the line entry to this section's entries. - LineSection->addLineEntry(LineEntry); + LineSection->addLineEntry(LineEntry, + MCOS->getContext().getDwarfCompileUnitID()); } // @@ -131,7 +132,12 @@ static inline const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS, // static inline void EmitDwarfLineTable(MCStreamer *MCOS, const MCSection *Section, - const MCLineSection *LineSection) { + const MCLineSection *LineSection, + unsigned CUID) { + // This LineSection does not contain any LineEntry for the given Compile Unit. + if (!LineSection->containEntriesForID(CUID)) + return; + unsigned FileNum = 1; unsigned LastLine = 1; unsigned Column = 0; @@ -141,8 +147,8 @@ static inline void EmitDwarfLineTable(MCStreamer *MCOS, // Loop through each MCLineEntry and encode the dwarf line number table. for (MCLineSection::const_iterator - it = LineSection->getMCLineEntries()->begin(), - ie = LineSection->getMCLineEntries()->end(); it != ie; ++it) { + it = LineSection->getMCLineEntries(CUID).begin(), + ie = LineSection->getMCLineEntries(CUID).end(); it != ie; ++it) { if (FileNum != it->getFileNum()) { FileNum = it->getFileNum(); @@ -215,9 +221,36 @@ const MCSymbol *MCDwarfFileTable::Emit(MCStreamer *MCOS) { // Switch to the section where the table will be emitted into. MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection()); - // Create a symbol at the beginning of this section. - MCSymbol *LineStartSym = context.CreateTempSymbol(); - // Set the value of the symbol, as we are at the start of the section. + const DenseMap<unsigned, MCSymbol *> &MCLineTableSymbols = + MCOS->getContext().getMCLineTableSymbols(); + // CUID and MCLineTableSymbols are set in DwarfDebug, when DwarfDebug does + // not exist, CUID will be 0 and MCLineTableSymbols will be empty. + // Handle Compile Unit 0, the line table start symbol is the section symbol. + const MCSymbol *LineStartSym = EmitCU(MCOS, 0); + // Handle the rest of the Compile Units. + for (unsigned Is = 1, Ie = MCLineTableSymbols.size(); Is < Ie; Is++) + EmitCU(MCOS, Is); + + // Now delete the MCLineSections that were created in MCLineEntry::Make() + // and used to emit the line table. + const DenseMap<const MCSection *, MCLineSection *> &MCLineSections = + MCOS->getContext().getMCLineSections(); + for (DenseMap<const MCSection *, MCLineSection *>::const_iterator it = + MCLineSections.begin(), ie = MCLineSections.end(); it != ie; + ++it) + delete it->second; + + return LineStartSym; +} + +const MCSymbol *MCDwarfFileTable::EmitCU(MCStreamer *MCOS, unsigned CUID) { + MCContext &context = MCOS->getContext(); + + // Create a symbol at the beginning of the line table. + MCSymbol *LineStartSym = MCOS->getContext().getMCLineTableSymbol(CUID); + if (!LineStartSym) + LineStartSym = context.CreateTempSymbol(); + // Set the value of the symbol, as we are at the start of the line table. MCOS->EmitLabel(LineStartSym); // Create a symbol for the end of the section (to be set when we get there). @@ -239,8 +272,7 @@ const MCSymbol *MCDwarfFileTable::Emit(MCStreamer *MCOS) { // total length, the 2 bytes for the version, and these 4 bytes for the // length of the prologue. MCOS->EmitAbsValue(MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym, - (4 + 2 + 4)), - 4, 0); + (4 + 2 + 4)), 4, 0); // Parameters of the state machine, are next. MCOS->EmitIntValue(DWARF2_LINE_MIN_INSN_LENGTH, 1); @@ -301,11 +333,7 @@ const MCSymbol *MCDwarfFileTable::Emit(MCStreamer *MCOS) { ++it) { const MCSection *Sec = *it; const MCLineSection *Line = MCLineSections.lookup(Sec); - EmitDwarfLineTable(MCOS, Sec, Line); - - // Now delete the MCLineSections that were created in MCLineEntry::Make() - // and used to emit the line table. - delete Line; + EmitDwarfLineTable(MCOS, Sec, Line, CUID); } if (MCOS->getContext().getAsmInfo().getLinkerRequiresNonEmptyDwarfLines() @@ -638,9 +666,15 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS, } // AT_producer, the version of the assembler tool. - MCOS->EmitBytes(StringRef("llvm-mc (based on LLVM ")); - MCOS->EmitBytes(StringRef(PACKAGE_VERSION)); - MCOS->EmitBytes(StringRef(")")); + StringRef DwarfDebugProducer = context.getDwarfDebugProducer(); + if (!DwarfDebugProducer.empty()){ + MCOS->EmitBytes(DwarfDebugProducer); + } + else { + MCOS->EmitBytes(StringRef("llvm-mc (based on LLVM ")); + MCOS->EmitBytes(StringRef(PACKAGE_VERSION)); + MCOS->EmitBytes(StringRef(")")); + } MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. // AT_language, a 4 byte value. We use DW_LANG_Mips_Assembler as the dwarf2 @@ -786,7 +820,7 @@ void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS, static int getDataAlignmentFactor(MCStreamer &streamer) { MCContext &context = streamer.getContext(); const MCAsmInfo &asmInfo = context.getAsmInfo(); - int size = asmInfo.getStackSlotSize(); // @LOCALMOD + int size = asmInfo.getCalleeSaveStackSlotSize(); if (asmInfo.isStackGrowthDirectionUp()) return size; else diff --git a/lib/MC/MCELF.cpp b/lib/MC/MCELF.cpp index 4db2846bc3..560cdbc6ab 100644 --- a/lib/MC/MCELF.cpp +++ b/lib/MC/MCELF.cpp @@ -52,6 +52,8 @@ unsigned MCELF::GetType(const MCSymbolData &SD) { return Type; } +// Visibility is stored in the first two bits of st_other +// st_other values are stored in the second byte of get/setFlags void MCELF::SetVisibility(MCSymbolData &SD, unsigned Visibility) { assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL || Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED); @@ -68,4 +70,17 @@ unsigned MCELF::GetVisibility(MCSymbolData &SD) { return Visibility; } +// Other is stored in the last six bits of st_other +// st_other values are stored in the second byte of get/setFlags +void MCELF::setOther(MCSymbolData &SD, unsigned Other) { + uint32_t OtherFlags = SD.getFlags() & ~(0x3f << ELF_Other_Shift); + SD.setFlags(OtherFlags | (Other << ELF_Other_Shift)); +} + +unsigned MCELF::getOther(MCSymbolData &SD) { + unsigned Other = + (SD.getFlags() & (0x3f << ELF_Other_Shift)) >> ELF_Other_Shift; + return Other; +} + } diff --git a/lib/MC/MCELFObjectTargetWriter.cpp b/lib/MC/MCELFObjectTargetWriter.cpp index 74cd042a0f..4cac84d666 100644 --- a/lib/MC/MCELFObjectTargetWriter.cpp +++ b/lib/MC/MCELFObjectTargetWriter.cpp @@ -24,11 +24,6 @@ MCELFObjectTargetWriter::MCELFObjectTargetWriter(bool Is64Bit_, IsN64(IsN64_){ } -/// Default e_flags = 0 -unsigned MCELFObjectTargetWriter::getEFlags() const { - return 0; -} - const MCSymbol *MCELFObjectTargetWriter::ExplicitRelSym(const MCAssembler &Asm, const MCValue &Target, const MCFragment &F, diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 27587d312a..c1428d8587 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -300,7 +300,9 @@ void MCELFStreamer::EmitFileDirective(StringRef Filename) { void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { switch (expr->getKind()) { - case MCExpr::Target: llvm_unreachable("Can't handle target exprs yet!"); + case MCExpr::Target: + cast<MCTargetExpr>(expr)->fixELFSymbolsInTLSFixups(getAssembler()); + break; case MCExpr::Constant: break; @@ -332,6 +334,19 @@ void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { case MCSymbolRefExpr::VK_Mips_GOTTPREL: case MCSymbolRefExpr::VK_Mips_TPREL_HI: case MCSymbolRefExpr::VK_Mips_TPREL_LO: + case MCSymbolRefExpr::VK_PPC_TPREL16_HA: + case MCSymbolRefExpr::VK_PPC_TPREL16_LO: + case MCSymbolRefExpr::VK_PPC_DTPREL16_HA: + case MCSymbolRefExpr::VK_PPC_DTPREL16_LO: + case MCSymbolRefExpr::VK_PPC_GOT_TPREL16_HA: + case MCSymbolRefExpr::VK_PPC_GOT_TPREL16_LO: + case MCSymbolRefExpr::VK_PPC_TLS: + case MCSymbolRefExpr::VK_PPC_GOT_TLSGD16_HA: + case MCSymbolRefExpr::VK_PPC_GOT_TLSGD16_LO: + case MCSymbolRefExpr::VK_PPC_TLSGD: + case MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_HA: + case MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_LO: + case MCSymbolRefExpr::VK_PPC_TLSLD: break; } MCSymbolData &SD = getAssembler().getOrCreateSymbolData(symRef.getSymbol()); @@ -502,6 +517,10 @@ void MCELFStreamer::EmitThumbFunc(MCSymbol *Func) { llvm_unreachable("Generic ELF doesn't support this directive"); } +MCSymbolData &MCELFStreamer::getOrCreateSymbolData(MCSymbol *Symbol) { + return getAssembler().getOrCreateSymbolData(*Symbol); +} + void MCELFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { llvm_unreachable("ELF doesn't support this directive"); } diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index f947dda83d..7d08d0ecd5 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -34,9 +34,9 @@ private: void EmitDataRegion(DataRegionData::KindTy Kind); void EmitDataRegionEnd(); public: - MCMachOStreamer(MCContext &Context, MCAsmBackend &MAB, - raw_ostream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(Context, MAB, OS, Emitter) {} + MCMachOStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, + MCCodeEmitter *Emitter) + : MCObjectStreamer(SK_MachOStreamer, Context, MAB, OS, Emitter) {} /// @name MCStreamer Interface /// @{ @@ -48,6 +48,7 @@ public: virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); + virtual void EmitLinkerOptions(ArrayRef<std::string> Options); virtual void EmitDataRegion(MCDataRegionType Kind); virtual void EmitThumbFunc(MCSymbol *Func); virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); @@ -86,6 +87,10 @@ public: virtual void FinishImpl(); /// @} + + static bool classof(const MCStreamer *S) { + return S->getKind() == SK_MachOStreamer; + } }; } // end anonymous namespace. @@ -178,6 +183,10 @@ void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { } } +void MCMachOStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) { + getAssembler().getLinkerOptions().push_back(Options); +} + void MCMachOStreamer::EmitDataRegion(MCDataRegionType Kind) { switch (Kind) { case MCDR_DataRegion: diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp index 3eee5caf6f..89f74c1709 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(Context) {} + MCNullStreamer(MCContext &Context) : MCStreamer(SK_NullStreamer, Context) {} /// @name MCStreamer Interface /// @{ @@ -109,6 +109,11 @@ namespace { } /// @} + + static bool classof(const MCStreamer *S) { + return S->getKind() == SK_NullStreamer; + } + }; } diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp index e34bc2653d..1e2086e565 100644 --- a/lib/MC/MCObjectFileInfo.cpp +++ b/lib/MC/MCObjectFileInfo.cpp @@ -186,6 +186,10 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { Ctx->getMachOSection("__DWARF", "__debug_frame", MCSectionMachO::S_ATTR_DEBUG, SectionKind::getMetadata()); + DwarfPubNamesSection = + Ctx->getMachOSection("__DWARF", "__debug_pubnames", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); DwarfPubTypesSection = Ctx->getMachOSection("__DWARF", "__debug_pubtypes", MCSectionMachO::S_ATTR_DEBUG, @@ -256,6 +260,25 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { TTypeEncoding = (CMModel == CodeModel::Small) ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_absptr; } + } else if (T.getArch() == Triple::aarch64) { + FDECFIEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + + // The small model guarantees static code/data size < 4GB, but not where it + // will be in memory. Most of these could end up >2GB away so even a signed + // pc-relative 32-bit address is insufficient, theoretically. + if (RelocM == Reloc::PIC_) { + PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | + dwarf::DW_EH_PE_sdata8; + LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8; + FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | + dwarf::DW_EH_PE_sdata8; + } else { + PersonalityEncoding = dwarf::DW_EH_PE_absptr; + LSDAEncoding = dwarf::DW_EH_PE_absptr; + FDEEncoding = dwarf::DW_EH_PE_udata4; + TTypeEncoding = dwarf::DW_EH_PE_absptr; + } } else if (T.getArch() == Triple::ppc64) { PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8; @@ -381,6 +404,9 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { DwarfFrameSection = Ctx->getELFSection(".debug_frame", ELF::SHT_PROGBITS, 0, SectionKind::getMetadata()); + DwarfPubNamesSection = + Ctx->getELFSection(".debug_pubnames", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); DwarfPubTypesSection = Ctx->getELFSection(".debug_pubtypes", ELF::SHT_PROGBITS, 0, SectionKind::getMetadata()); @@ -437,6 +463,9 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { DwarfStrOffDWOSection = Ctx->getELFSection(".debug_str_offsets.dwo", ELF::SHT_PROGBITS, 0, SectionKind::getMetadata()); + DwarfAddrSection = + Ctx->getELFSection(".debug_addr", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); } @@ -521,6 +550,11 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_MEM_READ, SectionKind::getMetadata()); + DwarfPubNamesSection = + Ctx->getCOFFSection(".debug_pubnames", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); DwarfPubTypesSection = Ctx->getCOFFSection(".debug_pubtypes", COFF::IMAGE_SCN_MEM_DISCARDABLE | diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index 8130c9b532..e835eea7df 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -20,22 +20,19 @@ #include "llvm/Support/ErrorHandling.h" using namespace llvm; -MCObjectStreamer::MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *Emitter_) - : MCStreamer(Context), - Assembler(new MCAssembler(Context, TAB, - *Emitter_, *TAB.createObjectWriter(OS), - OS)), - CurSectionData(0) -{ -} - -MCObjectStreamer::MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *Emitter_, +MCObjectStreamer::MCObjectStreamer(StreamerKind Kind, MCContext &Context, + MCAsmBackend &TAB, raw_ostream &OS, + MCCodeEmitter *Emitter_) + : MCStreamer(Kind, Context), + Assembler(new MCAssembler(Context, TAB, *Emitter_, + *TAB.createObjectWriter(OS), OS)), + CurSectionData(0) {} + +MCObjectStreamer::MCObjectStreamer(StreamerKind Kind, MCContext &Context, + MCAsmBackend &TAB, raw_ostream &OS, + MCCodeEmitter *Emitter_, MCAssembler *_Assembler) - : MCStreamer(Context), Assembler(_Assembler), CurSectionData(0) -{ -} + : MCStreamer(Kind, Context), Assembler(_Assembler), CurSectionData(0) {} MCObjectStreamer::~MCObjectStreamer() { delete &Assembler->getBackend(); @@ -235,8 +232,10 @@ void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst) { IF->getContents().append(Code.begin(), Code.end()); } -const char *BundlingNotImplementedMsg = +#ifndef NDEBUG +static const char *BundlingNotImplementedMsg = "Aligned bundling is not implemented for this object format"; +#endif void MCObjectStreamer::EmitBundleAlignMode(unsigned AlignPow2) { llvm_unreachable(BundlingNotImplementedMsg); diff --git a/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp index d0492fd16c..c1c594a746 100644 --- a/lib/MC/MCParser/AsmLexer.cpp +++ b/lib/MC/MCParser/AsmLexer.cpp @@ -156,10 +156,36 @@ AsmToken AsmLexer::LexLineComment() { } static void SkipIgnoredIntegerSuffix(const char *&CurPtr) { - if (CurPtr[0] == 'L' && CurPtr[1] == 'L') - CurPtr += 2; - if (CurPtr[0] == 'U' && CurPtr[1] == 'L' && CurPtr[2] == 'L') - CurPtr += 3; + // Skip ULL, UL, U, L and LL suffices. + if (CurPtr[0] == 'U') + ++CurPtr; + if (CurPtr[0] == 'L') + ++CurPtr; + if (CurPtr[0] == 'L') + ++CurPtr; +} + +// Look ahead to search for first non-hex digit, if it's [hH], then we treat the +// integer as a hexadecimal, possibly with leading zeroes. +static unsigned doLookAhead(const char *&CurPtr, unsigned DefaultRadix) { + const char *FirstHex = 0; + const char *LookAhead = CurPtr; + while (1) { + if (isdigit(*LookAhead)) { + ++LookAhead; + } else if (isxdigit(*LookAhead)) { + if (!FirstHex) + FirstHex = LookAhead; + ++LookAhead; + } else { + break; + } + } + bool isHex = *LookAhead == 'h' || *LookAhead == 'H'; + CurPtr = isHex || !FirstHex ? LookAhead : FirstHex; + if (isHex) + return 16; + return DefaultRadix; } /// LexDigit: First character is [0-9]. @@ -167,16 +193,15 @@ static void SkipIgnoredIntegerSuffix(const char *&CurPtr) { /// Forward/Backward Label: [0-9][fb] /// Binary integer: 0b[01]+ /// Octal integer: 0[0-7]+ -/// Hex integer: 0x[0-9a-fA-F]+ +/// Hex integer: 0x[0-9a-fA-F]+ or [0x]?[0-9][0-9a-fA-F]*[hH] /// Decimal integer: [1-9][0-9]* AsmToken AsmLexer::LexDigit() { // Decimal integer: [1-9][0-9]* if (CurPtr[-1] != '0' || CurPtr[0] == '.') { - while (isdigit(*CurPtr)) - ++CurPtr; - + unsigned Radix = doLookAhead(CurPtr, 10); + bool isHex = Radix == 16; // Check for floating point literals. - if (*CurPtr == '.' || *CurPtr == 'e') { + if (!isHex && (*CurPtr == '.' || *CurPtr == 'e')) { ++CurPtr; return LexFloatLiteral(); } @@ -184,17 +209,22 @@ AsmToken AsmLexer::LexDigit() { StringRef Result(TokStart, CurPtr - TokStart); long long Value; - if (Result.getAsInteger(10, Value)) { + if (Result.getAsInteger(Radix, Value)) { // Allow positive values that are too large to fit into a signed 64-bit // integer, but that do fit in an unsigned one, we just convert them over. unsigned long long UValue; - if (Result.getAsInteger(10, UValue)) - return ReturnError(TokStart, "invalid decimal number"); + if (Result.getAsInteger(Radix, UValue)) + return ReturnError(TokStart, !isHex ? "invalid decimal number" : + "invalid hexdecimal number"); Value = (long long)UValue; } - // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL - // suffixes on integer literals. + // Consume the [bB][hH]. + if (Radix == 2 || Radix == 16) + ++CurPtr; + + // The darwin/x86 (and x86-64) assembler accepts and ignores type + // suffices on integer literals. SkipIgnoredIntegerSuffix(CurPtr); return AsmToken(AsmToken::Integer, Result, Value); @@ -243,6 +273,10 @@ AsmToken AsmLexer::LexDigit() { if (StringRef(TokStart, CurPtr - TokStart).getAsInteger(0, Result)) return ReturnError(TokStart, "invalid hexadecimal number"); + // Consume the optional [hH]. + if (*CurPtr == 'h' || *CurPtr == 'H') + ++CurPtr; + // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL // suffixes on integer literals. SkipIgnoredIntegerSuffix(CurPtr); @@ -251,14 +285,18 @@ AsmToken AsmLexer::LexDigit() { (int64_t)Result); } - // Must be an octal number, it starts with 0. - while (*CurPtr >= '0' && *CurPtr <= '9') - ++CurPtr; - - StringRef Result(TokStart, CurPtr - TokStart); + // Either octal or hexadecimal. long long Value; - if (Result.getAsInteger(8, Value)) - return ReturnError(TokStart, "invalid octal number"); + unsigned Radix = doLookAhead(CurPtr, 8); + bool isHex = Radix == 16; + StringRef Result(TokStart, CurPtr - TokStart); + if (Result.getAsInteger(Radix, Value)) + return ReturnError(TokStart, !isHex ? "invalid octal number" : + "invalid hexdecimal number"); + + // Consume the [hH]. + if (Radix == 16) + ++CurPtr; // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL // suffixes on integer literals. diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 43c872b809..6ab49ec92c 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -13,6 +13,7 @@ #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAsmInfo.h" @@ -50,6 +51,25 @@ MCAsmParserSemaCallback::~MCAsmParserSemaCallback() {} namespace { +/// \brief Helper types for tracking macro definitions. +typedef std::vector<AsmToken> MCAsmMacroArgument; +typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments; +typedef std::pair<StringRef, MCAsmMacroArgument> MCAsmMacroParameter; +typedef std::vector<MCAsmMacroParameter> MCAsmMacroParameters; + +struct MCAsmMacro { + StringRef Name; + StringRef Body; + MCAsmMacroParameters Parameters; + +public: + MCAsmMacro(StringRef N, StringRef B, const MCAsmMacroParameters &P) : + Name(N), Body(B), Parameters(P) {} + + MCAsmMacro(const MCAsmMacro& Other) + : Name(Other.Name), Body(Other.Body), Parameters(Other.Parameters) {} +}; + /// \brief Helper class for storing information about an active macro /// instantiation. struct MacroInstantiation { @@ -73,7 +93,6 @@ public: MemoryBuffer *I); }; -//struct AsmRewrite; struct ParseStatementInfo { /// ParsedOperands - The parsed operands from the last parsed statement. SmallVector<MCParsedAsmOperand*, 8> ParsedOperands; @@ -121,9 +140,7 @@ private: /// ExtensionDirectiveMap - maps directive names to handler methods in parser /// extensions. Extensions register themselves in this map by calling - /// AddDirectiveHandler. - typedef std::pair<MCAsmParserExtension*, DirectiveHandler> - ExtensionDirectiveHandler; + /// addDirectiveHandler. StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap; /// MacroMap - Map of currently defined macros. @@ -160,10 +177,9 @@ public: virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false); - virtual void AddDirectiveHandler(MCAsmParserExtension *Object, - StringRef Directive, - DirectiveHandler Handler) { - ExtensionDirectiveMap[Directive] = std::make_pair(Object, Handler); + virtual void addDirectiveHandler(StringRef Directive, + ExtensionDirectiveHandler Handler) { + ExtensionDirectiveMap[Directive] = Handler; } public: @@ -194,7 +210,7 @@ public: void setParsingInlineAsm(bool V) { ParsingInlineAsm = V; } bool isParsingInlineAsm() { return ParsingInlineAsm; } - bool ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, + bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, SmallVectorImpl<std::pair<void *,bool> > &OpDecls, SmallVectorImpl<std::string> &Constraints, @@ -203,31 +219,17 @@ public: const MCInstPrinter *IP, MCAsmParserSemaCallback &SI); - bool ParseExpression(const MCExpr *&Res); - virtual bool ParseExpression(const MCExpr *&Res, SMLoc &EndLoc); - virtual bool ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc); - virtual bool ParseAbsoluteExpression(int64_t &Res); - - bool ParseMacroArgument(MCAsmMacroArgument &MA, - AsmToken::TokenKind &ArgumentDelimiter); + bool parseExpression(const MCExpr *&Res); + virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc); + virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc); + virtual bool parseAbsoluteExpression(int64_t &Res); - /// ParseIdentifier - Parse an identifier or string (as a quoted identifier) + /// parseIdentifier - 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(); - - virtual bool MacrosEnabled() {return MacrosEnabledFlag;} - virtual void SetMacrosEnabled(bool flag) {MacrosEnabledFlag = flag;} + virtual bool parseIdentifier(StringRef &Res); + virtual void eatToEndOfStatement(); - virtual const MCAsmMacro* LookupMacro(StringRef Name); - virtual void DefineMacro(StringRef Name, const MCAsmMacro& Macro); - virtual void UndefineMacro(StringRef Name); - - virtual bool InsideMacroInstantiation() {return !ActiveMacros.empty();} - virtual bool HandleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc); - void HandleMacroExit(); - - virtual void CheckForValidSection(); + virtual void checkForValidSection(); /// } private: @@ -236,11 +238,51 @@ private: void EatToEndOfLine(); bool ParseCppHashLineFilenameComment(const SMLoc &L); + void CheckForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body, + MCAsmMacroParameters Parameters); bool expandMacro(raw_svector_ostream &OS, StringRef Body, const MCAsmMacroParameters &Parameters, const MCAsmMacroArguments &A, const SMLoc &L); + /// \brief Are macros enabled in the parser? + bool MacrosEnabled() {return MacrosEnabledFlag;} + + /// \brief Control a flag in the parser that enables or disables macros. + 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); + + /// \brief Define a new macro with the given name and information. + 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); + + /// \brief Are we inside a macro instantiation? + bool InsideMacroInstantiation() {return !ActiveMacros.empty();} + + /// \brief Handle entry to macro instantiation. + /// + /// \param M The macro. + /// \param NameLoc Instantiation location. + bool HandleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc); + + /// \brief Handle exit from macro instantiation. + void HandleMacroExit(); + + /// \brief Extract AsmTokens for a macro argument. If the argument delimiter + /// is initially unknown, set it to AsmToken::Eof. It will be set to the + /// correct delimiter by the method. + bool ParseMacroArgument(MCAsmMacroArgument &MA, + AsmToken::TokenKind &ArgumentDelimiter); + + /// \brief Parse all macro arguments for a given macro. + bool ParseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A); + void PrintMacroInstantiations(); void PrintMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg, ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) const { @@ -262,12 +304,10 @@ private: /// location. void JumpToLoc(SMLoc Loc, int InBuffer=-1); - bool ParseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A); - /// \brief Parse up to the end of statement and a return the contents from the /// current token until the end of the statement; the current token on exit /// will be either the EndOfStatement or EOF. - virtual StringRef ParseStringToEndOfStatement(); + virtual StringRef parseStringToEndOfStatement(); /// \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. @@ -390,10 +430,7 @@ private: bool ParseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif" bool ParseDirectiveElse(SMLoc DirectiveLoc); // ".else" bool ParseDirectiveEndIf(SMLoc DirectiveLoc); // .endif - - /// ParseEscapedString - Parse the current token as a string which may include - /// escaped characters and return the string contents. - bool ParseEscapedString(std::string &Data); + virtual bool parseEscapedString(std::string &Data); const MCExpr *ApplyModifierToExpr(const MCExpr *E, MCSymbolRefExpr::VariantKind Variant); @@ -407,8 +444,12 @@ private: bool ParseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc" bool ParseDirectiveEndr(SMLoc DirectiveLoc); // ".endr" - // "_emit" - bool ParseDirectiveEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info); + // "_emit" or "__emit" + bool ParseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info, + size_t Len); + + // "align" + bool ParseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info); void initializeDirectiveKindMap(); }; @@ -577,7 +618,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // We had an error, validate that one was emitted and recover by skipping to // the next line. assert(HadError && "Parse statement returned an error, but none emitted!"); - EatToEndOfStatement(); + eatToEndOfStatement(); } if (TheCondState.TheCond != StartingCondState.TheCond || @@ -624,15 +665,15 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { return HadError; } -void AsmParser::CheckForValidSection() { +void AsmParser::checkForValidSection() { if (!ParsingInlineAsm && !getStreamer().getCurrentSection()) { TokError("expected section directive before assembly directive"); Out.InitToTextSection(); } } -/// EatToEndOfStatement - Throw away the rest of the line for testing purposes. -void AsmParser::EatToEndOfStatement() { +/// eatToEndOfStatement - Throw away the rest of the line for testing purposes. +void AsmParser::eatToEndOfStatement() { while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof)) Lex(); @@ -642,7 +683,7 @@ void AsmParser::EatToEndOfStatement() { Lex(); } -StringRef AsmParser::ParseStringToEndOfStatement() { +StringRef AsmParser::parseStringToEndOfStatement() { const char *Start = getTok().getLoc().getPointer(); while (Lexer.isNot(AsmToken::EndOfStatement) && @@ -671,7 +712,7 @@ StringRef AsmParser::ParseStringToComma() { /// parenexpr ::= expr) /// bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) { - if (ParseExpression(Res)) return true; + if (parseExpression(Res)) return true; if (Lexer.isNot(AsmToken::RParen)) return TokError("expected ')' in parentheses expression"); EndLoc = Lexer.getTok().getEndLoc(); @@ -685,7 +726,7 @@ bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) { /// bracketexpr ::= expr] /// bool AsmParser::ParseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) { - if (ParseExpression(Res)) return true; + if (parseExpression(Res)) return true; if (Lexer.isNot(AsmToken::RBrac)) return TokError("expected ']' in brackets expression"); EndLoc = Lexer.getTok().getEndLoc(); @@ -700,7 +741,9 @@ bool AsmParser::ParseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) { /// primaryexpr ::= '.' /// primaryexpr ::= ~,+,- primaryexpr bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { - switch (Lexer.getKind()) { + SMLoc FirstTokenLoc = getLexer().getLoc(); + AsmToken::TokenKind FirstTokenKind = Lexer.getKind(); + switch (FirstTokenKind) { default: return TokError("unknown token in expression"); // If we have an error assume that we've already handled it. @@ -716,8 +759,11 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { case AsmToken::String: case AsmToken::Identifier: { StringRef Identifier; - if (ParseIdentifier(Identifier)) + if (parseIdentifier(Identifier)) { + if (FirstTokenKind == AsmToken::Dollar) + return Error(FirstTokenLoc, "invalid token in expression"); return true; + } EndLoc = SMLoc::getFromPointer(Identifier.end()); @@ -818,9 +864,9 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { } } -bool AsmParser::ParseExpression(const MCExpr *&Res) { +bool AsmParser::parseExpression(const MCExpr *&Res) { SMLoc EndLoc; - return ParseExpression(Res, EndLoc); + return parseExpression(Res, EndLoc); } const MCExpr * @@ -871,7 +917,7 @@ AsmParser::ApplyModifierToExpr(const MCExpr *E, llvm_unreachable("Invalid expression kind!"); } -/// ParseExpression - Parse an expression and return it. +/// parseExpression - Parse an expression and return it. /// /// expr ::= expr &&,|| expr -> lowest. /// expr ::= expr |,^,&,! expr @@ -881,7 +927,7 @@ AsmParser::ApplyModifierToExpr(const MCExpr *E, /// expr ::= expr *,/,% expr -> highest. /// expr ::= primaryexpr /// -bool AsmParser::ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) { +bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) { // Parse the expression. Res = 0; if (ParsePrimaryExpr(Res, EndLoc) || ParseBinOpRHS(1, Res, EndLoc)) @@ -919,17 +965,17 @@ bool AsmParser::ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) { return false; } -bool AsmParser::ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) { +bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) { Res = 0; return ParseParenExpr(Res, EndLoc) || ParseBinOpRHS(1, Res, EndLoc); } -bool AsmParser::ParseAbsoluteExpression(int64_t &Res) { +bool AsmParser::parseAbsoluteExpression(int64_t &Res) { const MCExpr *Expr; SMLoc StartLoc = Lexer.getLoc(); - if (ParseExpression(Expr)) + if (parseExpression(Expr)) return true; if (!Expr->EvaluateAsAbsolute(Res)) @@ -1076,8 +1122,7 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { if (!TheCondState.Ignore) return TokError("unexpected token at start of statement"); IDVal = ""; - } - else { + } else { IDVal = getTok().getString(); Lex(); // Consume the integer token to be used as an identifier token. if (Lexer.getKind() != AsmToken::Colon) { @@ -1085,13 +1130,11 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { return TokError("unexpected token at start of statement"); } } - } else if (Lexer.is(AsmToken::Dot)) { // Treat '.' as a valid identifier in this context. Lex(); IDVal = "."; - - } else if (ParseIdentifier(IDVal)) { + } else if (parseIdentifier(IDVal)) { if (!TheCondState.Ignore) return TokError("unexpected token at start of statement"); IDVal = ""; @@ -1131,9 +1174,10 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { return ParseDirectiveEndIf(IDLoc); } - // If we are in a ".if 0" block, ignore this statement. + // Ignore the statement if in the middle of inactive conditional + // (e.g. ".if 0"). if (TheCondState.Ignore) { - EatToEndOfStatement(); + eatToEndOfStatement(); return false; } @@ -1142,7 +1186,7 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { // See what kind of statement we have. switch (Lexer.getKind()) { case AsmToken::Colon: { - CheckForValidSection(); + checkForValidSection(); // identifier ':' -> Label. Lex(); @@ -1288,7 +1332,7 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { case DK_ZERO: return ParseDirectiveZero(); case DK_EXTERN: - EatToEndOfStatement(); // .extern is the default, ignore it. + eatToEndOfStatement(); // .extern is the default, ignore it. return false; case DK_GLOBL: case DK_GLOBAL: @@ -1407,20 +1451,22 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { return Error(IDLoc, "unknown directive"); } - // _emit - if (ParsingInlineAsm && IDVal == "_emit") - return ParseDirectiveEmit(IDLoc, Info); + // __asm _emit or __asm __emit + if (ParsingInlineAsm && (IDVal == "_emit" || IDVal == "__emit" || + IDVal == "_EMIT" || IDVal == "__EMIT")) + return ParseDirectiveMSEmit(IDLoc, Info, IDVal.size()); - CheckForValidSection(); + // __asm align + if (ParsingInlineAsm && (IDVal == "align" || IDVal == "ALIGN")) + return ParseDirectiveMSAlign(IDLoc, Info); - // Canonicalize the opcode to lower case. - SmallString<128> OpcodeStr; - for (unsigned i = 0, e = IDVal.size(); i != e; ++i) - OpcodeStr.push_back(tolower(IDVal[i])); + checkForValidSection(); + // Canonicalize the opcode to lower case. + std::string OpcodeStr = IDVal.lower(); ParseInstructionInfo IInfo(Info.AsmRewrites); - bool HadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr.str(), - IDLoc,Info.ParsedOperands); + bool HadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, + IDLoc, Info.ParsedOperands); Info.ParseError = HadError; // Dump the parsed representation, if requested. @@ -1444,22 +1490,22 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { if (!HadError && getContext().getGenDwarfForAssembly() && getContext().getGenDwarfSection() == getStreamer().getCurrentSection()) { - unsigned Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer); + 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 std::vector<MCDwarfFile *> &MCDwarfFiles = - getContext().getMCDwarfFiles(); - if (CppHashFilename.size() != 0) { - if(MCDwarfFiles[getContext().getGenDwarfFileNumber()]->getName() != + // 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 std::vector<MCDwarfFile *> &MCDwarfFiles = + getContext().getMCDwarfFiles(); + if (CppHashFilename.size() != 0) { + if (MCDwarfFiles[getContext().getGenDwarfFileNumber()]->getName() != CppHashFilename) - getStreamer().EmitDwarfFileDirective( - getContext().nextGenDwarfFileNumber(), StringRef(), CppHashFilename); + getStreamer().EmitDwarfFileDirective( + getContext().nextGenDwarfFileNumber(), StringRef(), CppHashFilename); unsigned CppHashLocLineNo = SrcMgr.FindLineNumber(CppHashLoc,CppHashBuf); Line = CppHashLineNumber - 1 + (Line - CppHashLocLineNo); - } + } getStreamer().EmitDwarfLocDirective(getContext().getGenDwarfFileNumber(), Line, 0, DWARF2_LINE_DEFAULT_IS_STMT ? @@ -1585,7 +1631,8 @@ void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { // we can't do that. AsmLexer.cpp should probably be changed to handle // '@' as a special case when needed. static bool isIdentifierChar(char c) { - return isalnum(c) || c == '_' || c == '$' || c == '.'; + return isalnum(static_cast<unsigned char>(c)) || c == '_' || c == '$' || + c == '.'; } bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, @@ -1609,7 +1656,8 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, continue; char Next = Body[Pos + 1]; - if (Next == '$' || Next == 'n' || isdigit(Next)) + if (Next == '$' || Next == 'n' || + isdigit(static_cast<unsigned char>(Next))) break; } else { // This macro has parameters, look for \foo, \bar, etc. @@ -1954,7 +2002,7 @@ bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef, SMLoc EqualLoc = Lexer.getLoc(); const MCExpr *Value; - if (ParseExpression(Value)) + if (parseExpression(Value)) return true; // Note: we don't count b as used in "a = b". This is to allow @@ -2011,10 +2059,10 @@ bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef, return false; } -/// ParseIdentifier: +/// parseIdentifier: /// ::= identifier /// ::= string -bool AsmParser::ParseIdentifier(StringRef &Res) { +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) @@ -2057,7 +2105,7 @@ bool AsmParser::ParseIdentifier(StringRef &Res) { bool AsmParser::ParseDirectiveSet(StringRef IDVal, bool allow_redef) { StringRef Name; - if (ParseIdentifier(Name)) + if (parseIdentifier(Name)) return TokError("expected identifier after '" + Twine(IDVal) + "'"); if (getLexer().isNot(AsmToken::Comma)) @@ -2067,7 +2115,7 @@ bool AsmParser::ParseDirectiveSet(StringRef IDVal, bool allow_redef) { return ParseAssignment(Name, allow_redef, true); } -bool AsmParser::ParseEscapedString(std::string &Data) { +bool AsmParser::parseEscapedString(std::string &Data) { assert(getLexer().is(AsmToken::String) && "Unexpected current token!"); Data = ""; @@ -2129,14 +2177,14 @@ bool AsmParser::ParseEscapedString(std::string &Data) { /// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ] bool AsmParser::ParseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) { if (getLexer().isNot(AsmToken::EndOfStatement)) { - CheckForValidSection(); + checkForValidSection(); for (;;) { if (getLexer().isNot(AsmToken::String)) return TokError("expected string in '" + Twine(IDVal) + "' directive"); std::string Data; - if (ParseEscapedString(Data)) + if (parseEscapedString(Data)) return true; getStreamer().EmitBytes(Data, DEFAULT_ADDRSPACE); @@ -2162,12 +2210,12 @@ bool AsmParser::ParseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) { /// ::= (.byte | .short | ... ) [ expression (, expression)* ] bool AsmParser::ParseDirectiveValue(unsigned Size) { if (getLexer().isNot(AsmToken::EndOfStatement)) { - CheckForValidSection(); + checkForValidSection(); for (;;) { const MCExpr *Value; SMLoc ExprLoc = getLexer().getLoc(); - if (ParseExpression(Value)) + if (parseExpression(Value)) return true; // Special case constant expressions to match code generator. @@ -2198,7 +2246,7 @@ bool AsmParser::ParseDirectiveValue(unsigned Size) { /// ::= (.single | .double) [ expression (, expression)* ] bool AsmParser::ParseDirectiveRealValue(const fltSemantics &Semantics) { if (getLexer().isNot(AsmToken::EndOfStatement)) { - CheckForValidSection(); + checkForValidSection(); for (;;) { // We don't truly support arithmetic on floating point expressions, so we @@ -2255,16 +2303,16 @@ bool AsmParser::ParseDirectiveRealValue(const fltSemantics &Semantics) { /// ParseDirectiveZero /// ::= .zero expression bool AsmParser::ParseDirectiveZero() { - CheckForValidSection(); + checkForValidSection(); int64_t NumBytes; - if (ParseAbsoluteExpression(NumBytes)) + if (parseAbsoluteExpression(NumBytes)) return true; int64_t Val = 0; if (getLexer().is(AsmToken::Comma)) { Lex(); - if (ParseAbsoluteExpression(Val)) + if (parseAbsoluteExpression(Val)) return true; } @@ -2281,10 +2329,10 @@ bool AsmParser::ParseDirectiveZero() { /// ParseDirectiveFill /// ::= .fill expression , expression , expression bool AsmParser::ParseDirectiveFill() { - CheckForValidSection(); + checkForValidSection(); int64_t NumValues; - if (ParseAbsoluteExpression(NumValues)) + if (parseAbsoluteExpression(NumValues)) return true; if (getLexer().isNot(AsmToken::Comma)) @@ -2292,7 +2340,7 @@ bool AsmParser::ParseDirectiveFill() { Lex(); int64_t FillSize; - if (ParseAbsoluteExpression(FillSize)) + if (parseAbsoluteExpression(FillSize)) return true; if (getLexer().isNot(AsmToken::Comma)) @@ -2300,7 +2348,7 @@ bool AsmParser::ParseDirectiveFill() { Lex(); int64_t FillExpr; - if (ParseAbsoluteExpression(FillExpr)) + if (parseAbsoluteExpression(FillExpr)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -2320,11 +2368,11 @@ bool AsmParser::ParseDirectiveFill() { /// ParseDirectiveOrg /// ::= .org expression [ , expression ] bool AsmParser::ParseDirectiveOrg() { - CheckForValidSection(); + checkForValidSection(); const MCExpr *Offset; SMLoc Loc = getTok().getLoc(); - if (ParseExpression(Offset)) + if (parseExpression(Offset)) return true; // Parse optional fill expression. @@ -2334,7 +2382,7 @@ bool AsmParser::ParseDirectiveOrg() { return TokError("unexpected token in '.org' directive"); Lex(); - if (ParseAbsoluteExpression(FillExpr)) + if (parseAbsoluteExpression(FillExpr)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -2355,11 +2403,11 @@ bool AsmParser::ParseDirectiveOrg() { /// ParseDirectiveAlign /// ::= {.align, ...} expression [ , expression [ , expression ]] bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { - CheckForValidSection(); + checkForValidSection(); SMLoc AlignmentLoc = getLexer().getLoc(); int64_t Alignment; - if (ParseAbsoluteExpression(Alignment)) + if (parseAbsoluteExpression(Alignment)) return true; SMLoc MaxBytesLoc; @@ -2376,7 +2424,7 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { // .align 3,,4 if (getLexer().isNot(AsmToken::Comma)) { HasFillExpr = true; - if (ParseAbsoluteExpression(FillExpr)) + if (parseAbsoluteExpression(FillExpr)) return true; } @@ -2386,7 +2434,7 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { Lex(); MaxBytesLoc = getLexer().getLoc(); - if (ParseAbsoluteExpression(MaxBytesToFill)) + if (parseAbsoluteExpression(MaxBytesToFill)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -2408,6 +2456,10 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { } Alignment = 1ULL << Alignment; + } else { + // Reject alignments that aren't a power of two, for gas compatibility. + if (!isPowerOf2_64(Alignment)) + Error(AlignmentLoc, "alignment must be a power of 2"); } // Diagnose non-sensical max bytes to align. @@ -2556,7 +2608,7 @@ bool AsmParser::ParseDirectiveLoc() { StringRef Name; SMLoc Loc = getTok().getLoc(); - if (ParseIdentifier(Name)) + if (parseIdentifier(Name)) return TokError("unexpected token in '.loc' directive"); if (Name == "basic_block") @@ -2568,7 +2620,7 @@ bool AsmParser::ParseDirectiveLoc() { else if (Name == "is_stmt") { Loc = getTok().getLoc(); const MCExpr *Value; - if (ParseExpression(Value)) + if (parseExpression(Value)) return true; // The expression must be the constant 0 or 1. if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { @@ -2587,7 +2639,7 @@ bool AsmParser::ParseDirectiveLoc() { else if (Name == "isa") { Loc = getTok().getLoc(); const MCExpr *Value; - if (ParseExpression(Value)) + if (parseExpression(Value)) return true; // The expression must be a constant greater or equal to 0. if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { @@ -2601,7 +2653,7 @@ bool AsmParser::ParseDirectiveLoc() { } } else if (Name == "discriminator") { - if (ParseAbsoluteExpression(Discriminator)) + if (parseAbsoluteExpression(Discriminator)) return true; } else { @@ -2632,7 +2684,7 @@ bool AsmParser::ParseDirectiveCFISections() { bool EH = false; bool Debug = false; - if (ParseIdentifier(Name)) + if (parseIdentifier(Name)) return TokError("Expected an identifier"); if (Name == ".eh_frame") @@ -2643,7 +2695,7 @@ bool AsmParser::ParseDirectiveCFISections() { if (getLexer().is(AsmToken::Comma)) { Lex(); - if (ParseIdentifier(Name)) + if (parseIdentifier(Name)) return TokError("Expected an identifier"); if (Name == ".eh_frame") @@ -2680,7 +2732,7 @@ bool AsmParser::ParseRegisterOrRegisterNumber(int64_t &Register, return true; Register = getContext().getRegisterInfo().getDwarfRegNum(RegNo, true); } else - return ParseAbsoluteExpression(Register); + return parseAbsoluteExpression(Register); return false; } @@ -2697,7 +2749,7 @@ bool AsmParser::ParseDirectiveCFIDefCfa(SMLoc DirectiveLoc) { Lex(); int64_t Offset = 0; - if (ParseAbsoluteExpression(Offset)) + if (parseAbsoluteExpression(Offset)) return true; getStreamer().EmitCFIDefCfa(Register, Offset); @@ -2708,7 +2760,7 @@ bool AsmParser::ParseDirectiveCFIDefCfa(SMLoc DirectiveLoc) { /// ::= .cfi_def_cfa_offset offset bool AsmParser::ParseDirectiveCFIDefCfaOffset() { int64_t Offset = 0; - if (ParseAbsoluteExpression(Offset)) + if (parseAbsoluteExpression(Offset)) return true; getStreamer().EmitCFIDefCfaOffset(Offset); @@ -2738,7 +2790,7 @@ bool AsmParser::ParseDirectiveCFIRegister(SMLoc DirectiveLoc) { /// ::= .cfi_adjust_cfa_offset adjustment bool AsmParser::ParseDirectiveCFIAdjustCfaOffset() { int64_t Adjustment = 0; - if (ParseAbsoluteExpression(Adjustment)) + if (parseAbsoluteExpression(Adjustment)) return true; getStreamer().EmitCFIAdjustCfaOffset(Adjustment); @@ -2769,7 +2821,7 @@ bool AsmParser::ParseDirectiveCFIOffset(SMLoc DirectiveLoc) { return TokError("unexpected token in directive"); Lex(); - if (ParseAbsoluteExpression(Offset)) + if (parseAbsoluteExpression(Offset)) return true; getStreamer().EmitCFIOffset(Register, Offset); @@ -2789,7 +2841,7 @@ bool AsmParser::ParseDirectiveCFIRelOffset(SMLoc DirectiveLoc) { Lex(); int64_t Offset = 0; - if (ParseAbsoluteExpression(Offset)) + if (parseAbsoluteExpression(Offset)) return true; getStreamer().EmitCFIRelOffset(Register, Offset); @@ -2824,7 +2876,7 @@ static bool isValidEncoding(int64_t Encoding) { /// ::= .cfi_lsda encoding, [symbol_name] bool AsmParser::ParseDirectiveCFIPersonalityOrLsda(bool IsPersonality) { int64_t Encoding = 0; - if (ParseAbsoluteExpression(Encoding)) + if (parseAbsoluteExpression(Encoding)) return true; if (Encoding == dwarf::DW_EH_PE_omit) return false; @@ -2837,7 +2889,7 @@ bool AsmParser::ParseDirectiveCFIPersonalityOrLsda(bool IsPersonality) { Lex(); StringRef Name; - if (ParseIdentifier(Name)) + if (parseIdentifier(Name)) return TokError("expected identifier in directive"); MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); @@ -2891,7 +2943,7 @@ bool AsmParser::ParseDirectiveCFIRestore(SMLoc DirectiveLoc) { bool AsmParser::ParseDirectiveCFIEscape() { std::string Values; int64_t CurrValue; - if (ParseAbsoluteExpression(CurrValue)) + if (parseAbsoluteExpression(CurrValue)) return true; Values.push_back((uint8_t)CurrValue); @@ -2899,7 +2951,7 @@ bool AsmParser::ParseDirectiveCFIEscape() { while (getLexer().is(AsmToken::Comma)) { Lex(); - if (ParseAbsoluteExpression(CurrValue)) + if (parseAbsoluteExpression(CurrValue)) return true; Values.push_back((uint8_t)CurrValue); @@ -2948,7 +3000,7 @@ bool AsmParser::ParseDirectiveMacrosOnOff(StringRef Directive) { /// ::= .macro name [parameters] bool AsmParser::ParseDirectiveMacro(SMLoc DirectiveLoc) { StringRef Name; - if (ParseIdentifier(Name)) + if (parseIdentifier(Name)) return TokError("expected identifier in '.macro' directive"); MCAsmMacroParameters Parameters; @@ -2958,7 +3010,7 @@ bool AsmParser::ParseDirectiveMacro(SMLoc DirectiveLoc) { if (getLexer().isNot(AsmToken::EndOfStatement)) { for (;;) { MCAsmMacroParameter Parameter; - if (ParseIdentifier(Parameter.first)) + if (parseIdentifier(Parameter.first)) return TokError("expected identifier in '.macro' directive"); if (getLexer().is(AsmToken::Equal)) { @@ -3000,7 +3052,7 @@ bool AsmParser::ParseDirectiveMacro(SMLoc DirectiveLoc) { } // Otherwise, scan til the end of the statement. - EatToEndOfStatement(); + eatToEndOfStatement(); } if (LookupMacro(Name)) { @@ -3010,10 +3062,113 @@ bool AsmParser::ParseDirectiveMacro(SMLoc DirectiveLoc) { 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)); return false; } +/// 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 +/// not support named parameters they would be ignored on the macro defintion. +/// But to support both styles of parameters this is not possible so if a macro +/// defintion has named parameters but does not use them and has what appears +/// to be positional parameters, strings like $1, $2, ... and $n, then issue a +/// warning that the positional parameter found in body which have no effect. +/// Hoping the developer will either remove the named parameters from the macro +/// definiton so the positional parameters get used if that was what was +/// intended or change the macro to use the named parameters. It is possible +/// this warning will trigger when the none of the named parameters are used +/// and the strings like $1 are infact to simply to be passed trough unchanged. +void AsmParser::CheckForBadMacro(SMLoc DirectiveLoc, StringRef Name, + StringRef Body, + MCAsmMacroParameters Parameters) { + // If this macro is not defined with named parameters the warning we are + // checking for here doesn't apply. + unsigned NParameters = Parameters.size(); + if (NParameters == 0) + return; + + bool NamedParametersFound = false; + bool PositionalParametersFound = false; + + // Look at the body of the macro for use of both the named parameters and what + // are likely to be positional parameters. This is what expandMacro() is + // doing when it finds the parameters in the body. + while (!Body.empty()) { + // Scan for the next possible parameter. + std::size_t End = Body.size(), Pos = 0; + for (; Pos != End; ++Pos) { + // Check for a substitution or escape. + // This macro is defined with parameters, look for \foo, \bar, etc. + if (Body[Pos] == '\\' && Pos + 1 != End) + break; + + // This macro should have parameters, but look for $0, $1, ..., $n too. + if (Body[Pos] != '$' || Pos + 1 == End) + continue; + char Next = Body[Pos + 1]; + if (Next == '$' || Next == 'n' || + isdigit(static_cast<unsigned char>(Next))) + break; + } + + // Check if we reached the end. + if (Pos == End) + break; + + if (Body[Pos] == '$') { + switch (Body[Pos+1]) { + // $$ => $ + case '$': + break; + + // $n => number of arguments + case 'n': + PositionalParametersFound = true; + break; + + // $[0-9] => argument + default: { + PositionalParametersFound = true; + break; + } + } + Pos += 2; + } else { + unsigned I = Pos + 1; + while (isIdentifierChar(Body[I]) && I + 1 != End) + ++I; + + 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; + } + } else { + NamedParametersFound = true; + Pos += 1 + Argument.size(); + } + } + // Update the scan point. + Body = Body.substr(Pos); + } + + if (!NamedParametersFound && PositionalParametersFound) + Warning(DirectiveLoc, "macro defined with named parameters which are not " + "used in macro body, possible positional parameter " + "found in body which will have no effect"); +} + /// ParseDirectiveEndMacro /// ::= .endm /// ::= .endmacro @@ -3038,7 +3193,7 @@ bool AsmParser::ParseDirectiveEndMacro(StringRef Directive) { /// ::= .purgem bool AsmParser::ParseDirectivePurgeMacro(SMLoc DirectiveLoc) { StringRef Name; - if (ParseIdentifier(Name)) + if (parseIdentifier(Name)) return TokError("expected identifier in '.purgem' directive"); if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -3054,13 +3209,13 @@ bool AsmParser::ParseDirectivePurgeMacro(SMLoc DirectiveLoc) { /// ParseDirectiveBundleAlignMode /// ::= {.bundle_align_mode} expression bool AsmParser::ParseDirectiveBundleAlignMode() { - CheckForValidSection(); + checkForValidSection(); // Expect a single argument: an expression that evaluates to a constant // in the inclusive range 0-30. SMLoc ExprLoc = getLexer().getLoc(); int64_t AlignSizePow2; - if (ParseAbsoluteExpression(AlignSizePow2)) + if (parseAbsoluteExpression(AlignSizePow2)) return true; else if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token after expression in" @@ -3080,7 +3235,7 @@ bool AsmParser::ParseDirectiveBundleAlignMode() { /// ParseDirectiveBundleLock /// ::= {.bundle_lock} [align_to_end] bool AsmParser::ParseDirectiveBundleLock() { - CheckForValidSection(); + checkForValidSection(); bool AlignToEnd = false; if (getLexer().isNot(AsmToken::EndOfStatement)) { @@ -3089,7 +3244,7 @@ bool AsmParser::ParseDirectiveBundleLock() { const char *kInvalidOptionError = "invalid option for '.bundle_lock' directive"; - if (ParseIdentifier(Option)) + if (parseIdentifier(Option)) return Error(Loc, kInvalidOptionError); if (Option != "align_to_end") @@ -3109,7 +3264,7 @@ bool AsmParser::ParseDirectiveBundleLock() { /// ParseDirectiveBundleLock /// ::= {.bundle_lock} bool AsmParser::ParseDirectiveBundleUnlock() { - CheckForValidSection(); + checkForValidSection(); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.bundle_unlock' directive"); @@ -3122,10 +3277,10 @@ bool AsmParser::ParseDirectiveBundleUnlock() { /// ParseDirectiveSpace /// ::= (.skip | .space) expression [ , expression ] bool AsmParser::ParseDirectiveSpace(StringRef IDVal) { - CheckForValidSection(); + checkForValidSection(); int64_t NumBytes; - if (ParseAbsoluteExpression(NumBytes)) + if (parseAbsoluteExpression(NumBytes)) return true; int64_t FillExpr = 0; @@ -3134,7 +3289,7 @@ bool AsmParser::ParseDirectiveSpace(StringRef IDVal) { return TokError("unexpected token in '" + Twine(IDVal) + "' directive"); Lex(); - if (ParseAbsoluteExpression(FillExpr)) + if (parseAbsoluteExpression(FillExpr)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -3156,10 +3311,10 @@ bool AsmParser::ParseDirectiveSpace(StringRef IDVal) { /// ParseDirectiveLEB128 /// ::= (.sleb128 | .uleb128) expression bool AsmParser::ParseDirectiveLEB128(bool Signed) { - CheckForValidSection(); + checkForValidSection(); const MCExpr *Value; - if (ParseExpression(Value)) + if (parseExpression(Value)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -3181,7 +3336,7 @@ bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) { StringRef Name; SMLoc Loc = getTok().getLoc(); - if (ParseIdentifier(Name)) + if (parseIdentifier(Name)) return Error(Loc, "expected identifier in directive"); MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); @@ -3208,11 +3363,11 @@ bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) { /// ParseDirectiveComm /// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ] bool AsmParser::ParseDirectiveComm(bool IsLocal) { - CheckForValidSection(); + checkForValidSection(); SMLoc IDLoc = getLexer().getLoc(); StringRef Name; - if (ParseIdentifier(Name)) + if (parseIdentifier(Name)) return TokError("expected identifier in directive"); // Handle the identifier as the key symbol. @@ -3224,7 +3379,7 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) { int64_t Size; SMLoc SizeLoc = getLexer().getLoc(); - if (ParseAbsoluteExpression(Size)) + if (parseAbsoluteExpression(Size)) return true; int64_t Pow2Alignment = 0; @@ -3232,7 +3387,7 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) { if (getLexer().is(AsmToken::Comma)) { Lex(); Pow2AlignmentLoc = getLexer().getLoc(); - if (ParseAbsoluteExpression(Pow2Alignment)) + if (parseAbsoluteExpression(Pow2Alignment)) return true; LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType(); @@ -3285,7 +3440,7 @@ bool AsmParser::ParseDirectiveAbort() { // FIXME: Use loc from directive. SMLoc Loc = getLexer().getLoc(); - StringRef Str = ParseStringToEndOfStatement(); + StringRef Str = parseStringToEndOfStatement(); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.abort' directive"); @@ -3357,10 +3512,10 @@ bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) { TheCondStack.push_back(TheCondState); TheCondState.TheCond = AsmCond::IfCond; if (TheCondState.Ignore) { - EatToEndOfStatement(); + eatToEndOfStatement(); } else { int64_t ExprValue; - if (ParseAbsoluteExpression(ExprValue)) + if (parseAbsoluteExpression(ExprValue)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -3382,9 +3537,9 @@ bool AsmParser::ParseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) { TheCondState.TheCond = AsmCond::IfCond; if (TheCondState.Ignore) { - EatToEndOfStatement(); + eatToEndOfStatement(); } else { - StringRef Str = ParseStringToEndOfStatement(); + StringRef Str = parseStringToEndOfStatement(); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.ifb' directive"); @@ -3405,7 +3560,7 @@ bool AsmParser::ParseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) { TheCondState.TheCond = AsmCond::IfCond; if (TheCondState.Ignore) { - EatToEndOfStatement(); + eatToEndOfStatement(); } else { StringRef Str1 = ParseStringToComma(); @@ -3414,7 +3569,7 @@ bool AsmParser::ParseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) { Lex(); - StringRef Str2 = ParseStringToEndOfStatement(); + StringRef Str2 = parseStringToEndOfStatement(); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.ifc' directive"); @@ -3436,9 +3591,9 @@ bool AsmParser::ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { TheCondState.TheCond = AsmCond::IfCond; if (TheCondState.Ignore) { - EatToEndOfStatement(); + eatToEndOfStatement(); } else { - if (ParseIdentifier(Name)) + if (parseIdentifier(Name)) return TokError("expected identifier after '.ifdef'"); Lex(); @@ -3469,11 +3624,11 @@ bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) { LastIgnoreState = TheCondStack.back().Ignore; if (LastIgnoreState || TheCondState.CondMet) { TheCondState.Ignore = true; - EatToEndOfStatement(); + eatToEndOfStatement(); } else { int64_t ExprValue; - if (ParseAbsoluteExpression(ExprValue)) + if (parseAbsoluteExpression(ExprValue)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -3667,7 +3822,7 @@ MCAsmMacro *AsmParser::ParseMacroLikeBody(SMLoc DirectiveLoc) { } // Otherwise, scan till the end of the statement. - EatToEndOfStatement(); + eatToEndOfStatement(); } const char *BodyStart = StartToken.getLoc().getPointer(); @@ -3703,7 +3858,7 @@ void AsmParser::InstantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, bool AsmParser::ParseDirectiveRept(SMLoc DirectiveLoc) { int64_t Count; - if (ParseAbsoluteExpression(Count)) + if (parseAbsoluteExpression(Count)) return TokError("unexpected token in '.rept' directive"); if (Count < 0) @@ -3741,7 +3896,7 @@ bool AsmParser::ParseDirectiveIrp(SMLoc DirectiveLoc) { MCAsmMacroParameters Parameters; MCAsmMacroParameter Parameter; - if (ParseIdentifier(Parameter.first)) + if (parseIdentifier(Parameter.first)) return TokError("expected identifier in '.irp' directive"); Parameters.push_back(Parameter); @@ -3787,7 +3942,7 @@ bool AsmParser::ParseDirectiveIrpc(SMLoc DirectiveLoc) { MCAsmMacroParameters Parameters; MCAsmMacroParameter Parameter; - if (ParseIdentifier(Parameter.first)) + if (parseIdentifier(Parameter.first)) return TokError("expected identifier in '.irpc' directive"); Parameters.push_back(Parameter); @@ -3847,10 +4002,11 @@ bool AsmParser::ParseDirectiveEndr(SMLoc DirectiveLoc) { return false; } -bool AsmParser::ParseDirectiveEmit(SMLoc IDLoc, ParseStatementInfo &Info) { +bool AsmParser::ParseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info, + size_t Len) { const MCExpr *Value; SMLoc ExprLoc = getLexer().getLoc(); - if (ParseExpression(Value)) + if (parseExpression(Value)) return true; const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value); if (!MCE) @@ -3859,27 +4015,71 @@ bool AsmParser::ParseDirectiveEmit(SMLoc IDLoc, ParseStatementInfo &Info) { if (!isUIntN(8, IntValue) && !isIntN(8, IntValue)) return Error(ExprLoc, "literal value out of range for directive"); - Info.AsmRewrites->push_back(AsmRewrite(AOK_Emit, IDLoc, 5)); + Info.AsmRewrites->push_back(AsmRewrite(AOK_Emit, IDLoc, Len)); return false; } -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::ParseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) { + const MCExpr *Value; + SMLoc ExprLoc = getLexer().getLoc(); + if (parseExpression(Value)) + return true; + const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value); + if (!MCE) + return Error(ExprLoc, "unexpected expression in align"); + uint64_t IntValue = MCE->getValue(); + 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))); + 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); + if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer()) + return -1; + if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer()) + return 1; + + // It's possible to have a SizeDirective rewrite and an Input/Output rewrite + // to the same location. Make sure the SizeDirective rewrite is performed + // first. This also ensure the sort algorithm is stable. + if (AsmRewriteA->Kind == AOK_SizeDirective) { + assert ((AsmRewriteB->Kind == AOK_Input || AsmRewriteB->Kind == AOK_Output) && + "Expected an Input/Output rewrite!"); + return -1; + } + if (AsmRewriteB->Kind == AOK_SizeDirective) { + assert ((AsmRewriteA->Kind == AOK_Input || AsmRewriteA->Kind == AOK_Output) && + "Expected an Input/Output rewrite!"); + return 1; + } + 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) { SmallVector<void *, 4> InputDecls; SmallVector<void *, 4> OutputDecls; SmallVector<bool, 4> InputDeclsAddressOf; SmallVector<bool, 4> OutputDeclsAddressOf; SmallVector<std::string, 4> InputConstraints; SmallVector<std::string, 4> OutputConstraints; - std::set<std::string> ClobberRegs; + SmallVector<unsigned, 4> ClobberRegs; - SmallVector<struct AsmRewrite, 4> AsmStrRewrites; + SmallVector<AsmRewrite, 4> AsmStrRewrites; // Prime the lexer. Lex(); @@ -3895,65 +4095,60 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, if (Info.ParseError) return true; - if (Info.Opcode != ~0U) { - const MCInstrDesc &Desc = MII->get(Info.Opcode); + if (Info.Opcode == ~0U) + continue; - // Build the list of clobbers, outputs and inputs. - for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) { - MCParsedAsmOperand *Operand = Info.ParsedOperands[i]; + const MCInstrDesc &Desc = MII->get(Info.Opcode); - // Immediate. - if (Operand->isImm()) { - if (Operand->needAsmRewrite()) - AsmStrRewrites.push_back(AsmRewrite(AOK_ImmPrefix, - Operand->getStartLoc())); - continue; - } + // Build the list of clobbers, outputs and inputs. + for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) { + MCParsedAsmOperand *Operand = Info.ParsedOperands[i]; - // Register operand. - if (Operand->isReg() && !Operand->needAddressOf()) { - unsigned NumDefs = Desc.getNumDefs(); - // Clobber. - if (NumDefs && Operand->getMCOperandNum() < NumDefs) { - std::string Reg; - raw_string_ostream OS(Reg); - IP->printRegName(OS, Operand->getReg()); - ClobberRegs.insert(StringRef(OS.str())); - } - continue; - } + // Immediate. + if (Operand->isImm()) { + if (Operand->needAsmRewrite()) + AsmStrRewrites.push_back(AsmRewrite(AOK_ImmPrefix, + Operand->getStartLoc())); + continue; + } - // Expr/Input or Output. - unsigned Size; - bool IsVarDecl; - void *OpDecl = SI.LookupInlineAsmIdentifier(Operand->getName(), AsmLoc, - Size, IsVarDecl); - if (OpDecl) { - bool isOutput = (i == 1) && Desc.mayStore(); - if (Operand->isMem() && Operand->needSizeDirective()) - AsmStrRewrites.push_back(AsmRewrite(AOK_SizeDirective, - Operand->getStartLoc(), - /*Len*/0, - Operand->getMemSize())); - if (isOutput) { - std::string Constraint = "="; - ++InputIdx; - OutputDecls.push_back(OpDecl); - OutputDeclsAddressOf.push_back(Operand->needAddressOf()); - Constraint += Operand->getConstraint().str(); - OutputConstraints.push_back(Constraint); - AsmStrRewrites.push_back(AsmRewrite(AOK_Output, - Operand->getStartLoc(), - Operand->getNameLen())); - } else { - InputDecls.push_back(OpDecl); - InputDeclsAddressOf.push_back(Operand->needAddressOf()); - InputConstraints.push_back(Operand->getConstraint().str()); - AsmStrRewrites.push_back(AsmRewrite(AOK_Input, - Operand->getStartLoc(), - Operand->getNameLen())); - } - } + // Register operand. + if (Operand->isReg() && !Operand->needAddressOf()) { + unsigned NumDefs = Desc.getNumDefs(); + // Clobber. + if (NumDefs && Operand->getMCOperandNum() < NumDefs) + ClobberRegs.push_back(Operand->getReg()); + continue; + } + + // Expr/Input or Output. + bool IsVarDecl; + unsigned Length, Size, Type; + void *OpDecl = SI.LookupInlineAsmIdentifier(Operand->getName(), AsmLoc, + Length, Size, Type, + IsVarDecl); + if (!OpDecl) + continue; + + bool isOutput = (i == 1) && Desc.mayStore(); + if (Operand->isMem() && Operand->needSizeDirective()) + AsmStrRewrites.push_back(AsmRewrite(AOK_SizeDirective, + Operand->getStartLoc(), /*Len*/0, + Operand->getMemSize())); + + if (isOutput) { + ++InputIdx; + OutputDecls.push_back(OpDecl); + OutputDeclsAddressOf.push_back(Operand->needAddressOf()); + OutputConstraints.push_back('=' + Operand->getConstraint().str()); + AsmStrRewrites.push_back(AsmRewrite(AOK_Output, Operand->getStartLoc(), + Operand->getNameLen())); + } else { + InputDecls.push_back(OpDecl); + InputDeclsAddressOf.push_back(Operand->needAddressOf()); + InputConstraints.push_back(Operand->getConstraint().str()); + AsmStrRewrites.push_back(AsmRewrite(AOK_Input, Operand->getStartLoc(), + Operand->getNameLen())); } } } @@ -3963,9 +4158,14 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, NumInputs = InputDecls.size(); // Set the unique clobbers. - for (std::set<std::string>::iterator I = ClobberRegs.begin(), - E = ClobberRegs.end(); I != E; ++I) - Clobbers.push_back(*I); + array_pod_sort(ClobberRegs.begin(), ClobberRegs.end()); + ClobberRegs.erase(std::unique(ClobberRegs.begin(), ClobberRegs.end()), + ClobberRegs.end()); + Clobbers.assign(ClobberRegs.size(), std::string()); + for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) { + raw_string_ostream OS(Clobbers[I]); + IP->printRegName(OS, ClobberRegs[I]); + } // Merge the various outputs and inputs. Output are expected first. if (NumOutputs || NumInputs) { @@ -3987,10 +4187,14 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, AsmRewriteKind PrevKind = AOK_Imm; raw_string_ostream OS(AsmStringIR); const char *Start = SrcMgr.getMemoryBuffer(0)->getBufferStart(); - for (SmallVectorImpl<struct AsmRewrite>::iterator - I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) { + array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), RewritesSort); + for (SmallVectorImpl<AsmRewrite>::iterator I = AsmStrRewrites.begin(), + E = AsmStrRewrites.end(); + I != E; ++I) { const char *Loc = (*I).Loc.getPointer(); + assert(Loc >= Start && "Expected Loc to be after Start!"); + unsigned AdditionalSkip = 0; AsmRewriteKind Kind = (*I).Kind; // Emit everything up to the immediate/expression. If the previous rewrite @@ -4009,22 +4213,19 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, switch (Kind) { default: break; case AOK_Imm: - OS << Twine("$$"); - OS << (*I).Val; + OS << "$$" << (*I).Val; break; case AOK_ImmPrefix: - OS << Twine("$$"); + OS << "$$"; break; case AOK_Input: - OS << '$'; - OS << InputIdx++; + OS << '$' << InputIdx++; break; case AOK_Output: - OS << '$'; - OS << OutputIdx++; + OS << '$' << OutputIdx++; break; case AOK_SizeDirective: - switch((*I).Val) { + switch ((*I).Val) { default: break; case 8: OS << "byte ptr "; break; case 16: OS << "word ptr "; break; @@ -4038,6 +4239,15 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, case AOK_Emit: OS << ".byte"; break; + case AOK_Align: { + unsigned Val = (*I).Val; + OS << ".align " << Val; + + // Skip the original immediate. + assert(Val < 10 && "Expected alignment less then 2^10."); + AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4; + break; + } case AOK_DotOperator: OS << (*I).Val; break; @@ -4045,7 +4255,7 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, // Skip the original expression. if (Kind != AOK_SizeDirective) - Start = Loc + (*I).Len; + Start = Loc + (*I).Len + AdditionalSkip; } // Emit the remainder of the asm string. diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp index e7c564a243..a50eab217d 100644 --- a/lib/MC/MCParser/COFFAsmParser.cpp +++ b/lib/MC/MCParser/COFFAsmParser.cpp @@ -24,10 +24,11 @@ using namespace llvm; namespace { class COFFAsmParser : public MCAsmParserExtension { - template<bool (COFFAsmParser::*Handler)(StringRef, SMLoc)> - void AddDirectiveHandler(StringRef Directive) { - getParser().AddDirectiveHandler(this, Directive, - HandleDirective<COFFAsmParser, Handler>); + template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)> + void addDirectiveHandler(StringRef Directive) { + MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( + this, HandleDirective<COFFAsmParser, HandlerMethod>); + getParser().addDirectiveHandler(Directive, Handler); } bool ParseSectionSwitch(StringRef Section, @@ -38,43 +39,43 @@ class COFFAsmParser : public MCAsmParserExtension { // Call the base implementation. MCAsmParserExtension::Initialize(Parser); - AddDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text"); - AddDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data"); - AddDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss"); - AddDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def"); - AddDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl"); - AddDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type"); - AddDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef"); - AddDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32"); + addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text"); + addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data"); + addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32"); // Win64 EH directives. - AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>( + addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>( ".seh_proc"); - AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>( + addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>( ".seh_endproc"); - AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>( + addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>( ".seh_startchained"); - AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>( + addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>( ".seh_endchained"); - AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>( + addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>( ".seh_handler"); - AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>( + addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>( ".seh_handlerdata"); - AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>( + addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>( ".seh_pushreg"); - AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>( + addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>( ".seh_setframe"); - AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>( + addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>( ".seh_stackalloc"); - AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>( + addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>( ".seh_savereg"); - AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>( + addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>( ".seh_savexmm"); - AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>( + addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>( ".seh_pushframe"); - AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>( + addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>( ".seh_endprologue"); - AddDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak"); } bool ParseSectionDirectiveText(StringRef, SMLoc) { @@ -140,7 +141,7 @@ bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { for (;;) { StringRef Name; - if (getParser().ParseIdentifier(Name)) + if (getParser().parseIdentifier(Name)) return TokError("expected identifier in directive"); MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); @@ -176,7 +177,7 @@ bool COFFAsmParser::ParseSectionSwitch(StringRef Section, bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) { StringRef SymbolName; - if (getParser().ParseIdentifier(SymbolName)) + if (getParser().parseIdentifier(SymbolName)) return TokError("expected identifier in directive"); MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName); @@ -189,7 +190,7 @@ bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) { bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) { int64_t SymbolStorageClass; - if (getParser().ParseAbsoluteExpression(SymbolStorageClass)) + if (getParser().parseAbsoluteExpression(SymbolStorageClass)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -202,7 +203,7 @@ bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) { bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) { int64_t Type; - if (getParser().ParseAbsoluteExpression(Type)) + if (getParser().parseAbsoluteExpression(Type)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -221,7 +222,7 @@ bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) { bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) { StringRef SymbolID; - if (getParser().ParseIdentifier(SymbolID)) + if (getParser().parseIdentifier(SymbolID)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -236,7 +237,7 @@ bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) { bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) { StringRef SymbolID; - if (getParser().ParseIdentifier(SymbolID)) + if (getParser().parseIdentifier(SymbolID)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -269,7 +270,7 @@ bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) { bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) { StringRef SymbolID; - if (getParser().ParseIdentifier(SymbolID)) + if (getParser().parseIdentifier(SymbolID)) return true; if (getLexer().isNot(AsmToken::Comma)) @@ -322,7 +323,7 @@ bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) { Lex(); SMLoc startLoc = getLexer().getLoc(); - if (getParser().ParseAbsoluteExpression(Off)) + if (getParser().parseAbsoluteExpression(Off)) return true; if (Off & 0x0F) @@ -339,7 +340,7 @@ bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) { bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) { int64_t Size; SMLoc startLoc = getLexer().getLoc(); - if (getParser().ParseAbsoluteExpression(Size)) + if (getParser().parseAbsoluteExpression(Size)) return true; if (Size & 7) @@ -363,7 +364,7 @@ bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) { Lex(); SMLoc startLoc = getLexer().getLoc(); - if (getParser().ParseAbsoluteExpression(Off)) + if (getParser().parseAbsoluteExpression(Off)) return true; if (Off & 7) @@ -390,7 +391,7 @@ bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) { Lex(); SMLoc startLoc = getLexer().getLoc(); - if (getParser().ParseAbsoluteExpression(Off)) + if (getParser().parseAbsoluteExpression(Off)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -411,7 +412,7 @@ bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) { if (getLexer().is(AsmToken::At)) { SMLoc startLoc = getLexer().getLoc(); Lex(); - if (!getParser().ParseIdentifier(CodeID)) { + if (!getParser().parseIdentifier(CodeID)) { if (CodeID != "code") return Error(startLoc, "expected @code"); Code = true; @@ -438,7 +439,7 @@ bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) { return TokError("a handler attribute must begin with '@'"); SMLoc startLoc = getLexer().getLoc(); Lex(); - if (getParser().ParseIdentifier(identifier)) + if (getParser().parseIdentifier(identifier)) return Error(startLoc, "expected @unwind or @except"); if (identifier == "unwind") unwind = true; @@ -479,7 +480,7 @@ bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) { } else { int64_t n; - if (getParser().ParseAbsoluteExpression(n)) + if (getParser().parseAbsoluteExpression(n)) return true; if (n > 15) return Error(startLoc, "register number is too high"); diff --git a/lib/MC/MCParser/DarwinAsmParser.cpp b/lib/MC/MCParser/DarwinAsmParser.cpp index 7b042df292..6d6409fb69 100644 --- a/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/lib/MC/MCParser/DarwinAsmParser.cpp @@ -26,10 +26,11 @@ namespace { /// \brief Implementation of directive handling which is shared across all /// Darwin targets. class DarwinAsmParser : public MCAsmParserExtension { - template<bool (DarwinAsmParser::*Handler)(StringRef, SMLoc)> - void AddDirectiveHandler(StringRef Directive) { - getParser().AddDirectiveHandler(this, Directive, - HandleDirective<DarwinAsmParser, Handler>); + template<bool (DarwinAsmParser::*HandlerMethod)(StringRef, SMLoc)> + void addDirectiveHandler(StringRef Directive) { + MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( + this, HandleDirective<DarwinAsmParser, HandlerMethod>); + getParser().addDirectiveHandler(Directive, Handler); } bool ParseSectionSwitch(const char *Segment, const char *Section, @@ -43,77 +44,128 @@ public: // Call the base implementation. this->MCAsmParserExtension::Initialize(Parser); - AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDesc>(".desc"); - AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveLsym>(".lsym"); - AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveSubsectionsViaSymbols>( + addDirectiveHandler<&DarwinAsmParser::ParseDirectiveDesc>(".desc"); + addDirectiveHandler<&DarwinAsmParser::ParseDirectiveLsym>(".lsym"); + addDirectiveHandler<&DarwinAsmParser::ParseDirectiveSubsectionsViaSymbols>( ".subsections_via_symbols"); - AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDumpOrLoad>(".dump"); - AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDumpOrLoad>(".load"); - AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveSection>(".section"); - AddDirectiveHandler<&DarwinAsmParser::ParseDirectivePushSection>(".pushsection"); - AddDirectiveHandler<&DarwinAsmParser::ParseDirectivePopSection>(".popsection"); - AddDirectiveHandler<&DarwinAsmParser::ParseDirectivePrevious>(".previous"); - AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveSecureLogUnique>( + addDirectiveHandler<&DarwinAsmParser::ParseDirectiveDumpOrLoad>(".dump"); + addDirectiveHandler<&DarwinAsmParser::ParseDirectiveDumpOrLoad>(".load"); + addDirectiveHandler<&DarwinAsmParser::ParseDirectiveSection>(".section"); + addDirectiveHandler<&DarwinAsmParser::ParseDirectivePushSection>( + ".pushsection"); + addDirectiveHandler<&DarwinAsmParser::ParseDirectivePopSection>( + ".popsection"); + addDirectiveHandler<&DarwinAsmParser::ParseDirectivePrevious>(".previous"); + addDirectiveHandler<&DarwinAsmParser::ParseDirectiveSecureLogUnique>( ".secure_log_unique"); - AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveSecureLogReset>( + addDirectiveHandler<&DarwinAsmParser::ParseDirectiveSecureLogReset>( ".secure_log_reset"); - AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveTBSS>(".tbss"); - AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveZerofill>(".zerofill"); + addDirectiveHandler<&DarwinAsmParser::ParseDirectiveTBSS>(".tbss"); + addDirectiveHandler<&DarwinAsmParser::ParseDirectiveZerofill>(".zerofill"); - AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDataRegion>(".data_region"); - AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDataRegionEnd>(".end_data_region"); + addDirectiveHandler<&DarwinAsmParser::ParseDirectiveDataRegion>( + ".data_region"); + addDirectiveHandler<&DarwinAsmParser::ParseDirectiveDataRegionEnd>( + ".end_data_region"); // Special section directives. - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConst>(".const"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConstData>(".const_data"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConstructor>(".constructor"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveCString>(".cstring"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveData>(".data"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveDestructor>(".destructor"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveDyld>(".dyld"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveFVMLibInit0>(".fvmlib_init0"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveFVMLibInit1>(".fvmlib_init1"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveLazySymbolPointers>(".lazy_symbol_pointer"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveLiteral16>(".literal16"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveLiteral4>(".literal4"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveLiteral8>(".literal8"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveModInitFunc>(".mod_init_func"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveModTermFunc>(".mod_term_func"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveNonLazySymbolPointers>(".non_lazy_symbol_pointer"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCCatClsMeth>(".objc_cat_cls_meth"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCCatInstMeth>(".objc_cat_inst_meth"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCCategory>(".objc_category"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClass>(".objc_class"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClassNames>(".objc_class_names"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClassVars>(".objc_class_vars"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClsMeth>(".objc_cls_meth"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClsRefs>(".objc_cls_refs"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCInstMeth>(".objc_inst_meth"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCInstanceVars>(".objc_instance_vars"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCMessageRefs>(".objc_message_refs"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCMetaClass>(".objc_meta_class"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCMethVarNames>(".objc_meth_var_names"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCMethVarTypes>(".objc_meth_var_types"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCModuleInfo>(".objc_module_info"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCProtocol>(".objc_protocol"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCSelectorStrs>(".objc_selector_strs"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCStringObject>(".objc_string_object"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCSymbols>(".objc_symbols"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectivePICSymbolStub>(".picsymbol_stub"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveStaticConst>(".static_const"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveStaticData>(".static_data"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveSymbolStub>(".symbol_stub"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveTData>(".tdata"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveText>(".text"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveThreadInitFunc>(".thread_init_func"); - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveTLV>(".tlv"); - - AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveIdent>(".ident"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConst>(".const"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConstData>( + ".const_data"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConstructor>( + ".constructor"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveCString>( + ".cstring"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveData>(".data"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveDestructor>( + ".destructor"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveDyld>(".dyld"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveFVMLibInit0>( + ".fvmlib_init0"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveFVMLibInit1>( + ".fvmlib_init1"); + addDirectiveHandler< + &DarwinAsmParser::ParseSectionDirectiveLazySymbolPointers>( + ".lazy_symbol_pointer"); + addDirectiveHandler<&DarwinAsmParser::ParseDirectiveLinkerOption>( + ".linker_option"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveLiteral16>( + ".literal16"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveLiteral4>( + ".literal4"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveLiteral8>( + ".literal8"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveModInitFunc>( + ".mod_init_func"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveModTermFunc>( + ".mod_term_func"); + addDirectiveHandler< + &DarwinAsmParser::ParseSectionDirectiveNonLazySymbolPointers>( + ".non_lazy_symbol_pointer"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCCatClsMeth>( + ".objc_cat_cls_meth"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCCatInstMeth>( + ".objc_cat_inst_meth"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCCategory>( + ".objc_category"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClass>( + ".objc_class"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClassNames>( + ".objc_class_names"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClassVars>( + ".objc_class_vars"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClsMeth>( + ".objc_cls_meth"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClsRefs>( + ".objc_cls_refs"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCInstMeth>( + ".objc_inst_meth"); + addDirectiveHandler< + &DarwinAsmParser::ParseSectionDirectiveObjCInstanceVars>( + ".objc_instance_vars"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCMessageRefs>( + ".objc_message_refs"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCMetaClass>( + ".objc_meta_class"); + addDirectiveHandler< + &DarwinAsmParser::ParseSectionDirectiveObjCMethVarNames>( + ".objc_meth_var_names"); + addDirectiveHandler< + &DarwinAsmParser::ParseSectionDirectiveObjCMethVarTypes>( + ".objc_meth_var_types"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCModuleInfo>( + ".objc_module_info"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCProtocol>( + ".objc_protocol"); + addDirectiveHandler< + &DarwinAsmParser::ParseSectionDirectiveObjCSelectorStrs>( + ".objc_selector_strs"); + addDirectiveHandler< + &DarwinAsmParser::ParseSectionDirectiveObjCStringObject>( + ".objc_string_object"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCSymbols>( + ".objc_symbols"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectivePICSymbolStub>( + ".picsymbol_stub"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveStaticConst>( + ".static_const"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveStaticData>( + ".static_data"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveSymbolStub>( + ".symbol_stub"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveTData>(".tdata"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveText>(".text"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveThreadInitFunc>( + ".thread_init_func"); + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveTLV>(".tlv"); + + addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveIdent>(".ident"); } bool ParseDirectiveDesc(StringRef, SMLoc); bool ParseDirectiveDumpOrLoad(StringRef, SMLoc); bool ParseDirectiveLsym(StringRef, SMLoc); + bool ParseDirectiveLinkerOption(StringRef, SMLoc); bool ParseDirectiveSection(StringRef, SMLoc); bool ParseDirectivePushSection(StringRef, SMLoc); bool ParseDirectivePopSection(StringRef, SMLoc); @@ -293,7 +345,7 @@ public: } bool ParseSectionDirectiveIdent(StringRef, SMLoc) { // Darwin silently ignores the .ident directive. - getParser().EatToEndOfStatement(); + getParser().eatToEndOfStatement(); return false; } bool ParseSectionDirectiveThreadInitFunc(StringRef, SMLoc) { @@ -338,7 +390,7 @@ bool DarwinAsmParser::ParseSectionSwitch(const char *Segment, /// ::= .desc identifier , expression bool DarwinAsmParser::ParseDirectiveDesc(StringRef, SMLoc) { StringRef Name; - if (getParser().ParseIdentifier(Name)) + if (getParser().parseIdentifier(Name)) return TokError("expected identifier in directive"); // Handle the identifier as the key symbol. @@ -349,7 +401,7 @@ bool DarwinAsmParser::ParseDirectiveDesc(StringRef, SMLoc) { Lex(); int64_t DescValue; - if (getParser().ParseAbsoluteExpression(DescValue)) + if (getParser().parseAbsoluteExpression(DescValue)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -386,11 +438,38 @@ bool DarwinAsmParser::ParseDirectiveDumpOrLoad(StringRef Directive, return Warning(IDLoc, "ignoring directive .load for now"); } +/// ParseDirectiveLinkerOption +/// ::= .linker_option "string" ( , "string" )* +bool DarwinAsmParser::ParseDirectiveLinkerOption(StringRef IDVal, SMLoc) { + SmallVector<std::string, 4> Args; + for (;;) { + if (getLexer().isNot(AsmToken::String)) + return TokError("expected string in '" + Twine(IDVal) + "' directive"); + + std::string Data; + if (getParser().parseEscapedString(Data)) + return true; + + Args.push_back(Data); + + Lex(); + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in '" + Twine(IDVal) + "' directive"); + Lex(); + } + + getStreamer().EmitLinkerOptions(Args); + return false; +} + /// ParseDirectiveLsym /// ::= .lsym identifier , expression bool DarwinAsmParser::ParseDirectiveLsym(StringRef, SMLoc) { StringRef Name; - if (getParser().ParseIdentifier(Name)) + if (getParser().parseIdentifier(Name)) return TokError("expected identifier in directive"); // Handle the identifier as the key symbol. @@ -401,7 +480,7 @@ bool DarwinAsmParser::ParseDirectiveLsym(StringRef, SMLoc) { Lex(); const MCExpr *Value; - if (getParser().ParseExpression(Value)) + if (getParser().parseExpression(Value)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -422,7 +501,7 @@ bool DarwinAsmParser::ParseDirectiveSection(StringRef, SMLoc) { SMLoc Loc = getLexer().getLoc(); StringRef SectionName; - if (getParser().ParseIdentifier(SectionName)) + if (getParser().parseIdentifier(SectionName)) return Error(Loc, "expected identifier after '.section' directive"); // Verify there is a following comma. @@ -497,7 +576,7 @@ bool DarwinAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { /// ParseDirectiveSecureLogUnique /// ::= .secure_log_unique ... message ... bool DarwinAsmParser::ParseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) { - StringRef LogMessage = getParser().ParseStringToEndOfStatement(); + StringRef LogMessage = getParser().parseStringToEndOfStatement(); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.secure_log_unique' directive"); @@ -565,7 +644,7 @@ bool DarwinAsmParser::ParseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) { bool DarwinAsmParser::ParseDirectiveTBSS(StringRef, SMLoc) { SMLoc IDLoc = getLexer().getLoc(); StringRef Name; - if (getParser().ParseIdentifier(Name)) + if (getParser().parseIdentifier(Name)) return TokError("expected identifier in directive"); // Handle the identifier as the key symbol. @@ -577,7 +656,7 @@ bool DarwinAsmParser::ParseDirectiveTBSS(StringRef, SMLoc) { int64_t Size; SMLoc SizeLoc = getLexer().getLoc(); - if (getParser().ParseAbsoluteExpression(Size)) + if (getParser().parseAbsoluteExpression(Size)) return true; int64_t Pow2Alignment = 0; @@ -585,7 +664,7 @@ bool DarwinAsmParser::ParseDirectiveTBSS(StringRef, SMLoc) { if (getLexer().is(AsmToken::Comma)) { Lex(); Pow2AlignmentLoc = getLexer().getLoc(); - if (getParser().ParseAbsoluteExpression(Pow2Alignment)) + if (getParser().parseAbsoluteExpression(Pow2Alignment)) return true; } @@ -620,7 +699,7 @@ bool DarwinAsmParser::ParseDirectiveTBSS(StringRef, SMLoc) { /// , align_expression ]] bool DarwinAsmParser::ParseDirectiveZerofill(StringRef, SMLoc) { StringRef Segment; - if (getParser().ParseIdentifier(Segment)) + if (getParser().parseIdentifier(Segment)) return TokError("expected segment name after '.zerofill' directive"); if (getLexer().isNot(AsmToken::Comma)) @@ -628,7 +707,7 @@ bool DarwinAsmParser::ParseDirectiveZerofill(StringRef, SMLoc) { Lex(); StringRef Section; - if (getParser().ParseIdentifier(Section)) + if (getParser().parseIdentifier(Section)) return TokError("expected section name after comma in '.zerofill' " "directive"); @@ -648,7 +727,7 @@ bool DarwinAsmParser::ParseDirectiveZerofill(StringRef, SMLoc) { SMLoc IDLoc = getLexer().getLoc(); StringRef IDStr; - if (getParser().ParseIdentifier(IDStr)) + if (getParser().parseIdentifier(IDStr)) return TokError("expected identifier in directive"); // handle the identifier as the key symbol. @@ -660,7 +739,7 @@ bool DarwinAsmParser::ParseDirectiveZerofill(StringRef, SMLoc) { int64_t Size; SMLoc SizeLoc = getLexer().getLoc(); - if (getParser().ParseAbsoluteExpression(Size)) + if (getParser().parseAbsoluteExpression(Size)) return true; int64_t Pow2Alignment = 0; @@ -668,7 +747,7 @@ bool DarwinAsmParser::ParseDirectiveZerofill(StringRef, SMLoc) { if (getLexer().is(AsmToken::Comma)) { Lex(); Pow2AlignmentLoc = getLexer().getLoc(); - if (getParser().ParseAbsoluteExpression(Pow2Alignment)) + if (getParser().parseAbsoluteExpression(Pow2Alignment)) return true; } @@ -712,7 +791,7 @@ bool DarwinAsmParser::ParseDirectiveDataRegion(StringRef, SMLoc) { } StringRef RegionType; SMLoc Loc = getParser().getTok().getLoc(); - if (getParser().ParseIdentifier(RegionType)) + if (getParser().parseIdentifier(RegionType)) return TokError("expected region type after '.data_region' directive"); int Kind = StringSwitch<int>(RegionType) .Case("jt8", MCDR_DataRegionJT8) diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp index 87126f0e3e..4c45e08744 100644 --- a/lib/MC/MCParser/ELFAsmParser.cpp +++ b/lib/MC/MCParser/ELFAsmParser.cpp @@ -22,10 +22,12 @@ using namespace llvm; namespace { class ELFAsmParser : public MCAsmParserExtension { - template<bool (ELFAsmParser::*Handler)(StringRef, SMLoc)> - void AddDirectiveHandler(StringRef Directive) { - getParser().AddDirectiveHandler(this, Directive, - HandleDirective<ELFAsmParser, Handler>); + template<bool (ELFAsmParser::*HandlerMethod)(StringRef, SMLoc)> + void addDirectiveHandler(StringRef Directive) { + MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( + this, HandleDirective<ELFAsmParser, HandlerMethod>); + + getParser().addDirectiveHandler(Directive, Handler); } bool ParseSectionSwitch(StringRef Section, unsigned Type, @@ -41,38 +43,38 @@ public: // Call the base implementation. this->MCAsmParserExtension::Initialize(Parser); - AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data"); - AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text"); - AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss"); - AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata"); - AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata"); - AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss"); - AddDirectiveHandler< + addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data"); + addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text"); + addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss"); + addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata"); + addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata"); + addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss"); + addDirectiveHandler< &ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel"); - AddDirectiveHandler< + addDirectiveHandler< &ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro"); - AddDirectiveHandler< + addDirectiveHandler< &ELFAsmParser::ParseSectionDirectiveDataRelRoLocal>(".data.rel.ro.local"); - AddDirectiveHandler< + addDirectiveHandler< &ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame"); - AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section"); - AddDirectiveHandler< + addDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section"); + addDirectiveHandler< &ELFAsmParser::ParseDirectivePushSection>(".pushsection"); - AddDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection"); - AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size"); - AddDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous"); - AddDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type"); - AddDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident"); - AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver"); - AddDirectiveHandler<&ELFAsmParser::ParseDirectiveVersion>(".version"); - AddDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref"); - AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".weak"); - AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".local"); - AddDirectiveHandler< + addDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size"); + addDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveVersion>(".version"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".weak"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".local"); + addDirectiveHandler< &ELFAsmParser::ParseDirectiveSymbolAttribute>(".protected"); - AddDirectiveHandler< + addDirectiveHandler< &ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal"); - AddDirectiveHandler< + addDirectiveHandler< &ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden"); } @@ -167,7 +169,7 @@ bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { for (;;) { StringRef Name; - if (getParser().ParseIdentifier(Name)) + if (getParser().parseIdentifier(Name)) return TokError("expected identifier in directive"); MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); @@ -201,7 +203,7 @@ bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type, bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) { StringRef Name; - if (getParser().ParseIdentifier(Name)) + if (getParser().parseIdentifier(Name)) return TokError("expected identifier in directive"); MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); @@ -210,7 +212,7 @@ bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) { Lex(); const MCExpr *Expr; - if (getParser().ParseExpression(Expr)) + if (getParser().parseExpression(Expr)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -222,7 +224,7 @@ bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) { bool ELFAsmParser::ParseSectionName(StringRef &SectionName) { // A section name can contain -, so we cannot just use - // ParseIdentifier. + // parseIdentifier. SMLoc FirstLoc = getLexer().getLoc(); unsigned Size = 0; @@ -375,14 +377,14 @@ bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { return TokError("expected '@' or '%' before type"); Lex(); - if (getParser().ParseIdentifier(TypeName)) + if (getParser().parseIdentifier(TypeName)) return TokError("expected identifier in directive"); if (Mergeable) { if (getLexer().isNot(AsmToken::Comma)) return TokError("expected the entry size"); Lex(); - if (getParser().ParseAbsoluteExpression(Size)) + if (getParser().parseAbsoluteExpression(Size)) return true; if (Size <= 0) return TokError("entry size must be positive"); @@ -392,12 +394,12 @@ bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { if (getLexer().isNot(AsmToken::Comma)) return TokError("expected group name"); Lex(); - if (getParser().ParseIdentifier(GroupName)) + if (getParser().parseIdentifier(GroupName)) return true; if (getLexer().is(AsmToken::Comma)) { Lex(); StringRef Linkage; - if (getParser().ParseIdentifier(Linkage)) + if (getParser().parseIdentifier(Linkage)) return true; if (Linkage != "comdat") return TokError("Linkage must be 'comdat'"); @@ -411,7 +413,16 @@ bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { unsigned Type = ELF::SHT_PROGBITS; - if (!TypeName.empty()) { + if (TypeName.empty()) { + if (SectionName.startswith(".note")) + Type = ELF::SHT_NOTE; + else if (SectionName == ".init_array") + Type = ELF::SHT_INIT_ARRAY; + else if (SectionName == ".fini_array") + Type = ELF::SHT_FINI_ARRAY; + else if (SectionName == ".preinit_array") + Type = ELF::SHT_PREINIT_ARRAY; + } else { if (TypeName == "init_array") Type = ELF::SHT_INIT_ARRAY; else if (TypeName == "fini_array") @@ -450,7 +461,7 @@ bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { /// ::= .type identifier , @attribute bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) { StringRef Name; - if (getParser().ParseIdentifier(Name)) + if (getParser().parseIdentifier(Name)) return TokError("expected identifier in directive"); // Handle the identifier as the key symbol. @@ -468,7 +479,7 @@ bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) { SMLoc TypeLoc; TypeLoc = getLexer().getLoc(); - if (getParser().ParseIdentifier(Type)) + if (getParser().parseIdentifier(Type)) return TokError("expected symbol type in directive"); MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Type) @@ -527,7 +538,7 @@ bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) { /// ::= .symver foo, bar2@zed bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) { StringRef Name; - if (getParser().ParseIdentifier(Name)) + if (getParser().parseIdentifier(Name)) return TokError("expected identifier in directive"); if (getLexer().isNot(AsmToken::Comma)) @@ -536,7 +547,7 @@ bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) { Lex(); StringRef AliasName; - if (getParser().ParseIdentifier(AliasName)) + if (getParser().parseIdentifier(AliasName)) return TokError("expected identifier in directive"); if (AliasName.find('@') == StringRef::npos) @@ -582,7 +593,7 @@ bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) { // FIXME: Share code with the other alias building directives. StringRef AliasName; - if (getParser().ParseIdentifier(AliasName)) + if (getParser().parseIdentifier(AliasName)) return TokError("expected identifier in directive"); if (getLexer().isNot(AsmToken::Comma)) @@ -591,7 +602,7 @@ bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) { Lex(); StringRef Name; - if (getParser().ParseIdentifier(Name)) + if (getParser().parseIdentifier(Name)) return TokError("expected identifier in directive"); MCSymbol *Alias = getContext().GetOrCreateSymbol(AliasName); diff --git a/lib/MC/MCParser/MCAsmParser.cpp b/lib/MC/MCParser/MCAsmParser.cpp index a8b00cd84a..6e1ebad36c 100644 --- a/lib/MC/MCParser/MCAsmParser.cpp +++ b/lib/MC/MCParser/MCAsmParser.cpp @@ -38,9 +38,9 @@ bool MCAsmParser::TokError(const Twine &Msg, ArrayRef<SMRange> Ranges) { return true; } -bool MCAsmParser::ParseExpression(const MCExpr *&Res) { +bool MCAsmParser::parseExpression(const MCExpr *&Res) { SMLoc L; - return ParseExpression(Res, L); + return parseExpression(Res, L); } void MCParsedAsmOperand::dump() const { diff --git a/lib/MC/MCPureStreamer.cpp b/lib/MC/MCPureStreamer.cpp index 6ce7ae81d5..573308abb8 100644 --- a/lib/MC/MCPureStreamer.cpp +++ b/lib/MC/MCPureStreamer.cpp @@ -28,9 +28,9 @@ private: virtual void EmitInstToData(const MCInst &Inst); public: - MCPureStreamer(MCContext &Context, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(Context, TAB, OS, Emitter) {} + MCPureStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, + MCCodeEmitter *Emitter) + : MCObjectStreamer(SK_PureStreamer, Context, TAB, OS, Emitter) {} /// @name MCStreamer Interface /// @{ @@ -100,6 +100,10 @@ public: } /// @} + + static bool classof(const MCStreamer *S) { + return S->getKind() == SK_PureStreamer; + } }; } // end anonymous namespace. diff --git a/lib/MC/MCSectionMachO.cpp b/lib/MC/MCSectionMachO.cpp index e771556262..fc323155be 100644 --- a/lib/MC/MCSectionMachO.cpp +++ b/lib/MC/MCSectionMachO.cpp @@ -165,9 +165,9 @@ bool MCSectionMachO::isVirtualSection() const { /// StripSpaces - This removes leading and trailing spaces from the StringRef. static void StripSpaces(StringRef &Str) { - while (!Str.empty() && isspace(Str[0])) + while (!Str.empty() && isspace(static_cast<unsigned char>(Str[0]))) Str = Str.substr(1); - while (!Str.empty() && isspace(Str.back())) + while (!Str.empty() && isspace(static_cast<unsigned char>(Str.back()))) Str = Str.substr(0, Str.size()-1); } diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 00ebde3c40..9857f7bb08 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -21,10 +21,9 @@ #include <cstdlib> using namespace llvm; -MCStreamer::MCStreamer(MCContext &Ctx) - : Context(Ctx), EmitEHFrame(true), EmitDebugFrame(false), - CurrentW64UnwindInfo(0), LastSymbol(0), - AutoInitSections(false) { +MCStreamer::MCStreamer(StreamerKind Kind, MCContext &Ctx) + : Kind(Kind), Context(Ctx), EmitEHFrame(true), EmitDebugFrame(false), + CurrentW64UnwindInfo(0), LastSymbol(0), AutoInitSections(false) { const MCSection *section = NULL; SectionStack.push_back(std::make_pair(section, section)); } @@ -43,7 +42,7 @@ void MCStreamer::reset() { LastSymbol = 0; const MCSection *section = NULL; SectionStack.clear(); - SectionStack.push_back(std::make_pair(section, section)); + SectionStack.push_back(std::make_pair(section, section)); } const MCExpr *MCStreamer::BuildSymbolDiff(MCContext &Context, @@ -105,7 +104,7 @@ void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size, /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the /// client having to pass in a MCExpr for constant integers. void MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned Padding, - unsigned AddrSpace) { + unsigned AddrSpace) { SmallString<128> Tmp; raw_svector_ostream OSE(Tmp); encodeULEB128(Value, OSE, Padding); @@ -621,3 +620,8 @@ void MCStreamer::Finish() { FinishImpl(); } + +MCSymbolData &MCStreamer::getOrCreateSymbolData(MCSymbol *Symbol) { + report_fatal_error("Not supported!"); + return *(static_cast<MCSymbolData*> (NULL)); +} diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index 0098bead45..a5ba3c3653 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -376,6 +376,39 @@ void MachObjectWriter::WriteLinkeditLoadCommand(uint32_t Type, assert(OS.tell() - Start == macho::LinkeditLoadCommandSize); } +static unsigned ComputeLinkerOptionsLoadCommandSize( + const std::vector<std::string> &Options, bool is64Bit) +{ + unsigned Size = sizeof(macho::LinkerOptionsLoadCommand); + for (unsigned i = 0, e = Options.size(); i != e; ++i) + Size += Options[i].size() + 1; + return RoundUpToAlignment(Size, is64Bit ? 8 : 4); +} + +void MachObjectWriter::WriteLinkerOptionsLoadCommand( + const std::vector<std::string> &Options) +{ + unsigned Size = ComputeLinkerOptionsLoadCommandSize(Options, is64Bit()); + uint64_t Start = OS.tell(); + (void) Start; + + Write32(macho::LCT_LinkerOptions); + Write32(Size); + Write32(Options.size()); + uint64_t BytesWritten = sizeof(macho::LinkerOptionsLoadCommand); + for (unsigned i = 0, e = Options.size(); i != e; ++i) { + // Write each string, including the null byte. + const std::string &Option = Options[i]; + WriteBytes(Option.c_str(), Option.size() + 1); + BytesWritten += Option.size() + 1; + } + + // Pad to a multiple of the pointer size. + WriteBytes("", OffsetToAlignment(BytesWritten, is64Bit() ? 8 : 4)); + + assert(OS.tell() - Start == Size); +} + void MachObjectWriter::RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, @@ -693,6 +726,13 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, macho::SegmentLoadCommand64Size + NumSections * macho::Section64Size : macho::SegmentLoadCommand32Size + NumSections * macho::Section32Size; + // Add the data-in-code load command size, if used. + unsigned NumDataRegions = Asm.getDataRegions().size(); + if (NumDataRegions) { + ++NumLoadCommands; + LoadCommandsSize += macho::LinkeditLoadCommandSize; + } + // Add the symbol table load command sizes, if used. unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() + UndefinedSymbolData.size(); @@ -702,13 +742,15 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, macho::DysymtabLoadCommandSize); } - // Add the data-in-code load command size, if used. - unsigned NumDataRegions = Asm.getDataRegions().size(); - if (NumDataRegions) { + // Add the linker option load commands sizes. + const std::vector<std::vector<std::string> > &LinkerOptions = + Asm.getLinkerOptions(); + for (unsigned i = 0, e = LinkerOptions.size(); i != e; ++i) { ++NumLoadCommands; - LoadCommandsSize += macho::LinkeditLoadCommandSize; + LoadCommandsSize += ComputeLinkerOptionsLoadCommandSize(LinkerOptions[i], + is64Bit()); } - + // Compute the total size of the section data, as well as its file size and vm // size. uint64_t SectionDataStart = (is64Bit() ? macho::Header64Size : @@ -799,6 +841,11 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, IndirectSymbolOffset, NumIndirectSymbols); } + // Write the linker options load commands. + for (unsigned i = 0, e = LinkerOptions.size(); i != e; ++i) { + WriteLinkerOptionsLoadCommand(LinkerOptions[i]); + } + // Write the actual section data. for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp index e1d65387a1..6dffed73df 100644 --- a/lib/MC/WinCOFFObjectWriter.cpp +++ b/lib/MC/WinCOFFObjectWriter.cpp @@ -147,7 +147,9 @@ public: object_t *createCOFFEntity(StringRef Name, list_t &List); void DefineSection(MCSectionData const &SectionData); - void DefineSymbol(MCSymbolData const &SymbolData, MCAssembler &Assembler); + void DefineSymbol(MCSymbol const &Symbol, + MCSymbolData const &SymbolData, + MCAssembler &Assembler); void MakeSymbolReal(COFFSymbol &S, size_t Index); void MakeSectionReal(COFFSection &S, size_t Number); @@ -408,9 +410,10 @@ 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, +void WinCOFFObjectWriter::DefineSymbol(MCSymbol const &Symbol, + MCSymbolData const &SymbolData, MCAssembler &Assembler) { - COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&SymbolData.getSymbol()); + COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&Symbol); coff_symbol->Data.Type = (SymbolData.getFlags() & 0x0000FFFF) >> 0; coff_symbol->Data.StorageClass = (SymbolData.getFlags() & 0x00FF0000) >> 16; @@ -418,20 +421,17 @@ void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData, if (SymbolData.getFlags() & COFF::SF_WeakExternal) { coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; - if (SymbolData.getSymbol().isVariable()) { + if (Symbol.isVariable()) { coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; - const MCExpr *Value = SymbolData.getSymbol().getVariableValue(); // FIXME: This assert message isn't very good. - assert(Value->getKind() == MCExpr::SymbolRef && + assert(Symbol.getVariableValue()->getKind() == MCExpr::SymbolRef && "Value must be a SymbolRef!"); - const MCSymbolRefExpr *SymbolRef = - static_cast<const MCSymbolRefExpr *>(Value); - coff_symbol->Other = GetOrCreateCOFFSymbol(&SymbolRef->getSymbol()); + coff_symbol->Other = GetOrCreateCOFFSymbol(&Symbol); } else { std::string WeakName = std::string(".weak.") - + SymbolData.getSymbol().getName().str() + + Symbol.getName().str() + ".default"; COFFSymbol *WeakDefault = createSymbol(WeakName); WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; @@ -464,7 +464,7 @@ void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData, // Bind internal COFF symbol to MC symbol. coff_symbol->MCData = &SymbolData; - SymbolMap[&SymbolData.getSymbol()] = coff_symbol; + SymbolMap[&Symbol] = coff_symbol; } /// making a section real involves assigned it a number and putting @@ -619,8 +619,11 @@ void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, for (MCAssembler::const_symbol_iterator i = Asm.symbol_begin(), e = Asm.symbol_end(); i != e; i++) { - if (ExportSymbol(*i, Asm)) - DefineSymbol(*i, Asm); + if (ExportSymbol(*i, Asm)) { + const MCSymbol &Alias = i->getSymbol(); + const MCSymbol &Symbol = Alias.AliasedSymbol(); + DefineSymbol(Alias, Asm.getSymbolData(Symbol), Asm); + } } } diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp index cc2c272f38..75f343c421 100644 --- a/lib/MC/WinCOFFStreamer.cpp +++ b/lib/MC/WinCOFFStreamer.cpp @@ -55,7 +55,6 @@ public: virtual void EmitDebugLabel(MCSymbol *Symbol); virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); virtual void EmitThumbFunc(MCSymbol *Func); - virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); virtual void BeginCOFFSymbolDef(MCSymbol const *Symbol); @@ -76,6 +75,10 @@ public: 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(); @@ -129,13 +132,10 @@ private: }; } // end anonymous namespace. -WinCOFFStreamer::WinCOFFStreamer(MCContext &Context, - MCAsmBackend &MAB, - MCCodeEmitter &CE, - raw_ostream &OS) - : MCObjectStreamer(Context, MAB, OS, &CE) - , CurSymbol(NULL) { -} +WinCOFFStreamer::WinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, + MCCodeEmitter &CE, raw_ostream &OS) + : MCObjectStreamer(SK_WinCOFFStreamer, Context, MAB, OS, &CE), + CurSymbol(NULL) {} void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment, bool External) { @@ -201,44 +201,6 @@ void WinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) { llvm_unreachable("not implemented"); } -void WinCOFFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { - assert((Symbol->isInSection() - ? Symbol->getSection().getVariant() == MCSection::SV_COFF - : true) && "Got non COFF section in the COFF backend!"); - // FIXME: This is all very ugly and depressing. What needs to happen here - // depends on quite a few things that are all part of relaxation, which we - // don't really even do. - - if (Value->getKind() != MCExpr::SymbolRef) { - MCObjectStreamer::EmitAssignment(Symbol, Value); - } else { - // FIXME: This is a horrible way to do this :(. This should really be - // handled after we are done with the MC* objects and immediately before - // writing out the object file when we know exactly what the symbol should - // look like in the coff symbol table. I'm not doing that now because the - // COFF object writer doesn't have a clearly defined separation between MC - // data structures, the object writers data structures, and the raw, POD, - // data structures that get written to disk. - - // Copy over the aliased data. - MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); - const MCSymbolData &RealSD = getAssembler().getOrCreateSymbolData( - dyn_cast<const MCSymbolRefExpr>(Value)->getSymbol()); - - // FIXME: This is particularly nasty because it breaks as soon as any data - // members of MCSymbolData change. - SD.CommonAlign = RealSD.CommonAlign; - SD.CommonSize = RealSD.CommonSize; - SD.Flags = RealSD.Flags; - SD.Fragment = RealSD.Fragment; - SD.Index = RealSD.Index; - SD.IsExternal = RealSD.IsExternal; - SD.IsPrivateExtern = RealSD.IsPrivateExtern; - SD.Offset = RealSD.Offset; - SD.SymbolSize = RealSD.SymbolSize; - } -} - void WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { assert(Symbol && "Symbol must be non-null!"); |