forked from shhyou/rubi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
expr.c
179 lines (166 loc) · 6.29 KB
/
expr.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "expr.h"
#include "rubi.h"
#include "asm.h"
#include "parser.h"
extern int make_stdfunc(char *);
static inline int32_t isIndex() { return !strcmp(tok.tok[tok.pos].val, "["); }
static void primExpr()
{
if (isdigit(tok.tok[tok.pos].val[0])) { // number?
emit(0xb8 + EAX); emitI32(atoi(tok.tok[tok.pos++].val)); // mov eax %d
} else if (skip("'")) { // char?
emit(0xb8 + EAX);
emitI32(tok.tok[tok.pos++].val[0]); // mov eax %d
skip("'");
} else if (skip("\"")) { // string?
emit(0xb8); getString(); emitI32(0x00); // mov eax string_address
} else if (isalpha(tok.tok[tok.pos].val[0])) { // variable or inc or dec
char *name = tok.tok[tok.pos].val;
Variable *v;
if (isassign()) assignment();
else {
tok.pos++;
if (skip("[")) { // Array?
if ((v = getVar(name)) == NULL)
error("%d: '%s' was not declared",
tok.tok[tok.pos].nline, name);
relExpr();
emit(0x89); emit(0xc0 + EAX * 8 + ECX); // mov ecx eax
if (v->loctype == V_LOCAL) {
emit(0x8b); emit(0x55);
emit(256 - sizeof(int32_t) * v->id); // mov edx, [ebp - v*4]
} else if (v->loctype == V_GLOBAL) {
emit(0x8b); emit(0x15); emitI32(v->id);
// mov edx, GLOBAL_ADDR
}
if (v->type == T_INT) {
emit(0x8b); emit(0x04); emit(0x8a);
// mov eax, [edx + ecx * 4]
} else {
emit(0x0f); emit(0xb6); emit(0x04); emit(0x0a);
// movzx eax, [edx + ecx]
}
if (!skip("]"))
error("%d: expected expression ']'",
tok.tok[tok.pos].nline);
} else if (skip("(")) { // Function?
if (!make_stdfunc(name)) { // standard function
func_t *function = getFunc(name);
char *val = tok.tok[tok.pos].val;
if (isalpha(val[0]) || isdigit(val[0]) ||
!strcmp(val, "\"") || !strcmp(val, "(")) { // has arg?
for (int i = 0; i < function->args; i++) {
relExpr();
emit(0x50 + EAX); // push eax
skip(",");
}
}
emit(0xe8); emitI32(0xFFFFFFFF -
(ntvCount - function->address) - 3);
// call func
emit(0x81); emit(0xc0 + ESP);
emitI32(function->args * sizeof(int32_t)); // add esp %d
}
if (!skip(")"))
error("func: %d: expected expression ')'",
tok.tok[tok.pos].nline);
} else {
if ((v = getVar(name)) == NULL)
error("var: %d: '%s' was not declared",
tok.tok[tok.pos].nline, name);
if (v->loctype == V_LOCAL) {
emit(0x8b); emit(0x45); emit(256 - sizeof(int32_t) * v->id);
// mov eax variable
} else if (v->loctype == V_GLOBAL) {
emit(0xa1); emitI32(v->id); // mov eax GLOBAL_ADDR
}
}
}
} else if (skip("(")) {
if (isassign()) assignment(); else relExpr();
if (!skip(")")) error("%d: expected expression ')'",
tok.tok[tok.pos].nline);
}
while (isIndex()) {
emit(0x89); emit(0xc0 + EAX * 8 + ECX); // mov ecx eax
skip("[");
relExpr();
skip("]");
emit(0x8b); emit(0x04); emit(0x81); // mov eax [eax * 4 + ecx]
}
}
static void mulDivExpr()
{
int32_t mul = 0, div = 0;
primExpr();
while ((mul = skip("*")) || (div = skip("/")) || skip("%")) {
emit(0x50 + EAX); // push eax
primExpr();
emit(0x89); emit(0xc0 + EAX * 8 + EBX); // mov ebx eax
emit(0x58 + EAX); // pop eax
if (mul) {
emit(0xf7); emit(0xe8 + EBX); // mul ebx
} else if (div) {
emit(0xb8 + EDX); emitI32(0); // mov edx 0
emit(0xf7); emit(0xf8 + EBX); // div ebx
} else { /* mod */
emit(0xb8 + EDX); emitI32(0); // mov edx 0
emit(0xf7); emit(0xf8 + EBX); // div ebx
emit(0x89); emit(0xc0 + EDX * 8 + EAX); // mov eax edx
}
}
}
static void addSubExpr()
{
int32_t add;
mulDivExpr();
while ((add = skip("+")) || skip("-")) {
emit(0x50 + EAX); // push eax
mulDivExpr();
emit(0x89); emit(0xc0 + EAX * 8 + EBX); // mov ebx eax
emit(0x58 + EAX); // pop eax
if (add) {
emit(0x03); emit(EAX * 8 + 0xc0 + EBX); // add eax ebx
} else {
emit(0x2b); emit(EAX * 8 + 0xc0 + EBX); // sub eax ebx
}
}
}
static void condExpr()
{
int32_t lt = 0, gt = 0, ne = 0, eql = 0, fle = 0;
addSubExpr();
if ((lt = skip("<")) || (gt = skip(">")) || (ne = skip("!=")) ||
(eql = skip("==")) || (fle = skip("<=")) || skip(">=")) {
emit(0x50 + EAX); // push eax
addSubExpr();
emit(0x89); emit(0xc0 + EAX * 8 + EBX); // mov ebx eax
emit(0x58 + EAX); // pop eax
emit(0x39); emit(0xd8); // cmp %eax, %ebx
emit(0x0f);
emit(lt ? 0x9c /* < */ :
gt ? 0x9f /* > */ :
ne ? 0x95 /* != */ :
eql ? 0x94 /* == */ :
fle ? 0x9e /* <= */ :
0x9d /* >= */);
emit(0xc0); // setX al
emit(0x0f); emit(0xb6); emit(0xc0); // movzx eax al
}
}
void relExpr()
{
int and = 0, or = 0;
condExpr();
while ((and = skip("and") || skip("&")) ||
(or = skip("or") || skip("|")) || (skip("xor") || skip("^"))) {
emit(0x50 + EAX); // push eax
condExpr();
emit(0x89); emit(0xc0 + EAX * 8 + EBX); // mov ebx eax
emit(0x58 + EAX); // pop eax
emit(and ? 0x21 : or ? 0x09 : 0x31); emit(0xd8); // and eax ebx
}
}