blob: b83d68d4fe206ffee77541e650010c9d15229d37 [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
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +000010#include "llvm/ADT/StringRef.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000011#include "llvm/ADT/StringSwitch.h"
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +000012#include "llvm/ADT/Triple.h"
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000013#include "llvm/ADT/Twine.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000014#include "llvm/BinaryFormat/COFF.h"
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000015#include "llvm/MC/MCContext.h"
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +000016#include "llvm/MC/MCDirectives.h"
Saleem Abdulrasoolbdbc0082014-06-22 22:25:01 +000017#include "llvm/MC/MCObjectFileInfo.h"
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000018#include "llvm/MC/MCParser/MCAsmLexer.h"
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +000019#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000020#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Evan Chengd60fa58b2011-07-18 20:57:22 +000021#include "llvm/MC/MCRegisterInfo.h"
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000022#include "llvm/MC/MCSectionCOFF.h"
23#include "llvm/MC/MCStreamer.h"
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +000024#include "llvm/MC/SectionKind.h"
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +000025#include "llvm/Support/SMLoc.h"
26#include <cassert>
27#include <cstdint>
28#include <limits>
29#include <utility>
30
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000031using namespace llvm;
32
33namespace {
34
35class COFFAsmParser : public MCAsmParserExtension {
Eli Bendersky29b9f472013-01-16 00:50:52 +000036 template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
Jim Grosbachd2037eb2013-02-20 22:21:35 +000037 void addDirectiveHandler(StringRef Directive) {
Eli Bendersky29b9f472013-01-16 00:50:52 +000038 MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
39 this, HandleDirective<COFFAsmParser, HandlerMethod>);
Jim Grosbachd2037eb2013-02-20 22:21:35 +000040 getParser().addDirectiveHandler(Directive, Handler);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000041 }
42
43 bool ParseSectionSwitch(StringRef Section,
44 unsigned Characteristics,
45 SectionKind Kind);
46
Rafael Espindola60ec3832013-11-19 19:52:52 +000047 bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
48 SectionKind Kind, StringRef COMDATSymName,
Rafael Espindola0766ae02014-06-06 19:26:12 +000049 COFF::COMDATType Type);
Rafael Espindola60ec3832013-11-19 19:52:52 +000050
Nico Rieck1558c5a2013-07-04 21:32:07 +000051 bool ParseSectionName(StringRef &SectionName);
Reid Kleckner31263732016-09-14 22:41:50 +000052 bool ParseSectionFlags(StringRef SectionName, StringRef FlagsString,
53 unsigned *Flags);
Nico Rieck1558c5a2013-07-04 21:32:07 +000054
Craig Topper59be68f2014-03-08 07:14:16 +000055 void Initialize(MCAsmParser &Parser) override {
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +000056 // Call the base implementation.
57 MCAsmParserExtension::Initialize(Parser);
58
Jim Grosbachd2037eb2013-02-20 22:21:35 +000059 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
60 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
61 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
Nico Rieck1558c5a2013-07-04 21:32:07 +000062 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000063 addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
64 addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
65 addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
66 addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
67 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +000068 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
David Majnemer4eecd302015-05-30 04:56:02 +000069 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
Nico Riecka37acf72013-07-06 12:13:10 +000070 addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
Charles Davisc7250fa2011-05-22 21:12:15 +000071
72 // Win64 EH directives.
Jim Grosbachd2037eb2013-02-20 22:21:35 +000073 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
Charles Davisc7250fa2011-05-22 21:12:15 +000074 ".seh_proc");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000075 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
Charles Davisc7250fa2011-05-22 21:12:15 +000076 ".seh_endproc");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000077 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
Charles Davisc7250fa2011-05-22 21:12:15 +000078 ".seh_startchained");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000079 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
Charles Davisc7250fa2011-05-22 21:12:15 +000080 ".seh_endchained");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000081 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
Charles Davisc7250fa2011-05-22 21:12:15 +000082 ".seh_handler");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000083 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
Charles Davisc7250fa2011-05-22 21:12:15 +000084 ".seh_handlerdata");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000085 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
Charles Davisc7250fa2011-05-22 21:12:15 +000086 ".seh_pushreg");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000087 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
Charles Davisc7250fa2011-05-22 21:12:15 +000088 ".seh_setframe");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000089 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
Charles Davisc7250fa2011-05-22 21:12:15 +000090 ".seh_stackalloc");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000091 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
Charles Davisc7250fa2011-05-22 21:12:15 +000092 ".seh_savereg");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000093 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
Charles Davisc7250fa2011-05-22 21:12:15 +000094 ".seh_savexmm");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000095 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
Charles Davisc7250fa2011-05-22 21:12:15 +000096 ".seh_pushframe");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000097 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
Charles Davisc7250fa2011-05-22 21:12:15 +000098 ".seh_endprologue");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000099 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000100 }
101
102 bool ParseSectionDirectiveText(StringRef, SMLoc) {
103 return ParseSectionSwitch(".text",
104 COFF::IMAGE_SCN_CNT_CODE
105 | COFF::IMAGE_SCN_MEM_EXECUTE
106 | COFF::IMAGE_SCN_MEM_READ,
107 SectionKind::getText());
108 }
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +0000109
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000110 bool ParseSectionDirectiveData(StringRef, SMLoc) {
Rafael Espindola449711c2015-11-18 06:02:15 +0000111 return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
112 COFF::IMAGE_SCN_MEM_READ |
113 COFF::IMAGE_SCN_MEM_WRITE,
114 SectionKind::getData());
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000115 }
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +0000116
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000117 bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
118 return ParseSectionSwitch(".bss",
119 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
120 | COFF::IMAGE_SCN_MEM_READ
121 | COFF::IMAGE_SCN_MEM_WRITE,
122 SectionKind::getBSS());
123 }
124
Nico Rieck1558c5a2013-07-04 21:32:07 +0000125 bool ParseDirectiveSection(StringRef, SMLoc);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000126 bool ParseDirectiveDef(StringRef, SMLoc);
127 bool ParseDirectiveScl(StringRef, SMLoc);
128 bool ParseDirectiveType(StringRef, SMLoc);
129 bool ParseDirectiveEndef(StringRef, SMLoc);
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000130 bool ParseDirectiveSecRel32(StringRef, SMLoc);
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000131 bool ParseDirectiveSecIdx(StringRef, SMLoc);
David Majnemer4eecd302015-05-30 04:56:02 +0000132 bool ParseDirectiveSafeSEH(StringRef, SMLoc);
Rafael Espindola0766ae02014-06-06 19:26:12 +0000133 bool parseCOMDATType(COFF::COMDATType &Type);
Nico Riecka37acf72013-07-06 12:13:10 +0000134 bool ParseDirectiveLinkOnce(StringRef, SMLoc);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000135
Charles Davisc7250fa2011-05-22 21:12:15 +0000136 // Win64 EH directives.
137 bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
138 bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
139 bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
140 bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
141 bool ParseSEHDirectiveHandler(StringRef, SMLoc);
142 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
Charles Davis7f6176c2011-05-24 20:06:30 +0000143 bool ParseSEHDirectivePushReg(StringRef, SMLoc);
144 bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
145 bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
146 bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
147 bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
148 bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
Charles Davisc7250fa2011-05-22 21:12:15 +0000149 bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
150
151 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
Charles Davis7f6176c2011-05-24 20:06:30 +0000152 bool ParseSEHRegisterNumber(unsigned &RegNo);
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000153 bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +0000154
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000155public:
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +0000156 COFFAsmParser() = default;
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000157};
158
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000159} // end annonomous namespace.
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000160
Nico Rieck1558c5a2013-07-04 21:32:07 +0000161static SectionKind computeSectionKind(unsigned Flags) {
162 if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
163 return SectionKind::getText();
164 if (Flags & COFF::IMAGE_SCN_MEM_READ &&
165 (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
166 return SectionKind::getReadOnly();
Rafael Espindola449711c2015-11-18 06:02:15 +0000167 return SectionKind::getData();
Nico Rieck1558c5a2013-07-04 21:32:07 +0000168}
169
Reid Kleckner31263732016-09-14 22:41:50 +0000170bool COFFAsmParser::ParseSectionFlags(StringRef SectionName,
171 StringRef FlagsString, unsigned *Flags) {
Nico Rieck1558c5a2013-07-04 21:32:07 +0000172 enum {
Reid Kleckner31263732016-09-14 22:41:50 +0000173 None = 0,
174 Alloc = 1 << 0,
175 Code = 1 << 1,
176 Load = 1 << 2,
177 InitData = 1 << 3,
178 Shared = 1 << 4,
179 NoLoad = 1 << 5,
180 NoRead = 1 << 6,
181 NoWrite = 1 << 7,
182 Discardable = 1 << 8,
Nico Rieck1558c5a2013-07-04 21:32:07 +0000183 };
184
185 bool ReadOnlyRemoved = false;
186 unsigned SecFlags = None;
187
David Majnemerbee5f752014-07-04 23:15:28 +0000188 for (char FlagChar : FlagsString) {
189 switch (FlagChar) {
Nico Rieck1558c5a2013-07-04 21:32:07 +0000190 case 'a':
191 // Ignored.
192 break;
193
194 case 'b': // bss section
195 SecFlags |= Alloc;
196 if (SecFlags & InitData)
197 return TokError("conflicting section flags 'b' and 'd'.");
198 SecFlags &= ~Load;
199 break;
200
201 case 'd': // data section
202 SecFlags |= InitData;
203 if (SecFlags & Alloc)
204 return TokError("conflicting section flags 'b' and 'd'.");
205 SecFlags &= ~NoWrite;
206 if ((SecFlags & NoLoad) == 0)
207 SecFlags |= Load;
208 break;
209
210 case 'n': // section is not loaded
211 SecFlags |= NoLoad;
212 SecFlags &= ~Load;
213 break;
214
Reid Kleckner31263732016-09-14 22:41:50 +0000215 case 'D': // discardable
216 SecFlags |= Discardable;
217 break;
218
Nico Rieck1558c5a2013-07-04 21:32:07 +0000219 case 'r': // read-only
220 ReadOnlyRemoved = false;
221 SecFlags |= NoWrite;
222 if ((SecFlags & Code) == 0)
223 SecFlags |= InitData;
224 if ((SecFlags & NoLoad) == 0)
225 SecFlags |= Load;
226 break;
227
228 case 's': // shared section
229 SecFlags |= Shared | InitData;
230 SecFlags &= ~NoWrite;
231 if ((SecFlags & NoLoad) == 0)
232 SecFlags |= Load;
233 break;
234
235 case 'w': // writable
236 SecFlags &= ~NoWrite;
237 ReadOnlyRemoved = true;
238 break;
239
240 case 'x': // executable section
241 SecFlags |= Code;
242 if ((SecFlags & NoLoad) == 0)
243 SecFlags |= Load;
244 if (!ReadOnlyRemoved)
245 SecFlags |= NoWrite;
246 break;
247
248 case 'y': // not readable
249 SecFlags |= NoRead | NoWrite;
250 break;
251
252 default:
253 return TokError("unknown flag");
254 }
255 }
256
257 *Flags = 0;
258
259 if (SecFlags == None)
260 SecFlags = InitData;
261
262 if (SecFlags & Code)
263 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
264 if (SecFlags & InitData)
265 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
266 if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
267 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
268 if (SecFlags & NoLoad)
269 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
Reid Kleckner31263732016-09-14 22:41:50 +0000270 if ((SecFlags & Discardable) ||
271 MCSectionCOFF::isImplicitlyDiscardable(SectionName))
272 *Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE;
Nico Rieck1558c5a2013-07-04 21:32:07 +0000273 if ((SecFlags & NoRead) == 0)
274 *Flags |= COFF::IMAGE_SCN_MEM_READ;
275 if ((SecFlags & NoWrite) == 0)
276 *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
277 if (SecFlags & Shared)
278 *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
279
280 return false;
281}
282
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000283/// ParseDirectiveSymbolAttribute
284/// ::= { ".weak", ... } [ identifier ( , identifier )* ]
285bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
286 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
287 .Case(".weak", MCSA_Weak)
288 .Default(MCSA_Invalid);
289 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
290 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +0000291 while (true) {
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000292 StringRef Name;
293
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000294 if (getParser().parseIdentifier(Name))
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000295 return TokError("expected identifier in directive");
296
Jim Grosbach6f482002015-05-18 18:43:14 +0000297 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000298
299 getStreamer().EmitSymbolAttribute(Sym, Attr);
300
301 if (getLexer().is(AsmToken::EndOfStatement))
302 break;
303
304 if (getLexer().isNot(AsmToken::Comma))
305 return TokError("unexpected token in directive");
306 Lex();
307 }
308 }
309
310 Lex();
311 return false;
312}
313
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000314bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
315 unsigned Characteristics,
316 SectionKind Kind) {
David Majnemerc57d0382014-06-27 17:19:44 +0000317 return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
Rafael Espindola60ec3832013-11-19 19:52:52 +0000318}
319
320bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
321 unsigned Characteristics,
322 SectionKind Kind,
323 StringRef COMDATSymName,
Rafael Espindola0766ae02014-06-06 19:26:12 +0000324 COFF::COMDATType Type) {
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000325 if (getLexer().isNot(AsmToken::EndOfStatement))
326 return TokError("unexpected token in section switching directive");
327 Lex();
328
329 getStreamer().SwitchSection(getContext().getCOFFSection(
Rafael Espindola0766ae02014-06-06 19:26:12 +0000330 Section, Characteristics, Kind, COMDATSymName, Type));
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000331
332 return false;
333}
334
Nico Rieck1558c5a2013-07-04 21:32:07 +0000335bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
Hans Wennborg7ddcdc82013-10-18 02:14:40 +0000336 if (!getLexer().is(AsmToken::Identifier))
337 return true;
338
339 SectionName = getTok().getIdentifier();
340 Lex();
341 return false;
Nico Rieck1558c5a2013-07-04 21:32:07 +0000342}
343
Rafael Espindola60ec3832013-11-19 19:52:52 +0000344// .section name [, "flags"] [, identifier [ identifier ], identifier]
Nico Rieck1558c5a2013-07-04 21:32:07 +0000345//
346// Supported flags:
347// a: Ignored.
348// b: BSS section (uninitialized data)
349// d: data section (initialized data)
Reid Kleckner31263732016-09-14 22:41:50 +0000350// n: "noload" section (removed by linker)
351// D: Discardable section
Nico Rieck1558c5a2013-07-04 21:32:07 +0000352// r: Readable section
353// s: Shared section
354// w: Writable section
355// x: Executable section
356// y: Not-readable section (clears 'r')
357//
358// Subsections are not supported.
359bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
360 StringRef SectionName;
361
362 if (ParseSectionName(SectionName))
363 return TokError("expected identifier in directive");
364
365 unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
366 COFF::IMAGE_SCN_MEM_READ |
367 COFF::IMAGE_SCN_MEM_WRITE;
368
369 if (getLexer().is(AsmToken::Comma)) {
370 Lex();
371
372 if (getLexer().isNot(AsmToken::String))
373 return TokError("expected string in directive");
374
375 StringRef FlagsStr = getTok().getStringContents();
376 Lex();
377
Reid Kleckner31263732016-09-14 22:41:50 +0000378 if (ParseSectionFlags(SectionName, FlagsStr, &Flags))
Nico Rieck1558c5a2013-07-04 21:32:07 +0000379 return true;
380 }
381
David Majnemerc57d0382014-06-27 17:19:44 +0000382 COFF::COMDATType Type = (COFF::COMDATType)0;
Rafael Espindola60ec3832013-11-19 19:52:52 +0000383 StringRef COMDATSymName;
384 if (getLexer().is(AsmToken::Comma)) {
Aaron Ballman3182ee92015-06-09 12:03:46 +0000385 Type = COFF::IMAGE_COMDAT_SELECT_ANY;
Rafael Espindola60ec3832013-11-19 19:52:52 +0000386 Lex();
387
388 Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
389
Reid Kleckner21aedc42014-08-11 18:34:43 +0000390 if (!getLexer().is(AsmToken::Identifier))
391 return TokError("expected comdat type such as 'discard' or 'largest' "
392 "after protection bits");
393
Rafael Espindola0766ae02014-06-06 19:26:12 +0000394 if (parseCOMDATType(Type))
Rafael Espindola60ec3832013-11-19 19:52:52 +0000395 return true;
396
397 if (getLexer().isNot(AsmToken::Comma))
398 return TokError("expected comma in directive");
399 Lex();
400
401 if (getParser().parseIdentifier(COMDATSymName))
402 return TokError("expected identifier in directive");
403 }
404
Nico Rieck1558c5a2013-07-04 21:32:07 +0000405 if (getLexer().isNot(AsmToken::EndOfStatement))
406 return TokError("unexpected token in directive");
407
408 SectionKind Kind = computeSectionKind(Flags);
Saleem Abdulrasoolbdbc0082014-06-22 22:25:01 +0000409 if (Kind.isText()) {
410 const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
411 if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
412 Flags |= COFF::IMAGE_SCN_MEM_16BIT;
413 }
Rafael Espindola0766ae02014-06-06 19:26:12 +0000414 ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
Nico Rieck1558c5a2013-07-04 21:32:07 +0000415 return false;
416}
417
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000418bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
419 StringRef SymbolName;
420
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000421 if (getParser().parseIdentifier(SymbolName))
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000422 return TokError("expected identifier in directive");
423
Jim Grosbach6f482002015-05-18 18:43:14 +0000424 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000425
426 getStreamer().BeginCOFFSymbolDef(Sym);
427
428 Lex();
429 return false;
430}
431
432bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
433 int64_t SymbolStorageClass;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000434 if (getParser().parseAbsoluteExpression(SymbolStorageClass))
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000435 return true;
436
437 if (getLexer().isNot(AsmToken::EndOfStatement))
438 return TokError("unexpected token in directive");
439
440 Lex();
441 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
442 return false;
443}
444
445bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
446 int64_t Type;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000447 if (getParser().parseAbsoluteExpression(Type))
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000448 return true;
449
450 if (getLexer().isNot(AsmToken::EndOfStatement))
451 return TokError("unexpected token in directive");
452
453 Lex();
454 getStreamer().EmitCOFFSymbolType(Type);
455 return false;
456}
457
458bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
459 Lex();
460 getStreamer().EndCOFFSymbolDef();
461 return false;
462}
463
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000464bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
465 StringRef SymbolID;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000466 if (getParser().parseIdentifier(SymbolID))
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000467 return TokError("expected identifier in directive");
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000468
Keno Fischerf7d84ee2017-01-02 03:00:19 +0000469 int64_t Offset = 0;
470 SMLoc OffsetLoc;
471 if (getLexer().is(AsmToken::Plus)) {
472 OffsetLoc = getLexer().getLoc();
473 if (getParser().parseAbsoluteExpression(Offset))
474 return true;
475 }
476
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000477 if (getLexer().isNot(AsmToken::EndOfStatement))
478 return TokError("unexpected token in directive");
479
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +0000480 if (Offset < 0 || Offset > std::numeric_limits<uint32_t>::max())
481 return Error(
482 OffsetLoc,
483 "invalid '.secrel32' directive offset, can't be less "
484 "than zero or greater than std::numeric_limits<uint32_t>::max()");
Keno Fischerf7d84ee2017-01-02 03:00:19 +0000485
Jim Grosbach6f482002015-05-18 18:43:14 +0000486 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000487
488 Lex();
Keno Fischerf7d84ee2017-01-02 03:00:19 +0000489 getStreamer().EmitCOFFSecRel32(Symbol, Offset);
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000490 return false;
491}
492
David Majnemer4eecd302015-05-30 04:56:02 +0000493bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
494 StringRef SymbolID;
495 if (getParser().parseIdentifier(SymbolID))
496 return TokError("expected identifier in directive");
497
498 if (getLexer().isNot(AsmToken::EndOfStatement))
499 return TokError("unexpected token in directive");
500
501 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
502
503 Lex();
504 getStreamer().EmitCOFFSafeSEH(Symbol);
505 return false;
506}
507
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000508bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
509 StringRef SymbolID;
510 if (getParser().parseIdentifier(SymbolID))
511 return TokError("expected identifier in directive");
512
513 if (getLexer().isNot(AsmToken::EndOfStatement))
514 return TokError("unexpected token in directive");
515
Jim Grosbach6f482002015-05-18 18:43:14 +0000516 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000517
518 Lex();
519 getStreamer().EmitCOFFSectionIndex(Symbol);
520 return false;
521}
522
Rafael Espindola0766ae02014-06-06 19:26:12 +0000523/// ::= [ identifier ]
524bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
Rafael Espindola60ec3832013-11-19 19:52:52 +0000525 StringRef TypeId = getTok().getIdentifier();
Nico Riecka37acf72013-07-06 12:13:10 +0000526
Rafael Espindola60ec3832013-11-19 19:52:52 +0000527 Type = StringSwitch<COFF::COMDATType>(TypeId)
528 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
529 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
530 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
531 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
532 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
533 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
534 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
535 .Default((COFF::COMDATType)0);
Nico Riecka37acf72013-07-06 12:13:10 +0000536
Rafael Espindola60ec3832013-11-19 19:52:52 +0000537 if (Type == 0)
538 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
Nico Riecka37acf72013-07-06 12:13:10 +0000539
Rafael Espindola60ec3832013-11-19 19:52:52 +0000540 Lex();
Nico Riecka37acf72013-07-06 12:13:10 +0000541
Rafael Espindola60ec3832013-11-19 19:52:52 +0000542 return false;
543}
544
545/// ParseDirectiveLinkOnce
Rafael Espindola0766ae02014-06-06 19:26:12 +0000546/// ::= .linkonce [ identifier ]
Rafael Espindola60ec3832013-11-19 19:52:52 +0000547bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
548 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
Rafael Espindola60ec3832013-11-19 19:52:52 +0000549 if (getLexer().is(AsmToken::Identifier))
Rafael Espindola0766ae02014-06-06 19:26:12 +0000550 if (parseCOMDATType(Type))
Rafael Espindola60ec3832013-11-19 19:52:52 +0000551 return true;
552
Eric Christopher445c9522016-10-14 05:47:37 +0000553 const MCSectionCOFF *Current =
554 static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly());
Rafael Espindola60ec3832013-11-19 19:52:52 +0000555
Rafael Espindola0766ae02014-06-06 19:26:12 +0000556 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
557 return Error(Loc, "cannot make section associative with .linkonce");
Rafael Espindola60ec3832013-11-19 19:52:52 +0000558
Nico Riecka37acf72013-07-06 12:13:10 +0000559 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
560 return Error(Loc, Twine("section '") + Current->getSectionName() +
561 "' is already linkonce");
562
Rafael Espindola0766ae02014-06-06 19:26:12 +0000563 Current->setSelection(Type);
Nico Riecka37acf72013-07-06 12:13:10 +0000564
565 if (getLexer().isNot(AsmToken::EndOfStatement))
566 return TokError("unexpected token in directive");
567
568 return false;
569}
570
Charles Davisc7250fa2011-05-22 21:12:15 +0000571bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000572 StringRef SymbolID;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000573 if (getParser().parseIdentifier(SymbolID))
Charles Davisc7250fa2011-05-22 21:12:15 +0000574 return true;
575
Charles Davisc7250fa2011-05-22 21:12:15 +0000576 if (getLexer().isNot(AsmToken::EndOfStatement))
577 return TokError("unexpected token in directive");
578
Jim Grosbach6f482002015-05-18 18:43:14 +0000579 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000580
Charles Davisc7250fa2011-05-22 21:12:15 +0000581 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000582 getStreamer().EmitWinCFIStartProc(Symbol);
Charles Davisc7250fa2011-05-22 21:12:15 +0000583 return false;
584}
585
586bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
587 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000588 getStreamer().EmitWinCFIEndProc();
Charles Davisc7250fa2011-05-22 21:12:15 +0000589 return false;
590}
591
592bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
593 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000594 getStreamer().EmitWinCFIStartChained();
Charles Davisc7250fa2011-05-22 21:12:15 +0000595 return false;
596}
597
598bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
599 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000600 getStreamer().EmitWinCFIEndChained();
Charles Davisc7250fa2011-05-22 21:12:15 +0000601 return false;
602}
603
604bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000605 StringRef SymbolID;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000606 if (getParser().parseIdentifier(SymbolID))
Charles Davisc7250fa2011-05-22 21:12:15 +0000607 return true;
608
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000609 if (getLexer().isNot(AsmToken::Comma))
610 return TokError("you must specify one or both of @unwind or @except");
611 Lex();
Charles Davisc7250fa2011-05-22 21:12:15 +0000612 bool unwind = false, except = false;
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000613 if (ParseAtUnwindOrAtExcept(unwind, except))
614 return true;
Charles Davisc7250fa2011-05-22 21:12:15 +0000615 if (getLexer().is(AsmToken::Comma)) {
616 Lex();
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000617 if (ParseAtUnwindOrAtExcept(unwind, except))
Charles Davisc7250fa2011-05-22 21:12:15 +0000618 return true;
619 }
620 if (getLexer().isNot(AsmToken::EndOfStatement))
621 return TokError("unexpected token in directive");
622
Jim Grosbach6f482002015-05-18 18:43:14 +0000623 MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000624
Charles Davisc7250fa2011-05-22 21:12:15 +0000625 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000626 getStreamer().EmitWinEHHandler(handler, unwind, except);
Charles Davisc7250fa2011-05-22 21:12:15 +0000627 return false;
628}
629
630bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
631 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000632 getStreamer().EmitWinEHHandlerData();
Charles Davisc7250fa2011-05-22 21:12:15 +0000633 return false;
634}
635
636bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
Michael Ilseman5be22a12014-12-12 21:48:03 +0000637 unsigned Reg = 0;
Charles Davis7f6176c2011-05-24 20:06:30 +0000638 if (ParseSEHRegisterNumber(Reg))
639 return true;
640
641 if (getLexer().isNot(AsmToken::EndOfStatement))
642 return TokError("unexpected token in directive");
643
644 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000645 getStreamer().EmitWinCFIPushReg(Reg);
Charles Davis7f6176c2011-05-24 20:06:30 +0000646 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000647}
648
649bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
Michael Ilseman5be22a12014-12-12 21:48:03 +0000650 unsigned Reg = 0;
Charles Davis7f6176c2011-05-24 20:06:30 +0000651 int64_t Off;
652 if (ParseSEHRegisterNumber(Reg))
653 return true;
Charles Davis2f6ecea2011-05-25 21:43:45 +0000654 if (getLexer().isNot(AsmToken::Comma))
655 return TokError("you must specify a stack pointer offset");
656
657 Lex();
Charles Davis7f6176c2011-05-24 20:06:30 +0000658 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000659 if (getParser().parseAbsoluteExpression(Off))
Charles Davis7f6176c2011-05-24 20:06:30 +0000660 return true;
661
662 if (Off & 0x0F)
663 return Error(startLoc, "offset is not a multiple of 16");
664
665 if (getLexer().isNot(AsmToken::EndOfStatement))
666 return TokError("unexpected token in directive");
667
668 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000669 getStreamer().EmitWinCFISetFrame(Reg, Off);
Charles Davis7f6176c2011-05-24 20:06:30 +0000670 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000671}
672
Charles Davisd9eafdc2011-05-23 16:43:09 +0000673bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
674 int64_t Size;
Charles Davis7f6176c2011-05-24 20:06:30 +0000675 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000676 if (getParser().parseAbsoluteExpression(Size))
Charles Davisd9eafdc2011-05-23 16:43:09 +0000677 return true;
678
Charles Davis7f6176c2011-05-24 20:06:30 +0000679 if (Size & 7)
680 return Error(startLoc, "size is not a multiple of 8");
681
Charles Davisd9eafdc2011-05-23 16:43:09 +0000682 if (getLexer().isNot(AsmToken::EndOfStatement))
683 return TokError("unexpected token in directive");
684
685 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000686 getStreamer().EmitWinCFIAllocStack(Size);
Charles Davisd9eafdc2011-05-23 16:43:09 +0000687 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000688}
689
690bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
Michael Ilseman5be22a12014-12-12 21:48:03 +0000691 unsigned Reg = 0;
Charles Davis7f6176c2011-05-24 20:06:30 +0000692 int64_t Off;
693 if (ParseSEHRegisterNumber(Reg))
694 return true;
Charles Davis828b00c2011-05-25 04:51:25 +0000695 if (getLexer().isNot(AsmToken::Comma))
Charles Davis2f6ecea2011-05-25 21:43:45 +0000696 return TokError("you must specify an offset on the stack");
Charles Davis828b00c2011-05-25 04:51:25 +0000697
698 Lex();
Charles Davis7f6176c2011-05-24 20:06:30 +0000699 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000700 if (getParser().parseAbsoluteExpression(Off))
Charles Davis7f6176c2011-05-24 20:06:30 +0000701 return true;
702
703 if (Off & 7)
704 return Error(startLoc, "size is not a multiple of 8");
705
706 if (getLexer().isNot(AsmToken::EndOfStatement))
707 return TokError("unexpected token in directive");
708
709 Lex();
710 // FIXME: Err on %xmm* registers
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000711 getStreamer().EmitWinCFISaveReg(Reg, Off);
Charles Davis7f6176c2011-05-24 20:06:30 +0000712 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000713}
714
Charles Davis7f6176c2011-05-24 20:06:30 +0000715// FIXME: This method is inherently x86-specific. It should really be in the
716// x86 backend.
Charles Davisc7250fa2011-05-22 21:12:15 +0000717bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
Michael Ilseman5be22a12014-12-12 21:48:03 +0000718 unsigned Reg = 0;
Charles Davis7f6176c2011-05-24 20:06:30 +0000719 int64_t Off;
720 if (ParseSEHRegisterNumber(Reg))
721 return true;
Charles Davis828b00c2011-05-25 04:51:25 +0000722 if (getLexer().isNot(AsmToken::Comma))
Charles Davis2f6ecea2011-05-25 21:43:45 +0000723 return TokError("you must specify an offset on the stack");
Charles Davis828b00c2011-05-25 04:51:25 +0000724
725 Lex();
Charles Davis7f6176c2011-05-24 20:06:30 +0000726 SMLoc startLoc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000727 if (getParser().parseAbsoluteExpression(Off))
Charles Davis7f6176c2011-05-24 20:06:30 +0000728 return true;
729
730 if (getLexer().isNot(AsmToken::EndOfStatement))
731 return TokError("unexpected token in directive");
732
733 if (Off & 0x0F)
734 return Error(startLoc, "offset is not a multiple of 16");
735
736 Lex();
737 // FIXME: Err on non-%xmm* registers
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000738 getStreamer().EmitWinCFISaveXMM(Reg, Off);
Charles Davis7f6176c2011-05-24 20:06:30 +0000739 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000740}
741
Charles Davisd9eafdc2011-05-23 16:43:09 +0000742bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
Charles Davisb0c4f392011-05-25 04:08:15 +0000743 bool Code = false;
Charles Davisd9eafdc2011-05-23 16:43:09 +0000744 StringRef CodeID;
Charles Davisb0c4f392011-05-25 04:08:15 +0000745 if (getLexer().is(AsmToken::At)) {
746 SMLoc startLoc = getLexer().getLoc();
747 Lex();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000748 if (!getParser().parseIdentifier(CodeID)) {
Charles Davisb0c4f392011-05-25 04:08:15 +0000749 if (CodeID != "code")
750 return Error(startLoc, "expected @code");
751 Code = true;
752 }
Charles Davisd9eafdc2011-05-23 16:43:09 +0000753 }
754
755 if (getLexer().isNot(AsmToken::EndOfStatement))
756 return TokError("unexpected token in directive");
757
758 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000759 getStreamer().EmitWinCFIPushFrame(Code);
Charles Davisd9eafdc2011-05-23 16:43:09 +0000760 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000761}
762
763bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
764 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000765 getStreamer().EmitWinCFIEndProlog();
Charles Davisc7250fa2011-05-22 21:12:15 +0000766 return false;
767}
768
769bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
770 StringRef identifier;
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000771 if (getLexer().isNot(AsmToken::At))
772 return TokError("a handler attribute must begin with '@'");
Charles Davisc7250fa2011-05-22 21:12:15 +0000773 SMLoc startLoc = getLexer().getLoc();
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000774 Lex();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000775 if (getParser().parseIdentifier(identifier))
Charles Davisc7250fa2011-05-22 21:12:15 +0000776 return Error(startLoc, "expected @unwind or @except");
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000777 if (identifier == "unwind")
Charles Davisc7250fa2011-05-22 21:12:15 +0000778 unwind = true;
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000779 else if (identifier == "except")
Charles Davisc7250fa2011-05-22 21:12:15 +0000780 except = true;
781 else
782 return Error(startLoc, "expected @unwind or @except");
783 return false;
784}
785
Charles Davis7f6176c2011-05-24 20:06:30 +0000786bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
Charles Davis7f6176c2011-05-24 20:06:30 +0000787 SMLoc startLoc = getLexer().getLoc();
Charles Davis828b00c2011-05-25 04:51:25 +0000788 if (getLexer().is(AsmToken::Percent)) {
Bill Wendlingbc07a892013-06-18 07:20:20 +0000789 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
Charles Davis7f6176c2011-05-24 20:06:30 +0000790 SMLoc endLoc;
791 unsigned LLVMRegNo;
792 if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
Charles Davis828b00c2011-05-25 04:51:25 +0000793 return true;
Charles Davis7f6176c2011-05-24 20:06:30 +0000794
Evan Chengd60fa58b2011-07-18 20:57:22 +0000795#if 0
796 // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
797 // violation so this validation code is disabled.
798
Charles Davis7f6176c2011-05-24 20:06:30 +0000799 // Check that this is a non-volatile register.
Evan Chenga83b37a2011-07-15 02:09:41 +0000800 const unsigned *NVRegs = TAI.getCalleeSavedRegs();
Charles Davis7f6176c2011-05-24 20:06:30 +0000801 unsigned i;
802 for (i = 0; NVRegs[i] != 0; ++i)
803 if (NVRegs[i] == LLVMRegNo)
804 break;
805 if (NVRegs[i] == 0)
806 return Error(startLoc, "expected non-volatile register");
Evan Chengd60fa58b2011-07-18 20:57:22 +0000807#endif
Charles Davis7f6176c2011-05-24 20:06:30 +0000808
Bill Wendlingbc07a892013-06-18 07:20:20 +0000809 int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
Charles Davis7f6176c2011-05-24 20:06:30 +0000810 if (SEHRegNo < 0)
811 return Error(startLoc,"register can't be represented in SEH unwind info");
812 RegNo = SEHRegNo;
813 }
Charles Davis828b00c2011-05-25 04:51:25 +0000814 else {
815 int64_t n;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000816 if (getParser().parseAbsoluteExpression(n))
Charles Davis828b00c2011-05-25 04:51:25 +0000817 return true;
818 if (n > 15)
819 return Error(startLoc, "register number is too high");
Charles Davis7f6176c2011-05-24 20:06:30 +0000820 RegNo = n;
Charles Davis828b00c2011-05-25 04:51:25 +0000821 }
Charles Davis7f6176c2011-05-24 20:06:30 +0000822
Charles Davis7f6176c2011-05-24 20:06:30 +0000823 return false;
824}
825
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000826namespace llvm {
827
828MCAsmParserExtension *createCOFFAsmParser() {
829 return new COFFAsmParser;
830}
831
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +0000832} // end namespace llvm