Bug Summary

File:lib/MC/MCParser/COFFAsmParser.cpp
Warning:line 534, column 7
Called C++ object pointer is null

Annotated 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/MC/MCParser/MCAsmParserExtension.h"
11#include "llvm/ADT/StringSwitch.h"
12#include "llvm/ADT/Twine.h"
13#include "llvm/MC/MCAsmInfo.h"
14#include "llvm/MC/MCContext.h"
15#include "llvm/MC/MCExpr.h"
16#include "llvm/MC/MCObjectFileInfo.h"
17#include "llvm/MC/MCParser/MCAsmLexer.h"
18#include "llvm/MC/MCParser/MCTargetAsmParser.h"
19#include "llvm/MC/MCRegisterInfo.h"
20#include "llvm/MC/MCSectionCOFF.h"
21#include "llvm/MC/MCStreamer.h"
22#include "llvm/Support/COFF.h"
23using namespace llvm;
24
25namespace {
26
27class COFFAsmParser : public MCAsmParserExtension {
28 template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
29 void addDirectiveHandler(StringRef Directive) {
30 MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
31 this, HandleDirective<COFFAsmParser, HandlerMethod>);
32 getParser().addDirectiveHandler(Directive, Handler);
33 }
34
35 bool ParseSectionSwitch(StringRef Section,
36 unsigned Characteristics,
37 SectionKind Kind);
38
39 bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
40 SectionKind Kind, StringRef COMDATSymName,
41 COFF::COMDATType Type);
42
43 bool ParseSectionName(StringRef &SectionName);
44 bool ParseSectionFlags(StringRef SectionName, StringRef FlagsString,
45 unsigned *Flags);
46
47 void Initialize(MCAsmParser &Parser) override {
48 // Call the base implementation.
49 MCAsmParserExtension::Initialize(Parser);
50
51 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
52 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
53 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
54 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
55 addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
56 addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
57 addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
58 addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
59 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
60 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
61 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
62 addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
63
64 // Win64 EH directives.
65 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
66 ".seh_proc");
67 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
68 ".seh_endproc");
69 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
70 ".seh_startchained");
71 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
72 ".seh_endchained");
73 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
74 ".seh_handler");
75 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
76 ".seh_handlerdata");
77 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
78 ".seh_pushreg");
79 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
80 ".seh_setframe");
81 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
82 ".seh_stackalloc");
83 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
84 ".seh_savereg");
85 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
86 ".seh_savexmm");
87 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
88 ".seh_pushframe");
89 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
90 ".seh_endprologue");
91 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
92 }
93
94 bool ParseSectionDirectiveText(StringRef, SMLoc) {
95 return ParseSectionSwitch(".text",
96 COFF::IMAGE_SCN_CNT_CODE
97 | COFF::IMAGE_SCN_MEM_EXECUTE
98 | COFF::IMAGE_SCN_MEM_READ,
99 SectionKind::getText());
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 SectionKind::getData());
106 }
107 bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
108 return ParseSectionSwitch(".bss",
109 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
110 | COFF::IMAGE_SCN_MEM_READ
111 | COFF::IMAGE_SCN_MEM_WRITE,
112 SectionKind::getBSS());
113 }
114
115 bool ParseDirectiveSection(StringRef, SMLoc);
116 bool ParseDirectiveDef(StringRef, SMLoc);
117 bool ParseDirectiveScl(StringRef, SMLoc);
118 bool ParseDirectiveType(StringRef, SMLoc);
119 bool ParseDirectiveEndef(StringRef, SMLoc);
120 bool ParseDirectiveSecRel32(StringRef, SMLoc);
121 bool ParseDirectiveSecIdx(StringRef, SMLoc);
122 bool ParseDirectiveSafeSEH(StringRef, SMLoc);
123 bool parseCOMDATType(COFF::COMDATType &Type);
124 bool ParseDirectiveLinkOnce(StringRef, SMLoc);
125
126 // Win64 EH directives.
127 bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
128 bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
129 bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
130 bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
131 bool ParseSEHDirectiveHandler(StringRef, SMLoc);
132 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
133 bool ParseSEHDirectivePushReg(StringRef, SMLoc);
134 bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
135 bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
136 bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
137 bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
138 bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
139 bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
140
141 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
142 bool ParseSEHRegisterNumber(unsigned &RegNo);
143 bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
144public:
145 COFFAsmParser() {}
146};
147
148} // end annonomous namespace.
149
150static 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
159bool 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 )* ]
274bool 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!")((Attr != MCSA_Invalid && "unexpected symbol attribute directive!"
) ? static_cast<void> (0) : __assert_fail ("Attr != MCSA_Invalid && \"unexpected symbol attribute directive!\""
, "/tmp/buildd/llvm-toolchain-snapshot-4.0~svn284109/lib/MC/MCParser/COFFAsmParser.cpp"
, 278, __PRETTY_FUNCTION__))
;
279 if (getLexer().isNot(AsmToken::EndOfStatement)) {
280 for (;;) {
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
303bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
304 unsigned Characteristics,
305 SectionKind Kind) {
306 return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
307}
308
309bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
310 unsigned Characteristics,
311 SectionKind Kind,
312 StringRef COMDATSymName,
313 COFF::COMDATType Type) {
314 if (getLexer().isNot(AsmToken::EndOfStatement))
315 return TokError("unexpected token in section switching directive");
316 Lex();
317
318 getStreamer().SwitchSection(getContext().getCOFFSection(
319 Section, Characteristics, Kind, COMDATSymName, Type));
320
321 return false;
322}
323
324bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
325 if (!getLexer().is(AsmToken::Identifier))
326 return true;
327
328 SectionName = getTok().getIdentifier();
329 Lex();
330 return false;
331}
332
333// .section name [, "flags"] [, identifier [ identifier ], identifier]
334//
335// Supported flags:
336// a: Ignored.
337// b: BSS section (uninitialized data)
338// d: data section (initialized data)
339// n: "noload" section (removed by linker)
340// D: Discardable section
341// r: Readable section
342// s: Shared section
343// w: Writable section
344// x: Executable section
345// y: Not-readable section (clears 'r')
346//
347// Subsections are not supported.
348bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
349 StringRef SectionName;
350
351 if (ParseSectionName(SectionName))
352 return TokError("expected identifier in directive");
353
354 unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
355 COFF::IMAGE_SCN_MEM_READ |
356 COFF::IMAGE_SCN_MEM_WRITE;
357
358 if (getLexer().is(AsmToken::Comma)) {
359 Lex();
360
361 if (getLexer().isNot(AsmToken::String))
362 return TokError("expected string in directive");
363
364 StringRef FlagsStr = getTok().getStringContents();
365 Lex();
366
367 if (ParseSectionFlags(SectionName, FlagsStr, &Flags))
368 return true;
369 }
370
371 COFF::COMDATType Type = (COFF::COMDATType)0;
372 StringRef COMDATSymName;
373 if (getLexer().is(AsmToken::Comma)) {
374 Type = COFF::IMAGE_COMDAT_SELECT_ANY;
375 Lex();
376
377 Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
378
379 if (!getLexer().is(AsmToken::Identifier))
380 return TokError("expected comdat type such as 'discard' or 'largest' "
381 "after protection bits");
382
383 if (parseCOMDATType(Type))
384 return true;
385
386 if (getLexer().isNot(AsmToken::Comma))
387 return TokError("expected comma in directive");
388 Lex();
389
390 if (getParser().parseIdentifier(COMDATSymName))
391 return TokError("expected identifier in directive");
392 }
393
394 if (getLexer().isNot(AsmToken::EndOfStatement))
395 return TokError("unexpected token in directive");
396
397 SectionKind Kind = computeSectionKind(Flags);
398 if (Kind.isText()) {
399 const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
400 if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
401 Flags |= COFF::IMAGE_SCN_MEM_16BIT;
402 }
403 ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
404 return false;
405}
406
407bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
408 StringRef SymbolName;
409
410 if (getParser().parseIdentifier(SymbolName))
411 return TokError("expected identifier in directive");
412
413 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
414
415 getStreamer().BeginCOFFSymbolDef(Sym);
416
417 Lex();
418 return false;
419}
420
421bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
422 int64_t SymbolStorageClass;
423 if (getParser().parseAbsoluteExpression(SymbolStorageClass))
424 return true;
425
426 if (getLexer().isNot(AsmToken::EndOfStatement))
427 return TokError("unexpected token in directive");
428
429 Lex();
430 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
431 return false;
432}
433
434bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
435 int64_t Type;
436 if (getParser().parseAbsoluteExpression(Type))
437 return true;
438
439 if (getLexer().isNot(AsmToken::EndOfStatement))
440 return TokError("unexpected token in directive");
441
442 Lex();
443 getStreamer().EmitCOFFSymbolType(Type);
444 return false;
445}
446
447bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
448 Lex();
449 getStreamer().EndCOFFSymbolDef();
450 return false;
451}
452
453bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
454 StringRef SymbolID;
455 if (getParser().parseIdentifier(SymbolID))
456 return TokError("expected identifier in directive");
457
458 if (getLexer().isNot(AsmToken::EndOfStatement))
459 return TokError("unexpected token in directive");
460
461 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
462
463 Lex();
464 getStreamer().EmitCOFFSecRel32(Symbol);
465 return false;
466}
467
468bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
469 StringRef SymbolID;
470 if (getParser().parseIdentifier(SymbolID))
471 return TokError("expected identifier in directive");
472
473 if (getLexer().isNot(AsmToken::EndOfStatement))
474 return TokError("unexpected token in directive");
475
476 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
477
478 Lex();
479 getStreamer().EmitCOFFSafeSEH(Symbol);
480 return false;
481}
482
483bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
484 StringRef SymbolID;
485 if (getParser().parseIdentifier(SymbolID))
486 return TokError("expected identifier in directive");
487
488 if (getLexer().isNot(AsmToken::EndOfStatement))
489 return TokError("unexpected token in directive");
490
491 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
492
493 Lex();
494 getStreamer().EmitCOFFSectionIndex(Symbol);
495 return false;
496}
497
498/// ::= [ identifier ]
499bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
500 StringRef TypeId = getTok().getIdentifier();
501
502 Type = StringSwitch<COFF::COMDATType>(TypeId)
503 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
504 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
505 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
506 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
507 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
508 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
509 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
510 .Default((COFF::COMDATType)0);
511
512 if (Type == 0)
513 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
514
515 Lex();
516
517 return false;
518}
519
520/// ParseDirectiveLinkOnce
521/// ::= .linkonce [ identifier ]
522bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
523 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
524 if (getLexer().is(AsmToken::Identifier))
1
Taking false branch
525 if (parseCOMDATType(Type))
526 return true;
527
528 const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
2
'Current' initialized to a null pointer value
529 getStreamer().getCurrentSection().first);
530
531 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
3
Taking false branch
532 return Error(Loc, "cannot make section associative with .linkonce");
533
534 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
4
Called C++ object pointer is null
535 return Error(Loc, Twine("section '") + Current->getSectionName() +
536 "' is already linkonce");
537
538 Current->setSelection(Type);
539
540 if (getLexer().isNot(AsmToken::EndOfStatement))
541 return TokError("unexpected token in directive");
542
543 return false;
544}
545
546bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
547 StringRef SymbolID;
548 if (getParser().parseIdentifier(SymbolID))
549 return true;
550
551 if (getLexer().isNot(AsmToken::EndOfStatement))
552 return TokError("unexpected token in directive");
553
554 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
555
556 Lex();
557 getStreamer().EmitWinCFIStartProc(Symbol);
558 return false;
559}
560
561bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
562 Lex();
563 getStreamer().EmitWinCFIEndProc();
564 return false;
565}
566
567bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
568 Lex();
569 getStreamer().EmitWinCFIStartChained();
570 return false;
571}
572
573bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
574 Lex();
575 getStreamer().EmitWinCFIEndChained();
576 return false;
577}
578
579bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
580 StringRef SymbolID;
581 if (getParser().parseIdentifier(SymbolID))
582 return true;
583
584 if (getLexer().isNot(AsmToken::Comma))
585 return TokError("you must specify one or both of @unwind or @except");
586 Lex();
587 bool unwind = false, except = false;
588 if (ParseAtUnwindOrAtExcept(unwind, except))
589 return true;
590 if (getLexer().is(AsmToken::Comma)) {
591 Lex();
592 if (ParseAtUnwindOrAtExcept(unwind, except))
593 return true;
594 }
595 if (getLexer().isNot(AsmToken::EndOfStatement))
596 return TokError("unexpected token in directive");
597
598 MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
599
600 Lex();
601 getStreamer().EmitWinEHHandler(handler, unwind, except);
602 return false;
603}
604
605bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
606 Lex();
607 getStreamer().EmitWinEHHandlerData();
608 return false;
609}
610
611bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
612 unsigned Reg = 0;
613 if (ParseSEHRegisterNumber(Reg))
614 return true;
615
616 if (getLexer().isNot(AsmToken::EndOfStatement))
617 return TokError("unexpected token in directive");
618
619 Lex();
620 getStreamer().EmitWinCFIPushReg(Reg);
621 return false;
622}
623
624bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
625 unsigned Reg = 0;
626 int64_t Off;
627 if (ParseSEHRegisterNumber(Reg))
628 return true;
629 if (getLexer().isNot(AsmToken::Comma))
630 return TokError("you must specify a stack pointer offset");
631
632 Lex();
633 SMLoc startLoc = getLexer().getLoc();
634 if (getParser().parseAbsoluteExpression(Off))
635 return true;
636
637 if (Off & 0x0F)
638 return Error(startLoc, "offset is not a multiple of 16");
639
640 if (getLexer().isNot(AsmToken::EndOfStatement))
641 return TokError("unexpected token in directive");
642
643 Lex();
644 getStreamer().EmitWinCFISetFrame(Reg, Off);
645 return false;
646}
647
648bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
649 int64_t Size;
650 SMLoc startLoc = getLexer().getLoc();
651 if (getParser().parseAbsoluteExpression(Size))
652 return true;
653
654 if (Size & 7)
655 return Error(startLoc, "size is not a multiple of 8");
656
657 if (getLexer().isNot(AsmToken::EndOfStatement))
658 return TokError("unexpected token in directive");
659
660 Lex();
661 getStreamer().EmitWinCFIAllocStack(Size);
662 return false;
663}
664
665bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
666 unsigned Reg = 0;
667 int64_t Off;
668 if (ParseSEHRegisterNumber(Reg))
669 return true;
670 if (getLexer().isNot(AsmToken::Comma))
671 return TokError("you must specify an offset on the stack");
672
673 Lex();
674 SMLoc startLoc = getLexer().getLoc();
675 if (getParser().parseAbsoluteExpression(Off))
676 return true;
677
678 if (Off & 7)
679 return Error(startLoc, "size is not a multiple of 8");
680
681 if (getLexer().isNot(AsmToken::EndOfStatement))
682 return TokError("unexpected token in directive");
683
684 Lex();
685 // FIXME: Err on %xmm* registers
686 getStreamer().EmitWinCFISaveReg(Reg, Off);
687 return false;
688}
689
690// FIXME: This method is inherently x86-specific. It should really be in the
691// x86 backend.
692bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
693 unsigned Reg = 0;
694 int64_t Off;
695 if (ParseSEHRegisterNumber(Reg))
696 return true;
697 if (getLexer().isNot(AsmToken::Comma))
698 return TokError("you must specify an offset on the stack");
699
700 Lex();
701 SMLoc startLoc = getLexer().getLoc();
702 if (getParser().parseAbsoluteExpression(Off))
703 return true;
704
705 if (getLexer().isNot(AsmToken::EndOfStatement))
706 return TokError("unexpected token in directive");
707
708 if (Off & 0x0F)
709 return Error(startLoc, "offset is not a multiple of 16");
710
711 Lex();
712 // FIXME: Err on non-%xmm* registers
713 getStreamer().EmitWinCFISaveXMM(Reg, Off);
714 return false;
715}
716
717bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
718 bool Code = false;
719 StringRef CodeID;
720 if (getLexer().is(AsmToken::At)) {
721 SMLoc startLoc = getLexer().getLoc();
722 Lex();
723 if (!getParser().parseIdentifier(CodeID)) {
724 if (CodeID != "code")
725 return Error(startLoc, "expected @code");
726 Code = true;
727 }
728 }
729
730 if (getLexer().isNot(AsmToken::EndOfStatement))
731 return TokError("unexpected token in directive");
732
733 Lex();
734 getStreamer().EmitWinCFIPushFrame(Code);
735 return false;
736}
737
738bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
739 Lex();
740 getStreamer().EmitWinCFIEndProlog();
741 return false;
742}
743
744bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
745 StringRef identifier;
746 if (getLexer().isNot(AsmToken::At))
747 return TokError("a handler attribute must begin with '@'");
748 SMLoc startLoc = getLexer().getLoc();
749 Lex();
750 if (getParser().parseIdentifier(identifier))
751 return Error(startLoc, "expected @unwind or @except");
752 if (identifier == "unwind")
753 unwind = true;
754 else if (identifier == "except")
755 except = true;
756 else
757 return Error(startLoc, "expected @unwind or @except");
758 return false;
759}
760
761bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
762 SMLoc startLoc = getLexer().getLoc();
763 if (getLexer().is(AsmToken::Percent)) {
764 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
765 SMLoc endLoc;
766 unsigned LLVMRegNo;
767 if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
768 return true;
769
770#if 0
771 // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
772 // violation so this validation code is disabled.
773
774 // Check that this is a non-volatile register.
775 const unsigned *NVRegs = TAI.getCalleeSavedRegs();
776 unsigned i;
777 for (i = 0; NVRegs[i] != 0; ++i)
778 if (NVRegs[i] == LLVMRegNo)
779 break;
780 if (NVRegs[i] == 0)
781 return Error(startLoc, "expected non-volatile register");
782#endif
783
784 int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
785 if (SEHRegNo < 0)
786 return Error(startLoc,"register can't be represented in SEH unwind info");
787 RegNo = SEHRegNo;
788 }
789 else {
790 int64_t n;
791 if (getParser().parseAbsoluteExpression(n))
792 return true;
793 if (n > 15)
794 return Error(startLoc, "register number is too high");
795 RegNo = n;
796 }
797
798 return false;
799}
800
801namespace llvm {
802
803MCAsmParserExtension *createCOFFAsmParser() {
804 return new COFFAsmParser;
805}
806
807}