OSDN Git Service

Implement .seh_stackalloc and .seh_pushframe parsing.
[android-x86/external-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/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/Support/COFF.h"
19 using namespace llvm;
20
21 namespace {
22
23 class COFFAsmParser : public MCAsmParserExtension {
24   template<bool (COFFAsmParser::*Handler)(StringRef, SMLoc)>
25   void AddDirectiveHandler(StringRef Directive) {
26     getParser().AddDirectiveHandler(this, Directive,
27                                     HandleDirective<COFFAsmParser, Handler>);
28   }
29
30   bool ParseSectionSwitch(StringRef Section,
31                           unsigned Characteristics,
32                           SectionKind Kind);
33
34   virtual void Initialize(MCAsmParser &Parser) {
35     // Call the base implementation.
36     MCAsmParserExtension::Initialize(Parser);
37
38     AddDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
39     AddDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
40     AddDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
41     AddDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
42     AddDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
43     AddDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
44     AddDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
45
46     // Win64 EH directives.
47     AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
48                                                                    ".seh_proc");
49     AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
50                                                                 ".seh_endproc");
51     AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
52                                                            ".seh_startchained");
53     AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
54                                                              ".seh_endchained");
55     AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
56                                                                 ".seh_handler");
57     AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
58                                                             ".seh_handlerdata");
59     AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
60                                                                 ".seh_pushreg");
61     AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
62                                                                ".seh_setframe");
63     AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
64                                                              ".seh_stackalloc");
65     AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
66                                                                 ".seh_savereg");
67     AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
68                                                                 ".seh_savexmm");
69     AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
70                                                               ".seh_pushframe");
71     AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
72                                                             ".seh_endprologue");
73   }
74
75   bool ParseSectionDirectiveText(StringRef, SMLoc) {
76     return ParseSectionSwitch(".text",
77                               COFF::IMAGE_SCN_CNT_CODE
78                             | COFF::IMAGE_SCN_MEM_EXECUTE
79                             | COFF::IMAGE_SCN_MEM_READ,
80                               SectionKind::getText());
81   }
82   bool ParseSectionDirectiveData(StringRef, SMLoc) {
83     return ParseSectionSwitch(".data",
84                               COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
85                             | COFF::IMAGE_SCN_MEM_READ
86                             | COFF::IMAGE_SCN_MEM_WRITE,
87                               SectionKind::getDataRel());
88   }
89   bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
90     return ParseSectionSwitch(".bss",
91                               COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
92                             | COFF::IMAGE_SCN_MEM_READ
93                             | COFF::IMAGE_SCN_MEM_WRITE,
94                               SectionKind::getBSS());
95   }
96
97   bool ParseDirectiveDef(StringRef, SMLoc);
98   bool ParseDirectiveScl(StringRef, SMLoc);
99   bool ParseDirectiveType(StringRef, SMLoc);
100   bool ParseDirectiveEndef(StringRef, SMLoc);
101
102   // Win64 EH directives.
103   bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
104   bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
105   bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
106   bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
107   bool ParseSEHDirectiveHandler(StringRef, SMLoc);
108   bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
109   bool ParseSEHDirectivePushReg(StringRef, SMLoc L);
110   bool ParseSEHDirectiveSetFrame(StringRef, SMLoc L);
111   bool ParseSEHDirectiveAllocStack(StringRef, SMLoc L);
112   bool ParseSEHDirectiveSaveReg(StringRef, SMLoc L);
113   bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc L);
114   bool ParseSEHDirectivePushFrame(StringRef, SMLoc L);
115   bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
116
117   bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
118 public:
119   COFFAsmParser() {}
120 };
121
122 } // end annonomous namespace.
123
124 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
125                                        unsigned Characteristics,
126                                        SectionKind Kind) {
127   if (getLexer().isNot(AsmToken::EndOfStatement))
128     return TokError("unexpected token in section switching directive");
129   Lex();
130
131   getStreamer().SwitchSection(getContext().getCOFFSection(
132                                 Section, Characteristics, Kind));
133
134   return false;
135 }
136
137 bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
138   StringRef SymbolName;
139
140   if (getParser().ParseIdentifier(SymbolName))
141     return TokError("expected identifier in directive");
142
143   MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
144
145   getStreamer().BeginCOFFSymbolDef(Sym);
146
147   Lex();
148   return false;
149 }
150
151 bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
152   int64_t SymbolStorageClass;
153   if (getParser().ParseAbsoluteExpression(SymbolStorageClass))
154     return true;
155
156   if (getLexer().isNot(AsmToken::EndOfStatement))
157     return TokError("unexpected token in directive");
158
159   Lex();
160   getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
161   return false;
162 }
163
164 bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
165   int64_t Type;
166   if (getParser().ParseAbsoluteExpression(Type))
167     return true;
168
169   if (getLexer().isNot(AsmToken::EndOfStatement))
170     return TokError("unexpected token in directive");
171
172   Lex();
173   getStreamer().EmitCOFFSymbolType(Type);
174   return false;
175 }
176
177 bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
178   Lex();
179   getStreamer().EndCOFFSymbolDef();
180   return false;
181 }
182
183 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
184   const MCExpr *e;
185   const MCSymbolRefExpr *funcExpr;
186   SMLoc startLoc = getLexer().getLoc();
187   if (getParser().ParseExpression(e))
188     return true;
189
190   if (!(funcExpr = dyn_cast<MCSymbolRefExpr>(e)))
191     return Error(startLoc, "expected symbol");
192
193   if (getLexer().isNot(AsmToken::EndOfStatement))
194     return TokError("unexpected token in directive");
195
196   Lex();
197   getStreamer().EmitWin64EHStartProc(&funcExpr->getSymbol());
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   const MCExpr *e;
221   const MCSymbolRefExpr *funcExpr;
222   SMLoc startLoc = getLexer().getLoc();
223   if (getParser().ParseExpression(e))
224     return true;
225
226   if (!(funcExpr = dyn_cast<MCSymbolRefExpr>(e)))
227     return Error(startLoc, "expected symbol");
228
229   bool unwind = false, except = false;
230   if (!ParseAtUnwindOrAtExcept(unwind, except))
231     return true;
232   if (getLexer().is(AsmToken::Comma)) {
233     Lex();
234     if (!ParseAtUnwindOrAtExcept(unwind, except))
235       return true;
236   }
237   if (getLexer().isNot(AsmToken::EndOfStatement))
238     return TokError("unexpected token in directive");
239
240   Lex();
241   getStreamer().EmitWin64EHHandler(&funcExpr->getSymbol(), 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   return Error(L, "not implemented yet");
253 }
254
255 bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
256   return Error(L, "not implemented yet");
257 }
258
259 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
260   int64_t Size;
261   if (getParser().ParseAbsoluteExpression(Size))
262     return true;
263
264   if (getLexer().isNot(AsmToken::EndOfStatement))
265     return TokError("unexpected token in directive");
266
267   Lex();
268   getStreamer().EmitWin64EHAllocStack(Size);
269   return false;
270 }
271
272 bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
273   return Error(L, "not implemented yet");
274 }
275
276 bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
277   return Error(L, "not implemented yet");
278 }
279
280 bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
281   bool Code;
282   StringRef CodeID;
283   SMLoc startLoc = getLexer().getLoc();
284   if (!getParser().ParseIdentifier(CodeID)) {
285     if (CodeID != "@code")
286       return Error(startLoc, "expected @code");
287     Code = true;
288   }
289
290   if (getLexer().isNot(AsmToken::EndOfStatement))
291     return TokError("unexpected token in directive");
292
293   Lex();
294   getStreamer().EmitWin64EHPushFrame(Code);
295   return false;
296 }
297
298 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
299   Lex();
300   getStreamer().EmitWin64EHEndProlog();
301   return false;
302 }
303
304 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
305   StringRef identifier;
306   SMLoc startLoc = getLexer().getLoc();
307   if (!getParser().ParseIdentifier(identifier))
308     return Error(startLoc, "expected @unwind or @except");
309   if (identifier == "@unwind")
310     unwind = true;
311   else if (identifier == "@except")
312     except = true;
313   else
314     return Error(startLoc, "expected @unwind or @except");
315   return false;
316 }
317
318 namespace llvm {
319
320 MCAsmParserExtension *createCOFFAsmParser() {
321   return new COFFAsmParser;
322 }
323
324 }