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 };
173
174 bool ReadOnlyRemoved = false;
175 unsigned SecFlags = None;
176
177 for (char FlagChar : FlagsString) {
178 switch (FlagChar) {
179 case 'a':
180 // Ignored.
181 break;
182
183 case 'b': // bss section
184 SecFlags |= Alloc;
185 if (SecFlags & InitData)
186 return TokError("conflicting section flags 'b' and 'd'.");
187 SecFlags &= ~Load;
188 break;
189
190 case 'd': // data section
191 SecFlags |= InitData;
192 if (SecFlags & Alloc)
193 return TokError("conflicting section flags 'b' and 'd'.");
194 SecFlags &= ~NoWrite;
195 if ((SecFlags & NoLoad) == 0)
196 SecFlags |= Load;
197 break;
198
199 case 'n': // section is not loaded
200 SecFlags |= NoLoad;
201 SecFlags &= ~Load;
202 break;
203
204 case 'D': // discardable
205 SecFlags |= Discardable;
206 break;
207
208 case 'r': // read-only
209 ReadOnlyRemoved = false;
210 SecFlags |= NoWrite;
211 if ((SecFlags & Code) == 0)
212 SecFlags |= InitData;
213 if ((SecFlags & NoLoad) == 0)
214 SecFlags |= Load;
215 break;
216
217 case 's': // shared section
218 SecFlags |= Shared | InitData;
219 SecFlags &= ~NoWrite;
220 if ((SecFlags & NoLoad) == 0)
221 SecFlags |= Load;
222 break;
223
224 case 'w': // writable
225 SecFlags &= ~NoWrite;
226 ReadOnlyRemoved = true;
227 break;
228
229 case 'x': // executable section
230 SecFlags |= Code;
231 if ((SecFlags & NoLoad) == 0)
232 SecFlags |= Load;
233 if (!ReadOnlyRemoved)
234 SecFlags |= NoWrite;
235 break;
236
237 case 'y': // not readable
238 SecFlags |= NoRead | NoWrite;
239 break;
240
241 default:
242 return TokError("unknown flag");
243 }
244 }
245
246 *Flags = 0;
247
248 if (SecFlags == None)
249 SecFlags = InitData;
250
251 if (SecFlags & Code)
252 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
253 if (SecFlags & InitData)
254 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
255 if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
256 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
257 if (SecFlags & NoLoad)
258 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
259 if ((SecFlags & Discardable) ||
260 MCSectionCOFF::isImplicitlyDiscardable(SectionName))
261 *Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE;
262 if ((SecFlags & NoRead) == 0)
263 *Flags |= COFF::IMAGE_SCN_MEM_READ;
264 if ((SecFlags & NoWrite) == 0)
265 *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
266 if (SecFlags & Shared)
267 *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
268
269 return false;
270 }
271
272 /// ParseDirectiveSymbolAttribute
273 /// ::= { ".weak", ... } [ identifier ( , identifier )* ]
ParseDirectiveSymbolAttribute(StringRef Directive,SMLoc)274 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
275 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
276 .Case(".weak", MCSA_Weak)
277 .Default(MCSA_Invalid);
278 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
279 if (getLexer().isNot(AsmToken::EndOfStatement)) {
280 while (true) {
281 StringRef Name;
282
283 if (getParser().parseIdentifier(Name))
284 return TokError("expected identifier in directive");
285
286 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
287
288 getStreamer().emitSymbolAttribute(Sym, Attr);
289
290 if (getLexer().is(AsmToken::EndOfStatement))
291 break;
292
293 if (getLexer().isNot(AsmToken::Comma))
294 return TokError("unexpected token in directive");
295 Lex();
296 }
297 }
298
299 Lex();
300 return false;
301 }
302
ParseDirectiveCGProfile(StringRef S,SMLoc Loc)303 bool COFFAsmParser::ParseDirectiveCGProfile(StringRef S, SMLoc Loc) {
304 return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc);
305 }
306
ParseSectionSwitch(StringRef Section,unsigned Characteristics,SectionKind Kind)307 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
308 unsigned Characteristics,
309 SectionKind Kind) {
310 return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
311 }
312
ParseSectionSwitch(StringRef Section,unsigned Characteristics,SectionKind Kind,StringRef COMDATSymName,COFF::COMDATType Type)313 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
314 unsigned Characteristics,
315 SectionKind Kind,
316 StringRef COMDATSymName,
317 COFF::COMDATType Type) {
318 if (getLexer().isNot(AsmToken::EndOfStatement))
319 return TokError("unexpected token in section switching directive");
320 Lex();
321
322 getStreamer().switchSection(getContext().getCOFFSection(
323 Section, Characteristics, Kind, COMDATSymName, Type));
324
325 return false;
326 }
327
ParseSectionName(StringRef & SectionName)328 bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
329 if (!getLexer().is(AsmToken::Identifier) && !getLexer().is(AsmToken::String))
330 return true;
331
332 SectionName = getTok().getIdentifier();
333 Lex();
334 return false;
335 }
336
337 // .section name [, "flags"] [, identifier [ identifier ], identifier]
338 //
339 // Supported flags:
340 // a: Ignored.
341 // b: BSS section (uninitialized data)
342 // d: data section (initialized data)
343 // n: "noload" section (removed by linker)
344 // D: Discardable section
345 // r: Readable section
346 // s: Shared section
347 // w: Writable section
348 // x: Executable section
349 // y: Not-readable section (clears 'r')
350 //
351 // Subsections are not supported.
ParseDirectiveSection(StringRef,SMLoc)352 bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
353 StringRef SectionName;
354
355 if (ParseSectionName(SectionName))
356 return TokError("expected identifier in directive");
357
358 unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
359 COFF::IMAGE_SCN_MEM_READ |
360 COFF::IMAGE_SCN_MEM_WRITE;
361
362 if (getLexer().is(AsmToken::Comma)) {
363 Lex();
364
365 if (getLexer().isNot(AsmToken::String))
366 return TokError("expected string in directive");
367
368 StringRef FlagsStr = getTok().getStringContents();
369 Lex();
370
371 if (ParseSectionFlags(SectionName, FlagsStr, &Flags))
372 return true;
373 }
374
375 COFF::COMDATType Type = (COFF::COMDATType)0;
376 StringRef COMDATSymName;
377 if (getLexer().is(AsmToken::Comma)) {
378 Type = COFF::IMAGE_COMDAT_SELECT_ANY;
379 Lex();
380
381 Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
382
383 if (!getLexer().is(AsmToken::Identifier))
384 return TokError("expected comdat type such as 'discard' or 'largest' "
385 "after protection bits");
386
387 if (parseCOMDATType(Type))
388 return true;
389
390 if (getLexer().isNot(AsmToken::Comma))
391 return TokError("expected comma in directive");
392 Lex();
393
394 if (getParser().parseIdentifier(COMDATSymName))
395 return TokError("expected identifier in directive");
396 }
397
398 if (getLexer().isNot(AsmToken::EndOfStatement))
399 return TokError("unexpected token in directive");
400
401 SectionKind Kind = computeSectionKind(Flags);
402 if (Kind.isText()) {
403 const Triple &T = getContext().getTargetTriple();
404 if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
405 Flags |= COFF::IMAGE_SCN_MEM_16BIT;
406 }
407 ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
408 return false;
409 }
410
ParseDirectiveDef(StringRef,SMLoc)411 bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
412 StringRef SymbolName;
413
414 if (getParser().parseIdentifier(SymbolName))
415 return TokError("expected identifier in directive");
416
417 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
418
419 getStreamer().beginCOFFSymbolDef(Sym);
420
421 Lex();
422 return false;
423 }
424
ParseDirectiveScl(StringRef,SMLoc)425 bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
426 int64_t SymbolStorageClass;
427 if (getParser().parseAbsoluteExpression(SymbolStorageClass))
428 return true;
429
430 if (getLexer().isNot(AsmToken::EndOfStatement))
431 return TokError("unexpected token in directive");
432
433 Lex();
434 getStreamer().emitCOFFSymbolStorageClass(SymbolStorageClass);
435 return false;
436 }
437
ParseDirectiveType(StringRef,SMLoc)438 bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
439 int64_t Type;
440 if (getParser().parseAbsoluteExpression(Type))
441 return true;
442
443 if (getLexer().isNot(AsmToken::EndOfStatement))
444 return TokError("unexpected token in directive");
445
446 Lex();
447 getStreamer().emitCOFFSymbolType(Type);
448 return false;
449 }
450
ParseDirectiveEndef(StringRef,SMLoc)451 bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
452 Lex();
453 getStreamer().endCOFFSymbolDef();
454 return false;
455 }
456
ParseDirectiveSecRel32(StringRef,SMLoc)457 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
458 StringRef SymbolID;
459 if (getParser().parseIdentifier(SymbolID))
460 return TokError("expected identifier in directive");
461
462 int64_t Offset = 0;
463 SMLoc OffsetLoc;
464 if (getLexer().is(AsmToken::Plus)) {
465 OffsetLoc = getLexer().getLoc();
466 if (getParser().parseAbsoluteExpression(Offset))
467 return true;
468 }
469
470 if (getLexer().isNot(AsmToken::EndOfStatement))
471 return TokError("unexpected token in directive");
472
473 if (Offset < 0 || Offset > std::numeric_limits<uint32_t>::max())
474 return Error(
475 OffsetLoc,
476 "invalid '.secrel32' directive offset, can't be less "
477 "than zero or greater than std::numeric_limits<uint32_t>::max()");
478
479 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
480
481 Lex();
482 getStreamer().emitCOFFSecRel32(Symbol, Offset);
483 return false;
484 }
485
ParseDirectiveRVA(StringRef,SMLoc)486 bool COFFAsmParser::ParseDirectiveRVA(StringRef, SMLoc) {
487 auto parseOp = [&]() -> bool {
488 StringRef SymbolID;
489 if (getParser().parseIdentifier(SymbolID))
490 return TokError("expected identifier in directive");
491
492 int64_t Offset = 0;
493 SMLoc OffsetLoc;
494 if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) {
495 OffsetLoc = getLexer().getLoc();
496 if (getParser().parseAbsoluteExpression(Offset))
497 return true;
498 }
499
500 if (Offset < std::numeric_limits<int32_t>::min() ||
501 Offset > std::numeric_limits<int32_t>::max())
502 return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less "
503 "than -2147483648 or greater than "
504 "2147483647");
505
506 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
507
508 getStreamer().emitCOFFImgRel32(Symbol, Offset);
509 return false;
510 };
511
512 if (getParser().parseMany(parseOp))
513 return addErrorSuffix(" in directive");
514 return false;
515 }
516
ParseDirectiveSafeSEH(StringRef,SMLoc)517 bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
518 StringRef SymbolID;
519 if (getParser().parseIdentifier(SymbolID))
520 return TokError("expected identifier in directive");
521
522 if (getLexer().isNot(AsmToken::EndOfStatement))
523 return TokError("unexpected token in directive");
524
525 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
526
527 Lex();
528 getStreamer().emitCOFFSafeSEH(Symbol);
529 return false;
530 }
531
ParseDirectiveSecIdx(StringRef,SMLoc)532 bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
533 StringRef SymbolID;
534 if (getParser().parseIdentifier(SymbolID))
535 return TokError("expected identifier in directive");
536
537 if (getLexer().isNot(AsmToken::EndOfStatement))
538 return TokError("unexpected token in directive");
539
540 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
541
542 Lex();
543 getStreamer().emitCOFFSectionIndex(Symbol);
544 return false;
545 }
546
ParseDirectiveSymIdx(StringRef,SMLoc)547 bool COFFAsmParser::ParseDirectiveSymIdx(StringRef, SMLoc) {
548 StringRef SymbolID;
549 if (getParser().parseIdentifier(SymbolID))
550 return TokError("expected identifier in directive");
551
552 if (getLexer().isNot(AsmToken::EndOfStatement))
553 return TokError("unexpected token in directive");
554
555 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
556
557 Lex();
558 getStreamer().emitCOFFSymbolIndex(Symbol);
559 return false;
560 }
561
562 /// ::= [ identifier ]
parseCOMDATType(COFF::COMDATType & Type)563 bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
564 StringRef TypeId = getTok().getIdentifier();
565
566 Type = StringSwitch<COFF::COMDATType>(TypeId)
567 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
568 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
569 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
570 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
571 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
572 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
573 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
574 .Default((COFF::COMDATType)0);
575
576 if (Type == 0)
577 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
578
579 Lex();
580
581 return false;
582 }
583
584 /// ParseDirectiveLinkOnce
585 /// ::= .linkonce [ identifier ]
ParseDirectiveLinkOnce(StringRef,SMLoc Loc)586 bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
587 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
588 if (getLexer().is(AsmToken::Identifier))
589 if (parseCOMDATType(Type))
590 return true;
591
592 const MCSectionCOFF *Current =
593 static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly());
594
595 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
596 return Error(Loc, "cannot make section associative with .linkonce");
597
598 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
599 return Error(Loc, Twine("section '") + Current->getName() +
600 "' is already linkonce");
601
602 Current->setSelection(Type);
603
604 if (getLexer().isNot(AsmToken::EndOfStatement))
605 return TokError("unexpected token in directive");
606
607 return false;
608 }
609
ParseSEHDirectiveStartProc(StringRef,SMLoc Loc)610 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc Loc) {
611 StringRef SymbolID;
612 if (getParser().parseIdentifier(SymbolID))
613 return true;
614
615 if (getLexer().isNot(AsmToken::EndOfStatement))
616 return TokError("unexpected token in directive");
617
618 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
619
620 Lex();
621 getStreamer().emitWinCFIStartProc(Symbol, Loc);
622 return false;
623 }
624
ParseSEHDirectiveEndProc(StringRef,SMLoc Loc)625 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc Loc) {
626 Lex();
627 getStreamer().emitWinCFIEndProc(Loc);
628 return false;
629 }
630
ParseSEHDirectiveEndFuncletOrFunc(StringRef,SMLoc Loc)631 bool COFFAsmParser::ParseSEHDirectiveEndFuncletOrFunc(StringRef, SMLoc Loc) {
632 Lex();
633 getStreamer().emitWinCFIFuncletOrFuncEnd(Loc);
634 return false;
635 }
636
ParseSEHDirectiveStartChained(StringRef,SMLoc Loc)637 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc Loc) {
638 Lex();
639 getStreamer().emitWinCFIStartChained(Loc);
640 return false;
641 }
642
ParseSEHDirectiveEndChained(StringRef,SMLoc Loc)643 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc Loc) {
644 Lex();
645 getStreamer().emitWinCFIEndChained(Loc);
646 return false;
647 }
648
ParseSEHDirectiveHandler(StringRef,SMLoc Loc)649 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc Loc) {
650 StringRef SymbolID;
651 if (getParser().parseIdentifier(SymbolID))
652 return true;
653
654 if (getLexer().isNot(AsmToken::Comma))
655 return TokError("you must specify one or both of @unwind or @except");
656 Lex();
657 bool unwind = false, except = false;
658 if (ParseAtUnwindOrAtExcept(unwind, except))
659 return true;
660 if (getLexer().is(AsmToken::Comma)) {
661 Lex();
662 if (ParseAtUnwindOrAtExcept(unwind, except))
663 return true;
664 }
665 if (getLexer().isNot(AsmToken::EndOfStatement))
666 return TokError("unexpected token in directive");
667
668 MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
669
670 Lex();
671 getStreamer().emitWinEHHandler(handler, unwind, except, Loc);
672 return false;
673 }
674
ParseSEHDirectiveHandlerData(StringRef,SMLoc Loc)675 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) {
676 Lex();
677 getStreamer().emitWinEHHandlerData();
678 return false;
679 }
680
ParseSEHDirectiveAllocStack(StringRef,SMLoc Loc)681 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) {
682 int64_t Size;
683 if (getParser().parseAbsoluteExpression(Size))
684 return true;
685
686 if (getLexer().isNot(AsmToken::EndOfStatement))
687 return TokError("unexpected token in directive");
688
689 Lex();
690 getStreamer().emitWinCFIAllocStack(Size, Loc);
691 return false;
692 }
693
ParseSEHDirectiveEndProlog(StringRef,SMLoc Loc)694 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) {
695 Lex();
696 getStreamer().emitWinCFIEndProlog(Loc);
697 return false;
698 }
699
ParseAtUnwindOrAtExcept(bool & unwind,bool & except)700 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
701 StringRef identifier;
702 if (getLexer().isNot(AsmToken::At) && getLexer().isNot(AsmToken::Percent))
703 return TokError("a handler attribute must begin with '@' or '%'");
704 SMLoc startLoc = getLexer().getLoc();
705 Lex();
706 if (getParser().parseIdentifier(identifier))
707 return Error(startLoc, "expected @unwind or @except");
708 if (identifier == "unwind")
709 unwind = true;
710 else if (identifier == "except")
711 except = true;
712 else
713 return Error(startLoc, "expected @unwind or @except");
714 return false;
715 }
716
717 namespace llvm {
718
createCOFFAsmParser()719 MCAsmParserExtension *createCOFFAsmParser() {
720 return new COFFAsmParser;
721 }
722
723 } // end namespace llvm
724