1 //===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/MC/MCParser/MCAsmParserExtension.h"
11 #include "llvm/ADT/StringSwitch.h"
12 #include "llvm/ADT/Twine.h"
13 #include "llvm/MC/MCAsmInfo.h"
14 #include "llvm/MC/MCContext.h"
15 #include "llvm/MC/MCExpr.h"
16 #include "llvm/MC/MCObjectFileInfo.h"
17 #include "llvm/MC/MCParser/MCAsmLexer.h"
18 #include "llvm/MC/MCRegisterInfo.h"
19 #include "llvm/MC/MCSectionCOFF.h"
20 #include "llvm/MC/MCStreamer.h"
21 #include "llvm/MC/MCTargetAsmParser.h"
22 #include "llvm/Support/COFF.h"
27 class COFFAsmParser : public MCAsmParserExtension {
28 template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
29 void addDirectiveHandler(StringRef Directive) {
30 MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
31 this, HandleDirective<COFFAsmParser, HandlerMethod>);
32 getParser().addDirectiveHandler(Directive, Handler);
35 bool ParseSectionSwitch(StringRef Section,
36 unsigned Characteristics,
39 bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
40 SectionKind Kind, StringRef COMDATSymName,
41 COFF::COMDATType Type);
43 bool ParseSectionName(StringRef &SectionName);
44 bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags);
46 void Initialize(MCAsmParser &Parser) override {
47 // Call the base implementation.
48 MCAsmParserExtension::Initialize(Parser);
50 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
51 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
52 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
53 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
54 addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
55 addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
56 addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
57 addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
58 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
59 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
60 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
61 addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
63 // Win64 EH directives.
64 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
66 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
68 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
70 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
72 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
74 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
76 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
78 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
80 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
82 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
84 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
86 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
88 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
90 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
93 bool ParseSectionDirectiveText(StringRef, SMLoc) {
94 return ParseSectionSwitch(".text",
95 COFF::IMAGE_SCN_CNT_CODE
96 | COFF::IMAGE_SCN_MEM_EXECUTE
97 | COFF::IMAGE_SCN_MEM_READ,
98 SectionKind::getText());
100 bool ParseSectionDirectiveData(StringRef, SMLoc) {
101 return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
102 COFF::IMAGE_SCN_MEM_READ |
103 COFF::IMAGE_SCN_MEM_WRITE,
104 SectionKind::getData());
106 bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
107 return ParseSectionSwitch(".bss",
108 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
109 | COFF::IMAGE_SCN_MEM_READ
110 | COFF::IMAGE_SCN_MEM_WRITE,
111 SectionKind::getBSS());
114 bool ParseDirectiveSection(StringRef, SMLoc);
115 bool ParseDirectiveDef(StringRef, SMLoc);
116 bool ParseDirectiveScl(StringRef, SMLoc);
117 bool ParseDirectiveType(StringRef, SMLoc);
118 bool ParseDirectiveEndef(StringRef, SMLoc);
119 bool ParseDirectiveSecRel32(StringRef, SMLoc);
120 bool ParseDirectiveSecIdx(StringRef, SMLoc);
121 bool ParseDirectiveSafeSEH(StringRef, SMLoc);
122 bool parseCOMDATType(COFF::COMDATType &Type);
123 bool ParseDirectiveLinkOnce(StringRef, SMLoc);
125 // Win64 EH directives.
126 bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
127 bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
128 bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
129 bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
130 bool ParseSEHDirectiveHandler(StringRef, SMLoc);
131 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
132 bool ParseSEHDirectivePushReg(StringRef, SMLoc);
133 bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
134 bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
135 bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
136 bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
137 bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
138 bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
140 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
141 bool ParseSEHRegisterNumber(unsigned &RegNo);
142 bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
147 } // end annonomous namespace.
149 static SectionKind computeSectionKind(unsigned Flags) {
150 if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
151 return SectionKind::getText();
152 if (Flags & COFF::IMAGE_SCN_MEM_READ &&
153 (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
154 return SectionKind::getReadOnly();
155 return SectionKind::getData();
158 bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
171 bool ReadOnlyRemoved = false;
172 unsigned SecFlags = None;
174 for (char FlagChar : FlagsString) {
180 case 'b': // bss section
182 if (SecFlags & InitData)
183 return TokError("conflicting section flags 'b' and 'd'.");
187 case 'd': // data section
188 SecFlags |= InitData;
189 if (SecFlags & Alloc)
190 return TokError("conflicting section flags 'b' and 'd'.");
191 SecFlags &= ~NoWrite;
192 if ((SecFlags & NoLoad) == 0)
196 case 'n': // section is not loaded
201 case 'r': // read-only
202 ReadOnlyRemoved = false;
204 if ((SecFlags & Code) == 0)
205 SecFlags |= InitData;
206 if ((SecFlags & NoLoad) == 0)
210 case 's': // shared section
211 SecFlags |= Shared | InitData;
212 SecFlags &= ~NoWrite;
213 if ((SecFlags & NoLoad) == 0)
217 case 'w': // writable
218 SecFlags &= ~NoWrite;
219 ReadOnlyRemoved = true;
222 case 'x': // executable section
224 if ((SecFlags & NoLoad) == 0)
226 if (!ReadOnlyRemoved)
230 case 'y': // not readable
231 SecFlags |= NoRead | NoWrite;
235 return TokError("unknown flag");
241 if (SecFlags == None)
245 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
246 if (SecFlags & InitData)
247 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
248 if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
249 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
250 if (SecFlags & NoLoad)
251 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
252 if ((SecFlags & NoRead) == 0)
253 *Flags |= COFF::IMAGE_SCN_MEM_READ;
254 if ((SecFlags & NoWrite) == 0)
255 *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
256 if (SecFlags & Shared)
257 *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
262 /// ParseDirectiveSymbolAttribute
263 /// ::= { ".weak", ... } [ identifier ( , identifier )* ]
264 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
265 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
266 .Case(".weak", MCSA_Weak)
267 .Default(MCSA_Invalid);
268 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
269 if (getLexer().isNot(AsmToken::EndOfStatement)) {
273 if (getParser().parseIdentifier(Name))
274 return TokError("expected identifier in directive");
276 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
278 getStreamer().EmitSymbolAttribute(Sym, Attr);
280 if (getLexer().is(AsmToken::EndOfStatement))
283 if (getLexer().isNot(AsmToken::Comma))
284 return TokError("unexpected token in directive");
293 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
294 unsigned Characteristics,
296 return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
299 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
300 unsigned Characteristics,
302 StringRef COMDATSymName,
303 COFF::COMDATType Type) {
304 if (getLexer().isNot(AsmToken::EndOfStatement))
305 return TokError("unexpected token in section switching directive");
308 getStreamer().SwitchSection(getContext().getCOFFSection(
309 Section, Characteristics, Kind, COMDATSymName, Type));
314 bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
315 if (!getLexer().is(AsmToken::Identifier))
318 SectionName = getTok().getIdentifier();
323 // .section name [, "flags"] [, identifier [ identifier ], identifier]
327 // b: BSS section (uninitialized data)
328 // d: data section (initialized data)
329 // n: Discardable section
330 // r: Readable section
332 // w: Writable section
333 // x: Executable section
334 // y: Not-readable section (clears 'r')
336 // Subsections are not supported.
337 bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
338 StringRef SectionName;
340 if (ParseSectionName(SectionName))
341 return TokError("expected identifier in directive");
343 unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
344 COFF::IMAGE_SCN_MEM_READ |
345 COFF::IMAGE_SCN_MEM_WRITE;
347 if (getLexer().is(AsmToken::Comma)) {
350 if (getLexer().isNot(AsmToken::String))
351 return TokError("expected string in directive");
353 StringRef FlagsStr = getTok().getStringContents();
356 if (ParseSectionFlags(FlagsStr, &Flags))
360 COFF::COMDATType Type = (COFF::COMDATType)0;
361 StringRef COMDATSymName;
362 if (getLexer().is(AsmToken::Comma)) {
363 Type = COFF::IMAGE_COMDAT_SELECT_ANY;
366 Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
368 if (!getLexer().is(AsmToken::Identifier))
369 return TokError("expected comdat type such as 'discard' or 'largest' "
370 "after protection bits");
372 if (parseCOMDATType(Type))
375 if (getLexer().isNot(AsmToken::Comma))
376 return TokError("expected comma in directive");
379 if (getParser().parseIdentifier(COMDATSymName))
380 return TokError("expected identifier in directive");
383 if (getLexer().isNot(AsmToken::EndOfStatement))
384 return TokError("unexpected token in directive");
386 SectionKind Kind = computeSectionKind(Flags);
388 const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
389 if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
390 Flags |= COFF::IMAGE_SCN_MEM_16BIT;
392 ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
396 bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
397 StringRef SymbolName;
399 if (getParser().parseIdentifier(SymbolName))
400 return TokError("expected identifier in directive");
402 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
404 getStreamer().BeginCOFFSymbolDef(Sym);
410 bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
411 int64_t SymbolStorageClass;
412 if (getParser().parseAbsoluteExpression(SymbolStorageClass))
415 if (getLexer().isNot(AsmToken::EndOfStatement))
416 return TokError("unexpected token in directive");
419 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
423 bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
425 if (getParser().parseAbsoluteExpression(Type))
428 if (getLexer().isNot(AsmToken::EndOfStatement))
429 return TokError("unexpected token in directive");
432 getStreamer().EmitCOFFSymbolType(Type);
436 bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
438 getStreamer().EndCOFFSymbolDef();
442 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
444 if (getParser().parseIdentifier(SymbolID))
445 return TokError("expected identifier in directive");
447 if (getLexer().isNot(AsmToken::EndOfStatement))
448 return TokError("unexpected token in directive");
450 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
453 getStreamer().EmitCOFFSecRel32(Symbol);
457 bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
459 if (getParser().parseIdentifier(SymbolID))
460 return TokError("expected identifier in directive");
462 if (getLexer().isNot(AsmToken::EndOfStatement))
463 return TokError("unexpected token in directive");
465 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
468 getStreamer().EmitCOFFSafeSEH(Symbol);
472 bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
474 if (getParser().parseIdentifier(SymbolID))
475 return TokError("expected identifier in directive");
477 if (getLexer().isNot(AsmToken::EndOfStatement))
478 return TokError("unexpected token in directive");
480 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
483 getStreamer().EmitCOFFSectionIndex(Symbol);
487 /// ::= [ identifier ]
488 bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
489 StringRef TypeId = getTok().getIdentifier();
491 Type = StringSwitch<COFF::COMDATType>(TypeId)
492 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
493 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
494 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
495 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
496 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
497 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
498 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
499 .Default((COFF::COMDATType)0);
502 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
509 /// ParseDirectiveLinkOnce
510 /// ::= .linkonce [ identifier ]
511 bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
512 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
513 if (getLexer().is(AsmToken::Identifier))
514 if (parseCOMDATType(Type))
517 const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
518 getStreamer().getCurrentSection().first);
520 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
521 return Error(Loc, "cannot make section associative with .linkonce");
523 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
524 return Error(Loc, Twine("section '") + Current->getSectionName() +
525 "' is already linkonce");
527 Current->setSelection(Type);
529 if (getLexer().isNot(AsmToken::EndOfStatement))
530 return TokError("unexpected token in directive");
535 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
537 if (getParser().parseIdentifier(SymbolID))
540 if (getLexer().isNot(AsmToken::EndOfStatement))
541 return TokError("unexpected token in directive");
543 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
546 getStreamer().EmitWinCFIStartProc(Symbol);
550 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
552 getStreamer().EmitWinCFIEndProc();
556 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
558 getStreamer().EmitWinCFIStartChained();
562 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
564 getStreamer().EmitWinCFIEndChained();
568 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
570 if (getParser().parseIdentifier(SymbolID))
573 if (getLexer().isNot(AsmToken::Comma))
574 return TokError("you must specify one or both of @unwind or @except");
576 bool unwind = false, except = false;
577 if (ParseAtUnwindOrAtExcept(unwind, except))
579 if (getLexer().is(AsmToken::Comma)) {
581 if (ParseAtUnwindOrAtExcept(unwind, except))
584 if (getLexer().isNot(AsmToken::EndOfStatement))
585 return TokError("unexpected token in directive");
587 MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
590 getStreamer().EmitWinEHHandler(handler, unwind, except);
594 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
596 getStreamer().EmitWinEHHandlerData();
600 bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
602 if (ParseSEHRegisterNumber(Reg))
605 if (getLexer().isNot(AsmToken::EndOfStatement))
606 return TokError("unexpected token in directive");
609 getStreamer().EmitWinCFIPushReg(Reg);
613 bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
616 if (ParseSEHRegisterNumber(Reg))
618 if (getLexer().isNot(AsmToken::Comma))
619 return TokError("you must specify a stack pointer offset");
622 SMLoc startLoc = getLexer().getLoc();
623 if (getParser().parseAbsoluteExpression(Off))
627 return Error(startLoc, "offset is not a multiple of 16");
629 if (getLexer().isNot(AsmToken::EndOfStatement))
630 return TokError("unexpected token in directive");
633 getStreamer().EmitWinCFISetFrame(Reg, Off);
637 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
639 SMLoc startLoc = getLexer().getLoc();
640 if (getParser().parseAbsoluteExpression(Size))
644 return Error(startLoc, "size is not a multiple of 8");
646 if (getLexer().isNot(AsmToken::EndOfStatement))
647 return TokError("unexpected token in directive");
650 getStreamer().EmitWinCFIAllocStack(Size);
654 bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
657 if (ParseSEHRegisterNumber(Reg))
659 if (getLexer().isNot(AsmToken::Comma))
660 return TokError("you must specify an offset on the stack");
663 SMLoc startLoc = getLexer().getLoc();
664 if (getParser().parseAbsoluteExpression(Off))
668 return Error(startLoc, "size is not a multiple of 8");
670 if (getLexer().isNot(AsmToken::EndOfStatement))
671 return TokError("unexpected token in directive");
674 // FIXME: Err on %xmm* registers
675 getStreamer().EmitWinCFISaveReg(Reg, Off);
679 // FIXME: This method is inherently x86-specific. It should really be in the
681 bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
684 if (ParseSEHRegisterNumber(Reg))
686 if (getLexer().isNot(AsmToken::Comma))
687 return TokError("you must specify an offset on the stack");
690 SMLoc startLoc = getLexer().getLoc();
691 if (getParser().parseAbsoluteExpression(Off))
694 if (getLexer().isNot(AsmToken::EndOfStatement))
695 return TokError("unexpected token in directive");
698 return Error(startLoc, "offset is not a multiple of 16");
701 // FIXME: Err on non-%xmm* registers
702 getStreamer().EmitWinCFISaveXMM(Reg, Off);
706 bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
709 if (getLexer().is(AsmToken::At)) {
710 SMLoc startLoc = getLexer().getLoc();
712 if (!getParser().parseIdentifier(CodeID)) {
713 if (CodeID != "code")
714 return Error(startLoc, "expected @code");
719 if (getLexer().isNot(AsmToken::EndOfStatement))
720 return TokError("unexpected token in directive");
723 getStreamer().EmitWinCFIPushFrame(Code);
727 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
729 getStreamer().EmitWinCFIEndProlog();
733 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
734 StringRef identifier;
735 if (getLexer().isNot(AsmToken::At))
736 return TokError("a handler attribute must begin with '@'");
737 SMLoc startLoc = getLexer().getLoc();
739 if (getParser().parseIdentifier(identifier))
740 return Error(startLoc, "expected @unwind or @except");
741 if (identifier == "unwind")
743 else if (identifier == "except")
746 return Error(startLoc, "expected @unwind or @except");
750 bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
751 SMLoc startLoc = getLexer().getLoc();
752 if (getLexer().is(AsmToken::Percent)) {
753 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
756 if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
760 // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
761 // violation so this validation code is disabled.
763 // Check that this is a non-volatile register.
764 const unsigned *NVRegs = TAI.getCalleeSavedRegs();
766 for (i = 0; NVRegs[i] != 0; ++i)
767 if (NVRegs[i] == LLVMRegNo)
770 return Error(startLoc, "expected non-volatile register");
773 int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
775 return Error(startLoc,"register can't be represented in SEH unwind info");
780 if (getParser().parseAbsoluteExpression(n))
783 return Error(startLoc, "register number is too high");
792 MCAsmParserExtension *createCOFFAsmParser() {
793 return new COFFAsmParser;