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