Path: blob/main/contrib/llvm-project/llvm/lib/MC/MCParser/COFFAsmParser.cpp
35294 views
//===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/ADT/StringRef.h"9#include "llvm/ADT/StringSwitch.h"10#include "llvm/ADT/Twine.h"11#include "llvm/BinaryFormat/COFF.h"12#include "llvm/MC/MCContext.h"13#include "llvm/MC/MCDirectives.h"14#include "llvm/MC/MCParser/MCAsmLexer.h"15#include "llvm/MC/MCParser/MCAsmParserExtension.h"16#include "llvm/MC/MCSectionCOFF.h"17#include "llvm/MC/MCStreamer.h"18#include "llvm/MC/SectionKind.h"19#include "llvm/Support/SMLoc.h"20#include "llvm/TargetParser/Triple.h"21#include <cassert>22#include <cstdint>23#include <limits>24#include <utility>2526using namespace llvm;2728namespace {2930class COFFAsmParser : public MCAsmParserExtension {31template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>32void addDirectiveHandler(StringRef Directive) {33MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(34this, HandleDirective<COFFAsmParser, HandlerMethod>);35getParser().addDirectiveHandler(Directive, Handler);36}3738bool ParseSectionSwitch(StringRef Section, unsigned Characteristics);3940bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,41StringRef COMDATSymName, COFF::COMDATType Type);4243bool ParseSectionName(StringRef &SectionName);44bool ParseSectionFlags(StringRef SectionName, StringRef FlagsString,45unsigned *Flags);4647void Initialize(MCAsmParser &Parser) override {48// Call the base implementation.49MCAsmParserExtension::Initialize(Parser);5051addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");52addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");53addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");54addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");55addDirectiveHandler<&COFFAsmParser::ParseDirectivePushSection>(56".pushsection");57addDirectiveHandler<&COFFAsmParser::ParseDirectivePopSection>(58".popsection");59addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");60addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");61addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");62addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");63addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");64addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymIdx>(".symidx");65addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");66addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");67addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");68addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva");69addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");70addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak_anti_dep");71addDirectiveHandler<&COFFAsmParser::ParseDirectiveCGProfile>(".cg_profile");7273// Win64 EH directives.74addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(75".seh_proc");76addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(77".seh_endproc");78addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndFuncletOrFunc>(79".seh_endfunclet");80addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(81".seh_startchained");82addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(83".seh_endchained");84addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(85".seh_handler");86addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(87".seh_handlerdata");88addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(89".seh_stackalloc");90addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(91".seh_endprologue");92}9394bool ParseSectionDirectiveText(StringRef, SMLoc) {95return ParseSectionSwitch(".text", COFF::IMAGE_SCN_CNT_CODE |96COFF::IMAGE_SCN_MEM_EXECUTE |97COFF::IMAGE_SCN_MEM_READ);98}99100bool ParseSectionDirectiveData(StringRef, SMLoc) {101return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |102COFF::IMAGE_SCN_MEM_READ |103COFF::IMAGE_SCN_MEM_WRITE);104}105106bool ParseSectionDirectiveBSS(StringRef, SMLoc) {107return ParseSectionSwitch(".bss", COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |108COFF::IMAGE_SCN_MEM_READ |109COFF::IMAGE_SCN_MEM_WRITE);110}111112bool ParseDirectiveSection(StringRef, SMLoc);113bool parseSectionArguments(StringRef, SMLoc);114bool ParseDirectivePushSection(StringRef, SMLoc);115bool ParseDirectivePopSection(StringRef, SMLoc);116bool ParseDirectiveDef(StringRef, SMLoc);117bool ParseDirectiveScl(StringRef, SMLoc);118bool ParseDirectiveType(StringRef, SMLoc);119bool ParseDirectiveEndef(StringRef, SMLoc);120bool ParseDirectiveSecRel32(StringRef, SMLoc);121bool ParseDirectiveSecIdx(StringRef, SMLoc);122bool ParseDirectiveSafeSEH(StringRef, SMLoc);123bool ParseDirectiveSymIdx(StringRef, SMLoc);124bool parseCOMDATType(COFF::COMDATType &Type);125bool ParseDirectiveLinkOnce(StringRef, SMLoc);126bool ParseDirectiveRVA(StringRef, SMLoc);127bool ParseDirectiveCGProfile(StringRef, SMLoc);128129// Win64 EH directives.130bool ParseSEHDirectiveStartProc(StringRef, SMLoc);131bool ParseSEHDirectiveEndProc(StringRef, SMLoc);132bool ParseSEHDirectiveEndFuncletOrFunc(StringRef, SMLoc);133bool ParseSEHDirectiveStartChained(StringRef, SMLoc);134bool ParseSEHDirectiveEndChained(StringRef, SMLoc);135bool ParseSEHDirectiveHandler(StringRef, SMLoc);136bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);137bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);138bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);139140bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);141bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);142143public:144COFFAsmParser() = default;145};146147} // end anonymous namespace.148149bool COFFAsmParser::ParseSectionFlags(StringRef SectionName,150StringRef FlagsString, unsigned *Flags) {151enum {152None = 0,153Alloc = 1 << 0,154Code = 1 << 1,155Load = 1 << 2,156InitData = 1 << 3,157Shared = 1 << 4,158NoLoad = 1 << 5,159NoRead = 1 << 6,160NoWrite = 1 << 7,161Discardable = 1 << 8,162Info = 1 << 9,163};164165bool ReadOnlyRemoved = false;166unsigned SecFlags = None;167168for (char FlagChar : FlagsString) {169switch (FlagChar) {170case 'a':171// Ignored.172break;173174case 'b': // bss section175SecFlags |= Alloc;176if (SecFlags & InitData)177return TokError("conflicting section flags 'b' and 'd'.");178SecFlags &= ~Load;179break;180181case 'd': // data section182SecFlags |= InitData;183if (SecFlags & Alloc)184return TokError("conflicting section flags 'b' and 'd'.");185SecFlags &= ~NoWrite;186if ((SecFlags & NoLoad) == 0)187SecFlags |= Load;188break;189190case 'n': // section is not loaded191SecFlags |= NoLoad;192SecFlags &= ~Load;193break;194195case 'D': // discardable196SecFlags |= Discardable;197break;198199case 'r': // read-only200ReadOnlyRemoved = false;201SecFlags |= NoWrite;202if ((SecFlags & Code) == 0)203SecFlags |= InitData;204if ((SecFlags & NoLoad) == 0)205SecFlags |= Load;206break;207208case 's': // shared section209SecFlags |= Shared | InitData;210SecFlags &= ~NoWrite;211if ((SecFlags & NoLoad) == 0)212SecFlags |= Load;213break;214215case 'w': // writable216SecFlags &= ~NoWrite;217ReadOnlyRemoved = true;218break;219220case 'x': // executable section221SecFlags |= Code;222if ((SecFlags & NoLoad) == 0)223SecFlags |= Load;224if (!ReadOnlyRemoved)225SecFlags |= NoWrite;226break;227228case 'y': // not readable229SecFlags |= NoRead | NoWrite;230break;231232case 'i': // info233SecFlags |= Info;234break;235236default:237return TokError("unknown flag");238}239}240241*Flags = 0;242243if (SecFlags == None)244SecFlags = InitData;245246if (SecFlags & Code)247*Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;248if (SecFlags & InitData)249*Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;250if ((SecFlags & Alloc) && (SecFlags & Load) == 0)251*Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;252if (SecFlags & NoLoad)253*Flags |= COFF::IMAGE_SCN_LNK_REMOVE;254if ((SecFlags & Discardable) ||255MCSectionCOFF::isImplicitlyDiscardable(SectionName))256*Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE;257if ((SecFlags & NoRead) == 0)258*Flags |= COFF::IMAGE_SCN_MEM_READ;259if ((SecFlags & NoWrite) == 0)260*Flags |= COFF::IMAGE_SCN_MEM_WRITE;261if (SecFlags & Shared)262*Flags |= COFF::IMAGE_SCN_MEM_SHARED;263if (SecFlags & Info)264*Flags |= COFF::IMAGE_SCN_LNK_INFO;265266return false;267}268269/// ParseDirectiveSymbolAttribute270/// ::= { ".weak", ... } [ identifier ( , identifier )* ]271bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {272MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)273.Case(".weak", MCSA_Weak)274.Case(".weak_anti_dep", MCSA_WeakAntiDep)275.Default(MCSA_Invalid);276assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");277if (getLexer().isNot(AsmToken::EndOfStatement)) {278while (true) {279StringRef Name;280281if (getParser().parseIdentifier(Name))282return TokError("expected identifier in directive");283284MCSymbol *Sym = getContext().getOrCreateSymbol(Name);285286getStreamer().emitSymbolAttribute(Sym, Attr);287288if (getLexer().is(AsmToken::EndOfStatement))289break;290291if (getLexer().isNot(AsmToken::Comma))292return TokError("unexpected token in directive");293Lex();294}295}296297Lex();298return false;299}300301bool COFFAsmParser::ParseDirectiveCGProfile(StringRef S, SMLoc Loc) {302return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc);303}304305bool COFFAsmParser::ParseSectionSwitch(StringRef Section,306unsigned Characteristics) {307return ParseSectionSwitch(Section, Characteristics, "", (COFF::COMDATType)0);308}309310bool COFFAsmParser::ParseSectionSwitch(StringRef Section,311unsigned Characteristics,312StringRef COMDATSymName,313COFF::COMDATType Type) {314if (getLexer().isNot(AsmToken::EndOfStatement))315return TokError("unexpected token in section switching directive");316Lex();317318getStreamer().switchSection(getContext().getCOFFSection(319Section, Characteristics, COMDATSymName, Type));320321return false;322}323324bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {325if (!getLexer().is(AsmToken::Identifier) && !getLexer().is(AsmToken::String))326return true;327328SectionName = getTok().getIdentifier();329Lex();330return false;331}332333bool COFFAsmParser::ParseDirectiveSection(StringRef directive, SMLoc loc) {334return parseSectionArguments(directive, loc);335}336337// .section name [, "flags"] [, identifier [ identifier ], identifier]338// .pushsection <same as above>339//340// Supported flags:341// a: Ignored.342// b: BSS section (uninitialized data)343// d: data section (initialized data)344// n: "noload" section (removed by linker)345// D: Discardable section346// r: Readable section347// s: Shared section348// w: Writable section349// x: Executable section350// y: Not-readable section (clears 'r')351//352// Subsections are not supported.353bool COFFAsmParser::parseSectionArguments(StringRef, SMLoc) {354StringRef SectionName;355356if (ParseSectionName(SectionName))357return TokError("expected identifier in directive");358359unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |360COFF::IMAGE_SCN_MEM_READ |361COFF::IMAGE_SCN_MEM_WRITE;362363if (getLexer().is(AsmToken::Comma)) {364Lex();365366if (getLexer().isNot(AsmToken::String))367return TokError("expected string in directive");368369StringRef FlagsStr = getTok().getStringContents();370Lex();371372if (ParseSectionFlags(SectionName, FlagsStr, &Flags))373return true;374}375376COFF::COMDATType Type = (COFF::COMDATType)0;377StringRef COMDATSymName;378if (getLexer().is(AsmToken::Comma)) {379Type = COFF::IMAGE_COMDAT_SELECT_ANY;380Lex();381382Flags |= COFF::IMAGE_SCN_LNK_COMDAT;383384if (!getLexer().is(AsmToken::Identifier))385return TokError("expected comdat type such as 'discard' or 'largest' "386"after protection bits");387388if (parseCOMDATType(Type))389return true;390391if (getLexer().isNot(AsmToken::Comma))392return TokError("expected comma in directive");393Lex();394395if (getParser().parseIdentifier(COMDATSymName))396return TokError("expected identifier in directive");397}398399if (getLexer().isNot(AsmToken::EndOfStatement))400return TokError("unexpected token in directive");401402if (Flags & COFF::IMAGE_SCN_CNT_CODE) {403const Triple &T = getContext().getTargetTriple();404if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)405Flags |= COFF::IMAGE_SCN_MEM_16BIT;406}407ParseSectionSwitch(SectionName, Flags, COMDATSymName, Type);408return false;409}410411bool COFFAsmParser::ParseDirectivePushSection(StringRef directive, SMLoc loc) {412getStreamer().pushSection();413414if (parseSectionArguments(directive, loc)) {415getStreamer().popSection();416return true;417}418419return false;420}421422bool COFFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) {423if (!getStreamer().popSection())424return TokError(".popsection without corresponding .pushsection");425return false;426}427428bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {429StringRef SymbolName;430431if (getParser().parseIdentifier(SymbolName))432return TokError("expected identifier in directive");433434MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);435436getStreamer().beginCOFFSymbolDef(Sym);437438Lex();439return false;440}441442bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {443int64_t SymbolStorageClass;444if (getParser().parseAbsoluteExpression(SymbolStorageClass))445return true;446447if (getLexer().isNot(AsmToken::EndOfStatement))448return TokError("unexpected token in directive");449450Lex();451getStreamer().emitCOFFSymbolStorageClass(SymbolStorageClass);452return false;453}454455bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {456int64_t Type;457if (getParser().parseAbsoluteExpression(Type))458return true;459460if (getLexer().isNot(AsmToken::EndOfStatement))461return TokError("unexpected token in directive");462463Lex();464getStreamer().emitCOFFSymbolType(Type);465return false;466}467468bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {469Lex();470getStreamer().endCOFFSymbolDef();471return false;472}473474bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {475StringRef SymbolID;476if (getParser().parseIdentifier(SymbolID))477return TokError("expected identifier in directive");478479int64_t Offset = 0;480SMLoc OffsetLoc;481if (getLexer().is(AsmToken::Plus)) {482OffsetLoc = getLexer().getLoc();483if (getParser().parseAbsoluteExpression(Offset))484return true;485}486487if (getLexer().isNot(AsmToken::EndOfStatement))488return TokError("unexpected token in directive");489490if (Offset < 0 || Offset > std::numeric_limits<uint32_t>::max())491return Error(492OffsetLoc,493"invalid '.secrel32' directive offset, can't be less "494"than zero or greater than std::numeric_limits<uint32_t>::max()");495496MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);497498Lex();499getStreamer().emitCOFFSecRel32(Symbol, Offset);500return false;501}502503bool COFFAsmParser::ParseDirectiveRVA(StringRef, SMLoc) {504auto parseOp = [&]() -> bool {505StringRef SymbolID;506if (getParser().parseIdentifier(SymbolID))507return TokError("expected identifier in directive");508509int64_t Offset = 0;510SMLoc OffsetLoc;511if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) {512OffsetLoc = getLexer().getLoc();513if (getParser().parseAbsoluteExpression(Offset))514return true;515}516517if (Offset < std::numeric_limits<int32_t>::min() ||518Offset > std::numeric_limits<int32_t>::max())519return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less "520"than -2147483648 or greater than "521"2147483647");522523MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);524525getStreamer().emitCOFFImgRel32(Symbol, Offset);526return false;527};528529if (getParser().parseMany(parseOp))530return addErrorSuffix(" in directive");531return false;532}533534bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {535StringRef SymbolID;536if (getParser().parseIdentifier(SymbolID))537return TokError("expected identifier in directive");538539if (getLexer().isNot(AsmToken::EndOfStatement))540return TokError("unexpected token in directive");541542MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);543544Lex();545getStreamer().emitCOFFSafeSEH(Symbol);546return false;547}548549bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {550StringRef SymbolID;551if (getParser().parseIdentifier(SymbolID))552return TokError("expected identifier in directive");553554if (getLexer().isNot(AsmToken::EndOfStatement))555return TokError("unexpected token in directive");556557MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);558559Lex();560getStreamer().emitCOFFSectionIndex(Symbol);561return false;562}563564bool COFFAsmParser::ParseDirectiveSymIdx(StringRef, SMLoc) {565StringRef SymbolID;566if (getParser().parseIdentifier(SymbolID))567return TokError("expected identifier in directive");568569if (getLexer().isNot(AsmToken::EndOfStatement))570return TokError("unexpected token in directive");571572MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);573574Lex();575getStreamer().emitCOFFSymbolIndex(Symbol);576return false;577}578579/// ::= [ identifier ]580bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {581StringRef TypeId = getTok().getIdentifier();582583Type = StringSwitch<COFF::COMDATType>(TypeId)584.Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)585.Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)586.Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)587.Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)588.Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)589.Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)590.Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)591.Default((COFF::COMDATType)0);592593if (Type == 0)594return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));595596Lex();597598return false;599}600601/// ParseDirectiveLinkOnce602/// ::= .linkonce [ identifier ]603bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {604COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;605if (getLexer().is(AsmToken::Identifier))606if (parseCOMDATType(Type))607return true;608609const MCSectionCOFF *Current =610static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly());611612if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)613return Error(Loc, "cannot make section associative with .linkonce");614615if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)616return Error(Loc, Twine("section '") + Current->getName() +617"' is already linkonce");618619Current->setSelection(Type);620621if (getLexer().isNot(AsmToken::EndOfStatement))622return TokError("unexpected token in directive");623624return false;625}626627bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc Loc) {628StringRef SymbolID;629if (getParser().parseIdentifier(SymbolID))630return true;631632if (getLexer().isNot(AsmToken::EndOfStatement))633return TokError("unexpected token in directive");634635MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);636637Lex();638getStreamer().emitWinCFIStartProc(Symbol, Loc);639return false;640}641642bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc Loc) {643Lex();644getStreamer().emitWinCFIEndProc(Loc);645return false;646}647648bool COFFAsmParser::ParseSEHDirectiveEndFuncletOrFunc(StringRef, SMLoc Loc) {649Lex();650getStreamer().emitWinCFIFuncletOrFuncEnd(Loc);651return false;652}653654bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc Loc) {655Lex();656getStreamer().emitWinCFIStartChained(Loc);657return false;658}659660bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc Loc) {661Lex();662getStreamer().emitWinCFIEndChained(Loc);663return false;664}665666bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc Loc) {667StringRef SymbolID;668if (getParser().parseIdentifier(SymbolID))669return true;670671if (getLexer().isNot(AsmToken::Comma))672return TokError("you must specify one or both of @unwind or @except");673Lex();674bool unwind = false, except = false;675if (ParseAtUnwindOrAtExcept(unwind, except))676return true;677if (getLexer().is(AsmToken::Comma)) {678Lex();679if (ParseAtUnwindOrAtExcept(unwind, except))680return true;681}682if (getLexer().isNot(AsmToken::EndOfStatement))683return TokError("unexpected token in directive");684685MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);686687Lex();688getStreamer().emitWinEHHandler(handler, unwind, except, Loc);689return false;690}691692bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) {693Lex();694getStreamer().emitWinEHHandlerData();695return false;696}697698bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) {699int64_t Size;700if (getParser().parseAbsoluteExpression(Size))701return true;702703if (getLexer().isNot(AsmToken::EndOfStatement))704return TokError("unexpected token in directive");705706Lex();707getStreamer().emitWinCFIAllocStack(Size, Loc);708return false;709}710711bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) {712Lex();713getStreamer().emitWinCFIEndProlog(Loc);714return false;715}716717bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {718StringRef identifier;719if (getLexer().isNot(AsmToken::At) && getLexer().isNot(AsmToken::Percent))720return TokError("a handler attribute must begin with '@' or '%'");721SMLoc startLoc = getLexer().getLoc();722Lex();723if (getParser().parseIdentifier(identifier))724return Error(startLoc, "expected @unwind or @except");725if (identifier == "unwind")726unwind = true;727else if (identifier == "except")728except = true;729else730return Error(startLoc, "expected @unwind or @except");731return false;732}733734namespace llvm {735736MCAsmParserExtension *createCOFFAsmParser() {737return new COFFAsmParser;738}739740} // end namespace llvm741742743