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