OSDN Git Service

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