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

Generated by: LCOV version 1.13