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

source code of llvm/lib/MC/MCParser/COFFAsmParser.cpp