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/MCParser/MCAsmLexer.h"
17 #include "llvm/MC/MCRegisterInfo.h"
18 #include "llvm/MC/MCSectionCOFF.h"
19 #include "llvm/MC/MCStreamer.h"
20 #include "llvm/MC/MCTargetAsmParser.h"
21 #include "llvm/Support/COFF.h"
26 class COFFAsmParser : public MCAsmParserExtension {
27 template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
28 void addDirectiveHandler(StringRef Directive) {
29 MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
30 this, HandleDirective<COFFAsmParser, HandlerMethod>);
31 getParser().addDirectiveHandler(Directive, Handler);
34 bool ParseSectionSwitch(StringRef Section,
35 unsigned Characteristics,
38 bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
39 SectionKind Kind, StringRef COMDATSymName,
40 COFF::COMDATType Type, const MCSectionCOFF *Assoc);
42 bool ParseSectionName(StringRef &SectionName);
43 bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags);
45 virtual void Initialize(MCAsmParser &Parser) {
46 // Call the base implementation.
47 MCAsmParserExtension::Initialize(Parser);
49 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
50 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
51 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
52 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
53 addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
54 addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
55 addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
56 addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
57 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
58 addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
60 // Win64 EH directives.
61 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
63 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
65 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
67 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
69 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
71 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
73 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
75 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
77 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
79 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
81 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
83 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
85 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
87 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
90 bool ParseSectionDirectiveText(StringRef, SMLoc) {
91 return ParseSectionSwitch(".text",
92 COFF::IMAGE_SCN_CNT_CODE
93 | COFF::IMAGE_SCN_MEM_EXECUTE
94 | COFF::IMAGE_SCN_MEM_READ,
95 SectionKind::getText());
97 bool ParseSectionDirectiveData(StringRef, SMLoc) {
98 return ParseSectionSwitch(".data",
99 COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
100 | COFF::IMAGE_SCN_MEM_READ
101 | COFF::IMAGE_SCN_MEM_WRITE,
102 SectionKind::getDataRel());
104 bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
105 return ParseSectionSwitch(".bss",
106 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
107 | COFF::IMAGE_SCN_MEM_READ
108 | COFF::IMAGE_SCN_MEM_WRITE,
109 SectionKind::getBSS());
112 bool ParseDirectiveSection(StringRef, SMLoc);
113 bool ParseDirectiveDef(StringRef, SMLoc);
114 bool ParseDirectiveScl(StringRef, SMLoc);
115 bool ParseDirectiveType(StringRef, SMLoc);
116 bool ParseDirectiveEndef(StringRef, SMLoc);
117 bool ParseDirectiveSecRel32(StringRef, SMLoc);
118 bool parseCOMDATTypeAndAssoc(COFF::COMDATType &Type,
119 const MCSectionCOFF *&Assoc);
120 bool ParseDirectiveLinkOnce(StringRef, SMLoc);
122 // Win64 EH directives.
123 bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
124 bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
125 bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
126 bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
127 bool ParseSEHDirectiveHandler(StringRef, SMLoc);
128 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
129 bool ParseSEHDirectivePushReg(StringRef, SMLoc);
130 bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
131 bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
132 bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
133 bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
134 bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
135 bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
137 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
138 bool ParseSEHRegisterNumber(unsigned &RegNo);
139 bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
144 } // end annonomous namespace.
146 static SectionKind computeSectionKind(unsigned Flags) {
147 if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
148 return SectionKind::getText();
149 if (Flags & COFF::IMAGE_SCN_MEM_READ &&
150 (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
151 return SectionKind::getReadOnly();
152 return SectionKind::getDataRel();
155 bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
168 bool ReadOnlyRemoved = false;
169 unsigned SecFlags = None;
171 for (unsigned i = 0; i < FlagsString.size(); ++i) {
172 switch (FlagsString[i]) {
177 case 'b': // bss section
179 if (SecFlags & InitData)
180 return TokError("conflicting section flags 'b' and 'd'.");
184 case 'd': // data section
185 SecFlags |= InitData;
186 if (SecFlags & Alloc)
187 return TokError("conflicting section flags 'b' and 'd'.");
188 SecFlags &= ~NoWrite;
189 if ((SecFlags & NoLoad) == 0)
193 case 'n': // section is not loaded
198 case 'r': // read-only
199 ReadOnlyRemoved = false;
201 if ((SecFlags & Code) == 0)
202 SecFlags |= InitData;
203 if ((SecFlags & NoLoad) == 0)
207 case 's': // shared section
208 SecFlags |= Shared | InitData;
209 SecFlags &= ~NoWrite;
210 if ((SecFlags & NoLoad) == 0)
214 case 'w': // writable
215 SecFlags &= ~NoWrite;
216 ReadOnlyRemoved = true;
219 case 'x': // executable section
221 if ((SecFlags & NoLoad) == 0)
223 if (!ReadOnlyRemoved)
227 case 'y': // not readable
228 SecFlags |= NoRead | NoWrite;
232 return TokError("unknown flag");
238 if (SecFlags == None)
242 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
243 if (SecFlags & InitData)
244 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
245 if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
246 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
247 if (SecFlags & NoLoad)
248 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
249 if ((SecFlags & NoRead) == 0)
250 *Flags |= COFF::IMAGE_SCN_MEM_READ;
251 if ((SecFlags & NoWrite) == 0)
252 *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
253 if (SecFlags & Shared)
254 *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
259 /// ParseDirectiveSymbolAttribute
260 /// ::= { ".weak", ... } [ identifier ( , identifier )* ]
261 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
262 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
263 .Case(".weak", MCSA_Weak)
264 .Default(MCSA_Invalid);
265 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
266 if (getLexer().isNot(AsmToken::EndOfStatement)) {
270 if (getParser().parseIdentifier(Name))
271 return TokError("expected identifier in directive");
273 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
275 getStreamer().EmitSymbolAttribute(Sym, Attr);
277 if (getLexer().is(AsmToken::EndOfStatement))
280 if (getLexer().isNot(AsmToken::Comma))
281 return TokError("unexpected token in directive");
290 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
291 unsigned Characteristics,
293 return ParseSectionSwitch(Section, Characteristics, Kind, "",
294 COFF::IMAGE_COMDAT_SELECT_ANY, 0);
297 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
298 unsigned Characteristics,
300 StringRef COMDATSymName,
301 COFF::COMDATType Type,
302 const MCSectionCOFF *Assoc) {
303 if (getLexer().isNot(AsmToken::EndOfStatement))
304 return TokError("unexpected token in section switching directive");
307 getStreamer().SwitchSection(getContext().getCOFFSection(
308 Section, Characteristics, Kind, COMDATSymName, Type, Assoc));
313 bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
314 if (!getLexer().is(AsmToken::Identifier))
317 SectionName = getTok().getIdentifier();
322 // .section name [, "flags"] [, identifier [ identifier ], identifier]
326 // b: BSS section (uninitialized data)
327 // d: data section (initialized data)
328 // n: Discardable section
329 // r: Readable section
331 // w: Writable section
332 // x: Executable section
333 // y: Not-readable section (clears 'r')
335 // Subsections are not supported.
336 bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
337 StringRef SectionName;
339 if (ParseSectionName(SectionName))
340 return TokError("expected identifier in directive");
342 unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
343 COFF::IMAGE_SCN_MEM_READ |
344 COFF::IMAGE_SCN_MEM_WRITE;
346 if (getLexer().is(AsmToken::Comma)) {
349 if (getLexer().isNot(AsmToken::String))
350 return TokError("expected string in directive");
352 StringRef FlagsStr = getTok().getStringContents();
355 if (ParseSectionFlags(FlagsStr, &Flags))
359 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
360 const MCSectionCOFF *Assoc = 0;
361 StringRef COMDATSymName;
362 if (getLexer().is(AsmToken::Comma)) {
365 Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
367 if (parseCOMDATTypeAndAssoc(Type, Assoc))
370 if (getLexer().isNot(AsmToken::Comma))
371 return TokError("expected comma in directive");
374 if (getParser().parseIdentifier(COMDATSymName))
375 return TokError("expected identifier in directive");
378 if (getLexer().isNot(AsmToken::EndOfStatement))
379 return TokError("unexpected token in directive");
381 SectionKind Kind = computeSectionKind(Flags);
382 ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type, Assoc);
386 bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
387 StringRef SymbolName;
389 if (getParser().parseIdentifier(SymbolName))
390 return TokError("expected identifier in directive");
392 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
394 getStreamer().BeginCOFFSymbolDef(Sym);
400 bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
401 int64_t SymbolStorageClass;
402 if (getParser().parseAbsoluteExpression(SymbolStorageClass))
405 if (getLexer().isNot(AsmToken::EndOfStatement))
406 return TokError("unexpected token in directive");
409 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
413 bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
415 if (getParser().parseAbsoluteExpression(Type))
418 if (getLexer().isNot(AsmToken::EndOfStatement))
419 return TokError("unexpected token in directive");
422 getStreamer().EmitCOFFSymbolType(Type);
426 bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
428 getStreamer().EndCOFFSymbolDef();
432 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
434 if (getParser().parseIdentifier(SymbolID))
437 if (getLexer().isNot(AsmToken::EndOfStatement))
438 return TokError("unexpected token in directive");
440 MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
443 getStreamer().EmitCOFFSecRel32(Symbol);
447 /// ::= [ identifier [ identifier ] ]
448 bool COFFAsmParser::parseCOMDATTypeAndAssoc(COFF::COMDATType &Type,
449 const MCSectionCOFF *&Assoc) {
450 StringRef TypeId = getTok().getIdentifier();
452 Type = StringSwitch<COFF::COMDATType>(TypeId)
453 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
454 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
455 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
456 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
457 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
458 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
459 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
460 .Default((COFF::COMDATType)0);
463 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
467 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
468 SMLoc Loc = getTok().getLoc();
470 if (ParseSectionName(AssocName))
471 return TokError("expected associated section name");
473 Assoc = static_cast<const MCSectionCOFF*>(
474 getContext().getCOFFSection(AssocName));
476 return Error(Loc, "cannot associate unknown section '" + AssocName + "'");
477 if (!(Assoc->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT))
478 return Error(Loc, "associated section must be a COMDAT section");
479 if (Assoc->getSelection() == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
480 return Error(Loc, "associated section cannot be itself associative");
486 /// ParseDirectiveLinkOnce
487 /// ::= .linkonce [ identifier [ identifier ] ]
488 bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
489 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
490 const MCSectionCOFF *Assoc = 0;
491 if (getLexer().is(AsmToken::Identifier))
492 if (parseCOMDATTypeAndAssoc(Type, Assoc))
495 const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
496 getStreamer().getCurrentSection().first);
499 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
500 if (Assoc == Current)
501 return Error(Loc, "cannot associate a section with itself");
504 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
505 return Error(Loc, Twine("section '") + Current->getSectionName() +
506 "' is already linkonce");
508 Current->setSelection(Type, Assoc);
510 if (getLexer().isNot(AsmToken::EndOfStatement))
511 return TokError("unexpected token in directive");
516 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
518 if (getParser().parseIdentifier(SymbolID))
521 if (getLexer().isNot(AsmToken::EndOfStatement))
522 return TokError("unexpected token in directive");
524 MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
527 getStreamer().EmitWin64EHStartProc(Symbol);
531 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
533 getStreamer().EmitWin64EHEndProc();
537 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
539 getStreamer().EmitWin64EHStartChained();
543 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
545 getStreamer().EmitWin64EHEndChained();
549 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
551 if (getParser().parseIdentifier(SymbolID))
554 if (getLexer().isNot(AsmToken::Comma))
555 return TokError("you must specify one or both of @unwind or @except");
557 bool unwind = false, except = false;
558 if (ParseAtUnwindOrAtExcept(unwind, except))
560 if (getLexer().is(AsmToken::Comma)) {
562 if (ParseAtUnwindOrAtExcept(unwind, except))
565 if (getLexer().isNot(AsmToken::EndOfStatement))
566 return TokError("unexpected token in directive");
568 MCSymbol *handler = getContext().GetOrCreateSymbol(SymbolID);
571 getStreamer().EmitWin64EHHandler(handler, unwind, except);
575 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
577 getStreamer().EmitWin64EHHandlerData();
581 bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
583 if (ParseSEHRegisterNumber(Reg))
586 if (getLexer().isNot(AsmToken::EndOfStatement))
587 return TokError("unexpected token in directive");
590 getStreamer().EmitWin64EHPushReg(Reg);
594 bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
597 if (ParseSEHRegisterNumber(Reg))
599 if (getLexer().isNot(AsmToken::Comma))
600 return TokError("you must specify a stack pointer offset");
603 SMLoc startLoc = getLexer().getLoc();
604 if (getParser().parseAbsoluteExpression(Off))
608 return Error(startLoc, "offset is not a multiple of 16");
610 if (getLexer().isNot(AsmToken::EndOfStatement))
611 return TokError("unexpected token in directive");
614 getStreamer().EmitWin64EHSetFrame(Reg, Off);
618 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
620 SMLoc startLoc = getLexer().getLoc();
621 if (getParser().parseAbsoluteExpression(Size))
625 return Error(startLoc, "size is not a multiple of 8");
627 if (getLexer().isNot(AsmToken::EndOfStatement))
628 return TokError("unexpected token in directive");
631 getStreamer().EmitWin64EHAllocStack(Size);
635 bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
638 if (ParseSEHRegisterNumber(Reg))
640 if (getLexer().isNot(AsmToken::Comma))
641 return TokError("you must specify an offset on the stack");
644 SMLoc startLoc = getLexer().getLoc();
645 if (getParser().parseAbsoluteExpression(Off))
649 return Error(startLoc, "size is not a multiple of 8");
651 if (getLexer().isNot(AsmToken::EndOfStatement))
652 return TokError("unexpected token in directive");
655 // FIXME: Err on %xmm* registers
656 getStreamer().EmitWin64EHSaveReg(Reg, Off);
660 // FIXME: This method is inherently x86-specific. It should really be in the
662 bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
665 if (ParseSEHRegisterNumber(Reg))
667 if (getLexer().isNot(AsmToken::Comma))
668 return TokError("you must specify an offset on the stack");
671 SMLoc startLoc = getLexer().getLoc();
672 if (getParser().parseAbsoluteExpression(Off))
675 if (getLexer().isNot(AsmToken::EndOfStatement))
676 return TokError("unexpected token in directive");
679 return Error(startLoc, "offset is not a multiple of 16");
682 // FIXME: Err on non-%xmm* registers
683 getStreamer().EmitWin64EHSaveXMM(Reg, Off);
687 bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
690 if (getLexer().is(AsmToken::At)) {
691 SMLoc startLoc = getLexer().getLoc();
693 if (!getParser().parseIdentifier(CodeID)) {
694 if (CodeID != "code")
695 return Error(startLoc, "expected @code");
700 if (getLexer().isNot(AsmToken::EndOfStatement))
701 return TokError("unexpected token in directive");
704 getStreamer().EmitWin64EHPushFrame(Code);
708 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
710 getStreamer().EmitWin64EHEndProlog();
714 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
715 StringRef identifier;
716 if (getLexer().isNot(AsmToken::At))
717 return TokError("a handler attribute must begin with '@'");
718 SMLoc startLoc = getLexer().getLoc();
720 if (getParser().parseIdentifier(identifier))
721 return Error(startLoc, "expected @unwind or @except");
722 if (identifier == "unwind")
724 else if (identifier == "except")
727 return Error(startLoc, "expected @unwind or @except");
731 bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
732 SMLoc startLoc = getLexer().getLoc();
733 if (getLexer().is(AsmToken::Percent)) {
734 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
737 if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
741 // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
742 // violation so this validation code is disabled.
744 // Check that this is a non-volatile register.
745 const unsigned *NVRegs = TAI.getCalleeSavedRegs();
747 for (i = 0; NVRegs[i] != 0; ++i)
748 if (NVRegs[i] == LLVMRegNo)
751 return Error(startLoc, "expected non-volatile register");
754 int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
756 return Error(startLoc,"register can't be represented in SEH unwind info");
761 if (getParser().parseAbsoluteExpression(n))
764 return Error(startLoc, "register number is too high");
773 MCAsmParserExtension *createCOFFAsmParser() {
774 return new COFFAsmParser;