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/MC/SectionKind.h"
20 #include "llvm/Support/SMLoc.h"
21 #include "llvm/TargetParser/Triple.h"
31 class COFFAsmParser
: public MCAsmParserExtension
{
32 template<bool (COFFAsmParser::*HandlerMethod
)(StringRef
, SMLoc
)>
33 void addDirectiveHandler(StringRef Directive
) {
34 MCAsmParser::ExtensionDirectiveHandler Handler
= std::make_pair(
35 this, HandleDirective
<COFFAsmParser
, HandlerMethod
>);
36 getParser().addDirectiveHandler(Directive
, Handler
);
39 bool ParseSectionSwitch(StringRef Section
,
40 unsigned Characteristics
,
43 bool ParseSectionSwitch(StringRef Section
, unsigned Characteristics
,
44 SectionKind Kind
, StringRef COMDATSymName
,
45 COFF::COMDATType Type
);
47 bool ParseSectionName(StringRef
&SectionName
);
48 bool ParseSectionFlags(StringRef SectionName
, StringRef FlagsString
,
51 void Initialize(MCAsmParser
&Parser
) override
{
52 // Call the base implementation.
53 MCAsmParserExtension::Initialize(Parser
);
55 addDirectiveHandler
<&COFFAsmParser::ParseSectionDirectiveText
>(".text");
56 addDirectiveHandler
<&COFFAsmParser::ParseSectionDirectiveData
>(".data");
57 addDirectiveHandler
<&COFFAsmParser::ParseSectionDirectiveBSS
>(".bss");
58 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveSection
>(".section");
59 addDirectiveHandler
<&COFFAsmParser::ParseDirectivePushSection
>(
61 addDirectiveHandler
<&COFFAsmParser::ParseDirectivePopSection
>(
63 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveDef
>(".def");
64 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveScl
>(".scl");
65 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveType
>(".type");
66 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveEndef
>(".endef");
67 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveSecRel32
>(".secrel32");
68 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveSymIdx
>(".symidx");
69 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveSafeSEH
>(".safeseh");
70 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveSecIdx
>(".secidx");
71 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveLinkOnce
>(".linkonce");
72 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveRVA
>(".rva");
73 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveSymbolAttribute
>(".weak");
74 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveSymbolAttribute
>(".weak_anti_dep");
75 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveCGProfile
>(".cg_profile");
77 // Win64 EH directives.
78 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveStartProc
>(
80 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveEndProc
>(
82 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveEndFuncletOrFunc
>(
84 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveStartChained
>(
86 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveEndChained
>(
88 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveHandler
>(
90 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveHandlerData
>(
92 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveAllocStack
>(
94 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveEndProlog
>(
98 bool ParseSectionDirectiveText(StringRef
, SMLoc
) {
99 return ParseSectionSwitch(".text",
100 COFF::IMAGE_SCN_CNT_CODE
101 | COFF::IMAGE_SCN_MEM_EXECUTE
102 | COFF::IMAGE_SCN_MEM_READ
,
103 SectionKind::getText());
106 bool ParseSectionDirectiveData(StringRef
, SMLoc
) {
107 return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
|
108 COFF::IMAGE_SCN_MEM_READ
|
109 COFF::IMAGE_SCN_MEM_WRITE
,
110 SectionKind::getData());
113 bool ParseSectionDirectiveBSS(StringRef
, SMLoc
) {
114 return ParseSectionSwitch(".bss",
115 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
116 | COFF::IMAGE_SCN_MEM_READ
117 | COFF::IMAGE_SCN_MEM_WRITE
,
118 SectionKind::getBSS());
121 bool ParseDirectiveSection(StringRef
, SMLoc
);
122 bool parseSectionArguments(StringRef
, SMLoc
);
123 bool ParseDirectivePushSection(StringRef
, SMLoc
);
124 bool ParseDirectivePopSection(StringRef
, SMLoc
);
125 bool ParseDirectiveDef(StringRef
, SMLoc
);
126 bool ParseDirectiveScl(StringRef
, SMLoc
);
127 bool ParseDirectiveType(StringRef
, SMLoc
);
128 bool ParseDirectiveEndef(StringRef
, SMLoc
);
129 bool ParseDirectiveSecRel32(StringRef
, SMLoc
);
130 bool ParseDirectiveSecIdx(StringRef
, SMLoc
);
131 bool ParseDirectiveSafeSEH(StringRef
, SMLoc
);
132 bool ParseDirectiveSymIdx(StringRef
, SMLoc
);
133 bool parseCOMDATType(COFF::COMDATType
&Type
);
134 bool ParseDirectiveLinkOnce(StringRef
, SMLoc
);
135 bool ParseDirectiveRVA(StringRef
, SMLoc
);
136 bool ParseDirectiveCGProfile(StringRef
, SMLoc
);
138 // Win64 EH directives.
139 bool ParseSEHDirectiveStartProc(StringRef
, SMLoc
);
140 bool ParseSEHDirectiveEndProc(StringRef
, SMLoc
);
141 bool ParseSEHDirectiveEndFuncletOrFunc(StringRef
, SMLoc
);
142 bool ParseSEHDirectiveStartChained(StringRef
, SMLoc
);
143 bool ParseSEHDirectiveEndChained(StringRef
, SMLoc
);
144 bool ParseSEHDirectiveHandler(StringRef
, SMLoc
);
145 bool ParseSEHDirectiveHandlerData(StringRef
, SMLoc
);
146 bool ParseSEHDirectiveAllocStack(StringRef
, SMLoc
);
147 bool ParseSEHDirectiveEndProlog(StringRef
, SMLoc
);
149 bool ParseAtUnwindOrAtExcept(bool &unwind
, bool &except
);
150 bool ParseDirectiveSymbolAttribute(StringRef Directive
, SMLoc
);
153 COFFAsmParser() = default;
156 } // end anonymous namespace.
158 static SectionKind
computeSectionKind(unsigned Flags
) {
159 if (Flags
& COFF::IMAGE_SCN_MEM_EXECUTE
)
160 return SectionKind::getText();
161 if (Flags
& COFF::IMAGE_SCN_MEM_READ
&&
162 (Flags
& COFF::IMAGE_SCN_MEM_WRITE
) == 0)
163 return SectionKind::getReadOnly();
164 return SectionKind::getData();
167 bool COFFAsmParser::ParseSectionFlags(StringRef SectionName
,
168 StringRef FlagsString
, unsigned *Flags
) {
179 Discardable
= 1 << 8,
183 bool ReadOnlyRemoved
= false;
184 unsigned SecFlags
= None
;
186 for (char FlagChar
: FlagsString
) {
192 case 'b': // bss section
194 if (SecFlags
& InitData
)
195 return TokError("conflicting section flags 'b' and 'd'.");
199 case 'd': // data section
200 SecFlags
|= InitData
;
201 if (SecFlags
& Alloc
)
202 return TokError("conflicting section flags 'b' and 'd'.");
203 SecFlags
&= ~NoWrite
;
204 if ((SecFlags
& NoLoad
) == 0)
208 case 'n': // section is not loaded
213 case 'D': // discardable
214 SecFlags
|= Discardable
;
217 case 'r': // read-only
218 ReadOnlyRemoved
= false;
220 if ((SecFlags
& Code
) == 0)
221 SecFlags
|= InitData
;
222 if ((SecFlags
& NoLoad
) == 0)
226 case 's': // shared section
227 SecFlags
|= Shared
| InitData
;
228 SecFlags
&= ~NoWrite
;
229 if ((SecFlags
& NoLoad
) == 0)
233 case 'w': // writable
234 SecFlags
&= ~NoWrite
;
235 ReadOnlyRemoved
= true;
238 case 'x': // executable section
240 if ((SecFlags
& NoLoad
) == 0)
242 if (!ReadOnlyRemoved
)
246 case 'y': // not readable
247 SecFlags
|= NoRead
| NoWrite
;
255 return TokError("unknown flag");
261 if (SecFlags
== None
)
265 *Flags
|= COFF::IMAGE_SCN_CNT_CODE
| COFF::IMAGE_SCN_MEM_EXECUTE
;
266 if (SecFlags
& InitData
)
267 *Flags
|= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
;
268 if ((SecFlags
& Alloc
) && (SecFlags
& Load
) == 0)
269 *Flags
|= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
;
270 if (SecFlags
& NoLoad
)
271 *Flags
|= COFF::IMAGE_SCN_LNK_REMOVE
;
272 if ((SecFlags
& Discardable
) ||
273 MCSectionCOFF::isImplicitlyDiscardable(SectionName
))
274 *Flags
|= COFF::IMAGE_SCN_MEM_DISCARDABLE
;
275 if ((SecFlags
& NoRead
) == 0)
276 *Flags
|= COFF::IMAGE_SCN_MEM_READ
;
277 if ((SecFlags
& NoWrite
) == 0)
278 *Flags
|= COFF::IMAGE_SCN_MEM_WRITE
;
279 if (SecFlags
& Shared
)
280 *Flags
|= COFF::IMAGE_SCN_MEM_SHARED
;
282 *Flags
|= COFF::IMAGE_SCN_LNK_INFO
;
287 /// ParseDirectiveSymbolAttribute
288 /// ::= { ".weak", ... } [ identifier ( , identifier )* ]
289 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive
, SMLoc
) {
290 MCSymbolAttr Attr
= StringSwitch
<MCSymbolAttr
>(Directive
)
291 .Case(".weak", MCSA_Weak
)
292 .Case(".weak_anti_dep", MCSA_WeakAntiDep
)
293 .Default(MCSA_Invalid
);
294 assert(Attr
!= MCSA_Invalid
&& "unexpected symbol attribute directive!");
295 if (getLexer().isNot(AsmToken::EndOfStatement
)) {
299 if (getParser().parseIdentifier(Name
))
300 return TokError("expected identifier in directive");
302 MCSymbol
*Sym
= getContext().getOrCreateSymbol(Name
);
304 getStreamer().emitSymbolAttribute(Sym
, Attr
);
306 if (getLexer().is(AsmToken::EndOfStatement
))
309 if (getLexer().isNot(AsmToken::Comma
))
310 return TokError("unexpected token in directive");
319 bool COFFAsmParser::ParseDirectiveCGProfile(StringRef S
, SMLoc Loc
) {
320 return MCAsmParserExtension::ParseDirectiveCGProfile(S
, Loc
);
323 bool COFFAsmParser::ParseSectionSwitch(StringRef Section
,
324 unsigned Characteristics
,
326 return ParseSectionSwitch(Section
, Characteristics
, Kind
, "", (COFF::COMDATType
)0);
329 bool COFFAsmParser::ParseSectionSwitch(StringRef Section
,
330 unsigned Characteristics
,
332 StringRef COMDATSymName
,
333 COFF::COMDATType Type
) {
334 if (getLexer().isNot(AsmToken::EndOfStatement
))
335 return TokError("unexpected token in section switching directive");
338 getStreamer().switchSection(getContext().getCOFFSection(
339 Section
, Characteristics
, Kind
, COMDATSymName
, Type
));
344 bool COFFAsmParser::ParseSectionName(StringRef
&SectionName
) {
345 if (!getLexer().is(AsmToken::Identifier
) && !getLexer().is(AsmToken::String
))
348 SectionName
= getTok().getIdentifier();
353 bool COFFAsmParser::ParseDirectiveSection(StringRef directive
, SMLoc loc
) {
354 return parseSectionArguments(directive
, loc
);
357 // .section name [, "flags"] [, identifier [ identifier ], identifier]
358 // .pushsection <same as above>
362 // b: BSS section (uninitialized data)
363 // d: data section (initialized data)
364 // n: "noload" section (removed by linker)
365 // D: Discardable section
366 // r: Readable section
368 // w: Writable section
369 // x: Executable section
370 // y: Not-readable section (clears 'r')
372 // Subsections are not supported.
373 bool COFFAsmParser::parseSectionArguments(StringRef
, SMLoc
) {
374 StringRef SectionName
;
376 if (ParseSectionName(SectionName
))
377 return TokError("expected identifier in directive");
379 unsigned Flags
= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
|
380 COFF::IMAGE_SCN_MEM_READ
|
381 COFF::IMAGE_SCN_MEM_WRITE
;
383 if (getLexer().is(AsmToken::Comma
)) {
386 if (getLexer().isNot(AsmToken::String
))
387 return TokError("expected string in directive");
389 StringRef FlagsStr
= getTok().getStringContents();
392 if (ParseSectionFlags(SectionName
, FlagsStr
, &Flags
))
396 COFF::COMDATType Type
= (COFF::COMDATType
)0;
397 StringRef COMDATSymName
;
398 if (getLexer().is(AsmToken::Comma
)) {
399 Type
= COFF::IMAGE_COMDAT_SELECT_ANY
;
402 Flags
|= COFF::IMAGE_SCN_LNK_COMDAT
;
404 if (!getLexer().is(AsmToken::Identifier
))
405 return TokError("expected comdat type such as 'discard' or 'largest' "
406 "after protection bits");
408 if (parseCOMDATType(Type
))
411 if (getLexer().isNot(AsmToken::Comma
))
412 return TokError("expected comma in directive");
415 if (getParser().parseIdentifier(COMDATSymName
))
416 return TokError("expected identifier in directive");
419 if (getLexer().isNot(AsmToken::EndOfStatement
))
420 return TokError("unexpected token in directive");
422 SectionKind Kind
= computeSectionKind(Flags
);
424 const Triple
&T
= getContext().getTargetTriple();
425 if (T
.getArch() == Triple::arm
|| T
.getArch() == Triple::thumb
)
426 Flags
|= COFF::IMAGE_SCN_MEM_16BIT
;
428 ParseSectionSwitch(SectionName
, Flags
, Kind
, COMDATSymName
, Type
);
432 bool COFFAsmParser::ParseDirectivePushSection(StringRef directive
, SMLoc loc
) {
433 getStreamer().pushSection();
435 if (parseSectionArguments(directive
, loc
)) {
436 getStreamer().popSection();
443 bool COFFAsmParser::ParseDirectivePopSection(StringRef
, SMLoc
) {
444 if (!getStreamer().popSection())
445 return TokError(".popsection without corresponding .pushsection");
449 bool COFFAsmParser::ParseDirectiveDef(StringRef
, SMLoc
) {
450 StringRef SymbolName
;
452 if (getParser().parseIdentifier(SymbolName
))
453 return TokError("expected identifier in directive");
455 MCSymbol
*Sym
= getContext().getOrCreateSymbol(SymbolName
);
457 getStreamer().beginCOFFSymbolDef(Sym
);
463 bool COFFAsmParser::ParseDirectiveScl(StringRef
, SMLoc
) {
464 int64_t SymbolStorageClass
;
465 if (getParser().parseAbsoluteExpression(SymbolStorageClass
))
468 if (getLexer().isNot(AsmToken::EndOfStatement
))
469 return TokError("unexpected token in directive");
472 getStreamer().emitCOFFSymbolStorageClass(SymbolStorageClass
);
476 bool COFFAsmParser::ParseDirectiveType(StringRef
, SMLoc
) {
478 if (getParser().parseAbsoluteExpression(Type
))
481 if (getLexer().isNot(AsmToken::EndOfStatement
))
482 return TokError("unexpected token in directive");
485 getStreamer().emitCOFFSymbolType(Type
);
489 bool COFFAsmParser::ParseDirectiveEndef(StringRef
, SMLoc
) {
491 getStreamer().endCOFFSymbolDef();
495 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef
, SMLoc
) {
497 if (getParser().parseIdentifier(SymbolID
))
498 return TokError("expected identifier in directive");
502 if (getLexer().is(AsmToken::Plus
)) {
503 OffsetLoc
= getLexer().getLoc();
504 if (getParser().parseAbsoluteExpression(Offset
))
508 if (getLexer().isNot(AsmToken::EndOfStatement
))
509 return TokError("unexpected token in directive");
511 if (Offset
< 0 || Offset
> std::numeric_limits
<uint32_t>::max())
514 "invalid '.secrel32' directive offset, can't be less "
515 "than zero or greater than std::numeric_limits<uint32_t>::max()");
517 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(SymbolID
);
520 getStreamer().emitCOFFSecRel32(Symbol
, Offset
);
524 bool COFFAsmParser::ParseDirectiveRVA(StringRef
, SMLoc
) {
525 auto parseOp
= [&]() -> bool {
527 if (getParser().parseIdentifier(SymbolID
))
528 return TokError("expected identifier in directive");
532 if (getLexer().is(AsmToken::Plus
) || getLexer().is(AsmToken::Minus
)) {
533 OffsetLoc
= getLexer().getLoc();
534 if (getParser().parseAbsoluteExpression(Offset
))
538 if (Offset
< std::numeric_limits
<int32_t>::min() ||
539 Offset
> std::numeric_limits
<int32_t>::max())
540 return Error(OffsetLoc
, "invalid '.rva' directive offset, can't be less "
541 "than -2147483648 or greater than "
544 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(SymbolID
);
546 getStreamer().emitCOFFImgRel32(Symbol
, Offset
);
550 if (getParser().parseMany(parseOp
))
551 return addErrorSuffix(" in directive");
555 bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef
, SMLoc
) {
557 if (getParser().parseIdentifier(SymbolID
))
558 return TokError("expected identifier in directive");
560 if (getLexer().isNot(AsmToken::EndOfStatement
))
561 return TokError("unexpected token in directive");
563 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(SymbolID
);
566 getStreamer().emitCOFFSafeSEH(Symbol
);
570 bool COFFAsmParser::ParseDirectiveSecIdx(StringRef
, SMLoc
) {
572 if (getParser().parseIdentifier(SymbolID
))
573 return TokError("expected identifier in directive");
575 if (getLexer().isNot(AsmToken::EndOfStatement
))
576 return TokError("unexpected token in directive");
578 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(SymbolID
);
581 getStreamer().emitCOFFSectionIndex(Symbol
);
585 bool COFFAsmParser::ParseDirectiveSymIdx(StringRef
, SMLoc
) {
587 if (getParser().parseIdentifier(SymbolID
))
588 return TokError("expected identifier in directive");
590 if (getLexer().isNot(AsmToken::EndOfStatement
))
591 return TokError("unexpected token in directive");
593 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(SymbolID
);
596 getStreamer().emitCOFFSymbolIndex(Symbol
);
600 /// ::= [ identifier ]
601 bool COFFAsmParser::parseCOMDATType(COFF::COMDATType
&Type
) {
602 StringRef TypeId
= getTok().getIdentifier();
604 Type
= StringSwitch
<COFF::COMDATType
>(TypeId
)
605 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES
)
606 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY
)
607 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE
)
608 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH
)
609 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE
)
610 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST
)
611 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST
)
612 .Default((COFF::COMDATType
)0);
615 return TokError(Twine("unrecognized COMDAT type '" + TypeId
+ "'"));
622 /// ParseDirectiveLinkOnce
623 /// ::= .linkonce [ identifier ]
624 bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef
, SMLoc Loc
) {
625 COFF::COMDATType Type
= COFF::IMAGE_COMDAT_SELECT_ANY
;
626 if (getLexer().is(AsmToken::Identifier
))
627 if (parseCOMDATType(Type
))
630 const MCSectionCOFF
*Current
=
631 static_cast<const MCSectionCOFF
*>(getStreamer().getCurrentSectionOnly());
633 if (Type
== COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE
)
634 return Error(Loc
, "cannot make section associative with .linkonce");
636 if (Current
->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT
)
637 return Error(Loc
, Twine("section '") + Current
->getName() +
638 "' is already linkonce");
640 Current
->setSelection(Type
);
642 if (getLexer().isNot(AsmToken::EndOfStatement
))
643 return TokError("unexpected token in directive");
648 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef
, SMLoc Loc
) {
650 if (getParser().parseIdentifier(SymbolID
))
653 if (getLexer().isNot(AsmToken::EndOfStatement
))
654 return TokError("unexpected token in directive");
656 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(SymbolID
);
659 getStreamer().emitWinCFIStartProc(Symbol
, Loc
);
663 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef
, SMLoc Loc
) {
665 getStreamer().emitWinCFIEndProc(Loc
);
669 bool COFFAsmParser::ParseSEHDirectiveEndFuncletOrFunc(StringRef
, SMLoc Loc
) {
671 getStreamer().emitWinCFIFuncletOrFuncEnd(Loc
);
675 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef
, SMLoc Loc
) {
677 getStreamer().emitWinCFIStartChained(Loc
);
681 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef
, SMLoc Loc
) {
683 getStreamer().emitWinCFIEndChained(Loc
);
687 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef
, SMLoc Loc
) {
689 if (getParser().parseIdentifier(SymbolID
))
692 if (getLexer().isNot(AsmToken::Comma
))
693 return TokError("you must specify one or both of @unwind or @except");
695 bool unwind
= false, except
= false;
696 if (ParseAtUnwindOrAtExcept(unwind
, except
))
698 if (getLexer().is(AsmToken::Comma
)) {
700 if (ParseAtUnwindOrAtExcept(unwind
, except
))
703 if (getLexer().isNot(AsmToken::EndOfStatement
))
704 return TokError("unexpected token in directive");
706 MCSymbol
*handler
= getContext().getOrCreateSymbol(SymbolID
);
709 getStreamer().emitWinEHHandler(handler
, unwind
, except
, Loc
);
713 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef
, SMLoc Loc
) {
715 getStreamer().emitWinEHHandlerData();
719 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef
, SMLoc Loc
) {
721 if (getParser().parseAbsoluteExpression(Size
))
724 if (getLexer().isNot(AsmToken::EndOfStatement
))
725 return TokError("unexpected token in directive");
728 getStreamer().emitWinCFIAllocStack(Size
, Loc
);
732 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef
, SMLoc Loc
) {
734 getStreamer().emitWinCFIEndProlog(Loc
);
738 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind
, bool &except
) {
739 StringRef identifier
;
740 if (getLexer().isNot(AsmToken::At
) && getLexer().isNot(AsmToken::Percent
))
741 return TokError("a handler attribute must begin with '@' or '%'");
742 SMLoc startLoc
= getLexer().getLoc();
744 if (getParser().parseIdentifier(identifier
))
745 return Error(startLoc
, "expected @unwind or @except");
746 if (identifier
== "unwind")
748 else if (identifier
== "except")
751 return Error(startLoc
, "expected @unwind or @except");
757 MCAsmParserExtension
*createCOFFAsmParser() {
758 return new COFFAsmParser
;
761 } // end namespace llvm