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/Triple.h"
12 #include "llvm/ADT/Twine.h"
13 #include "llvm/BinaryFormat/COFF.h"
14 #include "llvm/MC/MCContext.h"
15 #include "llvm/MC/MCDirectives.h"
16 #include "llvm/MC/MCObjectFileInfo.h"
17 #include "llvm/MC/MCParser/MCAsmLexer.h"
18 #include "llvm/MC/MCParser/MCAsmParserExtension.h"
19 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
20 #include "llvm/MC/MCRegisterInfo.h"
21 #include "llvm/MC/MCSectionCOFF.h"
22 #include "llvm/MC/MCStreamer.h"
23 #include "llvm/MC/SectionKind.h"
24 #include "llvm/Support/SMLoc.h"
34 class COFFAsmParser
: public MCAsmParserExtension
{
35 template<bool (COFFAsmParser::*HandlerMethod
)(StringRef
, SMLoc
)>
36 void addDirectiveHandler(StringRef Directive
) {
37 MCAsmParser::ExtensionDirectiveHandler Handler
= std::make_pair(
38 this, HandleDirective
<COFFAsmParser
, HandlerMethod
>);
39 getParser().addDirectiveHandler(Directive
, Handler
);
42 bool ParseSectionSwitch(StringRef Section
,
43 unsigned Characteristics
,
46 bool ParseSectionSwitch(StringRef Section
, unsigned Characteristics
,
47 SectionKind Kind
, StringRef COMDATSymName
,
48 COFF::COMDATType Type
);
50 bool ParseSectionName(StringRef
&SectionName
);
51 bool ParseSectionFlags(StringRef SectionName
, StringRef FlagsString
,
54 void Initialize(MCAsmParser
&Parser
) override
{
55 // Call the base implementation.
56 MCAsmParserExtension::Initialize(Parser
);
58 addDirectiveHandler
<&COFFAsmParser::ParseSectionDirectiveText
>(".text");
59 addDirectiveHandler
<&COFFAsmParser::ParseSectionDirectiveData
>(".data");
60 addDirectiveHandler
<&COFFAsmParser::ParseSectionDirectiveBSS
>(".bss");
61 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveSection
>(".section");
62 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveDef
>(".def");
63 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveScl
>(".scl");
64 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveType
>(".type");
65 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveEndef
>(".endef");
66 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveSecRel32
>(".secrel32");
67 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveSymIdx
>(".symidx");
68 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveSafeSEH
>(".safeseh");
69 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveSecIdx
>(".secidx");
70 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveLinkOnce
>(".linkonce");
71 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveRVA
>(".rva");
73 // Win64 EH directives.
74 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveStartProc
>(
76 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveEndProc
>(
78 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveStartChained
>(
80 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveEndChained
>(
82 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveHandler
>(
84 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveHandlerData
>(
86 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectivePushReg
>(
88 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveSetFrame
>(
90 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveAllocStack
>(
92 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveSaveReg
>(
94 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveSaveXMM
>(
96 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectivePushFrame
>(
98 addDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveEndProlog
>(
100 addDirectiveHandler
<&COFFAsmParser::ParseDirectiveSymbolAttribute
>(".weak");
103 bool ParseSectionDirectiveText(StringRef
, SMLoc
) {
104 return ParseSectionSwitch(".text",
105 COFF::IMAGE_SCN_CNT_CODE
106 | COFF::IMAGE_SCN_MEM_EXECUTE
107 | COFF::IMAGE_SCN_MEM_READ
,
108 SectionKind::getText());
111 bool ParseSectionDirectiveData(StringRef
, SMLoc
) {
112 return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
|
113 COFF::IMAGE_SCN_MEM_READ
|
114 COFF::IMAGE_SCN_MEM_WRITE
,
115 SectionKind::getData());
118 bool ParseSectionDirectiveBSS(StringRef
, SMLoc
) {
119 return ParseSectionSwitch(".bss",
120 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
121 | COFF::IMAGE_SCN_MEM_READ
122 | COFF::IMAGE_SCN_MEM_WRITE
,
123 SectionKind::getBSS());
126 bool ParseDirectiveSection(StringRef
, SMLoc
);
127 bool ParseDirectiveDef(StringRef
, SMLoc
);
128 bool ParseDirectiveScl(StringRef
, SMLoc
);
129 bool ParseDirectiveType(StringRef
, SMLoc
);
130 bool ParseDirectiveEndef(StringRef
, SMLoc
);
131 bool ParseDirectiveSecRel32(StringRef
, SMLoc
);
132 bool ParseDirectiveSecIdx(StringRef
, SMLoc
);
133 bool ParseDirectiveSafeSEH(StringRef
, SMLoc
);
134 bool ParseDirectiveSymIdx(StringRef
, SMLoc
);
135 bool parseCOMDATType(COFF::COMDATType
&Type
);
136 bool ParseDirectiveLinkOnce(StringRef
, SMLoc
);
137 bool ParseDirectiveRVA(StringRef
, SMLoc
);
139 // Win64 EH directives.
140 bool ParseSEHDirectiveStartProc(StringRef
, SMLoc
);
141 bool ParseSEHDirectiveEndProc(StringRef
, SMLoc
);
142 bool ParseSEHDirectiveStartChained(StringRef
, SMLoc
);
143 bool ParseSEHDirectiveEndChained(StringRef
, SMLoc
);
144 bool ParseSEHDirectiveHandler(StringRef
, SMLoc
);
145 bool ParseSEHDirectiveHandlerData(StringRef
, SMLoc
);
146 bool ParseSEHDirectivePushReg(StringRef
, SMLoc
);
147 bool ParseSEHDirectiveSetFrame(StringRef
, SMLoc
);
148 bool ParseSEHDirectiveAllocStack(StringRef
, SMLoc
);
149 bool ParseSEHDirectiveSaveReg(StringRef
, SMLoc
);
150 bool ParseSEHDirectiveSaveXMM(StringRef
, SMLoc
);
151 bool ParseSEHDirectivePushFrame(StringRef
, SMLoc
);
152 bool ParseSEHDirectiveEndProlog(StringRef
, SMLoc
);
154 bool ParseAtUnwindOrAtExcept(bool &unwind
, bool &except
);
155 bool ParseSEHRegisterNumber(unsigned &RegNo
);
156 bool ParseDirectiveSymbolAttribute(StringRef Directive
, SMLoc
);
159 COFFAsmParser() = default;
162 } // end annonomous namespace.
164 static SectionKind
computeSectionKind(unsigned Flags
) {
165 if (Flags
& COFF::IMAGE_SCN_MEM_EXECUTE
)
166 return SectionKind::getText();
167 if (Flags
& COFF::IMAGE_SCN_MEM_READ
&&
168 (Flags
& COFF::IMAGE_SCN_MEM_WRITE
) == 0)
169 return SectionKind::getReadOnly();
170 return SectionKind::getData();
173 bool COFFAsmParser::ParseSectionFlags(StringRef SectionName
,
174 StringRef FlagsString
, unsigned *Flags
) {
185 Discardable
= 1 << 8,
188 bool ReadOnlyRemoved
= false;
189 unsigned SecFlags
= None
;
191 for (char FlagChar
: FlagsString
) {
197 case 'b': // bss section
199 if (SecFlags
& InitData
)
200 return TokError("conflicting section flags 'b' and 'd'.");
204 case 'd': // data section
205 SecFlags
|= InitData
;
206 if (SecFlags
& Alloc
)
207 return TokError("conflicting section flags 'b' and 'd'.");
208 SecFlags
&= ~NoWrite
;
209 if ((SecFlags
& NoLoad
) == 0)
213 case 'n': // section is not loaded
218 case 'D': // discardable
219 SecFlags
|= Discardable
;
222 case 'r': // read-only
223 ReadOnlyRemoved
= false;
225 if ((SecFlags
& Code
) == 0)
226 SecFlags
|= InitData
;
227 if ((SecFlags
& NoLoad
) == 0)
231 case 's': // shared section
232 SecFlags
|= Shared
| InitData
;
233 SecFlags
&= ~NoWrite
;
234 if ((SecFlags
& NoLoad
) == 0)
238 case 'w': // writable
239 SecFlags
&= ~NoWrite
;
240 ReadOnlyRemoved
= true;
243 case 'x': // executable section
245 if ((SecFlags
& NoLoad
) == 0)
247 if (!ReadOnlyRemoved
)
251 case 'y': // not readable
252 SecFlags
|= NoRead
| NoWrite
;
256 return TokError("unknown flag");
262 if (SecFlags
== None
)
266 *Flags
|= COFF::IMAGE_SCN_CNT_CODE
| COFF::IMAGE_SCN_MEM_EXECUTE
;
267 if (SecFlags
& InitData
)
268 *Flags
|= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
;
269 if ((SecFlags
& Alloc
) && (SecFlags
& Load
) == 0)
270 *Flags
|= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
;
271 if (SecFlags
& NoLoad
)
272 *Flags
|= COFF::IMAGE_SCN_LNK_REMOVE
;
273 if ((SecFlags
& Discardable
) ||
274 MCSectionCOFF::isImplicitlyDiscardable(SectionName
))
275 *Flags
|= COFF::IMAGE_SCN_MEM_DISCARDABLE
;
276 if ((SecFlags
& NoRead
) == 0)
277 *Flags
|= COFF::IMAGE_SCN_MEM_READ
;
278 if ((SecFlags
& NoWrite
) == 0)
279 *Flags
|= COFF::IMAGE_SCN_MEM_WRITE
;
280 if (SecFlags
& Shared
)
281 *Flags
|= COFF::IMAGE_SCN_MEM_SHARED
;
286 /// ParseDirectiveSymbolAttribute
287 /// ::= { ".weak", ... } [ identifier ( , identifier )* ]
288 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive
, SMLoc
) {
289 MCSymbolAttr Attr
= StringSwitch
<MCSymbolAttr
>(Directive
)
290 .Case(".weak", MCSA_Weak
)
291 .Default(MCSA_Invalid
);
292 assert(Attr
!= MCSA_Invalid
&& "unexpected symbol attribute directive!");
293 if (getLexer().isNot(AsmToken::EndOfStatement
)) {
297 if (getParser().parseIdentifier(Name
))
298 return TokError("expected identifier in directive");
300 MCSymbol
*Sym
= getContext().getOrCreateSymbol(Name
);
302 getStreamer().EmitSymbolAttribute(Sym
, Attr
);
304 if (getLexer().is(AsmToken::EndOfStatement
))
307 if (getLexer().isNot(AsmToken::Comma
))
308 return TokError("unexpected token in directive");
317 bool COFFAsmParser::ParseSectionSwitch(StringRef Section
,
318 unsigned Characteristics
,
320 return ParseSectionSwitch(Section
, Characteristics
, Kind
, "", (COFF::COMDATType
)0);
323 bool COFFAsmParser::ParseSectionSwitch(StringRef Section
,
324 unsigned Characteristics
,
326 StringRef COMDATSymName
,
327 COFF::COMDATType Type
) {
328 if (getLexer().isNot(AsmToken::EndOfStatement
))
329 return TokError("unexpected token in section switching directive");
332 getStreamer().SwitchSection(getContext().getCOFFSection(
333 Section
, Characteristics
, Kind
, COMDATSymName
, Type
));
338 bool COFFAsmParser::ParseSectionName(StringRef
&SectionName
) {
339 if (!getLexer().is(AsmToken::Identifier
))
342 SectionName
= getTok().getIdentifier();
347 // .section name [, "flags"] [, identifier [ identifier ], identifier]
351 // b: BSS section (uninitialized data)
352 // d: data section (initialized data)
353 // n: "noload" section (removed by linker)
354 // D: Discardable section
355 // r: Readable section
357 // w: Writable section
358 // x: Executable section
359 // y: Not-readable section (clears 'r')
361 // Subsections are not supported.
362 bool COFFAsmParser::ParseDirectiveSection(StringRef
, SMLoc
) {
363 StringRef SectionName
;
365 if (ParseSectionName(SectionName
))
366 return TokError("expected identifier in directive");
368 unsigned Flags
= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
|
369 COFF::IMAGE_SCN_MEM_READ
|
370 COFF::IMAGE_SCN_MEM_WRITE
;
372 if (getLexer().is(AsmToken::Comma
)) {
375 if (getLexer().isNot(AsmToken::String
))
376 return TokError("expected string in directive");
378 StringRef FlagsStr
= getTok().getStringContents();
381 if (ParseSectionFlags(SectionName
, FlagsStr
, &Flags
))
385 COFF::COMDATType Type
= (COFF::COMDATType
)0;
386 StringRef COMDATSymName
;
387 if (getLexer().is(AsmToken::Comma
)) {
388 Type
= COFF::IMAGE_COMDAT_SELECT_ANY
;
391 Flags
|= COFF::IMAGE_SCN_LNK_COMDAT
;
393 if (!getLexer().is(AsmToken::Identifier
))
394 return TokError("expected comdat type such as 'discard' or 'largest' "
395 "after protection bits");
397 if (parseCOMDATType(Type
))
400 if (getLexer().isNot(AsmToken::Comma
))
401 return TokError("expected comma in directive");
404 if (getParser().parseIdentifier(COMDATSymName
))
405 return TokError("expected identifier in directive");
408 if (getLexer().isNot(AsmToken::EndOfStatement
))
409 return TokError("unexpected token in directive");
411 SectionKind Kind
= computeSectionKind(Flags
);
413 const Triple
&T
= getContext().getObjectFileInfo()->getTargetTriple();
414 if (T
.getArch() == Triple::arm
|| T
.getArch() == Triple::thumb
)
415 Flags
|= COFF::IMAGE_SCN_MEM_16BIT
;
417 ParseSectionSwitch(SectionName
, Flags
, Kind
, COMDATSymName
, Type
);
421 bool COFFAsmParser::ParseDirectiveDef(StringRef
, SMLoc
) {
422 StringRef SymbolName
;
424 if (getParser().parseIdentifier(SymbolName
))
425 return TokError("expected identifier in directive");
427 MCSymbol
*Sym
= getContext().getOrCreateSymbol(SymbolName
);
429 getStreamer().BeginCOFFSymbolDef(Sym
);
435 bool COFFAsmParser::ParseDirectiveScl(StringRef
, SMLoc
) {
436 int64_t SymbolStorageClass
;
437 if (getParser().parseAbsoluteExpression(SymbolStorageClass
))
440 if (getLexer().isNot(AsmToken::EndOfStatement
))
441 return TokError("unexpected token in directive");
444 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass
);
448 bool COFFAsmParser::ParseDirectiveType(StringRef
, SMLoc
) {
450 if (getParser().parseAbsoluteExpression(Type
))
453 if (getLexer().isNot(AsmToken::EndOfStatement
))
454 return TokError("unexpected token in directive");
457 getStreamer().EmitCOFFSymbolType(Type
);
461 bool COFFAsmParser::ParseDirectiveEndef(StringRef
, SMLoc
) {
463 getStreamer().EndCOFFSymbolDef();
467 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef
, SMLoc
) {
469 if (getParser().parseIdentifier(SymbolID
))
470 return TokError("expected identifier in directive");
474 if (getLexer().is(AsmToken::Plus
)) {
475 OffsetLoc
= getLexer().getLoc();
476 if (getParser().parseAbsoluteExpression(Offset
))
480 if (getLexer().isNot(AsmToken::EndOfStatement
))
481 return TokError("unexpected token in directive");
483 if (Offset
< 0 || Offset
> std::numeric_limits
<uint32_t>::max())
486 "invalid '.secrel32' directive offset, can't be less "
487 "than zero or greater than std::numeric_limits<uint32_t>::max()");
489 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(SymbolID
);
492 getStreamer().EmitCOFFSecRel32(Symbol
, Offset
);
496 bool COFFAsmParser::ParseDirectiveRVA(StringRef
, SMLoc
) {
497 auto parseOp
= [&]() -> bool {
499 if (getParser().parseIdentifier(SymbolID
))
500 return TokError("expected identifier in directive");
504 if (getLexer().is(AsmToken::Plus
) || getLexer().is(AsmToken::Minus
)) {
505 OffsetLoc
= getLexer().getLoc();
506 if (getParser().parseAbsoluteExpression(Offset
))
510 if (Offset
< std::numeric_limits
<int32_t>::min() ||
511 Offset
> std::numeric_limits
<int32_t>::max())
512 return Error(OffsetLoc
, "invalid '.rva' directive offset, can't be less "
513 "than -2147483648 or greater than "
516 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(SymbolID
);
518 getStreamer().EmitCOFFImgRel32(Symbol
, Offset
);
522 if (getParser().parseMany(parseOp
))
523 return addErrorSuffix(" in directive");
527 bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef
, SMLoc
) {
529 if (getParser().parseIdentifier(SymbolID
))
530 return TokError("expected identifier in directive");
532 if (getLexer().isNot(AsmToken::EndOfStatement
))
533 return TokError("unexpected token in directive");
535 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(SymbolID
);
538 getStreamer().EmitCOFFSafeSEH(Symbol
);
542 bool COFFAsmParser::ParseDirectiveSecIdx(StringRef
, SMLoc
) {
544 if (getParser().parseIdentifier(SymbolID
))
545 return TokError("expected identifier in directive");
547 if (getLexer().isNot(AsmToken::EndOfStatement
))
548 return TokError("unexpected token in directive");
550 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(SymbolID
);
553 getStreamer().EmitCOFFSectionIndex(Symbol
);
557 bool COFFAsmParser::ParseDirectiveSymIdx(StringRef
, SMLoc
) {
559 if (getParser().parseIdentifier(SymbolID
))
560 return TokError("expected identifier in directive");
562 if (getLexer().isNot(AsmToken::EndOfStatement
))
563 return TokError("unexpected token in directive");
565 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(SymbolID
);
568 getStreamer().EmitCOFFSymbolIndex(Symbol
);
572 /// ::= [ identifier ]
573 bool COFFAsmParser::parseCOMDATType(COFF::COMDATType
&Type
) {
574 StringRef TypeId
= getTok().getIdentifier();
576 Type
= StringSwitch
<COFF::COMDATType
>(TypeId
)
577 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES
)
578 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY
)
579 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE
)
580 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH
)
581 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE
)
582 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST
)
583 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST
)
584 .Default((COFF::COMDATType
)0);
587 return TokError(Twine("unrecognized COMDAT type '" + TypeId
+ "'"));
594 /// ParseDirectiveLinkOnce
595 /// ::= .linkonce [ identifier ]
596 bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef
, SMLoc Loc
) {
597 COFF::COMDATType Type
= COFF::IMAGE_COMDAT_SELECT_ANY
;
598 if (getLexer().is(AsmToken::Identifier
))
599 if (parseCOMDATType(Type
))
602 const MCSectionCOFF
*Current
=
603 static_cast<const MCSectionCOFF
*>(getStreamer().getCurrentSectionOnly());
605 if (Type
== COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE
)
606 return Error(Loc
, "cannot make section associative with .linkonce");
608 if (Current
->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT
)
609 return Error(Loc
, Twine("section '") + Current
->getSectionName() +
610 "' is already linkonce");
612 Current
->setSelection(Type
);
614 if (getLexer().isNot(AsmToken::EndOfStatement
))
615 return TokError("unexpected token in directive");
620 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef
, SMLoc Loc
) {
622 if (getParser().parseIdentifier(SymbolID
))
625 if (getLexer().isNot(AsmToken::EndOfStatement
))
626 return TokError("unexpected token in directive");
628 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(SymbolID
);
631 getStreamer().EmitWinCFIStartProc(Symbol
, Loc
);
635 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef
, SMLoc Loc
) {
637 getStreamer().EmitWinCFIEndProc(Loc
);
641 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef
, SMLoc Loc
) {
643 getStreamer().EmitWinCFIStartChained(Loc
);
647 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef
, SMLoc Loc
) {
649 getStreamer().EmitWinCFIEndChained(Loc
);
653 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef
, SMLoc Loc
) {
655 if (getParser().parseIdentifier(SymbolID
))
658 if (getLexer().isNot(AsmToken::Comma
))
659 return TokError("you must specify one or both of @unwind or @except");
661 bool unwind
= false, except
= false;
662 if (ParseAtUnwindOrAtExcept(unwind
, except
))
664 if (getLexer().is(AsmToken::Comma
)) {
666 if (ParseAtUnwindOrAtExcept(unwind
, except
))
669 if (getLexer().isNot(AsmToken::EndOfStatement
))
670 return TokError("unexpected token in directive");
672 MCSymbol
*handler
= getContext().getOrCreateSymbol(SymbolID
);
675 getStreamer().EmitWinEHHandler(handler
, unwind
, except
, Loc
);
679 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef
, SMLoc Loc
) {
681 getStreamer().EmitWinEHHandlerData();
685 bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef
, SMLoc Loc
) {
687 if (ParseSEHRegisterNumber(Reg
))
690 if (getLexer().isNot(AsmToken::EndOfStatement
))
691 return TokError("unexpected token in directive");
694 getStreamer().EmitWinCFIPushReg(Reg
, Loc
);
698 bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef
, SMLoc Loc
) {
701 if (ParseSEHRegisterNumber(Reg
))
703 if (getLexer().isNot(AsmToken::Comma
))
704 return TokError("you must specify a stack pointer offset");
707 if (getParser().parseAbsoluteExpression(Off
))
710 if (getLexer().isNot(AsmToken::EndOfStatement
))
711 return TokError("unexpected token in directive");
714 getStreamer().EmitWinCFISetFrame(Reg
, Off
, Loc
);
718 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef
, SMLoc Loc
) {
720 if (getParser().parseAbsoluteExpression(Size
))
723 if (getLexer().isNot(AsmToken::EndOfStatement
))
724 return TokError("unexpected token in directive");
727 getStreamer().EmitWinCFIAllocStack(Size
, Loc
);
731 bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef
, SMLoc Loc
) {
734 if (ParseSEHRegisterNumber(Reg
))
736 if (getLexer().isNot(AsmToken::Comma
))
737 return TokError("you must specify an offset on the stack");
740 if (getParser().parseAbsoluteExpression(Off
))
743 if (getLexer().isNot(AsmToken::EndOfStatement
))
744 return TokError("unexpected token in directive");
747 // FIXME: Err on %xmm* registers
748 getStreamer().EmitWinCFISaveReg(Reg
, Off
, Loc
);
752 // FIXME: This method is inherently x86-specific. It should really be in the
754 bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef
, SMLoc Loc
) {
757 if (ParseSEHRegisterNumber(Reg
))
759 if (getLexer().isNot(AsmToken::Comma
))
760 return TokError("you must specify an offset on the stack");
763 if (getParser().parseAbsoluteExpression(Off
))
766 if (getLexer().isNot(AsmToken::EndOfStatement
))
767 return TokError("unexpected token in directive");
770 // FIXME: Err on non-%xmm* registers
771 getStreamer().EmitWinCFISaveXMM(Reg
, Off
, Loc
);
775 bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef
, SMLoc Loc
) {
778 if (getLexer().is(AsmToken::At
)) {
779 SMLoc startLoc
= getLexer().getLoc();
781 if (!getParser().parseIdentifier(CodeID
)) {
782 if (CodeID
!= "code")
783 return Error(startLoc
, "expected @code");
788 if (getLexer().isNot(AsmToken::EndOfStatement
))
789 return TokError("unexpected token in directive");
792 getStreamer().EmitWinCFIPushFrame(Code
, Loc
);
796 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef
, SMLoc Loc
) {
798 getStreamer().EmitWinCFIEndProlog(Loc
);
802 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind
, bool &except
) {
803 StringRef identifier
;
804 if (getLexer().isNot(AsmToken::At
))
805 return TokError("a handler attribute must begin with '@'");
806 SMLoc startLoc
= getLexer().getLoc();
808 if (getParser().parseIdentifier(identifier
))
809 return Error(startLoc
, "expected @unwind or @except");
810 if (identifier
== "unwind")
812 else if (identifier
== "except")
815 return Error(startLoc
, "expected @unwind or @except");
819 bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo
) {
820 SMLoc startLoc
= getLexer().getLoc();
821 if (getLexer().is(AsmToken::Percent
)) {
822 const MCRegisterInfo
*MRI
= getContext().getRegisterInfo();
825 if (getParser().getTargetParser().ParseRegister(LLVMRegNo
,startLoc
,endLoc
))
829 // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
830 // violation so this validation code is disabled.
832 // Check that this is a non-volatile register.
833 const unsigned *NVRegs
= TAI
.getCalleeSavedRegs();
835 for (i
= 0; NVRegs
[i
] != 0; ++i
)
836 if (NVRegs
[i
] == LLVMRegNo
)
839 return Error(startLoc
, "expected non-volatile register");
842 int SEHRegNo
= MRI
->getSEHRegNum(LLVMRegNo
);
844 return Error(startLoc
,"register can't be represented in SEH unwind info");
849 if (getParser().parseAbsoluteExpression(n
))
852 return Error(startLoc
, "register number is too high");
861 MCAsmParserExtension
*createCOFFAsmParser() {
862 return new COFFAsmParser
;
865 } // end namespace llvm