1 //===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/ADT/StringRef.h"
11 #include "llvm/ADT/StringSwitch.h"
12 #include "llvm/ADT/Triple.h"
13 #include "llvm/ADT/Twine.h"
14 #include "llvm/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/COFF.h"
25 #include "llvm/Support/SMLoc.h"
35 class COFFAsmParser : public MCAsmParserExtension {
36 template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
37 void addDirectiveHandler(StringRef Directive) {
38 MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
39 this, HandleDirective<COFFAsmParser, HandlerMethod>);
40 getParser().addDirectiveHandler(Directive, Handler);
43 bool ParseSectionSwitch(StringRef Section,
44 unsigned Characteristics,
47 bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
48 SectionKind Kind, StringRef COMDATSymName,
49 COFF::COMDATType Type);
51 bool ParseSectionName(StringRef &SectionName);
52 bool ParseSectionFlags(StringRef SectionName, StringRef FlagsString,
55 void Initialize(MCAsmParser &Parser) override {
56 // Call the base implementation.
57 MCAsmParserExtension::Initialize(Parser);
59 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
60 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
61 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
62 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
63 addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
64 addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
65 addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
66 addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
67 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
68 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
69 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
70 addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
72 // Win64 EH directives.
73 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
75 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
77 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
79 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
81 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
83 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
85 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
87 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
89 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
91 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
93 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
95 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
97 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
99 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
102 bool ParseSectionDirectiveText(StringRef, SMLoc) {
103 return ParseSectionSwitch(".text",
104 COFF::IMAGE_SCN_CNT_CODE
105 | COFF::IMAGE_SCN_MEM_EXECUTE
106 | COFF::IMAGE_SCN_MEM_READ,
107 SectionKind::getText());
110 bool ParseSectionDirectiveData(StringRef, SMLoc) {
111 return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
112 COFF::IMAGE_SCN_MEM_READ |
113 COFF::IMAGE_SCN_MEM_WRITE,
114 SectionKind::getData());
117 bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
118 return ParseSectionSwitch(".bss",
119 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
120 | COFF::IMAGE_SCN_MEM_READ
121 | COFF::IMAGE_SCN_MEM_WRITE,
122 SectionKind::getBSS());
125 bool ParseDirectiveSection(StringRef, SMLoc);
126 bool ParseDirectiveDef(StringRef, SMLoc);
127 bool ParseDirectiveScl(StringRef, SMLoc);
128 bool ParseDirectiveType(StringRef, SMLoc);
129 bool ParseDirectiveEndef(StringRef, SMLoc);
130 bool ParseDirectiveSecRel32(StringRef, SMLoc);
131 bool ParseDirectiveSecIdx(StringRef, SMLoc);
132 bool ParseDirectiveSafeSEH(StringRef, SMLoc);
133 bool parseCOMDATType(COFF::COMDATType &Type);
134 bool ParseDirectiveLinkOnce(StringRef, SMLoc);
136 // Win64 EH directives.
137 bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
138 bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
139 bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
140 bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
141 bool ParseSEHDirectiveHandler(StringRef, SMLoc);
142 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
143 bool ParseSEHDirectivePushReg(StringRef, SMLoc);
144 bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
145 bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
146 bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
147 bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
148 bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
149 bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
151 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
152 bool ParseSEHRegisterNumber(unsigned &RegNo);
153 bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
156 COFFAsmParser() = default;
159 } // end annonomous namespace.
161 static SectionKind computeSectionKind(unsigned Flags) {
162 if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
163 return SectionKind::getText();
164 if (Flags & COFF::IMAGE_SCN_MEM_READ &&
165 (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
166 return SectionKind::getReadOnly();
167 return SectionKind::getData();
170 bool COFFAsmParser::ParseSectionFlags(StringRef SectionName,
171 StringRef FlagsString, unsigned *Flags) {
182 Discardable = 1 << 8,
185 bool ReadOnlyRemoved = false;
186 unsigned SecFlags = None;
188 for (char FlagChar : FlagsString) {
194 case 'b': // bss section
196 if (SecFlags & InitData)
197 return TokError("conflicting section flags 'b' and 'd'.");
201 case 'd': // data section
202 SecFlags |= InitData;
203 if (SecFlags & Alloc)
204 return TokError("conflicting section flags 'b' and 'd'.");
205 SecFlags &= ~NoWrite;
206 if ((SecFlags & NoLoad) == 0)
210 case 'n': // section is not loaded
215 case 'D': // discardable
216 SecFlags |= Discardable;
219 case 'r': // read-only
220 ReadOnlyRemoved = false;
222 if ((SecFlags & Code) == 0)
223 SecFlags |= InitData;
224 if ((SecFlags & NoLoad) == 0)
228 case 's': // shared section
229 SecFlags |= Shared | InitData;
230 SecFlags &= ~NoWrite;
231 if ((SecFlags & NoLoad) == 0)
235 case 'w': // writable
236 SecFlags &= ~NoWrite;
237 ReadOnlyRemoved = true;
240 case 'x': // executable section
242 if ((SecFlags & NoLoad) == 0)
244 if (!ReadOnlyRemoved)
248 case 'y': // not readable
249 SecFlags |= NoRead | NoWrite;
253 return TokError("unknown flag");
259 if (SecFlags == None)
263 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
264 if (SecFlags & InitData)
265 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
266 if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
267 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
268 if (SecFlags & NoLoad)
269 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
270 if ((SecFlags & Discardable) ||
271 MCSectionCOFF::isImplicitlyDiscardable(SectionName))
272 *Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE;
273 if ((SecFlags & NoRead) == 0)
274 *Flags |= COFF::IMAGE_SCN_MEM_READ;
275 if ((SecFlags & NoWrite) == 0)
276 *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
277 if (SecFlags & Shared)
278 *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
283 /// ParseDirectiveSymbolAttribute
284 /// ::= { ".weak", ... } [ identifier ( , identifier )* ]
285 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
286 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
287 .Case(".weak", MCSA_Weak)
288 .Default(MCSA_Invalid);
289 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
290 if (getLexer().isNot(AsmToken::EndOfStatement)) {
294 if (getParser().parseIdentifier(Name))
295 return TokError("expected identifier in directive");
297 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
299 getStreamer().EmitSymbolAttribute(Sym, Attr);
301 if (getLexer().is(AsmToken::EndOfStatement))
304 if (getLexer().isNot(AsmToken::Comma))
305 return TokError("unexpected token in directive");
314 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
315 unsigned Characteristics,
317 return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
320 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
321 unsigned Characteristics,
323 StringRef COMDATSymName,
324 COFF::COMDATType Type) {
325 if (getLexer().isNot(AsmToken::EndOfStatement))
326 return TokError("unexpected token in section switching directive");
329 getStreamer().SwitchSection(getContext().getCOFFSection(
330 Section, Characteristics, Kind, COMDATSymName, Type));
335 bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
336 if (!getLexer().is(AsmToken::Identifier))
339 SectionName = getTok().getIdentifier();
344 // .section name [, "flags"] [, identifier [ identifier ], identifier]
348 // b: BSS section (uninitialized data)
349 // d: data section (initialized data)
350 // n: "noload" section (removed by linker)
351 // D: Discardable section
352 // r: Readable section
354 // w: Writable section
355 // x: Executable section
356 // y: Not-readable section (clears 'r')
358 // Subsections are not supported.
359 bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
360 StringRef SectionName;
362 if (ParseSectionName(SectionName))
363 return TokError("expected identifier in directive");
365 unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
366 COFF::IMAGE_SCN_MEM_READ |
367 COFF::IMAGE_SCN_MEM_WRITE;
369 if (getLexer().is(AsmToken::Comma)) {
372 if (getLexer().isNot(AsmToken::String))
373 return TokError("expected string in directive");
375 StringRef FlagsStr = getTok().getStringContents();
378 if (ParseSectionFlags(SectionName, FlagsStr, &Flags))
382 COFF::COMDATType Type = (COFF::COMDATType)0;
383 StringRef COMDATSymName;
384 if (getLexer().is(AsmToken::Comma)) {
385 Type = COFF::IMAGE_COMDAT_SELECT_ANY;
388 Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
390 if (!getLexer().is(AsmToken::Identifier))
391 return TokError("expected comdat type such as 'discard' or 'largest' "
392 "after protection bits");
394 if (parseCOMDATType(Type))
397 if (getLexer().isNot(AsmToken::Comma))
398 return TokError("expected comma in directive");
401 if (getParser().parseIdentifier(COMDATSymName))
402 return TokError("expected identifier in directive");
405 if (getLexer().isNot(AsmToken::EndOfStatement))
406 return TokError("unexpected token in directive");
408 SectionKind Kind = computeSectionKind(Flags);
410 const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
411 if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
412 Flags |= COFF::IMAGE_SCN_MEM_16BIT;
414 ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
418 bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
419 StringRef SymbolName;
421 if (getParser().parseIdentifier(SymbolName))
422 return TokError("expected identifier in directive");
424 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
426 getStreamer().BeginCOFFSymbolDef(Sym);
432 bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
433 int64_t SymbolStorageClass;
434 if (getParser().parseAbsoluteExpression(SymbolStorageClass))
437 if (getLexer().isNot(AsmToken::EndOfStatement))
438 return TokError("unexpected token in directive");
441 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
445 bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
447 if (getParser().parseAbsoluteExpression(Type))
450 if (getLexer().isNot(AsmToken::EndOfStatement))
451 return TokError("unexpected token in directive");
454 getStreamer().EmitCOFFSymbolType(Type);
458 bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
460 getStreamer().EndCOFFSymbolDef();
464 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
466 if (getParser().parseIdentifier(SymbolID))
467 return TokError("expected identifier in directive");
471 if (getLexer().is(AsmToken::Plus)) {
472 OffsetLoc = getLexer().getLoc();
473 if (getParser().parseAbsoluteExpression(Offset))
477 if (getLexer().isNot(AsmToken::EndOfStatement))
478 return TokError("unexpected token in directive");
480 if (Offset < 0 || Offset > std::numeric_limits<uint32_t>::max())
483 "invalid '.secrel32' directive offset, can't be less "
484 "than zero or greater than std::numeric_limits<uint32_t>::max()");
486 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
489 getStreamer().EmitCOFFSecRel32(Symbol, Offset);
493 bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
495 if (getParser().parseIdentifier(SymbolID))
496 return TokError("expected identifier in directive");
498 if (getLexer().isNot(AsmToken::EndOfStatement))
499 return TokError("unexpected token in directive");
501 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
504 getStreamer().EmitCOFFSafeSEH(Symbol);
508 bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
510 if (getParser().parseIdentifier(SymbolID))
511 return TokError("expected identifier in directive");
513 if (getLexer().isNot(AsmToken::EndOfStatement))
514 return TokError("unexpected token in directive");
516 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
519 getStreamer().EmitCOFFSectionIndex(Symbol);
523 /// ::= [ identifier ]
524 bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
525 StringRef TypeId = getTok().getIdentifier();
527 Type = StringSwitch<COFF::COMDATType>(TypeId)
528 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
529 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
530 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
531 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
532 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
533 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
534 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
535 .Default((COFF::COMDATType)0);
538 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
545 /// ParseDirectiveLinkOnce
546 /// ::= .linkonce [ identifier ]
547 bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
548 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
549 if (getLexer().is(AsmToken::Identifier))
550 if (parseCOMDATType(Type))
553 const MCSectionCOFF *Current =
554 static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly());
556 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
557 return Error(Loc, "cannot make section associative with .linkonce");
559 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
560 return Error(Loc, Twine("section '") + Current->getSectionName() +
561 "' is already linkonce");
563 Current->setSelection(Type);
565 if (getLexer().isNot(AsmToken::EndOfStatement))
566 return TokError("unexpected token in directive");
571 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
573 if (getParser().parseIdentifier(SymbolID))
576 if (getLexer().isNot(AsmToken::EndOfStatement))
577 return TokError("unexpected token in directive");
579 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
582 getStreamer().EmitWinCFIStartProc(Symbol);
586 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
588 getStreamer().EmitWinCFIEndProc();
592 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
594 getStreamer().EmitWinCFIStartChained();
598 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
600 getStreamer().EmitWinCFIEndChained();
604 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
606 if (getParser().parseIdentifier(SymbolID))
609 if (getLexer().isNot(AsmToken::Comma))
610 return TokError("you must specify one or both of @unwind or @except");
612 bool unwind = false, except = false;
613 if (ParseAtUnwindOrAtExcept(unwind, except))
615 if (getLexer().is(AsmToken::Comma)) {
617 if (ParseAtUnwindOrAtExcept(unwind, except))
620 if (getLexer().isNot(AsmToken::EndOfStatement))
621 return TokError("unexpected token in directive");
623 MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
626 getStreamer().EmitWinEHHandler(handler, unwind, except);
630 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
632 getStreamer().EmitWinEHHandlerData();
636 bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
638 if (ParseSEHRegisterNumber(Reg))
641 if (getLexer().isNot(AsmToken::EndOfStatement))
642 return TokError("unexpected token in directive");
645 getStreamer().EmitWinCFIPushReg(Reg);
649 bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
652 if (ParseSEHRegisterNumber(Reg))
654 if (getLexer().isNot(AsmToken::Comma))
655 return TokError("you must specify a stack pointer offset");
658 SMLoc startLoc = getLexer().getLoc();
659 if (getParser().parseAbsoluteExpression(Off))
663 return Error(startLoc, "offset is not a multiple of 16");
665 if (getLexer().isNot(AsmToken::EndOfStatement))
666 return TokError("unexpected token in directive");
669 getStreamer().EmitWinCFISetFrame(Reg, Off);
673 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
675 SMLoc startLoc = getLexer().getLoc();
676 if (getParser().parseAbsoluteExpression(Size))
680 return Error(startLoc, "size is not a multiple of 8");
682 if (getLexer().isNot(AsmToken::EndOfStatement))
683 return TokError("unexpected token in directive");
686 getStreamer().EmitWinCFIAllocStack(Size);
690 bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
693 if (ParseSEHRegisterNumber(Reg))
695 if (getLexer().isNot(AsmToken::Comma))
696 return TokError("you must specify an offset on the stack");
699 SMLoc startLoc = getLexer().getLoc();
700 if (getParser().parseAbsoluteExpression(Off))
704 return Error(startLoc, "size is not a multiple of 8");
706 if (getLexer().isNot(AsmToken::EndOfStatement))
707 return TokError("unexpected token in directive");
710 // FIXME: Err on %xmm* registers
711 getStreamer().EmitWinCFISaveReg(Reg, Off);
715 // FIXME: This method is inherently x86-specific. It should really be in the
717 bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
720 if (ParseSEHRegisterNumber(Reg))
722 if (getLexer().isNot(AsmToken::Comma))
723 return TokError("you must specify an offset on the stack");
726 SMLoc startLoc = getLexer().getLoc();
727 if (getParser().parseAbsoluteExpression(Off))
730 if (getLexer().isNot(AsmToken::EndOfStatement))
731 return TokError("unexpected token in directive");
734 return Error(startLoc, "offset is not a multiple of 16");
737 // FIXME: Err on non-%xmm* registers
738 getStreamer().EmitWinCFISaveXMM(Reg, Off);
742 bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
745 if (getLexer().is(AsmToken::At)) {
746 SMLoc startLoc = getLexer().getLoc();
748 if (!getParser().parseIdentifier(CodeID)) {
749 if (CodeID != "code")
750 return Error(startLoc, "expected @code");
755 if (getLexer().isNot(AsmToken::EndOfStatement))
756 return TokError("unexpected token in directive");
759 getStreamer().EmitWinCFIPushFrame(Code);
763 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
765 getStreamer().EmitWinCFIEndProlog();
769 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
770 StringRef identifier;
771 if (getLexer().isNot(AsmToken::At))
772 return TokError("a handler attribute must begin with '@'");
773 SMLoc startLoc = getLexer().getLoc();
775 if (getParser().parseIdentifier(identifier))
776 return Error(startLoc, "expected @unwind or @except");
777 if (identifier == "unwind")
779 else if (identifier == "except")
782 return Error(startLoc, "expected @unwind or @except");
786 bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
787 SMLoc startLoc = getLexer().getLoc();
788 if (getLexer().is(AsmToken::Percent)) {
789 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
792 if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
796 // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
797 // violation so this validation code is disabled.
799 // Check that this is a non-volatile register.
800 const unsigned *NVRegs = TAI.getCalleeSavedRegs();
802 for (i = 0; NVRegs[i] != 0; ++i)
803 if (NVRegs[i] == LLVMRegNo)
806 return Error(startLoc, "expected non-volatile register");
809 int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
811 return Error(startLoc,"register can't be represented in SEH unwind info");
816 if (getParser().parseAbsoluteExpression(n))
819 return Error(startLoc, "register number is too high");
828 MCAsmParserExtension *createCOFFAsmParser() {
829 return new COFFAsmParser;
832 } // end namespace llvm