blob: a4b2b195f7100fdcb1ec7e859c9c0ad3b5305154 [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) {
Rafael Espindola449711c2015-11-18 06:02:15 +0000101 return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
102 COFF::IMAGE_SCN_MEM_READ |
103 COFF::IMAGE_SCN_MEM_WRITE,
104 SectionKind::getData());
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000105 }
106 bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
107 return ParseSectionSwitch(".bss",
108 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
109 | COFF::IMAGE_SCN_MEM_READ
110 | COFF::IMAGE_SCN_MEM_WRITE,
111 SectionKind::getBSS());
112 }
113
Nico Rieck1558c5a2013-07-04 21:32:07 +0000114 bool ParseDirectiveSection(StringRef, SMLoc);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000115 bool ParseDirectiveDef(StringRef, SMLoc);
116 bool ParseDirectiveScl(StringRef, SMLoc);
117 bool ParseDirectiveType(StringRef, SMLoc);
118 bool ParseDirectiveEndef(StringRef, SMLoc);
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000119 bool ParseDirectiveSecRel32(StringRef, SMLoc);
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000120 bool ParseDirectiveSecIdx(StringRef, SMLoc);
David Majnemer4eecd302015-05-30 04:56:02 +0000121 bool ParseDirectiveSafeSEH(StringRef, SMLoc);
Rafael Espindola0766ae02014-06-06 19:26:12 +0000122 bool parseCOMDATType(COFF::COMDATType &Type);
Nico Riecka37acf72013-07-06 12:13:10 +0000123 bool ParseDirectiveLinkOnce(StringRef, SMLoc);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000124
Charles Davisc7250fa2011-05-22 21:12:15 +0000125 // Win64 EH directives.
126 bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
127 bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
128 bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
129 bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
130 bool ParseSEHDirectiveHandler(StringRef, SMLoc);
131 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
Charles Davis7f6176c2011-05-24 20:06:30 +0000132 bool ParseSEHDirectivePushReg(StringRef, SMLoc);
133 bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
134 bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
135 bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
136 bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
137 bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
Charles Davisc7250fa2011-05-22 21:12:15 +0000138 bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
139
140 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
Charles Davis7f6176c2011-05-24 20:06:30 +0000141 bool ParseSEHRegisterNumber(unsigned &RegNo);
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000142 bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000143public:
144 COFFAsmParser() {}
145};
146
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000147} // end annonomous namespace.
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000148
Nico Rieck1558c5a2013-07-04 21:32:07 +0000149static SectionKind computeSectionKind(unsigned Flags) {
150 if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
151 return SectionKind::getText();
152 if (Flags & COFF::IMAGE_SCN_MEM_READ &&
153 (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
154 return SectionKind::getReadOnly();
Rafael Espindola449711c2015-11-18 06:02:15 +0000155 return SectionKind::getData();
Nico Rieck1558c5a2013-07-04 21:32:07 +0000156}
157
158bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
159 enum {
160 None = 0,
161 Alloc = 1 << 0,
162 Code = 1 << 1,
163 Load = 1 << 2,
164 InitData = 1 << 3,
165 Shared = 1 << 4,
166 NoLoad = 1 << 5,
167 NoRead = 1 << 6,
168 NoWrite = 1 << 7
169 };
170
171 bool ReadOnlyRemoved = false;
172 unsigned SecFlags = None;
173
David Majnemerbee5f752014-07-04 23:15:28 +0000174 for (char FlagChar : FlagsString) {
175 switch (FlagChar) {
Nico Rieck1558c5a2013-07-04 21:32:07 +0000176 case 'a':
177 // Ignored.
178 break;
179
180 case 'b': // bss section
181 SecFlags |= Alloc;
182 if (SecFlags & InitData)
183 return TokError("conflicting section flags 'b' and 'd'.");
184 SecFlags &= ~Load;
185 break;
186
187 case 'd': // data section
188 SecFlags |= InitData;
189 if (SecFlags & Alloc)
190 return TokError("conflicting section flags 'b' and 'd'.");
191 SecFlags &= ~NoWrite;
192 if ((SecFlags & NoLoad) == 0)
193 SecFlags |= Load;
194 break;
195
196 case 'n': // section is not loaded
197 SecFlags |= NoLoad;
198 SecFlags &= ~Load;
199 break;
200
201 case 'r': // read-only
202 ReadOnlyRemoved = false;
203 SecFlags |= NoWrite;
204 if ((SecFlags & Code) == 0)
205 SecFlags |= InitData;
206 if ((SecFlags & NoLoad) == 0)
207 SecFlags |= Load;
208 break;
209
210 case 's': // shared section
211 SecFlags |= Shared | InitData;
212 SecFlags &= ~NoWrite;
213 if ((SecFlags & NoLoad) == 0)
214 SecFlags |= Load;
215 break;
216
217 case 'w': // writable
218 SecFlags &= ~NoWrite;
219 ReadOnlyRemoved = true;
220 break;
221
222 case 'x': // executable section
223 SecFlags |= Code;
224 if ((SecFlags & NoLoad) == 0)
225 SecFlags |= Load;
226 if (!ReadOnlyRemoved)
227 SecFlags |= NoWrite;
228 break;
229
230 case 'y': // not readable
231 SecFlags |= NoRead | NoWrite;
232 break;
233
234 default:
235 return TokError("unknown flag");
236 }
237 }
238
239 *Flags = 0;
240
241 if (SecFlags == None)
242 SecFlags = InitData;
243
244 if (SecFlags & Code)
245 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
246 if (SecFlags & InitData)
247 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
248 if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
249 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
250 if (SecFlags & NoLoad)
251 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
252 if ((SecFlags & NoRead) == 0)
253 *Flags |= COFF::IMAGE_SCN_MEM_READ;
254 if ((SecFlags & NoWrite) == 0)
255 *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
256 if (SecFlags & Shared)
257 *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
258
259 return false;
260}
261
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000262/// ParseDirectiveSymbolAttribute
263/// ::= { ".weak", ... } [ identifier ( , identifier )* ]
264bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
265 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
266 .Case(".weak", MCSA_Weak)
267 .Default(MCSA_Invalid);
268 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
269 if (getLexer().isNot(AsmToken::EndOfStatement)) {
270 for (;;) {
271 StringRef Name;
272
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000273 if (getParser().parseIdentifier(Name))
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000274 return TokError("expected identifier in directive");
275
Jim Grosbach6f482002015-05-18 18:43:14 +0000276 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000277
278 getStreamer().EmitSymbolAttribute(Sym, Attr);
279
280 if (getLexer().is(AsmToken::EndOfStatement))
281 break;
282
283 if (getLexer().isNot(AsmToken::Comma))
284 return TokError("unexpected token in directive");
285 Lex();
286 }
287 }
288
289 Lex();
290 return false;
291}
292
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000293bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
294 unsigned Characteristics,
295 SectionKind Kind) {
David Majnemerc57d0382014-06-27 17:19:44 +0000296 return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
Rafael Espindola60ec3832013-11-19 19:52:52 +0000297}
298
299bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
300 unsigned Characteristics,
301 SectionKind Kind,
302 StringRef COMDATSymName,
Rafael Espindola0766ae02014-06-06 19:26:12 +0000303 COFF::COMDATType Type) {
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000304 if (getLexer().isNot(AsmToken::EndOfStatement))
305 return TokError("unexpected token in section switching directive");
306 Lex();
307
308 getStreamer().SwitchSection(getContext().getCOFFSection(
Rafael Espindola0766ae02014-06-06 19:26:12 +0000309 Section, Characteristics, Kind, COMDATSymName, Type));
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000310
311 return false;
312}
313
Nico Rieck1558c5a2013-07-04 21:32:07 +0000314bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
Hans Wennborg7ddcdc82013-10-18 02:14:40 +0000315 if (!getLexer().is(AsmToken::Identifier))
316 return true;
317
318 SectionName = getTok().getIdentifier();
319 Lex();
320 return false;
Nico Rieck1558c5a2013-07-04 21:32:07 +0000321}
322
Rafael Espindola60ec3832013-11-19 19:52:52 +0000323// .section name [, "flags"] [, identifier [ identifier ], identifier]
Nico Rieck1558c5a2013-07-04 21:32:07 +0000324//
325// Supported flags:
326// a: Ignored.
327// b: BSS section (uninitialized data)
328// d: data section (initialized data)
329// n: Discardable section
330// r: Readable section
331// s: Shared section
332// w: Writable section
333// x: Executable section
334// y: Not-readable section (clears 'r')
335//
336// Subsections are not supported.
337bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
338 StringRef SectionName;
339
340 if (ParseSectionName(SectionName))
341 return TokError("expected identifier in directive");
342
343 unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
344 COFF::IMAGE_SCN_MEM_READ |
345 COFF::IMAGE_SCN_MEM_WRITE;
346
347 if (getLexer().is(AsmToken::Comma)) {
348 Lex();
349
350 if (getLexer().isNot(AsmToken::String))
351 return TokError("expected string in directive");
352
353 StringRef FlagsStr = getTok().getStringContents();
354 Lex();
355
356 if (ParseSectionFlags(FlagsStr, &Flags))
357 return true;
358 }
359
David Majnemerc57d0382014-06-27 17:19:44 +0000360 COFF::COMDATType Type = (COFF::COMDATType)0;
Rafael Espindola60ec3832013-11-19 19:52:52 +0000361 StringRef COMDATSymName;
362 if (getLexer().is(AsmToken::Comma)) {
Aaron Ballman3182ee92015-06-09 12:03:46 +0000363 Type = COFF::IMAGE_COMDAT_SELECT_ANY;
Rafael Espindola60ec3832013-11-19 19:52:52 +0000364 Lex();
365
366 Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
367
Reid Kleckner21aedc42014-08-11 18:34:43 +0000368 if (!getLexer().is(AsmToken::Identifier))
369 return TokError("expected comdat type such as 'discard' or 'largest' "
370 "after protection bits");
371
Rafael Espindola0766ae02014-06-06 19:26:12 +0000372 if (parseCOMDATType(Type))
Rafael Espindola60ec3832013-11-19 19:52:52 +0000373 return true;
374
375 if (getLexer().isNot(AsmToken::Comma))
376 return TokError("expected comma in directive");
377 Lex();
378
379 if (getParser().parseIdentifier(COMDATSymName))
380 return TokError("expected identifier in directive");
381 }
382
Nico Rieck1558c5a2013-07-04 21:32:07 +0000383 if (getLexer().isNot(AsmToken::EndOfStatement))
384 return TokError("unexpected token in directive");
385
386 SectionKind Kind = computeSectionKind(Flags);
Saleem Abdulrasoolbdbc0082014-06-22 22:25:01 +0000387 if (Kind.isText()) {
388 const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
389 if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
390 Flags |= COFF::IMAGE_SCN_MEM_16BIT;
391 }
Rafael Espindola0766ae02014-06-06 19:26:12 +0000392 ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
Nico Rieck1558c5a2013-07-04 21:32:07 +0000393 return false;
394}
395
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000396bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
397 StringRef SymbolName;
398
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000399 if (getParser().parseIdentifier(SymbolName))
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000400 return TokError("expected identifier in directive");
401
Jim Grosbach6f482002015-05-18 18:43:14 +0000402 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000403
404 getStreamer().BeginCOFFSymbolDef(Sym);
405
406 Lex();
407 return false;
408}
409
410bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
411 int64_t SymbolStorageClass;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000412 if (getParser().parseAbsoluteExpression(SymbolStorageClass))
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000413 return true;
414
415 if (getLexer().isNot(AsmToken::EndOfStatement))
416 return TokError("unexpected token in directive");
417
418 Lex();
419 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
420 return false;
421}
422
423bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
424 int64_t Type;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000425 if (getParser().parseAbsoluteExpression(Type))
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000426 return true;
427
428 if (getLexer().isNot(AsmToken::EndOfStatement))
429 return TokError("unexpected token in directive");
430
431 Lex();
432 getStreamer().EmitCOFFSymbolType(Type);
433 return false;
434}
435
436bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
437 Lex();
438 getStreamer().EndCOFFSymbolDef();
439 return false;
440}
441
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000442bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
443 StringRef SymbolID;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000444 if (getParser().parseIdentifier(SymbolID))
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000445 return TokError("expected identifier in directive");
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000446
447 if (getLexer().isNot(AsmToken::EndOfStatement))
448 return TokError("unexpected token in directive");
449
Jim Grosbach6f482002015-05-18 18:43:14 +0000450 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000451
452 Lex();
453 getStreamer().EmitCOFFSecRel32(Symbol);
454 return false;
455}
456
David Majnemer4eecd302015-05-30 04:56:02 +0000457bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
458 StringRef SymbolID;
459 if (getParser().parseIdentifier(SymbolID))
460 return TokError("expected identifier in directive");
461
462 if (getLexer().isNot(AsmToken::EndOfStatement))
463 return TokError("unexpected token in directive");
464
465 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
466
467 Lex();
468 getStreamer().EmitCOFFSafeSEH(Symbol);
469 return false;
470}
471
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000472bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
473 StringRef SymbolID;
474 if (getParser().parseIdentifier(SymbolID))
475 return TokError("expected identifier in directive");
476
477 if (getLexer().isNot(AsmToken::EndOfStatement))
478 return TokError("unexpected token in directive");
479
Jim Grosbach6f482002015-05-18 18:43:14 +0000480 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000481
482 Lex();
483 getStreamer().EmitCOFFSectionIndex(Symbol);
484 return false;
485}
486
Rafael Espindola0766ae02014-06-06 19:26:12 +0000487/// ::= [ identifier ]
488bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
Rafael Espindola60ec3832013-11-19 19:52:52 +0000489 StringRef TypeId = getTok().getIdentifier();
Nico Riecka37acf72013-07-06 12:13:10 +0000490
Rafael Espindola60ec3832013-11-19 19:52:52 +0000491 Type = StringSwitch<COFF::COMDATType>(TypeId)
492 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
493 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
494 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
495 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
496 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
497 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
498 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
499 .Default((COFF::COMDATType)0);
Nico Riecka37acf72013-07-06 12:13:10 +0000500
Rafael Espindola60ec3832013-11-19 19:52:52 +0000501 if (Type == 0)
502 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
Nico Riecka37acf72013-07-06 12:13:10 +0000503
Rafael Espindola60ec3832013-11-19 19:52:52 +0000504 Lex();
Nico Riecka37acf72013-07-06 12:13:10 +0000505
Rafael Espindola60ec3832013-11-19 19:52:52 +0000506 return false;
507}
508
509/// ParseDirectiveLinkOnce
Rafael Espindola0766ae02014-06-06 19:26:12 +0000510/// ::= .linkonce [ identifier ]
Rafael Espindola60ec3832013-11-19 19:52:52 +0000511bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
512 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
Rafael Espindola60ec3832013-11-19 19:52:52 +0000513 if (getLexer().is(AsmToken::Identifier))
Rafael Espindola0766ae02014-06-06 19:26:12 +0000514 if (parseCOMDATType(Type))
Rafael Espindola60ec3832013-11-19 19:52:52 +0000515 return true;
516
517 const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
518 getStreamer().getCurrentSection().first);
519
Rafael Espindola0766ae02014-06-06 19:26:12 +0000520 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
521 return Error(Loc, "cannot make section associative with .linkonce");
Rafael Espindola60ec3832013-11-19 19:52:52 +0000522
Nico Riecka37acf72013-07-06 12:13:10 +0000523 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
524 return Error(Loc, Twine("section '") + Current->getSectionName() +
525 "' is already linkonce");
526
Rafael Espindola0766ae02014-06-06 19:26:12 +0000527 Current->setSelection(Type);
Nico Riecka37acf72013-07-06 12:13:10 +0000528
529 if (getLexer().isNot(AsmToken::EndOfStatement))
530 return TokError("unexpected token in directive");
531
532 return false;
533}
534
Charles Davisc7250fa2011-05-22 21:12:15 +0000535bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000536 StringRef SymbolID;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000537 if (getParser().parseIdentifier(SymbolID))
Charles Davisc7250fa2011-05-22 21:12:15 +0000538 return true;
539
Charles Davisc7250fa2011-05-22 21:12:15 +0000540 if (getLexer().isNot(AsmToken::EndOfStatement))
541 return TokError("unexpected token in directive");
542
Jim Grosbach6f482002015-05-18 18:43:14 +0000543 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000544
Charles Davisc7250fa2011-05-22 21:12:15 +0000545 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000546 getStreamer().EmitWinCFIStartProc(Symbol);
Charles Davisc7250fa2011-05-22 21:12:15 +0000547 return false;
548}
549
550bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
551 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000552 getStreamer().EmitWinCFIEndProc();
Charles Davisc7250fa2011-05-22 21:12:15 +0000553 return false;
554}
555
556bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
557 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000558 getStreamer().EmitWinCFIStartChained();
Charles Davisc7250fa2011-05-22 21:12:15 +0000559 return false;
560}
561
562bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
563 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000564 getStreamer().EmitWinCFIEndChained();
Charles Davisc7250fa2011-05-22 21:12:15 +0000565 return false;
566}
567
568bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000569 StringRef SymbolID;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000570 if (getParser().parseIdentifier(SymbolID))
Charles Davisc7250fa2011-05-22 21:12:15 +0000571 return true;
572
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000573 if (getLexer().isNot(AsmToken::Comma))
574 return TokError("you must specify one or both of @unwind or @except");
575 Lex();
Charles Davisc7250fa2011-05-22 21:12:15 +0000576 bool unwind = false, except = false;
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000577 if (ParseAtUnwindOrAtExcept(unwind, except))
578 return true;
Charles Davisc7250fa2011-05-22 21:12:15 +0000579 if (getLexer().is(AsmToken::Comma)) {
580 Lex();
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000581 if (ParseAtUnwindOrAtExcept(unwind, except))
Charles Davisc7250fa2011-05-22 21:12:15 +0000582 return true;
583 }
584 if (getLexer().isNot(AsmToken::EndOfStatement))
585 return TokError("unexpected token in directive");
586
Jim Grosbach6f482002015-05-18 18:43:14 +0000587 MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000588
Charles Davisc7250fa2011-05-22 21:12:15 +0000589 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000590 getStreamer().EmitWinEHHandler(handler, unwind, except);
Charles Davisc7250fa2011-05-22 21:12:15 +0000591 return false;
592}
593
594bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
595 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000596 getStreamer().EmitWinEHHandlerData();
Charles Davisc7250fa2011-05-22 21:12:15 +0000597 return false;
598}
599
600bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
Michael Ilseman5be22a12014-12-12 21:48:03 +0000601 unsigned Reg = 0;
Charles Davis7f6176c2011-05-24 20:06:30 +0000602 if (ParseSEHRegisterNumber(Reg))
603 return true;
604
605 if (getLexer().isNot(AsmToken::EndOfStatement))
606 return TokError("unexpected token in directive");
607
608 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000609 getStreamer().EmitWinCFIPushReg(Reg);
Charles Davis7f6176c2011-05-24 20:06:30 +0000610 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000611}
612
613bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
Michael Ilseman5be22a12014-12-12 21:48:03 +0000614 unsigned Reg = 0;
Charles Davis7f6176c2011-05-24 20:06:30 +0000615 int64_t Off;
616 if (ParseSEHRegisterNumber(Reg))
617 return true;
Charles Davis2f6ecea2011-05-25 21:43:45 +0000618 if (getLexer().isNot(AsmToken::Comma))
619 return TokError("you must specify a stack pointer offset");
620
621 Lex();
Charles Davis7f6176c2011-05-24 20:06:30 +0000622 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000623 if (getParser().parseAbsoluteExpression(Off))
Charles Davis7f6176c2011-05-24 20:06:30 +0000624 return true;
625
626 if (Off & 0x0F)
627 return Error(startLoc, "offset is not a multiple of 16");
628
629 if (getLexer().isNot(AsmToken::EndOfStatement))
630 return TokError("unexpected token in directive");
631
632 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000633 getStreamer().EmitWinCFISetFrame(Reg, Off);
Charles Davis7f6176c2011-05-24 20:06:30 +0000634 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000635}
636
Charles Davisd9eafdc2011-05-23 16:43:09 +0000637bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
638 int64_t Size;
Charles Davis7f6176c2011-05-24 20:06:30 +0000639 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000640 if (getParser().parseAbsoluteExpression(Size))
Charles Davisd9eafdc2011-05-23 16:43:09 +0000641 return true;
642
Charles Davis7f6176c2011-05-24 20:06:30 +0000643 if (Size & 7)
644 return Error(startLoc, "size is not a multiple of 8");
645
Charles Davisd9eafdc2011-05-23 16:43:09 +0000646 if (getLexer().isNot(AsmToken::EndOfStatement))
647 return TokError("unexpected token in directive");
648
649 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000650 getStreamer().EmitWinCFIAllocStack(Size);
Charles Davisd9eafdc2011-05-23 16:43:09 +0000651 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000652}
653
654bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
Michael Ilseman5be22a12014-12-12 21:48:03 +0000655 unsigned Reg = 0;
Charles Davis7f6176c2011-05-24 20:06:30 +0000656 int64_t Off;
657 if (ParseSEHRegisterNumber(Reg))
658 return true;
Charles Davis828b00c2011-05-25 04:51:25 +0000659 if (getLexer().isNot(AsmToken::Comma))
Charles Davis2f6ecea2011-05-25 21:43:45 +0000660 return TokError("you must specify an offset on the stack");
Charles Davis828b00c2011-05-25 04:51:25 +0000661
662 Lex();
Charles Davis7f6176c2011-05-24 20:06:30 +0000663 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000664 if (getParser().parseAbsoluteExpression(Off))
Charles Davis7f6176c2011-05-24 20:06:30 +0000665 return true;
666
667 if (Off & 7)
668 return Error(startLoc, "size is not a multiple of 8");
669
670 if (getLexer().isNot(AsmToken::EndOfStatement))
671 return TokError("unexpected token in directive");
672
673 Lex();
674 // FIXME: Err on %xmm* registers
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000675 getStreamer().EmitWinCFISaveReg(Reg, Off);
Charles Davis7f6176c2011-05-24 20:06:30 +0000676 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000677}
678
Charles Davis7f6176c2011-05-24 20:06:30 +0000679// FIXME: This method is inherently x86-specific. It should really be in the
680// x86 backend.
Charles Davisc7250fa2011-05-22 21:12:15 +0000681bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
Michael Ilseman5be22a12014-12-12 21:48:03 +0000682 unsigned Reg = 0;
Charles Davis7f6176c2011-05-24 20:06:30 +0000683 int64_t Off;
684 if (ParseSEHRegisterNumber(Reg))
685 return true;
Charles Davis828b00c2011-05-25 04:51:25 +0000686 if (getLexer().isNot(AsmToken::Comma))
Charles Davis2f6ecea2011-05-25 21:43:45 +0000687 return TokError("you must specify an offset on the stack");
Charles Davis828b00c2011-05-25 04:51:25 +0000688
689 Lex();
Charles Davis7f6176c2011-05-24 20:06:30 +0000690 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000691 if (getParser().parseAbsoluteExpression(Off))
Charles Davis7f6176c2011-05-24 20:06:30 +0000692 return true;
693
694 if (getLexer().isNot(AsmToken::EndOfStatement))
695 return TokError("unexpected token in directive");
696
697 if (Off & 0x0F)
698 return Error(startLoc, "offset is not a multiple of 16");
699
700 Lex();
701 // FIXME: Err on non-%xmm* registers
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000702 getStreamer().EmitWinCFISaveXMM(Reg, Off);
Charles Davis7f6176c2011-05-24 20:06:30 +0000703 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000704}
705
Charles Davisd9eafdc2011-05-23 16:43:09 +0000706bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
Charles Davisb0c4f392011-05-25 04:08:15 +0000707 bool Code = false;
Charles Davisd9eafdc2011-05-23 16:43:09 +0000708 StringRef CodeID;
Charles Davisb0c4f392011-05-25 04:08:15 +0000709 if (getLexer().is(AsmToken::At)) {
710 SMLoc startLoc = getLexer().getLoc();
711 Lex();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000712 if (!getParser().parseIdentifier(CodeID)) {
Charles Davisb0c4f392011-05-25 04:08:15 +0000713 if (CodeID != "code")
714 return Error(startLoc, "expected @code");
715 Code = true;
716 }
Charles Davisd9eafdc2011-05-23 16:43:09 +0000717 }
718
719 if (getLexer().isNot(AsmToken::EndOfStatement))
720 return TokError("unexpected token in directive");
721
722 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000723 getStreamer().EmitWinCFIPushFrame(Code);
Charles Davisd9eafdc2011-05-23 16:43:09 +0000724 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000725}
726
727bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
728 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000729 getStreamer().EmitWinCFIEndProlog();
Charles Davisc7250fa2011-05-22 21:12:15 +0000730 return false;
731}
732
733bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
734 StringRef identifier;
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000735 if (getLexer().isNot(AsmToken::At))
736 return TokError("a handler attribute must begin with '@'");
Charles Davisc7250fa2011-05-22 21:12:15 +0000737 SMLoc startLoc = getLexer().getLoc();
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000738 Lex();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000739 if (getParser().parseIdentifier(identifier))
Charles Davisc7250fa2011-05-22 21:12:15 +0000740 return Error(startLoc, "expected @unwind or @except");
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000741 if (identifier == "unwind")
Charles Davisc7250fa2011-05-22 21:12:15 +0000742 unwind = true;
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000743 else if (identifier == "except")
Charles Davisc7250fa2011-05-22 21:12:15 +0000744 except = true;
745 else
746 return Error(startLoc, "expected @unwind or @except");
747 return false;
748}
749
Charles Davis7f6176c2011-05-24 20:06:30 +0000750bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
Charles Davis7f6176c2011-05-24 20:06:30 +0000751 SMLoc startLoc = getLexer().getLoc();
Charles Davis828b00c2011-05-25 04:51:25 +0000752 if (getLexer().is(AsmToken::Percent)) {
Bill Wendlingbc07a892013-06-18 07:20:20 +0000753 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
Charles Davis7f6176c2011-05-24 20:06:30 +0000754 SMLoc endLoc;
755 unsigned LLVMRegNo;
756 if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
Charles Davis828b00c2011-05-25 04:51:25 +0000757 return true;
Charles Davis7f6176c2011-05-24 20:06:30 +0000758
Evan Chengd60fa58b2011-07-18 20:57:22 +0000759#if 0
760 // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
761 // violation so this validation code is disabled.
762
Charles Davis7f6176c2011-05-24 20:06:30 +0000763 // Check that this is a non-volatile register.
Evan Chenga83b37a2011-07-15 02:09:41 +0000764 const unsigned *NVRegs = TAI.getCalleeSavedRegs();
Charles Davis7f6176c2011-05-24 20:06:30 +0000765 unsigned i;
766 for (i = 0; NVRegs[i] != 0; ++i)
767 if (NVRegs[i] == LLVMRegNo)
768 break;
769 if (NVRegs[i] == 0)
770 return Error(startLoc, "expected non-volatile register");
Evan Chengd60fa58b2011-07-18 20:57:22 +0000771#endif
Charles Davis7f6176c2011-05-24 20:06:30 +0000772
Bill Wendlingbc07a892013-06-18 07:20:20 +0000773 int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
Charles Davis7f6176c2011-05-24 20:06:30 +0000774 if (SEHRegNo < 0)
775 return Error(startLoc,"register can't be represented in SEH unwind info");
776 RegNo = SEHRegNo;
777 }
Charles Davis828b00c2011-05-25 04:51:25 +0000778 else {
779 int64_t n;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000780 if (getParser().parseAbsoluteExpression(n))
Charles Davis828b00c2011-05-25 04:51:25 +0000781 return true;
782 if (n > 15)
783 return Error(startLoc, "register number is too high");
Charles Davis7f6176c2011-05-24 20:06:30 +0000784 RegNo = n;
Charles Davis828b00c2011-05-25 04:51:25 +0000785 }
Charles Davis7f6176c2011-05-24 20:06:30 +0000786
Charles Davis7f6176c2011-05-24 20:06:30 +0000787 return false;
788}
789
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000790namespace llvm {
791
792MCAsmParserExtension *createCOFFAsmParser() {
793 return new COFFAsmParser;
794}
795
796}