LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
COFFAsmParser.cpp
Go to the documentation of this file.
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 
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"
17 #include "llvm/MC/MCRegisterInfo.h"
18 #include "llvm/MC/MCSectionCOFF.h"
19 #include "llvm/MC/MCStreamer.h"
21 #include "llvm/Support/COFF.h"
22 using namespace llvm;
23 
24 namespace {
25 
26 class COFFAsmParser : public MCAsmParserExtension {
27  template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
28  void addDirectiveHandler(StringRef Directive) {
29  MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
30  this, HandleDirective<COFFAsmParser, HandlerMethod>);
31  getParser().addDirectiveHandler(Directive, Handler);
32  }
33 
34  bool ParseSectionSwitch(StringRef Section,
35  unsigned Characteristics,
37 
38  bool ParseSectionName(StringRef &SectionName);
39  bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags);
40 
41  virtual void Initialize(MCAsmParser &Parser) {
42  // Call the base implementation.
44 
45  addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
46  addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
47  addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
48  addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
49  addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
50  addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
51  addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
52  addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
53  addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
54  addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
55 
56  // Win64 EH directives.
57  addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
58  ".seh_proc");
59  addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
60  ".seh_endproc");
61  addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
62  ".seh_startchained");
63  addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
64  ".seh_endchained");
65  addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
66  ".seh_handler");
67  addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
68  ".seh_handlerdata");
69  addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
70  ".seh_pushreg");
71  addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
72  ".seh_setframe");
73  addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
74  ".seh_stackalloc");
75  addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
76  ".seh_savereg");
77  addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
78  ".seh_savexmm");
79  addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
80  ".seh_pushframe");
81  addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
82  ".seh_endprologue");
83  addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
84  }
85 
86  bool ParseSectionDirectiveText(StringRef, SMLoc) {
87  return ParseSectionSwitch(".text",
88  COFF::IMAGE_SCN_CNT_CODE
89  | COFF::IMAGE_SCN_MEM_EXECUTE
90  | COFF::IMAGE_SCN_MEM_READ,
92  }
93  bool ParseSectionDirectiveData(StringRef, SMLoc) {
94  return ParseSectionSwitch(".data",
95  COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
96  | COFF::IMAGE_SCN_MEM_READ
97  | COFF::IMAGE_SCN_MEM_WRITE,
99  }
100  bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
101  return ParseSectionSwitch(".bss",
102  COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
103  | COFF::IMAGE_SCN_MEM_READ
104  | COFF::IMAGE_SCN_MEM_WRITE,
106  }
107 
108  bool ParseDirectiveSection(StringRef, SMLoc);
109  bool ParseDirectiveDef(StringRef, SMLoc);
110  bool ParseDirectiveScl(StringRef, SMLoc);
111  bool ParseDirectiveType(StringRef, SMLoc);
112  bool ParseDirectiveEndef(StringRef, SMLoc);
113  bool ParseDirectiveSecRel32(StringRef, SMLoc);
114  bool ParseDirectiveLinkOnce(StringRef, SMLoc);
115 
116  // Win64 EH directives.
117  bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
118  bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
119  bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
120  bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
121  bool ParseSEHDirectiveHandler(StringRef, SMLoc);
122  bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
123  bool ParseSEHDirectivePushReg(StringRef, SMLoc);
124  bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
125  bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
126  bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
127  bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
128  bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
129  bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
130 
131  bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
132  bool ParseSEHRegisterNumber(unsigned &RegNo);
133  bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
134 public:
135  COFFAsmParser() {}
136 };
137 
138 } // end annonomous namespace.
139 
141  if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
142  return SectionKind::getText();
143  if (Flags & COFF::IMAGE_SCN_MEM_READ &&
144  (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
145  return SectionKind::getReadOnly();
146  return SectionKind::getDataRel();
147 }
148 
149 bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
150  enum {
151  None = 0,
152  Alloc = 1 << 0,
153  Code = 1 << 1,
154  Load = 1 << 2,
155  InitData = 1 << 3,
156  Shared = 1 << 4,
157  NoLoad = 1 << 5,
158  NoRead = 1 << 6,
159  NoWrite = 1 << 7
160  };
161 
162  bool ReadOnlyRemoved = false;
163  unsigned SecFlags = None;
164 
165  for (unsigned i = 0; i < FlagsString.size(); ++i) {
166  switch (FlagsString[i]) {
167  case 'a':
168  // Ignored.
169  break;
170 
171  case 'b': // bss section
172  SecFlags |= Alloc;
173  if (SecFlags & InitData)
174  return TokError("conflicting section flags 'b' and 'd'.");
175  SecFlags &= ~Load;
176  break;
177 
178  case 'd': // data section
179  SecFlags |= InitData;
180  if (SecFlags & Alloc)
181  return TokError("conflicting section flags 'b' and 'd'.");
182  SecFlags &= ~NoWrite;
183  if ((SecFlags & NoLoad) == 0)
184  SecFlags |= Load;
185  break;
186 
187  case 'n': // section is not loaded
188  SecFlags |= NoLoad;
189  SecFlags &= ~Load;
190  break;
191 
192  case 'r': // read-only
193  ReadOnlyRemoved = false;
194  SecFlags |= NoWrite;
195  if ((SecFlags & Code) == 0)
196  SecFlags |= InitData;
197  if ((SecFlags & NoLoad) == 0)
198  SecFlags |= Load;
199  break;
200 
201  case 's': // shared section
202  SecFlags |= Shared | InitData;
203  SecFlags &= ~NoWrite;
204  if ((SecFlags & NoLoad) == 0)
205  SecFlags |= Load;
206  break;
207 
208  case 'w': // writable
209  SecFlags &= ~NoWrite;
210  ReadOnlyRemoved = true;
211  break;
212 
213  case 'x': // executable section
214  SecFlags |= Code;
215  if ((SecFlags & NoLoad) == 0)
216  SecFlags |= Load;
217  if (!ReadOnlyRemoved)
218  SecFlags |= NoWrite;
219  break;
220 
221  case 'y': // not readable
222  SecFlags |= NoRead | NoWrite;
223  break;
224 
225  default:
226  return TokError("unknown flag");
227  }
228  }
229 
230  *Flags = 0;
231 
232  if (SecFlags == None)
233  SecFlags = InitData;
234 
235  if (SecFlags & Code)
236  *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
237  if (SecFlags & InitData)
238  *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
239  if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
240  *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
241  if (SecFlags & NoLoad)
242  *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
243  if ((SecFlags & NoRead) == 0)
244  *Flags |= COFF::IMAGE_SCN_MEM_READ;
245  if ((SecFlags & NoWrite) == 0)
246  *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
247  if (SecFlags & Shared)
248  *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
249 
250  return false;
251 }
252 
253 /// ParseDirectiveSymbolAttribute
254 /// ::= { ".weak", ... } [ identifier ( , identifier )* ]
255 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
256  MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
257  .Case(".weak", MCSA_Weak)
259  assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
260  if (getLexer().isNot(AsmToken::EndOfStatement)) {
261  for (;;) {
262  StringRef Name;
263 
264  if (getParser().parseIdentifier(Name))
265  return TokError("expected identifier in directive");
266 
267  MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
268 
269  getStreamer().EmitSymbolAttribute(Sym, Attr);
270 
271  if (getLexer().is(AsmToken::EndOfStatement))
272  break;
273 
274  if (getLexer().isNot(AsmToken::Comma))
275  return TokError("unexpected token in directive");
276  Lex();
277  }
278  }
279 
280  Lex();
281  return false;
282 }
283 
284 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
285  unsigned Characteristics,
286  SectionKind Kind) {
287  if (getLexer().isNot(AsmToken::EndOfStatement))
288  return TokError("unexpected token in section switching directive");
289  Lex();
290 
291  getStreamer().SwitchSection(getContext().getCOFFSection(
292  Section, Characteristics, Kind));
293 
294  return false;
295 }
296 
297 bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
298  if (!getLexer().is(AsmToken::Identifier))
299  return true;
300 
301  SectionName = getTok().getIdentifier();
302  Lex();
303  return false;
304 }
305 
306 // .section name [, "flags"]
307 //
308 // Supported flags:
309 // a: Ignored.
310 // b: BSS section (uninitialized data)
311 // d: data section (initialized data)
312 // n: Discardable section
313 // r: Readable section
314 // s: Shared section
315 // w: Writable section
316 // x: Executable section
317 // y: Not-readable section (clears 'r')
318 //
319 // Subsections are not supported.
320 bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
321  StringRef SectionName;
322 
323  if (ParseSectionName(SectionName))
324  return TokError("expected identifier in directive");
325 
326  unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
327  COFF::IMAGE_SCN_MEM_READ |
328  COFF::IMAGE_SCN_MEM_WRITE;
329 
330  if (getLexer().is(AsmToken::Comma)) {
331  Lex();
332 
333  if (getLexer().isNot(AsmToken::String))
334  return TokError("expected string in directive");
335 
336  StringRef FlagsStr = getTok().getStringContents();
337  Lex();
338 
339  if (ParseSectionFlags(FlagsStr, &Flags))
340  return true;
341  }
342 
343  if (getLexer().isNot(AsmToken::EndOfStatement))
344  return TokError("unexpected token in directive");
345 
346  SectionKind Kind = computeSectionKind(Flags);
347  ParseSectionSwitch(SectionName, Flags, Kind);
348  return false;
349 }
350 
351 bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
352  StringRef SymbolName;
353 
354  if (getParser().parseIdentifier(SymbolName))
355  return TokError("expected identifier in directive");
356 
357  MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
358 
359  getStreamer().BeginCOFFSymbolDef(Sym);
360 
361  Lex();
362  return false;
363 }
364 
365 bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
366  int64_t SymbolStorageClass;
367  if (getParser().parseAbsoluteExpression(SymbolStorageClass))
368  return true;
369 
370  if (getLexer().isNot(AsmToken::EndOfStatement))
371  return TokError("unexpected token in directive");
372 
373  Lex();
374  getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
375  return false;
376 }
377 
378 bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
379  int64_t Type;
380  if (getParser().parseAbsoluteExpression(Type))
381  return true;
382 
383  if (getLexer().isNot(AsmToken::EndOfStatement))
384  return TokError("unexpected token in directive");
385 
386  Lex();
387  getStreamer().EmitCOFFSymbolType(Type);
388  return false;
389 }
390 
391 bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
392  Lex();
393  getStreamer().EndCOFFSymbolDef();
394  return false;
395 }
396 
397 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
398  StringRef SymbolID;
399  if (getParser().parseIdentifier(SymbolID))
400  return true;
401 
402  if (getLexer().isNot(AsmToken::EndOfStatement))
403  return TokError("unexpected token in directive");
404 
405  MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
406 
407  Lex();
408  getStreamer().EmitCOFFSecRel32(Symbol);
409  return false;
410 }
411 
412 /// ParseDirectiveLinkOnce
413 /// ::= .linkonce [ identifier [ identifier ] ]
414 bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
416 
417  if (getLexer().is(AsmToken::Identifier)) {
418  StringRef TypeId = getTok().getIdentifier();
419 
420  Type = StringSwitch<COFF::COMDATType>(TypeId)
421  .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
429 
430  if (Type == 0)
431  return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
432 
433  Lex();
434  }
435 
436  const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
437  getStreamer().getCurrentSection().first);
438 
439  const MCSectionCOFF *Assoc = 0;
441  StringRef AssocName;
442  SMLoc Loc = getTok().getLoc();
443  if (ParseSectionName(AssocName))
444  return TokError("expected associated section name");
445 
446  Assoc = static_cast<const MCSectionCOFF*>(
447  getContext().getCOFFSection(AssocName));
448  if (!Assoc)
449  return Error(Loc, "cannot associate unknown section '" + AssocName + "'");
450  if (Assoc == Current)
451  return Error(Loc, "cannot associate a section with itself");
452  if (!(Assoc->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT))
453  return Error(Loc, "associated section must be a COMDAT section");
455  return Error(Loc, "associated section cannot be itself associative");
456  }
457 
458  if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
459  return Error(Loc, Twine("section '") + Current->getSectionName() +
460  "' is already linkonce");
461 
462  Current->setSelection(Type, Assoc);
463 
464  if (getLexer().isNot(AsmToken::EndOfStatement))
465  return TokError("unexpected token in directive");
466 
467  return false;
468 }
469 
470 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
471  StringRef SymbolID;
472  if (getParser().parseIdentifier(SymbolID))
473  return true;
474 
475  if (getLexer().isNot(AsmToken::EndOfStatement))
476  return TokError("unexpected token in directive");
477 
478  MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
479 
480  Lex();
481  getStreamer().EmitWin64EHStartProc(Symbol);
482  return false;
483 }
484 
485 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
486  Lex();
487  getStreamer().EmitWin64EHEndProc();
488  return false;
489 }
490 
491 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
492  Lex();
493  getStreamer().EmitWin64EHStartChained();
494  return false;
495 }
496 
497 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
498  Lex();
499  getStreamer().EmitWin64EHEndChained();
500  return false;
501 }
502 
503 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
504  StringRef SymbolID;
505  if (getParser().parseIdentifier(SymbolID))
506  return true;
507 
508  if (getLexer().isNot(AsmToken::Comma))
509  return TokError("you must specify one or both of @unwind or @except");
510  Lex();
511  bool unwind = false, except = false;
512  if (ParseAtUnwindOrAtExcept(unwind, except))
513  return true;
514  if (getLexer().is(AsmToken::Comma)) {
515  Lex();
516  if (ParseAtUnwindOrAtExcept(unwind, except))
517  return true;
518  }
519  if (getLexer().isNot(AsmToken::EndOfStatement))
520  return TokError("unexpected token in directive");
521 
522  MCSymbol *handler = getContext().GetOrCreateSymbol(SymbolID);
523 
524  Lex();
525  getStreamer().EmitWin64EHHandler(handler, unwind, except);
526  return false;
527 }
528 
529 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
530  Lex();
531  getStreamer().EmitWin64EHHandlerData();
532  return false;
533 }
534 
535 bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
536  unsigned Reg;
537  if (ParseSEHRegisterNumber(Reg))
538  return true;
539 
540  if (getLexer().isNot(AsmToken::EndOfStatement))
541  return TokError("unexpected token in directive");
542 
543  Lex();
544  getStreamer().EmitWin64EHPushReg(Reg);
545  return false;
546 }
547 
548 bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
549  unsigned Reg;
550  int64_t Off;
551  if (ParseSEHRegisterNumber(Reg))
552  return true;
553  if (getLexer().isNot(AsmToken::Comma))
554  return TokError("you must specify a stack pointer offset");
555 
556  Lex();
557  SMLoc startLoc = getLexer().getLoc();
558  if (getParser().parseAbsoluteExpression(Off))
559  return true;
560 
561  if (Off & 0x0F)
562  return Error(startLoc, "offset is not a multiple of 16");
563 
564  if (getLexer().isNot(AsmToken::EndOfStatement))
565  return TokError("unexpected token in directive");
566 
567  Lex();
568  getStreamer().EmitWin64EHSetFrame(Reg, Off);
569  return false;
570 }
571 
572 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
573  int64_t Size;
574  SMLoc startLoc = getLexer().getLoc();
575  if (getParser().parseAbsoluteExpression(Size))
576  return true;
577 
578  if (Size & 7)
579  return Error(startLoc, "size is not a multiple of 8");
580 
581  if (getLexer().isNot(AsmToken::EndOfStatement))
582  return TokError("unexpected token in directive");
583 
584  Lex();
585  getStreamer().EmitWin64EHAllocStack(Size);
586  return false;
587 }
588 
589 bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
590  unsigned Reg;
591  int64_t Off;
592  if (ParseSEHRegisterNumber(Reg))
593  return true;
594  if (getLexer().isNot(AsmToken::Comma))
595  return TokError("you must specify an offset on the stack");
596 
597  Lex();
598  SMLoc startLoc = getLexer().getLoc();
599  if (getParser().parseAbsoluteExpression(Off))
600  return true;
601 
602  if (Off & 7)
603  return Error(startLoc, "size is not a multiple of 8");
604 
605  if (getLexer().isNot(AsmToken::EndOfStatement))
606  return TokError("unexpected token in directive");
607 
608  Lex();
609  // FIXME: Err on %xmm* registers
610  getStreamer().EmitWin64EHSaveReg(Reg, Off);
611  return false;
612 }
613 
614 // FIXME: This method is inherently x86-specific. It should really be in the
615 // x86 backend.
616 bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
617  unsigned Reg;
618  int64_t Off;
619  if (ParseSEHRegisterNumber(Reg))
620  return true;
621  if (getLexer().isNot(AsmToken::Comma))
622  return TokError("you must specify an offset on the stack");
623 
624  Lex();
625  SMLoc startLoc = getLexer().getLoc();
626  if (getParser().parseAbsoluteExpression(Off))
627  return true;
628 
629  if (getLexer().isNot(AsmToken::EndOfStatement))
630  return TokError("unexpected token in directive");
631 
632  if (Off & 0x0F)
633  return Error(startLoc, "offset is not a multiple of 16");
634 
635  Lex();
636  // FIXME: Err on non-%xmm* registers
637  getStreamer().EmitWin64EHSaveXMM(Reg, Off);
638  return false;
639 }
640 
641 bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
642  bool Code = false;
643  StringRef CodeID;
644  if (getLexer().is(AsmToken::At)) {
645  SMLoc startLoc = getLexer().getLoc();
646  Lex();
647  if (!getParser().parseIdentifier(CodeID)) {
648  if (CodeID != "code")
649  return Error(startLoc, "expected @code");
650  Code = true;
651  }
652  }
653 
654  if (getLexer().isNot(AsmToken::EndOfStatement))
655  return TokError("unexpected token in directive");
656 
657  Lex();
658  getStreamer().EmitWin64EHPushFrame(Code);
659  return false;
660 }
661 
662 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
663  Lex();
664  getStreamer().EmitWin64EHEndProlog();
665  return false;
666 }
667 
668 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
669  StringRef identifier;
670  if (getLexer().isNot(AsmToken::At))
671  return TokError("a handler attribute must begin with '@'");
672  SMLoc startLoc = getLexer().getLoc();
673  Lex();
674  if (getParser().parseIdentifier(identifier))
675  return Error(startLoc, "expected @unwind or @except");
676  if (identifier == "unwind")
677  unwind = true;
678  else if (identifier == "except")
679  except = true;
680  else
681  return Error(startLoc, "expected @unwind or @except");
682  return false;
683 }
684 
685 bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
686  SMLoc startLoc = getLexer().getLoc();
687  if (getLexer().is(AsmToken::Percent)) {
688  const MCRegisterInfo *MRI = getContext().getRegisterInfo();
689  SMLoc endLoc;
690  unsigned LLVMRegNo;
691  if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
692  return true;
693 
694 #if 0
695  // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
696  // violation so this validation code is disabled.
697 
698  // Check that this is a non-volatile register.
699  const unsigned *NVRegs = TAI.getCalleeSavedRegs();
700  unsigned i;
701  for (i = 0; NVRegs[i] != 0; ++i)
702  if (NVRegs[i] == LLVMRegNo)
703  break;
704  if (NVRegs[i] == 0)
705  return Error(startLoc, "expected non-volatile register");
706 #endif
707 
708  int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
709  if (SEHRegNo < 0)
710  return Error(startLoc,"register can't be represented in SEH unwind info");
711  RegNo = SEHRegNo;
712  }
713  else {
714  int64_t n;
715  if (getParser().parseAbsoluteExpression(n))
716  return true;
717  if (n > 15)
718  return Error(startLoc, "register number is too high");
719  RegNo = n;
720  }
721 
722  return false;
723 }
724 
725 namespace llvm {
726 
728  return new COFFAsmParser;
729 }
730 
731 }
COFF::RelocationTypeX86 Type
Definition: COFFYAML.cpp:227
size_t size() const
size - Get the string size.
Definition: StringRef.h:113
Not a valid directive.
Definition: MCDirectives.h:20
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser. The extension should use the AsmParser i...
static SectionKind getDataRel()
Definition: SectionKind.h:229
int getSelection() const
Definition: MCSectionCOFF.h:71
StringSwitch & Case(const char(&S)[N], const T &Value)
Definition: StringSwitch.h:55
static SectionKind computeSectionKind(unsigned Flags)
MCSectionCOFF - This represents a section on Windows.
Definition: MCSectionCOFF.h:24
static SectionKind getBSS()
Definition: SectionKind.h:225
int getSEHRegNum(unsigned RegNum) const
Map a target register to an equivalent SEH register number. Returns LLVM register number if there is ...
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:42
std::pair< MCAsmParserExtension *, DirectiveHandler > ExtensionDirectiveHandler
Definition: MCAsmParser.h:68
MCAsmParserExtension * createCOFFAsmParser()
unsigned getCharacteristics() const
Definition: MCSectionCOFF.h:70
StringRef getSectionName() const
Definition: MCSectionCOFF.h:63
MCSymbolAttr
Definition: MCDirectives.h:19
R Default(const T &Value) const
Definition: StringSwitch.h:111
SymbolStorageClass
Storage class tells where and what the symbol represents.
Definition: Support/COFF.h:147
void setSelection(int Selection, const MCSectionCOFF *Assoc=0) const
Generic interface for extending the MCAsmParser, which is implemented by target and object file assem...
const MCRegisterInfo & MRI
COFF::SectionCharacteristics Characteristics
Definition: COFFYAML.cpp:196
Represents a location in source code.
Definition: SMLoc.h:23
static SectionKind getReadOnly()
Definition: SectionKind.h:209
static SectionKind getText()
Definition: SectionKind.h:208