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

Generated by: LCOV version 1.13