blob: 04c1d0301cbf1aba21d88e7b76911d58436b829d [file] [log] [blame]
Chris Lattner27aa7d22009-06-21 20:16:42 +00001//===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
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// This class implements the parser for assembly files.
11//
12//===----------------------------------------------------------------------===//
13
14#include "AsmParser.h"
Chris Lattner29dfe7c2009-06-23 18:41:30 +000015#include "llvm/MC/MCInst.h"
Chris Lattnerb0789ed2009-06-21 20:54:55 +000016#include "llvm/Support/SourceMgr.h"
17#include "llvm/Support/raw_ostream.h"
Chris Lattner27aa7d22009-06-21 20:16:42 +000018using namespace llvm;
19
Chris Lattner14ee48a2009-06-21 21:22:11 +000020bool AsmParser::Error(SMLoc L, const char *Msg) {
21 Lexer.PrintMessage(L, Msg);
22 return true;
23}
24
25bool AsmParser::TokError(const char *Msg) {
26 Lexer.PrintMessage(Lexer.getLoc(), Msg);
27 return true;
28}
29
Chris Lattner27aa7d22009-06-21 20:16:42 +000030bool AsmParser::Run() {
Chris Lattnerb0789ed2009-06-21 20:54:55 +000031 // Prime the lexer.
32 Lexer.Lex();
33
34 while (Lexer.isNot(asmtok::Eof))
35 if (ParseStatement())
36 return true;
37
38 return false;
39}
40
Chris Lattner2cf5f142009-06-22 01:29:09 +000041/// EatToEndOfStatement - Throw away the rest of the line for testing purposes.
42void AsmParser::EatToEndOfStatement() {
43 while (Lexer.isNot(asmtok::EndOfStatement) &&
44 Lexer.isNot(asmtok::Eof))
45 Lexer.Lex();
46
47 // Eat EOL.
48 if (Lexer.is(asmtok::EndOfStatement))
49 Lexer.Lex();
50}
51
Chris Lattnerc4193832009-06-22 05:51:26 +000052
Chris Lattner74ec1a32009-06-22 06:32:03 +000053/// ParseParenExpr - Parse a paren expression and return it.
54/// NOTE: This assumes the leading '(' has already been consumed.
55///
56/// parenexpr ::= expr)
57///
58bool AsmParser::ParseParenExpr(int64_t &Res) {
59 if (ParseExpression(Res)) return true;
60 if (Lexer.isNot(asmtok::RParen))
61 return TokError("expected ')' in parentheses expression");
62 Lexer.Lex();
63 return false;
64}
Chris Lattnerc4193832009-06-22 05:51:26 +000065
Chris Lattner74ec1a32009-06-22 06:32:03 +000066/// ParsePrimaryExpr - Parse a primary expression and return it.
67/// primaryexpr ::= (parenexpr
68/// primaryexpr ::= symbol
69/// primaryexpr ::= number
70/// primaryexpr ::= ~,+,- primaryexpr
71bool AsmParser::ParsePrimaryExpr(int64_t &Res) {
Chris Lattnerc4193832009-06-22 05:51:26 +000072 switch (Lexer.getKind()) {
73 default:
74 return TokError("unknown token in expression");
75 case asmtok::Identifier:
76 // This is a label, this should be parsed as part of an expression, to
77 // handle things like LFOO+4
78 Res = 0; // FIXME.
79 Lexer.Lex(); // Eat identifier.
80 return false;
81 case asmtok::IntVal:
82 Res = Lexer.getCurIntVal();
83 Lexer.Lex(); // Eat identifier.
84 return false;
Chris Lattner74ec1a32009-06-22 06:32:03 +000085 case asmtok::LParen:
86 Lexer.Lex(); // Eat the '('.
87 return ParseParenExpr(Res);
88 case asmtok::Tilde:
89 case asmtok::Plus:
90 case asmtok::Minus:
91 Lexer.Lex(); // Eat the operator.
92 return ParsePrimaryExpr(Res);
Chris Lattnerc4193832009-06-22 05:51:26 +000093 }
94}
Chris Lattner74ec1a32009-06-22 06:32:03 +000095
96/// ParseExpression - Parse an expression and return it.
97///
98/// expr ::= expr +,- expr -> lowest.
99/// expr ::= expr |,^,&,! expr -> middle.
100/// expr ::= expr *,/,%,<<,>> expr -> highest.
101/// expr ::= primaryexpr
102///
103bool AsmParser::ParseExpression(int64_t &Res) {
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000104 return ParsePrimaryExpr(Res) ||
105 ParseBinOpRHS(1, Res);
Chris Lattner74ec1a32009-06-22 06:32:03 +0000106}
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000107
108static unsigned getBinOpPrecedence(asmtok::TokKind K) {
109 switch (K) {
110 default: return 0; // not a binop.
111 case asmtok::Plus:
112 case asmtok::Minus:
113 return 1;
114 case asmtok::Pipe:
115 case asmtok::Caret:
116 case asmtok::Amp:
117 case asmtok::Exclaim:
118 return 2;
119 case asmtok::Star:
120 case asmtok::Slash:
121 case asmtok::Percent:
122 case asmtok::LessLess:
123 case asmtok::GreaterGreater:
124 return 3;
125 }
126}
127
128
129/// ParseBinOpRHS - Parse all binary operators with precedence >= 'Precedence'.
130/// Res contains the LHS of the expression on input.
131bool AsmParser::ParseBinOpRHS(unsigned Precedence, int64_t &Res) {
132 while (1) {
133 unsigned TokPrec = getBinOpPrecedence(Lexer.getKind());
134
135 // If the next token is lower precedence than we are allowed to eat, return
136 // successfully with what we ate already.
137 if (TokPrec < Precedence)
138 return false;
139
140 //asmtok::TokKind BinOp = Lexer.getKind();
141 Lexer.Lex();
142
143 // Eat the next primary expression.
144 int64_t RHS;
145 if (ParsePrimaryExpr(RHS)) return true;
146
147 // If BinOp binds less tightly with RHS than the operator after RHS, let
148 // the pending operator take RHS as its LHS.
149 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind());
150 if (TokPrec < NextTokPrec) {
151 if (ParseBinOpRHS(Precedence+1, RHS)) return true;
152 }
153
154 // Merge LHS/RHS: fixme use the right operator etc.
155 Res += RHS;
156 }
157}
158
Chris Lattnerc4193832009-06-22 05:51:26 +0000159
160
161
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000162/// ParseStatement:
163/// ::= EndOfStatement
Chris Lattner2cf5f142009-06-22 01:29:09 +0000164/// ::= Label* Directive ...Operands... EndOfStatement
165/// ::= Label* Identifier OperandList* EndOfStatement
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000166bool AsmParser::ParseStatement() {
167 switch (Lexer.getKind()) {
168 default:
Chris Lattner14ee48a2009-06-21 21:22:11 +0000169 return TokError("unexpected token at start of statement");
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000170 case asmtok::EndOfStatement:
171 Lexer.Lex();
172 return false;
173 case asmtok::Identifier:
174 break;
175 // TODO: Recurse on local labels etc.
176 }
177
178 // If we have an identifier, handle it as the key symbol.
Chris Lattner2cf5f142009-06-22 01:29:09 +0000179 SMLoc IDLoc = Lexer.getLoc();
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000180 std::string IDVal = Lexer.getCurStrVal();
181
182 // Consume the identifier, see what is after it.
183 if (Lexer.Lex() == asmtok::Colon) {
184 // identifier ':' -> Label.
185 Lexer.Lex();
186 return ParseStatement();
187 }
188
189 // Otherwise, we have a normal instruction or directive.
Chris Lattner2cf5f142009-06-22 01:29:09 +0000190 if (IDVal[0] == '.') {
191 Lexer.PrintMessage(IDLoc, "warning: ignoring directive for now");
192 EatToEndOfStatement();
193 return false;
194 }
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000195
Chris Lattner2cf5f142009-06-22 01:29:09 +0000196
Chris Lattner29dfe7c2009-06-23 18:41:30 +0000197 MCInst Inst;
198 if (ParseX86InstOperands(Inst))
199 return true;
Chris Lattner2cf5f142009-06-22 01:29:09 +0000200
201 if (Lexer.isNot(asmtok::EndOfStatement))
202 return TokError("unexpected token in operand list");
203
204 // Eat the end of statement marker.
205 Lexer.Lex();
206
207 // Instruction is good, process it.
Chris Lattner29dfe7c2009-06-23 18:41:30 +0000208 outs() << "Found instruction: " << IDVal << " with " << Inst.getNumOperands()
Chris Lattner2cf5f142009-06-22 01:29:09 +0000209 << " operands.\n";
210
211 // Skip to end of line for now.
Chris Lattner27aa7d22009-06-21 20:16:42 +0000212 return false;
213}