blob: f09bce005d6a7b8500d5e7ffa85553f27bc5df6c [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"
Saleem Abdulrasoolbdbc0082014-06-22 22:25:01 +000016#include "llvm/MC/MCObjectFileInfo.h"
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000017#include "llvm/MC/MCParser/MCAsmLexer.h"
Evan Chengd60fa58b2011-07-18 20:57:22 +000018#include "llvm/MC/MCRegisterInfo.h"
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000019#include "llvm/MC/MCSectionCOFF.h"
20#include "llvm/MC/MCStreamer.h"
Evan Cheng11424442011-07-26 00:24:13 +000021#include "llvm/MC/MCTargetAsmParser.h"
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000022#include "llvm/Support/COFF.h"
23using namespace llvm;
24
25namespace {
26
27class COFFAsmParser : public MCAsmParserExtension {
Eli Bendersky29b9f472013-01-16 00:50:52 +000028 template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
Jim Grosbachd2037eb2013-02-20 22:21:35 +000029 void addDirectiveHandler(StringRef Directive) {
Eli Bendersky29b9f472013-01-16 00:50:52 +000030 MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
31 this, HandleDirective<COFFAsmParser, HandlerMethod>);
Jim Grosbachd2037eb2013-02-20 22:21:35 +000032 getParser().addDirectiveHandler(Directive, Handler);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000033 }
34
35 bool ParseSectionSwitch(StringRef Section,
36 unsigned Characteristics,
37 SectionKind Kind);
38
Rafael Espindola60ec3832013-11-19 19:52:52 +000039 bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
40 SectionKind Kind, StringRef COMDATSymName,
Rafael Espindola0766ae02014-06-06 19:26:12 +000041 COFF::COMDATType Type);
Rafael Espindola60ec3832013-11-19 19:52:52 +000042
Nico Rieck1558c5a2013-07-04 21:32:07 +000043 bool ParseSectionName(StringRef &SectionName);
44 bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags);
45
Craig Topper59be68f2014-03-08 07:14:16 +000046 void Initialize(MCAsmParser &Parser) override {
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000047 // Call the base implementation.
48 MCAsmParserExtension::Initialize(Parser);
49
Jim Grosbachd2037eb2013-02-20 22:21:35 +000050 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
51 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
52 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
Nico Rieck1558c5a2013-07-04 21:32:07 +000053 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000054 addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
55 addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
56 addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
57 addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
58 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +000059 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
David Majnemer4eecd302015-05-30 04:56:02 +000060 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
Nico Riecka37acf72013-07-06 12:13:10 +000061 addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
Charles Davisc7250fa2011-05-22 21:12:15 +000062
63 // Win64 EH directives.
Jim Grosbachd2037eb2013-02-20 22:21:35 +000064 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
Charles Davisc7250fa2011-05-22 21:12:15 +000065 ".seh_proc");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000066 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
Charles Davisc7250fa2011-05-22 21:12:15 +000067 ".seh_endproc");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000068 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
Charles Davisc7250fa2011-05-22 21:12:15 +000069 ".seh_startchained");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000070 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
Charles Davisc7250fa2011-05-22 21:12:15 +000071 ".seh_endchained");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000072 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
Charles Davisc7250fa2011-05-22 21:12:15 +000073 ".seh_handler");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000074 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
Charles Davisc7250fa2011-05-22 21:12:15 +000075 ".seh_handlerdata");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000076 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
Charles Davisc7250fa2011-05-22 21:12:15 +000077 ".seh_pushreg");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000078 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
Charles Davisc7250fa2011-05-22 21:12:15 +000079 ".seh_setframe");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000080 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
Charles Davisc7250fa2011-05-22 21:12:15 +000081 ".seh_stackalloc");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000082 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
Charles Davisc7250fa2011-05-22 21:12:15 +000083 ".seh_savereg");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000084 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
Charles Davisc7250fa2011-05-22 21:12:15 +000085 ".seh_savexmm");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000086 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
Charles Davisc7250fa2011-05-22 21:12:15 +000087 ".seh_pushframe");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000088 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
Charles Davisc7250fa2011-05-22 21:12:15 +000089 ".seh_endprologue");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000090 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000091 }
92
93 bool ParseSectionDirectiveText(StringRef, SMLoc) {
94 return ParseSectionSwitch(".text",
95 COFF::IMAGE_SCN_CNT_CODE
96 | COFF::IMAGE_SCN_MEM_EXECUTE
97 | COFF::IMAGE_SCN_MEM_READ,
98 SectionKind::getText());
99 }
100 bool ParseSectionDirectiveData(StringRef, SMLoc) {
101 return ParseSectionSwitch(".data",
102 COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
103 | COFF::IMAGE_SCN_MEM_READ
104 | COFF::IMAGE_SCN_MEM_WRITE,
105 SectionKind::getDataRel());
106 }
107 bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
108 return ParseSectionSwitch(".bss",
109 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
110 | COFF::IMAGE_SCN_MEM_READ
111 | COFF::IMAGE_SCN_MEM_WRITE,
112 SectionKind::getBSS());
113 }
114
Nico Rieck1558c5a2013-07-04 21:32:07 +0000115 bool ParseDirectiveSection(StringRef, SMLoc);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000116 bool ParseDirectiveDef(StringRef, SMLoc);
117 bool ParseDirectiveScl(StringRef, SMLoc);
118 bool ParseDirectiveType(StringRef, SMLoc);
119 bool ParseDirectiveEndef(StringRef, SMLoc);
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000120 bool ParseDirectiveSecRel32(StringRef, SMLoc);
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000121 bool ParseDirectiveSecIdx(StringRef, SMLoc);
David Majnemer4eecd302015-05-30 04:56:02 +0000122 bool ParseDirectiveSafeSEH(StringRef, SMLoc);
Rafael Espindola0766ae02014-06-06 19:26:12 +0000123 bool parseCOMDATType(COFF::COMDATType &Type);
Nico Riecka37acf72013-07-06 12:13:10 +0000124 bool ParseDirectiveLinkOnce(StringRef, SMLoc);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000125
Charles Davisc7250fa2011-05-22 21:12:15 +0000126 // Win64 EH directives.
127 bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
128 bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
129 bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
130 bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
131 bool ParseSEHDirectiveHandler(StringRef, SMLoc);
132 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
Charles Davis7f6176c2011-05-24 20:06:30 +0000133 bool ParseSEHDirectivePushReg(StringRef, SMLoc);
134 bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
135 bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
136 bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
137 bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
138 bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
Charles Davisc7250fa2011-05-22 21:12:15 +0000139 bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
140
141 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
Charles Davis7f6176c2011-05-24 20:06:30 +0000142 bool ParseSEHRegisterNumber(unsigned &RegNo);
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000143 bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000144public:
145 COFFAsmParser() {}
146};
147
148} // end annonomous namespace.
149
Nico Rieck1558c5a2013-07-04 21:32:07 +0000150static SectionKind computeSectionKind(unsigned Flags) {
151 if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
152 return SectionKind::getText();
153 if (Flags & COFF::IMAGE_SCN_MEM_READ &&
154 (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
155 return SectionKind::getReadOnly();
156 return SectionKind::getDataRel();
157}
158
159bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
160 enum {
161 None = 0,
162 Alloc = 1 << 0,
163 Code = 1 << 1,
164 Load = 1 << 2,
165 InitData = 1 << 3,
166 Shared = 1 << 4,
167 NoLoad = 1 << 5,
168 NoRead = 1 << 6,
169 NoWrite = 1 << 7
170 };
171
172 bool ReadOnlyRemoved = false;
173 unsigned SecFlags = None;
174
David Majnemerbee5f752014-07-04 23:15:28 +0000175 for (char FlagChar : FlagsString) {
176 switch (FlagChar) {
Nico Rieck1558c5a2013-07-04 21:32:07 +0000177 case 'a':
178 // Ignored.
179 break;
180
181 case 'b': // bss section
182 SecFlags |= Alloc;
183 if (SecFlags & InitData)
184 return TokError("conflicting section flags 'b' and 'd'.");
185 SecFlags &= ~Load;
186 break;
187
188 case 'd': // data section
189 SecFlags |= InitData;
190 if (SecFlags & Alloc)
191 return TokError("conflicting section flags 'b' and 'd'.");
192 SecFlags &= ~NoWrite;
193 if ((SecFlags & NoLoad) == 0)
194 SecFlags |= Load;
195 break;
196
197 case 'n': // section is not loaded
198 SecFlags |= NoLoad;
199 SecFlags &= ~Load;
200 break;
201
202 case 'r': // read-only
203 ReadOnlyRemoved = false;
204 SecFlags |= NoWrite;
205 if ((SecFlags & Code) == 0)
206 SecFlags |= InitData;
207 if ((SecFlags & NoLoad) == 0)
208 SecFlags |= Load;
209 break;
210
211 case 's': // shared section
212 SecFlags |= Shared | InitData;
213 SecFlags &= ~NoWrite;
214 if ((SecFlags & NoLoad) == 0)
215 SecFlags |= Load;
216 break;
217
218 case 'w': // writable
219 SecFlags &= ~NoWrite;
220 ReadOnlyRemoved = true;
221 break;
222
223 case 'x': // executable section
224 SecFlags |= Code;
225 if ((SecFlags & NoLoad) == 0)
226 SecFlags |= Load;
227 if (!ReadOnlyRemoved)
228 SecFlags |= NoWrite;
229 break;
230
231 case 'y': // not readable
232 SecFlags |= NoRead | NoWrite;
233 break;
234
235 default:
236 return TokError("unknown flag");
237 }
238 }
239
240 *Flags = 0;
241
242 if (SecFlags == None)
243 SecFlags = InitData;
244
245 if (SecFlags & Code)
246 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
247 if (SecFlags & InitData)
248 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
249 if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
250 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
251 if (SecFlags & NoLoad)
252 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
253 if ((SecFlags & NoRead) == 0)
254 *Flags |= COFF::IMAGE_SCN_MEM_READ;
255 if ((SecFlags & NoWrite) == 0)
256 *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
257 if (SecFlags & Shared)
258 *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
259
260 return false;
261}
262
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000263/// ParseDirectiveSymbolAttribute
264/// ::= { ".weak", ... } [ identifier ( , identifier )* ]
265bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
266 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
267 .Case(".weak", MCSA_Weak)
268 .Default(MCSA_Invalid);
269 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
270 if (getLexer().isNot(AsmToken::EndOfStatement)) {
271 for (;;) {
272 StringRef Name;
273
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000274 if (getParser().parseIdentifier(Name))
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000275 return TokError("expected identifier in directive");
276
Jim Grosbach6f482002015-05-18 18:43:14 +0000277 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000278
279 getStreamer().EmitSymbolAttribute(Sym, Attr);
280
281 if (getLexer().is(AsmToken::EndOfStatement))
282 break;
283
284 if (getLexer().isNot(AsmToken::Comma))
285 return TokError("unexpected token in directive");
286 Lex();
287 }
288 }
289
290 Lex();
291 return false;
292}
293
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000294bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
295 unsigned Characteristics,
296 SectionKind Kind) {
David Majnemerc57d0382014-06-27 17:19:44 +0000297 return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
Rafael Espindola60ec3832013-11-19 19:52:52 +0000298}
299
300bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
301 unsigned Characteristics,
302 SectionKind Kind,
303 StringRef COMDATSymName,
Rafael Espindola0766ae02014-06-06 19:26:12 +0000304 COFF::COMDATType Type) {
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 Espindola0766ae02014-06-06 19:26:12 +0000310 Section, Characteristics, Kind, COMDATSymName, Type));
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
David Majnemerc57d0382014-06-27 17:19:44 +0000361 COFF::COMDATType Type = (COFF::COMDATType)0;
Rafael Espindola60ec3832013-11-19 19:52:52 +0000362 StringRef COMDATSymName;
363 if (getLexer().is(AsmToken::Comma)) {
Aaron Ballman3182ee92015-06-09 12:03:46 +0000364 Type = COFF::IMAGE_COMDAT_SELECT_ANY;
Rafael Espindola60ec3832013-11-19 19:52:52 +0000365 Lex();
366
367 Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
368
Reid Kleckner21aedc42014-08-11 18:34:43 +0000369 if (!getLexer().is(AsmToken::Identifier))
370 return TokError("expected comdat type such as 'discard' or 'largest' "
371 "after protection bits");
372
Rafael Espindola0766ae02014-06-06 19:26:12 +0000373 if (parseCOMDATType(Type))
Rafael Espindola60ec3832013-11-19 19:52:52 +0000374 return true;
375
376 if (getLexer().isNot(AsmToken::Comma))
377 return TokError("expected comma in directive");
378 Lex();
379
380 if (getParser().parseIdentifier(COMDATSymName))
381 return TokError("expected identifier in directive");
382 }
383
Nico Rieck1558c5a2013-07-04 21:32:07 +0000384 if (getLexer().isNot(AsmToken::EndOfStatement))
385 return TokError("unexpected token in directive");
386
387 SectionKind Kind = computeSectionKind(Flags);
Saleem Abdulrasoolbdbc0082014-06-22 22:25:01 +0000388 if (Kind.isText()) {
389 const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
390 if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
391 Flags |= COFF::IMAGE_SCN_MEM_16BIT;
392 }
Rafael Espindola0766ae02014-06-06 19:26:12 +0000393 ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
Nico Rieck1558c5a2013-07-04 21:32:07 +0000394 return false;
395}
396
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000397bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
398 StringRef SymbolName;
399
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000400 if (getParser().parseIdentifier(SymbolName))
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000401 return TokError("expected identifier in directive");
402
Jim Grosbach6f482002015-05-18 18:43:14 +0000403 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000404
405 getStreamer().BeginCOFFSymbolDef(Sym);
406
407 Lex();
408 return false;
409}
410
411bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
412 int64_t SymbolStorageClass;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000413 if (getParser().parseAbsoluteExpression(SymbolStorageClass))
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000414 return true;
415
416 if (getLexer().isNot(AsmToken::EndOfStatement))
417 return TokError("unexpected token in directive");
418
419 Lex();
420 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
421 return false;
422}
423
424bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
425 int64_t Type;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000426 if (getParser().parseAbsoluteExpression(Type))
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000427 return true;
428
429 if (getLexer().isNot(AsmToken::EndOfStatement))
430 return TokError("unexpected token in directive");
431
432 Lex();
433 getStreamer().EmitCOFFSymbolType(Type);
434 return false;
435}
436
437bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
438 Lex();
439 getStreamer().EndCOFFSymbolDef();
440 return false;
441}
442
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000443bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
444 StringRef SymbolID;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000445 if (getParser().parseIdentifier(SymbolID))
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000446 return TokError("expected identifier in directive");
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000447
448 if (getLexer().isNot(AsmToken::EndOfStatement))
449 return TokError("unexpected token in directive");
450
Jim Grosbach6f482002015-05-18 18:43:14 +0000451 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000452
453 Lex();
454 getStreamer().EmitCOFFSecRel32(Symbol);
455 return false;
456}
457
David Majnemer4eecd302015-05-30 04:56:02 +0000458bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
459 StringRef SymbolID;
460 if (getParser().parseIdentifier(SymbolID))
461 return TokError("expected identifier in directive");
462
463 if (getLexer().isNot(AsmToken::EndOfStatement))
464 return TokError("unexpected token in directive");
465
466 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
467
468 Lex();
469 getStreamer().EmitCOFFSafeSEH(Symbol);
470 return false;
471}
472
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000473bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
474 StringRef SymbolID;
475 if (getParser().parseIdentifier(SymbolID))
476 return TokError("expected identifier in directive");
477
478 if (getLexer().isNot(AsmToken::EndOfStatement))
479 return TokError("unexpected token in directive");
480
Jim Grosbach6f482002015-05-18 18:43:14 +0000481 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000482
483 Lex();
484 getStreamer().EmitCOFFSectionIndex(Symbol);
485 return false;
486}
487
Rafael Espindola0766ae02014-06-06 19:26:12 +0000488/// ::= [ identifier ]
489bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
Rafael Espindola60ec3832013-11-19 19:52:52 +0000490 StringRef TypeId = getTok().getIdentifier();
Nico Riecka37acf72013-07-06 12:13:10 +0000491
Rafael Espindola60ec3832013-11-19 19:52:52 +0000492 Type = StringSwitch<COFF::COMDATType>(TypeId)
493 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
494 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
495 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
496 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
497 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
498 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
499 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
500 .Default((COFF::COMDATType)0);
Nico Riecka37acf72013-07-06 12:13:10 +0000501
Rafael Espindola60ec3832013-11-19 19:52:52 +0000502 if (Type == 0)
503 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
Nico Riecka37acf72013-07-06 12:13:10 +0000504
Rafael Espindola60ec3832013-11-19 19:52:52 +0000505 Lex();
Nico Riecka37acf72013-07-06 12:13:10 +0000506
Rafael Espindola60ec3832013-11-19 19:52:52 +0000507 return false;
508}
509
510/// ParseDirectiveLinkOnce
Rafael Espindola0766ae02014-06-06 19:26:12 +0000511/// ::= .linkonce [ identifier ]
Rafael Espindola60ec3832013-11-19 19:52:52 +0000512bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
513 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
Rafael Espindola60ec3832013-11-19 19:52:52 +0000514 if (getLexer().is(AsmToken::Identifier))
Rafael Espindola0766ae02014-06-06 19:26:12 +0000515 if (parseCOMDATType(Type))
Rafael Espindola60ec3832013-11-19 19:52:52 +0000516 return true;
517
518 const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
519 getStreamer().getCurrentSection().first);
520
Rafael Espindola0766ae02014-06-06 19:26:12 +0000521 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
522 return Error(Loc, "cannot make section associative with .linkonce");
Rafael Espindola60ec3832013-11-19 19:52:52 +0000523
Nico Riecka37acf72013-07-06 12:13:10 +0000524 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
525 return Error(Loc, Twine("section '") + Current->getSectionName() +
526 "' is already linkonce");
527
Rafael Espindola0766ae02014-06-06 19:26:12 +0000528 Current->setSelection(Type);
Nico Riecka37acf72013-07-06 12:13:10 +0000529
530 if (getLexer().isNot(AsmToken::EndOfStatement))
531 return TokError("unexpected token in directive");
532
533 return false;
534}
535
Charles Davisc7250fa2011-05-22 21:12:15 +0000536bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000537 StringRef SymbolID;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000538 if (getParser().parseIdentifier(SymbolID))
Charles Davisc7250fa2011-05-22 21:12:15 +0000539 return true;
540
Charles Davisc7250fa2011-05-22 21:12:15 +0000541 if (getLexer().isNot(AsmToken::EndOfStatement))
542 return TokError("unexpected token in directive");
543
Jim Grosbach6f482002015-05-18 18:43:14 +0000544 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000545
Charles Davisc7250fa2011-05-22 21:12:15 +0000546 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000547 getStreamer().EmitWinCFIStartProc(Symbol);
Charles Davisc7250fa2011-05-22 21:12:15 +0000548 return false;
549}
550
551bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
552 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000553 getStreamer().EmitWinCFIEndProc();
Charles Davisc7250fa2011-05-22 21:12:15 +0000554 return false;
555}
556
557bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
558 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000559 getStreamer().EmitWinCFIStartChained();
Charles Davisc7250fa2011-05-22 21:12:15 +0000560 return false;
561}
562
563bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
564 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000565 getStreamer().EmitWinCFIEndChained();
Charles Davisc7250fa2011-05-22 21:12:15 +0000566 return false;
567}
568
569bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000570 StringRef SymbolID;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000571 if (getParser().parseIdentifier(SymbolID))
Charles Davisc7250fa2011-05-22 21:12:15 +0000572 return true;
573
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000574 if (getLexer().isNot(AsmToken::Comma))
575 return TokError("you must specify one or both of @unwind or @except");
576 Lex();
Charles Davisc7250fa2011-05-22 21:12:15 +0000577 bool unwind = false, except = false;
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000578 if (ParseAtUnwindOrAtExcept(unwind, except))
579 return true;
Charles Davisc7250fa2011-05-22 21:12:15 +0000580 if (getLexer().is(AsmToken::Comma)) {
581 Lex();
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000582 if (ParseAtUnwindOrAtExcept(unwind, except))
Charles Davisc7250fa2011-05-22 21:12:15 +0000583 return true;
584 }
585 if (getLexer().isNot(AsmToken::EndOfStatement))
586 return TokError("unexpected token in directive");
587
Jim Grosbach6f482002015-05-18 18:43:14 +0000588 MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000589
Charles Davisc7250fa2011-05-22 21:12:15 +0000590 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000591 getStreamer().EmitWinEHHandler(handler, unwind, except);
Charles Davisc7250fa2011-05-22 21:12:15 +0000592 return false;
593}
594
595bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
596 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000597 getStreamer().EmitWinEHHandlerData();
Charles Davisc7250fa2011-05-22 21:12:15 +0000598 return false;
599}
600
601bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
Michael Ilseman5be22a12014-12-12 21:48:03 +0000602 unsigned Reg = 0;
Charles Davis7f6176c2011-05-24 20:06:30 +0000603 if (ParseSEHRegisterNumber(Reg))
604 return true;
605
606 if (getLexer().isNot(AsmToken::EndOfStatement))
607 return TokError("unexpected token in directive");
608
609 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000610 getStreamer().EmitWinCFIPushReg(Reg);
Charles Davis7f6176c2011-05-24 20:06:30 +0000611 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000612}
613
614bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
Michael Ilseman5be22a12014-12-12 21:48:03 +0000615 unsigned Reg = 0;
Charles Davis7f6176c2011-05-24 20:06:30 +0000616 int64_t Off;
617 if (ParseSEHRegisterNumber(Reg))
618 return true;
Charles Davis2f6ecea2011-05-25 21:43:45 +0000619 if (getLexer().isNot(AsmToken::Comma))
620 return TokError("you must specify a stack pointer offset");
621
622 Lex();
Charles Davis7f6176c2011-05-24 20:06:30 +0000623 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000624 if (getParser().parseAbsoluteExpression(Off))
Charles Davis7f6176c2011-05-24 20:06:30 +0000625 return true;
626
627 if (Off & 0x0F)
628 return Error(startLoc, "offset is not a multiple of 16");
629
630 if (getLexer().isNot(AsmToken::EndOfStatement))
631 return TokError("unexpected token in directive");
632
633 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000634 getStreamer().EmitWinCFISetFrame(Reg, Off);
Charles Davis7f6176c2011-05-24 20:06:30 +0000635 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000636}
637
Charles Davisd9eafdc2011-05-23 16:43:09 +0000638bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
639 int64_t Size;
Charles Davis7f6176c2011-05-24 20:06:30 +0000640 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000641 if (getParser().parseAbsoluteExpression(Size))
Charles Davisd9eafdc2011-05-23 16:43:09 +0000642 return true;
643
Charles Davis7f6176c2011-05-24 20:06:30 +0000644 if (Size & 7)
645 return Error(startLoc, "size is not a multiple of 8");
646
Charles Davisd9eafdc2011-05-23 16:43:09 +0000647 if (getLexer().isNot(AsmToken::EndOfStatement))
648 return TokError("unexpected token in directive");
649
650 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000651 getStreamer().EmitWinCFIAllocStack(Size);
Charles Davisd9eafdc2011-05-23 16:43:09 +0000652 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000653}
654
655bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
Michael Ilseman5be22a12014-12-12 21:48:03 +0000656 unsigned Reg = 0;
Charles Davis7f6176c2011-05-24 20:06:30 +0000657 int64_t Off;
658 if (ParseSEHRegisterNumber(Reg))
659 return true;
Charles Davis828b00c2011-05-25 04:51:25 +0000660 if (getLexer().isNot(AsmToken::Comma))
Charles Davis2f6ecea2011-05-25 21:43:45 +0000661 return TokError("you must specify an offset on the stack");
Charles Davis828b00c2011-05-25 04:51:25 +0000662
663 Lex();
Charles Davis7f6176c2011-05-24 20:06:30 +0000664 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000665 if (getParser().parseAbsoluteExpression(Off))
Charles Davis7f6176c2011-05-24 20:06:30 +0000666 return true;
667
668 if (Off & 7)
669 return Error(startLoc, "size is not a multiple of 8");
670
671 if (getLexer().isNot(AsmToken::EndOfStatement))
672 return TokError("unexpected token in directive");
673
674 Lex();
675 // FIXME: Err on %xmm* registers
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000676 getStreamer().EmitWinCFISaveReg(Reg, Off);
Charles Davis7f6176c2011-05-24 20:06:30 +0000677 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000678}
679
Charles Davis7f6176c2011-05-24 20:06:30 +0000680// FIXME: This method is inherently x86-specific. It should really be in the
681// x86 backend.
Charles Davisc7250fa2011-05-22 21:12:15 +0000682bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
Michael Ilseman5be22a12014-12-12 21:48:03 +0000683 unsigned Reg = 0;
Charles Davis7f6176c2011-05-24 20:06:30 +0000684 int64_t Off;
685 if (ParseSEHRegisterNumber(Reg))
686 return true;
Charles Davis828b00c2011-05-25 04:51:25 +0000687 if (getLexer().isNot(AsmToken::Comma))
Charles Davis2f6ecea2011-05-25 21:43:45 +0000688 return TokError("you must specify an offset on the stack");
Charles Davis828b00c2011-05-25 04:51:25 +0000689
690 Lex();
Charles Davis7f6176c2011-05-24 20:06:30 +0000691 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000692 if (getParser().parseAbsoluteExpression(Off))
Charles Davis7f6176c2011-05-24 20:06:30 +0000693 return true;
694
695 if (getLexer().isNot(AsmToken::EndOfStatement))
696 return TokError("unexpected token in directive");
697
698 if (Off & 0x0F)
699 return Error(startLoc, "offset is not a multiple of 16");
700
701 Lex();
702 // FIXME: Err on non-%xmm* registers
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000703 getStreamer().EmitWinCFISaveXMM(Reg, Off);
Charles Davis7f6176c2011-05-24 20:06:30 +0000704 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000705}
706
Charles Davisd9eafdc2011-05-23 16:43:09 +0000707bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
Charles Davisb0c4f392011-05-25 04:08:15 +0000708 bool Code = false;
Charles Davisd9eafdc2011-05-23 16:43:09 +0000709 StringRef CodeID;
Charles Davisb0c4f392011-05-25 04:08:15 +0000710 if (getLexer().is(AsmToken::At)) {
711 SMLoc startLoc = getLexer().getLoc();
712 Lex();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000713 if (!getParser().parseIdentifier(CodeID)) {
Charles Davisb0c4f392011-05-25 04:08:15 +0000714 if (CodeID != "code")
715 return Error(startLoc, "expected @code");
716 Code = true;
717 }
Charles Davisd9eafdc2011-05-23 16:43:09 +0000718 }
719
720 if (getLexer().isNot(AsmToken::EndOfStatement))
721 return TokError("unexpected token in directive");
722
723 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000724 getStreamer().EmitWinCFIPushFrame(Code);
Charles Davisd9eafdc2011-05-23 16:43:09 +0000725 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000726}
727
728bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
729 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000730 getStreamer().EmitWinCFIEndProlog();
Charles Davisc7250fa2011-05-22 21:12:15 +0000731 return false;
732}
733
734bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
735 StringRef identifier;
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000736 if (getLexer().isNot(AsmToken::At))
737 return TokError("a handler attribute must begin with '@'");
Charles Davisc7250fa2011-05-22 21:12:15 +0000738 SMLoc startLoc = getLexer().getLoc();
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000739 Lex();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000740 if (getParser().parseIdentifier(identifier))
Charles Davisc7250fa2011-05-22 21:12:15 +0000741 return Error(startLoc, "expected @unwind or @except");
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000742 if (identifier == "unwind")
Charles Davisc7250fa2011-05-22 21:12:15 +0000743 unwind = true;
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000744 else if (identifier == "except")
Charles Davisc7250fa2011-05-22 21:12:15 +0000745 except = true;
746 else
747 return Error(startLoc, "expected @unwind or @except");
748 return false;
749}
750
Charles Davis7f6176c2011-05-24 20:06:30 +0000751bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
Charles Davis7f6176c2011-05-24 20:06:30 +0000752 SMLoc startLoc = getLexer().getLoc();
Charles Davis828b00c2011-05-25 04:51:25 +0000753 if (getLexer().is(AsmToken::Percent)) {
Bill Wendlingbc07a892013-06-18 07:20:20 +0000754 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
Charles Davis7f6176c2011-05-24 20:06:30 +0000755 SMLoc endLoc;
756 unsigned LLVMRegNo;
757 if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
Charles Davis828b00c2011-05-25 04:51:25 +0000758 return true;
Charles Davis7f6176c2011-05-24 20:06:30 +0000759
Evan Chengd60fa58b2011-07-18 20:57:22 +0000760#if 0
761 // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
762 // violation so this validation code is disabled.
763
Charles Davis7f6176c2011-05-24 20:06:30 +0000764 // Check that this is a non-volatile register.
Evan Chenga83b37a2011-07-15 02:09:41 +0000765 const unsigned *NVRegs = TAI.getCalleeSavedRegs();
Charles Davis7f6176c2011-05-24 20:06:30 +0000766 unsigned i;
767 for (i = 0; NVRegs[i] != 0; ++i)
768 if (NVRegs[i] == LLVMRegNo)
769 break;
770 if (NVRegs[i] == 0)
771 return Error(startLoc, "expected non-volatile register");
Evan Chengd60fa58b2011-07-18 20:57:22 +0000772#endif
Charles Davis7f6176c2011-05-24 20:06:30 +0000773
Bill Wendlingbc07a892013-06-18 07:20:20 +0000774 int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
Charles Davis7f6176c2011-05-24 20:06:30 +0000775 if (SEHRegNo < 0)
776 return Error(startLoc,"register can't be represented in SEH unwind info");
777 RegNo = SEHRegNo;
778 }
Charles Davis828b00c2011-05-25 04:51:25 +0000779 else {
780 int64_t n;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000781 if (getParser().parseAbsoluteExpression(n))
Charles Davis828b00c2011-05-25 04:51:25 +0000782 return true;
783 if (n > 15)
784 return Error(startLoc, "register number is too high");
Charles Davis7f6176c2011-05-24 20:06:30 +0000785 RegNo = n;
Charles Davis828b00c2011-05-25 04:51:25 +0000786 }
Charles Davis7f6176c2011-05-24 20:06:30 +0000787
Charles Davis7f6176c2011-05-24 20:06:30 +0000788 return false;
789}
790
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000791namespace llvm {
792
793MCAsmParserExtension *createCOFFAsmParser() {
794 return new COFFAsmParser;
795}
796
797}