Disable X86 AsmMatcher for now, it is causing gcc-4.0 to run out of memory on
[oota-llvm.git] / lib / Target / X86 / AsmParser / X86AsmParser.cpp
1 //===-- X86AsmParser.cpp - Parse X86 assembly to MCInst instructions ------===//
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 "X86.h"
11 #include "llvm/ADT/SmallVector.h"
12 #include "llvm/ADT/Twine.h"
13 #include "llvm/MC/MCAsmLexer.h"
14 #include "llvm/MC/MCAsmParser.h"
15 #include "llvm/MC/MCInst.h"
16 #include "llvm/MC/MCValue.h"
17 #include "llvm/Support/SourceMgr.h"
18 #include "llvm/Target/TargetRegistry.h"
19 #include "llvm/Target/TargetAsmParser.h"
20 using namespace llvm;
21
22 namespace {
23 struct X86Operand;
24
25 class X86ATTAsmParser : public TargetAsmParser {
26   MCAsmParser &Parser;
27
28 private:
29   MCAsmParser &getParser() const { return Parser; }
30
31   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
32
33   void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
34
35   bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
36
37   bool ParseRegister(X86Operand &Op);
38
39   bool ParseOperand(X86Operand &Op);
40
41   bool ParseMemOperand(X86Operand &Op);
42   
43   /// @name Auto-generated Match Functions
44   /// {  
45
46   bool MatchInstruction(SmallVectorImpl<X86Operand> &Operands,
47                         MCInst &Inst);
48
49   bool MatchRegisterName(const StringRef &Name, unsigned &RegNo);
50
51   /// }
52
53 public:
54   X86ATTAsmParser(const Target &T, MCAsmParser &_Parser)
55     : TargetAsmParser(T), Parser(_Parser) {}
56
57   virtual bool ParseInstruction(const StringRef &Name, MCInst &Inst);
58 };
59   
60 } // end anonymous namespace
61
62
63 namespace {
64
65 /// X86Operand - Instances of this class represent a parsed X86 machine
66 /// instruction.
67 struct X86Operand {
68   enum {
69     Token,
70     Register,
71     Immediate,
72     Memory
73   } Kind;
74
75   union {
76     struct {
77       const char *Data;
78       unsigned Length;
79     } Tok;
80
81     struct {
82       unsigned RegNo;
83     } Reg;
84
85     struct {
86       MCValue Val;
87     } Imm;
88
89     struct {
90       unsigned SegReg;
91       MCValue Disp;
92       unsigned BaseReg;
93       unsigned IndexReg;
94       unsigned Scale;
95     } Mem;
96   };
97
98   StringRef getToken() const {
99     assert(Kind == Token && "Invalid access!");
100     return StringRef(Tok.Data, Tok.Length);
101   }
102
103   unsigned getReg() const {
104     assert(Kind == Register && "Invalid access!");
105     return Reg.RegNo;
106   }
107
108   const MCValue &getImm() const {
109     assert(Kind == Immediate && "Invalid access!");
110     return Imm.Val;
111   }
112
113   const MCValue &getMemDisp() const {
114     assert(Kind == Memory && "Invalid access!");
115     return Mem.Disp;
116   }
117   unsigned getMemSegReg() const {
118     assert(Kind == Memory && "Invalid access!");
119     return Mem.SegReg;
120   }
121   unsigned getMemBaseReg() const {
122     assert(Kind == Memory && "Invalid access!");
123     return Mem.BaseReg;
124   }
125   unsigned getMemIndexReg() const {
126     assert(Kind == Memory && "Invalid access!");
127     return Mem.IndexReg;
128   }
129   unsigned getMemScale() const {
130     assert(Kind == Memory && "Invalid access!");
131     return Mem.Scale;
132   }
133
134   bool isToken(const StringRef &Str) const { 
135     return Kind == Token && Str == getToken(); 
136   }
137
138   bool isImm() const { return Kind == Immediate; }
139   
140   bool isMem() const { return Kind == Memory; }
141
142   bool isReg() const { return Kind == Register; }
143
144   void addRegOperands(MCInst &Inst, unsigned N) {
145     assert(N == 1 && "Invalid number of operands!");
146     Inst.addOperand(MCOperand::CreateReg(getReg()));
147   }
148
149   void addImmOperands(MCInst &Inst, unsigned N) {
150     assert(N == 1 && "Invalid number of operands!");
151     Inst.addOperand(MCOperand::CreateMCValue(getImm()));
152   }
153
154   void addMemOperands(MCInst &Inst, unsigned N) {
155     assert((N == 4 || N == 5) && "Invalid number of operands!");
156
157     Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
158     Inst.addOperand(MCOperand::CreateImm(getMemScale()));
159     Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
160     Inst.addOperand(MCOperand::CreateMCValue(getMemDisp()));
161
162     // FIXME: What a hack.
163     if (N == 5)
164       Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
165   }
166
167   static X86Operand CreateToken(StringRef Str) {
168     X86Operand Res;
169     Res.Kind = Token;
170     Res.Tok.Data = Str.data();
171     Res.Tok.Length = Str.size();
172     return Res;
173   }
174
175   static X86Operand CreateReg(unsigned RegNo) {
176     X86Operand Res;
177     Res.Kind = Register;
178     Res.Reg.RegNo = RegNo;
179     return Res;
180   }
181
182   static X86Operand CreateImm(MCValue Val) {
183     X86Operand Res;
184     Res.Kind = Immediate;
185     Res.Imm.Val = Val;
186     return Res;
187   }
188
189   static X86Operand CreateMem(unsigned SegReg, MCValue Disp, unsigned BaseReg,
190                               unsigned IndexReg, unsigned Scale) {
191     // We should never just have a displacement, that would be an immediate.
192     assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
193
194     // The scale should always be one of {1,2,4,8}.
195     assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
196            "Invalid scale!");
197     X86Operand Res;
198     Res.Kind = Memory;
199     Res.Mem.SegReg   = SegReg;
200     Res.Mem.Disp     = Disp;
201     Res.Mem.BaseReg  = BaseReg;
202     Res.Mem.IndexReg = IndexReg;
203     Res.Mem.Scale    = Scale;
204     return Res;
205   }
206 };
207
208 } // end anonymous namespace.
209
210
211 bool X86ATTAsmParser::ParseRegister(X86Operand &Op) {
212   const AsmToken &Tok = getLexer().getTok();
213   assert(Tok.is(AsmToken::Register) && "Invalid token kind!");
214
215   // FIXME: Validate register for the current architecture; we have to do
216   // validation later, so maybe there is no need for this here.
217   unsigned RegNo;
218   assert(Tok.getString().startswith("%") && "Invalid register name!");
219   if (MatchRegisterName(Tok.getString().substr(1), RegNo))
220     return Error(Tok.getLoc(), "invalid register name");
221
222   Op = X86Operand::CreateReg(RegNo);
223   getLexer().Lex(); // Eat register token.
224
225   return false;
226 }
227
228 bool X86ATTAsmParser::ParseOperand(X86Operand &Op) {
229   switch (getLexer().getKind()) {
230   default:
231     return ParseMemOperand(Op);
232   case AsmToken::Register:
233     // FIXME: if a segment register, this could either be just the seg reg, or
234     // the start of a memory operand.
235     return ParseRegister(Op);
236   case AsmToken::Dollar: {
237     // $42 -> immediate.
238     getLexer().Lex();
239     MCValue Val;
240     if (getParser().ParseRelocatableExpression(Val))
241       return true;
242     Op = X86Operand::CreateImm(Val);
243     return false;
244   }
245   case AsmToken::Star:
246     getLexer().Lex(); // Eat the star.
247     
248     if (getLexer().is(AsmToken::Register)) {
249       if (ParseRegister(Op))
250         return true;
251     } else if (ParseMemOperand(Op))
252       return true;
253
254     // FIXME: Note the '*' in the operand for use by the matcher.
255     return false;
256   }
257 }
258
259 /// ParseMemOperand: segment: disp(basereg, indexreg, scale)
260 bool X86ATTAsmParser::ParseMemOperand(X86Operand &Op) {
261   // FIXME: If SegReg ':'  (e.g. %gs:), eat and remember.
262   unsigned SegReg = 0;
263   
264   // We have to disambiguate a parenthesized expression "(4+5)" from the start
265   // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)".  The
266   // only way to do this without lookahead is to eat the ( and see what is after
267   // it.
268   MCValue Disp = MCValue::get(0, 0, 0);
269   if (getLexer().isNot(AsmToken::LParen)) {
270     if (getParser().ParseRelocatableExpression(Disp)) return true;
271     
272     // After parsing the base expression we could either have a parenthesized
273     // memory address or not.  If not, return now.  If so, eat the (.
274     if (getLexer().isNot(AsmToken::LParen)) {
275       // Unless we have a segment register, treat this as an immediate.
276       if (SegReg)
277         Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 1);
278       else
279         Op = X86Operand::CreateImm(Disp);
280       return false;
281     }
282     
283     // Eat the '('.
284     getLexer().Lex();
285   } else {
286     // Okay, we have a '('.  We don't know if this is an expression or not, but
287     // so we have to eat the ( to see beyond it.
288     getLexer().Lex(); // Eat the '('.
289     
290     if (getLexer().is(AsmToken::Register) || getLexer().is(AsmToken::Comma)) {
291       // Nothing to do here, fall into the code below with the '(' part of the
292       // memory operand consumed.
293     } else {
294       // It must be an parenthesized expression, parse it now.
295       if (getParser().ParseParenRelocatableExpression(Disp))
296         return true;
297       
298       // After parsing the base expression we could either have a parenthesized
299       // memory address or not.  If not, return now.  If so, eat the (.
300       if (getLexer().isNot(AsmToken::LParen)) {
301         // Unless we have a segment register, treat this as an immediate.
302         if (SegReg)
303           Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 1);
304         else
305           Op = X86Operand::CreateImm(Disp);
306         return false;
307       }
308       
309       // Eat the '('.
310       getLexer().Lex();
311     }
312   }
313   
314   // If we reached here, then we just ate the ( of the memory operand.  Process
315   // the rest of the memory operand.
316   unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
317   
318   if (getLexer().is(AsmToken::Register)) {
319     if (ParseRegister(Op))
320       return true;
321     BaseReg = Op.getReg();
322   }
323   
324   if (getLexer().is(AsmToken::Comma)) {
325     getLexer().Lex(); // Eat the comma.
326
327     // Following the comma we should have either an index register, or a scale
328     // value. We don't support the later form, but we want to parse it
329     // correctly.
330     //
331     // Not that even though it would be completely consistent to support syntax
332     // like "1(%eax,,1)", the assembler doesn't.
333     if (getLexer().is(AsmToken::Register)) {
334       if (ParseRegister(Op))
335         return true;
336       IndexReg = Op.getReg();
337     
338       if (getLexer().isNot(AsmToken::RParen)) {
339         // Parse the scale amount:
340         //  ::= ',' [scale-expression]
341         if (getLexer().isNot(AsmToken::Comma))
342           return true;
343         getLexer().Lex(); // Eat the comma.
344
345         if (getLexer().isNot(AsmToken::RParen)) {
346           SMLoc Loc = getLexer().getTok().getLoc();
347
348           int64_t ScaleVal;
349           if (getParser().ParseAbsoluteExpression(ScaleVal))
350             return true;
351           
352           // Validate the scale amount.
353           if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8)
354             return Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
355           Scale = (unsigned)ScaleVal;
356         }
357       }
358     } else if (getLexer().isNot(AsmToken::RParen)) {
359       // Otherwise we have the unsupported form of a scale amount without an
360       // index.
361       SMLoc Loc = getLexer().getTok().getLoc();
362
363       int64_t Value;
364       if (getParser().ParseAbsoluteExpression(Value))
365         return true;
366       
367       return Error(Loc, "cannot have scale factor without index register");
368     }
369   }
370   
371   // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
372   if (getLexer().isNot(AsmToken::RParen))
373     return Error(getLexer().getTok().getLoc(),
374                     "unexpected token in memory operand");
375   getLexer().Lex(); // Eat the ')'.
376   
377   Op = X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale);
378   return false;
379 }
380
381 bool X86ATTAsmParser::ParseInstruction(const StringRef &Name, MCInst &Inst) {
382   SmallVector<X86Operand, 4> Operands;
383
384   Operands.push_back(X86Operand::CreateToken(Name));
385
386   SMLoc Loc = getLexer().getTok().getLoc();
387   if (getLexer().isNot(AsmToken::EndOfStatement)) {
388     // Read the first operand.
389     Operands.push_back(X86Operand());
390     if (ParseOperand(Operands.back()))
391       return true;
392
393     while (getLexer().is(AsmToken::Comma)) {
394       getLexer().Lex();  // Eat the comma.
395
396       // Parse and remember the operand.
397       Operands.push_back(X86Operand());
398       if (ParseOperand(Operands.back()))
399         return true;
400     }
401   }
402
403   if (!MatchInstruction(Operands, Inst))
404     return false;
405
406   // FIXME: We should give nicer diagnostics about the exact failure.
407
408   // FIXME: For now we just treat unrecognized instructions as "warnings".
409   Warning(Loc, "unrecognized instruction");
410
411   return false;
412 }
413
414 // Force static initialization.
415 extern "C" void LLVMInitializeX86AsmParser() {
416   RegisterAsmParser<X86ATTAsmParser> X(TheX86_32Target);
417   RegisterAsmParser<X86ATTAsmParser> Y(TheX86_64Target);
418 }
419
420 // FIXME: Disabled for now, this is causing gcc-4.0 to run out of memory during
421 // building.
422 #if 0
423
424 #include "X86GenAsmMatcher.inc"
425
426 #else
427
428 bool X86ATTAsmParser::MatchInstruction(SmallVectorImpl<X86Operand> &Operands,
429                                        MCInst &Inst) {
430   return false;
431 }
432   
433 bool X86ATTAsmParser::MatchRegisterName(const StringRef &Name,
434                                         unsigned &RegNo) {
435   return false;
436 }
437
438 #endif
439