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