File: | lib/MC/MCParser/COFFAsmParser.cpp |
Warning: | line 534, column 7 Called C++ object pointer is null |
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" | |||
23 | using namespace llvm; | |||
24 | ||||
25 | namespace { | |||
26 | ||||
27 | class 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); | |||
144 | public: | |||
145 | COFFAsmParser() {} | |||
146 | }; | |||
147 | ||||
148 | } // end annonomous namespace. | |||
149 | ||||
150 | static SectionKind computeSectionKind(unsigned Flags) { | |||
151 | if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE) | |||
152 | return SectionKind::getText(); | |||
153 | if (Flags & COFF::IMAGE_SCN_MEM_READ && | |||
154 | (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0) | |||
155 | return SectionKind::getReadOnly(); | |||
156 | return SectionKind::getData(); | |||
157 | } | |||
158 | ||||
159 | bool COFFAsmParser::ParseSectionFlags(StringRef SectionName, | |||
160 | StringRef FlagsString, unsigned *Flags) { | |||
161 | enum { | |||
162 | None = 0, | |||
163 | Alloc = 1 << 0, | |||
164 | Code = 1 << 1, | |||
165 | Load = 1 << 2, | |||
166 | InitData = 1 << 3, | |||
167 | Shared = 1 << 4, | |||
168 | NoLoad = 1 << 5, | |||
169 | NoRead = 1 << 6, | |||
170 | NoWrite = 1 << 7, | |||
171 | Discardable = 1 << 8, | |||
172 | }; | |||
173 | ||||
174 | bool ReadOnlyRemoved = false; | |||
175 | unsigned SecFlags = None; | |||
176 | ||||
177 | for (char FlagChar : FlagsString) { | |||
178 | switch (FlagChar) { | |||
179 | case 'a': | |||
180 | // Ignored. | |||
181 | break; | |||
182 | ||||
183 | case 'b': // bss section | |||
184 | SecFlags |= Alloc; | |||
185 | if (SecFlags & InitData) | |||
186 | return TokError("conflicting section flags 'b' and 'd'."); | |||
187 | SecFlags &= ~Load; | |||
188 | break; | |||
189 | ||||
190 | case 'd': // data section | |||
191 | SecFlags |= InitData; | |||
192 | if (SecFlags & Alloc) | |||
193 | return TokError("conflicting section flags 'b' and 'd'."); | |||
194 | SecFlags &= ~NoWrite; | |||
195 | if ((SecFlags & NoLoad) == 0) | |||
196 | SecFlags |= Load; | |||
197 | break; | |||
198 | ||||
199 | case 'n': // section is not loaded | |||
200 | SecFlags |= NoLoad; | |||
201 | SecFlags &= ~Load; | |||
202 | break; | |||
203 | ||||
204 | case 'D': // discardable | |||
205 | SecFlags |= Discardable; | |||
206 | break; | |||
207 | ||||
208 | case 'r': // read-only | |||
209 | ReadOnlyRemoved = false; | |||
210 | SecFlags |= NoWrite; | |||
211 | if ((SecFlags & Code) == 0) | |||
212 | SecFlags |= InitData; | |||
213 | if ((SecFlags & NoLoad) == 0) | |||
214 | SecFlags |= Load; | |||
215 | break; | |||
216 | ||||
217 | case 's': // shared section | |||
218 | SecFlags |= Shared | InitData; | |||
219 | SecFlags &= ~NoWrite; | |||
220 | if ((SecFlags & NoLoad) == 0) | |||
221 | SecFlags |= Load; | |||
222 | break; | |||
223 | ||||
224 | case 'w': // writable | |||
225 | SecFlags &= ~NoWrite; | |||
226 | ReadOnlyRemoved = true; | |||
227 | break; | |||
228 | ||||
229 | case 'x': // executable section | |||
230 | SecFlags |= Code; | |||
231 | if ((SecFlags & NoLoad) == 0) | |||
232 | SecFlags |= Load; | |||
233 | if (!ReadOnlyRemoved) | |||
234 | SecFlags |= NoWrite; | |||
235 | break; | |||
236 | ||||
237 | case 'y': // not readable | |||
238 | SecFlags |= NoRead | NoWrite; | |||
239 | break; | |||
240 | ||||
241 | default: | |||
242 | return TokError("unknown flag"); | |||
243 | } | |||
244 | } | |||
245 | ||||
246 | *Flags = 0; | |||
247 | ||||
248 | if (SecFlags == None) | |||
249 | SecFlags = InitData; | |||
250 | ||||
251 | if (SecFlags & Code) | |||
252 | *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE; | |||
253 | if (SecFlags & InitData) | |||
254 | *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; | |||
255 | if ((SecFlags & Alloc) && (SecFlags & Load) == 0) | |||
256 | *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; | |||
257 | if (SecFlags & NoLoad) | |||
258 | *Flags |= COFF::IMAGE_SCN_LNK_REMOVE; | |||
259 | if ((SecFlags & Discardable) || | |||
260 | MCSectionCOFF::isImplicitlyDiscardable(SectionName)) | |||
261 | *Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE; | |||
262 | if ((SecFlags & NoRead) == 0) | |||
263 | *Flags |= COFF::IMAGE_SCN_MEM_READ; | |||
264 | if ((SecFlags & NoWrite) == 0) | |||
265 | *Flags |= COFF::IMAGE_SCN_MEM_WRITE; | |||
266 | if (SecFlags & Shared) | |||
267 | *Flags |= COFF::IMAGE_SCN_MEM_SHARED; | |||
268 | ||||
269 | return false; | |||
270 | } | |||
271 | ||||
272 | /// ParseDirectiveSymbolAttribute | |||
273 | /// ::= { ".weak", ... } [ identifier ( , identifier )* ] | |||
274 | bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { | |||
275 | MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive) | |||
276 | .Case(".weak", MCSA_Weak) | |||
277 | .Default(MCSA_Invalid); | |||
278 | assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!")((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 | ||||
303 | bool COFFAsmParser::ParseSectionSwitch(StringRef Section, | |||
304 | unsigned Characteristics, | |||
305 | SectionKind Kind) { | |||
306 | return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0); | |||
307 | } | |||
308 | ||||
309 | bool 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 | ||||
324 | bool 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. | |||
348 | bool 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 | ||||
407 | bool 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 | ||||
421 | bool 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 | ||||
434 | bool 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 | ||||
447 | bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) { | |||
448 | Lex(); | |||
449 | getStreamer().EndCOFFSymbolDef(); | |||
450 | return false; | |||
451 | } | |||
452 | ||||
453 | bool 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 | ||||
468 | bool 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 | ||||
483 | bool 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 ] | |||
499 | bool 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 ] | |||
522 | bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) { | |||
523 | COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; | |||
524 | if (getLexer().is(AsmToken::Identifier)) | |||
| ||||
525 | if (parseCOMDATType(Type)) | |||
526 | return true; | |||
527 | ||||
528 | const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>( | |||
529 | getStreamer().getCurrentSection().first); | |||
530 | ||||
531 | if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) | |||
532 | return Error(Loc, "cannot make section associative with .linkonce"); | |||
533 | ||||
534 | if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) | |||
| ||||
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 | ||||
546 | bool 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 | ||||
561 | bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) { | |||
562 | Lex(); | |||
563 | getStreamer().EmitWinCFIEndProc(); | |||
564 | return false; | |||
565 | } | |||
566 | ||||
567 | bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) { | |||
568 | Lex(); | |||
569 | getStreamer().EmitWinCFIStartChained(); | |||
570 | return false; | |||
571 | } | |||
572 | ||||
573 | bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) { | |||
574 | Lex(); | |||
575 | getStreamer().EmitWinCFIEndChained(); | |||
576 | return false; | |||
577 | } | |||
578 | ||||
579 | bool 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 | ||||
605 | bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) { | |||
606 | Lex(); | |||
607 | getStreamer().EmitWinEHHandlerData(); | |||
608 | return false; | |||
609 | } | |||
610 | ||||
611 | bool 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 | ||||
624 | bool 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 | ||||
648 | bool 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 | ||||
665 | bool 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. | |||
692 | bool 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 | ||||
717 | bool 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 | ||||
738 | bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) { | |||
739 | Lex(); | |||
740 | getStreamer().EmitWinCFIEndProlog(); | |||
741 | return false; | |||
742 | } | |||
743 | ||||
744 | bool 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 | ||||
761 | bool 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 | ||||
801 | namespace llvm { | |||
802 | ||||
803 | MCAsmParserExtension *createCOFFAsmParser() { | |||
804 | return new COFFAsmParser; | |||
805 | } | |||
806 | ||||
807 | } |