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