[InstCombine] Signed saturation patterns
[llvm-complete.git] / lib / MC / MCParser / COFFAsmParser.cpp
blob06f8310ae061563a6dcec3e869a4288742cd04ff
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/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"
16 #include "llvm/MC/MCObjectFileInfo.h"
17 #include "llvm/MC/MCParser/MCAsmLexer.h"
18 #include "llvm/MC/MCParser/MCAsmParserExtension.h"
19 #include "llvm/MC/MCParser/MCTargetAsmParser.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>
30 using namespace llvm;
32 namespace {
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);
42 bool ParseSectionSwitch(StringRef Section,
43 unsigned Characteristics,
44 SectionKind Kind);
46 bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
47 SectionKind Kind, StringRef COMDATSymName,
48 COFF::COMDATType Type);
50 bool ParseSectionName(StringRef &SectionName);
51 bool ParseSectionFlags(StringRef SectionName, StringRef FlagsString,
52 unsigned *Flags);
54 void Initialize(MCAsmParser &Parser) override {
55 // Call the base implementation.
56 MCAsmParserExtension::Initialize(Parser);
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 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
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::ParseSEHDirectiveAllocStack>(
88 ".seh_stackalloc");
89 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
90 ".seh_endprologue");
93 bool ParseSectionDirectiveText(StringRef, SMLoc) {
94 return ParseSectionSwitch(".text",
95 COFF::IMAGE_SCN_CNT_CODE
96 | COFF::IMAGE_SCN_MEM_EXECUTE
97 | COFF::IMAGE_SCN_MEM_READ,
98 SectionKind::getText());
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,
105 SectionKind::getData());
108 bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
109 return ParseSectionSwitch(".bss",
110 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
111 | COFF::IMAGE_SCN_MEM_READ
112 | COFF::IMAGE_SCN_MEM_WRITE,
113 SectionKind::getBSS());
116 bool ParseDirectiveSection(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);
129 // Win64 EH directives.
130 bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
131 bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
132 bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
133 bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
134 bool ParseSEHDirectiveHandler(StringRef, SMLoc);
135 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
136 bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
137 bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
139 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
140 bool ParseSEHRegisterNumber(unsigned &RegNo);
141 bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
143 public:
144 COFFAsmParser() = default;
147 } // end annonomous namespace.
149 static SectionKind computeSectionKind(unsigned Flags) {
150 if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
151 return SectionKind::getText();
152 if (Flags & COFF::IMAGE_SCN_MEM_READ &&
153 (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
154 return SectionKind::getReadOnly();
155 return SectionKind::getData();
158 bool COFFAsmParser::ParseSectionFlags(StringRef SectionName,
159 StringRef FlagsString, unsigned *Flags) {
160 enum {
161 None = 0,
162 Alloc = 1 << 0,
163 Code = 1 << 1,
164 Load = 1 << 2,
165 InitData = 1 << 3,
166 Shared = 1 << 4,
167 NoLoad = 1 << 5,
168 NoRead = 1 << 6,
169 NoWrite = 1 << 7,
170 Discardable = 1 << 8,
173 bool ReadOnlyRemoved = false;
174 unsigned SecFlags = None;
176 for (char FlagChar : FlagsString) {
177 switch (FlagChar) {
178 case 'a':
179 // Ignored.
180 break;
182 case 'b': // bss section
183 SecFlags |= Alloc;
184 if (SecFlags & InitData)
185 return TokError("conflicting section flags 'b' and 'd'.");
186 SecFlags &= ~Load;
187 break;
189 case 'd': // data section
190 SecFlags |= InitData;
191 if (SecFlags & Alloc)
192 return TokError("conflicting section flags 'b' and 'd'.");
193 SecFlags &= ~NoWrite;
194 if ((SecFlags & NoLoad) == 0)
195 SecFlags |= Load;
196 break;
198 case 'n': // section is not loaded
199 SecFlags |= NoLoad;
200 SecFlags &= ~Load;
201 break;
203 case 'D': // discardable
204 SecFlags |= Discardable;
205 break;
207 case 'r': // read-only
208 ReadOnlyRemoved = false;
209 SecFlags |= NoWrite;
210 if ((SecFlags & Code) == 0)
211 SecFlags |= InitData;
212 if ((SecFlags & NoLoad) == 0)
213 SecFlags |= Load;
214 break;
216 case 's': // shared section
217 SecFlags |= Shared | InitData;
218 SecFlags &= ~NoWrite;
219 if ((SecFlags & NoLoad) == 0)
220 SecFlags |= Load;
221 break;
223 case 'w': // writable
224 SecFlags &= ~NoWrite;
225 ReadOnlyRemoved = true;
226 break;
228 case 'x': // executable section
229 SecFlags |= Code;
230 if ((SecFlags & NoLoad) == 0)
231 SecFlags |= Load;
232 if (!ReadOnlyRemoved)
233 SecFlags |= NoWrite;
234 break;
236 case 'y': // not readable
237 SecFlags |= NoRead | NoWrite;
238 break;
240 default:
241 return TokError("unknown flag");
245 *Flags = 0;
247 if (SecFlags == None)
248 SecFlags = InitData;
250 if (SecFlags & Code)
251 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
252 if (SecFlags & InitData)
253 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
254 if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
255 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
256 if (SecFlags & NoLoad)
257 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
258 if ((SecFlags & Discardable) ||
259 MCSectionCOFF::isImplicitlyDiscardable(SectionName))
260 *Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE;
261 if ((SecFlags & NoRead) == 0)
262 *Flags |= COFF::IMAGE_SCN_MEM_READ;
263 if ((SecFlags & NoWrite) == 0)
264 *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
265 if (SecFlags & Shared)
266 *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
268 return false;
271 /// ParseDirectiveSymbolAttribute
272 /// ::= { ".weak", ... } [ identifier ( , identifier )* ]
273 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
274 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
275 .Case(".weak", MCSA_Weak)
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::ParseSectionSwitch(StringRef Section,
303 unsigned Characteristics,
304 SectionKind Kind) {
305 return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
308 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
309 unsigned Characteristics,
310 SectionKind Kind,
311 StringRef COMDATSymName,
312 COFF::COMDATType Type) {
313 if (getLexer().isNot(AsmToken::EndOfStatement))
314 return TokError("unexpected token in section switching directive");
315 Lex();
317 getStreamer().SwitchSection(getContext().getCOFFSection(
318 Section, Characteristics, Kind, COMDATSymName, Type));
320 return false;
323 bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
324 if (!getLexer().is(AsmToken::Identifier))
325 return true;
327 SectionName = getTok().getIdentifier();
328 Lex();
329 return false;
332 // .section name [, "flags"] [, identifier [ identifier ], identifier]
334 // Supported flags:
335 // a: Ignored.
336 // b: BSS section (uninitialized data)
337 // d: data section (initialized data)
338 // n: "noload" section (removed by linker)
339 // D: Discardable section
340 // r: Readable section
341 // s: Shared section
342 // w: Writable section
343 // x: Executable section
344 // y: Not-readable section (clears 'r')
346 // Subsections are not supported.
347 bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
348 StringRef SectionName;
350 if (ParseSectionName(SectionName))
351 return TokError("expected identifier in directive");
353 unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
354 COFF::IMAGE_SCN_MEM_READ |
355 COFF::IMAGE_SCN_MEM_WRITE;
357 if (getLexer().is(AsmToken::Comma)) {
358 Lex();
360 if (getLexer().isNot(AsmToken::String))
361 return TokError("expected string in directive");
363 StringRef FlagsStr = getTok().getStringContents();
364 Lex();
366 if (ParseSectionFlags(SectionName, FlagsStr, &Flags))
367 return true;
370 COFF::COMDATType Type = (COFF::COMDATType)0;
371 StringRef COMDATSymName;
372 if (getLexer().is(AsmToken::Comma)) {
373 Type = COFF::IMAGE_COMDAT_SELECT_ANY;
374 Lex();
376 Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
378 if (!getLexer().is(AsmToken::Identifier))
379 return TokError("expected comdat type such as 'discard' or 'largest' "
380 "after protection bits");
382 if (parseCOMDATType(Type))
383 return true;
385 if (getLexer().isNot(AsmToken::Comma))
386 return TokError("expected comma in directive");
387 Lex();
389 if (getParser().parseIdentifier(COMDATSymName))
390 return TokError("expected identifier in directive");
393 if (getLexer().isNot(AsmToken::EndOfStatement))
394 return TokError("unexpected token in directive");
396 SectionKind Kind = computeSectionKind(Flags);
397 if (Kind.isText()) {
398 const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
399 if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
400 Flags |= COFF::IMAGE_SCN_MEM_16BIT;
402 ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
403 return false;
406 bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
407 StringRef SymbolName;
409 if (getParser().parseIdentifier(SymbolName))
410 return TokError("expected identifier in directive");
412 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
414 getStreamer().BeginCOFFSymbolDef(Sym);
416 Lex();
417 return false;
420 bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
421 int64_t SymbolStorageClass;
422 if (getParser().parseAbsoluteExpression(SymbolStorageClass))
423 return true;
425 if (getLexer().isNot(AsmToken::EndOfStatement))
426 return TokError("unexpected token in directive");
428 Lex();
429 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
430 return false;
433 bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
434 int64_t Type;
435 if (getParser().parseAbsoluteExpression(Type))
436 return true;
438 if (getLexer().isNot(AsmToken::EndOfStatement))
439 return TokError("unexpected token in directive");
441 Lex();
442 getStreamer().EmitCOFFSymbolType(Type);
443 return false;
446 bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
447 Lex();
448 getStreamer().EndCOFFSymbolDef();
449 return false;
452 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
453 StringRef SymbolID;
454 if (getParser().parseIdentifier(SymbolID))
455 return TokError("expected identifier in directive");
457 int64_t Offset = 0;
458 SMLoc OffsetLoc;
459 if (getLexer().is(AsmToken::Plus)) {
460 OffsetLoc = getLexer().getLoc();
461 if (getParser().parseAbsoluteExpression(Offset))
462 return true;
465 if (getLexer().isNot(AsmToken::EndOfStatement))
466 return TokError("unexpected token in directive");
468 if (Offset < 0 || Offset > std::numeric_limits<uint32_t>::max())
469 return Error(
470 OffsetLoc,
471 "invalid '.secrel32' directive offset, can't be less "
472 "than zero or greater than std::numeric_limits<uint32_t>::max()");
474 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
476 Lex();
477 getStreamer().EmitCOFFSecRel32(Symbol, Offset);
478 return false;
481 bool COFFAsmParser::ParseDirectiveRVA(StringRef, SMLoc) {
482 auto parseOp = [&]() -> bool {
483 StringRef SymbolID;
484 if (getParser().parseIdentifier(SymbolID))
485 return TokError("expected identifier in directive");
487 int64_t Offset = 0;
488 SMLoc OffsetLoc;
489 if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) {
490 OffsetLoc = getLexer().getLoc();
491 if (getParser().parseAbsoluteExpression(Offset))
492 return true;
495 if (Offset < std::numeric_limits<int32_t>::min() ||
496 Offset > std::numeric_limits<int32_t>::max())
497 return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less "
498 "than -2147483648 or greater than "
499 "2147483647");
501 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
503 getStreamer().EmitCOFFImgRel32(Symbol, Offset);
504 return false;
507 if (getParser().parseMany(parseOp))
508 return addErrorSuffix(" in directive");
509 return false;
512 bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
513 StringRef SymbolID;
514 if (getParser().parseIdentifier(SymbolID))
515 return TokError("expected identifier in directive");
517 if (getLexer().isNot(AsmToken::EndOfStatement))
518 return TokError("unexpected token in directive");
520 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
522 Lex();
523 getStreamer().EmitCOFFSafeSEH(Symbol);
524 return false;
527 bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
528 StringRef SymbolID;
529 if (getParser().parseIdentifier(SymbolID))
530 return TokError("expected identifier in directive");
532 if (getLexer().isNot(AsmToken::EndOfStatement))
533 return TokError("unexpected token in directive");
535 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
537 Lex();
538 getStreamer().EmitCOFFSectionIndex(Symbol);
539 return false;
542 bool COFFAsmParser::ParseDirectiveSymIdx(StringRef, SMLoc) {
543 StringRef SymbolID;
544 if (getParser().parseIdentifier(SymbolID))
545 return TokError("expected identifier in directive");
547 if (getLexer().isNot(AsmToken::EndOfStatement))
548 return TokError("unexpected token in directive");
550 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
552 Lex();
553 getStreamer().EmitCOFFSymbolIndex(Symbol);
554 return false;
557 /// ::= [ identifier ]
558 bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
559 StringRef TypeId = getTok().getIdentifier();
561 Type = StringSwitch<COFF::COMDATType>(TypeId)
562 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
563 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
564 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
565 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
566 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
567 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
568 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
569 .Default((COFF::COMDATType)0);
571 if (Type == 0)
572 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
574 Lex();
576 return false;
579 /// ParseDirectiveLinkOnce
580 /// ::= .linkonce [ identifier ]
581 bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
582 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
583 if (getLexer().is(AsmToken::Identifier))
584 if (parseCOMDATType(Type))
585 return true;
587 const MCSectionCOFF *Current =
588 static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly());
590 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
591 return Error(Loc, "cannot make section associative with .linkonce");
593 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
594 return Error(Loc, Twine("section '") + Current->getSectionName() +
595 "' is already linkonce");
597 Current->setSelection(Type);
599 if (getLexer().isNot(AsmToken::EndOfStatement))
600 return TokError("unexpected token in directive");
602 return false;
605 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc Loc) {
606 StringRef SymbolID;
607 if (getParser().parseIdentifier(SymbolID))
608 return true;
610 if (getLexer().isNot(AsmToken::EndOfStatement))
611 return TokError("unexpected token in directive");
613 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
615 Lex();
616 getStreamer().EmitWinCFIStartProc(Symbol, Loc);
617 return false;
620 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc Loc) {
621 Lex();
622 getStreamer().EmitWinCFIEndProc(Loc);
623 return false;
626 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc Loc) {
627 Lex();
628 getStreamer().EmitWinCFIStartChained(Loc);
629 return false;
632 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc Loc) {
633 Lex();
634 getStreamer().EmitWinCFIEndChained(Loc);
635 return false;
638 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc Loc) {
639 StringRef SymbolID;
640 if (getParser().parseIdentifier(SymbolID))
641 return true;
643 if (getLexer().isNot(AsmToken::Comma))
644 return TokError("you must specify one or both of @unwind or @except");
645 Lex();
646 bool unwind = false, except = false;
647 if (ParseAtUnwindOrAtExcept(unwind, except))
648 return true;
649 if (getLexer().is(AsmToken::Comma)) {
650 Lex();
651 if (ParseAtUnwindOrAtExcept(unwind, except))
652 return true;
654 if (getLexer().isNot(AsmToken::EndOfStatement))
655 return TokError("unexpected token in directive");
657 MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
659 Lex();
660 getStreamer().EmitWinEHHandler(handler, unwind, except, Loc);
661 return false;
664 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) {
665 Lex();
666 getStreamer().EmitWinEHHandlerData();
667 return false;
670 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) {
671 int64_t Size;
672 if (getParser().parseAbsoluteExpression(Size))
673 return true;
675 if (getLexer().isNot(AsmToken::EndOfStatement))
676 return TokError("unexpected token in directive");
678 Lex();
679 getStreamer().EmitWinCFIAllocStack(Size, Loc);
680 return false;
683 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) {
684 Lex();
685 getStreamer().EmitWinCFIEndProlog(Loc);
686 return false;
689 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
690 StringRef identifier;
691 if (getLexer().isNot(AsmToken::At))
692 return TokError("a handler attribute must begin with '@'");
693 SMLoc startLoc = getLexer().getLoc();
694 Lex();
695 if (getParser().parseIdentifier(identifier))
696 return Error(startLoc, "expected @unwind or @except");
697 if (identifier == "unwind")
698 unwind = true;
699 else if (identifier == "except")
700 except = true;
701 else
702 return Error(startLoc, "expected @unwind or @except");
703 return false;
706 namespace llvm {
708 MCAsmParserExtension *createCOFFAsmParser() {
709 return new COFFAsmParser;
712 } // end namespace llvm