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