blob: c2a22619db2553e72597ce7dda73bf43cffd9492 [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
Nico Riecka6d343a2013-07-04 21:32:07 +000038 bool ParseSectionName(StringRef &SectionName);
39 bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags);
40
Michael J. Spencer7d490042010-10-09 11:01:07 +000041 virtual void Initialize(MCAsmParser &Parser) {
42 // Call the base implementation.
43 MCAsmParserExtension::Initialize(Parser);
44
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000045 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
46 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
47 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
Nico Riecka6d343a2013-07-04 21:32:07 +000048 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000049 addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
50 addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
51 addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
52 addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
53 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
Charles Davisfbc539f2011-05-22 21:12:15 +000054
55 // Win64 EH directives.
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000056 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
Charles Davisfbc539f2011-05-22 21:12:15 +000057 ".seh_proc");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000058 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
Charles Davisfbc539f2011-05-22 21:12:15 +000059 ".seh_endproc");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000060 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
Charles Davisfbc539f2011-05-22 21:12:15 +000061 ".seh_startchained");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000062 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
Charles Davisfbc539f2011-05-22 21:12:15 +000063 ".seh_endchained");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000064 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
Charles Davisfbc539f2011-05-22 21:12:15 +000065 ".seh_handler");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000066 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
Charles Davisfbc539f2011-05-22 21:12:15 +000067 ".seh_handlerdata");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000068 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
Charles Davisfbc539f2011-05-22 21:12:15 +000069 ".seh_pushreg");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000070 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
Charles Davisfbc539f2011-05-22 21:12:15 +000071 ".seh_setframe");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000072 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
Charles Davisfbc539f2011-05-22 21:12:15 +000073 ".seh_stackalloc");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000074 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
Charles Davisfbc539f2011-05-22 21:12:15 +000075 ".seh_savereg");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000076 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
Charles Davisfbc539f2011-05-22 21:12:15 +000077 ".seh_savexmm");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000078 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
Charles Davisfbc539f2011-05-22 21:12:15 +000079 ".seh_pushframe");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000080 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
Charles Davisfbc539f2011-05-22 21:12:15 +000081 ".seh_endprologue");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000082 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
Michael J. Spencer7d490042010-10-09 11:01:07 +000083 }
84
85 bool ParseSectionDirectiveText(StringRef, SMLoc) {
86 return ParseSectionSwitch(".text",
87 COFF::IMAGE_SCN_CNT_CODE
88 | COFF::IMAGE_SCN_MEM_EXECUTE
89 | COFF::IMAGE_SCN_MEM_READ,
90 SectionKind::getText());
91 }
92 bool ParseSectionDirectiveData(StringRef, SMLoc) {
93 return ParseSectionSwitch(".data",
94 COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
95 | COFF::IMAGE_SCN_MEM_READ
96 | COFF::IMAGE_SCN_MEM_WRITE,
97 SectionKind::getDataRel());
98 }
99 bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
100 return ParseSectionSwitch(".bss",
101 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
102 | COFF::IMAGE_SCN_MEM_READ
103 | COFF::IMAGE_SCN_MEM_WRITE,
104 SectionKind::getBSS());
105 }
106
Nico Riecka6d343a2013-07-04 21:32:07 +0000107 bool ParseDirectiveSection(StringRef, SMLoc);
Michael J. Spencer7d490042010-10-09 11:01:07 +0000108 bool ParseDirectiveDef(StringRef, SMLoc);
109 bool ParseDirectiveScl(StringRef, SMLoc);
110 bool ParseDirectiveType(StringRef, SMLoc);
111 bool ParseDirectiveEndef(StringRef, SMLoc);
Rafael Espindola8f7d12c2011-12-17 01:14:52 +0000112 bool ParseDirectiveSecRel32(StringRef, SMLoc);
Michael J. Spencer7d490042010-10-09 11:01:07 +0000113
Charles Davisfbc539f2011-05-22 21:12:15 +0000114 // Win64 EH directives.
115 bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
116 bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
117 bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
118 bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
119 bool ParseSEHDirectiveHandler(StringRef, SMLoc);
120 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
Charles Davis3b32d022011-05-24 20:06:30 +0000121 bool ParseSEHDirectivePushReg(StringRef, SMLoc);
122 bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
123 bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
124 bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
125 bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
126 bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
Charles Davisfbc539f2011-05-22 21:12:15 +0000127 bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
128
129 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
Charles Davis3b32d022011-05-24 20:06:30 +0000130 bool ParseSEHRegisterNumber(unsigned &RegNo);
Jim Grosbachf2a35fb2011-07-25 17:55:35 +0000131 bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
Michael J. Spencer7d490042010-10-09 11:01:07 +0000132public:
133 COFFAsmParser() {}
134};
135
136} // end annonomous namespace.
137
Nico Riecka6d343a2013-07-04 21:32:07 +0000138static SectionKind computeSectionKind(unsigned Flags) {
139 if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
140 return SectionKind::getText();
141 if (Flags & COFF::IMAGE_SCN_MEM_READ &&
142 (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
143 return SectionKind::getReadOnly();
144 return SectionKind::getDataRel();
145}
146
147bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
148 enum {
149 None = 0,
150 Alloc = 1 << 0,
151 Code = 1 << 1,
152 Load = 1 << 2,
153 InitData = 1 << 3,
154 Shared = 1 << 4,
155 NoLoad = 1 << 5,
156 NoRead = 1 << 6,
157 NoWrite = 1 << 7
158 };
159
160 bool ReadOnlyRemoved = false;
161 unsigned SecFlags = None;
162
163 for (unsigned i = 0; i < FlagsString.size(); ++i) {
164 switch (FlagsString[i]) {
165 case 'a':
166 // Ignored.
167 break;
168
169 case 'b': // bss section
170 SecFlags |= Alloc;
171 if (SecFlags & InitData)
172 return TokError("conflicting section flags 'b' and 'd'.");
173 SecFlags &= ~Load;
174 break;
175
176 case 'd': // data section
177 SecFlags |= InitData;
178 if (SecFlags & Alloc)
179 return TokError("conflicting section flags 'b' and 'd'.");
180 SecFlags &= ~NoWrite;
181 if ((SecFlags & NoLoad) == 0)
182 SecFlags |= Load;
183 break;
184
185 case 'n': // section is not loaded
186 SecFlags |= NoLoad;
187 SecFlags &= ~Load;
188 break;
189
190 case 'r': // read-only
191 ReadOnlyRemoved = false;
192 SecFlags |= NoWrite;
193 if ((SecFlags & Code) == 0)
194 SecFlags |= InitData;
195 if ((SecFlags & NoLoad) == 0)
196 SecFlags |= Load;
197 break;
198
199 case 's': // shared section
200 SecFlags |= Shared | InitData;
201 SecFlags &= ~NoWrite;
202 if ((SecFlags & NoLoad) == 0)
203 SecFlags |= Load;
204 break;
205
206 case 'w': // writable
207 SecFlags &= ~NoWrite;
208 ReadOnlyRemoved = true;
209 break;
210
211 case 'x': // executable section
212 SecFlags |= Code;
213 if ((SecFlags & NoLoad) == 0)
214 SecFlags |= Load;
215 if (!ReadOnlyRemoved)
216 SecFlags |= NoWrite;
217 break;
218
219 case 'y': // not readable
220 SecFlags |= NoRead | NoWrite;
221 break;
222
223 default:
224 return TokError("unknown flag");
225 }
226 }
227
228 *Flags = 0;
229
230 if (SecFlags == None)
231 SecFlags = InitData;
232
233 if (SecFlags & Code)
234 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
235 if (SecFlags & InitData)
236 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
237 if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
238 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
239 if (SecFlags & NoLoad)
240 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
241 if ((SecFlags & NoRead) == 0)
242 *Flags |= COFF::IMAGE_SCN_MEM_READ;
243 if ((SecFlags & NoWrite) == 0)
244 *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
245 if (SecFlags & Shared)
246 *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
247
248 return false;
249}
250
Jim Grosbachf2a35fb2011-07-25 17:55:35 +0000251/// ParseDirectiveSymbolAttribute
252/// ::= { ".weak", ... } [ identifier ( , identifier )* ]
253bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
254 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
255 .Case(".weak", MCSA_Weak)
256 .Default(MCSA_Invalid);
257 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
258 if (getLexer().isNot(AsmToken::EndOfStatement)) {
259 for (;;) {
260 StringRef Name;
261
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000262 if (getParser().parseIdentifier(Name))
Jim Grosbachf2a35fb2011-07-25 17:55:35 +0000263 return TokError("expected identifier in directive");
264
265 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
266
267 getStreamer().EmitSymbolAttribute(Sym, Attr);
268
269 if (getLexer().is(AsmToken::EndOfStatement))
270 break;
271
272 if (getLexer().isNot(AsmToken::Comma))
273 return TokError("unexpected token in directive");
274 Lex();
275 }
276 }
277
278 Lex();
279 return false;
280}
281
Michael J. Spencer7d490042010-10-09 11:01:07 +0000282bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
283 unsigned Characteristics,
284 SectionKind Kind) {
285 if (getLexer().isNot(AsmToken::EndOfStatement))
286 return TokError("unexpected token in section switching directive");
287 Lex();
288
289 getStreamer().SwitchSection(getContext().getCOFFSection(
290 Section, Characteristics, Kind));
291
292 return false;
293}
294
Nico Riecka6d343a2013-07-04 21:32:07 +0000295bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
296 if (!getLexer().is(AsmToken::Identifier))
297 return true;
298
299 SectionName = getTok().getIdentifier();
300 Lex();
301 return false;
302}
303
304// .section name [, "flags"]
305//
306// Supported flags:
307// a: Ignored.
308// b: BSS section (uninitialized data)
309// d: data section (initialized data)
310// n: Discardable section
311// r: Readable section
312// s: Shared section
313// w: Writable section
314// x: Executable section
315// y: Not-readable section (clears 'r')
316//
317// Subsections are not supported.
318bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
319 StringRef SectionName;
320
321 if (ParseSectionName(SectionName))
322 return TokError("expected identifier in directive");
323
324 unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
325 COFF::IMAGE_SCN_MEM_READ |
326 COFF::IMAGE_SCN_MEM_WRITE;
327
328 if (getLexer().is(AsmToken::Comma)) {
329 Lex();
330
331 if (getLexer().isNot(AsmToken::String))
332 return TokError("expected string in directive");
333
334 StringRef FlagsStr = getTok().getStringContents();
335 Lex();
336
337 if (ParseSectionFlags(FlagsStr, &Flags))
338 return true;
339 }
340
341 if (getLexer().isNot(AsmToken::EndOfStatement))
342 return TokError("unexpected token in directive");
343
344 SectionKind Kind = computeSectionKind(Flags);
345 ParseSectionSwitch(SectionName, Flags, Kind);
346 return false;
347}
348
Michael J. Spencer7d490042010-10-09 11:01:07 +0000349bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
350 StringRef SymbolName;
351
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000352 if (getParser().parseIdentifier(SymbolName))
Michael J. Spencer7d490042010-10-09 11:01:07 +0000353 return TokError("expected identifier in directive");
354
355 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
356
357 getStreamer().BeginCOFFSymbolDef(Sym);
358
359 Lex();
360 return false;
361}
362
363bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
364 int64_t SymbolStorageClass;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000365 if (getParser().parseAbsoluteExpression(SymbolStorageClass))
Michael J. Spencer7d490042010-10-09 11:01:07 +0000366 return true;
367
368 if (getLexer().isNot(AsmToken::EndOfStatement))
369 return TokError("unexpected token in directive");
370
371 Lex();
372 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
373 return false;
374}
375
376bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
377 int64_t Type;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000378 if (getParser().parseAbsoluteExpression(Type))
Michael J. Spencer7d490042010-10-09 11:01:07 +0000379 return true;
380
381 if (getLexer().isNot(AsmToken::EndOfStatement))
382 return TokError("unexpected token in directive");
383
384 Lex();
385 getStreamer().EmitCOFFSymbolType(Type);
386 return false;
387}
388
389bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
390 Lex();
391 getStreamer().EndCOFFSymbolDef();
392 return false;
393}
394
Rafael Espindola8f7d12c2011-12-17 01:14:52 +0000395bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
396 StringRef SymbolID;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000397 if (getParser().parseIdentifier(SymbolID))
Rafael Espindola8f7d12c2011-12-17 01:14:52 +0000398 return true;
399
400 if (getLexer().isNot(AsmToken::EndOfStatement))
401 return TokError("unexpected token in directive");
402
403 MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
404
405 Lex();
406 getStreamer().EmitCOFFSecRel32(Symbol);
407 return false;
408}
409
Charles Davisfbc539f2011-05-22 21:12:15 +0000410bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
Charles Davis30921322011-05-25 01:33:42 +0000411 StringRef SymbolID;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000412 if (getParser().parseIdentifier(SymbolID))
Charles Davisfbc539f2011-05-22 21:12:15 +0000413 return true;
414
Charles Davisfbc539f2011-05-22 21:12:15 +0000415 if (getLexer().isNot(AsmToken::EndOfStatement))
416 return TokError("unexpected token in directive");
417
Charles Davis30921322011-05-25 01:33:42 +0000418 MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
419
Charles Davisfbc539f2011-05-22 21:12:15 +0000420 Lex();
Charles Davis30921322011-05-25 01:33:42 +0000421 getStreamer().EmitWin64EHStartProc(Symbol);
Charles Davisfbc539f2011-05-22 21:12:15 +0000422 return false;
423}
424
425bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
426 Lex();
427 getStreamer().EmitWin64EHEndProc();
428 return false;
429}
430
431bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
432 Lex();
433 getStreamer().EmitWin64EHStartChained();
434 return false;
435}
436
437bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
438 Lex();
439 getStreamer().EmitWin64EHEndChained();
440 return false;
441}
442
443bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
Charles Davis30921322011-05-25 01:33:42 +0000444 StringRef SymbolID;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000445 if (getParser().parseIdentifier(SymbolID))
Charles Davisfbc539f2011-05-22 21:12:15 +0000446 return true;
447
Charles Davis30921322011-05-25 01:33:42 +0000448 if (getLexer().isNot(AsmToken::Comma))
449 return TokError("you must specify one or both of @unwind or @except");
450 Lex();
Charles Davisfbc539f2011-05-22 21:12:15 +0000451 bool unwind = false, except = false;
Charles Davis30921322011-05-25 01:33:42 +0000452 if (ParseAtUnwindOrAtExcept(unwind, except))
453 return true;
Charles Davisfbc539f2011-05-22 21:12:15 +0000454 if (getLexer().is(AsmToken::Comma)) {
455 Lex();
Charles Davis30921322011-05-25 01:33:42 +0000456 if (ParseAtUnwindOrAtExcept(unwind, except))
Charles Davisfbc539f2011-05-22 21:12:15 +0000457 return true;
458 }
459 if (getLexer().isNot(AsmToken::EndOfStatement))
460 return TokError("unexpected token in directive");
461
Charles Davis30921322011-05-25 01:33:42 +0000462 MCSymbol *handler = getContext().GetOrCreateSymbol(SymbolID);
463
Charles Davisfbc539f2011-05-22 21:12:15 +0000464 Lex();
Charles Davis30921322011-05-25 01:33:42 +0000465 getStreamer().EmitWin64EHHandler(handler, unwind, except);
Charles Davisfbc539f2011-05-22 21:12:15 +0000466 return false;
467}
468
469bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
470 Lex();
471 getStreamer().EmitWin64EHHandlerData();
472 return false;
473}
474
475bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
Charles Davis3b32d022011-05-24 20:06:30 +0000476 unsigned Reg;
477 if (ParseSEHRegisterNumber(Reg))
478 return true;
479
480 if (getLexer().isNot(AsmToken::EndOfStatement))
481 return TokError("unexpected token in directive");
482
483 Lex();
484 getStreamer().EmitWin64EHPushReg(Reg);
485 return false;
Charles Davisfbc539f2011-05-22 21:12:15 +0000486}
487
488bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
Charles Davis3b32d022011-05-24 20:06:30 +0000489 unsigned Reg;
490 int64_t Off;
491 if (ParseSEHRegisterNumber(Reg))
492 return true;
Charles Davis410ef2b2011-05-25 21:43:45 +0000493 if (getLexer().isNot(AsmToken::Comma))
494 return TokError("you must specify a stack pointer offset");
495
496 Lex();
Charles Davis3b32d022011-05-24 20:06:30 +0000497 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000498 if (getParser().parseAbsoluteExpression(Off))
Charles Davis3b32d022011-05-24 20:06:30 +0000499 return true;
500
501 if (Off & 0x0F)
502 return Error(startLoc, "offset is not a multiple of 16");
503
504 if (getLexer().isNot(AsmToken::EndOfStatement))
505 return TokError("unexpected token in directive");
506
507 Lex();
508 getStreamer().EmitWin64EHSetFrame(Reg, Off);
509 return false;
Charles Davisfbc539f2011-05-22 21:12:15 +0000510}
511
Charles Davis16e1b3f2011-05-23 16:43:09 +0000512bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
513 int64_t Size;
Charles Davis3b32d022011-05-24 20:06:30 +0000514 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000515 if (getParser().parseAbsoluteExpression(Size))
Charles Davis16e1b3f2011-05-23 16:43:09 +0000516 return true;
517
Charles Davis3b32d022011-05-24 20:06:30 +0000518 if (Size & 7)
519 return Error(startLoc, "size is not a multiple of 8");
520
Charles Davis16e1b3f2011-05-23 16:43:09 +0000521 if (getLexer().isNot(AsmToken::EndOfStatement))
522 return TokError("unexpected token in directive");
523
524 Lex();
525 getStreamer().EmitWin64EHAllocStack(Size);
526 return false;
Charles Davisfbc539f2011-05-22 21:12:15 +0000527}
528
529bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
Charles Davis3b32d022011-05-24 20:06:30 +0000530 unsigned Reg;
531 int64_t Off;
532 if (ParseSEHRegisterNumber(Reg))
533 return true;
Charles Davis575630c2011-05-25 04:51:25 +0000534 if (getLexer().isNot(AsmToken::Comma))
Charles Davis410ef2b2011-05-25 21:43:45 +0000535 return TokError("you must specify an offset on the stack");
Charles Davis575630c2011-05-25 04:51:25 +0000536
537 Lex();
Charles Davis3b32d022011-05-24 20:06:30 +0000538 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000539 if (getParser().parseAbsoluteExpression(Off))
Charles Davis3b32d022011-05-24 20:06:30 +0000540 return true;
541
542 if (Off & 7)
543 return Error(startLoc, "size is not a multiple of 8");
544
545 if (getLexer().isNot(AsmToken::EndOfStatement))
546 return TokError("unexpected token in directive");
547
548 Lex();
549 // FIXME: Err on %xmm* registers
550 getStreamer().EmitWin64EHSaveReg(Reg, Off);
551 return false;
Charles Davisfbc539f2011-05-22 21:12:15 +0000552}
553
Charles Davis3b32d022011-05-24 20:06:30 +0000554// FIXME: This method is inherently x86-specific. It should really be in the
555// x86 backend.
Charles Davisfbc539f2011-05-22 21:12:15 +0000556bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
Charles Davis3b32d022011-05-24 20:06:30 +0000557 unsigned Reg;
558 int64_t Off;
559 if (ParseSEHRegisterNumber(Reg))
560 return true;
Charles Davis575630c2011-05-25 04:51:25 +0000561 if (getLexer().isNot(AsmToken::Comma))
Charles Davis410ef2b2011-05-25 21:43:45 +0000562 return TokError("you must specify an offset on the stack");
Charles Davis575630c2011-05-25 04:51:25 +0000563
564 Lex();
Charles Davis3b32d022011-05-24 20:06:30 +0000565 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000566 if (getParser().parseAbsoluteExpression(Off))
Charles Davis3b32d022011-05-24 20:06:30 +0000567 return true;
568
569 if (getLexer().isNot(AsmToken::EndOfStatement))
570 return TokError("unexpected token in directive");
571
572 if (Off & 0x0F)
573 return Error(startLoc, "offset is not a multiple of 16");
574
575 Lex();
576 // FIXME: Err on non-%xmm* registers
577 getStreamer().EmitWin64EHSaveXMM(Reg, Off);
578 return false;
Charles Davisfbc539f2011-05-22 21:12:15 +0000579}
580
Charles Davis16e1b3f2011-05-23 16:43:09 +0000581bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
Charles Davis47268162011-05-25 04:08:15 +0000582 bool Code = false;
Charles Davis16e1b3f2011-05-23 16:43:09 +0000583 StringRef CodeID;
Charles Davis47268162011-05-25 04:08:15 +0000584 if (getLexer().is(AsmToken::At)) {
585 SMLoc startLoc = getLexer().getLoc();
586 Lex();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000587 if (!getParser().parseIdentifier(CodeID)) {
Charles Davis47268162011-05-25 04:08:15 +0000588 if (CodeID != "code")
589 return Error(startLoc, "expected @code");
590 Code = true;
591 }
Charles Davis16e1b3f2011-05-23 16:43:09 +0000592 }
593
594 if (getLexer().isNot(AsmToken::EndOfStatement))
595 return TokError("unexpected token in directive");
596
597 Lex();
598 getStreamer().EmitWin64EHPushFrame(Code);
599 return false;
Charles Davisfbc539f2011-05-22 21:12:15 +0000600}
601
602bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
603 Lex();
604 getStreamer().EmitWin64EHEndProlog();
605 return false;
606}
607
608bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
609 StringRef identifier;
Charles Davis30921322011-05-25 01:33:42 +0000610 if (getLexer().isNot(AsmToken::At))
611 return TokError("a handler attribute must begin with '@'");
Charles Davisfbc539f2011-05-22 21:12:15 +0000612 SMLoc startLoc = getLexer().getLoc();
Charles Davis30921322011-05-25 01:33:42 +0000613 Lex();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000614 if (getParser().parseIdentifier(identifier))
Charles Davisfbc539f2011-05-22 21:12:15 +0000615 return Error(startLoc, "expected @unwind or @except");
Charles Davis30921322011-05-25 01:33:42 +0000616 if (identifier == "unwind")
Charles Davisfbc539f2011-05-22 21:12:15 +0000617 unwind = true;
Charles Davis30921322011-05-25 01:33:42 +0000618 else if (identifier == "except")
Charles Davisfbc539f2011-05-22 21:12:15 +0000619 except = true;
620 else
621 return Error(startLoc, "expected @unwind or @except");
622 return false;
623}
624
Charles Davis3b32d022011-05-24 20:06:30 +0000625bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
Charles Davis3b32d022011-05-24 20:06:30 +0000626 SMLoc startLoc = getLexer().getLoc();
Charles Davis575630c2011-05-25 04:51:25 +0000627 if (getLexer().is(AsmToken::Percent)) {
Bill Wendling99cb6222013-06-18 07:20:20 +0000628 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
Charles Davis3b32d022011-05-24 20:06:30 +0000629 SMLoc endLoc;
630 unsigned LLVMRegNo;
631 if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
Charles Davis575630c2011-05-25 04:51:25 +0000632 return true;
Charles Davis3b32d022011-05-24 20:06:30 +0000633
Evan Cheng0e6a0522011-07-18 20:57:22 +0000634#if 0
635 // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
636 // violation so this validation code is disabled.
637
Charles Davis3b32d022011-05-24 20:06:30 +0000638 // Check that this is a non-volatile register.
Evan Cheng1be0e272011-07-15 02:09:41 +0000639 const unsigned *NVRegs = TAI.getCalleeSavedRegs();
Charles Davis3b32d022011-05-24 20:06:30 +0000640 unsigned i;
641 for (i = 0; NVRegs[i] != 0; ++i)
642 if (NVRegs[i] == LLVMRegNo)
643 break;
644 if (NVRegs[i] == 0)
645 return Error(startLoc, "expected non-volatile register");
Evan Cheng0e6a0522011-07-18 20:57:22 +0000646#endif
Charles Davis3b32d022011-05-24 20:06:30 +0000647
Bill Wendling99cb6222013-06-18 07:20:20 +0000648 int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
Charles Davis3b32d022011-05-24 20:06:30 +0000649 if (SEHRegNo < 0)
650 return Error(startLoc,"register can't be represented in SEH unwind info");
651 RegNo = SEHRegNo;
652 }
Charles Davis575630c2011-05-25 04:51:25 +0000653 else {
654 int64_t n;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000655 if (getParser().parseAbsoluteExpression(n))
Charles Davis575630c2011-05-25 04:51:25 +0000656 return true;
657 if (n > 15)
658 return Error(startLoc, "register number is too high");
Charles Davis3b32d022011-05-24 20:06:30 +0000659 RegNo = n;
Charles Davis575630c2011-05-25 04:51:25 +0000660 }
Charles Davis3b32d022011-05-24 20:06:30 +0000661
Charles Davis3b32d022011-05-24 20:06:30 +0000662 return false;
663}
664
Michael J. Spencer7d490042010-10-09 11:01:07 +0000665namespace llvm {
666
667MCAsmParserExtension *createCOFFAsmParser() {
668 return new COFFAsmParser;
669}
670
671}