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