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