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