]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / llvm / lib / MC / MCParser / COFFAsmParser.cpp
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/MCParser/MCAsmLexer.h"
17 #include "llvm/MC/MCRegisterInfo.h"
18 #include "llvm/MC/MCSectionCOFF.h"
19 #include "llvm/MC/MCStreamer.h"
20 #include "llvm/MC/MCTargetAsmParser.h"
21 #include "llvm/Support/COFF.h"
22 using namespace llvm;
23
24 namespace {
25
26 class COFFAsmParser : public MCAsmParserExtension {
27   template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
28   void addDirectiveHandler(StringRef Directive) {
29     MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
30         this, HandleDirective<COFFAsmParser, HandlerMethod>);
31     getParser().addDirectiveHandler(Directive, Handler);
32   }
33
34   bool ParseSectionSwitch(StringRef Section,
35                           unsigned Characteristics,
36                           SectionKind Kind);
37
38   virtual void Initialize(MCAsmParser &Parser) {
39     // Call the base implementation.
40     MCAsmParserExtension::Initialize(Parser);
41
42     addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
43     addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
44     addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
45     addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
46     addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
47     addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
48     addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
49     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
50
51     // Win64 EH directives.
52     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
53                                                                    ".seh_proc");
54     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
55                                                                 ".seh_endproc");
56     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
57                                                            ".seh_startchained");
58     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
59                                                              ".seh_endchained");
60     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
61                                                                 ".seh_handler");
62     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
63                                                             ".seh_handlerdata");
64     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
65                                                                 ".seh_pushreg");
66     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
67                                                                ".seh_setframe");
68     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
69                                                              ".seh_stackalloc");
70     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
71                                                                 ".seh_savereg");
72     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
73                                                                 ".seh_savexmm");
74     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
75                                                               ".seh_pushframe");
76     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
77                                                             ".seh_endprologue");
78     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
79   }
80
81   bool ParseSectionDirectiveText(StringRef, SMLoc) {
82     return ParseSectionSwitch(".text",
83                               COFF::IMAGE_SCN_CNT_CODE
84                             | COFF::IMAGE_SCN_MEM_EXECUTE
85                             | COFF::IMAGE_SCN_MEM_READ,
86                               SectionKind::getText());
87   }
88   bool ParseSectionDirectiveData(StringRef, SMLoc) {
89     return ParseSectionSwitch(".data",
90                               COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
91                             | COFF::IMAGE_SCN_MEM_READ
92                             | COFF::IMAGE_SCN_MEM_WRITE,
93                               SectionKind::getDataRel());
94   }
95   bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
96     return ParseSectionSwitch(".bss",
97                               COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
98                             | COFF::IMAGE_SCN_MEM_READ
99                             | COFF::IMAGE_SCN_MEM_WRITE,
100                               SectionKind::getBSS());
101   }
102
103   bool ParseDirectiveDef(StringRef, SMLoc);
104   bool ParseDirectiveScl(StringRef, SMLoc);
105   bool ParseDirectiveType(StringRef, SMLoc);
106   bool ParseDirectiveEndef(StringRef, SMLoc);
107   bool ParseDirectiveSecRel32(StringRef, SMLoc);
108
109   // Win64 EH directives.
110   bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
111   bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
112   bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
113   bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
114   bool ParseSEHDirectiveHandler(StringRef, SMLoc);
115   bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
116   bool ParseSEHDirectivePushReg(StringRef, SMLoc);
117   bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
118   bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
119   bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
120   bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
121   bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
122   bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
123
124   bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
125   bool ParseSEHRegisterNumber(unsigned &RegNo);
126   bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
127 public:
128   COFFAsmParser() {}
129 };
130
131 } // end annonomous namespace.
132
133 /// ParseDirectiveSymbolAttribute
134 ///  ::= { ".weak", ... } [ identifier ( , identifier )* ]
135 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
136   MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
137     .Case(".weak", MCSA_Weak)
138     .Default(MCSA_Invalid);
139   assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
140   if (getLexer().isNot(AsmToken::EndOfStatement)) {
141     for (;;) {
142       StringRef Name;
143
144       if (getParser().parseIdentifier(Name))
145         return TokError("expected identifier in directive");
146
147       MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
148
149       getStreamer().EmitSymbolAttribute(Sym, Attr);
150
151       if (getLexer().is(AsmToken::EndOfStatement))
152         break;
153
154       if (getLexer().isNot(AsmToken::Comma))
155         return TokError("unexpected token in directive");
156       Lex();
157     }
158   }
159
160   Lex();
161   return false;
162 }
163
164 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
165                                        unsigned Characteristics,
166                                        SectionKind Kind) {
167   if (getLexer().isNot(AsmToken::EndOfStatement))
168     return TokError("unexpected token in section switching directive");
169   Lex();
170
171   getStreamer().SwitchSection(getContext().getCOFFSection(
172                                 Section, Characteristics, Kind));
173
174   return false;
175 }
176
177 bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
178   StringRef SymbolName;
179
180   if (getParser().parseIdentifier(SymbolName))
181     return TokError("expected identifier in directive");
182
183   MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
184
185   getStreamer().BeginCOFFSymbolDef(Sym);
186
187   Lex();
188   return false;
189 }
190
191 bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
192   int64_t SymbolStorageClass;
193   if (getParser().parseAbsoluteExpression(SymbolStorageClass))
194     return true;
195
196   if (getLexer().isNot(AsmToken::EndOfStatement))
197     return TokError("unexpected token in directive");
198
199   Lex();
200   getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
201   return false;
202 }
203
204 bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
205   int64_t Type;
206   if (getParser().parseAbsoluteExpression(Type))
207     return true;
208
209   if (getLexer().isNot(AsmToken::EndOfStatement))
210     return TokError("unexpected token in directive");
211
212   Lex();
213   getStreamer().EmitCOFFSymbolType(Type);
214   return false;
215 }
216
217 bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
218   Lex();
219   getStreamer().EndCOFFSymbolDef();
220   return false;
221 }
222
223 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
224   StringRef SymbolID;
225   if (getParser().parseIdentifier(SymbolID))
226     return true;
227
228   if (getLexer().isNot(AsmToken::EndOfStatement))
229     return TokError("unexpected token in directive");
230
231   MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
232
233   Lex();
234   getStreamer().EmitCOFFSecRel32(Symbol);
235   return false;
236 }
237
238 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
239   StringRef SymbolID;
240   if (getParser().parseIdentifier(SymbolID))
241     return true;
242
243   if (getLexer().isNot(AsmToken::EndOfStatement))
244     return TokError("unexpected token in directive");
245
246   MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
247
248   Lex();
249   getStreamer().EmitWin64EHStartProc(Symbol);
250   return false;
251 }
252
253 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
254   Lex();
255   getStreamer().EmitWin64EHEndProc();
256   return false;
257 }
258
259 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
260   Lex();
261   getStreamer().EmitWin64EHStartChained();
262   return false;
263 }
264
265 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
266   Lex();
267   getStreamer().EmitWin64EHEndChained();
268   return false;
269 }
270
271 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
272   StringRef SymbolID;
273   if (getParser().parseIdentifier(SymbolID))
274     return true;
275
276   if (getLexer().isNot(AsmToken::Comma))
277     return TokError("you must specify one or both of @unwind or @except");
278   Lex();
279   bool unwind = false, except = false;
280   if (ParseAtUnwindOrAtExcept(unwind, except))
281     return true;
282   if (getLexer().is(AsmToken::Comma)) {
283     Lex();
284     if (ParseAtUnwindOrAtExcept(unwind, except))
285       return true;
286   }
287   if (getLexer().isNot(AsmToken::EndOfStatement))
288     return TokError("unexpected token in directive");
289
290   MCSymbol *handler = getContext().GetOrCreateSymbol(SymbolID);
291
292   Lex();
293   getStreamer().EmitWin64EHHandler(handler, unwind, except);
294   return false;
295 }
296
297 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
298   Lex();
299   getStreamer().EmitWin64EHHandlerData();
300   return false;
301 }
302
303 bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
304   unsigned Reg;
305   if (ParseSEHRegisterNumber(Reg))
306     return true;
307
308   if (getLexer().isNot(AsmToken::EndOfStatement))
309     return TokError("unexpected token in directive");
310
311   Lex();
312   getStreamer().EmitWin64EHPushReg(Reg);
313   return false;
314 }
315
316 bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
317   unsigned Reg;
318   int64_t Off;
319   if (ParseSEHRegisterNumber(Reg))
320     return true;
321   if (getLexer().isNot(AsmToken::Comma))
322     return TokError("you must specify a stack pointer offset");
323
324   Lex();
325   SMLoc startLoc = getLexer().getLoc();
326   if (getParser().parseAbsoluteExpression(Off))
327     return true;
328
329   if (Off & 0x0F)
330     return Error(startLoc, "offset is not a multiple of 16");
331
332   if (getLexer().isNot(AsmToken::EndOfStatement))
333     return TokError("unexpected token in directive");
334
335   Lex();
336   getStreamer().EmitWin64EHSetFrame(Reg, Off);
337   return false;
338 }
339
340 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
341   int64_t Size;
342   SMLoc startLoc = getLexer().getLoc();
343   if (getParser().parseAbsoluteExpression(Size))
344     return true;
345
346   if (Size & 7)
347     return Error(startLoc, "size is not a multiple of 8");
348
349   if (getLexer().isNot(AsmToken::EndOfStatement))
350     return TokError("unexpected token in directive");
351
352   Lex();
353   getStreamer().EmitWin64EHAllocStack(Size);
354   return false;
355 }
356
357 bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
358   unsigned Reg;
359   int64_t Off;
360   if (ParseSEHRegisterNumber(Reg))
361     return true;
362   if (getLexer().isNot(AsmToken::Comma))
363     return TokError("you must specify an offset on the stack");
364
365   Lex();
366   SMLoc startLoc = getLexer().getLoc();
367   if (getParser().parseAbsoluteExpression(Off))
368     return true;
369
370   if (Off & 7)
371     return Error(startLoc, "size is not a multiple of 8");
372
373   if (getLexer().isNot(AsmToken::EndOfStatement))
374     return TokError("unexpected token in directive");
375
376   Lex();
377   // FIXME: Err on %xmm* registers
378   getStreamer().EmitWin64EHSaveReg(Reg, Off);
379   return false;
380 }
381
382 // FIXME: This method is inherently x86-specific. It should really be in the
383 // x86 backend.
384 bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
385   unsigned Reg;
386   int64_t Off;
387   if (ParseSEHRegisterNumber(Reg))
388     return true;
389   if (getLexer().isNot(AsmToken::Comma))
390     return TokError("you must specify an offset on the stack");
391
392   Lex();
393   SMLoc startLoc = getLexer().getLoc();
394   if (getParser().parseAbsoluteExpression(Off))
395     return true;
396
397   if (getLexer().isNot(AsmToken::EndOfStatement))
398     return TokError("unexpected token in directive");
399
400   if (Off & 0x0F)
401     return Error(startLoc, "offset is not a multiple of 16");
402
403   Lex();
404   // FIXME: Err on non-%xmm* registers
405   getStreamer().EmitWin64EHSaveXMM(Reg, Off);
406   return false;
407 }
408
409 bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
410   bool Code = false;
411   StringRef CodeID;
412   if (getLexer().is(AsmToken::At)) {
413     SMLoc startLoc = getLexer().getLoc();
414     Lex();
415     if (!getParser().parseIdentifier(CodeID)) {
416       if (CodeID != "code")
417         return Error(startLoc, "expected @code");
418       Code = true;
419     }
420   }
421
422   if (getLexer().isNot(AsmToken::EndOfStatement))
423     return TokError("unexpected token in directive");
424
425   Lex();
426   getStreamer().EmitWin64EHPushFrame(Code);
427   return false;
428 }
429
430 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
431   Lex();
432   getStreamer().EmitWin64EHEndProlog();
433   return false;
434 }
435
436 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
437   StringRef identifier;
438   if (getLexer().isNot(AsmToken::At))
439     return TokError("a handler attribute must begin with '@'");
440   SMLoc startLoc = getLexer().getLoc();
441   Lex();
442   if (getParser().parseIdentifier(identifier))
443     return Error(startLoc, "expected @unwind or @except");
444   if (identifier == "unwind")
445     unwind = true;
446   else if (identifier == "except")
447     except = true;
448   else
449     return Error(startLoc, "expected @unwind or @except");
450   return false;
451 }
452
453 bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
454   SMLoc startLoc = getLexer().getLoc();
455   if (getLexer().is(AsmToken::Percent)) {
456     const MCRegisterInfo &MRI = getContext().getRegisterInfo();
457     SMLoc endLoc;
458     unsigned LLVMRegNo;
459     if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
460       return true;
461
462 #if 0
463     // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
464     // violation so this validation code is disabled.
465
466     // Check that this is a non-volatile register.
467     const unsigned *NVRegs = TAI.getCalleeSavedRegs();
468     unsigned i;
469     for (i = 0; NVRegs[i] != 0; ++i)
470       if (NVRegs[i] == LLVMRegNo)
471         break;
472     if (NVRegs[i] == 0)
473       return Error(startLoc, "expected non-volatile register");
474 #endif
475
476     int SEHRegNo = MRI.getSEHRegNum(LLVMRegNo);
477     if (SEHRegNo < 0)
478       return Error(startLoc,"register can't be represented in SEH unwind info");
479     RegNo = SEHRegNo;
480   }
481   else {
482     int64_t n;
483     if (getParser().parseAbsoluteExpression(n))
484       return true;
485     if (n > 15)
486       return Error(startLoc, "register number is too high");
487     RegNo = n;
488   }
489
490   return false;
491 }
492
493 namespace llvm {
494
495 MCAsmParserExtension *createCOFFAsmParser() {
496   return new COFFAsmParser;
497 }
498
499 }