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