blob: a50eab217d21c2fd4aabc8fd9ece0a8b207c41e3 [file] [log] [blame]
Michael J. Spencer7d490042010-10-09 11:01:07 +00001//===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Jim Grosbachf2a35fb2011-07-25 17:55:35 +000011#include "llvm/ADT/StringSwitch.h"
Michael J. Spencer7d490042010-10-09 11:01:07 +000012#include "llvm/ADT/Twine.h"
13#include "llvm/MC/MCAsmInfo.h"
14#include "llvm/MC/MCContext.h"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000015#include "llvm/MC/MCExpr.h"
Michael J. Spencer7d490042010-10-09 11:01:07 +000016#include "llvm/MC/MCParser/MCAsmLexer.h"
Evan Cheng0e6a0522011-07-18 20:57:22 +000017#include "llvm/MC/MCRegisterInfo.h"
Michael J. Spencer7d490042010-10-09 11:01:07 +000018#include "llvm/MC/MCSectionCOFF.h"
19#include "llvm/MC/MCStreamer.h"
Evan Cheng94b95502011-07-26 00:24:13 +000020#include "llvm/MC/MCTargetAsmParser.h"
Michael J. Spencer7d490042010-10-09 11:01:07 +000021#include "llvm/Support/COFF.h"
22using namespace llvm;
23
24namespace {
25
26class COFFAsmParser : public MCAsmParserExtension {
Eli Bendersky171192f2013-01-16 00:50:52 +000027 template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000028 void addDirectiveHandler(StringRef Directive) {
Eli Bendersky171192f2013-01-16 00:50:52 +000029 MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
30 this, HandleDirective<COFFAsmParser, HandlerMethod>);
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000031 getParser().addDirectiveHandler(Directive, Handler);
Michael J. Spencer7d490042010-10-09 11:01:07 +000032 }
33
34 bool ParseSectionSwitch(StringRef Section,
35 unsigned Characteristics,
36 SectionKind Kind);
37
38 virtual void Initialize(MCAsmParser &Parser) {
39 // Call the base implementation.
40 MCAsmParserExtension::Initialize(Parser);
41
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000042 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
43 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
44 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
45 addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
46 addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
47 addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
48 addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
49 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
Charles Davisfbc539f2011-05-22 21:12:15 +000050
51 // Win64 EH directives.
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000052 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
Charles Davisfbc539f2011-05-22 21:12:15 +000053 ".seh_proc");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000054 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
Charles Davisfbc539f2011-05-22 21:12:15 +000055 ".seh_endproc");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000056 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
Charles Davisfbc539f2011-05-22 21:12:15 +000057 ".seh_startchained");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000058 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
Charles Davisfbc539f2011-05-22 21:12:15 +000059 ".seh_endchained");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000060 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
Charles Davisfbc539f2011-05-22 21:12:15 +000061 ".seh_handler");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000062 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
Charles Davisfbc539f2011-05-22 21:12:15 +000063 ".seh_handlerdata");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000064 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
Charles Davisfbc539f2011-05-22 21:12:15 +000065 ".seh_pushreg");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000066 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
Charles Davisfbc539f2011-05-22 21:12:15 +000067 ".seh_setframe");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000068 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
Charles Davisfbc539f2011-05-22 21:12:15 +000069 ".seh_stackalloc");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000070 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
Charles Davisfbc539f2011-05-22 21:12:15 +000071 ".seh_savereg");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000072 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
Charles Davisfbc539f2011-05-22 21:12:15 +000073 ".seh_savexmm");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000074 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
Charles Davisfbc539f2011-05-22 21:12:15 +000075 ".seh_pushframe");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000076 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
Charles Davisfbc539f2011-05-22 21:12:15 +000077 ".seh_endprologue");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000078 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
Michael J. Spencer7d490042010-10-09 11:01:07 +000079 }
80
81 bool ParseSectionDirectiveText(StringRef, SMLoc) {
82 return ParseSectionSwitch(".text",
83 COFF::IMAGE_SCN_CNT_CODE
84 | COFF::IMAGE_SCN_MEM_EXECUTE
85 | COFF::IMAGE_SCN_MEM_READ,
86 SectionKind::getText());
87 }
88 bool ParseSectionDirectiveData(StringRef, SMLoc) {
89 return ParseSectionSwitch(".data",
90 COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
91 | COFF::IMAGE_SCN_MEM_READ
92 | COFF::IMAGE_SCN_MEM_WRITE,
93 SectionKind::getDataRel());
94 }
95 bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
96 return ParseSectionSwitch(".bss",
97 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
98 | COFF::IMAGE_SCN_MEM_READ
99 | COFF::IMAGE_SCN_MEM_WRITE,
100 SectionKind::getBSS());
101 }
102
103 bool ParseDirectiveDef(StringRef, SMLoc);
104 bool ParseDirectiveScl(StringRef, SMLoc);
105 bool ParseDirectiveType(StringRef, SMLoc);
106 bool ParseDirectiveEndef(StringRef, SMLoc);
Rafael Espindola8f7d12c2011-12-17 01:14:52 +0000107 bool ParseDirectiveSecRel32(StringRef, SMLoc);
Michael J. Spencer7d490042010-10-09 11:01:07 +0000108
Charles Davisfbc539f2011-05-22 21:12:15 +0000109 // Win64 EH directives.
110 bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
111 bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
112 bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
113 bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
114 bool ParseSEHDirectiveHandler(StringRef, SMLoc);
115 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
Charles Davis3b32d022011-05-24 20:06:30 +0000116 bool ParseSEHDirectivePushReg(StringRef, SMLoc);
117 bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
118 bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
119 bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
120 bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
121 bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
Charles Davisfbc539f2011-05-22 21:12:15 +0000122 bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
123
124 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
Charles Davis3b32d022011-05-24 20:06:30 +0000125 bool ParseSEHRegisterNumber(unsigned &RegNo);
Jim Grosbachf2a35fb2011-07-25 17:55:35 +0000126 bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
Michael J. Spencer7d490042010-10-09 11:01:07 +0000127public:
128 COFFAsmParser() {}
129};
130
131} // end annonomous namespace.
132
Jim Grosbachf2a35fb2011-07-25 17:55:35 +0000133/// ParseDirectiveSymbolAttribute
134/// ::= { ".weak", ... } [ identifier ( , identifier )* ]
135bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
136 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
137 .Case(".weak", MCSA_Weak)
138 .Default(MCSA_Invalid);
139 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
140 if (getLexer().isNot(AsmToken::EndOfStatement)) {
141 for (;;) {
142 StringRef Name;
143
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000144 if (getParser().parseIdentifier(Name))
Jim Grosbachf2a35fb2011-07-25 17:55:35 +0000145 return TokError("expected identifier in directive");
146
147 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
148
149 getStreamer().EmitSymbolAttribute(Sym, Attr);
150
151 if (getLexer().is(AsmToken::EndOfStatement))
152 break;
153
154 if (getLexer().isNot(AsmToken::Comma))
155 return TokError("unexpected token in directive");
156 Lex();
157 }
158 }
159
160 Lex();
161 return false;
162}
163
Michael J. Spencer7d490042010-10-09 11:01:07 +0000164bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
165 unsigned Characteristics,
166 SectionKind Kind) {
167 if (getLexer().isNot(AsmToken::EndOfStatement))
168 return TokError("unexpected token in section switching directive");
169 Lex();
170
171 getStreamer().SwitchSection(getContext().getCOFFSection(
172 Section, Characteristics, Kind));
173
174 return false;
175}
176
177bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
178 StringRef SymbolName;
179
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000180 if (getParser().parseIdentifier(SymbolName))
Michael J. Spencer7d490042010-10-09 11:01:07 +0000181 return TokError("expected identifier in directive");
182
183 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
184
185 getStreamer().BeginCOFFSymbolDef(Sym);
186
187 Lex();
188 return false;
189}
190
191bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
192 int64_t SymbolStorageClass;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000193 if (getParser().parseAbsoluteExpression(SymbolStorageClass))
Michael J. Spencer7d490042010-10-09 11:01:07 +0000194 return true;
195
196 if (getLexer().isNot(AsmToken::EndOfStatement))
197 return TokError("unexpected token in directive");
198
199 Lex();
200 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
201 return false;
202}
203
204bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
205 int64_t Type;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000206 if (getParser().parseAbsoluteExpression(Type))
Michael J. Spencer7d490042010-10-09 11:01:07 +0000207 return true;
208
209 if (getLexer().isNot(AsmToken::EndOfStatement))
210 return TokError("unexpected token in directive");
211
212 Lex();
213 getStreamer().EmitCOFFSymbolType(Type);
214 return false;
215}
216
217bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
218 Lex();
219 getStreamer().EndCOFFSymbolDef();
220 return false;
221}
222
Rafael Espindola8f7d12c2011-12-17 01:14:52 +0000223bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
224 StringRef SymbolID;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000225 if (getParser().parseIdentifier(SymbolID))
Rafael Espindola8f7d12c2011-12-17 01:14:52 +0000226 return true;
227
228 if (getLexer().isNot(AsmToken::EndOfStatement))
229 return TokError("unexpected token in directive");
230
231 MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
232
233 Lex();
234 getStreamer().EmitCOFFSecRel32(Symbol);
235 return false;
236}
237
Charles Davisfbc539f2011-05-22 21:12:15 +0000238bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
Charles Davis30921322011-05-25 01:33:42 +0000239 StringRef SymbolID;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000240 if (getParser().parseIdentifier(SymbolID))
Charles Davisfbc539f2011-05-22 21:12:15 +0000241 return true;
242
Charles Davisfbc539f2011-05-22 21:12:15 +0000243 if (getLexer().isNot(AsmToken::EndOfStatement))
244 return TokError("unexpected token in directive");
245
Charles Davis30921322011-05-25 01:33:42 +0000246 MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
247
Charles Davisfbc539f2011-05-22 21:12:15 +0000248 Lex();
Charles Davis30921322011-05-25 01:33:42 +0000249 getStreamer().EmitWin64EHStartProc(Symbol);
Charles Davisfbc539f2011-05-22 21:12:15 +0000250 return false;
251}
252
253bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
254 Lex();
255 getStreamer().EmitWin64EHEndProc();
256 return false;
257}
258
259bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
260 Lex();
261 getStreamer().EmitWin64EHStartChained();
262 return false;
263}
264
265bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
266 Lex();
267 getStreamer().EmitWin64EHEndChained();
268 return false;
269}
270
271bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
Charles Davis30921322011-05-25 01:33:42 +0000272 StringRef SymbolID;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000273 if (getParser().parseIdentifier(SymbolID))
Charles Davisfbc539f2011-05-22 21:12:15 +0000274 return true;
275
Charles Davis30921322011-05-25 01:33:42 +0000276 if (getLexer().isNot(AsmToken::Comma))
277 return TokError("you must specify one or both of @unwind or @except");
278 Lex();
Charles Davisfbc539f2011-05-22 21:12:15 +0000279 bool unwind = false, except = false;
Charles Davis30921322011-05-25 01:33:42 +0000280 if (ParseAtUnwindOrAtExcept(unwind, except))
281 return true;
Charles Davisfbc539f2011-05-22 21:12:15 +0000282 if (getLexer().is(AsmToken::Comma)) {
283 Lex();
Charles Davis30921322011-05-25 01:33:42 +0000284 if (ParseAtUnwindOrAtExcept(unwind, except))
Charles Davisfbc539f2011-05-22 21:12:15 +0000285 return true;
286 }
287 if (getLexer().isNot(AsmToken::EndOfStatement))
288 return TokError("unexpected token in directive");
289
Charles Davis30921322011-05-25 01:33:42 +0000290 MCSymbol *handler = getContext().GetOrCreateSymbol(SymbolID);
291
Charles Davisfbc539f2011-05-22 21:12:15 +0000292 Lex();
Charles Davis30921322011-05-25 01:33:42 +0000293 getStreamer().EmitWin64EHHandler(handler, unwind, except);
Charles Davisfbc539f2011-05-22 21:12:15 +0000294 return false;
295}
296
297bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
298 Lex();
299 getStreamer().EmitWin64EHHandlerData();
300 return false;
301}
302
303bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
Charles Davis3b32d022011-05-24 20:06:30 +0000304 unsigned Reg;
305 if (ParseSEHRegisterNumber(Reg))
306 return true;
307
308 if (getLexer().isNot(AsmToken::EndOfStatement))
309 return TokError("unexpected token in directive");
310
311 Lex();
312 getStreamer().EmitWin64EHPushReg(Reg);
313 return false;
Charles Davisfbc539f2011-05-22 21:12:15 +0000314}
315
316bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
Charles Davis3b32d022011-05-24 20:06:30 +0000317 unsigned Reg;
318 int64_t Off;
319 if (ParseSEHRegisterNumber(Reg))
320 return true;
Charles Davis410ef2b2011-05-25 21:43:45 +0000321 if (getLexer().isNot(AsmToken::Comma))
322 return TokError("you must specify a stack pointer offset");
323
324 Lex();
Charles Davis3b32d022011-05-24 20:06:30 +0000325 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000326 if (getParser().parseAbsoluteExpression(Off))
Charles Davis3b32d022011-05-24 20:06:30 +0000327 return true;
328
329 if (Off & 0x0F)
330 return Error(startLoc, "offset is not a multiple of 16");
331
332 if (getLexer().isNot(AsmToken::EndOfStatement))
333 return TokError("unexpected token in directive");
334
335 Lex();
336 getStreamer().EmitWin64EHSetFrame(Reg, Off);
337 return false;
Charles Davisfbc539f2011-05-22 21:12:15 +0000338}
339
Charles Davis16e1b3f2011-05-23 16:43:09 +0000340bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
341 int64_t Size;
Charles Davis3b32d022011-05-24 20:06:30 +0000342 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000343 if (getParser().parseAbsoluteExpression(Size))
Charles Davis16e1b3f2011-05-23 16:43:09 +0000344 return true;
345
Charles Davis3b32d022011-05-24 20:06:30 +0000346 if (Size & 7)
347 return Error(startLoc, "size is not a multiple of 8");
348
Charles Davis16e1b3f2011-05-23 16:43:09 +0000349 if (getLexer().isNot(AsmToken::EndOfStatement))
350 return TokError("unexpected token in directive");
351
352 Lex();
353 getStreamer().EmitWin64EHAllocStack(Size);
354 return false;
Charles Davisfbc539f2011-05-22 21:12:15 +0000355}
356
357bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
Charles Davis3b32d022011-05-24 20:06:30 +0000358 unsigned Reg;
359 int64_t Off;
360 if (ParseSEHRegisterNumber(Reg))
361 return true;
Charles Davis575630c2011-05-25 04:51:25 +0000362 if (getLexer().isNot(AsmToken::Comma))
Charles Davis410ef2b2011-05-25 21:43:45 +0000363 return TokError("you must specify an offset on the stack");
Charles Davis575630c2011-05-25 04:51:25 +0000364
365 Lex();
Charles Davis3b32d022011-05-24 20:06:30 +0000366 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000367 if (getParser().parseAbsoluteExpression(Off))
Charles Davis3b32d022011-05-24 20:06:30 +0000368 return true;
369
370 if (Off & 7)
371 return Error(startLoc, "size is not a multiple of 8");
372
373 if (getLexer().isNot(AsmToken::EndOfStatement))
374 return TokError("unexpected token in directive");
375
376 Lex();
377 // FIXME: Err on %xmm* registers
378 getStreamer().EmitWin64EHSaveReg(Reg, Off);
379 return false;
Charles Davisfbc539f2011-05-22 21:12:15 +0000380}
381
Charles Davis3b32d022011-05-24 20:06:30 +0000382// FIXME: This method is inherently x86-specific. It should really be in the
383// x86 backend.
Charles Davisfbc539f2011-05-22 21:12:15 +0000384bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
Charles Davis3b32d022011-05-24 20:06:30 +0000385 unsigned Reg;
386 int64_t Off;
387 if (ParseSEHRegisterNumber(Reg))
388 return true;
Charles Davis575630c2011-05-25 04:51:25 +0000389 if (getLexer().isNot(AsmToken::Comma))
Charles Davis410ef2b2011-05-25 21:43:45 +0000390 return TokError("you must specify an offset on the stack");
Charles Davis575630c2011-05-25 04:51:25 +0000391
392 Lex();
Charles Davis3b32d022011-05-24 20:06:30 +0000393 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000394 if (getParser().parseAbsoluteExpression(Off))
Charles Davis3b32d022011-05-24 20:06:30 +0000395 return true;
396
397 if (getLexer().isNot(AsmToken::EndOfStatement))
398 return TokError("unexpected token in directive");
399
400 if (Off & 0x0F)
401 return Error(startLoc, "offset is not a multiple of 16");
402
403 Lex();
404 // FIXME: Err on non-%xmm* registers
405 getStreamer().EmitWin64EHSaveXMM(Reg, Off);
406 return false;
Charles Davisfbc539f2011-05-22 21:12:15 +0000407}
408
Charles Davis16e1b3f2011-05-23 16:43:09 +0000409bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
Charles Davis47268162011-05-25 04:08:15 +0000410 bool Code = false;
Charles Davis16e1b3f2011-05-23 16:43:09 +0000411 StringRef CodeID;
Charles Davis47268162011-05-25 04:08:15 +0000412 if (getLexer().is(AsmToken::At)) {
413 SMLoc startLoc = getLexer().getLoc();
414 Lex();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000415 if (!getParser().parseIdentifier(CodeID)) {
Charles Davis47268162011-05-25 04:08:15 +0000416 if (CodeID != "code")
417 return Error(startLoc, "expected @code");
418 Code = true;
419 }
Charles Davis16e1b3f2011-05-23 16:43:09 +0000420 }
421
422 if (getLexer().isNot(AsmToken::EndOfStatement))
423 return TokError("unexpected token in directive");
424
425 Lex();
426 getStreamer().EmitWin64EHPushFrame(Code);
427 return false;
Charles Davisfbc539f2011-05-22 21:12:15 +0000428}
429
430bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
431 Lex();
432 getStreamer().EmitWin64EHEndProlog();
433 return false;
434}
435
436bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
437 StringRef identifier;
Charles Davis30921322011-05-25 01:33:42 +0000438 if (getLexer().isNot(AsmToken::At))
439 return TokError("a handler attribute must begin with '@'");
Charles Davisfbc539f2011-05-22 21:12:15 +0000440 SMLoc startLoc = getLexer().getLoc();
Charles Davis30921322011-05-25 01:33:42 +0000441 Lex();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000442 if (getParser().parseIdentifier(identifier))
Charles Davisfbc539f2011-05-22 21:12:15 +0000443 return Error(startLoc, "expected @unwind or @except");
Charles Davis30921322011-05-25 01:33:42 +0000444 if (identifier == "unwind")
Charles Davisfbc539f2011-05-22 21:12:15 +0000445 unwind = true;
Charles Davis30921322011-05-25 01:33:42 +0000446 else if (identifier == "except")
Charles Davisfbc539f2011-05-22 21:12:15 +0000447 except = true;
448 else
449 return Error(startLoc, "expected @unwind or @except");
450 return false;
451}
452
Charles Davis3b32d022011-05-24 20:06:30 +0000453bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
Charles Davis3b32d022011-05-24 20:06:30 +0000454 SMLoc startLoc = getLexer().getLoc();
Charles Davis575630c2011-05-25 04:51:25 +0000455 if (getLexer().is(AsmToken::Percent)) {
Evan Cheng0e6a0522011-07-18 20:57:22 +0000456 const MCRegisterInfo &MRI = getContext().getRegisterInfo();
Charles Davis3b32d022011-05-24 20:06:30 +0000457 SMLoc endLoc;
458 unsigned LLVMRegNo;
459 if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
Charles Davis575630c2011-05-25 04:51:25 +0000460 return true;
Charles Davis3b32d022011-05-24 20:06:30 +0000461
Evan Cheng0e6a0522011-07-18 20:57:22 +0000462#if 0
463 // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
464 // violation so this validation code is disabled.
465
Charles Davis3b32d022011-05-24 20:06:30 +0000466 // Check that this is a non-volatile register.
Evan Cheng1be0e272011-07-15 02:09:41 +0000467 const unsigned *NVRegs = TAI.getCalleeSavedRegs();
Charles Davis3b32d022011-05-24 20:06:30 +0000468 unsigned i;
469 for (i = 0; NVRegs[i] != 0; ++i)
470 if (NVRegs[i] == LLVMRegNo)
471 break;
472 if (NVRegs[i] == 0)
473 return Error(startLoc, "expected non-volatile register");
Evan Cheng0e6a0522011-07-18 20:57:22 +0000474#endif
Charles Davis3b32d022011-05-24 20:06:30 +0000475
Evan Cheng0e6a0522011-07-18 20:57:22 +0000476 int SEHRegNo = MRI.getSEHRegNum(LLVMRegNo);
Charles Davis3b32d022011-05-24 20:06:30 +0000477 if (SEHRegNo < 0)
478 return Error(startLoc,"register can't be represented in SEH unwind info");
479 RegNo = SEHRegNo;
480 }
Charles Davis575630c2011-05-25 04:51:25 +0000481 else {
482 int64_t n;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000483 if (getParser().parseAbsoluteExpression(n))
Charles Davis575630c2011-05-25 04:51:25 +0000484 return true;
485 if (n > 15)
486 return Error(startLoc, "register number is too high");
Charles Davis3b32d022011-05-24 20:06:30 +0000487 RegNo = n;
Charles Davis575630c2011-05-25 04:51:25 +0000488 }
Charles Davis3b32d022011-05-24 20:06:30 +0000489
Charles Davis3b32d022011-05-24 20:06:30 +0000490 return false;
491}
492
Michael J. Spencer7d490042010-10-09 11:01:07 +0000493namespace llvm {
494
495MCAsmParserExtension *createCOFFAsmParser() {
496 return new COFFAsmParser;
497}
498
499}