[AArch64] Default to SEH exception handling on MinGW
[llvm-complete.git] / lib / MC / MCParser / COFFAsmParser.cpp
blob1217ea99e4656e38f0dad1a10e49b181be3af48b
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");
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");
103 bool ParseSectionDirectiveText(StringRef, SMLoc) {
104 return ParseSectionSwitch(".text",
105 COFF::IMAGE_SCN_CNT_CODE
106 | COFF::IMAGE_SCN_MEM_EXECUTE
107 | COFF::IMAGE_SCN_MEM_READ,
108 SectionKind::getText());
111 bool ParseSectionDirectiveData(StringRef, SMLoc) {
112 return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
113 COFF::IMAGE_SCN_MEM_READ |
114 COFF::IMAGE_SCN_MEM_WRITE,
115 SectionKind::getData());
118 bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
119 return ParseSectionSwitch(".bss",
120 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
121 | COFF::IMAGE_SCN_MEM_READ
122 | COFF::IMAGE_SCN_MEM_WRITE,
123 SectionKind::getBSS());
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);
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);
154 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
155 bool ParseSEHRegisterNumber(unsigned &RegNo);
156 bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
158 public:
159 COFFAsmParser() = default;
162 } // end annonomous namespace.
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();
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,
188 bool ReadOnlyRemoved = false;
189 unsigned SecFlags = None;
191 for (char FlagChar : FlagsString) {
192 switch (FlagChar) {
193 case 'a':
194 // Ignored.
195 break;
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;
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;
213 case 'n': // section is not loaded
214 SecFlags |= NoLoad;
215 SecFlags &= ~Load;
216 break;
218 case 'D': // discardable
219 SecFlags |= Discardable;
220 break;
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;
231 case 's': // shared section
232 SecFlags |= Shared | InitData;
233 SecFlags &= ~NoWrite;
234 if ((SecFlags & NoLoad) == 0)
235 SecFlags |= Load;
236 break;
238 case 'w': // writable
239 SecFlags &= ~NoWrite;
240 ReadOnlyRemoved = true;
241 break;
243 case 'x': // executable section
244 SecFlags |= Code;
245 if ((SecFlags & NoLoad) == 0)
246 SecFlags |= Load;
247 if (!ReadOnlyRemoved)
248 SecFlags |= NoWrite;
249 break;
251 case 'y': // not readable
252 SecFlags |= NoRead | NoWrite;
253 break;
255 default:
256 return TokError("unknown flag");
260 *Flags = 0;
262 if (SecFlags == None)
263 SecFlags = InitData;
265 if (SecFlags & Code)
266 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
267 if (SecFlags & InitData)
268 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
269 if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
270 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
271 if (SecFlags & NoLoad)
272 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
273 if ((SecFlags & Discardable) ||
274 MCSectionCOFF::isImplicitlyDiscardable(SectionName))
275 *Flags |= COFF::IMAGE_SCN_MEM_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;
283 return false;
286 /// ParseDirectiveSymbolAttribute
287 /// ::= { ".weak", ... } [ identifier ( , identifier )* ]
288 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
289 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
290 .Case(".weak", MCSA_Weak)
291 .Default(MCSA_Invalid);
292 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
293 if (getLexer().isNot(AsmToken::EndOfStatement)) {
294 while (true) {
295 StringRef Name;
297 if (getParser().parseIdentifier(Name))
298 return TokError("expected identifier in directive");
300 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
302 getStreamer().EmitSymbolAttribute(Sym, Attr);
304 if (getLexer().is(AsmToken::EndOfStatement))
305 break;
307 if (getLexer().isNot(AsmToken::Comma))
308 return TokError("unexpected token in directive");
309 Lex();
313 Lex();
314 return false;
317 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
318 unsigned Characteristics,
319 SectionKind Kind) {
320 return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
323 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
324 unsigned Characteristics,
325 SectionKind Kind,
326 StringRef COMDATSymName,
327 COFF::COMDATType Type) {
328 if (getLexer().isNot(AsmToken::EndOfStatement))
329 return TokError("unexpected token in section switching directive");
330 Lex();
332 getStreamer().SwitchSection(getContext().getCOFFSection(
333 Section, Characteristics, Kind, COMDATSymName, Type));
335 return false;
338 bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
339 if (!getLexer().is(AsmToken::Identifier))
340 return true;
342 SectionName = getTok().getIdentifier();
343 Lex();
344 return false;
347 // .section name [, "flags"] [, identifier [ identifier ], identifier]
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')
361 // Subsections are not supported.
362 bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
363 StringRef SectionName;
365 if (ParseSectionName(SectionName))
366 return TokError("expected identifier in directive");
368 unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
369 COFF::IMAGE_SCN_MEM_READ |
370 COFF::IMAGE_SCN_MEM_WRITE;
372 if (getLexer().is(AsmToken::Comma)) {
373 Lex();
375 if (getLexer().isNot(AsmToken::String))
376 return TokError("expected string in directive");
378 StringRef FlagsStr = getTok().getStringContents();
379 Lex();
381 if (ParseSectionFlags(SectionName, FlagsStr, &Flags))
382 return true;
385 COFF::COMDATType Type = (COFF::COMDATType)0;
386 StringRef COMDATSymName;
387 if (getLexer().is(AsmToken::Comma)) {
388 Type = COFF::IMAGE_COMDAT_SELECT_ANY;
389 Lex();
391 Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
393 if (!getLexer().is(AsmToken::Identifier))
394 return TokError("expected comdat type such as 'discard' or 'largest' "
395 "after protection bits");
397 if (parseCOMDATType(Type))
398 return true;
400 if (getLexer().isNot(AsmToken::Comma))
401 return TokError("expected comma in directive");
402 Lex();
404 if (getParser().parseIdentifier(COMDATSymName))
405 return TokError("expected identifier in directive");
408 if (getLexer().isNot(AsmToken::EndOfStatement))
409 return TokError("unexpected token in directive");
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;
417 ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
418 return false;
421 bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
422 StringRef SymbolName;
424 if (getParser().parseIdentifier(SymbolName))
425 return TokError("expected identifier in directive");
427 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
429 getStreamer().BeginCOFFSymbolDef(Sym);
431 Lex();
432 return false;
435 bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
436 int64_t SymbolStorageClass;
437 if (getParser().parseAbsoluteExpression(SymbolStorageClass))
438 return true;
440 if (getLexer().isNot(AsmToken::EndOfStatement))
441 return TokError("unexpected token in directive");
443 Lex();
444 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
445 return false;
448 bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
449 int64_t Type;
450 if (getParser().parseAbsoluteExpression(Type))
451 return true;
453 if (getLexer().isNot(AsmToken::EndOfStatement))
454 return TokError("unexpected token in directive");
456 Lex();
457 getStreamer().EmitCOFFSymbolType(Type);
458 return false;
461 bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
462 Lex();
463 getStreamer().EndCOFFSymbolDef();
464 return false;
467 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
468 StringRef SymbolID;
469 if (getParser().parseIdentifier(SymbolID))
470 return TokError("expected identifier in directive");
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;
480 if (getLexer().isNot(AsmToken::EndOfStatement))
481 return TokError("unexpected token in directive");
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()");
489 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
491 Lex();
492 getStreamer().EmitCOFFSecRel32(Symbol, Offset);
493 return false;
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");
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;
510 if (Offset < std::numeric_limits<int32_t>::min() ||
511 Offset > std::numeric_limits<int32_t>::max())
512 return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less "
513 "than -2147483648 or greater than "
514 "2147483647");
516 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
518 getStreamer().EmitCOFFImgRel32(Symbol, Offset);
519 return false;
522 if (getParser().parseMany(parseOp))
523 return addErrorSuffix(" in directive");
524 return false;
527 bool COFFAsmParser::ParseDirectiveSafeSEH(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().EmitCOFFSafeSEH(Symbol);
539 return false;
542 bool COFFAsmParser::ParseDirectiveSecIdx(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().EmitCOFFSectionIndex(Symbol);
554 return false;
557 bool COFFAsmParser::ParseDirectiveSymIdx(StringRef, SMLoc) {
558 StringRef SymbolID;
559 if (getParser().parseIdentifier(SymbolID))
560 return TokError("expected identifier in directive");
562 if (getLexer().isNot(AsmToken::EndOfStatement))
563 return TokError("unexpected token in directive");
565 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
567 Lex();
568 getStreamer().EmitCOFFSymbolIndex(Symbol);
569 return false;
572 /// ::= [ identifier ]
573 bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
574 StringRef TypeId = getTok().getIdentifier();
576 Type = StringSwitch<COFF::COMDATType>(TypeId)
577 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
578 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
579 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
580 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
581 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
582 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
583 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
584 .Default((COFF::COMDATType)0);
586 if (Type == 0)
587 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
589 Lex();
591 return false;
594 /// ParseDirectiveLinkOnce
595 /// ::= .linkonce [ identifier ]
596 bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
597 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
598 if (getLexer().is(AsmToken::Identifier))
599 if (parseCOMDATType(Type))
600 return true;
602 const MCSectionCOFF *Current =
603 static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly());
605 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
606 return Error(Loc, "cannot make section associative with .linkonce");
608 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
609 return Error(Loc, Twine("section '") + Current->getSectionName() +
610 "' is already linkonce");
612 Current->setSelection(Type);
614 if (getLexer().isNot(AsmToken::EndOfStatement))
615 return TokError("unexpected token in directive");
617 return false;
620 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc Loc) {
621 StringRef SymbolID;
622 if (getParser().parseIdentifier(SymbolID))
623 return true;
625 if (getLexer().isNot(AsmToken::EndOfStatement))
626 return TokError("unexpected token in directive");
628 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
630 Lex();
631 getStreamer().EmitWinCFIStartProc(Symbol, Loc);
632 return false;
635 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc Loc) {
636 Lex();
637 getStreamer().EmitWinCFIEndProc(Loc);
638 return false;
641 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc Loc) {
642 Lex();
643 getStreamer().EmitWinCFIStartChained(Loc);
644 return false;
647 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc Loc) {
648 Lex();
649 getStreamer().EmitWinCFIEndChained(Loc);
650 return false;
653 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc Loc) {
654 StringRef SymbolID;
655 if (getParser().parseIdentifier(SymbolID))
656 return true;
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;
669 if (getLexer().isNot(AsmToken::EndOfStatement))
670 return TokError("unexpected token in directive");
672 MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
674 Lex();
675 getStreamer().EmitWinEHHandler(handler, unwind, except, Loc);
676 return false;
679 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) {
680 Lex();
681 getStreamer().EmitWinEHHandlerData();
682 return false;
685 bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc Loc) {
686 unsigned Reg = 0;
687 if (ParseSEHRegisterNumber(Reg))
688 return true;
690 if (getLexer().isNot(AsmToken::EndOfStatement))
691 return TokError("unexpected token in directive");
693 Lex();
694 getStreamer().EmitWinCFIPushReg(Reg, Loc);
695 return false;
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");
706 Lex();
707 if (getParser().parseAbsoluteExpression(Off))
708 return true;
710 if (getLexer().isNot(AsmToken::EndOfStatement))
711 return TokError("unexpected token in directive");
713 Lex();
714 getStreamer().EmitWinCFISetFrame(Reg, Off, Loc);
715 return false;
718 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) {
719 int64_t Size;
720 if (getParser().parseAbsoluteExpression(Size))
721 return true;
723 if (getLexer().isNot(AsmToken::EndOfStatement))
724 return TokError("unexpected token in directive");
726 Lex();
727 getStreamer().EmitWinCFIAllocStack(Size, Loc);
728 return false;
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");
739 Lex();
740 if (getParser().parseAbsoluteExpression(Off))
741 return true;
743 if (getLexer().isNot(AsmToken::EndOfStatement))
744 return TokError("unexpected token in directive");
746 Lex();
747 // FIXME: Err on %xmm* registers
748 getStreamer().EmitWinCFISaveReg(Reg, Off, Loc);
749 return false;
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");
762 Lex();
763 if (getParser().parseAbsoluteExpression(Off))
764 return true;
766 if (getLexer().isNot(AsmToken::EndOfStatement))
767 return TokError("unexpected token in directive");
769 Lex();
770 // FIXME: Err on non-%xmm* registers
771 getStreamer().EmitWinCFISaveXMM(Reg, Off, Loc);
772 return false;
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;
788 if (getLexer().isNot(AsmToken::EndOfStatement))
789 return TokError("unexpected token in directive");
791 Lex();
792 getStreamer().EmitWinCFIPushFrame(Code, Loc);
793 return false;
796 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) {
797 Lex();
798 getStreamer().EmitWinCFIEndProlog(Loc);
799 return false;
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;
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;
828 #if 0
829 // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
830 // violation so this validation code is disabled.
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
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;
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;
856 return false;
859 namespace llvm {
861 MCAsmParserExtension *createCOFFAsmParser() {
862 return new COFFAsmParser;
865 } // end namespace llvm