LCOV - code coverage report
Current view: top level - lib/MC/MCParser - COFFAsmParser.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 362 411 88.1 %
Date: 2017-09-14 15:23:50 Functions: 35 36 97.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13