blob: 3040e45560bfae8648ac72e5cef461a763b0d884 [file] [log] [blame]
swissChili8cfb7c42021-04-18 21:17:58 -07001/* -*- mode:c -*- */
2
swissChilica107a02021-04-14 12:07:30 -07003#include "compiler.h"
swissChilif3e7f182021-04-20 13:57:22 -07004#include "lib/std.h"
swissChili53472e82021-05-08 16:06:32 -07005#include "plat/plat.h"
swissChilica107a02021-04-14 12:07:30 -07006
7#include <dasm_proto.h>
8#include <dasm_x86.h>
9
swissChili923b5362021-05-09 20:31:43 -070010#include <stdlib.h>
11#include <string.h>
12
swissChili53472e82021-05-08 16:06:32 -070013#define value_size sizeof(value_t)
swissChilica107a02021-04-14 12:07:30 -070014
15|.arch x86;
16
17|.macro setup, nvars;
18| push ebp;
19| mov ebp, esp;
swissChili8cfb7c42021-04-18 21:17:58 -070020| sub esp, (value_size * nvars);
swissChilica107a02021-04-14 12:07:30 -070021|.endmacro;
22
23|.macro cleanup;
24| mov esp, ebp;
25| pop ebp;
26| ret;
27|.endmacro;
28
29dasm_State *d;
30unsigned int npc = 8;
31
swissChili53472e82021-05-08 16:06:32 -070032struct function *find_function(struct environment *env, char *name)
swissChilica107a02021-04-14 12:07:30 -070033{
34 struct function *f = env->first;
35
swissChili53472e82021-05-08 16:06:32 -070036 while (strcmp(f->name, name) != 0)
swissChilica107a02021-04-14 12:07:30 -070037 {
swissChili53472e82021-05-08 16:06:32 -070038 if (f->prev)
swissChilica107a02021-04-14 12:07:30 -070039 f = f->prev;
40 else
41 return NULL;
42 }
43
44 return f;
45}
46
swissChili53472e82021-05-08 16:06:32 -070047void compile_tl(value_t val, struct environment *env)
swissChilica107a02021-04-14 12:07:30 -070048{
swissChili53472e82021-05-08 16:06:32 -070049 if (!listp(val))
50 err("Top level must be a list");
swissChilica107a02021-04-14 12:07:30 -070051
swissChili53472e82021-05-08 16:06:32 -070052 value_t form = car(val);
53 value_t args = cdr(val);
54
55 if (symstreq(form, "defun"))
swissChili8fc5e2f2021-04-22 13:45:10 -070056 {
57 dasm_State *d;
58 dasm_State **Dst = &d;
swissChilica107a02021-04-14 12:07:30 -070059
swissChili8fc5e2f2021-04-22 13:45:10 -070060 |.section code;
swissChili53472e82021-05-08 16:06:32 -070061 dasm_init(&d, DASM_MAXSECTION);
62
swissChili8fc5e2f2021-04-22 13:45:10 -070063 |.globals lbl_;
swissChili53472e82021-05-08 16:06:32 -070064 void *labels[lbl__MAX];
65 dasm_setupglobal(&d, labels, lbl__MAX);
66
swissChili8fc5e2f2021-04-22 13:45:10 -070067 |.actionlist lisp_actions;
swissChili53472e82021-05-08 16:06:32 -070068 dasm_setup(&d, lisp_actions);
69
swissChili8fc5e2f2021-04-22 13:45:10 -070070 struct local local;
71 local.first = NULL;
72 local.num_vars = 0;
swissChilia820dea2021-05-09 16:46:55 -070073 local.npc = 8;
74 local.nextpc = 0;
75
76 dasm_growpc(&d, local.npc);
swissChili53472e82021-05-08 16:06:32 -070077
swissChili8fc5e2f2021-04-22 13:45:10 -070078 // Generate code
swissChili923b5362021-05-09 20:31:43 -070079 // TODO: first pass, extract bound and free variables
swissChili53472e82021-05-08 16:06:32 -070080
swissChili8fc5e2f2021-04-22 13:45:10 -070081 | setup 0;
swissChilif3e7f182021-04-20 13:57:22 -070082
swissChili53472e82021-05-08 16:06:32 -070083 value_t name = car(args);
84 args = cdr(args);
85 value_t arglist = car(args);
86 value_t body = cdr(args);
swissChili8fc5e2f2021-04-22 13:45:10 -070087
swissChili53472e82021-05-08 16:06:32 -070088 if ((name & HEAP_MASK) != SYMBOL_TAG)
89 err("function name must be a symbol");
90
swissChili923b5362021-05-09 20:31:43 -070091 value_t a = arglist;
92 for (int i = 0; !nilp(a); a = cdr(a), i++)
93 {
94 if (!symbolp(car(a)))
95 {
96 err("defun argument must be a symbol");
97 }
98
99 add_variable(&local, V_ARGUMENT, (char *)(car(a) ^ SYMBOL_TAG), i);
100 }
101
swissChili53472e82021-05-08 16:06:32 -0700102 for (; !nilp(body); body = cdr(body))
swissChili8fc5e2f2021-04-22 13:45:10 -0700103 {
swissChili53472e82021-05-08 16:06:32 -0700104 compile_expression(env, &local, car(body), Dst);
swissChili8fc5e2f2021-04-22 13:45:10 -0700105 }
106
107 | cleanup;
108
swissChili53472e82021-05-08 16:06:32 -0700109 add_function(env, (char *)(name ^ SYMBOL_TAG), link(Dst),
110 length(arglist));
swissChili8fc5e2f2021-04-22 13:45:10 -0700111
swissChili53472e82021-05-08 16:06:32 -0700112 dasm_free(&d);
swissChili8fc5e2f2021-04-22 13:45:10 -0700113 }
114}
115
swissChili53472e82021-05-08 16:06:32 -0700116struct environment compile_all(struct istream *is)
swissChili8fc5e2f2021-04-22 13:45:10 -0700117{
118 value_t val;
swissChilif3e7f182021-04-20 13:57:22 -0700119 struct environment env;
120 env.first = NULL;
swissChili53472e82021-05-08 16:06:32 -0700121 load_std(&env);
122
123 while (read1(is, &val))
swissChili8fc5e2f2021-04-22 13:45:10 -0700124 {
swissChili53472e82021-05-08 16:06:32 -0700125 compile_tl(val, &env);
swissChili8fc5e2f2021-04-22 13:45:10 -0700126 }
swissChilif3e7f182021-04-20 13:57:22 -0700127
swissChili8fc5e2f2021-04-22 13:45:10 -0700128 return env;
swissChilica107a02021-04-14 12:07:30 -0700129}
swissChilib3ca4fb2021-04-20 10:33:00 -0700130
swissChili53472e82021-05-08 16:06:32 -0700131int nextpc(struct local *local, dasm_State **Dst)
swissChilib3ca4fb2021-04-20 10:33:00 -0700132{
swissChili53472e82021-05-08 16:06:32 -0700133 int n = local->nextpc++;
134 if (n > local->npc)
135 {
136 local->npc += 16;
137 dasm_growpc(Dst, local->npc);
138 }
139 return n;
140}
141
142void compile_expression(struct environment *env, struct local *local,
143 value_t val, dasm_State **Dst)
144{
145 if (symstreq(val, "nil"))
146 {
147 | mov eax, (nil);
148 }
swissChili923b5362021-05-09 20:31:43 -0700149 else if (symstreq(val, "t"))
150 {
151 | mov eax, (t);
152 }
153 else if (integerp(val) || stringp(val))
swissChilib3ca4fb2021-04-20 10:33:00 -0700154 {
155 | mov eax, val;
156 }
swissChili53472e82021-05-08 16:06:32 -0700157 else if (listp(val))
swissChilib3ca4fb2021-04-20 10:33:00 -0700158 {
swissChili53472e82021-05-08 16:06:32 -0700159 value_t fsym = car(val);
160 value_t args = cdr(val);
161 int nargs = length(args);
swissChilib3ca4fb2021-04-20 10:33:00 -0700162
swissChili53472e82021-05-08 16:06:32 -0700163 if (!symbolp(fsym))
swissChilif3e7f182021-04-20 13:57:22 -0700164 {
swissChili53472e82021-05-08 16:06:32 -0700165 err("function name must be a symbol");
swissChilif3e7f182021-04-20 13:57:22 -0700166 }
167
swissChili53472e82021-05-08 16:06:32 -0700168 if (symstreq(fsym, "if"))
swissChilib3ca4fb2021-04-20 10:33:00 -0700169 {
swissChili53472e82021-05-08 16:06:32 -0700170 if (nargs < 2 || nargs > 3)
171 err("Must give at least 2 arguments to if");
swissChilib3ca4fb2021-04-20 10:33:00 -0700172
swissChili53472e82021-05-08 16:06:32 -0700173 compile_expression(env, local, car(args), Dst);
174 int false_label = nextpc(local, Dst),
175 after_label = nextpc(local, Dst);
176
177 // result is in eax
178 | cmp eax, (nil);
179 | je =>false_label;
180
181 compile_expression(env, local, elt(args, 1), Dst);
swissChilia820dea2021-05-09 16:46:55 -0700182 | jmp =>after_label;
swissChili923b5362021-05-09 20:31:43 -0700183 |=>false_label:;
swissChili53472e82021-05-08 16:06:32 -0700184 if (nargs == 3)
185 compile_expression(env, local, elt(args, 2), Dst);
186 |=>after_label:
187 }
188 else
189 {
190 struct function *func =
191 find_function(env, (char *)(fsym ^ SYMBOL_TAG));
192
swissChili923b5362021-05-09 20:31:43 -0700193 if (func == NULL)
194 err("Function undefined");
195
swissChili53472e82021-05-08 16:06:32 -0700196 if (nargs != func->nargs)
197 err("wrong number of args");
198
199 for (int i = length(args) - 1; i >= 0; i--)
200 {
201 compile_expression(env, local, elt(args, i), Dst);
202 | push eax;
203 }
204
205 | mov ebx, (func->code_addr);
206 | call ebx;
swissChili923b5362021-05-09 20:31:43 -0700207 | add esp, (nargs * value_size);
swissChili53472e82021-05-08 16:06:32 -0700208 // result in eax
209 }
swissChilib3ca4fb2021-04-20 10:33:00 -0700210 }
swissChili923b5362021-05-09 20:31:43 -0700211 else if (symbolp(val))
212 {
213 // For now ignore global variables, only search locally
214 struct variable *v = find_variable(local, (char *)(val ^ SYMBOL_TAG));
215
216 if (!v)
217 err("Variable unbound");
218
219 switch (v->type)
220 {
221 case V_ARGUMENT:
222 | mov eax, dword [ebp + value_size * (v->number + 2)];
223 break;
224 default:
225 err("Sorry, can only access V_ARGUMENT variables for now :(");
226 }
227 }
swissChilib3ca4fb2021-04-20 10:33:00 -0700228}
swissChilif3e7f182021-04-20 13:57:22 -0700229
swissChili53472e82021-05-08 16:06:32 -0700230void compile_expr_to_func(struct environment *env, char *name, value_t val,
231 dasm_State **Dst)
swissChilif3e7f182021-04-20 13:57:22 -0700232{
233 | setup 0;
234
235 struct local local;
swissChili53472e82021-05-08 16:06:32 -0700236 compile_expression(env, &local, val, Dst);
237
swissChilif3e7f182021-04-20 13:57:22 -0700238 | cleanup;
239
swissChili53472e82021-05-08 16:06:32 -0700240 add_function(env, name, link(Dst), 0);
swissChilif3e7f182021-04-20 13:57:22 -0700241}
swissChili923b5362021-05-09 20:31:43 -0700242
243struct variable *add_variable(struct local *local, enum var_type type,
244 char *name, int number)
245{
246 struct variable *var = malloc(sizeof(struct variable));
247 var->prev = local->first;
248 var->type = type;
249 var->name = name;
250 var->number = number;
251
252 local->first = var;
253
254 return var;
255}
256
257void destroy_local(struct local *local)
258{
259 for (struct variable *v = local->first; v;)
260 {
261 struct variable *t = v;
262 v = v->prev;
263 free(t);
264 }
265}
266
267struct variable *find_variable(struct local *local, char *name)
268{
269 struct variable *v = local->first;
270
271 for (; v && strcmp(v->name, name) != 0; v = v->prev)
272 {}
273
274 return v;
275}