MC: Add .section directive to COFF
[oota-llvm.git] / lib / MC / MCParser / COFFAsmParser.cpp
1 //===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
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"
22 using namespace llvm;
23
24 namespace {
25
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);
32   }
33
34   bool ParseSectionSwitch(StringRef Section,
35                           unsigned Characteristics,
36                           SectionKind Kind);
37
38   bool ParseSectionName(StringRef &SectionName);
39   bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags);
40
41   virtual void Initialize(MCAsmParser &Parser) {
42     // Call the base implementation.
43     MCAsmParserExtension::Initialize(Parser);
44
45     addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
46     addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
47     addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
48     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
49     addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
50     addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
51     addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
52     addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
53     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
54
55     // Win64 EH directives.
56     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
57                                                                    ".seh_proc");
58     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
59                                                                 ".seh_endproc");
60     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
61                                                            ".seh_startchained");
62     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
63                                                              ".seh_endchained");
64     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
65                                                                 ".seh_handler");
66     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
67                                                             ".seh_handlerdata");
68     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
69                                                                 ".seh_pushreg");
70     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
71                                                                ".seh_setframe");
72     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
73                                                              ".seh_stackalloc");
74     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
75                                                                 ".seh_savereg");
76     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
77                                                                 ".seh_savexmm");
78     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
79                                                               ".seh_pushframe");
80     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
81                                                             ".seh_endprologue");
82     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
83   }
84
85   bool ParseSectionDirectiveText(StringRef, SMLoc) {
86     return ParseSectionSwitch(".text",
87                               COFF::IMAGE_SCN_CNT_CODE
88                             | COFF::IMAGE_SCN_MEM_EXECUTE
89                             | COFF::IMAGE_SCN_MEM_READ,
90                               SectionKind::getText());
91   }
92   bool ParseSectionDirectiveData(StringRef, SMLoc) {
93     return ParseSectionSwitch(".data",
94                               COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
95                             | COFF::IMAGE_SCN_MEM_READ
96                             | COFF::IMAGE_SCN_MEM_WRITE,
97                               SectionKind::getDataRel());
98   }
99   bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
100     return ParseSectionSwitch(".bss",
101                               COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
102                             | COFF::IMAGE_SCN_MEM_READ
103                             | COFF::IMAGE_SCN_MEM_WRITE,
104                               SectionKind::getBSS());
105   }
106
107   bool ParseDirectiveSection(StringRef, SMLoc);
108   bool ParseDirectiveDef(StringRef, SMLoc);
109   bool ParseDirectiveScl(StringRef, SMLoc);
110   bool ParseDirectiveType(StringRef, SMLoc);
111   bool ParseDirectiveEndef(StringRef, SMLoc);
112   bool ParseDirectiveSecRel32(StringRef, SMLoc);
113
114   // Win64 EH directives.
115   bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
116   bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
117   bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
118   bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
119   bool ParseSEHDirectiveHandler(StringRef, SMLoc);
120   bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
121   bool ParseSEHDirectivePushReg(StringRef, SMLoc);
122   bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
123   bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
124   bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
125   bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
126   bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
127   bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
128
129   bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
130   bool ParseSEHRegisterNumber(unsigned &RegNo);
131   bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
132 public:
133   COFFAsmParser() {}
134 };
135
136 } // end annonomous namespace.
137
138 static SectionKind computeSectionKind(unsigned Flags) {
139   if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
140     return SectionKind::getText();
141   if (Flags & COFF::IMAGE_SCN_MEM_READ &&
142       (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
143     return SectionKind::getReadOnly();
144   return SectionKind::getDataRel();
145 }
146
147 bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
148   enum {
149     None      = 0,
150     Alloc     = 1 << 0,
151     Code      = 1 << 1,
152     Load      = 1 << 2,
153     InitData  = 1 << 3,
154     Shared    = 1 << 4,
155     NoLoad    = 1 << 5,
156     NoRead    = 1 << 6,
157     NoWrite  =  1 << 7
158   };
159
160   bool ReadOnlyRemoved = false;
161   unsigned SecFlags = None;
162
163   for (unsigned i = 0; i < FlagsString.size(); ++i) {
164     switch (FlagsString[i]) {
165     case 'a':
166       // Ignored.
167       break;
168
169     case 'b': // bss section
170       SecFlags |= Alloc;
171       if (SecFlags & InitData)
172         return TokError("conflicting section flags 'b' and 'd'.");
173       SecFlags &= ~Load;
174       break;
175
176     case 'd': // data section
177       SecFlags |= InitData;
178       if (SecFlags & Alloc)
179         return TokError("conflicting section flags 'b' and 'd'.");
180       SecFlags &= ~NoWrite;
181       if ((SecFlags & NoLoad) == 0)
182         SecFlags |= Load;
183       break;
184
185     case 'n': // section is not loaded
186       SecFlags |= NoLoad;
187       SecFlags &= ~Load;
188       break;
189
190     case 'r': // read-only
191       ReadOnlyRemoved = false;
192       SecFlags |= NoWrite;
193       if ((SecFlags & Code) == 0)
194         SecFlags |= InitData;
195       if ((SecFlags & NoLoad) == 0)
196         SecFlags |= Load;
197       break;
198
199     case 's': // shared section
200       SecFlags |= Shared | InitData;
201       SecFlags &= ~NoWrite;
202       if ((SecFlags & NoLoad) == 0)
203         SecFlags |= Load;
204       break;
205
206     case 'w': // writable
207       SecFlags &= ~NoWrite;
208       ReadOnlyRemoved = true;
209       break;
210
211     case 'x': // executable section
212       SecFlags |= Code;
213       if ((SecFlags & NoLoad) == 0)
214         SecFlags |= Load;
215       if (!ReadOnlyRemoved)
216         SecFlags |= NoWrite;
217       break;
218
219     case 'y': // not readable
220       SecFlags |= NoRead | NoWrite;
221       break;
222
223     default:
224       return TokError("unknown flag");
225     }
226   }
227
228   *Flags = 0;
229
230   if (SecFlags == None)
231     SecFlags = InitData;
232
233   if (SecFlags & Code)
234     *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
235   if (SecFlags & InitData)
236     *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
237   if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
238     *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
239   if (SecFlags & NoLoad)
240     *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
241   if ((SecFlags & NoRead) == 0)
242     *Flags |= COFF::IMAGE_SCN_MEM_READ;
243   if ((SecFlags & NoWrite) == 0)
244     *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
245   if (SecFlags & Shared)
246     *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
247
248   return false;
249 }
250
251 /// ParseDirectiveSymbolAttribute
252 ///  ::= { ".weak", ... } [ identifier ( , identifier )* ]
253 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
254   MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
255     .Case(".weak", MCSA_Weak)
256     .Default(MCSA_Invalid);
257   assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
258   if (getLexer().isNot(AsmToken::EndOfStatement)) {
259     for (;;) {
260       StringRef Name;
261
262       if (getParser().parseIdentifier(Name))
263         return TokError("expected identifier in directive");
264
265       MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
266
267       getStreamer().EmitSymbolAttribute(Sym, Attr);
268
269       if (getLexer().is(AsmToken::EndOfStatement))
270         break;
271
272       if (getLexer().isNot(AsmToken::Comma))
273         return TokError("unexpected token in directive");
274       Lex();
275     }
276   }
277
278   Lex();
279   return false;
280 }
281
282 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
283                                        unsigned Characteristics,
284                                        SectionKind Kind) {
285   if (getLexer().isNot(AsmToken::EndOfStatement))
286     return TokError("unexpected token in section switching directive");
287   Lex();
288
289   getStreamer().SwitchSection(getContext().getCOFFSection(
290                                 Section, Characteristics, Kind));
291
292   return false;
293 }
294
295 bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
296   if (!getLexer().is(AsmToken::Identifier))
297     return true;
298
299   SectionName = getTok().getIdentifier();
300   Lex();
301   return false;
302 }
303
304 // .section name [, "flags"]
305 //
306 // Supported flags:
307 //   a: Ignored.
308 //   b: BSS section (uninitialized data)
309 //   d: data section (initialized data)
310 //   n: Discardable section
311 //   r: Readable section
312 //   s: Shared section
313 //   w: Writable section
314 //   x: Executable section
315 //   y: Not-readable section (clears 'r')
316 //
317 // Subsections are not supported.
318 bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
319   StringRef SectionName;
320
321   if (ParseSectionName(SectionName))
322     return TokError("expected identifier in directive");
323
324   unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
325                    COFF::IMAGE_SCN_MEM_READ |
326                    COFF::IMAGE_SCN_MEM_WRITE;
327
328   if (getLexer().is(AsmToken::Comma)) {
329     Lex();
330
331     if (getLexer().isNot(AsmToken::String))
332       return TokError("expected string in directive");
333
334     StringRef FlagsStr = getTok().getStringContents();
335     Lex();
336
337     if (ParseSectionFlags(FlagsStr, &Flags))
338       return true;
339   }
340
341   if (getLexer().isNot(AsmToken::EndOfStatement))
342     return TokError("unexpected token in directive");
343
344   SectionKind Kind = computeSectionKind(Flags);
345   ParseSectionSwitch(SectionName, Flags, Kind);
346   return false;
347 }
348
349 bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
350   StringRef SymbolName;
351
352   if (getParser().parseIdentifier(SymbolName))
353     return TokError("expected identifier in directive");
354
355   MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
356
357   getStreamer().BeginCOFFSymbolDef(Sym);
358
359   Lex();
360   return false;
361 }
362
363 bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
364   int64_t SymbolStorageClass;
365   if (getParser().parseAbsoluteExpression(SymbolStorageClass))
366     return true;
367
368   if (getLexer().isNot(AsmToken::EndOfStatement))
369     return TokError("unexpected token in directive");
370
371   Lex();
372   getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
373   return false;
374 }
375
376 bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
377   int64_t Type;
378   if (getParser().parseAbsoluteExpression(Type))
379     return true;
380
381   if (getLexer().isNot(AsmToken::EndOfStatement))
382     return TokError("unexpected token in directive");
383
384   Lex();
385   getStreamer().EmitCOFFSymbolType(Type);
386   return false;
387 }
388
389 bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
390   Lex();
391   getStreamer().EndCOFFSymbolDef();
392   return false;
393 }
394
395 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
396   StringRef SymbolID;
397   if (getParser().parseIdentifier(SymbolID))
398     return true;
399
400   if (getLexer().isNot(AsmToken::EndOfStatement))
401     return TokError("unexpected token in directive");
402
403   MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
404
405   Lex();
406   getStreamer().EmitCOFFSecRel32(Symbol);
407   return false;
408 }
409
410 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
411   StringRef SymbolID;
412   if (getParser().parseIdentifier(SymbolID))
413     return true;
414
415   if (getLexer().isNot(AsmToken::EndOfStatement))
416     return TokError("unexpected token in directive");
417
418   MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
419
420   Lex();
421   getStreamer().EmitWin64EHStartProc(Symbol);
422   return false;
423 }
424
425 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
426   Lex();
427   getStreamer().EmitWin64EHEndProc();
428   return false;
429 }
430
431 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
432   Lex();
433   getStreamer().EmitWin64EHStartChained();
434   return false;
435 }
436
437 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
438   Lex();
439   getStreamer().EmitWin64EHEndChained();
440   return false;
441 }
442
443 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
444   StringRef SymbolID;
445   if (getParser().parseIdentifier(SymbolID))
446     return true;
447
448   if (getLexer().isNot(AsmToken::Comma))
449     return TokError("you must specify one or both of @unwind or @except");
450   Lex();
451   bool unwind = false, except = false;
452   if (ParseAtUnwindOrAtExcept(unwind, except))
453     return true;
454   if (getLexer().is(AsmToken::Comma)) {
455     Lex();
456     if (ParseAtUnwindOrAtExcept(unwind, except))
457       return true;
458   }
459   if (getLexer().isNot(AsmToken::EndOfStatement))
460     return TokError("unexpected token in directive");
461
462   MCSymbol *handler = getContext().GetOrCreateSymbol(SymbolID);
463
464   Lex();
465   getStreamer().EmitWin64EHHandler(handler, unwind, except);
466   return false;
467 }
468
469 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
470   Lex();
471   getStreamer().EmitWin64EHHandlerData();
472   return false;
473 }
474
475 bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
476   unsigned Reg;
477   if (ParseSEHRegisterNumber(Reg))
478     return true;
479
480   if (getLexer().isNot(AsmToken::EndOfStatement))
481     return TokError("unexpected token in directive");
482
483   Lex();
484   getStreamer().EmitWin64EHPushReg(Reg);
485   return false;
486 }
487
488 bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
489   unsigned Reg;
490   int64_t Off;
491   if (ParseSEHRegisterNumber(Reg))
492     return true;
493   if (getLexer().isNot(AsmToken::Comma))
494     return TokError("you must specify a stack pointer offset");
495
496   Lex();
497   SMLoc startLoc = getLexer().getLoc();
498   if (getParser().parseAbsoluteExpression(Off))
499     return true;
500
501   if (Off & 0x0F)
502     return Error(startLoc, "offset is not a multiple of 16");
503
504   if (getLexer().isNot(AsmToken::EndOfStatement))
505     return TokError("unexpected token in directive");
506
507   Lex();
508   getStreamer().EmitWin64EHSetFrame(Reg, Off);
509   return false;
510 }
511
512 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
513   int64_t Size;
514   SMLoc startLoc = getLexer().getLoc();
515   if (getParser().parseAbsoluteExpression(Size))
516     return true;
517
518   if (Size & 7)
519     return Error(startLoc, "size is not a multiple of 8");
520
521   if (getLexer().isNot(AsmToken::EndOfStatement))
522     return TokError("unexpected token in directive");
523
524   Lex();
525   getStreamer().EmitWin64EHAllocStack(Size);
526   return false;
527 }
528
529 bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
530   unsigned Reg;
531   int64_t Off;
532   if (ParseSEHRegisterNumber(Reg))
533     return true;
534   if (getLexer().isNot(AsmToken::Comma))
535     return TokError("you must specify an offset on the stack");
536
537   Lex();
538   SMLoc startLoc = getLexer().getLoc();
539   if (getParser().parseAbsoluteExpression(Off))
540     return true;
541
542   if (Off & 7)
543     return Error(startLoc, "size is not a multiple of 8");
544
545   if (getLexer().isNot(AsmToken::EndOfStatement))
546     return TokError("unexpected token in directive");
547
548   Lex();
549   // FIXME: Err on %xmm* registers
550   getStreamer().EmitWin64EHSaveReg(Reg, Off);
551   return false;
552 }
553
554 // FIXME: This method is inherently x86-specific. It should really be in the
555 // x86 backend.
556 bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
557   unsigned Reg;
558   int64_t Off;
559   if (ParseSEHRegisterNumber(Reg))
560     return true;
561   if (getLexer().isNot(AsmToken::Comma))
562     return TokError("you must specify an offset on the stack");
563
564   Lex();
565   SMLoc startLoc = getLexer().getLoc();
566   if (getParser().parseAbsoluteExpression(Off))
567     return true;
568
569   if (getLexer().isNot(AsmToken::EndOfStatement))
570     return TokError("unexpected token in directive");
571
572   if (Off & 0x0F)
573     return Error(startLoc, "offset is not a multiple of 16");
574
575   Lex();
576   // FIXME: Err on non-%xmm* registers
577   getStreamer().EmitWin64EHSaveXMM(Reg, Off);
578   return false;
579 }
580
581 bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
582   bool Code = false;
583   StringRef CodeID;
584   if (getLexer().is(AsmToken::At)) {
585     SMLoc startLoc = getLexer().getLoc();
586     Lex();
587     if (!getParser().parseIdentifier(CodeID)) {
588       if (CodeID != "code")
589         return Error(startLoc, "expected @code");
590       Code = true;
591     }
592   }
593
594   if (getLexer().isNot(AsmToken::EndOfStatement))
595     return TokError("unexpected token in directive");
596
597   Lex();
598   getStreamer().EmitWin64EHPushFrame(Code);
599   return false;
600 }
601
602 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
603   Lex();
604   getStreamer().EmitWin64EHEndProlog();
605   return false;
606 }
607
608 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
609   StringRef identifier;
610   if (getLexer().isNot(AsmToken::At))
611     return TokError("a handler attribute must begin with '@'");
612   SMLoc startLoc = getLexer().getLoc();
613   Lex();
614   if (getParser().parseIdentifier(identifier))
615     return Error(startLoc, "expected @unwind or @except");
616   if (identifier == "unwind")
617     unwind = true;
618   else if (identifier == "except")
619     except = true;
620   else
621     return Error(startLoc, "expected @unwind or @except");
622   return false;
623 }
624
625 bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
626   SMLoc startLoc = getLexer().getLoc();
627   if (getLexer().is(AsmToken::Percent)) {
628     const MCRegisterInfo *MRI = getContext().getRegisterInfo();
629     SMLoc endLoc;
630     unsigned LLVMRegNo;
631     if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
632       return true;
633
634 #if 0
635     // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
636     // violation so this validation code is disabled.
637
638     // Check that this is a non-volatile register.
639     const unsigned *NVRegs = TAI.getCalleeSavedRegs();
640     unsigned i;
641     for (i = 0; NVRegs[i] != 0; ++i)
642       if (NVRegs[i] == LLVMRegNo)
643         break;
644     if (NVRegs[i] == 0)
645       return Error(startLoc, "expected non-volatile register");
646 #endif
647
648     int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
649     if (SEHRegNo < 0)
650       return Error(startLoc,"register can't be represented in SEH unwind info");
651     RegNo = SEHRegNo;
652   }
653   else {
654     int64_t n;
655     if (getParser().parseAbsoluteExpression(n))
656       return true;
657     if (n > 15)
658       return Error(startLoc, "register number is too high");
659     RegNo = n;
660   }
661
662   return false;
663 }
664
665 namespace llvm {
666
667 MCAsmParserExtension *createCOFFAsmParser() {
668   return new COFFAsmParser;
669 }
670
671 }