blob: 1ab1af48ad0b37e2a98656fddd752335e67e87c6 [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 Lattnerb0789ed2009-06-21 20:54:55 +000015#include "llvm/Support/SourceMgr.h"
16#include "llvm/Support/raw_ostream.h"
Chris Lattner27aa7d22009-06-21 20:16:42 +000017using namespace llvm;
18
Chris Lattner14ee48a2009-06-21 21:22:11 +000019bool AsmParser::Error(SMLoc L, const char *Msg) {
20 Lexer.PrintMessage(L, Msg);
21 return true;
22}
23
24bool AsmParser::TokError(const char *Msg) {
25 Lexer.PrintMessage(Lexer.getLoc(), Msg);
26 return true;
27}
28
Chris Lattner27aa7d22009-06-21 20:16:42 +000029bool AsmParser::Run() {
Chris Lattnerb0789ed2009-06-21 20:54:55 +000030 // Prime the lexer.
31 Lexer.Lex();
32
33 while (Lexer.isNot(asmtok::Eof))
34 if (ParseStatement())
35 return true;
36
37 return false;
38}
39
Chris Lattner2cf5f142009-06-22 01:29:09 +000040/// EatToEndOfStatement - Throw away the rest of the line for testing purposes.
41void AsmParser::EatToEndOfStatement() {
42 while (Lexer.isNot(asmtok::EndOfStatement) &&
43 Lexer.isNot(asmtok::Eof))
44 Lexer.Lex();
45
46 // Eat EOL.
47 if (Lexer.is(asmtok::EndOfStatement))
48 Lexer.Lex();
49}
50
51struct AsmParser::X86Operand {
52 enum {
53 Register,
54 Immediate
55 } Kind;
56
57 union {
58 struct {
59 unsigned RegNo;
60 } Reg;
61
62 struct {
63 // FIXME: Should be a general expression.
64 int64_t Val;
65 } Imm;
66 };
67
68 static X86Operand CreateReg(unsigned RegNo) {
69 X86Operand Res;
70 Res.Kind = Register;
71 Res.Reg.RegNo = RegNo;
72 return Res;
73 }
74 static X86Operand CreateImm(int64_t Val) {
75 X86Operand Res;
76 Res.Kind = Immediate;
77 Res.Imm.Val = Val;
78 return Res;
79 }
80};
81
82bool AsmParser::ParseX86Operand(X86Operand &Op) {
83 switch (Lexer.getKind()) {
84 default:
85 return TokError("unknown token at start of instruction operand");
86 case asmtok::Register:
87 // FIXME: Decode reg #.
88 Op = X86Operand::CreateReg(0);
89 Lexer.Lex(); // Eat register.
90 return false;
91 case asmtok::Dollar:
92 // $42 -> immediate.
93 Lexer.Lex();
94 // FIXME: Parse an arbitrary expression here, like $(4+5)
95 if (Lexer.isNot(asmtok::IntVal))
96 return TokError("expected integer constant");
97
98 Op = X86Operand::CreateReg(Lexer.getCurIntVal());
99 Lexer.Lex(); // Eat register.
100 return false;
101 case asmtok::Identifier:
102 // This is a label, this should be parsed as part of an expression, to
103 // handle things like LFOO+4
104 Op = X86Operand::CreateImm(0); // FIXME.
105 Lexer.Lex(); // Eat identifier.
106 return false;
107
108 //case asmtok::Star:
109 // * %eax
110 // * <memaddress>
111 // Note that these are both "dereferenced".
112 }
113}
114
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000115
116/// ParseStatement:
117/// ::= EndOfStatement
Chris Lattner2cf5f142009-06-22 01:29:09 +0000118/// ::= Label* Directive ...Operands... EndOfStatement
119/// ::= Label* Identifier OperandList* EndOfStatement
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000120bool AsmParser::ParseStatement() {
121 switch (Lexer.getKind()) {
122 default:
Chris Lattner14ee48a2009-06-21 21:22:11 +0000123 return TokError("unexpected token at start of statement");
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000124 case asmtok::EndOfStatement:
125 Lexer.Lex();
126 return false;
127 case asmtok::Identifier:
128 break;
129 // TODO: Recurse on local labels etc.
130 }
131
132 // If we have an identifier, handle it as the key symbol.
Chris Lattner2cf5f142009-06-22 01:29:09 +0000133 SMLoc IDLoc = Lexer.getLoc();
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000134 std::string IDVal = Lexer.getCurStrVal();
135
136 // Consume the identifier, see what is after it.
137 if (Lexer.Lex() == asmtok::Colon) {
138 // identifier ':' -> Label.
139 Lexer.Lex();
140 return ParseStatement();
141 }
142
143 // Otherwise, we have a normal instruction or directive.
Chris Lattner2cf5f142009-06-22 01:29:09 +0000144 if (IDVal[0] == '.') {
145 Lexer.PrintMessage(IDLoc, "warning: ignoring directive for now");
146 EatToEndOfStatement();
147 return false;
148 }
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000149
Chris Lattner2cf5f142009-06-22 01:29:09 +0000150 // If it's an instruction, parse an operand list.
151 std::vector<X86Operand> Operands;
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000152
Chris Lattner2cf5f142009-06-22 01:29:09 +0000153 // Read the first operand, if present. Note that we require a newline at the
154 // end of file, so we don't have to worry about Eof here.
155 if (Lexer.isNot(asmtok::EndOfStatement)) {
156 X86Operand Op;
157 if (ParseX86Operand(Op))
158 return true;
159 Operands.push_back(Op);
160 }
161
162 while (Lexer.is(asmtok::Comma)) {
163 Lexer.Lex(); // Eat the comma.
164
165 // Parse and remember the operand.
166 X86Operand Op;
167 if (ParseX86Operand(Op))
168 return true;
169 Operands.push_back(Op);
170 }
171
172 if (Lexer.isNot(asmtok::EndOfStatement))
173 return TokError("unexpected token in operand list");
174
175 // Eat the end of statement marker.
176 Lexer.Lex();
177
178 // Instruction is good, process it.
179 outs() << "Found instruction: " << IDVal << " with " << Operands.size()
180 << " operands.\n";
181
182 // Skip to end of line for now.
Chris Lattner27aa7d22009-06-21 20:16:42 +0000183 return false;
184}