X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FMC%2FMCParser%2FCOFFAsmParser.cpp;h=cc356c7a1748482c19b41baa61e24e5fc60f8b20;hb=8aa3ff05c18ff034c556c23ca0795585b2c2c4c2;hp=ce99509fe78fcae14307fb0052009538d4a7cf7b;hpb=3b32d0240c820a8aa829a950628586512a406ea0;p=oota-llvm.git diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp index ce99509fe78..cc356c7a174 100644 --- a/lib/MC/MCParser/COFFAsmParser.cpp +++ b/lib/MC/MCParser/COFFAsmParser.cpp @@ -8,70 +8,84 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCParser/MCAsmParserExtension.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetAsmParser.h" +#include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Support/COFF.h" using namespace llvm; namespace { class COFFAsmParser : public MCAsmParserExtension { - template - void AddDirectiveHandler(StringRef Directive) { - getParser().AddDirectiveHandler(this, Directive, - HandleDirective); + template + void addDirectiveHandler(StringRef Directive) { + MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( + this, HandleDirective); + getParser().addDirectiveHandler(Directive, Handler); } bool ParseSectionSwitch(StringRef Section, unsigned Characteristics, SectionKind Kind); + bool ParseSectionSwitch(StringRef Section, unsigned Characteristics, + SectionKind Kind, StringRef COMDATSymName, + COFF::COMDATType Type, const MCSectionCOFF *Assoc); + + bool ParseSectionName(StringRef &SectionName); + bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags); + virtual void Initialize(MCAsmParser &Parser) { // 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::ParseSectionDirectiveText>(".text"); + addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data"); + addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce"); // 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"); } bool ParseSectionDirectiveText(StringRef, SMLoc) { @@ -96,10 +110,16 @@ class COFFAsmParser : public MCAsmParserExtension { SectionKind::getBSS()); } + bool ParseDirectiveSection(StringRef, SMLoc); bool ParseDirectiveDef(StringRef, SMLoc); bool ParseDirectiveScl(StringRef, SMLoc); bool ParseDirectiveType(StringRef, SMLoc); bool ParseDirectiveEndef(StringRef, SMLoc); + bool ParseDirectiveSecRel32(StringRef, SMLoc); + bool ParseDirectiveSecIdx(StringRef, SMLoc); + bool parseCOMDATTypeAndAssoc(COFF::COMDATType &Type, + const MCSectionCOFF *&Assoc); + bool ParseDirectiveLinkOnce(StringRef, SMLoc); // Win64 EH directives. bool ParseSEHDirectiveStartProc(StringRef, SMLoc); @@ -118,29 +138,257 @@ class COFFAsmParser : public MCAsmParserExtension { bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except); bool ParseSEHRegisterNumber(unsigned &RegNo); + bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc); public: COFFAsmParser() {} }; } // end annonomous namespace. +static SectionKind computeSectionKind(unsigned Flags) { + if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE) + return SectionKind::getText(); + if (Flags & COFF::IMAGE_SCN_MEM_READ && + (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0) + return SectionKind::getReadOnly(); + return SectionKind::getDataRel(); +} + +bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) { + enum { + None = 0, + Alloc = 1 << 0, + Code = 1 << 1, + Load = 1 << 2, + InitData = 1 << 3, + Shared = 1 << 4, + NoLoad = 1 << 5, + NoRead = 1 << 6, + NoWrite = 1 << 7 + }; + + bool ReadOnlyRemoved = false; + unsigned SecFlags = None; + + for (unsigned i = 0; i < FlagsString.size(); ++i) { + switch (FlagsString[i]) { + case 'a': + // Ignored. + break; + + case 'b': // bss section + SecFlags |= Alloc; + if (SecFlags & InitData) + return TokError("conflicting section flags 'b' and 'd'."); + SecFlags &= ~Load; + break; + + case 'd': // data section + SecFlags |= InitData; + if (SecFlags & Alloc) + return TokError("conflicting section flags 'b' and 'd'."); + SecFlags &= ~NoWrite; + if ((SecFlags & NoLoad) == 0) + SecFlags |= Load; + break; + + case 'n': // section is not loaded + SecFlags |= NoLoad; + SecFlags &= ~Load; + break; + + case 'r': // read-only + ReadOnlyRemoved = false; + SecFlags |= NoWrite; + if ((SecFlags & Code) == 0) + SecFlags |= InitData; + if ((SecFlags & NoLoad) == 0) + SecFlags |= Load; + break; + + case 's': // shared section + SecFlags |= Shared | InitData; + SecFlags &= ~NoWrite; + if ((SecFlags & NoLoad) == 0) + SecFlags |= Load; + break; + + case 'w': // writable + SecFlags &= ~NoWrite; + ReadOnlyRemoved = true; + break; + + case 'x': // executable section + SecFlags |= Code; + if ((SecFlags & NoLoad) == 0) + SecFlags |= Load; + if (!ReadOnlyRemoved) + SecFlags |= NoWrite; + break; + + case 'y': // not readable + SecFlags |= NoRead | NoWrite; + break; + + default: + return TokError("unknown flag"); + } + } + + *Flags = 0; + + if (SecFlags == None) + SecFlags = InitData; + + if (SecFlags & Code) + *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE; + if (SecFlags & InitData) + *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; + if ((SecFlags & Alloc) && (SecFlags & Load) == 0) + *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; + if (SecFlags & NoLoad) + *Flags |= COFF::IMAGE_SCN_LNK_REMOVE; + if ((SecFlags & NoRead) == 0) + *Flags |= COFF::IMAGE_SCN_MEM_READ; + if ((SecFlags & NoWrite) == 0) + *Flags |= COFF::IMAGE_SCN_MEM_WRITE; + if (SecFlags & Shared) + *Flags |= COFF::IMAGE_SCN_MEM_SHARED; + + return false; +} + +/// ParseDirectiveSymbolAttribute +/// ::= { ".weak", ... } [ identifier ( , identifier )* ] +bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { + MCSymbolAttr Attr = StringSwitch(Directive) + .Case(".weak", MCSA_Weak) + .Default(MCSA_Invalid); + assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); + if (getLexer().isNot(AsmToken::EndOfStatement)) { + for (;;) { + StringRef Name; + + if (getParser().parseIdentifier(Name)) + return TokError("expected identifier in directive"); + + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + + getStreamer().EmitSymbolAttribute(Sym, Attr); + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + } + } + + Lex(); + return false; +} + bool COFFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Characteristics, SectionKind Kind) { + return ParseSectionSwitch(Section, Characteristics, Kind, "", + COFF::IMAGE_COMDAT_SELECT_ANY, 0); +} + +bool COFFAsmParser::ParseSectionSwitch(StringRef Section, + unsigned Characteristics, + SectionKind Kind, + StringRef COMDATSymName, + COFF::COMDATType Type, + const MCSectionCOFF *Assoc) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in section switching directive"); Lex(); getStreamer().SwitchSection(getContext().getCOFFSection( - Section, Characteristics, Kind)); + Section, Characteristics, Kind, COMDATSymName, Type, Assoc)); + + return false; +} + +bool COFFAsmParser::ParseSectionName(StringRef &SectionName) { + if (!getLexer().is(AsmToken::Identifier)) + return true; + SectionName = getTok().getIdentifier(); + Lex(); + return false; +} + +// .section name [, "flags"] [, identifier [ identifier ], identifier] +// +// Supported flags: +// a: Ignored. +// b: BSS section (uninitialized data) +// d: data section (initialized data) +// n: Discardable section +// r: Readable section +// s: Shared section +// w: Writable section +// x: Executable section +// y: Not-readable section (clears 'r') +// +// Subsections are not supported. +bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { + StringRef SectionName; + + if (ParseSectionName(SectionName)) + return TokError("expected identifier in directive"); + + unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE; + + if (getLexer().is(AsmToken::Comma)) { + Lex(); + + if (getLexer().isNot(AsmToken::String)) + return TokError("expected string in directive"); + + StringRef FlagsStr = getTok().getStringContents(); + Lex(); + + if (ParseSectionFlags(FlagsStr, &Flags)) + return true; + } + + COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; + const MCSectionCOFF *Assoc = 0; + StringRef COMDATSymName; + if (getLexer().is(AsmToken::Comma)) { + Lex(); + + Flags |= COFF::IMAGE_SCN_LNK_COMDAT; + + if (parseCOMDATTypeAndAssoc(Type, Assoc)) + return true; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("expected comma in directive"); + Lex(); + + if (getParser().parseIdentifier(COMDATSymName)) + return TokError("expected identifier in directive"); + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + SectionKind Kind = computeSectionKind(Flags); + ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type, Assoc); return false; } 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); @@ -153,7 +401,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)) @@ -166,7 +414,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)) @@ -183,21 +431,117 @@ bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) { return false; } +bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) { + StringRef SymbolID; + if (getParser().parseIdentifier(SymbolID)) + return TokError("expected identifier in directive"); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID); + + Lex(); + getStreamer().EmitCOFFSecRel32(Symbol); + return false; +} + +bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) { + StringRef SymbolID; + if (getParser().parseIdentifier(SymbolID)) + return TokError("expected identifier in directive"); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID); + + Lex(); + getStreamer().EmitCOFFSectionIndex(Symbol); + return false; +} + +/// ::= [ identifier [ identifier ] ] +bool COFFAsmParser::parseCOMDATTypeAndAssoc(COFF::COMDATType &Type, + const MCSectionCOFF *&Assoc) { + StringRef TypeId = getTok().getIdentifier(); + + Type = StringSwitch(TypeId) + .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) + .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY) + .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE) + .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH) + .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) + .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST) + .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST) + .Default((COFF::COMDATType)0); + + if (Type == 0) + return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'")); + + Lex(); + + if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { + SMLoc Loc = getTok().getLoc(); + StringRef AssocName; + if (ParseSectionName(AssocName)) + return TokError("expected associated section name"); + + Assoc = static_cast( + getContext().getCOFFSection(AssocName)); + if (!Assoc) + return Error(Loc, "cannot associate unknown section '" + AssocName + "'"); + if (!(Assoc->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)) + return Error(Loc, "associated section must be a COMDAT section"); + if (Assoc->getSelection() == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) + return Error(Loc, "associated section cannot be itself associative"); + } + + return false; +} + +/// ParseDirectiveLinkOnce +/// ::= .linkonce [ identifier [ identifier ] ] +bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) { + COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; + const MCSectionCOFF *Assoc = 0; + if (getLexer().is(AsmToken::Identifier)) + if (parseCOMDATTypeAndAssoc(Type, Assoc)) + return true; + + const MCSectionCOFF *Current = static_cast( + getStreamer().getCurrentSection().first); + + + if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { + if (Assoc == Current) + return Error(Loc, "cannot associate a section with itself"); + } + + if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) + return Error(Loc, Twine("section '") + Current->getSectionName() + + "' is already linkonce"); + + Current->setSelection(Type, Assoc); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + return false; +} + bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) { - const MCExpr *e; - const MCSymbolRefExpr *funcExpr; - SMLoc startLoc = getLexer().getLoc(); - if (getParser().ParseExpression(e)) + StringRef SymbolID; + if (getParser().parseIdentifier(SymbolID)) return true; - if (!(funcExpr = dyn_cast(e))) - return Error(startLoc, "expected symbol"); - if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); + MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID); + Lex(); - getStreamer().EmitWin64EHStartProc(&funcExpr->getSymbol()); + getStreamer().EmitWin64EHStartProc(Symbol); return false; } @@ -220,29 +564,28 @@ bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) { } bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) { - const MCExpr *e; - const MCSymbolRefExpr *funcExpr; - SMLoc startLoc = getLexer().getLoc(); - if (getParser().ParseExpression(e)) + StringRef SymbolID; + if (getParser().parseIdentifier(SymbolID)) return true; - if (!(funcExpr = dyn_cast(e))) - return Error(startLoc, "expected symbol"); - + if (getLexer().isNot(AsmToken::Comma)) + return TokError("you must specify one or both of @unwind or @except"); + Lex(); bool unwind = false, except = false; - startLoc = getLexer().getLoc(); - if (!ParseAtUnwindOrAtExcept(unwind, except)) - return Error(startLoc,"you must specify one or both of @unwind or @except"); + if (ParseAtUnwindOrAtExcept(unwind, except)) + return true; if (getLexer().is(AsmToken::Comma)) { Lex(); - if (!ParseAtUnwindOrAtExcept(unwind, except)) + if (ParseAtUnwindOrAtExcept(unwind, except)) return true; } if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); + MCSymbol *handler = getContext().GetOrCreateSymbol(SymbolID); + Lex(); - getStreamer().EmitWin64EHHandler(&funcExpr->getSymbol(), unwind, except); + getStreamer().EmitWin64EHHandler(handler, unwind, except); return false; } @@ -270,8 +613,12 @@ bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) { int64_t Off; if (ParseSEHRegisterNumber(Reg)) return true; + if (getLexer().isNot(AsmToken::Comma)) + return TokError("you must specify a stack pointer offset"); + + Lex(); SMLoc startLoc = getLexer().getLoc(); - if (getParser().ParseAbsoluteExpression(Off)) + if (getParser().parseAbsoluteExpression(Off)) return true; if (Off & 0x0F) @@ -288,7 +635,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) @@ -307,8 +654,12 @@ bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) { int64_t Off; if (ParseSEHRegisterNumber(Reg)) return true; + if (getLexer().isNot(AsmToken::Comma)) + return TokError("you must specify an offset on the stack"); + + Lex(); SMLoc startLoc = getLexer().getLoc(); - if (getParser().ParseAbsoluteExpression(Off)) + if (getParser().parseAbsoluteExpression(Off)) return true; if (Off & 7) @@ -330,8 +681,12 @@ bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) { int64_t Off; if (ParseSEHRegisterNumber(Reg)) return true; + if (getLexer().isNot(AsmToken::Comma)) + return TokError("you must specify an offset on the stack"); + + Lex(); SMLoc startLoc = getLexer().getLoc(); - if (getParser().ParseAbsoluteExpression(Off)) + if (getParser().parseAbsoluteExpression(Off)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -347,13 +702,16 @@ bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) { } bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) { - bool Code; + bool Code = false; StringRef CodeID; - SMLoc startLoc = getLexer().getLoc(); - if (!getParser().ParseIdentifier(CodeID)) { - if (CodeID != "@code") - return Error(startLoc, "expected @code"); - Code = true; + if (getLexer().is(AsmToken::At)) { + SMLoc startLoc = getLexer().getLoc(); + Lex(); + if (!getParser().parseIdentifier(CodeID)) { + if (CodeID != "code") + return Error(startLoc, "expected @code"); + Code = true; + } } if (getLexer().isNot(AsmToken::EndOfStatement)) @@ -372,12 +730,15 @@ bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) { bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) { StringRef identifier; + if (getLexer().isNot(AsmToken::At)) + return TokError("a handler attribute must begin with '@'"); SMLoc startLoc = getLexer().getLoc(); - if (!getParser().ParseIdentifier(identifier)) + Lex(); + if (getParser().parseIdentifier(identifier)) return Error(startLoc, "expected @unwind or @except"); - if (identifier == "@unwind") + if (identifier == "unwind") unwind = true; - else if (identifier == "@except") + else if (identifier == "except") except = true; else return Error(startLoc, "expected @unwind or @except"); @@ -385,34 +746,42 @@ bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) { } bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) { - int64_t n; SMLoc startLoc = getLexer().getLoc(); - if (getParser().ParseAbsoluteExpression(n)) { - const TargetAsmInfo &asmInfo = getContext().getTargetAsmInfo(); + if (getLexer().is(AsmToken::Percent)) { + const MCRegisterInfo *MRI = getContext().getRegisterInfo(); SMLoc endLoc; unsigned LLVMRegNo; if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc)) - return Error(startLoc, "expected register or number"); + return true; + +#if 0 + // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering + // violation so this validation code is disabled. // Check that this is a non-volatile register. - const unsigned *NVRegs = asmInfo.getCalleeSavedRegs(); + const unsigned *NVRegs = TAI.getCalleeSavedRegs(); unsigned i; for (i = 0; NVRegs[i] != 0; ++i) if (NVRegs[i] == LLVMRegNo) break; if (NVRegs[i] == 0) return Error(startLoc, "expected non-volatile register"); +#endif - int SEHRegNo = asmInfo.getSEHRegNum(LLVMRegNo); + int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo); if (SEHRegNo < 0) return Error(startLoc,"register can't be represented in SEH unwind info"); RegNo = SEHRegNo; } - else + else { + int64_t n; + if (getParser().parseAbsoluteExpression(n)) + return true; + if (n > 15) + return Error(startLoc, "register number is too high"); RegNo = n; + } - if (RegNo > 15) - return Error(startLoc, "register number is too high"); return false; }