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