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",
102 COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
103 | COFF::IMAGE_SCN_MEM_READ
104 | COFF::IMAGE_SCN_MEM_WRITE,
105 SectionKind::getDataRel());
107 bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
108 return ParseSectionSwitch(".bss",
109 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
110 | COFF::IMAGE_SCN_MEM_READ
111 | COFF::IMAGE_SCN_MEM_WRITE,
112 SectionKind::getBSS());
115 bool ParseDirectiveSection(StringRef, SMLoc);
116 bool ParseDirectiveDef(StringRef, SMLoc);
117 bool ParseDirectiveScl(StringRef, SMLoc);
118 bool ParseDirectiveType(StringRef, SMLoc);
119 bool ParseDirectiveEndef(StringRef, SMLoc);
120 bool ParseDirectiveSecRel32(StringRef, SMLoc);
121 bool ParseDirectiveSecIdx(StringRef, SMLoc);
122 bool ParseDirectiveSafeSEH(StringRef, SMLoc);
123 bool parseCOMDATType(COFF::COMDATType &Type);
124 bool ParseDirectiveLinkOnce(StringRef, SMLoc);
126 // Win64 EH directives.
127 bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
128 bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
129 bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
130 bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
131 bool ParseSEHDirectiveHandler(StringRef, SMLoc);
132 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
133 bool ParseSEHDirectivePushReg(StringRef, SMLoc);
134 bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
135 bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
136 bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
137 bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
138 bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
139 bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
141 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
142 bool ParseSEHRegisterNumber(unsigned &RegNo);
143 bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
148 } // end annonomous namespace.
150 static SectionKind computeSectionKind(unsigned Flags) {
151 if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
152 return SectionKind::getText();
153 if (Flags & COFF::IMAGE_SCN_MEM_READ &&
154 (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
155 return SectionKind::getReadOnly();
156 return SectionKind::getDataRel();
159 bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
172 bool ReadOnlyRemoved = false;
173 unsigned SecFlags = None;
175 for (char FlagChar : FlagsString) {
181 case 'b': // bss section
183 if (SecFlags & InitData)
184 return TokError("conflicting section flags 'b' and 'd'.");
188 case 'd': // data section
189 SecFlags |= InitData;
190 if (SecFlags & Alloc)
191 return TokError("conflicting section flags 'b' and 'd'.");
192 SecFlags &= ~NoWrite;
193 if ((SecFlags & NoLoad) == 0)
197 case 'n': // section is not loaded
202 case 'r': // read-only
203 ReadOnlyRemoved = false;
205 if ((SecFlags & Code) == 0)
206 SecFlags |= InitData;
207 if ((SecFlags & NoLoad) == 0)
211 case 's': // shared section
212 SecFlags |= Shared | InitData;
213 SecFlags &= ~NoWrite;
214 if ((SecFlags & NoLoad) == 0)
218 case 'w': // writable
219 SecFlags &= ~NoWrite;
220 ReadOnlyRemoved = true;
223 case 'x': // executable section
225 if ((SecFlags & NoLoad) == 0)
227 if (!ReadOnlyRemoved)
231 case 'y': // not readable
232 SecFlags |= NoRead | NoWrite;
236 return TokError("unknown flag");
242 if (SecFlags == None)
246 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
247 if (SecFlags & InitData)
248 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
249 if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
250 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
251 if (SecFlags & NoLoad)
252 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
253 if ((SecFlags & NoRead) == 0)
254 *Flags |= COFF::IMAGE_SCN_MEM_READ;
255 if ((SecFlags & NoWrite) == 0)
256 *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
257 if (SecFlags & Shared)
258 *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
263 /// ParseDirectiveSymbolAttribute
264 /// ::= { ".weak", ... } [ identifier ( , identifier )* ]
265 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
266 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
267 .Case(".weak", MCSA_Weak)
268 .Default(MCSA_Invalid);
269 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
270 if (getLexer().isNot(AsmToken::EndOfStatement)) {
274 if (getParser().parseIdentifier(Name))
275 return TokError("expected identifier in directive");
277 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
279 getStreamer().EmitSymbolAttribute(Sym, Attr);
281 if (getLexer().is(AsmToken::EndOfStatement))
284 if (getLexer().isNot(AsmToken::Comma))
285 return TokError("unexpected token in directive");
294 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
295 unsigned Characteristics,
297 return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
300 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
301 unsigned Characteristics,
303 StringRef COMDATSymName,
304 COFF::COMDATType Type) {
305 if (getLexer().isNot(AsmToken::EndOfStatement))
306 return TokError("unexpected token in section switching directive");
309 getStreamer().SwitchSection(getContext().getCOFFSection(
310 Section, Characteristics, Kind, COMDATSymName, Type));
315 bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
316 if (!getLexer().is(AsmToken::Identifier))
319 SectionName = getTok().getIdentifier();
324 // .section name [, "flags"] [, identifier [ identifier ], identifier]
328 // b: BSS section (uninitialized data)
329 // d: data section (initialized data)
330 // n: Discardable section
331 // r: Readable section
333 // w: Writable section
334 // x: Executable section
335 // y: Not-readable section (clears 'r')
337 // Subsections are not supported.
338 bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
339 StringRef SectionName;
341 if (ParseSectionName(SectionName))
342 return TokError("expected identifier in directive");
344 unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
345 COFF::IMAGE_SCN_MEM_READ |
346 COFF::IMAGE_SCN_MEM_WRITE;
348 if (getLexer().is(AsmToken::Comma)) {
351 if (getLexer().isNot(AsmToken::String))
352 return TokError("expected string in directive");
354 StringRef FlagsStr = getTok().getStringContents();
357 if (ParseSectionFlags(FlagsStr, &Flags))
361 COFF::COMDATType Type = (COFF::COMDATType)0;
362 StringRef COMDATSymName;
363 if (getLexer().is(AsmToken::Comma)) {
364 Type = COFF::IMAGE_COMDAT_SELECT_ANY;;
367 Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
369 if (!getLexer().is(AsmToken::Identifier))
370 return TokError("expected comdat type such as 'discard' or 'largest' "
371 "after protection bits");
373 if (parseCOMDATType(Type))
376 if (getLexer().isNot(AsmToken::Comma))
377 return TokError("expected comma in directive");
380 if (getParser().parseIdentifier(COMDATSymName))
381 return TokError("expected identifier in directive");
384 if (getLexer().isNot(AsmToken::EndOfStatement))
385 return TokError("unexpected token in directive");
387 SectionKind Kind = computeSectionKind(Flags);
389 const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
390 if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
391 Flags |= COFF::IMAGE_SCN_MEM_16BIT;
393 ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
397 bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
398 StringRef SymbolName;
400 if (getParser().parseIdentifier(SymbolName))
401 return TokError("expected identifier in directive");
403 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
405 getStreamer().BeginCOFFSymbolDef(Sym);
411 bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
412 int64_t SymbolStorageClass;
413 if (getParser().parseAbsoluteExpression(SymbolStorageClass))
416 if (getLexer().isNot(AsmToken::EndOfStatement))
417 return TokError("unexpected token in directive");
420 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
424 bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
426 if (getParser().parseAbsoluteExpression(Type))
429 if (getLexer().isNot(AsmToken::EndOfStatement))
430 return TokError("unexpected token in directive");
433 getStreamer().EmitCOFFSymbolType(Type);
437 bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
439 getStreamer().EndCOFFSymbolDef();
443 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
445 if (getParser().parseIdentifier(SymbolID))
446 return TokError("expected identifier in directive");
448 if (getLexer().isNot(AsmToken::EndOfStatement))
449 return TokError("unexpected token in directive");
451 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
454 getStreamer().EmitCOFFSecRel32(Symbol);
458 bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
460 if (getParser().parseIdentifier(SymbolID))
461 return TokError("expected identifier in directive");
463 if (getLexer().isNot(AsmToken::EndOfStatement))
464 return TokError("unexpected token in directive");
466 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
469 getStreamer().EmitCOFFSafeSEH(Symbol);
473 bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
475 if (getParser().parseIdentifier(SymbolID))
476 return TokError("expected identifier in directive");
478 if (getLexer().isNot(AsmToken::EndOfStatement))
479 return TokError("unexpected token in directive");
481 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
484 getStreamer().EmitCOFFSectionIndex(Symbol);
488 /// ::= [ identifier ]
489 bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
490 StringRef TypeId = getTok().getIdentifier();
492 Type = StringSwitch<COFF::COMDATType>(TypeId)
493 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
494 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
495 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
496 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
497 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
498 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
499 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
500 .Default((COFF::COMDATType)0);
503 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
510 /// ParseDirectiveLinkOnce
511 /// ::= .linkonce [ identifier ]
512 bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
513 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
514 if (getLexer().is(AsmToken::Identifier))
515 if (parseCOMDATType(Type))
518 const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
519 getStreamer().getCurrentSection().first);
521 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
522 return Error(Loc, "cannot make section associative with .linkonce");
524 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
525 return Error(Loc, Twine("section '") + Current->getSectionName() +
526 "' is already linkonce");
528 Current->setSelection(Type);
530 if (getLexer().isNot(AsmToken::EndOfStatement))
531 return TokError("unexpected token in directive");
536 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
538 if (getParser().parseIdentifier(SymbolID))
541 if (getLexer().isNot(AsmToken::EndOfStatement))
542 return TokError("unexpected token in directive");
544 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
547 getStreamer().EmitWinCFIStartProc(Symbol);
551 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
553 getStreamer().EmitWinCFIEndProc();
557 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
559 getStreamer().EmitWinCFIStartChained();
563 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
565 getStreamer().EmitWinCFIEndChained();
569 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
571 if (getParser().parseIdentifier(SymbolID))
574 if (getLexer().isNot(AsmToken::Comma))
575 return TokError("you must specify one or both of @unwind or @except");
577 bool unwind = false, except = false;
578 if (ParseAtUnwindOrAtExcept(unwind, except))
580 if (getLexer().is(AsmToken::Comma)) {
582 if (ParseAtUnwindOrAtExcept(unwind, except))
585 if (getLexer().isNot(AsmToken::EndOfStatement))
586 return TokError("unexpected token in directive");
588 MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
591 getStreamer().EmitWinEHHandler(handler, unwind, except);
595 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
597 getStreamer().EmitWinEHHandlerData();
601 bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
603 if (ParseSEHRegisterNumber(Reg))
606 if (getLexer().isNot(AsmToken::EndOfStatement))
607 return TokError("unexpected token in directive");
610 getStreamer().EmitWinCFIPushReg(Reg);
614 bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
617 if (ParseSEHRegisterNumber(Reg))
619 if (getLexer().isNot(AsmToken::Comma))
620 return TokError("you must specify a stack pointer offset");
623 SMLoc startLoc = getLexer().getLoc();
624 if (getParser().parseAbsoluteExpression(Off))
628 return Error(startLoc, "offset is not a multiple of 16");
630 if (getLexer().isNot(AsmToken::EndOfStatement))
631 return TokError("unexpected token in directive");
634 getStreamer().EmitWinCFISetFrame(Reg, Off);
638 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
640 SMLoc startLoc = getLexer().getLoc();
641 if (getParser().parseAbsoluteExpression(Size))
645 return Error(startLoc, "size is not a multiple of 8");
647 if (getLexer().isNot(AsmToken::EndOfStatement))
648 return TokError("unexpected token in directive");
651 getStreamer().EmitWinCFIAllocStack(Size);
655 bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
658 if (ParseSEHRegisterNumber(Reg))
660 if (getLexer().isNot(AsmToken::Comma))
661 return TokError("you must specify an offset on the stack");
664 SMLoc startLoc = getLexer().getLoc();
665 if (getParser().parseAbsoluteExpression(Off))
669 return Error(startLoc, "size is not a multiple of 8");
671 if (getLexer().isNot(AsmToken::EndOfStatement))
672 return TokError("unexpected token in directive");
675 // FIXME: Err on %xmm* registers
676 getStreamer().EmitWinCFISaveReg(Reg, Off);
680 // FIXME: This method is inherently x86-specific. It should really be in the
682 bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
685 if (ParseSEHRegisterNumber(Reg))
687 if (getLexer().isNot(AsmToken::Comma))
688 return TokError("you must specify an offset on the stack");
691 SMLoc startLoc = getLexer().getLoc();
692 if (getParser().parseAbsoluteExpression(Off))
695 if (getLexer().isNot(AsmToken::EndOfStatement))
696 return TokError("unexpected token in directive");
699 return Error(startLoc, "offset is not a multiple of 16");
702 // FIXME: Err on non-%xmm* registers
703 getStreamer().EmitWinCFISaveXMM(Reg, Off);
707 bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
710 if (getLexer().is(AsmToken::At)) {
711 SMLoc startLoc = getLexer().getLoc();
713 if (!getParser().parseIdentifier(CodeID)) {
714 if (CodeID != "code")
715 return Error(startLoc, "expected @code");
720 if (getLexer().isNot(AsmToken::EndOfStatement))
721 return TokError("unexpected token in directive");
724 getStreamer().EmitWinCFIPushFrame(Code);
728 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
730 getStreamer().EmitWinCFIEndProlog();
734 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
735 StringRef identifier;
736 if (getLexer().isNot(AsmToken::At))
737 return TokError("a handler attribute must begin with '@'");
738 SMLoc startLoc = getLexer().getLoc();
740 if (getParser().parseIdentifier(identifier))
741 return Error(startLoc, "expected @unwind or @except");
742 if (identifier == "unwind")
744 else if (identifier == "except")
747 return Error(startLoc, "expected @unwind or @except");
751 bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
752 SMLoc startLoc = getLexer().getLoc();
753 if (getLexer().is(AsmToken::Percent)) {
754 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
757 if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
761 // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
762 // violation so this validation code is disabled.
764 // Check that this is a non-volatile register.
765 const unsigned *NVRegs = TAI.getCalleeSavedRegs();
767 for (i = 0; NVRegs[i] != 0; ++i)
768 if (NVRegs[i] == LLVMRegNo)
771 return Error(startLoc, "expected non-volatile register");
774 int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
776 return Error(startLoc,"register can't be represented in SEH unwind info");
781 if (getParser().parseAbsoluteExpression(n))
784 return Error(startLoc, "register number is too high");
793 MCAsmParserExtension *createCOFFAsmParser() {
794 return new COFFAsmParser;