Line data Source code
1 : //===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #include "llvm/ADT/StringRef.h"
11 : #include "llvm/ADT/StringSwitch.h"
12 : #include "llvm/ADT/Triple.h"
13 : #include "llvm/ADT/Twine.h"
14 : #include "llvm/BinaryFormat/COFF.h"
15 : #include "llvm/MC/MCContext.h"
16 : #include "llvm/MC/MCDirectives.h"
17 : #include "llvm/MC/MCObjectFileInfo.h"
18 : #include "llvm/MC/MCParser/MCAsmLexer.h"
19 : #include "llvm/MC/MCParser/MCAsmParserExtension.h"
20 : #include "llvm/MC/MCParser/MCTargetAsmParser.h"
21 : #include "llvm/MC/MCRegisterInfo.h"
22 : #include "llvm/MC/MCSectionCOFF.h"
23 : #include "llvm/MC/MCStreamer.h"
24 : #include "llvm/MC/SectionKind.h"
25 : #include "llvm/Support/SMLoc.h"
26 : #include <cassert>
27 : #include <cstdint>
28 : #include <limits>
29 : #include <utility>
30 :
31 : using namespace llvm;
32 :
33 : namespace {
34 :
35 : class COFFAsmParser : public MCAsmParserExtension {
36 : template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
37 : void addDirectiveHandler(StringRef Directive) {
38 : MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
39 : this, HandleDirective<COFFAsmParser, HandlerMethod>);
40 364 : getParser().addDirectiveHandler(Directive, Handler);
41 : }
42 :
43 : bool ParseSectionSwitch(StringRef Section,
44 : unsigned Characteristics,
45 : SectionKind Kind);
46 :
47 : bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
48 : SectionKind Kind, StringRef COMDATSymName,
49 : COFF::COMDATType Type);
50 :
51 : bool ParseSectionName(StringRef &SectionName);
52 : bool ParseSectionFlags(StringRef SectionName, StringRef FlagsString,
53 : unsigned *Flags);
54 :
55 364 : void Initialize(MCAsmParser &Parser) override {
56 : // Call the base implementation.
57 364 : MCAsmParserExtension::Initialize(Parser);
58 :
59 364 : addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
60 364 : addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
61 364 : addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
62 364 : addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
63 364 : addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
64 364 : addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
65 364 : addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
66 364 : addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
67 364 : addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
68 364 : addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymIdx>(".symidx");
69 364 : addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
70 364 : addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
71 364 : addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
72 364 : addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva");
73 :
74 : // Win64 EH directives.
75 364 : addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
76 : ".seh_proc");
77 364 : addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
78 : ".seh_endproc");
79 364 : addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
80 : ".seh_startchained");
81 364 : addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
82 : ".seh_endchained");
83 364 : addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
84 : ".seh_handler");
85 364 : addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
86 : ".seh_handlerdata");
87 364 : addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
88 : ".seh_pushreg");
89 364 : addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
90 : ".seh_setframe");
91 364 : addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
92 : ".seh_stackalloc");
93 364 : addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
94 : ".seh_savereg");
95 364 : addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
96 : ".seh_savexmm");
97 364 : addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
98 : ".seh_pushframe");
99 364 : addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
100 : ".seh_endprologue");
101 364 : addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
102 364 : }
103 :
104 0 : bool ParseSectionDirectiveText(StringRef, SMLoc) {
105 0 : return ParseSectionSwitch(".text",
106 : COFF::IMAGE_SCN_CNT_CODE
107 : | COFF::IMAGE_SCN_MEM_EXECUTE
108 : | COFF::IMAGE_SCN_MEM_READ,
109 0 : SectionKind::getText());
110 : }
111 :
112 0 : bool ParseSectionDirectiveData(StringRef, SMLoc) {
113 0 : return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
114 : COFF::IMAGE_SCN_MEM_READ |
115 : COFF::IMAGE_SCN_MEM_WRITE,
116 0 : SectionKind::getData());
117 : }
118 :
119 0 : bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
120 0 : return ParseSectionSwitch(".bss",
121 : COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
122 : | COFF::IMAGE_SCN_MEM_READ
123 : | COFF::IMAGE_SCN_MEM_WRITE,
124 0 : SectionKind::getBSS());
125 : }
126 :
127 : bool ParseDirectiveSection(StringRef, SMLoc);
128 : bool ParseDirectiveDef(StringRef, SMLoc);
129 : bool ParseDirectiveScl(StringRef, SMLoc);
130 : bool ParseDirectiveType(StringRef, SMLoc);
131 : bool ParseDirectiveEndef(StringRef, SMLoc);
132 : bool ParseDirectiveSecRel32(StringRef, SMLoc);
133 : bool ParseDirectiveSecIdx(StringRef, SMLoc);
134 : bool ParseDirectiveSafeSEH(StringRef, SMLoc);
135 : bool ParseDirectiveSymIdx(StringRef, SMLoc);
136 : bool parseCOMDATType(COFF::COMDATType &Type);
137 : bool ParseDirectiveLinkOnce(StringRef, SMLoc);
138 : bool ParseDirectiveRVA(StringRef, SMLoc);
139 :
140 : // Win64 EH directives.
141 : bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
142 : bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
143 : bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
144 : bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
145 : bool ParseSEHDirectiveHandler(StringRef, SMLoc);
146 : bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
147 : bool ParseSEHDirectivePushReg(StringRef, SMLoc);
148 : bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
149 : bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
150 : bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
151 : bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
152 : bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
153 : bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
154 :
155 : bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
156 : bool ParseSEHRegisterNumber(unsigned &RegNo);
157 : bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
158 :
159 : public:
160 364 : COFFAsmParser() = default;
161 : };
162 :
163 : } // end annonomous namespace.
164 :
165 : static SectionKind computeSectionKind(unsigned Flags) {
166 0 : if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
167 : return SectionKind::getText();
168 0 : if (Flags & COFF::IMAGE_SCN_MEM_READ &&
169 0 : (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
170 : return SectionKind::getReadOnly();
171 : return SectionKind::getData();
172 : }
173 :
174 331 : bool COFFAsmParser::ParseSectionFlags(StringRef SectionName,
175 : StringRef FlagsString, unsigned *Flags) {
176 : enum {
177 : None = 0,
178 : Alloc = 1 << 0,
179 : Code = 1 << 1,
180 : Load = 1 << 2,
181 : InitData = 1 << 3,
182 : Shared = 1 << 4,
183 : NoLoad = 1 << 5,
184 : NoRead = 1 << 6,
185 : NoWrite = 1 << 7,
186 : Discardable = 1 << 8,
187 : };
188 :
189 : bool ReadOnlyRemoved = false;
190 : unsigned SecFlags = None;
191 :
192 951 : for (char FlagChar : FlagsString) {
193 624 : switch (FlagChar) {
194 : case 'a':
195 : // Ignored.
196 : break;
197 :
198 8 : case 'b': // bss section
199 : SecFlags |= Alloc;
200 8 : if (SecFlags & InitData)
201 2 : return TokError("conflicting section flags 'b' and 'd'.");
202 6 : SecFlags &= ~Load;
203 6 : break;
204 :
205 173 : case 'd': // data section
206 : SecFlags |= InitData;
207 173 : if (SecFlags & Alloc)
208 2 : return TokError("conflicting section flags 'b' and 'd'.");
209 171 : SecFlags &= ~NoWrite;
210 171 : if ((SecFlags & NoLoad) == 0)
211 171 : SecFlags |= Load;
212 : break;
213 :
214 5 : case 'n': // section is not loaded
215 : SecFlags |= NoLoad;
216 5 : SecFlags &= ~Load;
217 5 : break;
218 :
219 2 : case 'D': // discardable
220 2 : SecFlags |= Discardable;
221 2 : break;
222 :
223 276 : case 'r': // read-only
224 : ReadOnlyRemoved = false;
225 276 : SecFlags |= NoWrite;
226 276 : if ((SecFlags & Code) == 0)
227 169 : SecFlags |= InitData;
228 276 : if ((SecFlags & NoLoad) == 0)
229 276 : SecFlags |= Load;
230 : break;
231 :
232 3 : case 's': // shared section
233 : SecFlags |= Shared | InitData;
234 3 : SecFlags &= ~NoWrite;
235 3 : if ((SecFlags & NoLoad) == 0)
236 3 : SecFlags |= Load;
237 : break;
238 :
239 32 : case 'w': // writable
240 32 : SecFlags &= ~NoWrite;
241 : ReadOnlyRemoved = true;
242 32 : break;
243 :
244 116 : case 'x': // executable section
245 116 : SecFlags |= Code;
246 116 : if ((SecFlags & NoLoad) == 0)
247 116 : SecFlags |= Load;
248 116 : if (!ReadOnlyRemoved)
249 116 : SecFlags |= NoWrite;
250 : break;
251 :
252 7 : case 'y': // not readable
253 7 : SecFlags |= NoRead | NoWrite;
254 7 : break;
255 :
256 0 : default:
257 0 : return TokError("unknown flag");
258 : }
259 : }
260 :
261 327 : *Flags = 0;
262 :
263 327 : if (SecFlags == None)
264 : SecFlags = InitData;
265 :
266 327 : if (SecFlags & Code)
267 116 : *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
268 327 : if (SecFlags & InitData)
269 198 : *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
270 327 : if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
271 4 : *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
272 327 : if (SecFlags & NoLoad)
273 5 : *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
274 327 : if ((SecFlags & Discardable) ||
275 : MCSectionCOFF::isImplicitlyDiscardable(SectionName))
276 70 : *Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE;
277 327 : if ((SecFlags & NoRead) == 0)
278 320 : *Flags |= COFF::IMAGE_SCN_MEM_READ;
279 327 : if ((SecFlags & NoWrite) == 0)
280 47 : *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
281 327 : if (SecFlags & Shared)
282 3 : *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
283 :
284 : return false;
285 : }
286 :
287 : /// ParseDirectiveSymbolAttribute
288 : /// ::= { ".weak", ... } [ identifier ( , identifier )* ]
289 0 : bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
290 0 : MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
291 0 : .Case(".weak", MCSA_Weak)
292 : .Default(MCSA_Invalid);
293 : assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
294 0 : if (getLexer().isNot(AsmToken::EndOfStatement)) {
295 : while (true) {
296 0 : StringRef Name;
297 :
298 0 : if (getParser().parseIdentifier(Name))
299 0 : return TokError("expected identifier in directive");
300 :
301 0 : MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
302 :
303 0 : getStreamer().EmitSymbolAttribute(Sym, Attr);
304 :
305 0 : if (getLexer().is(AsmToken::EndOfStatement))
306 : break;
307 :
308 0 : if (getLexer().isNot(AsmToken::Comma))
309 0 : return TokError("unexpected token in directive");
310 : Lex();
311 0 : }
312 : }
313 :
314 : Lex();
315 0 : return false;
316 : }
317 :
318 : bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
319 : unsigned Characteristics,
320 : SectionKind Kind) {
321 0 : return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
322 : }
323 :
324 631 : bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
325 : unsigned Characteristics,
326 : SectionKind Kind,
327 : StringRef COMDATSymName,
328 : COFF::COMDATType Type) {
329 631 : if (getLexer().isNot(AsmToken::EndOfStatement))
330 0 : return TokError("unexpected token in section switching directive");
331 : Lex();
332 :
333 631 : getStreamer().SwitchSection(getContext().getCOFFSection(
334 631 : Section, Characteristics, Kind, COMDATSymName, Type));
335 :
336 631 : return false;
337 : }
338 :
339 434 : bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
340 434 : if (!getLexer().is(AsmToken::Identifier))
341 : return true;
342 :
343 434 : SectionName = getTok().getIdentifier();
344 : Lex();
345 434 : return false;
346 : }
347 :
348 : // .section name [, "flags"] [, identifier [ identifier ], identifier]
349 : //
350 : // Supported flags:
351 : // a: Ignored.
352 : // b: BSS section (uninitialized data)
353 : // d: data section (initialized data)
354 : // n: "noload" section (removed by linker)
355 : // D: Discardable section
356 : // r: Readable section
357 : // s: Shared section
358 : // w: Writable section
359 : // x: Executable section
360 : // y: Not-readable section (clears 'r')
361 : //
362 : // Subsections are not supported.
363 0 : bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
364 0 : StringRef SectionName;
365 :
366 0 : if (ParseSectionName(SectionName))
367 0 : return TokError("expected identifier in directive");
368 :
369 0 : unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
370 : COFF::IMAGE_SCN_MEM_READ |
371 : COFF::IMAGE_SCN_MEM_WRITE;
372 :
373 0 : if (getLexer().is(AsmToken::Comma)) {
374 : Lex();
375 :
376 0 : if (getLexer().isNot(AsmToken::String))
377 0 : return TokError("expected string in directive");
378 :
379 0 : StringRef FlagsStr = getTok().getStringContents();
380 : Lex();
381 :
382 0 : if (ParseSectionFlags(SectionName, FlagsStr, &Flags))
383 0 : return true;
384 : }
385 :
386 0 : COFF::COMDATType Type = (COFF::COMDATType)0;
387 0 : StringRef COMDATSymName;
388 0 : if (getLexer().is(AsmToken::Comma)) {
389 0 : Type = COFF::IMAGE_COMDAT_SELECT_ANY;
390 : Lex();
391 :
392 0 : Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
393 :
394 0 : if (!getLexer().is(AsmToken::Identifier))
395 0 : return TokError("expected comdat type such as 'discard' or 'largest' "
396 : "after protection bits");
397 :
398 0 : if (parseCOMDATType(Type))
399 0 : return true;
400 :
401 0 : if (getLexer().isNot(AsmToken::Comma))
402 0 : return TokError("expected comma in directive");
403 : Lex();
404 :
405 0 : if (getParser().parseIdentifier(COMDATSymName))
406 0 : return TokError("expected identifier in directive");
407 : }
408 :
409 0 : if (getLexer().isNot(AsmToken::EndOfStatement))
410 0 : return TokError("unexpected token in directive");
411 :
412 0 : SectionKind Kind = computeSectionKind(Flags);
413 0 : if (Kind.isText()) {
414 0 : const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
415 0 : if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
416 0 : Flags |= COFF::IMAGE_SCN_MEM_16BIT;
417 : }
418 0 : ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
419 0 : return false;
420 : }
421 :
422 0 : bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
423 0 : StringRef SymbolName;
424 :
425 0 : if (getParser().parseIdentifier(SymbolName))
426 0 : return TokError("expected identifier in directive");
427 :
428 0 : MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
429 :
430 0 : getStreamer().BeginCOFFSymbolDef(Sym);
431 :
432 : Lex();
433 0 : return false;
434 : }
435 :
436 0 : bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
437 : int64_t SymbolStorageClass;
438 0 : if (getParser().parseAbsoluteExpression(SymbolStorageClass))
439 0 : return true;
440 :
441 0 : if (getLexer().isNot(AsmToken::EndOfStatement))
442 0 : return TokError("unexpected token in directive");
443 :
444 : Lex();
445 0 : getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
446 0 : return false;
447 : }
448 :
449 0 : bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
450 : int64_t Type;
451 0 : if (getParser().parseAbsoluteExpression(Type))
452 0 : return true;
453 :
454 0 : if (getLexer().isNot(AsmToken::EndOfStatement))
455 0 : return TokError("unexpected token in directive");
456 :
457 : Lex();
458 0 : getStreamer().EmitCOFFSymbolType(Type);
459 0 : return false;
460 : }
461 :
462 0 : bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
463 : Lex();
464 0 : getStreamer().EndCOFFSymbolDef();
465 0 : return false;
466 : }
467 :
468 0 : bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
469 0 : StringRef SymbolID;
470 0 : if (getParser().parseIdentifier(SymbolID))
471 0 : return TokError("expected identifier in directive");
472 :
473 0 : int64_t Offset = 0;
474 : SMLoc OffsetLoc;
475 0 : if (getLexer().is(AsmToken::Plus)) {
476 0 : OffsetLoc = getLexer().getLoc();
477 0 : if (getParser().parseAbsoluteExpression(Offset))
478 0 : return true;
479 : }
480 :
481 0 : if (getLexer().isNot(AsmToken::EndOfStatement))
482 0 : return TokError("unexpected token in directive");
483 :
484 0 : if (Offset < 0 || Offset > std::numeric_limits<uint32_t>::max())
485 0 : return Error(
486 : OffsetLoc,
487 : "invalid '.secrel32' directive offset, can't be less "
488 : "than zero or greater than std::numeric_limits<uint32_t>::max()");
489 :
490 0 : MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
491 :
492 : Lex();
493 0 : getStreamer().EmitCOFFSecRel32(Symbol, Offset);
494 0 : return false;
495 : }
496 :
497 0 : bool COFFAsmParser::ParseDirectiveRVA(StringRef, SMLoc) {
498 : auto parseOp = [&]() -> bool {
499 : StringRef SymbolID;
500 : if (getParser().parseIdentifier(SymbolID))
501 : return TokError("expected identifier in directive");
502 :
503 : int64_t Offset = 0;
504 : SMLoc OffsetLoc;
505 : if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) {
506 : OffsetLoc = getLexer().getLoc();
507 : if (getParser().parseAbsoluteExpression(Offset))
508 : return true;
509 : }
510 :
511 : if (Offset < std::numeric_limits<int32_t>::min() ||
512 : Offset > std::numeric_limits<int32_t>::max())
513 : return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less "
514 : "than -2147483648 or greater than "
515 : "2147483647");
516 :
517 : MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
518 :
519 : getStreamer().EmitCOFFImgRel32(Symbol, Offset);
520 : return false;
521 0 : };
522 :
523 0 : if (getParser().parseMany(parseOp))
524 0 : return addErrorSuffix(" in directive");
525 : return false;
526 : }
527 :
528 0 : bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
529 0 : StringRef SymbolID;
530 0 : if (getParser().parseIdentifier(SymbolID))
531 0 : return TokError("expected identifier in directive");
532 :
533 0 : if (getLexer().isNot(AsmToken::EndOfStatement))
534 0 : return TokError("unexpected token in directive");
535 :
536 0 : MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
537 :
538 : Lex();
539 0 : getStreamer().EmitCOFFSafeSEH(Symbol);
540 0 : return false;
541 : }
542 :
543 0 : bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
544 0 : StringRef SymbolID;
545 0 : if (getParser().parseIdentifier(SymbolID))
546 0 : return TokError("expected identifier in directive");
547 :
548 0 : if (getLexer().isNot(AsmToken::EndOfStatement))
549 0 : return TokError("unexpected token in directive");
550 :
551 0 : MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
552 :
553 : Lex();
554 0 : getStreamer().EmitCOFFSectionIndex(Symbol);
555 0 : return false;
556 : }
557 :
558 0 : bool COFFAsmParser::ParseDirectiveSymIdx(StringRef, SMLoc) {
559 0 : StringRef SymbolID;
560 0 : if (getParser().parseIdentifier(SymbolID))
561 0 : return TokError("expected identifier in directive");
562 :
563 0 : if (getLexer().isNot(AsmToken::EndOfStatement))
564 0 : return TokError("unexpected token in directive");
565 :
566 0 : MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
567 :
568 : Lex();
569 0 : getStreamer().EmitCOFFSymbolIndex(Symbol);
570 0 : return false;
571 : }
572 :
573 : /// ::= [ identifier ]
574 159 : bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
575 159 : StringRef TypeId = getTok().getIdentifier();
576 :
577 159 : Type = StringSwitch<COFF::COMDATType>(TypeId)
578 159 : .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
579 159 : .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
580 159 : .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
581 159 : .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
582 159 : .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
583 159 : .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
584 159 : .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
585 : .Default((COFF::COMDATType)0);
586 :
587 159 : if (Type == 0)
588 1 : return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
589 :
590 : Lex();
591 :
592 158 : return false;
593 : }
594 :
595 : /// ParseDirectiveLinkOnce
596 : /// ::= .linkonce [ identifier ]
597 0 : bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
598 0 : COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
599 0 : if (getLexer().is(AsmToken::Identifier))
600 0 : if (parseCOMDATType(Type))
601 0 : return true;
602 :
603 : const MCSectionCOFF *Current =
604 : static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly());
605 :
606 0 : if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
607 0 : return Error(Loc, "cannot make section associative with .linkonce");
608 :
609 0 : if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
610 0 : return Error(Loc, Twine("section '") + Current->getSectionName() +
611 0 : "' is already linkonce");
612 :
613 0 : Current->setSelection(Type);
614 :
615 0 : if (getLexer().isNot(AsmToken::EndOfStatement))
616 0 : return TokError("unexpected token in directive");
617 :
618 : return false;
619 : }
620 :
621 0 : bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc Loc) {
622 0 : StringRef SymbolID;
623 0 : if (getParser().parseIdentifier(SymbolID))
624 0 : return true;
625 :
626 0 : if (getLexer().isNot(AsmToken::EndOfStatement))
627 0 : return TokError("unexpected token in directive");
628 :
629 0 : MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
630 :
631 : Lex();
632 0 : getStreamer().EmitWinCFIStartProc(Symbol, Loc);
633 0 : return false;
634 : }
635 :
636 0 : bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc Loc) {
637 : Lex();
638 0 : getStreamer().EmitWinCFIEndProc(Loc);
639 0 : return false;
640 : }
641 :
642 0 : bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc Loc) {
643 : Lex();
644 0 : getStreamer().EmitWinCFIStartChained(Loc);
645 0 : return false;
646 : }
647 :
648 0 : bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc Loc) {
649 : Lex();
650 0 : getStreamer().EmitWinCFIEndChained(Loc);
651 0 : return false;
652 : }
653 :
654 0 : bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc Loc) {
655 0 : StringRef SymbolID;
656 0 : if (getParser().parseIdentifier(SymbolID))
657 0 : return true;
658 :
659 0 : if (getLexer().isNot(AsmToken::Comma))
660 0 : return TokError("you must specify one or both of @unwind or @except");
661 : Lex();
662 0 : bool unwind = false, except = false;
663 0 : if (ParseAtUnwindOrAtExcept(unwind, except))
664 0 : return true;
665 0 : if (getLexer().is(AsmToken::Comma)) {
666 : Lex();
667 0 : if (ParseAtUnwindOrAtExcept(unwind, except))
668 0 : return true;
669 : }
670 0 : if (getLexer().isNot(AsmToken::EndOfStatement))
671 0 : return TokError("unexpected token in directive");
672 :
673 0 : MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
674 :
675 : Lex();
676 0 : getStreamer().EmitWinEHHandler(handler, unwind, except, Loc);
677 0 : return false;
678 : }
679 :
680 0 : bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) {
681 : Lex();
682 0 : getStreamer().EmitWinEHHandlerData();
683 0 : return false;
684 : }
685 :
686 0 : bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc Loc) {
687 0 : unsigned Reg = 0;
688 0 : if (ParseSEHRegisterNumber(Reg))
689 0 : return true;
690 :
691 0 : if (getLexer().isNot(AsmToken::EndOfStatement))
692 0 : return TokError("unexpected token in directive");
693 :
694 : Lex();
695 0 : getStreamer().EmitWinCFIPushReg(Reg, Loc);
696 0 : return false;
697 : }
698 :
699 0 : bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc Loc) {
700 0 : unsigned Reg = 0;
701 : int64_t Off;
702 0 : if (ParseSEHRegisterNumber(Reg))
703 0 : return true;
704 0 : if (getLexer().isNot(AsmToken::Comma))
705 0 : return TokError("you must specify a stack pointer offset");
706 :
707 : Lex();
708 0 : if (getParser().parseAbsoluteExpression(Off))
709 0 : return true;
710 :
711 0 : if (getLexer().isNot(AsmToken::EndOfStatement))
712 0 : return TokError("unexpected token in directive");
713 :
714 : Lex();
715 0 : getStreamer().EmitWinCFISetFrame(Reg, Off, Loc);
716 0 : return false;
717 : }
718 :
719 0 : bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) {
720 : int64_t Size;
721 0 : if (getParser().parseAbsoluteExpression(Size))
722 0 : return true;
723 :
724 0 : if (getLexer().isNot(AsmToken::EndOfStatement))
725 0 : return TokError("unexpected token in directive");
726 :
727 : Lex();
728 0 : getStreamer().EmitWinCFIAllocStack(Size, Loc);
729 0 : return false;
730 : }
731 :
732 0 : bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc Loc) {
733 0 : unsigned Reg = 0;
734 : int64_t Off;
735 0 : if (ParseSEHRegisterNumber(Reg))
736 0 : return true;
737 0 : if (getLexer().isNot(AsmToken::Comma))
738 0 : return TokError("you must specify an offset on the stack");
739 :
740 : Lex();
741 0 : if (getParser().parseAbsoluteExpression(Off))
742 0 : return true;
743 :
744 0 : if (getLexer().isNot(AsmToken::EndOfStatement))
745 0 : return TokError("unexpected token in directive");
746 :
747 : Lex();
748 : // FIXME: Err on %xmm* registers
749 0 : getStreamer().EmitWinCFISaveReg(Reg, Off, Loc);
750 0 : return false;
751 : }
752 :
753 : // FIXME: This method is inherently x86-specific. It should really be in the
754 : // x86 backend.
755 0 : bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc Loc) {
756 0 : unsigned Reg = 0;
757 : int64_t Off;
758 0 : if (ParseSEHRegisterNumber(Reg))
759 0 : return true;
760 0 : if (getLexer().isNot(AsmToken::Comma))
761 0 : return TokError("you must specify an offset on the stack");
762 :
763 : Lex();
764 0 : if (getParser().parseAbsoluteExpression(Off))
765 0 : return true;
766 :
767 0 : if (getLexer().isNot(AsmToken::EndOfStatement))
768 0 : return TokError("unexpected token in directive");
769 :
770 : Lex();
771 : // FIXME: Err on non-%xmm* registers
772 0 : getStreamer().EmitWinCFISaveXMM(Reg, Off, Loc);
773 0 : return false;
774 : }
775 :
776 0 : bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc Loc) {
777 : bool Code = false;
778 0 : StringRef CodeID;
779 0 : if (getLexer().is(AsmToken::At)) {
780 0 : SMLoc startLoc = getLexer().getLoc();
781 : Lex();
782 0 : if (!getParser().parseIdentifier(CodeID)) {
783 : if (CodeID != "code")
784 0 : return Error(startLoc, "expected @code");
785 : Code = true;
786 : }
787 : }
788 :
789 0 : if (getLexer().isNot(AsmToken::EndOfStatement))
790 0 : return TokError("unexpected token in directive");
791 :
792 : Lex();
793 0 : getStreamer().EmitWinCFIPushFrame(Code, Loc);
794 0 : return false;
795 : }
796 :
797 0 : bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) {
798 : Lex();
799 0 : getStreamer().EmitWinCFIEndProlog(Loc);
800 0 : return false;
801 : }
802 :
803 5 : bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
804 5 : StringRef identifier;
805 5 : if (getLexer().isNot(AsmToken::At))
806 0 : return TokError("a handler attribute must begin with '@'");
807 5 : SMLoc startLoc = getLexer().getLoc();
808 : Lex();
809 5 : if (getParser().parseIdentifier(identifier))
810 0 : return Error(startLoc, "expected @unwind or @except");
811 : if (identifier == "unwind")
812 1 : unwind = true;
813 : else if (identifier == "except")
814 4 : except = true;
815 : else
816 0 : return Error(startLoc, "expected @unwind or @except");
817 : return false;
818 : }
819 :
820 32 : bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
821 32 : SMLoc startLoc = getLexer().getLoc();
822 32 : if (getLexer().is(AsmToken::Percent)) {
823 7 : const MCRegisterInfo *MRI = getContext().getRegisterInfo();
824 7 : SMLoc endLoc;
825 : unsigned LLVMRegNo;
826 7 : if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
827 0 : return true;
828 :
829 : #if 0
830 : // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
831 : // violation so this validation code is disabled.
832 :
833 : // Check that this is a non-volatile register.
834 : const unsigned *NVRegs = TAI.getCalleeSavedRegs();
835 : unsigned i;
836 : for (i = 0; NVRegs[i] != 0; ++i)
837 : if (NVRegs[i] == LLVMRegNo)
838 : break;
839 : if (NVRegs[i] == 0)
840 : return Error(startLoc, "expected non-volatile register");
841 : #endif
842 :
843 7 : int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
844 7 : if (SEHRegNo < 0)
845 0 : return Error(startLoc,"register can't be represented in SEH unwind info");
846 7 : RegNo = SEHRegNo;
847 : }
848 : else {
849 : int64_t n;
850 25 : if (getParser().parseAbsoluteExpression(n))
851 0 : return true;
852 25 : if (n > 15)
853 0 : return Error(startLoc, "register number is too high");
854 25 : RegNo = n;
855 : }
856 :
857 : return false;
858 : }
859 :
860 : namespace llvm {
861 :
862 364 : MCAsmParserExtension *createCOFFAsmParser() {
863 364 : return new COFFAsmParser;
864 : }
865 :
866 : } // end namespace llvm
|