Revert "[AMDGPU][CodeGen] Do not backtrace invalid -regalloc param (#119687)"
[llvm-project.git] / llvm / lib / MC / MCParser / COFFAsmParser.cpp
blob4d95a7208528359a5301748cb8824adce40a9052
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 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/StringRef.h"
10 #include "llvm/ADT/StringSwitch.h"
11 #include "llvm/ADT/Twine.h"
12 #include "llvm/BinaryFormat/COFF.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCDirectives.h"
15 #include "llvm/MC/MCParser/MCAsmLexer.h"
16 #include "llvm/MC/MCParser/MCAsmParserExtension.h"
17 #include "llvm/MC/MCSectionCOFF.h"
18 #include "llvm/MC/MCStreamer.h"
19 #include "llvm/Support/SMLoc.h"
20 #include "llvm/TargetParser/Triple.h"
21 #include <cassert>
22 #include <cstdint>
23 #include <limits>
24 #include <utility>
26 using namespace llvm;
28 namespace {
30 class COFFAsmParser : public MCAsmParserExtension {
31 template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
32 void addDirectiveHandler(StringRef Directive) {
33 MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
34 this, HandleDirective<COFFAsmParser, HandlerMethod>);
35 getParser().addDirectiveHandler(Directive, Handler);
38 bool parseSectionSwitch(StringRef Section, unsigned Characteristics);
40 bool parseSectionSwitch(StringRef Section, unsigned Characteristics,
41 StringRef COMDATSymName, COFF::COMDATType Type);
43 bool parseSectionName(StringRef &SectionName);
44 bool parseSectionFlags(StringRef SectionName, StringRef FlagsString,
45 unsigned *Flags);
47 void Initialize(MCAsmParser &Parser) override {
48 // Call the base implementation.
49 MCAsmParserExtension::Initialize(Parser);
51 addDirectiveHandler<&COFFAsmParser::parseSectionDirectiveText>(".text");
52 addDirectiveHandler<&COFFAsmParser::parseSectionDirectiveData>(".data");
53 addDirectiveHandler<&COFFAsmParser::parseSectionDirectiveBSS>(".bss");
54 addDirectiveHandler<&COFFAsmParser::parseDirectiveSection>(".section");
55 addDirectiveHandler<&COFFAsmParser::parseDirectivePushSection>(
56 ".pushsection");
57 addDirectiveHandler<&COFFAsmParser::parseDirectivePopSection>(
58 ".popsection");
59 addDirectiveHandler<&COFFAsmParser::parseDirectiveDef>(".def");
60 addDirectiveHandler<&COFFAsmParser::parseDirectiveScl>(".scl");
61 addDirectiveHandler<&COFFAsmParser::parseDirectiveType>(".type");
62 addDirectiveHandler<&COFFAsmParser::parseDirectiveEndef>(".endef");
63 addDirectiveHandler<&COFFAsmParser::parseDirectiveSecRel32>(".secrel32");
64 addDirectiveHandler<&COFFAsmParser::parseDirectiveSymIdx>(".symidx");
65 addDirectiveHandler<&COFFAsmParser::parseDirectiveSafeSEH>(".safeseh");
66 addDirectiveHandler<&COFFAsmParser::parseDirectiveSecIdx>(".secidx");
67 addDirectiveHandler<&COFFAsmParser::parseDirectiveLinkOnce>(".linkonce");
68 addDirectiveHandler<&COFFAsmParser::parseDirectiveRVA>(".rva");
69 addDirectiveHandler<&COFFAsmParser::parseDirectiveSymbolAttribute>(".weak");
70 addDirectiveHandler<&COFFAsmParser::parseDirectiveSymbolAttribute>(
71 ".weak_anti_dep");
72 addDirectiveHandler<&COFFAsmParser::parseDirectiveCGProfile>(".cg_profile");
74 // Win64 EH directives.
75 addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveStartProc>(
76 ".seh_proc");
77 addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveEndProc>(
78 ".seh_endproc");
79 addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveEndFuncletOrFunc>(
80 ".seh_endfunclet");
81 addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveStartChained>(
82 ".seh_startchained");
83 addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveEndChained>(
84 ".seh_endchained");
85 addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveHandler>(
86 ".seh_handler");
87 addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveHandlerData>(
88 ".seh_handlerdata");
89 addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveAllocStack>(
90 ".seh_stackalloc");
91 addDirectiveHandler<&COFFAsmParser::parseSEHDirectiveEndProlog>(
92 ".seh_endprologue");
95 bool parseSectionDirectiveText(StringRef, SMLoc) {
96 return parseSectionSwitch(".text", COFF::IMAGE_SCN_CNT_CODE |
97 COFF::IMAGE_SCN_MEM_EXECUTE |
98 COFF::IMAGE_SCN_MEM_READ);
101 bool parseSectionDirectiveData(StringRef, SMLoc) {
102 return parseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
103 COFF::IMAGE_SCN_MEM_READ |
104 COFF::IMAGE_SCN_MEM_WRITE);
107 bool parseSectionDirectiveBSS(StringRef, SMLoc) {
108 return parseSectionSwitch(".bss", COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
109 COFF::IMAGE_SCN_MEM_READ |
110 COFF::IMAGE_SCN_MEM_WRITE);
113 bool parseDirectiveSection(StringRef, SMLoc);
114 bool parseSectionArguments(StringRef, SMLoc);
115 bool parseDirectivePushSection(StringRef, SMLoc);
116 bool parseDirectivePopSection(StringRef, SMLoc);
117 bool parseDirectiveDef(StringRef, SMLoc);
118 bool parseDirectiveScl(StringRef, SMLoc);
119 bool parseDirectiveType(StringRef, SMLoc);
120 bool parseDirectiveEndef(StringRef, SMLoc);
121 bool parseDirectiveSecRel32(StringRef, SMLoc);
122 bool parseDirectiveSecIdx(StringRef, SMLoc);
123 bool parseDirectiveSafeSEH(StringRef, SMLoc);
124 bool parseDirectiveSymIdx(StringRef, SMLoc);
125 bool parseCOMDATType(COFF::COMDATType &Type);
126 bool parseDirectiveLinkOnce(StringRef, SMLoc);
127 bool parseDirectiveRVA(StringRef, SMLoc);
128 bool parseDirectiveCGProfile(StringRef, SMLoc);
130 // Win64 EH directives.
131 bool parseSEHDirectiveStartProc(StringRef, SMLoc);
132 bool parseSEHDirectiveEndProc(StringRef, SMLoc);
133 bool parseSEHDirectiveEndFuncletOrFunc(StringRef, SMLoc);
134 bool parseSEHDirectiveStartChained(StringRef, SMLoc);
135 bool parseSEHDirectiveEndChained(StringRef, SMLoc);
136 bool parseSEHDirectiveHandler(StringRef, SMLoc);
137 bool parseSEHDirectiveHandlerData(StringRef, SMLoc);
138 bool parseSEHDirectiveAllocStack(StringRef, SMLoc);
139 bool parseSEHDirectiveEndProlog(StringRef, SMLoc);
141 bool parseAtUnwindOrAtExcept(bool &unwind, bool &except);
142 bool parseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
144 public:
145 COFFAsmParser() = default;
148 } // end anonymous namespace.
150 bool COFFAsmParser::parseSectionFlags(StringRef SectionName,
151 StringRef FlagsString, unsigned *Flags) {
152 enum {
153 None = 0,
154 Alloc = 1 << 0,
155 Code = 1 << 1,
156 Load = 1 << 2,
157 InitData = 1 << 3,
158 Shared = 1 << 4,
159 NoLoad = 1 << 5,
160 NoRead = 1 << 6,
161 NoWrite = 1 << 7,
162 Discardable = 1 << 8,
163 Info = 1 << 9,
166 bool ReadOnlyRemoved = false;
167 unsigned SecFlags = None;
169 for (char FlagChar : FlagsString) {
170 switch (FlagChar) {
171 case 'a':
172 // Ignored.
173 break;
175 case 'b': // bss section
176 SecFlags |= Alloc;
177 if (SecFlags & InitData)
178 return TokError("conflicting section flags 'b' and 'd'.");
179 SecFlags &= ~Load;
180 break;
182 case 'd': // data section
183 SecFlags |= InitData;
184 if (SecFlags & Alloc)
185 return TokError("conflicting section flags 'b' and 'd'.");
186 SecFlags &= ~NoWrite;
187 if ((SecFlags & NoLoad) == 0)
188 SecFlags |= Load;
189 break;
191 case 'n': // section is not loaded
192 SecFlags |= NoLoad;
193 SecFlags &= ~Load;
194 break;
196 case 'D': // discardable
197 SecFlags |= Discardable;
198 break;
200 case 'r': // read-only
201 ReadOnlyRemoved = false;
202 SecFlags |= NoWrite;
203 if ((SecFlags & Code) == 0)
204 SecFlags |= InitData;
205 if ((SecFlags & NoLoad) == 0)
206 SecFlags |= Load;
207 break;
209 case 's': // shared section
210 SecFlags |= Shared | InitData;
211 SecFlags &= ~NoWrite;
212 if ((SecFlags & NoLoad) == 0)
213 SecFlags |= Load;
214 break;
216 case 'w': // writable
217 SecFlags &= ~NoWrite;
218 ReadOnlyRemoved = true;
219 break;
221 case 'x': // executable section
222 SecFlags |= Code;
223 if ((SecFlags & NoLoad) == 0)
224 SecFlags |= Load;
225 if (!ReadOnlyRemoved)
226 SecFlags |= NoWrite;
227 break;
229 case 'y': // not readable
230 SecFlags |= NoRead | NoWrite;
231 break;
233 case 'i': // info
234 SecFlags |= Info;
235 break;
237 default:
238 return TokError("unknown flag");
242 *Flags = 0;
244 if (SecFlags == None)
245 SecFlags = InitData;
247 if (SecFlags & Code)
248 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
249 if (SecFlags & InitData)
250 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
251 if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
252 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
253 if (SecFlags & NoLoad)
254 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
255 if ((SecFlags & Discardable) ||
256 MCSectionCOFF::isImplicitlyDiscardable(SectionName))
257 *Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE;
258 if ((SecFlags & NoRead) == 0)
259 *Flags |= COFF::IMAGE_SCN_MEM_READ;
260 if ((SecFlags & NoWrite) == 0)
261 *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
262 if (SecFlags & Shared)
263 *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
264 if (SecFlags & Info)
265 *Flags |= COFF::IMAGE_SCN_LNK_INFO;
267 return false;
270 /// ParseDirectiveSymbolAttribute
271 /// ::= { ".weak", ... } [ identifier ( , identifier )* ]
272 bool COFFAsmParser::parseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
273 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
274 .Case(".weak", MCSA_Weak)
275 .Case(".weak_anti_dep", MCSA_WeakAntiDep)
276 .Default(MCSA_Invalid);
277 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
278 if (getLexer().isNot(AsmToken::EndOfStatement)) {
279 while (true) {
280 StringRef Name;
282 if (getParser().parseIdentifier(Name))
283 return TokError("expected identifier in directive");
285 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
287 getStreamer().emitSymbolAttribute(Sym, Attr);
289 if (getLexer().is(AsmToken::EndOfStatement))
290 break;
292 if (getLexer().isNot(AsmToken::Comma))
293 return TokError("unexpected token in directive");
294 Lex();
298 Lex();
299 return false;
302 bool COFFAsmParser::parseDirectiveCGProfile(StringRef S, SMLoc Loc) {
303 return MCAsmParserExtension::parseDirectiveCGProfile(S, Loc);
306 bool COFFAsmParser::parseSectionSwitch(StringRef Section,
307 unsigned Characteristics) {
308 return parseSectionSwitch(Section, Characteristics, "", (COFF::COMDATType)0);
311 bool COFFAsmParser::parseSectionSwitch(StringRef Section,
312 unsigned Characteristics,
313 StringRef COMDATSymName,
314 COFF::COMDATType Type) {
315 if (getLexer().isNot(AsmToken::EndOfStatement))
316 return TokError("unexpected token in section switching directive");
317 Lex();
319 getStreamer().switchSection(getContext().getCOFFSection(
320 Section, Characteristics, COMDATSymName, Type));
322 return false;
325 bool COFFAsmParser::parseSectionName(StringRef &SectionName) {
326 if (!getLexer().is(AsmToken::Identifier) && !getLexer().is(AsmToken::String))
327 return true;
329 SectionName = getTok().getIdentifier();
330 Lex();
331 return false;
334 bool COFFAsmParser::parseDirectiveSection(StringRef directive, SMLoc loc) {
335 return parseSectionArguments(directive, loc);
338 // .section name [, "flags"] [, identifier [ identifier ], identifier]
339 // .pushsection <same as above>
341 // Supported flags:
342 // a: Ignored.
343 // b: BSS section (uninitialized data)
344 // d: data section (initialized data)
345 // n: "noload" section (removed by linker)
346 // D: Discardable section
347 // r: Readable section
348 // s: Shared section
349 // w: Writable section
350 // x: Executable section
351 // y: Not-readable section (clears 'r')
353 // Subsections are not supported.
354 bool COFFAsmParser::parseSectionArguments(StringRef, SMLoc) {
355 StringRef SectionName;
357 if (parseSectionName(SectionName))
358 return TokError("expected identifier in directive");
360 unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
361 COFF::IMAGE_SCN_MEM_READ |
362 COFF::IMAGE_SCN_MEM_WRITE;
364 if (getLexer().is(AsmToken::Comma)) {
365 Lex();
367 if (getLexer().isNot(AsmToken::String))
368 return TokError("expected string in directive");
370 StringRef FlagsStr = getTok().getStringContents();
371 Lex();
373 if (parseSectionFlags(SectionName, FlagsStr, &Flags))
374 return true;
377 COFF::COMDATType Type = (COFF::COMDATType)0;
378 StringRef COMDATSymName;
379 if (getLexer().is(AsmToken::Comma)) {
380 Type = COFF::IMAGE_COMDAT_SELECT_ANY;
381 Lex();
383 Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
385 if (!getLexer().is(AsmToken::Identifier))
386 return TokError("expected comdat type such as 'discard' or 'largest' "
387 "after protection bits");
389 if (parseCOMDATType(Type))
390 return true;
392 if (getLexer().isNot(AsmToken::Comma))
393 return TokError("expected comma in directive");
394 Lex();
396 if (getParser().parseIdentifier(COMDATSymName))
397 return TokError("expected identifier in directive");
400 if (getLexer().isNot(AsmToken::EndOfStatement))
401 return TokError("unexpected token in directive");
403 if (Flags & COFF::IMAGE_SCN_CNT_CODE) {
404 const Triple &T = getContext().getTargetTriple();
405 if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
406 Flags |= COFF::IMAGE_SCN_MEM_16BIT;
408 parseSectionSwitch(SectionName, Flags, COMDATSymName, Type);
409 return false;
412 bool COFFAsmParser::parseDirectivePushSection(StringRef directive, SMLoc loc) {
413 getStreamer().pushSection();
415 if (parseSectionArguments(directive, loc)) {
416 getStreamer().popSection();
417 return true;
420 return false;
423 bool COFFAsmParser::parseDirectivePopSection(StringRef, SMLoc) {
424 if (!getStreamer().popSection())
425 return TokError(".popsection without corresponding .pushsection");
426 return false;
429 bool COFFAsmParser::parseDirectiveDef(StringRef, SMLoc) {
430 StringRef SymbolName;
432 if (getParser().parseIdentifier(SymbolName))
433 return TokError("expected identifier in directive");
435 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
437 getStreamer().beginCOFFSymbolDef(Sym);
439 Lex();
440 return false;
443 bool COFFAsmParser::parseDirectiveScl(StringRef, SMLoc) {
444 int64_t SymbolStorageClass;
445 if (getParser().parseAbsoluteExpression(SymbolStorageClass))
446 return true;
448 if (getLexer().isNot(AsmToken::EndOfStatement))
449 return TokError("unexpected token in directive");
451 Lex();
452 getStreamer().emitCOFFSymbolStorageClass(SymbolStorageClass);
453 return false;
456 bool COFFAsmParser::parseDirectiveType(StringRef, SMLoc) {
457 int64_t Type;
458 if (getParser().parseAbsoluteExpression(Type))
459 return true;
461 if (getLexer().isNot(AsmToken::EndOfStatement))
462 return TokError("unexpected token in directive");
464 Lex();
465 getStreamer().emitCOFFSymbolType(Type);
466 return false;
469 bool COFFAsmParser::parseDirectiveEndef(StringRef, SMLoc) {
470 Lex();
471 getStreamer().endCOFFSymbolDef();
472 return false;
475 bool COFFAsmParser::parseDirectiveSecRel32(StringRef, SMLoc) {
476 StringRef SymbolID;
477 if (getParser().parseIdentifier(SymbolID))
478 return TokError("expected identifier in directive");
480 int64_t Offset = 0;
481 SMLoc OffsetLoc;
482 if (getLexer().is(AsmToken::Plus)) {
483 OffsetLoc = getLexer().getLoc();
484 if (getParser().parseAbsoluteExpression(Offset))
485 return true;
488 if (getLexer().isNot(AsmToken::EndOfStatement))
489 return TokError("unexpected token in directive");
491 if (Offset < 0 || Offset > std::numeric_limits<uint32_t>::max())
492 return Error(
493 OffsetLoc,
494 "invalid '.secrel32' directive offset, can't be less "
495 "than zero or greater than std::numeric_limits<uint32_t>::max()");
497 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
499 Lex();
500 getStreamer().emitCOFFSecRel32(Symbol, Offset);
501 return false;
504 bool COFFAsmParser::parseDirectiveRVA(StringRef, SMLoc) {
505 auto parseOp = [&]() -> bool {
506 StringRef SymbolID;
507 if (getParser().parseIdentifier(SymbolID))
508 return TokError("expected identifier in directive");
510 int64_t Offset = 0;
511 SMLoc OffsetLoc;
512 if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) {
513 OffsetLoc = getLexer().getLoc();
514 if (getParser().parseAbsoluteExpression(Offset))
515 return true;
518 if (Offset < std::numeric_limits<int32_t>::min() ||
519 Offset > std::numeric_limits<int32_t>::max())
520 return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less "
521 "than -2147483648 or greater than "
522 "2147483647");
524 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
526 getStreamer().emitCOFFImgRel32(Symbol, Offset);
527 return false;
530 if (getParser().parseMany(parseOp))
531 return addErrorSuffix(" in directive");
532 return false;
535 bool COFFAsmParser::parseDirectiveSafeSEH(StringRef, SMLoc) {
536 StringRef SymbolID;
537 if (getParser().parseIdentifier(SymbolID))
538 return TokError("expected identifier in directive");
540 if (getLexer().isNot(AsmToken::EndOfStatement))
541 return TokError("unexpected token in directive");
543 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
545 Lex();
546 getStreamer().emitCOFFSafeSEH(Symbol);
547 return false;
550 bool COFFAsmParser::parseDirectiveSecIdx(StringRef, SMLoc) {
551 StringRef SymbolID;
552 if (getParser().parseIdentifier(SymbolID))
553 return TokError("expected identifier in directive");
555 if (getLexer().isNot(AsmToken::EndOfStatement))
556 return TokError("unexpected token in directive");
558 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
560 Lex();
561 getStreamer().emitCOFFSectionIndex(Symbol);
562 return false;
565 bool COFFAsmParser::parseDirectiveSymIdx(StringRef, SMLoc) {
566 StringRef SymbolID;
567 if (getParser().parseIdentifier(SymbolID))
568 return TokError("expected identifier in directive");
570 if (getLexer().isNot(AsmToken::EndOfStatement))
571 return TokError("unexpected token in directive");
573 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
575 Lex();
576 getStreamer().emitCOFFSymbolIndex(Symbol);
577 return false;
580 /// ::= [ identifier ]
581 bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
582 StringRef TypeId = getTok().getIdentifier();
584 Type = StringSwitch<COFF::COMDATType>(TypeId)
585 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
586 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
587 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
588 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
589 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
590 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
591 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
592 .Default((COFF::COMDATType)0);
594 if (Type == 0)
595 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
597 Lex();
599 return false;
602 /// ParseDirectiveLinkOnce
603 /// ::= .linkonce [ identifier ]
604 bool COFFAsmParser::parseDirectiveLinkOnce(StringRef, SMLoc Loc) {
605 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
606 if (getLexer().is(AsmToken::Identifier))
607 if (parseCOMDATType(Type))
608 return true;
610 const MCSectionCOFF *Current =
611 static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly());
613 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
614 return Error(Loc, "cannot make section associative with .linkonce");
616 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
617 return Error(Loc, Twine("section '") + Current->getName() +
618 "' is already linkonce");
620 Current->setSelection(Type);
622 if (getLexer().isNot(AsmToken::EndOfStatement))
623 return TokError("unexpected token in directive");
625 return false;
628 bool COFFAsmParser::parseSEHDirectiveStartProc(StringRef, SMLoc Loc) {
629 StringRef SymbolID;
630 if (getParser().parseIdentifier(SymbolID))
631 return true;
633 if (getLexer().isNot(AsmToken::EndOfStatement))
634 return TokError("unexpected token in directive");
636 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
638 Lex();
639 getStreamer().emitWinCFIStartProc(Symbol, Loc);
640 return false;
643 bool COFFAsmParser::parseSEHDirectiveEndProc(StringRef, SMLoc Loc) {
644 Lex();
645 getStreamer().emitWinCFIEndProc(Loc);
646 return false;
649 bool COFFAsmParser::parseSEHDirectiveEndFuncletOrFunc(StringRef, SMLoc Loc) {
650 Lex();
651 getStreamer().emitWinCFIFuncletOrFuncEnd(Loc);
652 return false;
655 bool COFFAsmParser::parseSEHDirectiveStartChained(StringRef, SMLoc Loc) {
656 Lex();
657 getStreamer().emitWinCFIStartChained(Loc);
658 return false;
661 bool COFFAsmParser::parseSEHDirectiveEndChained(StringRef, SMLoc Loc) {
662 Lex();
663 getStreamer().emitWinCFIEndChained(Loc);
664 return false;
667 bool COFFAsmParser::parseSEHDirectiveHandler(StringRef, SMLoc Loc) {
668 StringRef SymbolID;
669 if (getParser().parseIdentifier(SymbolID))
670 return true;
672 if (getLexer().isNot(AsmToken::Comma))
673 return TokError("you must specify one or both of @unwind or @except");
674 Lex();
675 bool unwind = false, except = false;
676 if (parseAtUnwindOrAtExcept(unwind, except))
677 return true;
678 if (getLexer().is(AsmToken::Comma)) {
679 Lex();
680 if (parseAtUnwindOrAtExcept(unwind, except))
681 return true;
683 if (getLexer().isNot(AsmToken::EndOfStatement))
684 return TokError("unexpected token in directive");
686 MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
688 Lex();
689 getStreamer().emitWinEHHandler(handler, unwind, except, Loc);
690 return false;
693 bool COFFAsmParser::parseSEHDirectiveHandlerData(StringRef, SMLoc Loc) {
694 Lex();
695 getStreamer().emitWinEHHandlerData();
696 return false;
699 bool COFFAsmParser::parseSEHDirectiveAllocStack(StringRef, SMLoc Loc) {
700 int64_t Size;
701 if (getParser().parseAbsoluteExpression(Size))
702 return true;
704 if (getLexer().isNot(AsmToken::EndOfStatement))
705 return TokError("unexpected token in directive");
707 Lex();
708 getStreamer().emitWinCFIAllocStack(Size, Loc);
709 return false;
712 bool COFFAsmParser::parseSEHDirectiveEndProlog(StringRef, SMLoc Loc) {
713 Lex();
714 getStreamer().emitWinCFIEndProlog(Loc);
715 return false;
718 bool COFFAsmParser::parseAtUnwindOrAtExcept(bool &unwind, bool &except) {
719 StringRef identifier;
720 if (getLexer().isNot(AsmToken::At) && getLexer().isNot(AsmToken::Percent))
721 return TokError("a handler attribute must begin with '@' or '%'");
722 SMLoc startLoc = getLexer().getLoc();
723 Lex();
724 if (getParser().parseIdentifier(identifier))
725 return Error(startLoc, "expected @unwind or @except");
726 if (identifier == "unwind")
727 unwind = true;
728 else if (identifier == "except")
729 except = true;
730 else
731 return Error(startLoc, "expected @unwind or @except");
732 return false;
735 namespace llvm {
737 MCAsmParserExtension *createCOFFAsmParser() {
738 return new COFFAsmParser;
741 } // end namespace llvm