LLVM API Documentation

COFFAsmParser.cpp
Go to the documentation of this file.
00001 //===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "llvm/MC/MCParser/MCAsmParserExtension.h"
00011 #include "llvm/ADT/StringSwitch.h"
00012 #include "llvm/ADT/Twine.h"
00013 #include "llvm/MC/MCAsmInfo.h"
00014 #include "llvm/MC/MCContext.h"
00015 #include "llvm/MC/MCExpr.h"
00016 #include "llvm/MC/MCObjectFileInfo.h"
00017 #include "llvm/MC/MCParser/MCAsmLexer.h"
00018 #include "llvm/MC/MCRegisterInfo.h"
00019 #include "llvm/MC/MCSectionCOFF.h"
00020 #include "llvm/MC/MCStreamer.h"
00021 #include "llvm/MC/MCTargetAsmParser.h"
00022 #include "llvm/Support/COFF.h"
00023 using namespace llvm;
00024 
00025 namespace {
00026 
00027 class COFFAsmParser : public MCAsmParserExtension {
00028   template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
00029   void addDirectiveHandler(StringRef Directive) {
00030     MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
00031         this, HandleDirective<COFFAsmParser, HandlerMethod>);
00032     getParser().addDirectiveHandler(Directive, Handler);
00033   }
00034 
00035   bool ParseSectionSwitch(StringRef Section,
00036                           unsigned Characteristics,
00037                           SectionKind Kind);
00038 
00039   bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
00040                           SectionKind Kind, StringRef COMDATSymName,
00041                           COFF::COMDATType Type);
00042 
00043   bool ParseSectionName(StringRef &SectionName);
00044   bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags);
00045 
00046   void Initialize(MCAsmParser &Parser) override {
00047     // Call the base implementation.
00048     MCAsmParserExtension::Initialize(Parser);
00049 
00050     addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
00051     addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
00052     addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
00053     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
00054     addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
00055     addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
00056     addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
00057     addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
00058     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
00059     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
00060     addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
00061 
00062     // Win64 EH directives.
00063     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
00064                                                                    ".seh_proc");
00065     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
00066                                                                 ".seh_endproc");
00067     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
00068                                                            ".seh_startchained");
00069     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
00070                                                              ".seh_endchained");
00071     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
00072                                                                 ".seh_handler");
00073     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
00074                                                             ".seh_handlerdata");
00075     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
00076                                                                 ".seh_pushreg");
00077     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
00078                                                                ".seh_setframe");
00079     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
00080                                                              ".seh_stackalloc");
00081     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
00082                                                                 ".seh_savereg");
00083     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
00084                                                                 ".seh_savexmm");
00085     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
00086                                                               ".seh_pushframe");
00087     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
00088                                                             ".seh_endprologue");
00089     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
00090   }
00091 
00092   bool ParseSectionDirectiveText(StringRef, SMLoc) {
00093     return ParseSectionSwitch(".text",
00094                               COFF::IMAGE_SCN_CNT_CODE
00095                             | COFF::IMAGE_SCN_MEM_EXECUTE
00096                             | COFF::IMAGE_SCN_MEM_READ,
00097                               SectionKind::getText());
00098   }
00099   bool ParseSectionDirectiveData(StringRef, SMLoc) {
00100     return ParseSectionSwitch(".data",
00101                               COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
00102                             | COFF::IMAGE_SCN_MEM_READ
00103                             | COFF::IMAGE_SCN_MEM_WRITE,
00104                               SectionKind::getDataRel());
00105   }
00106   bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
00107     return ParseSectionSwitch(".bss",
00108                               COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
00109                             | COFF::IMAGE_SCN_MEM_READ
00110                             | COFF::IMAGE_SCN_MEM_WRITE,
00111                               SectionKind::getBSS());
00112   }
00113 
00114   bool ParseDirectiveSection(StringRef, SMLoc);
00115   bool ParseDirectiveDef(StringRef, SMLoc);
00116   bool ParseDirectiveScl(StringRef, SMLoc);
00117   bool ParseDirectiveType(StringRef, SMLoc);
00118   bool ParseDirectiveEndef(StringRef, SMLoc);
00119   bool ParseDirectiveSecRel32(StringRef, SMLoc);
00120   bool ParseDirectiveSecIdx(StringRef, SMLoc);
00121   bool parseCOMDATType(COFF::COMDATType &Type);
00122   bool ParseDirectiveLinkOnce(StringRef, SMLoc);
00123 
00124   // Win64 EH directives.
00125   bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
00126   bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
00127   bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
00128   bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
00129   bool ParseSEHDirectiveHandler(StringRef, SMLoc);
00130   bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
00131   bool ParseSEHDirectivePushReg(StringRef, SMLoc);
00132   bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
00133   bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
00134   bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
00135   bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
00136   bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
00137   bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
00138 
00139   bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
00140   bool ParseSEHRegisterNumber(unsigned &RegNo);
00141   bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
00142 public:
00143   COFFAsmParser() {}
00144 };
00145 
00146 } // end annonomous namespace.
00147 
00148 static SectionKind computeSectionKind(unsigned Flags) {
00149   if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
00150     return SectionKind::getText();
00151   if (Flags & COFF::IMAGE_SCN_MEM_READ &&
00152       (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
00153     return SectionKind::getReadOnly();
00154   return SectionKind::getDataRel();
00155 }
00156 
00157 bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
00158   enum {
00159     None      = 0,
00160     Alloc     = 1 << 0,
00161     Code      = 1 << 1,
00162     Load      = 1 << 2,
00163     InitData  = 1 << 3,
00164     Shared    = 1 << 4,
00165     NoLoad    = 1 << 5,
00166     NoRead    = 1 << 6,
00167     NoWrite  =  1 << 7
00168   };
00169 
00170   bool ReadOnlyRemoved = false;
00171   unsigned SecFlags = None;
00172 
00173   for (char FlagChar : FlagsString) {
00174     switch (FlagChar) {
00175     case 'a':
00176       // Ignored.
00177       break;
00178 
00179     case 'b': // bss section
00180       SecFlags |= Alloc;
00181       if (SecFlags & InitData)
00182         return TokError("conflicting section flags 'b' and 'd'.");
00183       SecFlags &= ~Load;
00184       break;
00185 
00186     case 'd': // data section
00187       SecFlags |= InitData;
00188       if (SecFlags & Alloc)
00189         return TokError("conflicting section flags 'b' and 'd'.");
00190       SecFlags &= ~NoWrite;
00191       if ((SecFlags & NoLoad) == 0)
00192         SecFlags |= Load;
00193       break;
00194 
00195     case 'n': // section is not loaded
00196       SecFlags |= NoLoad;
00197       SecFlags &= ~Load;
00198       break;
00199 
00200     case 'r': // read-only
00201       ReadOnlyRemoved = false;
00202       SecFlags |= NoWrite;
00203       if ((SecFlags & Code) == 0)
00204         SecFlags |= InitData;
00205       if ((SecFlags & NoLoad) == 0)
00206         SecFlags |= Load;
00207       break;
00208 
00209     case 's': // shared section
00210       SecFlags |= Shared | InitData;
00211       SecFlags &= ~NoWrite;
00212       if ((SecFlags & NoLoad) == 0)
00213         SecFlags |= Load;
00214       break;
00215 
00216     case 'w': // writable
00217       SecFlags &= ~NoWrite;
00218       ReadOnlyRemoved = true;
00219       break;
00220 
00221     case 'x': // executable section
00222       SecFlags |= Code;
00223       if ((SecFlags & NoLoad) == 0)
00224         SecFlags |= Load;
00225       if (!ReadOnlyRemoved)
00226         SecFlags |= NoWrite;
00227       break;
00228 
00229     case 'y': // not readable
00230       SecFlags |= NoRead | NoWrite;
00231       break;
00232 
00233     default:
00234       return TokError("unknown flag");
00235     }
00236   }
00237 
00238   *Flags = 0;
00239 
00240   if (SecFlags == None)
00241     SecFlags = InitData;
00242 
00243   if (SecFlags & Code)
00244     *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
00245   if (SecFlags & InitData)
00246     *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
00247   if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
00248     *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
00249   if (SecFlags & NoLoad)
00250     *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
00251   if ((SecFlags & NoRead) == 0)
00252     *Flags |= COFF::IMAGE_SCN_MEM_READ;
00253   if ((SecFlags & NoWrite) == 0)
00254     *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
00255   if (SecFlags & Shared)
00256     *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
00257 
00258   return false;
00259 }
00260 
00261 /// ParseDirectiveSymbolAttribute
00262 ///  ::= { ".weak", ... } [ identifier ( , identifier )* ]
00263 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
00264   MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
00265     .Case(".weak", MCSA_Weak)
00266     .Default(MCSA_Invalid);
00267   assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
00268   if (getLexer().isNot(AsmToken::EndOfStatement)) {
00269     for (;;) {
00270       StringRef Name;
00271 
00272       if (getParser().parseIdentifier(Name))
00273         return TokError("expected identifier in directive");
00274 
00275       MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
00276 
00277       getStreamer().EmitSymbolAttribute(Sym, Attr);
00278 
00279       if (getLexer().is(AsmToken::EndOfStatement))
00280         break;
00281 
00282       if (getLexer().isNot(AsmToken::Comma))
00283         return TokError("unexpected token in directive");
00284       Lex();
00285     }
00286   }
00287 
00288   Lex();
00289   return false;
00290 }
00291 
00292 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
00293                                        unsigned Characteristics,
00294                                        SectionKind Kind) {
00295   return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
00296 }
00297 
00298 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
00299                                        unsigned Characteristics,
00300                                        SectionKind Kind,
00301                                        StringRef COMDATSymName,
00302                                        COFF::COMDATType Type) {
00303   if (getLexer().isNot(AsmToken::EndOfStatement))
00304     return TokError("unexpected token in section switching directive");
00305   Lex();
00306 
00307   getStreamer().SwitchSection(getContext().getCOFFSection(
00308       Section, Characteristics, Kind, COMDATSymName, Type));
00309 
00310   return false;
00311 }
00312 
00313 bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
00314   if (!getLexer().is(AsmToken::Identifier))
00315     return true;
00316 
00317   SectionName = getTok().getIdentifier();
00318   Lex();
00319   return false;
00320 }
00321 
00322 // .section name [, "flags"] [, identifier [ identifier ], identifier]
00323 //
00324 // Supported flags:
00325 //   a: Ignored.
00326 //   b: BSS section (uninitialized data)
00327 //   d: data section (initialized data)
00328 //   n: Discardable section
00329 //   r: Readable section
00330 //   s: Shared section
00331 //   w: Writable section
00332 //   x: Executable section
00333 //   y: Not-readable section (clears 'r')
00334 //
00335 // Subsections are not supported.
00336 bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
00337   StringRef SectionName;
00338 
00339   if (ParseSectionName(SectionName))
00340     return TokError("expected identifier in directive");
00341 
00342   unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
00343                    COFF::IMAGE_SCN_MEM_READ |
00344                    COFF::IMAGE_SCN_MEM_WRITE;
00345 
00346   if (getLexer().is(AsmToken::Comma)) {
00347     Lex();
00348 
00349     if (getLexer().isNot(AsmToken::String))
00350       return TokError("expected string in directive");
00351 
00352     StringRef FlagsStr = getTok().getStringContents();
00353     Lex();
00354 
00355     if (ParseSectionFlags(FlagsStr, &Flags))
00356       return true;
00357   }
00358 
00359   COFF::COMDATType Type = (COFF::COMDATType)0;
00360   StringRef COMDATSymName;
00361   if (getLexer().is(AsmToken::Comma)) {
00362     Type = COFF::IMAGE_COMDAT_SELECT_ANY;;
00363     Lex();
00364 
00365     Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
00366 
00367     if (!getLexer().is(AsmToken::Identifier))
00368       return TokError("expected comdat type such as 'discard' or 'largest' "
00369                       "after protection bits");
00370 
00371     if (parseCOMDATType(Type))
00372       return true;
00373 
00374     if (getLexer().isNot(AsmToken::Comma))
00375       return TokError("expected comma in directive");
00376     Lex();
00377 
00378     if (getParser().parseIdentifier(COMDATSymName))
00379       return TokError("expected identifier in directive");
00380   }
00381 
00382   if (getLexer().isNot(AsmToken::EndOfStatement))
00383     return TokError("unexpected token in directive");
00384 
00385   SectionKind Kind = computeSectionKind(Flags);
00386   if (Kind.isText()) {
00387     const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
00388     if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
00389       Flags |= COFF::IMAGE_SCN_MEM_16BIT;
00390   }
00391   ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
00392   return false;
00393 }
00394 
00395 bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
00396   StringRef SymbolName;
00397 
00398   if (getParser().parseIdentifier(SymbolName))
00399     return TokError("expected identifier in directive");
00400 
00401   MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
00402 
00403   getStreamer().BeginCOFFSymbolDef(Sym);
00404 
00405   Lex();
00406   return false;
00407 }
00408 
00409 bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
00410   int64_t SymbolStorageClass;
00411   if (getParser().parseAbsoluteExpression(SymbolStorageClass))
00412     return true;
00413 
00414   if (getLexer().isNot(AsmToken::EndOfStatement))
00415     return TokError("unexpected token in directive");
00416 
00417   Lex();
00418   getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
00419   return false;
00420 }
00421 
00422 bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
00423   int64_t Type;
00424   if (getParser().parseAbsoluteExpression(Type))
00425     return true;
00426 
00427   if (getLexer().isNot(AsmToken::EndOfStatement))
00428     return TokError("unexpected token in directive");
00429 
00430   Lex();
00431   getStreamer().EmitCOFFSymbolType(Type);
00432   return false;
00433 }
00434 
00435 bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
00436   Lex();
00437   getStreamer().EndCOFFSymbolDef();
00438   return false;
00439 }
00440 
00441 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
00442   StringRef SymbolID;
00443   if (getParser().parseIdentifier(SymbolID))
00444     return TokError("expected identifier in directive");
00445 
00446   if (getLexer().isNot(AsmToken::EndOfStatement))
00447     return TokError("unexpected token in directive");
00448 
00449   MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
00450 
00451   Lex();
00452   getStreamer().EmitCOFFSecRel32(Symbol);
00453   return false;
00454 }
00455 
00456 bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
00457   StringRef SymbolID;
00458   if (getParser().parseIdentifier(SymbolID))
00459     return TokError("expected identifier in directive");
00460 
00461   if (getLexer().isNot(AsmToken::EndOfStatement))
00462     return TokError("unexpected token in directive");
00463 
00464   MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
00465 
00466   Lex();
00467   getStreamer().EmitCOFFSectionIndex(Symbol);
00468   return false;
00469 }
00470 
00471 /// ::= [ identifier ]
00472 bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
00473   StringRef TypeId = getTok().getIdentifier();
00474 
00475   Type = StringSwitch<COFF::COMDATType>(TypeId)
00476     .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
00477     .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
00478     .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
00479     .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
00480     .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
00481     .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
00482     .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
00483     .Default((COFF::COMDATType)0);
00484 
00485   if (Type == 0)
00486     return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
00487 
00488   Lex();
00489 
00490   return false;
00491 }
00492 
00493 /// ParseDirectiveLinkOnce
00494 ///  ::= .linkonce [ identifier ]
00495 bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
00496   COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
00497   if (getLexer().is(AsmToken::Identifier))
00498     if (parseCOMDATType(Type))
00499       return true;
00500 
00501   const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
00502                                        getStreamer().getCurrentSection().first);
00503 
00504   if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
00505     return Error(Loc, "cannot make section associative with .linkonce");
00506 
00507   if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
00508     return Error(Loc, Twine("section '") + Current->getSectionName() +
00509                                                        "' is already linkonce");
00510 
00511   Current->setSelection(Type);
00512 
00513   if (getLexer().isNot(AsmToken::EndOfStatement))
00514     return TokError("unexpected token in directive");
00515 
00516   return false;
00517 }
00518 
00519 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
00520   StringRef SymbolID;
00521   if (getParser().parseIdentifier(SymbolID))
00522     return true;
00523 
00524   if (getLexer().isNot(AsmToken::EndOfStatement))
00525     return TokError("unexpected token in directive");
00526 
00527   MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
00528 
00529   Lex();
00530   getStreamer().EmitWinCFIStartProc(Symbol);
00531   return false;
00532 }
00533 
00534 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
00535   Lex();
00536   getStreamer().EmitWinCFIEndProc();
00537   return false;
00538 }
00539 
00540 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
00541   Lex();
00542   getStreamer().EmitWinCFIStartChained();
00543   return false;
00544 }
00545 
00546 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
00547   Lex();
00548   getStreamer().EmitWinCFIEndChained();
00549   return false;
00550 }
00551 
00552 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
00553   StringRef SymbolID;
00554   if (getParser().parseIdentifier(SymbolID))
00555     return true;
00556 
00557   if (getLexer().isNot(AsmToken::Comma))
00558     return TokError("you must specify one or both of @unwind or @except");
00559   Lex();
00560   bool unwind = false, except = false;
00561   if (ParseAtUnwindOrAtExcept(unwind, except))
00562     return true;
00563   if (getLexer().is(AsmToken::Comma)) {
00564     Lex();
00565     if (ParseAtUnwindOrAtExcept(unwind, except))
00566       return true;
00567   }
00568   if (getLexer().isNot(AsmToken::EndOfStatement))
00569     return TokError("unexpected token in directive");
00570 
00571   MCSymbol *handler = getContext().GetOrCreateSymbol(SymbolID);
00572 
00573   Lex();
00574   getStreamer().EmitWinEHHandler(handler, unwind, except);
00575   return false;
00576 }
00577 
00578 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
00579   Lex();
00580   getStreamer().EmitWinEHHandlerData();
00581   return false;
00582 }
00583 
00584 bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
00585   unsigned Reg;
00586   if (ParseSEHRegisterNumber(Reg))
00587     return true;
00588 
00589   if (getLexer().isNot(AsmToken::EndOfStatement))
00590     return TokError("unexpected token in directive");
00591 
00592   Lex();
00593   getStreamer().EmitWinCFIPushReg(Reg);
00594   return false;
00595 }
00596 
00597 bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
00598   unsigned Reg;
00599   int64_t Off;
00600   if (ParseSEHRegisterNumber(Reg))
00601     return true;
00602   if (getLexer().isNot(AsmToken::Comma))
00603     return TokError("you must specify a stack pointer offset");
00604 
00605   Lex();
00606   SMLoc startLoc = getLexer().getLoc();
00607   if (getParser().parseAbsoluteExpression(Off))
00608     return true;
00609 
00610   if (Off & 0x0F)
00611     return Error(startLoc, "offset is not a multiple of 16");
00612 
00613   if (getLexer().isNot(AsmToken::EndOfStatement))
00614     return TokError("unexpected token in directive");
00615 
00616   Lex();
00617   getStreamer().EmitWinCFISetFrame(Reg, Off);
00618   return false;
00619 }
00620 
00621 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
00622   int64_t Size;
00623   SMLoc startLoc = getLexer().getLoc();
00624   if (getParser().parseAbsoluteExpression(Size))
00625     return true;
00626 
00627   if (Size & 7)
00628     return Error(startLoc, "size is not a multiple of 8");
00629 
00630   if (getLexer().isNot(AsmToken::EndOfStatement))
00631     return TokError("unexpected token in directive");
00632 
00633   Lex();
00634   getStreamer().EmitWinCFIAllocStack(Size);
00635   return false;
00636 }
00637 
00638 bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
00639   unsigned Reg;
00640   int64_t Off;
00641   if (ParseSEHRegisterNumber(Reg))
00642     return true;
00643   if (getLexer().isNot(AsmToken::Comma))
00644     return TokError("you must specify an offset on the stack");
00645 
00646   Lex();
00647   SMLoc startLoc = getLexer().getLoc();
00648   if (getParser().parseAbsoluteExpression(Off))
00649     return true;
00650 
00651   if (Off & 7)
00652     return Error(startLoc, "size is not a multiple of 8");
00653 
00654   if (getLexer().isNot(AsmToken::EndOfStatement))
00655     return TokError("unexpected token in directive");
00656 
00657   Lex();
00658   // FIXME: Err on %xmm* registers
00659   getStreamer().EmitWinCFISaveReg(Reg, Off);
00660   return false;
00661 }
00662 
00663 // FIXME: This method is inherently x86-specific. It should really be in the
00664 // x86 backend.
00665 bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
00666   unsigned Reg;
00667   int64_t Off;
00668   if (ParseSEHRegisterNumber(Reg))
00669     return true;
00670   if (getLexer().isNot(AsmToken::Comma))
00671     return TokError("you must specify an offset on the stack");
00672 
00673   Lex();
00674   SMLoc startLoc = getLexer().getLoc();
00675   if (getParser().parseAbsoluteExpression(Off))
00676     return true;
00677 
00678   if (getLexer().isNot(AsmToken::EndOfStatement))
00679     return TokError("unexpected token in directive");
00680 
00681   if (Off & 0x0F)
00682     return Error(startLoc, "offset is not a multiple of 16");
00683 
00684   Lex();
00685   // FIXME: Err on non-%xmm* registers
00686   getStreamer().EmitWinCFISaveXMM(Reg, Off);
00687   return false;
00688 }
00689 
00690 bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
00691   bool Code = false;
00692   StringRef CodeID;
00693   if (getLexer().is(AsmToken::At)) {
00694     SMLoc startLoc = getLexer().getLoc();
00695     Lex();
00696     if (!getParser().parseIdentifier(CodeID)) {
00697       if (CodeID != "code")
00698         return Error(startLoc, "expected @code");
00699       Code = true;
00700     }
00701   }
00702 
00703   if (getLexer().isNot(AsmToken::EndOfStatement))
00704     return TokError("unexpected token in directive");
00705 
00706   Lex();
00707   getStreamer().EmitWinCFIPushFrame(Code);
00708   return false;
00709 }
00710 
00711 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
00712   Lex();
00713   getStreamer().EmitWinCFIEndProlog();
00714   return false;
00715 }
00716 
00717 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
00718   StringRef identifier;
00719   if (getLexer().isNot(AsmToken::At))
00720     return TokError("a handler attribute must begin with '@'");
00721   SMLoc startLoc = getLexer().getLoc();
00722   Lex();
00723   if (getParser().parseIdentifier(identifier))
00724     return Error(startLoc, "expected @unwind or @except");
00725   if (identifier == "unwind")
00726     unwind = true;
00727   else if (identifier == "except")
00728     except = true;
00729   else
00730     return Error(startLoc, "expected @unwind or @except");
00731   return false;
00732 }
00733 
00734 bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
00735   SMLoc startLoc = getLexer().getLoc();
00736   if (getLexer().is(AsmToken::Percent)) {
00737     const MCRegisterInfo *MRI = getContext().getRegisterInfo();
00738     SMLoc endLoc;
00739     unsigned LLVMRegNo;
00740     if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
00741       return true;
00742 
00743 #if 0
00744     // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
00745     // violation so this validation code is disabled.
00746 
00747     // Check that this is a non-volatile register.
00748     const unsigned *NVRegs = TAI.getCalleeSavedRegs();
00749     unsigned i;
00750     for (i = 0; NVRegs[i] != 0; ++i)
00751       if (NVRegs[i] == LLVMRegNo)
00752         break;
00753     if (NVRegs[i] == 0)
00754       return Error(startLoc, "expected non-volatile register");
00755 #endif
00756 
00757     int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
00758     if (SEHRegNo < 0)
00759       return Error(startLoc,"register can't be represented in SEH unwind info");
00760     RegNo = SEHRegNo;
00761   }
00762   else {
00763     int64_t n;
00764     if (getParser().parseAbsoluteExpression(n))
00765       return true;
00766     if (n > 15)
00767       return Error(startLoc, "register number is too high");
00768     RegNo = n;
00769   }
00770 
00771   return false;
00772 }
00773 
00774 namespace llvm {
00775 
00776 MCAsmParserExtension *createCOFFAsmParser() {
00777   return new COFFAsmParser;
00778 }
00779 
00780 }