Home | History | Annotate | Download | only in MCParser
      1 //===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/MC/MCParser/MCAsmParserExtension.h"
     11 #include "llvm/ADT/StringSwitch.h"
     12 #include "llvm/ADT/Twine.h"
     13 #include "llvm/MC/MCAsmInfo.h"
     14 #include "llvm/MC/MCContext.h"
     15 #include "llvm/MC/MCExpr.h"
     16 #include "llvm/MC/MCObjectFileInfo.h"
     17 #include "llvm/MC/MCParser/MCAsmLexer.h"
     18 #include "llvm/MC/MCRegisterInfo.h"
     19 #include "llvm/MC/MCSectionCOFF.h"
     20 #include "llvm/MC/MCStreamer.h"
     21 #include "llvm/MC/MCTargetAsmParser.h"
     22 #include "llvm/Support/COFF.h"
     23 using namespace llvm;
     24 
     25 namespace {
     26 
     27 class COFFAsmParser : public MCAsmParserExtension {
     28   template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
     29   void addDirectiveHandler(StringRef Directive) {
     30     MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
     31         this, HandleDirective<COFFAsmParser, HandlerMethod>);
     32     getParser().addDirectiveHandler(Directive, Handler);
     33   }
     34 
     35   bool ParseSectionSwitch(StringRef Section,
     36                           unsigned Characteristics,
     37                           SectionKind Kind);
     38 
     39   bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
     40                           SectionKind Kind, StringRef COMDATSymName,
     41                           COFF::COMDATType Type);
     42 
     43   bool ParseSectionName(StringRef &SectionName);
     44   bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags);
     45 
     46   void Initialize(MCAsmParser &Parser) override {
     47     // Call the base implementation.
     48     MCAsmParserExtension::Initialize(Parser);
     49 
     50     addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
     51     addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
     52     addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
     53     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
     54     addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
     55     addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
     56     addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
     57     addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
     58     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
     59     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
     60     addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
     61 
     62     // Win64 EH directives.
     63     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
     64                                                                    ".seh_proc");
     65     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
     66                                                                 ".seh_endproc");
     67     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
     68                                                            ".seh_startchained");
     69     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
     70                                                              ".seh_endchained");
     71     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
     72                                                                 ".seh_handler");
     73     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
     74                                                             ".seh_handlerdata");
     75     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
     76                                                                 ".seh_pushreg");
     77     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
     78                                                                ".seh_setframe");
     79     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
     80                                                              ".seh_stackalloc");
     81     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
     82                                                                 ".seh_savereg");
     83     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
     84                                                                 ".seh_savexmm");
     85     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
     86                                                               ".seh_pushframe");
     87     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
     88                                                             ".seh_endprologue");
     89     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
     90   }
     91 
     92   bool ParseSectionDirectiveText(StringRef, SMLoc) {
     93     return ParseSectionSwitch(".text",
     94                               COFF::IMAGE_SCN_CNT_CODE
     95                             | COFF::IMAGE_SCN_MEM_EXECUTE
     96                             | COFF::IMAGE_SCN_MEM_READ,
     97                               SectionKind::getText());
     98   }
     99   bool ParseSectionDirectiveData(StringRef, SMLoc) {
    100     return ParseSectionSwitch(".data",
    101                               COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
    102                             | COFF::IMAGE_SCN_MEM_READ
    103                             | COFF::IMAGE_SCN_MEM_WRITE,
    104                               SectionKind::getDataRel());
    105   }
    106   bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
    107     return ParseSectionSwitch(".bss",
    108                               COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
    109                             | COFF::IMAGE_SCN_MEM_READ
    110                             | COFF::IMAGE_SCN_MEM_WRITE,
    111                               SectionKind::getBSS());
    112   }
    113 
    114   bool ParseDirectiveSection(StringRef, SMLoc);
    115   bool ParseDirectiveDef(StringRef, SMLoc);
    116   bool ParseDirectiveScl(StringRef, SMLoc);
    117   bool ParseDirectiveType(StringRef, SMLoc);
    118   bool ParseDirectiveEndef(StringRef, SMLoc);
    119   bool ParseDirectiveSecRel32(StringRef, SMLoc);
    120   bool ParseDirectiveSecIdx(StringRef, SMLoc);
    121   bool parseCOMDATType(COFF::COMDATType &Type);
    122   bool ParseDirectiveLinkOnce(StringRef, SMLoc);
    123 
    124   // Win64 EH directives.
    125   bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
    126   bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
    127   bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
    128   bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
    129   bool ParseSEHDirectiveHandler(StringRef, SMLoc);
    130   bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
    131   bool ParseSEHDirectivePushReg(StringRef, SMLoc);
    132   bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
    133   bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
    134   bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
    135   bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
    136   bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
    137   bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
    138 
    139   bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
    140   bool ParseSEHRegisterNumber(unsigned &RegNo);
    141   bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
    142 public:
    143   COFFAsmParser() {}
    144 };
    145 
    146 } // end annonomous namespace.
    147 
    148 static SectionKind computeSectionKind(unsigned Flags) {
    149   if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
    150     return SectionKind::getText();
    151   if (Flags & COFF::IMAGE_SCN_MEM_READ &&
    152       (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
    153     return SectionKind::getReadOnly();
    154   return SectionKind::getDataRel();
    155 }
    156 
    157 bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
    158   enum {
    159     None      = 0,
    160     Alloc     = 1 << 0,
    161     Code      = 1 << 1,
    162     Load      = 1 << 2,
    163     InitData  = 1 << 3,
    164     Shared    = 1 << 4,
    165     NoLoad    = 1 << 5,
    166     NoRead    = 1 << 6,
    167     NoWrite  =  1 << 7
    168   };
    169 
    170   bool ReadOnlyRemoved = false;
    171   unsigned SecFlags = None;
    172 
    173   for (char FlagChar : FlagsString) {
    174     switch (FlagChar) {
    175     case 'a':
    176       // Ignored.
    177       break;
    178 
    179     case 'b': // bss section
    180       SecFlags |= Alloc;
    181       if (SecFlags & InitData)
    182         return TokError("conflicting section flags 'b' and 'd'.");
    183       SecFlags &= ~Load;
    184       break;
    185 
    186     case 'd': // data section
    187       SecFlags |= InitData;
    188       if (SecFlags & Alloc)
    189         return TokError("conflicting section flags 'b' and 'd'.");
    190       SecFlags &= ~NoWrite;
    191       if ((SecFlags & NoLoad) == 0)
    192         SecFlags |= Load;
    193       break;
    194 
    195     case 'n': // section is not loaded
    196       SecFlags |= NoLoad;
    197       SecFlags &= ~Load;
    198       break;
    199 
    200     case 'r': // read-only
    201       ReadOnlyRemoved = false;
    202       SecFlags |= NoWrite;
    203       if ((SecFlags & Code) == 0)
    204         SecFlags |= InitData;
    205       if ((SecFlags & NoLoad) == 0)
    206         SecFlags |= Load;
    207       break;
    208 
    209     case 's': // shared section
    210       SecFlags |= Shared | InitData;
    211       SecFlags &= ~NoWrite;
    212       if ((SecFlags & NoLoad) == 0)
    213         SecFlags |= Load;
    214       break;
    215 
    216     case 'w': // writable
    217       SecFlags &= ~NoWrite;
    218       ReadOnlyRemoved = true;
    219       break;
    220 
    221     case 'x': // executable section
    222       SecFlags |= Code;
    223       if ((SecFlags & NoLoad) == 0)
    224         SecFlags |= Load;
    225       if (!ReadOnlyRemoved)
    226         SecFlags |= NoWrite;
    227       break;
    228 
    229     case 'y': // not readable
    230       SecFlags |= NoRead | NoWrite;
    231       break;
    232 
    233     default:
    234       return TokError("unknown flag");
    235     }
    236   }
    237 
    238   *Flags = 0;
    239 
    240   if (SecFlags == None)
    241     SecFlags = InitData;
    242 
    243   if (SecFlags & Code)
    244     *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
    245   if (SecFlags & InitData)
    246     *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
    247   if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
    248     *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
    249   if (SecFlags & NoLoad)
    250     *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
    251   if ((SecFlags & NoRead) == 0)
    252     *Flags |= COFF::IMAGE_SCN_MEM_READ;
    253   if ((SecFlags & NoWrite) == 0)
    254     *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
    255   if (SecFlags & Shared)
    256     *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
    257 
    258   return false;
    259 }
    260 
    261 /// ParseDirectiveSymbolAttribute
    262 ///  ::= { ".weak", ... } [ identifier ( , identifier )* ]
    263 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
    264   MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
    265     .Case(".weak", MCSA_Weak)
    266     .Default(MCSA_Invalid);
    267   assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
    268   if (getLexer().isNot(AsmToken::EndOfStatement)) {
    269     for (;;) {
    270       StringRef Name;
    271 
    272       if (getParser().parseIdentifier(Name))
    273         return TokError("expected identifier in directive");
    274 
    275       MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
    276 
    277       getStreamer().EmitSymbolAttribute(Sym, Attr);
    278 
    279       if (getLexer().is(AsmToken::EndOfStatement))
    280         break;
    281 
    282       if (getLexer().isNot(AsmToken::Comma))
    283         return TokError("unexpected token in directive");
    284       Lex();
    285     }
    286   }
    287 
    288   Lex();
    289   return false;
    290 }
    291 
    292 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
    293                                        unsigned Characteristics,
    294                                        SectionKind Kind) {
    295   return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
    296 }
    297 
    298 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
    299                                        unsigned Characteristics,
    300                                        SectionKind Kind,
    301                                        StringRef COMDATSymName,
    302                                        COFF::COMDATType Type) {
    303   if (getLexer().isNot(AsmToken::EndOfStatement))
    304     return TokError("unexpected token in section switching directive");
    305   Lex();
    306 
    307   getStreamer().SwitchSection(getContext().getCOFFSection(
    308       Section, Characteristics, Kind, COMDATSymName, Type));
    309 
    310   return false;
    311 }
    312 
    313 bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
    314   if (!getLexer().is(AsmToken::Identifier))
    315     return true;
    316 
    317   SectionName = getTok().getIdentifier();
    318   Lex();
    319   return false;
    320 }
    321 
    322 // .section name [, "flags"] [, identifier [ identifier ], identifier]
    323 //
    324 // Supported flags:
    325 //   a: Ignored.
    326 //   b: BSS section (uninitialized data)
    327 //   d: data section (initialized data)
    328 //   n: Discardable section
    329 //   r: Readable section
    330 //   s: Shared section
    331 //   w: Writable section
    332 //   x: Executable section
    333 //   y: Not-readable section (clears 'r')
    334 //
    335 // Subsections are not supported.
    336 bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
    337   StringRef SectionName;
    338 
    339   if (ParseSectionName(SectionName))
    340     return TokError("expected identifier in directive");
    341 
    342   unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
    343                    COFF::IMAGE_SCN_MEM_READ |
    344                    COFF::IMAGE_SCN_MEM_WRITE;
    345 
    346   if (getLexer().is(AsmToken::Comma)) {
    347     Lex();
    348 
    349     if (getLexer().isNot(AsmToken::String))
    350       return TokError("expected string in directive");
    351 
    352     StringRef FlagsStr = getTok().getStringContents();
    353     Lex();
    354 
    355     if (ParseSectionFlags(FlagsStr, &Flags))
    356       return true;
    357   }
    358 
    359   COFF::COMDATType Type = (COFF::COMDATType)0;
    360   StringRef COMDATSymName;
    361   if (getLexer().is(AsmToken::Comma)) {
    362     Type = COFF::IMAGE_COMDAT_SELECT_ANY;;
    363     Lex();
    364 
    365     Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
    366 
    367     if (parseCOMDATType(Type))
    368       return true;
    369 
    370     if (getLexer().isNot(AsmToken::Comma))
    371       return TokError("expected comma in directive");
    372     Lex();
    373 
    374     if (getParser().parseIdentifier(COMDATSymName))
    375       return TokError("expected identifier in directive");
    376   }
    377 
    378   if (getLexer().isNot(AsmToken::EndOfStatement))
    379     return TokError("unexpected token in directive");
    380 
    381   SectionKind Kind = computeSectionKind(Flags);
    382   if (Kind.isText()) {
    383     const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
    384     if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
    385       Flags |= COFF::IMAGE_SCN_MEM_16BIT;
    386   }
    387   ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
    388   return false;
    389 }
    390 
    391 bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
    392   StringRef SymbolName;
    393 
    394   if (getParser().parseIdentifier(SymbolName))
    395     return TokError("expected identifier in directive");
    396 
    397   MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
    398 
    399   getStreamer().BeginCOFFSymbolDef(Sym);
    400 
    401   Lex();
    402   return false;
    403 }
    404 
    405 bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
    406   int64_t SymbolStorageClass;
    407   if (getParser().parseAbsoluteExpression(SymbolStorageClass))
    408     return true;
    409 
    410   if (getLexer().isNot(AsmToken::EndOfStatement))
    411     return TokError("unexpected token in directive");
    412 
    413   Lex();
    414   getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
    415   return false;
    416 }
    417 
    418 bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
    419   int64_t Type;
    420   if (getParser().parseAbsoluteExpression(Type))
    421     return true;
    422 
    423   if (getLexer().isNot(AsmToken::EndOfStatement))
    424     return TokError("unexpected token in directive");
    425 
    426   Lex();
    427   getStreamer().EmitCOFFSymbolType(Type);
    428   return false;
    429 }
    430 
    431 bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
    432   Lex();
    433   getStreamer().EndCOFFSymbolDef();
    434   return false;
    435 }
    436 
    437 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
    438   StringRef SymbolID;
    439   if (getParser().parseIdentifier(SymbolID))
    440     return TokError("expected identifier in directive");
    441 
    442   if (getLexer().isNot(AsmToken::EndOfStatement))
    443     return TokError("unexpected token in directive");
    444 
    445   MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
    446 
    447   Lex();
    448   getStreamer().EmitCOFFSecRel32(Symbol);
    449   return false;
    450 }
    451 
    452 bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
    453   StringRef SymbolID;
    454   if (getParser().parseIdentifier(SymbolID))
    455     return TokError("expected identifier in directive");
    456 
    457   if (getLexer().isNot(AsmToken::EndOfStatement))
    458     return TokError("unexpected token in directive");
    459 
    460   MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
    461 
    462   Lex();
    463   getStreamer().EmitCOFFSectionIndex(Symbol);
    464   return false;
    465 }
    466 
    467 /// ::= [ identifier ]
    468 bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
    469   StringRef TypeId = getTok().getIdentifier();
    470 
    471   Type = StringSwitch<COFF::COMDATType>(TypeId)
    472     .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
    473     .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
    474     .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
    475     .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
    476     .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
    477     .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
    478     .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
    479     .Default((COFF::COMDATType)0);
    480 
    481   if (Type == 0)
    482     return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
    483 
    484   Lex();
    485 
    486   return false;
    487 }
    488 
    489 /// ParseDirectiveLinkOnce
    490 ///  ::= .linkonce [ identifier ]
    491 bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
    492   COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
    493   if (getLexer().is(AsmToken::Identifier))
    494     if (parseCOMDATType(Type))
    495       return true;
    496 
    497   const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
    498                                        getStreamer().getCurrentSection().first);
    499 
    500   if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
    501     return Error(Loc, "cannot make section associative with .linkonce");
    502 
    503   if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
    504     return Error(Loc, Twine("section '") + Current->getSectionName() +
    505                                                        "' is already linkonce");
    506 
    507   Current->setSelection(Type);
    508 
    509   if (getLexer().isNot(AsmToken::EndOfStatement))
    510     return TokError("unexpected token in directive");
    511 
    512   return false;
    513 }
    514 
    515 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
    516   StringRef SymbolID;
    517   if (getParser().parseIdentifier(SymbolID))
    518     return true;
    519 
    520   if (getLexer().isNot(AsmToken::EndOfStatement))
    521     return TokError("unexpected token in directive");
    522 
    523   MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
    524 
    525   Lex();
    526   getStreamer().EmitWinCFIStartProc(Symbol);
    527   return false;
    528 }
    529 
    530 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
    531   Lex();
    532   getStreamer().EmitWinCFIEndProc();
    533   return false;
    534 }
    535 
    536 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
    537   Lex();
    538   getStreamer().EmitWinCFIStartChained();
    539   return false;
    540 }
    541 
    542 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
    543   Lex();
    544   getStreamer().EmitWinCFIEndChained();
    545   return false;
    546 }
    547 
    548 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
    549   StringRef SymbolID;
    550   if (getParser().parseIdentifier(SymbolID))
    551     return true;
    552 
    553   if (getLexer().isNot(AsmToken::Comma))
    554     return TokError("you must specify one or both of @unwind or @except");
    555   Lex();
    556   bool unwind = false, except = false;
    557   if (ParseAtUnwindOrAtExcept(unwind, except))
    558     return true;
    559   if (getLexer().is(AsmToken::Comma)) {
    560     Lex();
    561     if (ParseAtUnwindOrAtExcept(unwind, except))
    562       return true;
    563   }
    564   if (getLexer().isNot(AsmToken::EndOfStatement))
    565     return TokError("unexpected token in directive");
    566 
    567   MCSymbol *handler = getContext().GetOrCreateSymbol(SymbolID);
    568 
    569   Lex();
    570   getStreamer().EmitWinEHHandler(handler, unwind, except);
    571   return false;
    572 }
    573 
    574 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
    575   Lex();
    576   getStreamer().EmitWinEHHandlerData();
    577   return false;
    578 }
    579 
    580 bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
    581   unsigned Reg;
    582   if (ParseSEHRegisterNumber(Reg))
    583     return true;
    584 
    585   if (getLexer().isNot(AsmToken::EndOfStatement))
    586     return TokError("unexpected token in directive");
    587 
    588   Lex();
    589   getStreamer().EmitWinCFIPushReg(Reg);
    590   return false;
    591 }
    592 
    593 bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
    594   unsigned Reg;
    595   int64_t Off;
    596   if (ParseSEHRegisterNumber(Reg))
    597     return true;
    598   if (getLexer().isNot(AsmToken::Comma))
    599     return TokError("you must specify a stack pointer offset");
    600 
    601   Lex();
    602   SMLoc startLoc = getLexer().getLoc();
    603   if (getParser().parseAbsoluteExpression(Off))
    604     return true;
    605 
    606   if (Off & 0x0F)
    607     return Error(startLoc, "offset is not a multiple of 16");
    608 
    609   if (getLexer().isNot(AsmToken::EndOfStatement))
    610     return TokError("unexpected token in directive");
    611 
    612   Lex();
    613   getStreamer().EmitWinCFISetFrame(Reg, Off);
    614   return false;
    615 }
    616 
    617 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
    618   int64_t Size;
    619   SMLoc startLoc = getLexer().getLoc();
    620   if (getParser().parseAbsoluteExpression(Size))
    621     return true;
    622 
    623   if (Size & 7)
    624     return Error(startLoc, "size is not a multiple of 8");
    625 
    626   if (getLexer().isNot(AsmToken::EndOfStatement))
    627     return TokError("unexpected token in directive");
    628 
    629   Lex();
    630   getStreamer().EmitWinCFIAllocStack(Size);
    631   return false;
    632 }
    633 
    634 bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
    635   unsigned Reg;
    636   int64_t Off;
    637   if (ParseSEHRegisterNumber(Reg))
    638     return true;
    639   if (getLexer().isNot(AsmToken::Comma))
    640     return TokError("you must specify an offset on the stack");
    641 
    642   Lex();
    643   SMLoc startLoc = getLexer().getLoc();
    644   if (getParser().parseAbsoluteExpression(Off))
    645     return true;
    646 
    647   if (Off & 7)
    648     return Error(startLoc, "size is not a multiple of 8");
    649 
    650   if (getLexer().isNot(AsmToken::EndOfStatement))
    651     return TokError("unexpected token in directive");
    652 
    653   Lex();
    654   // FIXME: Err on %xmm* registers
    655   getStreamer().EmitWinCFISaveReg(Reg, Off);
    656   return false;
    657 }
    658 
    659 // FIXME: This method is inherently x86-specific. It should really be in the
    660 // x86 backend.
    661 bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
    662   unsigned Reg;
    663   int64_t Off;
    664   if (ParseSEHRegisterNumber(Reg))
    665     return true;
    666   if (getLexer().isNot(AsmToken::Comma))
    667     return TokError("you must specify an offset on the stack");
    668 
    669   Lex();
    670   SMLoc startLoc = getLexer().getLoc();
    671   if (getParser().parseAbsoluteExpression(Off))
    672     return true;
    673 
    674   if (getLexer().isNot(AsmToken::EndOfStatement))
    675     return TokError("unexpected token in directive");
    676 
    677   if (Off & 0x0F)
    678     return Error(startLoc, "offset is not a multiple of 16");
    679 
    680   Lex();
    681   // FIXME: Err on non-%xmm* registers
    682   getStreamer().EmitWinCFISaveXMM(Reg, Off);
    683   return false;
    684 }
    685 
    686 bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
    687   bool Code = false;
    688   StringRef CodeID;
    689   if (getLexer().is(AsmToken::At)) {
    690     SMLoc startLoc = getLexer().getLoc();
    691     Lex();
    692     if (!getParser().parseIdentifier(CodeID)) {
    693       if (CodeID != "code")
    694         return Error(startLoc, "expected @code");
    695       Code = true;
    696     }
    697   }
    698 
    699   if (getLexer().isNot(AsmToken::EndOfStatement))
    700     return TokError("unexpected token in directive");
    701 
    702   Lex();
    703   getStreamer().EmitWinCFIPushFrame(Code);
    704   return false;
    705 }
    706 
    707 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
    708   Lex();
    709   getStreamer().EmitWinCFIEndProlog();
    710   return false;
    711 }
    712 
    713 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
    714   StringRef identifier;
    715   if (getLexer().isNot(AsmToken::At))
    716     return TokError("a handler attribute must begin with '@'");
    717   SMLoc startLoc = getLexer().getLoc();
    718   Lex();
    719   if (getParser().parseIdentifier(identifier))
    720     return Error(startLoc, "expected @unwind or @except");
    721   if (identifier == "unwind")
    722     unwind = true;
    723   else if (identifier == "except")
    724     except = true;
    725   else
    726     return Error(startLoc, "expected @unwind or @except");
    727   return false;
    728 }
    729 
    730 bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
    731   SMLoc startLoc = getLexer().getLoc();
    732   if (getLexer().is(AsmToken::Percent)) {
    733     const MCRegisterInfo *MRI = getContext().getRegisterInfo();
    734     SMLoc endLoc;
    735     unsigned LLVMRegNo;
    736     if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
    737       return true;
    738 
    739 #if 0
    740     // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
    741     // violation so this validation code is disabled.
    742 
    743     // Check that this is a non-volatile register.
    744     const unsigned *NVRegs = TAI.getCalleeSavedRegs();
    745     unsigned i;
    746     for (i = 0; NVRegs[i] != 0; ++i)
    747       if (NVRegs[i] == LLVMRegNo)
    748         break;
    749     if (NVRegs[i] == 0)
    750       return Error(startLoc, "expected non-volatile register");
    751 #endif
    752 
    753     int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
    754     if (SEHRegNo < 0)
    755       return Error(startLoc,"register can't be represented in SEH unwind info");
    756     RegNo = SEHRegNo;
    757   }
    758   else {
    759     int64_t n;
    760     if (getParser().parseAbsoluteExpression(n))
    761       return true;
    762     if (n > 15)
    763       return Error(startLoc, "register number is too high");
    764     RegNo = n;
    765   }
    766 
    767   return false;
    768 }
    769 
    770 namespace llvm {
    771 
    772 MCAsmParserExtension *createCOFFAsmParser() {
    773   return new COFFAsmParser;
    774 }
    775 
    776 }
    777