blob: b3c094366ab931d3281fabca57dc9ed032f4f2a4 [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");
Nico Rieck80646282013-07-06 12:13:10 +000054 addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
Charles Davisfbc539f2011-05-22 21:12:15 +000055
56 // Win64 EH directives.
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000057 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
Charles Davisfbc539f2011-05-22 21:12:15 +000058 ".seh_proc");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000059 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
Charles Davisfbc539f2011-05-22 21:12:15 +000060 ".seh_endproc");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000061 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
Charles Davisfbc539f2011-05-22 21:12:15 +000062 ".seh_startchained");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000063 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
Charles Davisfbc539f2011-05-22 21:12:15 +000064 ".seh_endchained");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000065 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
Charles Davisfbc539f2011-05-22 21:12:15 +000066 ".seh_handler");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000067 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
Charles Davisfbc539f2011-05-22 21:12:15 +000068 ".seh_handlerdata");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000069 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
Charles Davisfbc539f2011-05-22 21:12:15 +000070 ".seh_pushreg");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000071 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
Charles Davisfbc539f2011-05-22 21:12:15 +000072 ".seh_setframe");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000073 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
Charles Davisfbc539f2011-05-22 21:12:15 +000074 ".seh_stackalloc");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000075 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
Charles Davisfbc539f2011-05-22 21:12:15 +000076 ".seh_savereg");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000077 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
Charles Davisfbc539f2011-05-22 21:12:15 +000078 ".seh_savexmm");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000079 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
Charles Davisfbc539f2011-05-22 21:12:15 +000080 ".seh_pushframe");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000081 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
Charles Davisfbc539f2011-05-22 21:12:15 +000082 ".seh_endprologue");
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +000083 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
Michael J. Spencer7d490042010-10-09 11:01:07 +000084 }
85
86 bool ParseSectionDirectiveText(StringRef, SMLoc) {
87 return ParseSectionSwitch(".text",
88 COFF::IMAGE_SCN_CNT_CODE
89 | COFF::IMAGE_SCN_MEM_EXECUTE
90 | COFF::IMAGE_SCN_MEM_READ,
91 SectionKind::getText());
92 }
93 bool ParseSectionDirectiveData(StringRef, SMLoc) {
94 return ParseSectionSwitch(".data",
95 COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
96 | COFF::IMAGE_SCN_MEM_READ
97 | COFF::IMAGE_SCN_MEM_WRITE,
98 SectionKind::getDataRel());
99 }
100 bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
101 return ParseSectionSwitch(".bss",
102 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
103 | COFF::IMAGE_SCN_MEM_READ
104 | COFF::IMAGE_SCN_MEM_WRITE,
105 SectionKind::getBSS());
106 }
107
Nico Riecka6d343a2013-07-04 21:32:07 +0000108 bool ParseDirectiveSection(StringRef, SMLoc);
Michael J. Spencer7d490042010-10-09 11:01:07 +0000109 bool ParseDirectiveDef(StringRef, SMLoc);
110 bool ParseDirectiveScl(StringRef, SMLoc);
111 bool ParseDirectiveType(StringRef, SMLoc);
112 bool ParseDirectiveEndef(StringRef, SMLoc);
Rafael Espindola8f7d12c2011-12-17 01:14:52 +0000113 bool ParseDirectiveSecRel32(StringRef, SMLoc);
Nico Rieck80646282013-07-06 12:13:10 +0000114 bool ParseDirectiveLinkOnce(StringRef, SMLoc);
Michael J. Spencer7d490042010-10-09 11:01:07 +0000115
Charles Davisfbc539f2011-05-22 21:12:15 +0000116 // Win64 EH directives.
117 bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
118 bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
119 bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
120 bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
121 bool ParseSEHDirectiveHandler(StringRef, SMLoc);
122 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
Charles Davis3b32d022011-05-24 20:06:30 +0000123 bool ParseSEHDirectivePushReg(StringRef, SMLoc);
124 bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
125 bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
126 bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
127 bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
128 bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
Charles Davisfbc539f2011-05-22 21:12:15 +0000129 bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
130
131 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
Charles Davis3b32d022011-05-24 20:06:30 +0000132 bool ParseSEHRegisterNumber(unsigned &RegNo);
Jim Grosbachf2a35fb2011-07-25 17:55:35 +0000133 bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
Michael J. Spencer7d490042010-10-09 11:01:07 +0000134public:
135 COFFAsmParser() {}
136};
137
138} // end annonomous namespace.
139
Nico Riecka6d343a2013-07-04 21:32:07 +0000140static SectionKind computeSectionKind(unsigned Flags) {
141 if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
142 return SectionKind::getText();
143 if (Flags & COFF::IMAGE_SCN_MEM_READ &&
144 (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
145 return SectionKind::getReadOnly();
146 return SectionKind::getDataRel();
147}
148
149bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
150 enum {
151 None = 0,
152 Alloc = 1 << 0,
153 Code = 1 << 1,
154 Load = 1 << 2,
155 InitData = 1 << 3,
156 Shared = 1 << 4,
157 NoLoad = 1 << 5,
158 NoRead = 1 << 6,
159 NoWrite = 1 << 7
160 };
161
162 bool ReadOnlyRemoved = false;
163 unsigned SecFlags = None;
164
165 for (unsigned i = 0; i < FlagsString.size(); ++i) {
166 switch (FlagsString[i]) {
167 case 'a':
168 // Ignored.
169 break;
170
171 case 'b': // bss section
172 SecFlags |= Alloc;
173 if (SecFlags & InitData)
174 return TokError("conflicting section flags 'b' and 'd'.");
175 SecFlags &= ~Load;
176 break;
177
178 case 'd': // data section
179 SecFlags |= InitData;
180 if (SecFlags & Alloc)
181 return TokError("conflicting section flags 'b' and 'd'.");
182 SecFlags &= ~NoWrite;
183 if ((SecFlags & NoLoad) == 0)
184 SecFlags |= Load;
185 break;
186
187 case 'n': // section is not loaded
188 SecFlags |= NoLoad;
189 SecFlags &= ~Load;
190 break;
191
192 case 'r': // read-only
193 ReadOnlyRemoved = false;
194 SecFlags |= NoWrite;
195 if ((SecFlags & Code) == 0)
196 SecFlags |= InitData;
197 if ((SecFlags & NoLoad) == 0)
198 SecFlags |= Load;
199 break;
200
201 case 's': // shared section
202 SecFlags |= Shared | InitData;
203 SecFlags &= ~NoWrite;
204 if ((SecFlags & NoLoad) == 0)
205 SecFlags |= Load;
206 break;
207
208 case 'w': // writable
209 SecFlags &= ~NoWrite;
210 ReadOnlyRemoved = true;
211 break;
212
213 case 'x': // executable section
214 SecFlags |= Code;
215 if ((SecFlags & NoLoad) == 0)
216 SecFlags |= Load;
217 if (!ReadOnlyRemoved)
218 SecFlags |= NoWrite;
219 break;
220
221 case 'y': // not readable
222 SecFlags |= NoRead | NoWrite;
223 break;
224
225 default:
226 return TokError("unknown flag");
227 }
228 }
229
230 *Flags = 0;
231
232 if (SecFlags == None)
233 SecFlags = InitData;
234
235 if (SecFlags & Code)
236 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
237 if (SecFlags & InitData)
238 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
239 if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
240 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
241 if (SecFlags & NoLoad)
242 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
243 if ((SecFlags & NoRead) == 0)
244 *Flags |= COFF::IMAGE_SCN_MEM_READ;
245 if ((SecFlags & NoWrite) == 0)
246 *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
247 if (SecFlags & Shared)
248 *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
249
250 return false;
251}
252
Jim Grosbachf2a35fb2011-07-25 17:55:35 +0000253/// ParseDirectiveSymbolAttribute
254/// ::= { ".weak", ... } [ identifier ( , identifier )* ]
255bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
256 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
257 .Case(".weak", MCSA_Weak)
258 .Default(MCSA_Invalid);
259 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
260 if (getLexer().isNot(AsmToken::EndOfStatement)) {
261 for (;;) {
262 StringRef Name;
263
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000264 if (getParser().parseIdentifier(Name))
Jim Grosbachf2a35fb2011-07-25 17:55:35 +0000265 return TokError("expected identifier in directive");
266
267 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
268
269 getStreamer().EmitSymbolAttribute(Sym, Attr);
270
271 if (getLexer().is(AsmToken::EndOfStatement))
272 break;
273
274 if (getLexer().isNot(AsmToken::Comma))
275 return TokError("unexpected token in directive");
276 Lex();
277 }
278 }
279
280 Lex();
281 return false;
282}
283
Michael J. Spencer7d490042010-10-09 11:01:07 +0000284bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
285 unsigned Characteristics,
286 SectionKind Kind) {
287 if (getLexer().isNot(AsmToken::EndOfStatement))
288 return TokError("unexpected token in section switching directive");
289 Lex();
290
291 getStreamer().SwitchSection(getContext().getCOFFSection(
292 Section, Characteristics, Kind));
293
294 return false;
295}
296
Nico Riecka6d343a2013-07-04 21:32:07 +0000297bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
Hans Wennborgb74b88e2013-10-17 01:13:02 +0000298 return getParser().parseIdentifier(SectionName);
Nico Riecka6d343a2013-07-04 21:32:07 +0000299}
300
301// .section name [, "flags"]
302//
303// Supported flags:
304// a: Ignored.
305// b: BSS section (uninitialized data)
306// d: data section (initialized data)
307// n: Discardable section
308// r: Readable section
309// s: Shared section
310// w: Writable section
311// x: Executable section
312// y: Not-readable section (clears 'r')
313//
314// Subsections are not supported.
315bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
316 StringRef SectionName;
317
318 if (ParseSectionName(SectionName))
319 return TokError("expected identifier in directive");
320
321 unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
322 COFF::IMAGE_SCN_MEM_READ |
323 COFF::IMAGE_SCN_MEM_WRITE;
324
325 if (getLexer().is(AsmToken::Comma)) {
326 Lex();
327
328 if (getLexer().isNot(AsmToken::String))
329 return TokError("expected string in directive");
330
331 StringRef FlagsStr = getTok().getStringContents();
332 Lex();
333
334 if (ParseSectionFlags(FlagsStr, &Flags))
335 return true;
336 }
337
338 if (getLexer().isNot(AsmToken::EndOfStatement))
339 return TokError("unexpected token in directive");
340
341 SectionKind Kind = computeSectionKind(Flags);
342 ParseSectionSwitch(SectionName, Flags, Kind);
343 return false;
344}
345
Michael J. Spencer7d490042010-10-09 11:01:07 +0000346bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
347 StringRef SymbolName;
348
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000349 if (getParser().parseIdentifier(SymbolName))
Michael J. Spencer7d490042010-10-09 11:01:07 +0000350 return TokError("expected identifier in directive");
351
352 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
353
354 getStreamer().BeginCOFFSymbolDef(Sym);
355
356 Lex();
357 return false;
358}
359
360bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
361 int64_t SymbolStorageClass;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000362 if (getParser().parseAbsoluteExpression(SymbolStorageClass))
Michael J. Spencer7d490042010-10-09 11:01:07 +0000363 return true;
364
365 if (getLexer().isNot(AsmToken::EndOfStatement))
366 return TokError("unexpected token in directive");
367
368 Lex();
369 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
370 return false;
371}
372
373bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
374 int64_t Type;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000375 if (getParser().parseAbsoluteExpression(Type))
Michael J. Spencer7d490042010-10-09 11:01:07 +0000376 return true;
377
378 if (getLexer().isNot(AsmToken::EndOfStatement))
379 return TokError("unexpected token in directive");
380
381 Lex();
382 getStreamer().EmitCOFFSymbolType(Type);
383 return false;
384}
385
386bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
387 Lex();
388 getStreamer().EndCOFFSymbolDef();
389 return false;
390}
391
Rafael Espindola8f7d12c2011-12-17 01:14:52 +0000392bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
393 StringRef SymbolID;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000394 if (getParser().parseIdentifier(SymbolID))
Rafael Espindola8f7d12c2011-12-17 01:14:52 +0000395 return true;
396
397 if (getLexer().isNot(AsmToken::EndOfStatement))
398 return TokError("unexpected token in directive");
399
400 MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
401
402 Lex();
403 getStreamer().EmitCOFFSecRel32(Symbol);
404 return false;
405}
406
Nico Rieck80646282013-07-06 12:13:10 +0000407/// ParseDirectiveLinkOnce
408/// ::= .linkonce [ identifier [ identifier ] ]
409bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
410 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
411
412 if (getLexer().is(AsmToken::Identifier)) {
413 StringRef TypeId = getTok().getIdentifier();
414
415 Type = StringSwitch<COFF::COMDATType>(TypeId)
416 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
417 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
418 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
419 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
420 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
421 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
422 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
423 .Default((COFF::COMDATType)0);
424
425 if (Type == 0)
426 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
427
428 Lex();
429 }
430
431 const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
432 getStreamer().getCurrentSection().first);
433
434 const MCSectionCOFF *Assoc = 0;
435 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
436 StringRef AssocName;
437 SMLoc Loc = getTok().getLoc();
438 if (ParseSectionName(AssocName))
439 return TokError("expected associated section name");
440
441 Assoc = static_cast<const MCSectionCOFF*>(
442 getContext().getCOFFSection(AssocName));
443 if (!Assoc)
444 return Error(Loc, "cannot associate unknown section '" + AssocName + "'");
445 if (Assoc == Current)
446 return Error(Loc, "cannot associate a section with itself");
447 if (!(Assoc->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT))
448 return Error(Loc, "associated section must be a COMDAT section");
449 if (Assoc->getSelection() == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
450 return Error(Loc, "associated section cannot be itself associative");
451 }
452
453 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
454 return Error(Loc, Twine("section '") + Current->getSectionName() +
455 "' is already linkonce");
456
457 Current->setSelection(Type, Assoc);
458
459 if (getLexer().isNot(AsmToken::EndOfStatement))
460 return TokError("unexpected token in directive");
461
462 return false;
463}
464
Charles Davisfbc539f2011-05-22 21:12:15 +0000465bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
Charles Davis30921322011-05-25 01:33:42 +0000466 StringRef SymbolID;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000467 if (getParser().parseIdentifier(SymbolID))
Charles Davisfbc539f2011-05-22 21:12:15 +0000468 return true;
469
Charles Davisfbc539f2011-05-22 21:12:15 +0000470 if (getLexer().isNot(AsmToken::EndOfStatement))
471 return TokError("unexpected token in directive");
472
Charles Davis30921322011-05-25 01:33:42 +0000473 MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
474
Charles Davisfbc539f2011-05-22 21:12:15 +0000475 Lex();
Charles Davis30921322011-05-25 01:33:42 +0000476 getStreamer().EmitWin64EHStartProc(Symbol);
Charles Davisfbc539f2011-05-22 21:12:15 +0000477 return false;
478}
479
480bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
481 Lex();
482 getStreamer().EmitWin64EHEndProc();
483 return false;
484}
485
486bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
487 Lex();
488 getStreamer().EmitWin64EHStartChained();
489 return false;
490}
491
492bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
493 Lex();
494 getStreamer().EmitWin64EHEndChained();
495 return false;
496}
497
498bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
Charles Davis30921322011-05-25 01:33:42 +0000499 StringRef SymbolID;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000500 if (getParser().parseIdentifier(SymbolID))
Charles Davisfbc539f2011-05-22 21:12:15 +0000501 return true;
502
Charles Davis30921322011-05-25 01:33:42 +0000503 if (getLexer().isNot(AsmToken::Comma))
504 return TokError("you must specify one or both of @unwind or @except");
505 Lex();
Charles Davisfbc539f2011-05-22 21:12:15 +0000506 bool unwind = false, except = false;
Charles Davis30921322011-05-25 01:33:42 +0000507 if (ParseAtUnwindOrAtExcept(unwind, except))
508 return true;
Charles Davisfbc539f2011-05-22 21:12:15 +0000509 if (getLexer().is(AsmToken::Comma)) {
510 Lex();
Charles Davis30921322011-05-25 01:33:42 +0000511 if (ParseAtUnwindOrAtExcept(unwind, except))
Charles Davisfbc539f2011-05-22 21:12:15 +0000512 return true;
513 }
514 if (getLexer().isNot(AsmToken::EndOfStatement))
515 return TokError("unexpected token in directive");
516
Charles Davis30921322011-05-25 01:33:42 +0000517 MCSymbol *handler = getContext().GetOrCreateSymbol(SymbolID);
518
Charles Davisfbc539f2011-05-22 21:12:15 +0000519 Lex();
Charles Davis30921322011-05-25 01:33:42 +0000520 getStreamer().EmitWin64EHHandler(handler, unwind, except);
Charles Davisfbc539f2011-05-22 21:12:15 +0000521 return false;
522}
523
524bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
525 Lex();
526 getStreamer().EmitWin64EHHandlerData();
527 return false;
528}
529
530bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
Charles Davis3b32d022011-05-24 20:06:30 +0000531 unsigned Reg;
532 if (ParseSEHRegisterNumber(Reg))
533 return true;
534
535 if (getLexer().isNot(AsmToken::EndOfStatement))
536 return TokError("unexpected token in directive");
537
538 Lex();
539 getStreamer().EmitWin64EHPushReg(Reg);
540 return false;
Charles Davisfbc539f2011-05-22 21:12:15 +0000541}
542
543bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
Charles Davis3b32d022011-05-24 20:06:30 +0000544 unsigned Reg;
545 int64_t Off;
546 if (ParseSEHRegisterNumber(Reg))
547 return true;
Charles Davis410ef2b2011-05-25 21:43:45 +0000548 if (getLexer().isNot(AsmToken::Comma))
549 return TokError("you must specify a stack pointer offset");
550
551 Lex();
Charles Davis3b32d022011-05-24 20:06:30 +0000552 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000553 if (getParser().parseAbsoluteExpression(Off))
Charles Davis3b32d022011-05-24 20:06:30 +0000554 return true;
555
556 if (Off & 0x0F)
557 return Error(startLoc, "offset is not a multiple of 16");
558
559 if (getLexer().isNot(AsmToken::EndOfStatement))
560 return TokError("unexpected token in directive");
561
562 Lex();
563 getStreamer().EmitWin64EHSetFrame(Reg, Off);
564 return false;
Charles Davisfbc539f2011-05-22 21:12:15 +0000565}
566
Charles Davis16e1b3f2011-05-23 16:43:09 +0000567bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
568 int64_t Size;
Charles Davis3b32d022011-05-24 20:06:30 +0000569 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000570 if (getParser().parseAbsoluteExpression(Size))
Charles Davis16e1b3f2011-05-23 16:43:09 +0000571 return true;
572
Charles Davis3b32d022011-05-24 20:06:30 +0000573 if (Size & 7)
574 return Error(startLoc, "size is not a multiple of 8");
575
Charles Davis16e1b3f2011-05-23 16:43:09 +0000576 if (getLexer().isNot(AsmToken::EndOfStatement))
577 return TokError("unexpected token in directive");
578
579 Lex();
580 getStreamer().EmitWin64EHAllocStack(Size);
581 return false;
Charles Davisfbc539f2011-05-22 21:12:15 +0000582}
583
584bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
Charles Davis3b32d022011-05-24 20:06:30 +0000585 unsigned Reg;
586 int64_t Off;
587 if (ParseSEHRegisterNumber(Reg))
588 return true;
Charles Davis575630c2011-05-25 04:51:25 +0000589 if (getLexer().isNot(AsmToken::Comma))
Charles Davis410ef2b2011-05-25 21:43:45 +0000590 return TokError("you must specify an offset on the stack");
Charles Davis575630c2011-05-25 04:51:25 +0000591
592 Lex();
Charles Davis3b32d022011-05-24 20:06:30 +0000593 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000594 if (getParser().parseAbsoluteExpression(Off))
Charles Davis3b32d022011-05-24 20:06:30 +0000595 return true;
596
597 if (Off & 7)
598 return Error(startLoc, "size is not a multiple of 8");
599
600 if (getLexer().isNot(AsmToken::EndOfStatement))
601 return TokError("unexpected token in directive");
602
603 Lex();
604 // FIXME: Err on %xmm* registers
605 getStreamer().EmitWin64EHSaveReg(Reg, Off);
606 return false;
Charles Davisfbc539f2011-05-22 21:12:15 +0000607}
608
Charles Davis3b32d022011-05-24 20:06:30 +0000609// FIXME: This method is inherently x86-specific. It should really be in the
610// x86 backend.
Charles Davisfbc539f2011-05-22 21:12:15 +0000611bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
Charles Davis3b32d022011-05-24 20:06:30 +0000612 unsigned Reg;
613 int64_t Off;
614 if (ParseSEHRegisterNumber(Reg))
615 return true;
Charles Davis575630c2011-05-25 04:51:25 +0000616 if (getLexer().isNot(AsmToken::Comma))
Charles Davis410ef2b2011-05-25 21:43:45 +0000617 return TokError("you must specify an offset on the stack");
Charles Davis575630c2011-05-25 04:51:25 +0000618
619 Lex();
Charles Davis3b32d022011-05-24 20:06:30 +0000620 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000621 if (getParser().parseAbsoluteExpression(Off))
Charles Davis3b32d022011-05-24 20:06:30 +0000622 return true;
623
624 if (getLexer().isNot(AsmToken::EndOfStatement))
625 return TokError("unexpected token in directive");
626
627 if (Off & 0x0F)
628 return Error(startLoc, "offset is not a multiple of 16");
629
630 Lex();
631 // FIXME: Err on non-%xmm* registers
632 getStreamer().EmitWin64EHSaveXMM(Reg, Off);
633 return false;
Charles Davisfbc539f2011-05-22 21:12:15 +0000634}
635
Charles Davis16e1b3f2011-05-23 16:43:09 +0000636bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
Charles Davis47268162011-05-25 04:08:15 +0000637 bool Code = false;
Charles Davis16e1b3f2011-05-23 16:43:09 +0000638 StringRef CodeID;
Charles Davis47268162011-05-25 04:08:15 +0000639 if (getLexer().is(AsmToken::At)) {
640 SMLoc startLoc = getLexer().getLoc();
641 Lex();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000642 if (!getParser().parseIdentifier(CodeID)) {
Charles Davis47268162011-05-25 04:08:15 +0000643 if (CodeID != "code")
644 return Error(startLoc, "expected @code");
645 Code = true;
646 }
Charles Davis16e1b3f2011-05-23 16:43:09 +0000647 }
648
649 if (getLexer().isNot(AsmToken::EndOfStatement))
650 return TokError("unexpected token in directive");
651
652 Lex();
653 getStreamer().EmitWin64EHPushFrame(Code);
654 return false;
Charles Davisfbc539f2011-05-22 21:12:15 +0000655}
656
657bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
658 Lex();
659 getStreamer().EmitWin64EHEndProlog();
660 return false;
661}
662
663bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
664 StringRef identifier;
Charles Davis30921322011-05-25 01:33:42 +0000665 if (getLexer().isNot(AsmToken::At))
666 return TokError("a handler attribute must begin with '@'");
Charles Davisfbc539f2011-05-22 21:12:15 +0000667 SMLoc startLoc = getLexer().getLoc();
Charles Davis30921322011-05-25 01:33:42 +0000668 Lex();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000669 if (getParser().parseIdentifier(identifier))
Charles Davisfbc539f2011-05-22 21:12:15 +0000670 return Error(startLoc, "expected @unwind or @except");
Charles Davis30921322011-05-25 01:33:42 +0000671 if (identifier == "unwind")
Charles Davisfbc539f2011-05-22 21:12:15 +0000672 unwind = true;
Charles Davis30921322011-05-25 01:33:42 +0000673 else if (identifier == "except")
Charles Davisfbc539f2011-05-22 21:12:15 +0000674 except = true;
675 else
676 return Error(startLoc, "expected @unwind or @except");
677 return false;
678}
679
Charles Davis3b32d022011-05-24 20:06:30 +0000680bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
Charles Davis3b32d022011-05-24 20:06:30 +0000681 SMLoc startLoc = getLexer().getLoc();
Charles Davis575630c2011-05-25 04:51:25 +0000682 if (getLexer().is(AsmToken::Percent)) {
Bill Wendling99cb6222013-06-18 07:20:20 +0000683 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
Charles Davis3b32d022011-05-24 20:06:30 +0000684 SMLoc endLoc;
685 unsigned LLVMRegNo;
686 if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
Charles Davis575630c2011-05-25 04:51:25 +0000687 return true;
Charles Davis3b32d022011-05-24 20:06:30 +0000688
Evan Cheng0e6a0522011-07-18 20:57:22 +0000689#if 0
690 // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
691 // violation so this validation code is disabled.
692
Charles Davis3b32d022011-05-24 20:06:30 +0000693 // Check that this is a non-volatile register.
Evan Cheng1be0e272011-07-15 02:09:41 +0000694 const unsigned *NVRegs = TAI.getCalleeSavedRegs();
Charles Davis3b32d022011-05-24 20:06:30 +0000695 unsigned i;
696 for (i = 0; NVRegs[i] != 0; ++i)
697 if (NVRegs[i] == LLVMRegNo)
698 break;
699 if (NVRegs[i] == 0)
700 return Error(startLoc, "expected non-volatile register");
Evan Cheng0e6a0522011-07-18 20:57:22 +0000701#endif
Charles Davis3b32d022011-05-24 20:06:30 +0000702
Bill Wendling99cb6222013-06-18 07:20:20 +0000703 int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
Charles Davis3b32d022011-05-24 20:06:30 +0000704 if (SEHRegNo < 0)
705 return Error(startLoc,"register can't be represented in SEH unwind info");
706 RegNo = SEHRegNo;
707 }
Charles Davis575630c2011-05-25 04:51:25 +0000708 else {
709 int64_t n;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000710 if (getParser().parseAbsoluteExpression(n))
Charles Davis575630c2011-05-25 04:51:25 +0000711 return true;
712 if (n > 15)
713 return Error(startLoc, "register number is too high");
Charles Davis3b32d022011-05-24 20:06:30 +0000714 RegNo = n;
Charles Davis575630c2011-05-25 04:51:25 +0000715 }
Charles Davis3b32d022011-05-24 20:06:30 +0000716
Charles Davis3b32d022011-05-24 20:06:30 +0000717 return false;
718}
719
Michael J. Spencer7d490042010-10-09 11:01:07 +0000720namespace llvm {
721
722MCAsmParserExtension *createCOFFAsmParser() {
723 return new COFFAsmParser;
724}
725
726}