blob: cc356c7a1748482c19b41baa61e24e5fc60f8b20 [file] [log] [blame]
Michael J. Spencerc8dbdfd2010-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 Grosbach38b1ed82011-07-25 17:55:35 +000011#include "llvm/ADT/StringSwitch.h"
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000012#include "llvm/ADT/Twine.h"
13#include "llvm/MC/MCAsmInfo.h"
14#include "llvm/MC/MCContext.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000015#include "llvm/MC/MCExpr.h"
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000016#include "llvm/MC/MCParser/MCAsmLexer.h"
Evan Chengd60fa58b2011-07-18 20:57:22 +000017#include "llvm/MC/MCRegisterInfo.h"
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000018#include "llvm/MC/MCSectionCOFF.h"
19#include "llvm/MC/MCStreamer.h"
Evan Cheng11424442011-07-26 00:24:13 +000020#include "llvm/MC/MCTargetAsmParser.h"
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000021#include "llvm/Support/COFF.h"
22using namespace llvm;
23
24namespace {
25
26class COFFAsmParser : public MCAsmParserExtension {
Eli Bendersky29b9f472013-01-16 00:50:52 +000027 template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
Jim Grosbachd2037eb2013-02-20 22:21:35 +000028 void addDirectiveHandler(StringRef Directive) {
Eli Bendersky29b9f472013-01-16 00:50:52 +000029 MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
30 this, HandleDirective<COFFAsmParser, HandlerMethod>);
Jim Grosbachd2037eb2013-02-20 22:21:35 +000031 getParser().addDirectiveHandler(Directive, Handler);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000032 }
33
34 bool ParseSectionSwitch(StringRef Section,
35 unsigned Characteristics,
36 SectionKind Kind);
37
Rafael Espindola60ec3832013-11-19 19:52:52 +000038 bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
39 SectionKind Kind, StringRef COMDATSymName,
40 COFF::COMDATType Type, const MCSectionCOFF *Assoc);
41
Nico Rieck1558c5a2013-07-04 21:32:07 +000042 bool ParseSectionName(StringRef &SectionName);
43 bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags);
44
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000045 virtual void Initialize(MCAsmParser &Parser) {
46 // Call the base implementation.
47 MCAsmParserExtension::Initialize(Parser);
48
Jim Grosbachd2037eb2013-02-20 22:21:35 +000049 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
50 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
51 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
Nico Rieck1558c5a2013-07-04 21:32:07 +000052 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000053 addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
54 addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
55 addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
56 addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
57 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +000058 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
Nico Riecka37acf72013-07-06 12:13:10 +000059 addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
Charles Davisc7250fa2011-05-22 21:12:15 +000060
61 // Win64 EH directives.
Jim Grosbachd2037eb2013-02-20 22:21:35 +000062 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
Charles Davisc7250fa2011-05-22 21:12:15 +000063 ".seh_proc");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000064 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
Charles Davisc7250fa2011-05-22 21:12:15 +000065 ".seh_endproc");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000066 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
Charles Davisc7250fa2011-05-22 21:12:15 +000067 ".seh_startchained");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000068 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
Charles Davisc7250fa2011-05-22 21:12:15 +000069 ".seh_endchained");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000070 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
Charles Davisc7250fa2011-05-22 21:12:15 +000071 ".seh_handler");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000072 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
Charles Davisc7250fa2011-05-22 21:12:15 +000073 ".seh_handlerdata");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000074 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
Charles Davisc7250fa2011-05-22 21:12:15 +000075 ".seh_pushreg");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000076 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
Charles Davisc7250fa2011-05-22 21:12:15 +000077 ".seh_setframe");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000078 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
Charles Davisc7250fa2011-05-22 21:12:15 +000079 ".seh_stackalloc");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000080 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
Charles Davisc7250fa2011-05-22 21:12:15 +000081 ".seh_savereg");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000082 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
Charles Davisc7250fa2011-05-22 21:12:15 +000083 ".seh_savexmm");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000084 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
Charles Davisc7250fa2011-05-22 21:12:15 +000085 ".seh_pushframe");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000086 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
Charles Davisc7250fa2011-05-22 21:12:15 +000087 ".seh_endprologue");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000088 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000089 }
90
91 bool ParseSectionDirectiveText(StringRef, SMLoc) {
92 return ParseSectionSwitch(".text",
93 COFF::IMAGE_SCN_CNT_CODE
94 | COFF::IMAGE_SCN_MEM_EXECUTE
95 | COFF::IMAGE_SCN_MEM_READ,
96 SectionKind::getText());
97 }
98 bool ParseSectionDirectiveData(StringRef, SMLoc) {
99 return ParseSectionSwitch(".data",
100 COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
101 | COFF::IMAGE_SCN_MEM_READ
102 | COFF::IMAGE_SCN_MEM_WRITE,
103 SectionKind::getDataRel());
104 }
105 bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
106 return ParseSectionSwitch(".bss",
107 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
108 | COFF::IMAGE_SCN_MEM_READ
109 | COFF::IMAGE_SCN_MEM_WRITE,
110 SectionKind::getBSS());
111 }
112
Nico Rieck1558c5a2013-07-04 21:32:07 +0000113 bool ParseDirectiveSection(StringRef, SMLoc);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000114 bool ParseDirectiveDef(StringRef, SMLoc);
115 bool ParseDirectiveScl(StringRef, SMLoc);
116 bool ParseDirectiveType(StringRef, SMLoc);
117 bool ParseDirectiveEndef(StringRef, SMLoc);
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000118 bool ParseDirectiveSecRel32(StringRef, SMLoc);
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000119 bool ParseDirectiveSecIdx(StringRef, SMLoc);
Rafael Espindola60ec3832013-11-19 19:52:52 +0000120 bool parseCOMDATTypeAndAssoc(COFF::COMDATType &Type,
121 const MCSectionCOFF *&Assoc);
Nico Riecka37acf72013-07-06 12:13:10 +0000122 bool ParseDirectiveLinkOnce(StringRef, SMLoc);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000123
Charles Davisc7250fa2011-05-22 21:12:15 +0000124 // Win64 EH directives.
125 bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
126 bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
127 bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
128 bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
129 bool ParseSEHDirectiveHandler(StringRef, SMLoc);
130 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
Charles Davis7f6176c2011-05-24 20:06:30 +0000131 bool ParseSEHDirectivePushReg(StringRef, SMLoc);
132 bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
133 bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
134 bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
135 bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
136 bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
Charles Davisc7250fa2011-05-22 21:12:15 +0000137 bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
138
139 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
Charles Davis7f6176c2011-05-24 20:06:30 +0000140 bool ParseSEHRegisterNumber(unsigned &RegNo);
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000141 bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000142public:
143 COFFAsmParser() {}
144};
145
146} // end annonomous namespace.
147
Nico Rieck1558c5a2013-07-04 21:32:07 +0000148static SectionKind computeSectionKind(unsigned Flags) {
149 if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
150 return SectionKind::getText();
151 if (Flags & COFF::IMAGE_SCN_MEM_READ &&
152 (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
153 return SectionKind::getReadOnly();
154 return SectionKind::getDataRel();
155}
156
157bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
158 enum {
159 None = 0,
160 Alloc = 1 << 0,
161 Code = 1 << 1,
162 Load = 1 << 2,
163 InitData = 1 << 3,
164 Shared = 1 << 4,
165 NoLoad = 1 << 5,
166 NoRead = 1 << 6,
167 NoWrite = 1 << 7
168 };
169
170 bool ReadOnlyRemoved = false;
171 unsigned SecFlags = None;
172
173 for (unsigned i = 0; i < FlagsString.size(); ++i) {
174 switch (FlagsString[i]) {
175 case 'a':
176 // Ignored.
177 break;
178
179 case 'b': // bss section
180 SecFlags |= Alloc;
181 if (SecFlags & InitData)
182 return TokError("conflicting section flags 'b' and 'd'.");
183 SecFlags &= ~Load;
184 break;
185
186 case 'd': // data section
187 SecFlags |= InitData;
188 if (SecFlags & Alloc)
189 return TokError("conflicting section flags 'b' and 'd'.");
190 SecFlags &= ~NoWrite;
191 if ((SecFlags & NoLoad) == 0)
192 SecFlags |= Load;
193 break;
194
195 case 'n': // section is not loaded
196 SecFlags |= NoLoad;
197 SecFlags &= ~Load;
198 break;
199
200 case 'r': // read-only
201 ReadOnlyRemoved = false;
202 SecFlags |= NoWrite;
203 if ((SecFlags & Code) == 0)
204 SecFlags |= InitData;
205 if ((SecFlags & NoLoad) == 0)
206 SecFlags |= Load;
207 break;
208
209 case 's': // shared section
210 SecFlags |= Shared | InitData;
211 SecFlags &= ~NoWrite;
212 if ((SecFlags & NoLoad) == 0)
213 SecFlags |= Load;
214 break;
215
216 case 'w': // writable
217 SecFlags &= ~NoWrite;
218 ReadOnlyRemoved = true;
219 break;
220
221 case 'x': // executable section
222 SecFlags |= Code;
223 if ((SecFlags & NoLoad) == 0)
224 SecFlags |= Load;
225 if (!ReadOnlyRemoved)
226 SecFlags |= NoWrite;
227 break;
228
229 case 'y': // not readable
230 SecFlags |= NoRead | NoWrite;
231 break;
232
233 default:
234 return TokError("unknown flag");
235 }
236 }
237
238 *Flags = 0;
239
240 if (SecFlags == None)
241 SecFlags = InitData;
242
243 if (SecFlags & Code)
244 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
245 if (SecFlags & InitData)
246 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
247 if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
248 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
249 if (SecFlags & NoLoad)
250 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
251 if ((SecFlags & NoRead) == 0)
252 *Flags |= COFF::IMAGE_SCN_MEM_READ;
253 if ((SecFlags & NoWrite) == 0)
254 *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
255 if (SecFlags & Shared)
256 *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
257
258 return false;
259}
260
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000261/// ParseDirectiveSymbolAttribute
262/// ::= { ".weak", ... } [ identifier ( , identifier )* ]
263bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
264 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
265 .Case(".weak", MCSA_Weak)
266 .Default(MCSA_Invalid);
267 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
268 if (getLexer().isNot(AsmToken::EndOfStatement)) {
269 for (;;) {
270 StringRef Name;
271
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000272 if (getParser().parseIdentifier(Name))
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000273 return TokError("expected identifier in directive");
274
275 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
276
277 getStreamer().EmitSymbolAttribute(Sym, Attr);
278
279 if (getLexer().is(AsmToken::EndOfStatement))
280 break;
281
282 if (getLexer().isNot(AsmToken::Comma))
283 return TokError("unexpected token in directive");
284 Lex();
285 }
286 }
287
288 Lex();
289 return false;
290}
291
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000292bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
293 unsigned Characteristics,
294 SectionKind Kind) {
Rafael Espindola60ec3832013-11-19 19:52:52 +0000295 return ParseSectionSwitch(Section, Characteristics, Kind, "",
296 COFF::IMAGE_COMDAT_SELECT_ANY, 0);
297}
298
299bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
300 unsigned Characteristics,
301 SectionKind Kind,
302 StringRef COMDATSymName,
303 COFF::COMDATType Type,
304 const MCSectionCOFF *Assoc) {
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000305 if (getLexer().isNot(AsmToken::EndOfStatement))
306 return TokError("unexpected token in section switching directive");
307 Lex();
308
309 getStreamer().SwitchSection(getContext().getCOFFSection(
Rafael Espindola60ec3832013-11-19 19:52:52 +0000310 Section, Characteristics, Kind, COMDATSymName, Type, Assoc));
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000311
312 return false;
313}
314
Nico Rieck1558c5a2013-07-04 21:32:07 +0000315bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
Hans Wennborg7ddcdc82013-10-18 02:14:40 +0000316 if (!getLexer().is(AsmToken::Identifier))
317 return true;
318
319 SectionName = getTok().getIdentifier();
320 Lex();
321 return false;
Nico Rieck1558c5a2013-07-04 21:32:07 +0000322}
323
Rafael Espindola60ec3832013-11-19 19:52:52 +0000324// .section name [, "flags"] [, identifier [ identifier ], identifier]
Nico Rieck1558c5a2013-07-04 21:32:07 +0000325//
326// Supported flags:
327// a: Ignored.
328// b: BSS section (uninitialized data)
329// d: data section (initialized data)
330// n: Discardable section
331// r: Readable section
332// s: Shared section
333// w: Writable section
334// x: Executable section
335// y: Not-readable section (clears 'r')
336//
337// Subsections are not supported.
338bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
339 StringRef SectionName;
340
341 if (ParseSectionName(SectionName))
342 return TokError("expected identifier in directive");
343
344 unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
345 COFF::IMAGE_SCN_MEM_READ |
346 COFF::IMAGE_SCN_MEM_WRITE;
347
348 if (getLexer().is(AsmToken::Comma)) {
349 Lex();
350
351 if (getLexer().isNot(AsmToken::String))
352 return TokError("expected string in directive");
353
354 StringRef FlagsStr = getTok().getStringContents();
355 Lex();
356
357 if (ParseSectionFlags(FlagsStr, &Flags))
358 return true;
359 }
360
Rafael Espindola60ec3832013-11-19 19:52:52 +0000361 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
362 const MCSectionCOFF *Assoc = 0;
363 StringRef COMDATSymName;
364 if (getLexer().is(AsmToken::Comma)) {
365 Lex();
366
367 Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
368
369 if (parseCOMDATTypeAndAssoc(Type, Assoc))
370 return true;
371
372 if (getLexer().isNot(AsmToken::Comma))
373 return TokError("expected comma in directive");
374 Lex();
375
376 if (getParser().parseIdentifier(COMDATSymName))
377 return TokError("expected identifier in directive");
378 }
379
Nico Rieck1558c5a2013-07-04 21:32:07 +0000380 if (getLexer().isNot(AsmToken::EndOfStatement))
381 return TokError("unexpected token in directive");
382
383 SectionKind Kind = computeSectionKind(Flags);
Rafael Espindola60ec3832013-11-19 19:52:52 +0000384 ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type, Assoc);
Nico Rieck1558c5a2013-07-04 21:32:07 +0000385 return false;
386}
387
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000388bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
389 StringRef SymbolName;
390
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000391 if (getParser().parseIdentifier(SymbolName))
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000392 return TokError("expected identifier in directive");
393
394 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
395
396 getStreamer().BeginCOFFSymbolDef(Sym);
397
398 Lex();
399 return false;
400}
401
402bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
403 int64_t SymbolStorageClass;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000404 if (getParser().parseAbsoluteExpression(SymbolStorageClass))
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000405 return true;
406
407 if (getLexer().isNot(AsmToken::EndOfStatement))
408 return TokError("unexpected token in directive");
409
410 Lex();
411 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
412 return false;
413}
414
415bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
416 int64_t Type;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000417 if (getParser().parseAbsoluteExpression(Type))
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000418 return true;
419
420 if (getLexer().isNot(AsmToken::EndOfStatement))
421 return TokError("unexpected token in directive");
422
423 Lex();
424 getStreamer().EmitCOFFSymbolType(Type);
425 return false;
426}
427
428bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
429 Lex();
430 getStreamer().EndCOFFSymbolDef();
431 return false;
432}
433
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000434bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
435 StringRef SymbolID;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000436 if (getParser().parseIdentifier(SymbolID))
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000437 return TokError("expected identifier in directive");
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000438
439 if (getLexer().isNot(AsmToken::EndOfStatement))
440 return TokError("unexpected token in directive");
441
442 MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
443
444 Lex();
445 getStreamer().EmitCOFFSecRel32(Symbol);
446 return false;
447}
448
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000449bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
450 StringRef SymbolID;
451 if (getParser().parseIdentifier(SymbolID))
452 return TokError("expected identifier in directive");
453
454 if (getLexer().isNot(AsmToken::EndOfStatement))
455 return TokError("unexpected token in directive");
456
457 MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
458
459 Lex();
460 getStreamer().EmitCOFFSectionIndex(Symbol);
461 return false;
462}
463
Rafael Espindola60ec3832013-11-19 19:52:52 +0000464/// ::= [ identifier [ identifier ] ]
465bool COFFAsmParser::parseCOMDATTypeAndAssoc(COFF::COMDATType &Type,
466 const MCSectionCOFF *&Assoc) {
467 StringRef TypeId = getTok().getIdentifier();
Nico Riecka37acf72013-07-06 12:13:10 +0000468
Rafael Espindola60ec3832013-11-19 19:52:52 +0000469 Type = StringSwitch<COFF::COMDATType>(TypeId)
470 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
471 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
472 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
473 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
474 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
475 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
476 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
477 .Default((COFF::COMDATType)0);
Nico Riecka37acf72013-07-06 12:13:10 +0000478
Rafael Espindola60ec3832013-11-19 19:52:52 +0000479 if (Type == 0)
480 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
Nico Riecka37acf72013-07-06 12:13:10 +0000481
Rafael Espindola60ec3832013-11-19 19:52:52 +0000482 Lex();
Nico Riecka37acf72013-07-06 12:13:10 +0000483
Nico Riecka37acf72013-07-06 12:13:10 +0000484 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
Nico Riecka37acf72013-07-06 12:13:10 +0000485 SMLoc Loc = getTok().getLoc();
Rafael Espindola60ec3832013-11-19 19:52:52 +0000486 StringRef AssocName;
Nico Riecka37acf72013-07-06 12:13:10 +0000487 if (ParseSectionName(AssocName))
488 return TokError("expected associated section name");
489
490 Assoc = static_cast<const MCSectionCOFF*>(
491 getContext().getCOFFSection(AssocName));
492 if (!Assoc)
493 return Error(Loc, "cannot associate unknown section '" + AssocName + "'");
Nico Riecka37acf72013-07-06 12:13:10 +0000494 if (!(Assoc->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT))
495 return Error(Loc, "associated section must be a COMDAT section");
496 if (Assoc->getSelection() == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
497 return Error(Loc, "associated section cannot be itself associative");
498 }
499
Rafael Espindola60ec3832013-11-19 19:52:52 +0000500 return false;
501}
502
503/// ParseDirectiveLinkOnce
504/// ::= .linkonce [ identifier [ identifier ] ]
505bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
506 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
507 const MCSectionCOFF *Assoc = 0;
508 if (getLexer().is(AsmToken::Identifier))
509 if (parseCOMDATTypeAndAssoc(Type, Assoc))
510 return true;
511
512 const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
513 getStreamer().getCurrentSection().first);
514
515
516 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
517 if (Assoc == Current)
518 return Error(Loc, "cannot associate a section with itself");
519 }
520
Nico Riecka37acf72013-07-06 12:13:10 +0000521 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
522 return Error(Loc, Twine("section '") + Current->getSectionName() +
523 "' is already linkonce");
524
525 Current->setSelection(Type, Assoc);
526
527 if (getLexer().isNot(AsmToken::EndOfStatement))
528 return TokError("unexpected token in directive");
529
530 return false;
531}
532
Charles Davisc7250fa2011-05-22 21:12:15 +0000533bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000534 StringRef SymbolID;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000535 if (getParser().parseIdentifier(SymbolID))
Charles Davisc7250fa2011-05-22 21:12:15 +0000536 return true;
537
Charles Davisc7250fa2011-05-22 21:12:15 +0000538 if (getLexer().isNot(AsmToken::EndOfStatement))
539 return TokError("unexpected token in directive");
540
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000541 MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
542
Charles Davisc7250fa2011-05-22 21:12:15 +0000543 Lex();
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000544 getStreamer().EmitWin64EHStartProc(Symbol);
Charles Davisc7250fa2011-05-22 21:12:15 +0000545 return false;
546}
547
548bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
549 Lex();
550 getStreamer().EmitWin64EHEndProc();
551 return false;
552}
553
554bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
555 Lex();
556 getStreamer().EmitWin64EHStartChained();
557 return false;
558}
559
560bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
561 Lex();
562 getStreamer().EmitWin64EHEndChained();
563 return false;
564}
565
566bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000567 StringRef SymbolID;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000568 if (getParser().parseIdentifier(SymbolID))
Charles Davisc7250fa2011-05-22 21:12:15 +0000569 return true;
570
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000571 if (getLexer().isNot(AsmToken::Comma))
572 return TokError("you must specify one or both of @unwind or @except");
573 Lex();
Charles Davisc7250fa2011-05-22 21:12:15 +0000574 bool unwind = false, except = false;
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000575 if (ParseAtUnwindOrAtExcept(unwind, except))
576 return true;
Charles Davisc7250fa2011-05-22 21:12:15 +0000577 if (getLexer().is(AsmToken::Comma)) {
578 Lex();
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000579 if (ParseAtUnwindOrAtExcept(unwind, except))
Charles Davisc7250fa2011-05-22 21:12:15 +0000580 return true;
581 }
582 if (getLexer().isNot(AsmToken::EndOfStatement))
583 return TokError("unexpected token in directive");
584
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000585 MCSymbol *handler = getContext().GetOrCreateSymbol(SymbolID);
586
Charles Davisc7250fa2011-05-22 21:12:15 +0000587 Lex();
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000588 getStreamer().EmitWin64EHHandler(handler, unwind, except);
Charles Davisc7250fa2011-05-22 21:12:15 +0000589 return false;
590}
591
592bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
593 Lex();
594 getStreamer().EmitWin64EHHandlerData();
595 return false;
596}
597
598bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
Charles Davis7f6176c2011-05-24 20:06:30 +0000599 unsigned Reg;
600 if (ParseSEHRegisterNumber(Reg))
601 return true;
602
603 if (getLexer().isNot(AsmToken::EndOfStatement))
604 return TokError("unexpected token in directive");
605
606 Lex();
607 getStreamer().EmitWin64EHPushReg(Reg);
608 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000609}
610
611bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
Charles Davis7f6176c2011-05-24 20:06:30 +0000612 unsigned Reg;
613 int64_t Off;
614 if (ParseSEHRegisterNumber(Reg))
615 return true;
Charles Davis2f6ecea2011-05-25 21:43:45 +0000616 if (getLexer().isNot(AsmToken::Comma))
617 return TokError("you must specify a stack pointer offset");
618
619 Lex();
Charles Davis7f6176c2011-05-24 20:06:30 +0000620 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000621 if (getParser().parseAbsoluteExpression(Off))
Charles Davis7f6176c2011-05-24 20:06:30 +0000622 return true;
623
624 if (Off & 0x0F)
625 return Error(startLoc, "offset is not a multiple of 16");
626
627 if (getLexer().isNot(AsmToken::EndOfStatement))
628 return TokError("unexpected token in directive");
629
630 Lex();
631 getStreamer().EmitWin64EHSetFrame(Reg, Off);
632 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000633}
634
Charles Davisd9eafdc2011-05-23 16:43:09 +0000635bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
636 int64_t Size;
Charles Davis7f6176c2011-05-24 20:06:30 +0000637 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000638 if (getParser().parseAbsoluteExpression(Size))
Charles Davisd9eafdc2011-05-23 16:43:09 +0000639 return true;
640
Charles Davis7f6176c2011-05-24 20:06:30 +0000641 if (Size & 7)
642 return Error(startLoc, "size is not a multiple of 8");
643
Charles Davisd9eafdc2011-05-23 16:43:09 +0000644 if (getLexer().isNot(AsmToken::EndOfStatement))
645 return TokError("unexpected token in directive");
646
647 Lex();
648 getStreamer().EmitWin64EHAllocStack(Size);
649 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000650}
651
652bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
Charles Davis7f6176c2011-05-24 20:06:30 +0000653 unsigned Reg;
654 int64_t Off;
655 if (ParseSEHRegisterNumber(Reg))
656 return true;
Charles Davis828b00c2011-05-25 04:51:25 +0000657 if (getLexer().isNot(AsmToken::Comma))
Charles Davis2f6ecea2011-05-25 21:43:45 +0000658 return TokError("you must specify an offset on the stack");
Charles Davis828b00c2011-05-25 04:51:25 +0000659
660 Lex();
Charles Davis7f6176c2011-05-24 20:06:30 +0000661 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000662 if (getParser().parseAbsoluteExpression(Off))
Charles Davis7f6176c2011-05-24 20:06:30 +0000663 return true;
664
665 if (Off & 7)
666 return Error(startLoc, "size is not a multiple of 8");
667
668 if (getLexer().isNot(AsmToken::EndOfStatement))
669 return TokError("unexpected token in directive");
670
671 Lex();
672 // FIXME: Err on %xmm* registers
673 getStreamer().EmitWin64EHSaveReg(Reg, Off);
674 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000675}
676
Charles Davis7f6176c2011-05-24 20:06:30 +0000677// FIXME: This method is inherently x86-specific. It should really be in the
678// x86 backend.
Charles Davisc7250fa2011-05-22 21:12:15 +0000679bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
Charles Davis7f6176c2011-05-24 20:06:30 +0000680 unsigned Reg;
681 int64_t Off;
682 if (ParseSEHRegisterNumber(Reg))
683 return true;
Charles Davis828b00c2011-05-25 04:51:25 +0000684 if (getLexer().isNot(AsmToken::Comma))
Charles Davis2f6ecea2011-05-25 21:43:45 +0000685 return TokError("you must specify an offset on the stack");
Charles Davis828b00c2011-05-25 04:51:25 +0000686
687 Lex();
Charles Davis7f6176c2011-05-24 20:06:30 +0000688 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000689 if (getParser().parseAbsoluteExpression(Off))
Charles Davis7f6176c2011-05-24 20:06:30 +0000690 return true;
691
692 if (getLexer().isNot(AsmToken::EndOfStatement))
693 return TokError("unexpected token in directive");
694
695 if (Off & 0x0F)
696 return Error(startLoc, "offset is not a multiple of 16");
697
698 Lex();
699 // FIXME: Err on non-%xmm* registers
700 getStreamer().EmitWin64EHSaveXMM(Reg, Off);
701 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000702}
703
Charles Davisd9eafdc2011-05-23 16:43:09 +0000704bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
Charles Davisb0c4f392011-05-25 04:08:15 +0000705 bool Code = false;
Charles Davisd9eafdc2011-05-23 16:43:09 +0000706 StringRef CodeID;
Charles Davisb0c4f392011-05-25 04:08:15 +0000707 if (getLexer().is(AsmToken::At)) {
708 SMLoc startLoc = getLexer().getLoc();
709 Lex();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000710 if (!getParser().parseIdentifier(CodeID)) {
Charles Davisb0c4f392011-05-25 04:08:15 +0000711 if (CodeID != "code")
712 return Error(startLoc, "expected @code");
713 Code = true;
714 }
Charles Davisd9eafdc2011-05-23 16:43:09 +0000715 }
716
717 if (getLexer().isNot(AsmToken::EndOfStatement))
718 return TokError("unexpected token in directive");
719
720 Lex();
721 getStreamer().EmitWin64EHPushFrame(Code);
722 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000723}
724
725bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
726 Lex();
727 getStreamer().EmitWin64EHEndProlog();
728 return false;
729}
730
731bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
732 StringRef identifier;
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000733 if (getLexer().isNot(AsmToken::At))
734 return TokError("a handler attribute must begin with '@'");
Charles Davisc7250fa2011-05-22 21:12:15 +0000735 SMLoc startLoc = getLexer().getLoc();
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000736 Lex();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000737 if (getParser().parseIdentifier(identifier))
Charles Davisc7250fa2011-05-22 21:12:15 +0000738 return Error(startLoc, "expected @unwind or @except");
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000739 if (identifier == "unwind")
Charles Davisc7250fa2011-05-22 21:12:15 +0000740 unwind = true;
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000741 else if (identifier == "except")
Charles Davisc7250fa2011-05-22 21:12:15 +0000742 except = true;
743 else
744 return Error(startLoc, "expected @unwind or @except");
745 return false;
746}
747
Charles Davis7f6176c2011-05-24 20:06:30 +0000748bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
Charles Davis7f6176c2011-05-24 20:06:30 +0000749 SMLoc startLoc = getLexer().getLoc();
Charles Davis828b00c2011-05-25 04:51:25 +0000750 if (getLexer().is(AsmToken::Percent)) {
Bill Wendlingbc07a892013-06-18 07:20:20 +0000751 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
Charles Davis7f6176c2011-05-24 20:06:30 +0000752 SMLoc endLoc;
753 unsigned LLVMRegNo;
754 if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
Charles Davis828b00c2011-05-25 04:51:25 +0000755 return true;
Charles Davis7f6176c2011-05-24 20:06:30 +0000756
Evan Chengd60fa58b2011-07-18 20:57:22 +0000757#if 0
758 // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
759 // violation so this validation code is disabled.
760
Charles Davis7f6176c2011-05-24 20:06:30 +0000761 // Check that this is a non-volatile register.
Evan Chenga83b37a2011-07-15 02:09:41 +0000762 const unsigned *NVRegs = TAI.getCalleeSavedRegs();
Charles Davis7f6176c2011-05-24 20:06:30 +0000763 unsigned i;
764 for (i = 0; NVRegs[i] != 0; ++i)
765 if (NVRegs[i] == LLVMRegNo)
766 break;
767 if (NVRegs[i] == 0)
768 return Error(startLoc, "expected non-volatile register");
Evan Chengd60fa58b2011-07-18 20:57:22 +0000769#endif
Charles Davis7f6176c2011-05-24 20:06:30 +0000770
Bill Wendlingbc07a892013-06-18 07:20:20 +0000771 int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
Charles Davis7f6176c2011-05-24 20:06:30 +0000772 if (SEHRegNo < 0)
773 return Error(startLoc,"register can't be represented in SEH unwind info");
774 RegNo = SEHRegNo;
775 }
Charles Davis828b00c2011-05-25 04:51:25 +0000776 else {
777 int64_t n;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000778 if (getParser().parseAbsoluteExpression(n))
Charles Davis828b00c2011-05-25 04:51:25 +0000779 return true;
780 if (n > 15)
781 return Error(startLoc, "register number is too high");
Charles Davis7f6176c2011-05-24 20:06:30 +0000782 RegNo = n;
Charles Davis828b00c2011-05-25 04:51:25 +0000783 }
Charles Davis7f6176c2011-05-24 20:06:30 +0000784
Charles Davis7f6176c2011-05-24 20:06:30 +0000785 return false;
786}
787
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000788namespace llvm {
789
790MCAsmParserExtension *createCOFFAsmParser() {
791 return new COFFAsmParser;
792}
793
794}