LLVM  8.0.1
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 
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"
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,
46 
47  bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
48  SectionKind Kind, StringRef COMDATSymName,
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.
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",
110  }
111 
112  bool ParseSectionDirectiveData(StringRef, SMLoc) {
113  return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
117  }
118 
119  bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
120  return ParseSectionSwitch(".bss",
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)
268  if (SecFlags & InitData)
270  if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
272  if (SecFlags & NoLoad)
273  *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
274  if ((SecFlags & 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)
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,
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) {
365 
366  if (ParseSectionName(SectionName))
367  return TokError("expected identifier in directive");
368 
369  unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
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 
387  StringRef COMDATSymName;
388  if (getLexer().is(AsmToken::Comma)) {
390  Lex();
391 
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) {
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() ||
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)
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) {
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 
607  return Error(Loc, "cannot make section associative with .linkonce");
608 
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 
863  return new COFFAsmParser;
864 }
865 
866 } // end namespace llvm
static SectionKind getData()
Definition: SectionKind.h:202
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
This class represents lattice values for constants.
Definition: AllocatorList.h:24
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
Not a valid directive.
Definition: MCDirectives.h:20
Generic assembler parser interface, for use by target specific assembly parsers.
Definition: MCAsmParser.h:110
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
unsigned Reg
void setSelection(int Selection) const
static SectionKind computeSectionKind(unsigned Flags)
This represents a section on Windows.
Definition: MCSectionCOFF.h:27
amdgpu Simplify well known AMD library false Value Value const Twine & Name
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
static SectionKind getBSS()
Definition: SectionKind.h:198
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE R Default(T Value)
Definition: StringSwitch.h:203
bool isText() const
Definition: SectionKind.h:119
ArchType getArch() const
getArch - Get the parsed architecture type of this triple.
Definition: Triple.h:290
unsigned getCharacteristics() const
Definition: MCSectionCOFF.h:73
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:43
unsigned const MachineRegisterInfo * MRI
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
SectionKind - This is a simple POD value that classifies the properties of a section.
Definition: SectionKind.h:23
MCAsmParserExtension * createCOFFAsmParser()
StringRef getSectionName() const
Definition: MCSectionCOFF.h:72
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
MCSymbolAttr
Definition: MCDirectives.h:19
SymbolStorageClass
Storage class tells where and what the symbol represents.
Definition: COFF.h:204
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:70
COFFYAML::WeakExternalCharacteristics Characteristics
Definition: COFFYAML.cpp:323
COMDATType
Definition: COFF.h:403
uint32_t Size
Definition: Profile.cpp:47
const unsigned Kind
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
int getSEHRegNum(unsigned RegNum) const
Map a target register to an equivalent SEH register number.
static bool isImplicitlyDiscardable(StringRef Name)
Definition: MCSectionCOFF.h:91
Generic interface for extending the MCAsmParser, which is implemented by target and object file assem...
std::pair< MCAsmParserExtension *, DirectiveHandler > ExtensionDirectiveHandler
Definition: MCAsmParser.h:114
const char SectionName[]
Definition: AMDGPUPTNote.h:24
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
Represents a location in source code.
Definition: SMLoc.h:24
static SectionKind getReadOnly()
Definition: SectionKind.h:182
static SectionKind getText()
Definition: SectionKind.h:180