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