1 //===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/ADT/StringRef.h"
10 #include "llvm/ADT/StringSwitch.h"
11 #include "llvm/ADT/Triple.h"
12 #include "llvm/ADT/Twine.h"
13 #include "llvm/BinaryFormat/COFF.h"
14 #include "llvm/MC/MCContext.h"
15 #include "llvm/MC/MCDirectives.h"
16 #include "llvm/MC/MCParser/MCAsmLexer.h"
17 #include "llvm/MC/MCParser/MCAsmParserExtension.h"
18 #include "llvm/MC/MCSectionCOFF.h"
19 #include "llvm/MC/MCStreamer.h"
20 #include "llvm/MC/SectionKind.h"
21 #include "llvm/Support/SMLoc.h"
22 #include <cassert>
23 #include <cstdint>
24 #include <limits>
25 #include <utility>
26
27 using namespace llvm;
28
29 namespace {
30
31 class COFFAsmParser : public MCAsmParserExtension {
32 template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
addDirectiveHandler(StringRef Directive)33 void addDirectiveHandler(StringRef Directive) {
34 MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
35 this, HandleDirective<COFFAsmParser, HandlerMethod>);
36 getParser().addDirectiveHandler(Directive, Handler);
37 }
38
39 bool ParseSectionSwitch(StringRef Section,
40 unsigned Characteristics,
41 SectionKind Kind);
42
43 bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
44 SectionKind Kind, StringRef COMDATSymName,
45 COFF::COMDATType Type);
46
47 bool ParseSectionName(StringRef &SectionName);
48 bool ParseSectionFlags(StringRef SectionName, StringRef FlagsString,
49 unsigned *Flags);
50
Initialize(MCAsmParser & Parser)51 void Initialize(MCAsmParser &Parser) override {
52 // Call the base implementation.
53 MCAsmParserExtension::Initialize(Parser);
54
55 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
56 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
57 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
58 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
59 addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
60 addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
61 addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
62 addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
63 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
64 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymIdx>(".symidx");
65 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
66 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
67 addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
68 addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva");
69 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
70 addDirectiveHandler<&COFFAsmParser::ParseDirectiveCGProfile>(".cg_profile");
71
72 // Win64 EH directives.
73 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
74 ".seh_proc");
75 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
76 ".seh_endproc");
77 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndFuncletOrFunc>(
78 ".seh_endfunclet");
79 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
80 ".seh_startchained");
81 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
82 ".seh_endchained");
83 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
84 ".seh_handler");
85 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
86 ".seh_handlerdata");
87 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
88 ".seh_stackalloc");
89 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
90 ".seh_endprologue");
91 }
92
ParseSectionDirectiveText(StringRef,SMLoc)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
ParseSectionDirectiveData(StringRef,SMLoc)101 bool ParseSectionDirectiveData(StringRef, SMLoc) {
102 return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
103 COFF::IMAGE_SCN_MEM_READ |
104 COFF::IMAGE_SCN_MEM_WRITE,
105 SectionKind::getData());
106 }
107
ParseSectionDirectiveBSS(StringRef,SMLoc)108 bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
109 return ParseSectionSwitch(".bss",
110 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
111 | COFF::IMAGE_SCN_MEM_READ
112 | COFF::IMAGE_SCN_MEM_WRITE,
113 SectionKind::getBSS());
114 }
115
116 bool ParseDirectiveSection(StringRef, SMLoc);
117 bool ParseDirectiveDef(StringRef, SMLoc);
118 bool ParseDirectiveScl(StringRef, SMLoc);
119 bool ParseDirectiveType(StringRef, SMLoc);
120 bool ParseDirectiveEndef(StringRef, SMLoc);
121 bool ParseDirectiveSecRel32(StringRef, SMLoc);
122 bool ParseDirectiveSecIdx(StringRef, SMLoc);
123 bool ParseDirectiveSafeSEH(StringRef, SMLoc);
124 bool ParseDirectiveSymIdx(StringRef, SMLoc);
125 bool parseCOMDATType(COFF::COMDATType &Type);
126 bool ParseDirectiveLinkOnce(StringRef, SMLoc);
127 bool ParseDirectiveRVA(StringRef, SMLoc);
128 bool ParseDirectiveCGProfile(StringRef, SMLoc);
129
130 // Win64 EH directives.
131 bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
132 bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
133 bool ParseSEHDirectiveEndFuncletOrFunc(StringRef, SMLoc);
134 bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
135 bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
136 bool ParseSEHDirectiveHandler(StringRef, SMLoc);
137 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
138 bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
139 bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
140
141 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
142 bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
143
144 public:
145 COFFAsmParser() = default;
146 };
147
148 } // end anonymous namespace.
149
computeSectionKind(unsigned Flags)150 static SectionKind computeSectionKind(unsigned Flags) {
151 if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
152 return SectionKind::getText();
153 if (Flags & COFF::IMAGE_SCN_MEM_READ &&
154 (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
155 return SectionKind::getReadOnly();
156 return SectionKind::getData();
157 }
158
ParseSectionFlags(StringRef SectionName,StringRef FlagsString,unsigned * Flags)159 bool COFFAsmParser::ParseSectionFlags(StringRef SectionName,
160 StringRef FlagsString, unsigned *Flags) {
161 enum {
162 None = 0,
163 Alloc = 1 << 0,
164 Code = 1 << 1,
165 Load = 1 << 2,
166 InitData = 1 << 3,
167 Shared = 1 << 4,
168 NoLoad = 1 << 5,
169 NoRead = 1 << 6,
170 NoWrite = 1 << 7,
171 Discardable = 1 << 8,
172 Info = 1 << 9,
173 };
174
175 bool ReadOnlyRemoved = false;
176 unsigned SecFlags = None;
177
178 for (char FlagChar : FlagsString) {
179 switch (FlagChar) {
180 case 'a':
181 // Ignored.
182 break;
183
184 case 'b': // bss section
185 SecFlags |= Alloc;
186 if (SecFlags & InitData)
187 return TokError("conflicting section flags 'b' and 'd'.");
188 SecFlags &= ~Load;
189 break;
190
191 case 'd': // data section
192 SecFlags |= InitData;
193 if (SecFlags & Alloc)
194 return TokError("conflicting section flags 'b' and 'd'.");
195 SecFlags &= ~NoWrite;
196 if ((SecFlags & NoLoad) == 0)
197 SecFlags |= Load;
198 break;
199
200 case 'n': // section is not loaded
201 SecFlags |= NoLoad;
202 SecFlags &= ~Load;
203 break;
204
205 case 'D': // discardable
206 SecFlags |= Discardable;
207 break;
208
209 case 'r': // read-only
210 ReadOnlyRemoved = false;
211 SecFlags |= NoWrite;
212 if ((SecFlags & Code) == 0)
213 SecFlags |= InitData;
214 if ((SecFlags & NoLoad) == 0)
215 SecFlags |= Load;
216 break;
217
218 case 's': // shared section
219 SecFlags |= Shared | InitData;
220 SecFlags &= ~NoWrite;
221 if ((SecFlags & NoLoad) == 0)
222 SecFlags |= Load;
223 break;
224
225 case 'w': // writable
226 SecFlags &= ~NoWrite;
227 ReadOnlyRemoved = true;
228 break;
229
230 case 'x': // executable section
231 SecFlags |= Code;
232 if ((SecFlags & NoLoad) == 0)
233 SecFlags |= Load;
234 if (!ReadOnlyRemoved)
235 SecFlags |= NoWrite;
236 break;
237
238 case 'y': // not readable
239 SecFlags |= NoRead | NoWrite;
240 break;
241
242 case 'i': // info
243 SecFlags |= Info;
244 break;
245
246 default:
247 return TokError("unknown flag");
248 }
249 }
250
251 *Flags = 0;
252
253 if (SecFlags == None)
254 SecFlags = InitData;
255
256 if (SecFlags & Code)
257 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
258 if (SecFlags & InitData)
259 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
260 if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
261 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
262 if (SecFlags & NoLoad)
263 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
264 if ((SecFlags & Discardable) ||
265 MCSectionCOFF::isImplicitlyDiscardable(SectionName))
266 *Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE;
267 if ((SecFlags & NoRead) == 0)
268 *Flags |= COFF::IMAGE_SCN_MEM_READ;
269 if ((SecFlags & NoWrite) == 0)
270 *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
271 if (SecFlags & Shared)
272 *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
273 if (SecFlags & Info)
274 *Flags |= COFF::IMAGE_SCN_LNK_INFO;
275
276 return false;
277 }
278
279 /// ParseDirectiveSymbolAttribute
280 /// ::= { ".weak", ... } [ identifier ( , identifier )* ]
ParseDirectiveSymbolAttribute(StringRef Directive,SMLoc)281 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
282 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
283 .Case(".weak", MCSA_Weak)
284 .Default(MCSA_Invalid);
285 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
286 if (getLexer().isNot(AsmToken::EndOfStatement)) {
287 while (true) {
288 StringRef Name;
289
290 if (getParser().parseIdentifier(Name))
291 return TokError("expected identifier in directive");
292
293 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
294
295 getStreamer().emitSymbolAttribute(Sym, Attr);
296
297 if (getLexer().is(AsmToken::EndOfStatement))
298 break;
299
300 if (getLexer().isNot(AsmToken::Comma))
301 return TokError("unexpected token in directive");
302 Lex();
303 }
304 }
305
306 Lex();
307 return false;
308 }
309
ParseDirectiveCGProfile(StringRef S,SMLoc Loc)310 bool COFFAsmParser::ParseDirectiveCGProfile(StringRef S, SMLoc Loc) {
311 return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc);
312 }
313
ParseSectionSwitch(StringRef Section,unsigned Characteristics,SectionKind Kind)314 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
315 unsigned Characteristics,
316 SectionKind Kind) {
317 return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
318 }
319
ParseSectionSwitch(StringRef Section,unsigned Characteristics,SectionKind Kind,StringRef COMDATSymName,COFF::COMDATType Type)320 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
321 unsigned Characteristics,
322 SectionKind Kind,
323 StringRef COMDATSymName,
324 COFF::COMDATType Type) {
325 if (getLexer().isNot(AsmToken::EndOfStatement))
326 return TokError("unexpected token in section switching directive");
327 Lex();
328
329 getStreamer().switchSection(getContext().getCOFFSection(
330 Section, Characteristics, Kind, COMDATSymName, Type));
331
332 return false;
333 }
334
ParseSectionName(StringRef & SectionName)335 bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
336 if (!getLexer().is(AsmToken::Identifier) && !getLexer().is(AsmToken::String))
337 return true;
338
339 SectionName = getTok().getIdentifier();
340 Lex();
341 return false;
342 }
343
344 // .section name [, "flags"] [, identifier [ identifier ], identifier]
345 //
346 // Supported flags:
347 // a: Ignored.
348 // b: BSS section (uninitialized data)
349 // d: data section (initialized data)
350 // n: "noload" section (removed by linker)
351 // D: Discardable section
352 // 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.
ParseDirectiveSection(StringRef,SMLoc)359 bool 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
378 if (ParseSectionFlags(SectionName, FlagsStr, &Flags))
379 return true;
380 }
381
382 COFF::COMDATType Type = (COFF::COMDATType)0;
383 StringRef COMDATSymName;
384 if (getLexer().is(AsmToken::Comma)) {
385 Type = COFF::IMAGE_COMDAT_SELECT_ANY;
386 Lex();
387
388 Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
389
390 if (!getLexer().is(AsmToken::Identifier))
391 return TokError("expected comdat type such as 'discard' or 'largest' "
392 "after protection bits");
393
394 if (parseCOMDATType(Type))
395 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
405 if (getLexer().isNot(AsmToken::EndOfStatement))
406 return TokError("unexpected token in directive");
407
408 SectionKind Kind = computeSectionKind(Flags);
409 if (Kind.isText()) {
410 const Triple &T = getContext().getTargetTriple();
411 if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
412 Flags |= COFF::IMAGE_SCN_MEM_16BIT;
413 }
414 ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
415 return false;
416 }
417
ParseDirectiveDef(StringRef,SMLoc)418 bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
419 StringRef SymbolName;
420
421 if (getParser().parseIdentifier(SymbolName))
422 return TokError("expected identifier in directive");
423
424 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
425
426 getStreamer().beginCOFFSymbolDef(Sym);
427
428 Lex();
429 return false;
430 }
431
ParseDirectiveScl(StringRef,SMLoc)432 bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
433 int64_t SymbolStorageClass;
434 if (getParser().parseAbsoluteExpression(SymbolStorageClass))
435 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
ParseDirectiveType(StringRef,SMLoc)445 bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
446 int64_t Type;
447 if (getParser().parseAbsoluteExpression(Type))
448 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
ParseDirectiveEndef(StringRef,SMLoc)458 bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
459 Lex();
460 getStreamer().endCOFFSymbolDef();
461 return false;
462 }
463
ParseDirectiveSecRel32(StringRef,SMLoc)464 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
465 StringRef SymbolID;
466 if (getParser().parseIdentifier(SymbolID))
467 return TokError("expected identifier in directive");
468
469 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
477 if (getLexer().isNot(AsmToken::EndOfStatement))
478 return TokError("unexpected token in directive");
479
480 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()");
485
486 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
487
488 Lex();
489 getStreamer().emitCOFFSecRel32(Symbol, Offset);
490 return false;
491 }
492
ParseDirectiveRVA(StringRef,SMLoc)493 bool COFFAsmParser::ParseDirectiveRVA(StringRef, SMLoc) {
494 auto parseOp = [&]() -> bool {
495 StringRef SymbolID;
496 if (getParser().parseIdentifier(SymbolID))
497 return TokError("expected identifier in directive");
498
499 int64_t Offset = 0;
500 SMLoc OffsetLoc;
501 if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) {
502 OffsetLoc = getLexer().getLoc();
503 if (getParser().parseAbsoluteExpression(Offset))
504 return true;
505 }
506
507 if (Offset < std::numeric_limits<int32_t>::min() ||
508 Offset > std::numeric_limits<int32_t>::max())
509 return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less "
510 "than -2147483648 or greater than "
511 "2147483647");
512
513 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
514
515 getStreamer().emitCOFFImgRel32(Symbol, Offset);
516 return false;
517 };
518
519 if (getParser().parseMany(parseOp))
520 return addErrorSuffix(" in directive");
521 return false;
522 }
523
ParseDirectiveSafeSEH(StringRef,SMLoc)524 bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
525 StringRef SymbolID;
526 if (getParser().parseIdentifier(SymbolID))
527 return TokError("expected identifier in directive");
528
529 if (getLexer().isNot(AsmToken::EndOfStatement))
530 return TokError("unexpected token in directive");
531
532 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
533
534 Lex();
535 getStreamer().emitCOFFSafeSEH(Symbol);
536 return false;
537 }
538
ParseDirectiveSecIdx(StringRef,SMLoc)539 bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
540 StringRef SymbolID;
541 if (getParser().parseIdentifier(SymbolID))
542 return TokError("expected identifier in directive");
543
544 if (getLexer().isNot(AsmToken::EndOfStatement))
545 return TokError("unexpected token in directive");
546
547 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
548
549 Lex();
550 getStreamer().emitCOFFSectionIndex(Symbol);
551 return false;
552 }
553
ParseDirectiveSymIdx(StringRef,SMLoc)554 bool COFFAsmParser::ParseDirectiveSymIdx(StringRef, SMLoc) {
555 StringRef SymbolID;
556 if (getParser().parseIdentifier(SymbolID))
557 return TokError("expected identifier in directive");
558
559 if (getLexer().isNot(AsmToken::EndOfStatement))
560 return TokError("unexpected token in directive");
561
562 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
563
564 Lex();
565 getStreamer().emitCOFFSymbolIndex(Symbol);
566 return false;
567 }
568
569 /// ::= [ identifier ]
parseCOMDATType(COFF::COMDATType & Type)570 bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
571 StringRef TypeId = getTok().getIdentifier();
572
573 Type = StringSwitch<COFF::COMDATType>(TypeId)
574 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
575 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
576 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
577 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
578 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
579 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
580 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
581 .Default((COFF::COMDATType)0);
582
583 if (Type == 0)
584 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
585
586 Lex();
587
588 return false;
589 }
590
591 /// ParseDirectiveLinkOnce
592 /// ::= .linkonce [ identifier ]
ParseDirectiveLinkOnce(StringRef,SMLoc Loc)593 bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
594 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
595 if (getLexer().is(AsmToken::Identifier))
596 if (parseCOMDATType(Type))
597 return true;
598
599 const MCSectionCOFF *Current =
600 static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly());
601
602 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
603 return Error(Loc, "cannot make section associative with .linkonce");
604
605 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
606 return Error(Loc, Twine("section '") + Current->getName() +
607 "' is already linkonce");
608
609 Current->setSelection(Type);
610
611 if (getLexer().isNot(AsmToken::EndOfStatement))
612 return TokError("unexpected token in directive");
613
614 return false;
615 }
616
ParseSEHDirectiveStartProc(StringRef,SMLoc Loc)617 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc Loc) {
618 StringRef SymbolID;
619 if (getParser().parseIdentifier(SymbolID))
620 return true;
621
622 if (getLexer().isNot(AsmToken::EndOfStatement))
623 return TokError("unexpected token in directive");
624
625 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
626
627 Lex();
628 getStreamer().emitWinCFIStartProc(Symbol, Loc);
629 return false;
630 }
631
ParseSEHDirectiveEndProc(StringRef,SMLoc Loc)632 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc Loc) {
633 Lex();
634 getStreamer().emitWinCFIEndProc(Loc);
635 return false;
636 }
637
ParseSEHDirectiveEndFuncletOrFunc(StringRef,SMLoc Loc)638 bool COFFAsmParser::ParseSEHDirectiveEndFuncletOrFunc(StringRef, SMLoc Loc) {
639 Lex();
640 getStreamer().emitWinCFIFuncletOrFuncEnd(Loc);
641 return false;
642 }
643
ParseSEHDirectiveStartChained(StringRef,SMLoc Loc)644 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc Loc) {
645 Lex();
646 getStreamer().emitWinCFIStartChained(Loc);
647 return false;
648 }
649
ParseSEHDirectiveEndChained(StringRef,SMLoc Loc)650 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc Loc) {
651 Lex();
652 getStreamer().emitWinCFIEndChained(Loc);
653 return false;
654 }
655
ParseSEHDirectiveHandler(StringRef,SMLoc Loc)656 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc Loc) {
657 StringRef SymbolID;
658 if (getParser().parseIdentifier(SymbolID))
659 return true;
660
661 if (getLexer().isNot(AsmToken::Comma))
662 return TokError("you must specify one or both of @unwind or @except");
663 Lex();
664 bool unwind = false, except = false;
665 if (ParseAtUnwindOrAtExcept(unwind, except))
666 return true;
667 if (getLexer().is(AsmToken::Comma)) {
668 Lex();
669 if (ParseAtUnwindOrAtExcept(unwind, except))
670 return true;
671 }
672 if (getLexer().isNot(AsmToken::EndOfStatement))
673 return TokError("unexpected token in directive");
674
675 MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
676
677 Lex();
678 getStreamer().emitWinEHHandler(handler, unwind, except, Loc);
679 return false;
680 }
681
ParseSEHDirectiveHandlerData(StringRef,SMLoc Loc)682 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) {
683 Lex();
684 getStreamer().emitWinEHHandlerData();
685 return false;
686 }
687
ParseSEHDirectiveAllocStack(StringRef,SMLoc Loc)688 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) {
689 int64_t Size;
690 if (getParser().parseAbsoluteExpression(Size))
691 return true;
692
693 if (getLexer().isNot(AsmToken::EndOfStatement))
694 return TokError("unexpected token in directive");
695
696 Lex();
697 getStreamer().emitWinCFIAllocStack(Size, Loc);
698 return false;
699 }
700
ParseSEHDirectiveEndProlog(StringRef,SMLoc Loc)701 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) {
702 Lex();
703 getStreamer().emitWinCFIEndProlog(Loc);
704 return false;
705 }
706
ParseAtUnwindOrAtExcept(bool & unwind,bool & except)707 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
708 StringRef identifier;
709 if (getLexer().isNot(AsmToken::At) && getLexer().isNot(AsmToken::Percent))
710 return TokError("a handler attribute must begin with '@' or '%'");
711 SMLoc startLoc = getLexer().getLoc();
712 Lex();
713 if (getParser().parseIdentifier(identifier))
714 return Error(startLoc, "expected @unwind or @except");
715 if (identifier == "unwind")
716 unwind = true;
717 else if (identifier == "except")
718 except = true;
719 else
720 return Error(startLoc, "expected @unwind or @except");
721 return false;
722 }
723
724 namespace llvm {
725
createCOFFAsmParser()726 MCAsmParserExtension *createCOFFAsmParser() {
727 return new COFFAsmParser;
728 }
729
730 } // end namespace llvm
731