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