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