blob: 2a754eab05bbde43aae9fa01ea83de8b74385994 [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");
Adrian McCarthydb2736d2018-01-09 23:49:30 +000068 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymIdx>(".symidx");
Adrian McCarthyce63a922018-01-08 17:12:01 +000069 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
Adrian McCarthydb2736d2018-01-09 23:49:30 +000070 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
Nico Riecka37acf72013-07-06 12:13:10 +000071 addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
Charles Davisc7250fa2011-05-22 21:12:15 +000072
73 // Win64 EH directives.
Jim Grosbachd2037eb2013-02-20 22:21:35 +000074 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
Charles Davisc7250fa2011-05-22 21:12:15 +000075 ".seh_proc");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000076 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
Charles Davisc7250fa2011-05-22 21:12:15 +000077 ".seh_endproc");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000078 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
Charles Davisc7250fa2011-05-22 21:12:15 +000079 ".seh_startchained");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000080 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
Charles Davisc7250fa2011-05-22 21:12:15 +000081 ".seh_endchained");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000082 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
Charles Davisc7250fa2011-05-22 21:12:15 +000083 ".seh_handler");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000084 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
Charles Davisc7250fa2011-05-22 21:12:15 +000085 ".seh_handlerdata");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000086 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
Charles Davisc7250fa2011-05-22 21:12:15 +000087 ".seh_pushreg");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000088 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
Charles Davisc7250fa2011-05-22 21:12:15 +000089 ".seh_setframe");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000090 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
Charles Davisc7250fa2011-05-22 21:12:15 +000091 ".seh_stackalloc");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000092 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
Charles Davisc7250fa2011-05-22 21:12:15 +000093 ".seh_savereg");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000094 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
Charles Davisc7250fa2011-05-22 21:12:15 +000095 ".seh_savexmm");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000096 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
Charles Davisc7250fa2011-05-22 21:12:15 +000097 ".seh_pushframe");
Jim Grosbachd2037eb2013-02-20 22:21:35 +000098 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
Charles Davisc7250fa2011-05-22 21:12:15 +000099 ".seh_endprologue");
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000100 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000101 }
102
103 bool ParseSectionDirectiveText(StringRef, SMLoc) {
104 return ParseSectionSwitch(".text",
105 COFF::IMAGE_SCN_CNT_CODE
106 | COFF::IMAGE_SCN_MEM_EXECUTE
107 | COFF::IMAGE_SCN_MEM_READ,
108 SectionKind::getText());
109 }
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +0000110
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000111 bool ParseSectionDirectiveData(StringRef, SMLoc) {
Rafael Espindola449711c2015-11-18 06:02:15 +0000112 return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
113 COFF::IMAGE_SCN_MEM_READ |
114 COFF::IMAGE_SCN_MEM_WRITE,
115 SectionKind::getData());
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000116 }
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +0000117
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000118 bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
119 return ParseSectionSwitch(".bss",
120 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
121 | COFF::IMAGE_SCN_MEM_READ
122 | COFF::IMAGE_SCN_MEM_WRITE,
123 SectionKind::getBSS());
124 }
125
Nico Rieck1558c5a2013-07-04 21:32:07 +0000126 bool ParseDirectiveSection(StringRef, SMLoc);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000127 bool ParseDirectiveDef(StringRef, SMLoc);
128 bool ParseDirectiveScl(StringRef, SMLoc);
129 bool ParseDirectiveType(StringRef, SMLoc);
130 bool ParseDirectiveEndef(StringRef, SMLoc);
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000131 bool ParseDirectiveSecRel32(StringRef, SMLoc);
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000132 bool ParseDirectiveSecIdx(StringRef, SMLoc);
David Majnemer4eecd302015-05-30 04:56:02 +0000133 bool ParseDirectiveSafeSEH(StringRef, SMLoc);
Adrian McCarthydb2736d2018-01-09 23:49:30 +0000134 bool ParseDirectiveSymIdx(StringRef, SMLoc);
Rafael Espindola0766ae02014-06-06 19:26:12 +0000135 bool parseCOMDATType(COFF::COMDATType &Type);
Nico Riecka37acf72013-07-06 12:13:10 +0000136 bool ParseDirectiveLinkOnce(StringRef, SMLoc);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000137
Charles Davisc7250fa2011-05-22 21:12:15 +0000138 // Win64 EH directives.
139 bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
140 bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
141 bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
142 bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
143 bool ParseSEHDirectiveHandler(StringRef, SMLoc);
144 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
Charles Davis7f6176c2011-05-24 20:06:30 +0000145 bool ParseSEHDirectivePushReg(StringRef, SMLoc);
146 bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
147 bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
148 bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
149 bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
150 bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
Charles Davisc7250fa2011-05-22 21:12:15 +0000151 bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
152
153 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
Charles Davis7f6176c2011-05-24 20:06:30 +0000154 bool ParseSEHRegisterNumber(unsigned &RegNo);
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000155 bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +0000156
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000157public:
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +0000158 COFFAsmParser() = default;
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000159};
160
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000161} // end annonomous namespace.
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000162
Nico Rieck1558c5a2013-07-04 21:32:07 +0000163static SectionKind computeSectionKind(unsigned Flags) {
164 if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
165 return SectionKind::getText();
166 if (Flags & COFF::IMAGE_SCN_MEM_READ &&
167 (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
168 return SectionKind::getReadOnly();
Rafael Espindola449711c2015-11-18 06:02:15 +0000169 return SectionKind::getData();
Nico Rieck1558c5a2013-07-04 21:32:07 +0000170}
171
Reid Kleckner31263732016-09-14 22:41:50 +0000172bool COFFAsmParser::ParseSectionFlags(StringRef SectionName,
173 StringRef FlagsString, unsigned *Flags) {
Nico Rieck1558c5a2013-07-04 21:32:07 +0000174 enum {
Reid Kleckner31263732016-09-14 22:41:50 +0000175 None = 0,
176 Alloc = 1 << 0,
177 Code = 1 << 1,
178 Load = 1 << 2,
179 InitData = 1 << 3,
180 Shared = 1 << 4,
181 NoLoad = 1 << 5,
182 NoRead = 1 << 6,
183 NoWrite = 1 << 7,
184 Discardable = 1 << 8,
Nico Rieck1558c5a2013-07-04 21:32:07 +0000185 };
186
187 bool ReadOnlyRemoved = false;
188 unsigned SecFlags = None;
189
David Majnemerbee5f752014-07-04 23:15:28 +0000190 for (char FlagChar : FlagsString) {
191 switch (FlagChar) {
Nico Rieck1558c5a2013-07-04 21:32:07 +0000192 case 'a':
193 // Ignored.
194 break;
195
196 case 'b': // bss section
197 SecFlags |= Alloc;
198 if (SecFlags & InitData)
199 return TokError("conflicting section flags 'b' and 'd'.");
200 SecFlags &= ~Load;
201 break;
202
203 case 'd': // data section
204 SecFlags |= InitData;
205 if (SecFlags & Alloc)
206 return TokError("conflicting section flags 'b' and 'd'.");
207 SecFlags &= ~NoWrite;
208 if ((SecFlags & NoLoad) == 0)
209 SecFlags |= Load;
210 break;
211
212 case 'n': // section is not loaded
213 SecFlags |= NoLoad;
214 SecFlags &= ~Load;
215 break;
216
Reid Kleckner31263732016-09-14 22:41:50 +0000217 case 'D': // discardable
218 SecFlags |= Discardable;
219 break;
220
Nico Rieck1558c5a2013-07-04 21:32:07 +0000221 case 'r': // read-only
222 ReadOnlyRemoved = false;
223 SecFlags |= NoWrite;
224 if ((SecFlags & Code) == 0)
225 SecFlags |= InitData;
226 if ((SecFlags & NoLoad) == 0)
227 SecFlags |= Load;
228 break;
229
230 case 's': // shared section
231 SecFlags |= Shared | InitData;
232 SecFlags &= ~NoWrite;
233 if ((SecFlags & NoLoad) == 0)
234 SecFlags |= Load;
235 break;
236
237 case 'w': // writable
238 SecFlags &= ~NoWrite;
239 ReadOnlyRemoved = true;
240 break;
241
242 case 'x': // executable section
243 SecFlags |= Code;
244 if ((SecFlags & NoLoad) == 0)
245 SecFlags |= Load;
246 if (!ReadOnlyRemoved)
247 SecFlags |= NoWrite;
248 break;
249
250 case 'y': // not readable
251 SecFlags |= NoRead | NoWrite;
252 break;
253
254 default:
255 return TokError("unknown flag");
256 }
257 }
258
259 *Flags = 0;
260
261 if (SecFlags == None)
262 SecFlags = InitData;
263
264 if (SecFlags & Code)
265 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
266 if (SecFlags & InitData)
267 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
268 if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
269 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
270 if (SecFlags & NoLoad)
271 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
Reid Kleckner31263732016-09-14 22:41:50 +0000272 if ((SecFlags & Discardable) ||
273 MCSectionCOFF::isImplicitlyDiscardable(SectionName))
274 *Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE;
Nico Rieck1558c5a2013-07-04 21:32:07 +0000275 if ((SecFlags & NoRead) == 0)
276 *Flags |= COFF::IMAGE_SCN_MEM_READ;
277 if ((SecFlags & NoWrite) == 0)
278 *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
279 if (SecFlags & Shared)
280 *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
281
282 return false;
283}
284
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000285/// ParseDirectiveSymbolAttribute
286/// ::= { ".weak", ... } [ identifier ( , identifier )* ]
287bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
288 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
289 .Case(".weak", MCSA_Weak)
290 .Default(MCSA_Invalid);
291 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
292 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +0000293 while (true) {
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000294 StringRef Name;
295
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000296 if (getParser().parseIdentifier(Name))
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000297 return TokError("expected identifier in directive");
298
Jim Grosbach6f482002015-05-18 18:43:14 +0000299 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach38b1ed82011-07-25 17:55:35 +0000300
301 getStreamer().EmitSymbolAttribute(Sym, Attr);
302
303 if (getLexer().is(AsmToken::EndOfStatement))
304 break;
305
306 if (getLexer().isNot(AsmToken::Comma))
307 return TokError("unexpected token in directive");
308 Lex();
309 }
310 }
311
312 Lex();
313 return false;
314}
315
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000316bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
317 unsigned Characteristics,
318 SectionKind Kind) {
David Majnemerc57d0382014-06-27 17:19:44 +0000319 return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
Rafael Espindola60ec3832013-11-19 19:52:52 +0000320}
321
322bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
323 unsigned Characteristics,
324 SectionKind Kind,
325 StringRef COMDATSymName,
Rafael Espindola0766ae02014-06-06 19:26:12 +0000326 COFF::COMDATType Type) {
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000327 if (getLexer().isNot(AsmToken::EndOfStatement))
328 return TokError("unexpected token in section switching directive");
329 Lex();
330
331 getStreamer().SwitchSection(getContext().getCOFFSection(
Rafael Espindola0766ae02014-06-06 19:26:12 +0000332 Section, Characteristics, Kind, COMDATSymName, Type));
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000333
334 return false;
335}
336
Nico Rieck1558c5a2013-07-04 21:32:07 +0000337bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
Hans Wennborg7ddcdc82013-10-18 02:14:40 +0000338 if (!getLexer().is(AsmToken::Identifier))
339 return true;
340
341 SectionName = getTok().getIdentifier();
342 Lex();
343 return false;
Nico Rieck1558c5a2013-07-04 21:32:07 +0000344}
345
Rafael Espindola60ec3832013-11-19 19:52:52 +0000346// .section name [, "flags"] [, identifier [ identifier ], identifier]
Nico Rieck1558c5a2013-07-04 21:32:07 +0000347//
348// Supported flags:
349// a: Ignored.
350// b: BSS section (uninitialized data)
351// d: data section (initialized data)
Reid Kleckner31263732016-09-14 22:41:50 +0000352// n: "noload" section (removed by linker)
353// D: Discardable section
Nico Rieck1558c5a2013-07-04 21:32:07 +0000354// r: Readable section
355// s: Shared section
356// w: Writable section
357// x: Executable section
358// y: Not-readable section (clears 'r')
359//
360// Subsections are not supported.
361bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
362 StringRef SectionName;
363
364 if (ParseSectionName(SectionName))
365 return TokError("expected identifier in directive");
366
367 unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
368 COFF::IMAGE_SCN_MEM_READ |
369 COFF::IMAGE_SCN_MEM_WRITE;
370
371 if (getLexer().is(AsmToken::Comma)) {
372 Lex();
373
374 if (getLexer().isNot(AsmToken::String))
375 return TokError("expected string in directive");
376
377 StringRef FlagsStr = getTok().getStringContents();
378 Lex();
379
Reid Kleckner31263732016-09-14 22:41:50 +0000380 if (ParseSectionFlags(SectionName, FlagsStr, &Flags))
Nico Rieck1558c5a2013-07-04 21:32:07 +0000381 return true;
382 }
383
David Majnemerc57d0382014-06-27 17:19:44 +0000384 COFF::COMDATType Type = (COFF::COMDATType)0;
Rafael Espindola60ec3832013-11-19 19:52:52 +0000385 StringRef COMDATSymName;
386 if (getLexer().is(AsmToken::Comma)) {
Aaron Ballman3182ee92015-06-09 12:03:46 +0000387 Type = COFF::IMAGE_COMDAT_SELECT_ANY;
Rafael Espindola60ec3832013-11-19 19:52:52 +0000388 Lex();
389
390 Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
391
Reid Kleckner21aedc42014-08-11 18:34:43 +0000392 if (!getLexer().is(AsmToken::Identifier))
393 return TokError("expected comdat type such as 'discard' or 'largest' "
394 "after protection bits");
395
Rafael Espindola0766ae02014-06-06 19:26:12 +0000396 if (parseCOMDATType(Type))
Rafael Espindola60ec3832013-11-19 19:52:52 +0000397 return true;
398
399 if (getLexer().isNot(AsmToken::Comma))
400 return TokError("expected comma in directive");
401 Lex();
402
403 if (getParser().parseIdentifier(COMDATSymName))
404 return TokError("expected identifier in directive");
405 }
406
Nico Rieck1558c5a2013-07-04 21:32:07 +0000407 if (getLexer().isNot(AsmToken::EndOfStatement))
408 return TokError("unexpected token in directive");
409
410 SectionKind Kind = computeSectionKind(Flags);
Saleem Abdulrasoolbdbc0082014-06-22 22:25:01 +0000411 if (Kind.isText()) {
412 const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
413 if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
414 Flags |= COFF::IMAGE_SCN_MEM_16BIT;
415 }
Rafael Espindola0766ae02014-06-06 19:26:12 +0000416 ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
Nico Rieck1558c5a2013-07-04 21:32:07 +0000417 return false;
418}
419
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000420bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
421 StringRef SymbolName;
422
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000423 if (getParser().parseIdentifier(SymbolName))
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000424 return TokError("expected identifier in directive");
425
Jim Grosbach6f482002015-05-18 18:43:14 +0000426 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000427
428 getStreamer().BeginCOFFSymbolDef(Sym);
429
430 Lex();
431 return false;
432}
433
434bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
435 int64_t SymbolStorageClass;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000436 if (getParser().parseAbsoluteExpression(SymbolStorageClass))
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000437 return true;
438
439 if (getLexer().isNot(AsmToken::EndOfStatement))
440 return TokError("unexpected token in directive");
441
442 Lex();
443 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
444 return false;
445}
446
447bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
448 int64_t Type;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000449 if (getParser().parseAbsoluteExpression(Type))
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000450 return true;
451
452 if (getLexer().isNot(AsmToken::EndOfStatement))
453 return TokError("unexpected token in directive");
454
455 Lex();
456 getStreamer().EmitCOFFSymbolType(Type);
457 return false;
458}
459
460bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
461 Lex();
462 getStreamer().EndCOFFSymbolDef();
463 return false;
464}
465
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000466bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
467 StringRef SymbolID;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000468 if (getParser().parseIdentifier(SymbolID))
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000469 return TokError("expected identifier in directive");
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000470
Keno Fischerf7d84ee2017-01-02 03:00:19 +0000471 int64_t Offset = 0;
472 SMLoc OffsetLoc;
473 if (getLexer().is(AsmToken::Plus)) {
474 OffsetLoc = getLexer().getLoc();
475 if (getParser().parseAbsoluteExpression(Offset))
476 return true;
477 }
478
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000479 if (getLexer().isNot(AsmToken::EndOfStatement))
480 return TokError("unexpected token in directive");
481
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +0000482 if (Offset < 0 || Offset > std::numeric_limits<uint32_t>::max())
483 return Error(
484 OffsetLoc,
485 "invalid '.secrel32' directive offset, can't be less "
486 "than zero or greater than std::numeric_limits<uint32_t>::max()");
Keno Fischerf7d84ee2017-01-02 03:00:19 +0000487
Jim Grosbach6f482002015-05-18 18:43:14 +0000488 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000489
490 Lex();
Keno Fischerf7d84ee2017-01-02 03:00:19 +0000491 getStreamer().EmitCOFFSecRel32(Symbol, Offset);
Rafael Espindolad3df3d32011-12-17 01:14:52 +0000492 return false;
493}
494
David Majnemer4eecd302015-05-30 04:56:02 +0000495bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
496 StringRef SymbolID;
497 if (getParser().parseIdentifier(SymbolID))
498 return TokError("expected identifier in directive");
499
500 if (getLexer().isNot(AsmToken::EndOfStatement))
501 return TokError("unexpected token in directive");
502
503 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
504
505 Lex();
506 getStreamer().EmitCOFFSafeSEH(Symbol);
507 return false;
508}
509
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000510bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
511 StringRef SymbolID;
512 if (getParser().parseIdentifier(SymbolID))
513 return TokError("expected identifier in directive");
514
515 if (getLexer().isNot(AsmToken::EndOfStatement))
516 return TokError("unexpected token in directive");
517
Jim Grosbach6f482002015-05-18 18:43:14 +0000518 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
Timur Iskhodzhanovc1fb2d62013-12-20 18:15:00 +0000519
520 Lex();
521 getStreamer().EmitCOFFSectionIndex(Symbol);
522 return false;
523}
524
Adrian McCarthydb2736d2018-01-09 23:49:30 +0000525bool COFFAsmParser::ParseDirectiveSymIdx(StringRef, SMLoc) {
526 StringRef SymbolID;
527 if (getParser().parseIdentifier(SymbolID))
528 return TokError("expected identifier in directive");
529
530 if (getLexer().isNot(AsmToken::EndOfStatement))
531 return TokError("unexpected token in directive");
532
533 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
534
535 Lex();
536 getStreamer().EmitCOFFSymbolIndex(Symbol);
537 return false;
538}
539
Rafael Espindola0766ae02014-06-06 19:26:12 +0000540/// ::= [ identifier ]
541bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
Rafael Espindola60ec3832013-11-19 19:52:52 +0000542 StringRef TypeId = getTok().getIdentifier();
Nico Riecka37acf72013-07-06 12:13:10 +0000543
Rafael Espindola60ec3832013-11-19 19:52:52 +0000544 Type = StringSwitch<COFF::COMDATType>(TypeId)
545 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
546 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
547 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
548 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
549 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
550 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
551 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
552 .Default((COFF::COMDATType)0);
Nico Riecka37acf72013-07-06 12:13:10 +0000553
Rafael Espindola60ec3832013-11-19 19:52:52 +0000554 if (Type == 0)
555 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
Nico Riecka37acf72013-07-06 12:13:10 +0000556
Rafael Espindola60ec3832013-11-19 19:52:52 +0000557 Lex();
Nico Riecka37acf72013-07-06 12:13:10 +0000558
Rafael Espindola60ec3832013-11-19 19:52:52 +0000559 return false;
560}
561
562/// ParseDirectiveLinkOnce
Rafael Espindola0766ae02014-06-06 19:26:12 +0000563/// ::= .linkonce [ identifier ]
Rafael Espindola60ec3832013-11-19 19:52:52 +0000564bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
565 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
Rafael Espindola60ec3832013-11-19 19:52:52 +0000566 if (getLexer().is(AsmToken::Identifier))
Rafael Espindola0766ae02014-06-06 19:26:12 +0000567 if (parseCOMDATType(Type))
Rafael Espindola60ec3832013-11-19 19:52:52 +0000568 return true;
569
Eric Christopher445c9522016-10-14 05:47:37 +0000570 const MCSectionCOFF *Current =
571 static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly());
Rafael Espindola60ec3832013-11-19 19:52:52 +0000572
Rafael Espindola0766ae02014-06-06 19:26:12 +0000573 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
574 return Error(Loc, "cannot make section associative with .linkonce");
Rafael Espindola60ec3832013-11-19 19:52:52 +0000575
Nico Riecka37acf72013-07-06 12:13:10 +0000576 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
577 return Error(Loc, Twine("section '") + Current->getSectionName() +
578 "' is already linkonce");
579
Rafael Espindola0766ae02014-06-06 19:26:12 +0000580 Current->setSelection(Type);
Nico Riecka37acf72013-07-06 12:13:10 +0000581
582 if (getLexer().isNot(AsmToken::EndOfStatement))
583 return TokError("unexpected token in directive");
584
585 return false;
586}
587
Reid Klecknere52d1e62017-10-10 01:26:25 +0000588bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc Loc) {
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000589 StringRef SymbolID;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000590 if (getParser().parseIdentifier(SymbolID))
Charles Davisc7250fa2011-05-22 21:12:15 +0000591 return true;
592
Charles Davisc7250fa2011-05-22 21:12:15 +0000593 if (getLexer().isNot(AsmToken::EndOfStatement))
594 return TokError("unexpected token in directive");
595
Jim Grosbach6f482002015-05-18 18:43:14 +0000596 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000597
Charles Davisc7250fa2011-05-22 21:12:15 +0000598 Lex();
Reid Klecknere52d1e62017-10-10 01:26:25 +0000599 getStreamer().EmitWinCFIStartProc(Symbol, Loc);
Charles Davisc7250fa2011-05-22 21:12:15 +0000600 return false;
601}
602
Reid Klecknere52d1e62017-10-10 01:26:25 +0000603bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc Loc) {
Charles Davisc7250fa2011-05-22 21:12:15 +0000604 Lex();
Reid Klecknere52d1e62017-10-10 01:26:25 +0000605 getStreamer().EmitWinCFIEndProc(Loc);
Charles Davisc7250fa2011-05-22 21:12:15 +0000606 return false;
607}
608
Reid Klecknere52d1e62017-10-10 01:26:25 +0000609bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc Loc) {
Charles Davisc7250fa2011-05-22 21:12:15 +0000610 Lex();
Reid Klecknere52d1e62017-10-10 01:26:25 +0000611 getStreamer().EmitWinCFIStartChained(Loc);
Charles Davisc7250fa2011-05-22 21:12:15 +0000612 return false;
613}
614
Reid Klecknere52d1e62017-10-10 01:26:25 +0000615bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc Loc) {
Charles Davisc7250fa2011-05-22 21:12:15 +0000616 Lex();
Reid Klecknere52d1e62017-10-10 01:26:25 +0000617 getStreamer().EmitWinCFIEndChained(Loc);
Charles Davisc7250fa2011-05-22 21:12:15 +0000618 return false;
619}
620
Reid Klecknere52d1e62017-10-10 01:26:25 +0000621bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc Loc) {
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000622 StringRef SymbolID;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000623 if (getParser().parseIdentifier(SymbolID))
Charles Davisc7250fa2011-05-22 21:12:15 +0000624 return true;
625
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000626 if (getLexer().isNot(AsmToken::Comma))
627 return TokError("you must specify one or both of @unwind or @except");
628 Lex();
Charles Davisc7250fa2011-05-22 21:12:15 +0000629 bool unwind = false, except = false;
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000630 if (ParseAtUnwindOrAtExcept(unwind, except))
631 return true;
Charles Davisc7250fa2011-05-22 21:12:15 +0000632 if (getLexer().is(AsmToken::Comma)) {
633 Lex();
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000634 if (ParseAtUnwindOrAtExcept(unwind, except))
Charles Davisc7250fa2011-05-22 21:12:15 +0000635 return true;
636 }
637 if (getLexer().isNot(AsmToken::EndOfStatement))
638 return TokError("unexpected token in directive");
639
Jim Grosbach6f482002015-05-18 18:43:14 +0000640 MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000641
Charles Davisc7250fa2011-05-22 21:12:15 +0000642 Lex();
Reid Klecknere52d1e62017-10-10 01:26:25 +0000643 getStreamer().EmitWinEHHandler(handler, unwind, except, Loc);
Charles Davisc7250fa2011-05-22 21:12:15 +0000644 return false;
645}
646
Reid Klecknere52d1e62017-10-10 01:26:25 +0000647bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) {
Charles Davisc7250fa2011-05-22 21:12:15 +0000648 Lex();
Saleem Abdulrasool7206a522014-06-29 01:52:01 +0000649 getStreamer().EmitWinEHHandlerData();
Charles Davisc7250fa2011-05-22 21:12:15 +0000650 return false;
651}
652
Reid Klecknere52d1e62017-10-10 01:26:25 +0000653bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc Loc) {
Michael Ilseman5be22a12014-12-12 21:48:03 +0000654 unsigned Reg = 0;
Charles Davis7f6176c2011-05-24 20:06:30 +0000655 if (ParseSEHRegisterNumber(Reg))
656 return true;
657
658 if (getLexer().isNot(AsmToken::EndOfStatement))
659 return TokError("unexpected token in directive");
660
661 Lex();
Reid Klecknere52d1e62017-10-10 01:26:25 +0000662 getStreamer().EmitWinCFIPushReg(Reg, Loc);
Charles Davis7f6176c2011-05-24 20:06:30 +0000663 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000664}
665
Reid Klecknere52d1e62017-10-10 01:26:25 +0000666bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc Loc) {
Michael Ilseman5be22a12014-12-12 21:48:03 +0000667 unsigned Reg = 0;
Charles Davis7f6176c2011-05-24 20:06:30 +0000668 int64_t Off;
669 if (ParseSEHRegisterNumber(Reg))
670 return true;
Charles Davis2f6ecea2011-05-25 21:43:45 +0000671 if (getLexer().isNot(AsmToken::Comma))
672 return TokError("you must specify a stack pointer offset");
673
674 Lex();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000675 if (getParser().parseAbsoluteExpression(Off))
Charles Davis7f6176c2011-05-24 20:06:30 +0000676 return true;
677
Charles Davis7f6176c2011-05-24 20:06:30 +0000678 if (getLexer().isNot(AsmToken::EndOfStatement))
679 return TokError("unexpected token in directive");
680
681 Lex();
Reid Klecknere52d1e62017-10-10 01:26:25 +0000682 getStreamer().EmitWinCFISetFrame(Reg, Off, Loc);
Charles Davis7f6176c2011-05-24 20:06:30 +0000683 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000684}
685
Reid Klecknere52d1e62017-10-10 01:26:25 +0000686bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) {
Charles Davisd9eafdc2011-05-23 16:43:09 +0000687 int64_t Size;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000688 if (getParser().parseAbsoluteExpression(Size))
Charles Davisd9eafdc2011-05-23 16:43:09 +0000689 return true;
690
691 if (getLexer().isNot(AsmToken::EndOfStatement))
692 return TokError("unexpected token in directive");
693
694 Lex();
Reid Klecknere52d1e62017-10-10 01:26:25 +0000695 getStreamer().EmitWinCFIAllocStack(Size, Loc);
Charles Davisd9eafdc2011-05-23 16:43:09 +0000696 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000697}
698
Reid Klecknere52d1e62017-10-10 01:26:25 +0000699bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc Loc) {
Michael Ilseman5be22a12014-12-12 21:48:03 +0000700 unsigned Reg = 0;
Charles Davis7f6176c2011-05-24 20:06:30 +0000701 int64_t Off;
702 if (ParseSEHRegisterNumber(Reg))
703 return true;
Charles Davis828b00c2011-05-25 04:51:25 +0000704 if (getLexer().isNot(AsmToken::Comma))
Charles Davis2f6ecea2011-05-25 21:43:45 +0000705 return TokError("you must specify an offset on the stack");
Charles Davis828b00c2011-05-25 04:51:25 +0000706
707 Lex();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000708 if (getParser().parseAbsoluteExpression(Off))
Charles Davis7f6176c2011-05-24 20:06:30 +0000709 return true;
710
Charles Davis7f6176c2011-05-24 20:06:30 +0000711 if (getLexer().isNot(AsmToken::EndOfStatement))
712 return TokError("unexpected token in directive");
713
714 Lex();
715 // FIXME: Err on %xmm* registers
Reid Klecknere52d1e62017-10-10 01:26:25 +0000716 getStreamer().EmitWinCFISaveReg(Reg, Off, Loc);
Charles Davis7f6176c2011-05-24 20:06:30 +0000717 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000718}
719
Charles Davis7f6176c2011-05-24 20:06:30 +0000720// FIXME: This method is inherently x86-specific. It should really be in the
721// x86 backend.
Reid Klecknere52d1e62017-10-10 01:26:25 +0000722bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc Loc) {
Michael Ilseman5be22a12014-12-12 21:48:03 +0000723 unsigned Reg = 0;
Charles Davis7f6176c2011-05-24 20:06:30 +0000724 int64_t Off;
725 if (ParseSEHRegisterNumber(Reg))
726 return true;
Charles Davis828b00c2011-05-25 04:51:25 +0000727 if (getLexer().isNot(AsmToken::Comma))
Charles Davis2f6ecea2011-05-25 21:43:45 +0000728 return TokError("you must specify an offset on the stack");
Charles Davis828b00c2011-05-25 04:51:25 +0000729
730 Lex();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000731 if (getParser().parseAbsoluteExpression(Off))
Charles Davis7f6176c2011-05-24 20:06:30 +0000732 return true;
733
734 if (getLexer().isNot(AsmToken::EndOfStatement))
735 return TokError("unexpected token in directive");
736
Charles Davis7f6176c2011-05-24 20:06:30 +0000737 Lex();
738 // FIXME: Err on non-%xmm* registers
Reid Klecknere52d1e62017-10-10 01:26:25 +0000739 getStreamer().EmitWinCFISaveXMM(Reg, Off, Loc);
Charles Davis7f6176c2011-05-24 20:06:30 +0000740 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000741}
742
Reid Klecknere52d1e62017-10-10 01:26:25 +0000743bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc Loc) {
Charles Davisb0c4f392011-05-25 04:08:15 +0000744 bool Code = false;
Charles Davisd9eafdc2011-05-23 16:43:09 +0000745 StringRef CodeID;
Charles Davisb0c4f392011-05-25 04:08:15 +0000746 if (getLexer().is(AsmToken::At)) {
747 SMLoc startLoc = getLexer().getLoc();
748 Lex();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000749 if (!getParser().parseIdentifier(CodeID)) {
Charles Davisb0c4f392011-05-25 04:08:15 +0000750 if (CodeID != "code")
751 return Error(startLoc, "expected @code");
752 Code = true;
753 }
Charles Davisd9eafdc2011-05-23 16:43:09 +0000754 }
755
756 if (getLexer().isNot(AsmToken::EndOfStatement))
757 return TokError("unexpected token in directive");
758
759 Lex();
Reid Klecknere52d1e62017-10-10 01:26:25 +0000760 getStreamer().EmitWinCFIPushFrame(Code, Loc);
Charles Davisd9eafdc2011-05-23 16:43:09 +0000761 return false;
Charles Davisc7250fa2011-05-22 21:12:15 +0000762}
763
Reid Klecknere52d1e62017-10-10 01:26:25 +0000764bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) {
Charles Davisc7250fa2011-05-22 21:12:15 +0000765 Lex();
Reid Klecknere52d1e62017-10-10 01:26:25 +0000766 getStreamer().EmitWinCFIEndProlog(Loc);
Charles Davisc7250fa2011-05-22 21:12:15 +0000767 return false;
768}
769
770bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
771 StringRef identifier;
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000772 if (getLexer().isNot(AsmToken::At))
773 return TokError("a handler attribute must begin with '@'");
Charles Davisc7250fa2011-05-22 21:12:15 +0000774 SMLoc startLoc = getLexer().getLoc();
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000775 Lex();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000776 if (getParser().parseIdentifier(identifier))
Charles Davisc7250fa2011-05-22 21:12:15 +0000777 return Error(startLoc, "expected @unwind or @except");
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000778 if (identifier == "unwind")
Charles Davisc7250fa2011-05-22 21:12:15 +0000779 unwind = true;
Charles Davisfc1e7ce2011-05-25 01:33:42 +0000780 else if (identifier == "except")
Charles Davisc7250fa2011-05-22 21:12:15 +0000781 except = true;
782 else
783 return Error(startLoc, "expected @unwind or @except");
784 return false;
785}
786
Charles Davis7f6176c2011-05-24 20:06:30 +0000787bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
Charles Davis7f6176c2011-05-24 20:06:30 +0000788 SMLoc startLoc = getLexer().getLoc();
Charles Davis828b00c2011-05-25 04:51:25 +0000789 if (getLexer().is(AsmToken::Percent)) {
Bill Wendlingbc07a892013-06-18 07:20:20 +0000790 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
Charles Davis7f6176c2011-05-24 20:06:30 +0000791 SMLoc endLoc;
792 unsigned LLVMRegNo;
793 if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
Charles Davis828b00c2011-05-25 04:51:25 +0000794 return true;
Charles Davis7f6176c2011-05-24 20:06:30 +0000795
Evan Chengd60fa58b2011-07-18 20:57:22 +0000796#if 0
797 // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
798 // violation so this validation code is disabled.
799
Charles Davis7f6176c2011-05-24 20:06:30 +0000800 // Check that this is a non-volatile register.
Evan Chenga83b37a2011-07-15 02:09:41 +0000801 const unsigned *NVRegs = TAI.getCalleeSavedRegs();
Charles Davis7f6176c2011-05-24 20:06:30 +0000802 unsigned i;
803 for (i = 0; NVRegs[i] != 0; ++i)
804 if (NVRegs[i] == LLVMRegNo)
805 break;
806 if (NVRegs[i] == 0)
807 return Error(startLoc, "expected non-volatile register");
Evan Chengd60fa58b2011-07-18 20:57:22 +0000808#endif
Charles Davis7f6176c2011-05-24 20:06:30 +0000809
Bill Wendlingbc07a892013-06-18 07:20:20 +0000810 int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
Charles Davis7f6176c2011-05-24 20:06:30 +0000811 if (SEHRegNo < 0)
812 return Error(startLoc,"register can't be represented in SEH unwind info");
813 RegNo = SEHRegNo;
814 }
Charles Davis828b00c2011-05-25 04:51:25 +0000815 else {
816 int64_t n;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000817 if (getParser().parseAbsoluteExpression(n))
Charles Davis828b00c2011-05-25 04:51:25 +0000818 return true;
819 if (n > 15)
820 return Error(startLoc, "register number is too high");
Charles Davis7f6176c2011-05-24 20:06:30 +0000821 RegNo = n;
Charles Davis828b00c2011-05-25 04:51:25 +0000822 }
Charles Davis7f6176c2011-05-24 20:06:30 +0000823
Charles Davis7f6176c2011-05-24 20:06:30 +0000824 return false;
825}
826
Michael J. Spencerc8dbdfd2010-10-09 11:01:07 +0000827namespace llvm {
828
829MCAsmParserExtension *createCOFFAsmParser() {
830 return new COFFAsmParser;
831}
832
Eugene Zelenko4b6ff6b2017-02-10 01:33:54 +0000833} // end namespace llvm