brintos

brintos / llvm-project-archived public Read only

0
0
Text · 24.6 KiB · d9ec04c Raw
800 lines · cpp
1//===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ADT/StringRef.h"10#include "llvm/ADT/StringSwitch.h"11#include "llvm/ADT/Twine.h"12#include "llvm/BinaryFormat/COFF.h"13#include "llvm/MC/MCContext.h"14#include "llvm/MC/MCDirectives.h"15#include "llvm/MC/MCParser/AsmLexer.h"16#include "llvm/MC/MCParser/MCAsmParserExtension.h"17#include "llvm/MC/MCSectionCOFF.h"18#include "llvm/MC/MCStreamer.h"19#include "llvm/Support/SMLoc.h"20#include "llvm/TargetParser/Triple.h"21#include <cassert>22#include <cstdint>23#include <limits>24 25using namespace llvm;26 27namespace {28 29class COFFAsmParser : public MCAsmParserExtension {30  template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>31  void addDirectiveHandler(StringRef Directive) {32    MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(33        this, HandleDirective<COFFAsmParser, HandlerMethod>);34    getParser().addDirectiveHandler(Directive, Handler);35  }36 37  bool parseSectionSwitch(StringRef Section, unsigned Characteristics);38 39  bool parseSectionSwitch(StringRef Section, unsigned Characteristics,40                          StringRef COMDATSymName, COFF::COMDATType Type,41                          unsigned UniqueID);42 43  bool parseSectionName(StringRef &SectionName);44  bool parseSectionFlags(StringRef SectionName, StringRef FlagsString,45                         unsigned *Flags);46  void Initialize(MCAsmParser &Parser) override {47    // Call the base implementation.48    MCAsmParserExtension::Initialize(Parser);49 50    addDirectiveHandler<&COFFAsmParser::parseSectionDirectiveText>(".text");51    addDirectiveHandler<&COFFAsmParser::parseSectionDirectiveData>(".data");52    addDirectiveHandler<&COFFAsmParser::parseSectionDirectiveBSS>(".bss");53    addDirectiveHandler<&COFFAsmParser::parseDirectiveSection>(".section");54    addDirectiveHandler<&COFFAsmParser::parseDirectivePushSection>(55        ".pushsection");56    addDirectiveHandler<&COFFAsmParser::parseDirectivePopSection>(57        ".popsection");58    addDirectiveHandler<&COFFAsmParser::parseDirectiveDef>(".def");59    addDirectiveHandler<&COFFAsmParser::parseDirectiveScl>(".scl");60    addDirectiveHandler<&COFFAsmParser::parseDirectiveType>(".type");61    addDirectiveHandler<&COFFAsmParser::parseDirectiveEndef>(".endef");62    addDirectiveHandler<&COFFAsmParser::parseDirectiveSecRel32>(".secrel32");63    addDirectiveHandler<&COFFAsmParser::parseDirectiveSymIdx>(".symidx");64    addDirectiveHandler<&COFFAsmParser::parseDirectiveSafeSEH>(".safeseh");65    addDirectiveHandler<&COFFAsmParser::parseDirectiveSecIdx>(".secidx");66    addDirectiveHandler<&COFFAsmParser::parseDirectiveLinkOnce>(".linkonce");67    addDirectiveHandler<&COFFAsmParser::parseDirectiveRVA>(".rva");68    addDirectiveHandler<&COFFAsmParser::parseDirectiveSymbolAttribute>(".weak");69    addDirectiveHandler<&COFFAsmParser::parseDirectiveSymbolAttribute>(70        ".weak_anti_dep");71    addDirectiveHandler<&COFFAsmParser::parseDirectiveCGProfile>(".cg_profile");72    addDirectiveHandler<&COFFAsmParser::parseDirectiveSecNum>(".secnum");73    addDirectiveHandler<&COFFAsmParser::parseDirectiveSecOffset>(".secoffset");74 75    // Win64 EH directives.76    addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveStartProc>(77        ".seh_proc");78    addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveEndProc>(79        ".seh_endproc");80    addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveEndFuncletOrFunc>(81        ".seh_endfunclet");82    addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveStartChained>(83        ".seh_startchained");84    addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveEndChained>(85        ".seh_endchained");86    addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveHandler>(87        ".seh_handler");88    addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveHandlerData>(89        ".seh_handlerdata");90    addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveAllocStack>(91        ".seh_stackalloc");92    addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveEndProlog>(93        ".seh_endprologue");94    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveBeginEpilog>(95        ".seh_startepilogue");96    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndEpilog>(97        ".seh_endepilogue");98    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveUnwindV2Start>(99        ".seh_unwindv2start");100    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveUnwindVersion>(101        ".seh_unwindversion");102  }103 104  bool parseSectionDirectiveText(StringRef, SMLoc) {105    return parseSectionSwitch(".text", COFF::IMAGE_SCN_CNT_CODE |106                                           COFF::IMAGE_SCN_MEM_EXECUTE |107                                           COFF::IMAGE_SCN_MEM_READ);108  }109 110  bool parseSectionDirectiveData(StringRef, SMLoc) {111    return parseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |112                                           COFF::IMAGE_SCN_MEM_READ |113                                           COFF::IMAGE_SCN_MEM_WRITE);114  }115 116  bool parseSectionDirectiveBSS(StringRef, SMLoc) {117    return parseSectionSwitch(".bss", COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |118                                          COFF::IMAGE_SCN_MEM_READ |119                                          COFF::IMAGE_SCN_MEM_WRITE);120  }121 122  bool parseDirectiveSection(StringRef, SMLoc);123  bool parseSectionArguments(StringRef, SMLoc);124  bool parseDirectivePushSection(StringRef, SMLoc);125  bool parseDirectivePopSection(StringRef, SMLoc);126  bool parseDirectiveDef(StringRef, SMLoc);127  bool parseDirectiveScl(StringRef, SMLoc);128  bool parseDirectiveType(StringRef, SMLoc);129  bool parseDirectiveEndef(StringRef, SMLoc);130  bool parseDirectiveSecRel32(StringRef, SMLoc);131  bool parseDirectiveSecIdx(StringRef, SMLoc);132  bool parseDirectiveSafeSEH(StringRef, SMLoc);133  bool parseDirectiveSymIdx(StringRef, SMLoc);134  bool parseCOMDATType(COFF::COMDATType &Type);135  bool parseDirectiveLinkOnce(StringRef, SMLoc);136  bool parseDirectiveRVA(StringRef, SMLoc);137  bool parseDirectiveCGProfile(StringRef, SMLoc);138  bool parseDirectiveSecNum(StringRef, SMLoc);139  bool parseDirectiveSecOffset(StringRef, SMLoc);140 141  // Win64 EH directives.142  bool parseSEHDirectiveStartProc(StringRef, SMLoc);143  bool parseSEHDirectiveEndProc(StringRef, SMLoc);144  bool parseSEHDirectiveEndFuncletOrFunc(StringRef, SMLoc);145  bool parseSEHDirectiveStartChained(StringRef, SMLoc);146  bool parseSEHDirectiveEndChained(StringRef, SMLoc);147  bool parseSEHDirectiveHandler(StringRef, SMLoc);148  bool parseSEHDirectiveHandlerData(StringRef, SMLoc);149  bool parseSEHDirectiveAllocStack(StringRef, SMLoc);150  bool parseSEHDirectiveEndProlog(StringRef, SMLoc);151  bool ParseSEHDirectiveBeginEpilog(StringRef, SMLoc);152  bool ParseSEHDirectiveEndEpilog(StringRef, SMLoc);153  bool ParseSEHDirectiveUnwindV2Start(StringRef, SMLoc);154  bool ParseSEHDirectiveUnwindVersion(StringRef, SMLoc);155 156  bool parseAtUnwindOrAtExcept(bool &unwind, bool &except);157  bool parseDirectiveSymbolAttribute(StringRef Directive, SMLoc);158 159public:160  COFFAsmParser() = default;161};162 163} // end anonymous namespace.164 165bool COFFAsmParser::parseSectionFlags(StringRef SectionName,166                                      StringRef FlagsString, unsigned *Flags) {167  enum {168    None = 0,169    Alloc = 1 << 0,170    Code = 1 << 1,171    Load = 1 << 2,172    InitData = 1 << 3,173    Shared = 1 << 4,174    NoLoad = 1 << 5,175    NoRead = 1 << 6,176    NoWrite = 1 << 7,177    Discardable = 1 << 8,178    Info = 1 << 9,179  };180 181  bool ReadOnlyRemoved = false;182  unsigned SecFlags = None;183 184  for (char FlagChar : FlagsString) {185    switch (FlagChar) {186    case 'a':187      // Ignored.188      break;189 190    case 'b': // bss section191      SecFlags |= Alloc;192      if (SecFlags & InitData)193        return TokError("conflicting section flags 'b' and 'd'.");194      SecFlags &= ~Load;195      break;196 197    case 'd': // data section198      SecFlags |= InitData;199      if (SecFlags & Alloc)200        return TokError("conflicting section flags 'b' and 'd'.");201      SecFlags &= ~NoWrite;202      if ((SecFlags & NoLoad) == 0)203        SecFlags |= Load;204      break;205 206    case 'n': // section is not loaded207      SecFlags |= NoLoad;208      SecFlags &= ~Load;209      break;210 211    case 'D': // discardable212      SecFlags |= Discardable;213      break;214 215    case 'r': // read-only216      ReadOnlyRemoved = false;217      SecFlags |= NoWrite;218      if ((SecFlags & Code) == 0)219        SecFlags |= InitData;220      if ((SecFlags & NoLoad) == 0)221        SecFlags |= Load;222      break;223 224    case 's': // shared section225      SecFlags |= Shared | InitData;226      SecFlags &= ~NoWrite;227      if ((SecFlags & NoLoad) == 0)228        SecFlags |= Load;229      break;230 231    case 'w': // writable232      SecFlags &= ~NoWrite;233      ReadOnlyRemoved = true;234      break;235 236    case 'x': // executable section237      SecFlags |= Code;238      if ((SecFlags & NoLoad) == 0)239        SecFlags |= Load;240      if (!ReadOnlyRemoved)241        SecFlags |= NoWrite;242      break;243 244    case 'y': // not readable245      SecFlags |= NoRead | NoWrite;246      break;247 248    case 'i': // info249      SecFlags |= Info;250      break;251 252    default:253      return TokError("unknown flag");254    }255  }256 257  *Flags = 0;258 259  if (SecFlags == None)260    SecFlags = InitData;261 262  if (SecFlags & Code)263    *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;264  if (SecFlags & InitData)265    *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;266  if ((SecFlags & Alloc) && (SecFlags & Load) == 0)267    *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;268  if (SecFlags & NoLoad)269    *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;270  if ((SecFlags & Discardable) ||271      MCSectionCOFF::isImplicitlyDiscardable(SectionName))272    *Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE;273  if ((SecFlags & NoRead) == 0)274    *Flags |= COFF::IMAGE_SCN_MEM_READ;275  if ((SecFlags & NoWrite) == 0)276    *Flags |= COFF::IMAGE_SCN_MEM_WRITE;277  if (SecFlags & Shared)278    *Flags |= COFF::IMAGE_SCN_MEM_SHARED;279  if (SecFlags & Info)280    *Flags |= COFF::IMAGE_SCN_LNK_INFO;281 282  return false;283}284 285/// ParseDirectiveSymbolAttribute286///  ::= { ".weak", ... } [ identifier ( , identifier )* ]287bool COFFAsmParser::parseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {288  MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)289    .Case(".weak", MCSA_Weak)290    .Case(".weak_anti_dep", MCSA_WeakAntiDep)291    .Default(MCSA_Invalid);292  assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");293  if (getLexer().isNot(AsmToken::EndOfStatement)) {294    while (true) {295      MCSymbol *Sym;296 297      if (getParser().parseSymbol(Sym))298        return TokError("expected identifier in directive");299 300      getStreamer().emitSymbolAttribute(Sym, Attr);301 302      if (getLexer().is(AsmToken::EndOfStatement))303        break;304 305      if (getLexer().isNot(AsmToken::Comma))306        return TokError("unexpected token in directive");307      Lex();308    }309  }310 311  Lex();312  return false;313}314 315bool COFFAsmParser::parseDirectiveCGProfile(StringRef S, SMLoc Loc) {316  return MCAsmParserExtension::parseDirectiveCGProfile(S, Loc);317}318 319bool COFFAsmParser::parseSectionSwitch(StringRef Section,320                                       unsigned Characteristics) {321  return parseSectionSwitch(Section, Characteristics, "", (COFF::COMDATType)0,322                            MCSection::NonUniqueID);323}324 325bool COFFAsmParser::parseSectionSwitch(StringRef Section,326                                       unsigned Characteristics,327                                       StringRef COMDATSymName,328                                       COFF::COMDATType Type,329                                       unsigned UniqueID) {330  if (getLexer().isNot(AsmToken::EndOfStatement))331    return TokError("unexpected token in section switching directive");332  Lex();333 334  getStreamer().switchSection(getContext().getCOFFSection(335      Section, Characteristics, COMDATSymName, Type, UniqueID));336 337  return false;338}339 340bool COFFAsmParser::parseSectionName(StringRef &SectionName) {341  if (!getLexer().is(AsmToken::Identifier) && !getLexer().is(AsmToken::String))342    return true;343 344  SectionName = getTok().getIdentifier();345  Lex();346  return false;347}348 349bool COFFAsmParser::parseDirectiveSection(StringRef directive, SMLoc loc) {350  return parseSectionArguments(directive, loc);351}352 353// .section name [, "flags"] [, identifier [ identifier ], identifier]354// .pushsection <same as above>355//356// Supported flags:357//   a: Ignored.358//   b: BSS section (uninitialized data)359//   d: data section (initialized data)360//   n: "noload" section (removed by linker)361//   D: Discardable section362//   r: Readable section363//   s: Shared section364//   w: Writable section365//   x: Executable section366//   y: Not-readable section (clears 'r')367//368// Subsections are not supported.369bool COFFAsmParser::parseSectionArguments(StringRef, SMLoc) {370  StringRef SectionName;371 372  if (parseSectionName(SectionName))373    return TokError("expected identifier in directive");374 375  unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |376                   COFF::IMAGE_SCN_MEM_READ |377                   COFF::IMAGE_SCN_MEM_WRITE;378 379  if (getLexer().is(AsmToken::Comma)) {380    Lex();381 382    if (getLexer().isNot(AsmToken::String))383      return TokError("expected string in directive");384 385    StringRef FlagsStr = getTok().getStringContents();386    Lex();387 388    if (parseSectionFlags(SectionName, FlagsStr, &Flags))389      return true;390  }391 392  COFF::COMDATType Type = (COFF::COMDATType)0;393  StringRef COMDATSymName;394  if (getLexer().is(AsmToken::Comma) &&395      getLexer().peekTok().getString() != "unique") {396    Type = COFF::IMAGE_COMDAT_SELECT_ANY;397    Lex();398 399    Flags |= COFF::IMAGE_SCN_LNK_COMDAT;400 401    if (!getLexer().is(AsmToken::Identifier))402      return TokError("expected comdat type such as 'discard' or 'largest' "403                      "after protection bits");404 405    if (parseCOMDATType(Type))406      return true;407 408    if (getLexer().isNot(AsmToken::Comma))409      return TokError("expected comma in directive");410    Lex();411 412    if (getParser().parseIdentifier(COMDATSymName))413      return TokError("expected identifier in directive");414  }415 416  int64_t UniqueID = MCSection::NonUniqueID;417  if (maybeParseUniqueID(UniqueID))418    return true;419 420  if (getLexer().isNot(AsmToken::EndOfStatement))421    return TokError("unexpected token in directive");422 423  if (Flags & COFF::IMAGE_SCN_CNT_CODE) {424    const Triple &T = getContext().getTargetTriple();425    if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)426      Flags |= COFF::IMAGE_SCN_MEM_16BIT;427  }428  parseSectionSwitch(SectionName, Flags, COMDATSymName, Type, UniqueID);429  return false;430}431 432bool COFFAsmParser::parseDirectivePushSection(StringRef directive, SMLoc loc) {433  getStreamer().pushSection();434 435  if (parseSectionArguments(directive, loc)) {436    getStreamer().popSection();437    return true;438  }439 440  return false;441}442 443bool COFFAsmParser::parseDirectivePopSection(StringRef, SMLoc) {444  if (!getStreamer().popSection())445    return TokError(".popsection without corresponding .pushsection");446  return false;447}448 449bool COFFAsmParser::parseDirectiveDef(StringRef, SMLoc) {450  MCSymbol *Sym;451 452  if (getParser().parseSymbol(Sym))453    return TokError("expected identifier in directive");454 455  getStreamer().beginCOFFSymbolDef(Sym);456 457  Lex();458  return false;459}460 461bool COFFAsmParser::parseDirectiveScl(StringRef, SMLoc) {462  int64_t SymbolStorageClass;463  if (getParser().parseAbsoluteExpression(SymbolStorageClass))464    return true;465 466  if (getLexer().isNot(AsmToken::EndOfStatement))467    return TokError("unexpected token in directive");468 469  Lex();470  getStreamer().emitCOFFSymbolStorageClass(SymbolStorageClass);471  return false;472}473 474bool COFFAsmParser::parseDirectiveType(StringRef, SMLoc) {475  int64_t Type;476  if (getParser().parseAbsoluteExpression(Type))477    return true;478 479  if (getLexer().isNot(AsmToken::EndOfStatement))480    return TokError("unexpected token in directive");481 482  Lex();483  getStreamer().emitCOFFSymbolType(Type);484  return false;485}486 487bool COFFAsmParser::parseDirectiveEndef(StringRef, SMLoc) {488  Lex();489  getStreamer().endCOFFSymbolDef();490  return false;491}492 493bool COFFAsmParser::parseDirectiveSecRel32(StringRef, SMLoc) {494  MCSymbol *Symbol;495  if (getParser().parseSymbol(Symbol))496    return TokError("expected identifier in directive");497 498  int64_t Offset = 0;499  SMLoc OffsetLoc;500  if (getLexer().is(AsmToken::Plus)) {501    OffsetLoc = getLexer().getLoc();502    if (getParser().parseAbsoluteExpression(Offset))503      return true;504  }505 506  if (getLexer().isNot(AsmToken::EndOfStatement))507    return TokError("unexpected token in directive");508 509  if (Offset < 0 || Offset > std::numeric_limits<uint32_t>::max())510    return Error(511        OffsetLoc,512        "invalid '.secrel32' directive offset, can't be less "513        "than zero or greater than std::numeric_limits<uint32_t>::max()");514 515  Lex();516  getStreamer().emitCOFFSecRel32(Symbol, Offset);517  return false;518}519 520bool COFFAsmParser::parseDirectiveRVA(StringRef, SMLoc) {521  auto parseOp = [&]() -> bool {522    MCSymbol *Symbol;523    if (getParser().parseSymbol(Symbol))524      return TokError("expected identifier in directive");525 526    int64_t Offset = 0;527    SMLoc OffsetLoc;528    if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) {529      OffsetLoc = getLexer().getLoc();530      if (getParser().parseAbsoluteExpression(Offset))531        return true;532    }533 534    if (Offset < std::numeric_limits<int32_t>::min() ||535        Offset > std::numeric_limits<int32_t>::max())536      return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less "537                              "than -2147483648 or greater than "538                              "2147483647");539 540    getStreamer().emitCOFFImgRel32(Symbol, Offset);541    return false;542  };543 544  if (getParser().parseMany(parseOp))545    return addErrorSuffix(" in directive");546  return false;547}548 549bool COFFAsmParser::parseDirectiveSafeSEH(StringRef, SMLoc) {550  MCSymbol *Symbol;551  if (getParser().parseSymbol(Symbol))552    return TokError("expected identifier in directive");553 554  if (getLexer().isNot(AsmToken::EndOfStatement))555    return TokError("unexpected token in directive");556 557  Lex();558  getStreamer().emitCOFFSafeSEH(Symbol);559  return false;560}561 562bool COFFAsmParser::parseDirectiveSecIdx(StringRef, SMLoc) {563  MCSymbol *Symbol;564  if (getParser().parseSymbol(Symbol))565    return TokError("expected identifier in directive");566 567  if (getLexer().isNot(AsmToken::EndOfStatement))568    return TokError("unexpected token in directive");569 570  Lex();571  getStreamer().emitCOFFSectionIndex(Symbol);572  return false;573}574 575bool COFFAsmParser::parseDirectiveSymIdx(StringRef, SMLoc) {576  MCSymbol *Symbol;577  if (getParser().parseSymbol(Symbol))578    return TokError("expected identifier in directive");579 580  if (getLexer().isNot(AsmToken::EndOfStatement))581    return TokError("unexpected token in directive");582 583  Lex();584  getStreamer().emitCOFFSymbolIndex(Symbol);585  return false;586}587 588bool COFFAsmParser::parseDirectiveSecNum(StringRef, SMLoc) {589  MCSymbol *Symbol;590  if (getParser().parseSymbol(Symbol))591    return TokError("expected identifier in directive");592 593  if (getLexer().isNot(AsmToken::EndOfStatement))594    return TokError("unexpected token in directive");595 596  Lex();597  getStreamer().emitCOFFSecNumber(Symbol);598  return false;599}600 601bool COFFAsmParser::parseDirectiveSecOffset(StringRef, SMLoc) {602  MCSymbol *Symbol;603  if (getParser().parseSymbol(Symbol))604    return TokError("expected identifier in directive");605 606  if (getLexer().isNot(AsmToken::EndOfStatement))607    return TokError("unexpected token in directive");608 609  Lex();610  getStreamer().emitCOFFSecOffset(Symbol);611  return false;612}613 614/// ::= [ identifier ]615bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {616  StringRef TypeId = getTok().getIdentifier();617 618  Type = StringSwitch<COFF::COMDATType>(TypeId)619    .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)620    .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)621    .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)622    .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)623    .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)624    .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)625    .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)626    .Default((COFF::COMDATType)0);627 628  if (Type == 0)629    return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));630 631  Lex();632 633  return false;634}635 636/// ParseDirectiveLinkOnce637///  ::= .linkonce [ identifier ]638bool COFFAsmParser::parseDirectiveLinkOnce(StringRef, SMLoc Loc) {639  COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;640  if (getLexer().is(AsmToken::Identifier))641    if (parseCOMDATType(Type))642      return true;643 644  const MCSectionCOFF *Current =645      static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly());646 647  if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)648    return Error(Loc, "cannot make section associative with .linkonce");649 650  if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)651    return Error(Loc, Twine("section '") + Current->getName() +652                          "' is already linkonce");653 654  Current->setSelection(Type);655 656  if (getLexer().isNot(AsmToken::EndOfStatement))657    return TokError("unexpected token in directive");658 659  return false;660}661 662bool COFFAsmParser::parseSEHDirectiveStartProc(StringRef, SMLoc Loc) {663  MCSymbol *Symbol;664  if (getParser().parseSymbol(Symbol))665    return true;666 667  if (getLexer().isNot(AsmToken::EndOfStatement))668    return TokError("unexpected token in directive");669 670  Lex();671  getStreamer().emitWinCFIStartProc(Symbol, Loc);672  return false;673}674 675bool COFFAsmParser::parseSEHDirectiveEndProc(StringRef, SMLoc Loc) {676  Lex();677  getStreamer().emitWinCFIEndProc(Loc);678  return false;679}680 681bool COFFAsmParser::parseSEHDirectiveEndFuncletOrFunc(StringRef, SMLoc Loc) {682  Lex();683  getStreamer().emitWinCFIFuncletOrFuncEnd(Loc);684  return false;685}686 687bool COFFAsmParser::parseSEHDirectiveStartChained(StringRef, SMLoc Loc) {688  Lex();689  getStreamer().emitWinCFIStartChained(Loc);690  return false;691}692 693bool COFFAsmParser::parseSEHDirectiveEndChained(StringRef, SMLoc Loc) {694  Lex();695  getStreamer().emitWinCFIEndChained(Loc);696  return false;697}698 699bool COFFAsmParser::parseSEHDirectiveHandler(StringRef, SMLoc Loc) {700  MCSymbol *handler;701  if (getParser().parseSymbol(handler))702    return true;703 704  if (getLexer().isNot(AsmToken::Comma))705    return TokError("you must specify one or both of @unwind or @except");706  Lex();707  bool unwind = false, except = false;708  if (parseAtUnwindOrAtExcept(unwind, except))709    return true;710  if (getLexer().is(AsmToken::Comma)) {711    Lex();712    if (parseAtUnwindOrAtExcept(unwind, except))713      return true;714  }715  if (getLexer().isNot(AsmToken::EndOfStatement))716    return TokError("unexpected token in directive");717 718  Lex();719  getStreamer().emitWinEHHandler(handler, unwind, except, Loc);720  return false;721}722 723bool COFFAsmParser::parseSEHDirectiveHandlerData(StringRef, SMLoc Loc) {724  Lex();725  getStreamer().emitWinEHHandlerData();726  return false;727}728 729bool COFFAsmParser::parseSEHDirectiveAllocStack(StringRef, SMLoc Loc) {730  int64_t Size;731  if (getParser().parseAbsoluteExpression(Size))732    return true;733 734  if (getLexer().isNot(AsmToken::EndOfStatement))735    return TokError("unexpected token in directive");736 737  Lex();738  getStreamer().emitWinCFIAllocStack(Size, Loc);739  return false;740}741 742bool COFFAsmParser::parseSEHDirectiveEndProlog(StringRef, SMLoc Loc) {743  Lex();744  getStreamer().emitWinCFIEndProlog(Loc);745  return false;746}747 748bool COFFAsmParser::ParseSEHDirectiveBeginEpilog(StringRef, SMLoc Loc) {749  Lex();750  getStreamer().emitWinCFIBeginEpilogue(Loc);751  return false;752}753 754bool COFFAsmParser::ParseSEHDirectiveEndEpilog(StringRef, SMLoc Loc) {755  Lex();756  getStreamer().emitWinCFIEndEpilogue(Loc);757  return false;758}759 760bool COFFAsmParser::ParseSEHDirectiveUnwindV2Start(StringRef, SMLoc Loc) {761  Lex();762  getStreamer().emitWinCFIUnwindV2Start(Loc);763  return false;764}765 766bool COFFAsmParser::ParseSEHDirectiveUnwindVersion(StringRef, SMLoc Loc) {767  int64_t Version;768  if (getParser().parseIntToken(Version, "expected unwind version number"))769    return true;770 771  if ((Version < 1) || (Version > UINT8_MAX))772    return Error(Loc, "invalid unwind version");773 774  if (getLexer().isNot(AsmToken::EndOfStatement))775    return TokError("unexpected token in directive");776 777  Lex();778  getStreamer().emitWinCFIUnwindVersion(Version, Loc);779  return false;780}781 782bool COFFAsmParser::parseAtUnwindOrAtExcept(bool &unwind, bool &except) {783  StringRef identifier;784  if (getLexer().isNot(AsmToken::At) && getLexer().isNot(AsmToken::Percent))785    return TokError("a handler attribute must begin with '@' or '%'");786  SMLoc startLoc = getLexer().getLoc();787  Lex();788  if (getParser().parseIdentifier(identifier))789    return Error(startLoc, "expected @unwind or @except");790  if (identifier == "unwind")791    unwind = true;792  else if (identifier == "except")793    except = true;794  else795    return Error(startLoc, "expected @unwind or @except");796  return false;797}798 799MCAsmParserExtension *llvm::createCOFFAsmParser() { return new COFFAsmParser; }800