1 //===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
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-exception
7 //===----------------------------------------------------------------------===//
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/MCAsmLexer.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"
30 class COFFAsmParser
: public MCAsmParserExtension
{
31 template<bool (COFFAsmParser::*HandlerMethod
)(StringRef
, SMLoc
)>
32 void addDirectiveHandler(StringRef Directive
) {
33 MCAsmParser::ExtensionDirectiveHandler Handler
= std::make_pair(
34 this, HandleDirective
<COFFAsmParser
, HandlerMethod
>);
35 getParser().addDirectiveHandler(Directive
, Handler
);
38 bool parseSectionSwitch(StringRef Section
, unsigned Characteristics
);
40 bool parseSectionSwitch(StringRef Section
, unsigned Characteristics
,
41 StringRef COMDATSymName
, COFF::COMDATType Type
);
43 bool parseSectionName(StringRef
&SectionName
);
44 bool parseSectionFlags(StringRef SectionName
, StringRef FlagsString
,
47 void Initialize(MCAsmParser
&Parser
) override
{
48 // Call the base implementation.
49 MCAsmParserExtension::Initialize(Parser
);
51 addDirectiveHandler
<&COFFAsmParser::parseSectionDirectiveText
>(".text");
52 addDirectiveHandler
<&COFFAsmParser::parseSectionDirectiveData
>(".data");
53 addDirectiveHandler
<&COFFAsmParser::parseSectionDirectiveBSS
>(".bss");
54 addDirectiveHandler
<&COFFAsmParser::parseDirectiveSection
>(".section");
55 addDirectiveHandler
<&COFFAsmParser::parseDirectivePushSection
>(
57 addDirectiveHandler
<&COFFAsmParser::parseDirectivePopSection
>(
59 addDirectiveHandler
<&COFFAsmParser::parseDirectiveDef
>(".def");
60 addDirectiveHandler
<&COFFAsmParser::parseDirectiveScl
>(".scl");
61 addDirectiveHandler
<&COFFAsmParser::parseDirectiveType
>(".type");
62 addDirectiveHandler
<&COFFAsmParser::parseDirectiveEndef
>(".endef");
63 addDirectiveHandler
<&COFFAsmParser::parseDirectiveSecRel32
>(".secrel32");
64 addDirectiveHandler
<&COFFAsmParser::parseDirectiveSymIdx
>(".symidx");
65 addDirectiveHandler
<&COFFAsmParser::parseDirectiveSafeSEH
>(".safeseh");
66 addDirectiveHandler
<&COFFAsmParser::parseDirectiveSecIdx
>(".secidx");
67 addDirectiveHandler
<&COFFAsmParser::parseDirectiveLinkOnce
>(".linkonce");
68 addDirectiveHandler
<&COFFAsmParser::parseDirectiveRVA
>(".rva");
69 addDirectiveHandler
<&COFFAsmParser::parseDirectiveSymbolAttribute
>(".weak");
70 addDirectiveHandler
<&COFFAsmParser::parseDirectiveSymbolAttribute
>(
72 addDirectiveHandler
<&COFFAsmParser::parseDirectiveCGProfile
>(".cg_profile");
74 // Win64 EH directives.
75 addDirectiveHandler
<&COFFAsmParser::parseSEHDirectiveStartProc
>(
77 addDirectiveHandler
<&COFFAsmParser::parseSEHDirectiveEndProc
>(
79 addDirectiveHandler
<&COFFAsmParser::parseSEHDirectiveEndFuncletOrFunc
>(
81 addDirectiveHandler
<&COFFAsmParser::parseSEHDirectiveStartChained
>(
83 addDirectiveHandler
<&COFFAsmParser::parseSEHDirectiveEndChained
>(
85 addDirectiveHandler
<&COFFAsmParser::parseSEHDirectiveHandler
>(
87 addDirectiveHandler
<&COFFAsmParser::parseSEHDirectiveHandlerData
>(
89 addDirectiveHandler
<&COFFAsmParser::parseSEHDirectiveAllocStack
>(
91 addDirectiveHandler
<&COFFAsmParser::parseSEHDirectiveEndProlog
>(
95 bool parseSectionDirectiveText(StringRef
, SMLoc
) {
96 return parseSectionSwitch(".text", COFF::IMAGE_SCN_CNT_CODE
|
97 COFF::IMAGE_SCN_MEM_EXECUTE
|
98 COFF::IMAGE_SCN_MEM_READ
);
101 bool parseSectionDirectiveData(StringRef
, SMLoc
) {
102 return parseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
|
103 COFF::IMAGE_SCN_MEM_READ
|
104 COFF::IMAGE_SCN_MEM_WRITE
);
107 bool parseSectionDirectiveBSS(StringRef
, SMLoc
) {
108 return parseSectionSwitch(".bss", COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
|
109 COFF::IMAGE_SCN_MEM_READ
|
110 COFF::IMAGE_SCN_MEM_WRITE
);
113 bool parseDirectiveSection(StringRef
, SMLoc
);
114 bool parseSectionArguments(StringRef
, SMLoc
);
115 bool parseDirectivePushSection(StringRef
, SMLoc
);
116 bool parseDirectivePopSection(StringRef
, SMLoc
);
117 bool parseDirectiveDef(StringRef
, SMLoc
);
118 bool parseDirectiveScl(StringRef
, SMLoc
);
119 bool parseDirectiveType(StringRef
, SMLoc
);
120 bool parseDirectiveEndef(StringRef
, SMLoc
);
121 bool parseDirectiveSecRel32(StringRef
, SMLoc
);
122 bool parseDirectiveSecIdx(StringRef
, SMLoc
);
123 bool parseDirectiveSafeSEH(StringRef
, SMLoc
);
124 bool parseDirectiveSymIdx(StringRef
, SMLoc
);
125 bool parseCOMDATType(COFF::COMDATType
&Type
);
126 bool parseDirectiveLinkOnce(StringRef
, SMLoc
);
127 bool parseDirectiveRVA(StringRef
, SMLoc
);
128 bool parseDirectiveCGProfile(StringRef
, SMLoc
);
130 // Win64 EH directives.
131 bool parseSEHDirectiveStartProc(StringRef
, SMLoc
);
132 bool parseSEHDirectiveEndProc(StringRef
, SMLoc
);
133 bool parseSEHDirectiveEndFuncletOrFunc(StringRef
, SMLoc
);
134 bool parseSEHDirectiveStartChained(StringRef
, SMLoc
);
135 bool parseSEHDirectiveEndChained(StringRef
, SMLoc
);
136 bool parseSEHDirectiveHandler(StringRef
, SMLoc
);
137 bool parseSEHDirectiveHandlerData(StringRef
, SMLoc
);
138 bool parseSEHDirectiveAllocStack(StringRef
, SMLoc
);
139 bool parseSEHDirectiveEndProlog(StringRef
, SMLoc
);
141 bool parseAtUnwindOrAtExcept(bool &unwind
, bool &except
);
142 bool parseDirectiveSymbolAttribute(StringRef Directive
, SMLoc
);
145 COFFAsmParser() = default;
148 } // end anonymous namespace.
150 bool COFFAsmParser::parseSectionFlags(StringRef SectionName
,
151 StringRef FlagsString
, unsigned *Flags
) {
162 Discardable
= 1 << 8,
166 bool ReadOnlyRemoved
= false;
167 unsigned SecFlags
= None
;
169 for (char FlagChar
: FlagsString
) {
175 case 'b': // bss section
177 if (SecFlags
& InitData
)
178 return TokError("conflicting section flags 'b' and 'd'.");
182 case 'd': // data section
183 SecFlags
|= InitData
;
184 if (SecFlags
& Alloc
)
185 return TokError("conflicting section flags 'b' and 'd'.");
186 SecFlags
&= ~NoWrite
;
187 if ((SecFlags
& NoLoad
) == 0)
191 case 'n': // section is not loaded
196 case 'D': // discardable
197 SecFlags
|= Discardable
;
200 case 'r': // read-only
201 ReadOnlyRemoved
= false;
203 if ((SecFlags
& Code
) == 0)
204 SecFlags
|= InitData
;
205 if ((SecFlags
& NoLoad
) == 0)
209 case 's': // shared section
210 SecFlags
|= Shared
| InitData
;
211 SecFlags
&= ~NoWrite
;
212 if ((SecFlags
& NoLoad
) == 0)
216 case 'w': // writable
217 SecFlags
&= ~NoWrite
;
218 ReadOnlyRemoved
= true;
221 case 'x': // executable section
223 if ((SecFlags
& NoLoad
) == 0)
225 if (!ReadOnlyRemoved
)
229 case 'y': // not readable
230 SecFlags
|= NoRead
| NoWrite
;
238 return TokError("unknown flag");
244 if (SecFlags
== None
)
248 *Flags
|= COFF::IMAGE_SCN_CNT_CODE
| COFF::IMAGE_SCN_MEM_EXECUTE
;
249 if (SecFlags
& InitData
)
250 *Flags
|= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
;
251 if ((SecFlags
& Alloc
) && (SecFlags
& Load
) == 0)
252 *Flags
|= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
;
253 if (SecFlags
& NoLoad
)
254 *Flags
|= COFF::IMAGE_SCN_LNK_REMOVE
;
255 if ((SecFlags
& Discardable
) ||
256 MCSectionCOFF::isImplicitlyDiscardable(SectionName
))
257 *Flags
|= COFF::IMAGE_SCN_MEM_DISCARDABLE
;
258 if ((SecFlags
& NoRead
) == 0)
259 *Flags
|= COFF::IMAGE_SCN_MEM_READ
;
260 if ((SecFlags
& NoWrite
) == 0)
261 *Flags
|= COFF::IMAGE_SCN_MEM_WRITE
;
262 if (SecFlags
& Shared
)
263 *Flags
|= COFF::IMAGE_SCN_MEM_SHARED
;
265 *Flags
|= COFF::IMAGE_SCN_LNK_INFO
;
270 /// ParseDirectiveSymbolAttribute
271 /// ::= { ".weak", ... } [ identifier ( , identifier )* ]
272 bool COFFAsmParser::parseDirectiveSymbolAttribute(StringRef Directive
, SMLoc
) {
273 MCSymbolAttr Attr
= StringSwitch
<MCSymbolAttr
>(Directive
)
274 .Case(".weak", MCSA_Weak
)
275 .Case(".weak_anti_dep", MCSA_WeakAntiDep
)
276 .Default(MCSA_Invalid
);
277 assert(Attr
!= MCSA_Invalid
&& "unexpected symbol attribute directive!");
278 if (getLexer().isNot(AsmToken::EndOfStatement
)) {
282 if (getParser().parseIdentifier(Name
))
283 return TokError("expected identifier in directive");
285 MCSymbol
*Sym
= getContext().getOrCreateSymbol(Name
);
287 getStreamer().emitSymbolAttribute(Sym
, Attr
);
289 if (getLexer().is(AsmToken::EndOfStatement
))
292 if (getLexer().isNot(AsmToken::Comma
))
293 return TokError("unexpected token in directive");
302 bool COFFAsmParser::parseDirectiveCGProfile(StringRef S
, SMLoc Loc
) {
303 return MCAsmParserExtension::parseDirectiveCGProfile(S
, Loc
);
306 bool COFFAsmParser::parseSectionSwitch(StringRef Section
,
307 unsigned Characteristics
) {
308 return parseSectionSwitch(Section
, Characteristics
, "", (COFF::COMDATType
)0);
311 bool COFFAsmParser::parseSectionSwitch(StringRef Section
,
312 unsigned Characteristics
,
313 StringRef COMDATSymName
,
314 COFF::COMDATType Type
) {
315 if (getLexer().isNot(AsmToken::EndOfStatement
))
316 return TokError("unexpected token in section switching directive");
319 getStreamer().switchSection(getContext().getCOFFSection(
320 Section
, Characteristics
, COMDATSymName
, Type
));
325 bool COFFAsmParser::parseSectionName(StringRef
&SectionName
) {
326 if (!getLexer().is(AsmToken::Identifier
) && !getLexer().is(AsmToken::String
))
329 SectionName
= getTok().getIdentifier();
334 bool COFFAsmParser::parseDirectiveSection(StringRef directive
, SMLoc loc
) {
335 return parseSectionArguments(directive
, loc
);
338 // .section name [, "flags"] [, identifier [ identifier ], identifier]
339 // .pushsection <same as above>
343 // b: BSS section (uninitialized data)
344 // d: data section (initialized data)
345 // n: "noload" section (removed by linker)
346 // D: Discardable section
347 // r: Readable section
349 // w: Writable section
350 // x: Executable section
351 // y: Not-readable section (clears 'r')
353 // Subsections are not supported.
354 bool COFFAsmParser::parseSectionArguments(StringRef
, SMLoc
) {
355 StringRef SectionName
;
357 if (parseSectionName(SectionName
))
358 return TokError("expected identifier in directive");
360 unsigned Flags
= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
|
361 COFF::IMAGE_SCN_MEM_READ
|
362 COFF::IMAGE_SCN_MEM_WRITE
;
364 if (getLexer().is(AsmToken::Comma
)) {
367 if (getLexer().isNot(AsmToken::String
))
368 return TokError("expected string in directive");
370 StringRef FlagsStr
= getTok().getStringContents();
373 if (parseSectionFlags(SectionName
, FlagsStr
, &Flags
))
377 COFF::COMDATType Type
= (COFF::COMDATType
)0;
378 StringRef COMDATSymName
;
379 if (getLexer().is(AsmToken::Comma
)) {
380 Type
= COFF::IMAGE_COMDAT_SELECT_ANY
;
383 Flags
|= COFF::IMAGE_SCN_LNK_COMDAT
;
385 if (!getLexer().is(AsmToken::Identifier
))
386 return TokError("expected comdat type such as 'discard' or 'largest' "
387 "after protection bits");
389 if (parseCOMDATType(Type
))
392 if (getLexer().isNot(AsmToken::Comma
))
393 return TokError("expected comma in directive");
396 if (getParser().parseIdentifier(COMDATSymName
))
397 return TokError("expected identifier in directive");
400 if (getLexer().isNot(AsmToken::EndOfStatement
))
401 return TokError("unexpected token in directive");
403 if (Flags
& COFF::IMAGE_SCN_CNT_CODE
) {
404 const Triple
&T
= getContext().getTargetTriple();
405 if (T
.getArch() == Triple::arm
|| T
.getArch() == Triple::thumb
)
406 Flags
|= COFF::IMAGE_SCN_MEM_16BIT
;
408 parseSectionSwitch(SectionName
, Flags
, COMDATSymName
, Type
);
412 bool COFFAsmParser::parseDirectivePushSection(StringRef directive
, SMLoc loc
) {
413 getStreamer().pushSection();
415 if (parseSectionArguments(directive
, loc
)) {
416 getStreamer().popSection();
423 bool COFFAsmParser::parseDirectivePopSection(StringRef
, SMLoc
) {
424 if (!getStreamer().popSection())
425 return TokError(".popsection without corresponding .pushsection");
429 bool COFFAsmParser::parseDirectiveDef(StringRef
, SMLoc
) {
430 StringRef SymbolName
;
432 if (getParser().parseIdentifier(SymbolName
))
433 return TokError("expected identifier in directive");
435 MCSymbol
*Sym
= getContext().getOrCreateSymbol(SymbolName
);
437 getStreamer().beginCOFFSymbolDef(Sym
);
443 bool COFFAsmParser::parseDirectiveScl(StringRef
, SMLoc
) {
444 int64_t SymbolStorageClass
;
445 if (getParser().parseAbsoluteExpression(SymbolStorageClass
))
448 if (getLexer().isNot(AsmToken::EndOfStatement
))
449 return TokError("unexpected token in directive");
452 getStreamer().emitCOFFSymbolStorageClass(SymbolStorageClass
);
456 bool COFFAsmParser::parseDirectiveType(StringRef
, SMLoc
) {
458 if (getParser().parseAbsoluteExpression(Type
))
461 if (getLexer().isNot(AsmToken::EndOfStatement
))
462 return TokError("unexpected token in directive");
465 getStreamer().emitCOFFSymbolType(Type
);
469 bool COFFAsmParser::parseDirectiveEndef(StringRef
, SMLoc
) {
471 getStreamer().endCOFFSymbolDef();
475 bool COFFAsmParser::parseDirectiveSecRel32(StringRef
, SMLoc
) {
477 if (getParser().parseIdentifier(SymbolID
))
478 return TokError("expected identifier in directive");
482 if (getLexer().is(AsmToken::Plus
)) {
483 OffsetLoc
= getLexer().getLoc();
484 if (getParser().parseAbsoluteExpression(Offset
))
488 if (getLexer().isNot(AsmToken::EndOfStatement
))
489 return TokError("unexpected token in directive");
491 if (Offset
< 0 || Offset
> std::numeric_limits
<uint32_t>::max())
494 "invalid '.secrel32' directive offset, can't be less "
495 "than zero or greater than std::numeric_limits<uint32_t>::max()");
497 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(SymbolID
);
500 getStreamer().emitCOFFSecRel32(Symbol
, Offset
);
504 bool COFFAsmParser::parseDirectiveRVA(StringRef
, SMLoc
) {
505 auto parseOp
= [&]() -> bool {
507 if (getParser().parseIdentifier(SymbolID
))
508 return TokError("expected identifier in directive");
512 if (getLexer().is(AsmToken::Plus
) || getLexer().is(AsmToken::Minus
)) {
513 OffsetLoc
= getLexer().getLoc();
514 if (getParser().parseAbsoluteExpression(Offset
))
518 if (Offset
< std::numeric_limits
<int32_t>::min() ||
519 Offset
> std::numeric_limits
<int32_t>::max())
520 return Error(OffsetLoc
, "invalid '.rva' directive offset, can't be less "
521 "than -2147483648 or greater than "
524 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(SymbolID
);
526 getStreamer().emitCOFFImgRel32(Symbol
, Offset
);
530 if (getParser().parseMany(parseOp
))
531 return addErrorSuffix(" in directive");
535 bool COFFAsmParser::parseDirectiveSafeSEH(StringRef
, SMLoc
) {
537 if (getParser().parseIdentifier(SymbolID
))
538 return TokError("expected identifier in directive");
540 if (getLexer().isNot(AsmToken::EndOfStatement
))
541 return TokError("unexpected token in directive");
543 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(SymbolID
);
546 getStreamer().emitCOFFSafeSEH(Symbol
);
550 bool COFFAsmParser::parseDirectiveSecIdx(StringRef
, SMLoc
) {
552 if (getParser().parseIdentifier(SymbolID
))
553 return TokError("expected identifier in directive");
555 if (getLexer().isNot(AsmToken::EndOfStatement
))
556 return TokError("unexpected token in directive");
558 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(SymbolID
);
561 getStreamer().emitCOFFSectionIndex(Symbol
);
565 bool COFFAsmParser::parseDirectiveSymIdx(StringRef
, SMLoc
) {
567 if (getParser().parseIdentifier(SymbolID
))
568 return TokError("expected identifier in directive");
570 if (getLexer().isNot(AsmToken::EndOfStatement
))
571 return TokError("unexpected token in directive");
573 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(SymbolID
);
576 getStreamer().emitCOFFSymbolIndex(Symbol
);
580 /// ::= [ identifier ]
581 bool COFFAsmParser::parseCOMDATType(COFF::COMDATType
&Type
) {
582 StringRef TypeId
= getTok().getIdentifier();
584 Type
= StringSwitch
<COFF::COMDATType
>(TypeId
)
585 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES
)
586 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY
)
587 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE
)
588 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH
)
589 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE
)
590 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST
)
591 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST
)
592 .Default((COFF::COMDATType
)0);
595 return TokError(Twine("unrecognized COMDAT type '" + TypeId
+ "'"));
602 /// ParseDirectiveLinkOnce
603 /// ::= .linkonce [ identifier ]
604 bool COFFAsmParser::parseDirectiveLinkOnce(StringRef
, SMLoc Loc
) {
605 COFF::COMDATType Type
= COFF::IMAGE_COMDAT_SELECT_ANY
;
606 if (getLexer().is(AsmToken::Identifier
))
607 if (parseCOMDATType(Type
))
610 const MCSectionCOFF
*Current
=
611 static_cast<const MCSectionCOFF
*>(getStreamer().getCurrentSectionOnly());
613 if (Type
== COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE
)
614 return Error(Loc
, "cannot make section associative with .linkonce");
616 if (Current
->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT
)
617 return Error(Loc
, Twine("section '") + Current
->getName() +
618 "' is already linkonce");
620 Current
->setSelection(Type
);
622 if (getLexer().isNot(AsmToken::EndOfStatement
))
623 return TokError("unexpected token in directive");
628 bool COFFAsmParser::parseSEHDirectiveStartProc(StringRef
, SMLoc Loc
) {
630 if (getParser().parseIdentifier(SymbolID
))
633 if (getLexer().isNot(AsmToken::EndOfStatement
))
634 return TokError("unexpected token in directive");
636 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(SymbolID
);
639 getStreamer().emitWinCFIStartProc(Symbol
, Loc
);
643 bool COFFAsmParser::parseSEHDirectiveEndProc(StringRef
, SMLoc Loc
) {
645 getStreamer().emitWinCFIEndProc(Loc
);
649 bool COFFAsmParser::parseSEHDirectiveEndFuncletOrFunc(StringRef
, SMLoc Loc
) {
651 getStreamer().emitWinCFIFuncletOrFuncEnd(Loc
);
655 bool COFFAsmParser::parseSEHDirectiveStartChained(StringRef
, SMLoc Loc
) {
657 getStreamer().emitWinCFIStartChained(Loc
);
661 bool COFFAsmParser::parseSEHDirectiveEndChained(StringRef
, SMLoc Loc
) {
663 getStreamer().emitWinCFIEndChained(Loc
);
667 bool COFFAsmParser::parseSEHDirectiveHandler(StringRef
, SMLoc Loc
) {
669 if (getParser().parseIdentifier(SymbolID
))
672 if (getLexer().isNot(AsmToken::Comma
))
673 return TokError("you must specify one or both of @unwind or @except");
675 bool unwind
= false, except
= false;
676 if (parseAtUnwindOrAtExcept(unwind
, except
))
678 if (getLexer().is(AsmToken::Comma
)) {
680 if (parseAtUnwindOrAtExcept(unwind
, except
))
683 if (getLexer().isNot(AsmToken::EndOfStatement
))
684 return TokError("unexpected token in directive");
686 MCSymbol
*handler
= getContext().getOrCreateSymbol(SymbolID
);
689 getStreamer().emitWinEHHandler(handler
, unwind
, except
, Loc
);
693 bool COFFAsmParser::parseSEHDirectiveHandlerData(StringRef
, SMLoc Loc
) {
695 getStreamer().emitWinEHHandlerData();
699 bool COFFAsmParser::parseSEHDirectiveAllocStack(StringRef
, SMLoc Loc
) {
701 if (getParser().parseAbsoluteExpression(Size
))
704 if (getLexer().isNot(AsmToken::EndOfStatement
))
705 return TokError("unexpected token in directive");
708 getStreamer().emitWinCFIAllocStack(Size
, Loc
);
712 bool COFFAsmParser::parseSEHDirectiveEndProlog(StringRef
, SMLoc Loc
) {
714 getStreamer().emitWinCFIEndProlog(Loc
);
718 bool COFFAsmParser::parseAtUnwindOrAtExcept(bool &unwind
, bool &except
) {
719 StringRef identifier
;
720 if (getLexer().isNot(AsmToken::At
) && getLexer().isNot(AsmToken::Percent
))
721 return TokError("a handler attribute must begin with '@' or '%'");
722 SMLoc startLoc
= getLexer().getLoc();
724 if (getParser().parseIdentifier(identifier
))
725 return Error(startLoc
, "expected @unwind or @except");
726 if (identifier
== "unwind")
728 else if (identifier
== "except")
731 return Error(startLoc
, "expected @unwind or @except");
737 MCAsmParserExtension
*createCOFFAsmParser() {
738 return new COFFAsmParser
;
741 } // end namespace llvm