Skip to content

Commit 55a8648

Browse files
committed
Some things work, many things don't
1 parent 4cf518f commit 55a8648

File tree

6 files changed

+147
-37
lines changed

6 files changed

+147
-37
lines changed

backend.c

+51-21
Original file line numberDiff line numberDiff line change
@@ -105,16 +105,16 @@ static void init_code_buf(void) {
105105
size_t len = 8 * 1024 * 1024;
106106
code_buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
107107
if (!code_buf)
108-
failwith("Couldn't allocate buffer for code");
108+
failwith("Couldn't allocate buffer for code\n");
109109
code_buf_start = code_buf;
110110
code_buf_end = code_buf_start + len;
111111
}
112112

113113
void compile_finalize(void) {
114114
// mprotect it
115115
size_t len = code_buf_end - code_buf_start;
116-
if (!mprotect(code_buf_start, len, PROT_READ | PROT_EXEC))
117-
failwith("Couldn't map as executable: %s", strerror(errno));
116+
if (mprotect(code_buf_start, len, PROT_READ | PROT_EXEC))
117+
failwith("Couldn't map as executable: %s\n", strerror(errno));
118118
}
119119

120120
static void write_code(size_t len, const uint8_t code[len]) {
@@ -197,11 +197,13 @@ static void store_arg(size_t idx, enum reg reg) {
197197
}
198198

199199
static void blackhole_self(void) {
200-
// movabs rsi, rt_blackhole_entry
201-
CODE(0x48, 0xbf, U64((uint64_t) rt_blackhole_entry));
202-
STORE(RSI, SELF, 0);
203-
CODE(0xbe, U32(2)); // mov esi, 2
204-
STORE(RSI, SELF, 8);
200+
// Use rax as a temporary register since it's possible that both rsi and rdi
201+
// are in use
202+
// movabs rax, rt_blackhole_entry
203+
CODE(0x48, 0xb8, U64((uint64_t) rt_blackhole_entry));
204+
STORE(RAX, SELF, 0);
205+
CODE(0xb8, U32(2)); // mov esi, 2
206+
STORE(RAX, SELF, 8);
205207
}
206208

207209

@@ -224,15 +226,16 @@ static void write_header(uint32_t size, uint32_t tag) {
224226
}
225227

226228
static void *start_closure(size_t argc, size_t envc) {
227-
assert(argc < INT_MAX);
229+
/* assert(argc < INT_MAX); */
230+
assert(argc < 127); // TODO: allow more args (? maybe)
228231
assert(envc < INT_MAX);
229232

230233
write_header(envc == 0 ? 0 : envc + 1, FUN);
231234
void *code_start = code_buf;
232235

233236
CODE(
234-
// cmp %r15, argc
235-
0x4c, 0x39, 0x3c, 0x25, U32(argc),
237+
// cmp r15, argc
238+
0x49, 0x83, 0xff, (uint8_t) argc,
236239
// jge rest_of_code (+12)
237240
0x7d, 12,
238241
// movabs rt_too_few_args, %rdi
@@ -312,14 +315,17 @@ static void heap_check(size_t bytes_allocated) {
312315
static void load_var(size_t lvl, struct env *this_env, enum reg dest, var v) {
313316
assert(v < lvl);
314317
if (v >= this_env->args_start) {
315-
load_arg(dest, lvl - v);
318+
load_arg(dest, lvl - v - 1);
316319
} else {
317320
assert(this_env->upvals[v].is_used);
318321
load_env_item(dest, SELF, this_env->upvals[v].env_idx);
319322
}
320323
}
321324

322325
static void do_allocations(size_t lvl, struct env *this_env, size_t n, struct compile_result locals[n]) {
326+
if (n == 0)
327+
return;
328+
323329
size_t words_allocated = 0;
324330
for (size_t i = 0; i < n; i++) {
325331
if (locals[i].env->envc == 0)
@@ -392,11 +398,15 @@ typedef struct {
392398

393399
// Store src to all its destinations, so that it can be overwritten afterwards.
394400
static void vacate_one(mov_state *s, int src) {
401+
printf("Vacating %d\n"); // FIXME
402+
395403
switch (s->dest_info[src].status) {
396404
case DONE:
405+
printf("It was done\n"); // FIXME
397406
break;
398407

399408
case IN_PROGRESS:
409+
printf("A Cycle!\n"); // FIXME
400410
// A cycle! Use rdi as a temporary register to break the cycle
401411
assert(s->in_rdi == -1);
402412
s->in_rdi = src;
@@ -407,6 +417,14 @@ static void vacate_one(mov_state *s, int src) {
407417
break;
408418

409419
case NOT_STARTED:
420+
printf("Not started\n"); // FIXME
421+
if (s->src_to_dest[src] == -1) {
422+
printf("Didn't do anything\n"); // FIXME
423+
// Don't do anything if it has no destinations
424+
s->dest_info[src].status = DONE;
425+
break;
426+
}
427+
410428
# define FOREACH_DEST(dest) \
411429
for (int dest = s->src_to_dest[src]; dest != -1; dest = s->dest_info[dest].next_with_same_src)
412430

@@ -421,9 +439,9 @@ static void vacate_one(mov_state *s, int src) {
421439
enum reg self = s->in_rdi == s->n ? RDI : SELF;
422440
if (dest == s->n) {
423441
if (s->for_a_thunk) {
424-
load_env_item(RDI, self, s->dest_info[dest].src_idx);
442+
load_env_item(RSI, self, s->dest_info[dest].src_idx);
425443
blackhole_self();
426-
MOV_RR(SELF, RDI);
444+
MOV_RR(SELF, RSI);
427445
} else {
428446
load_env_item(SELF, self, s->dest_info[dest].src_idx);
429447
}
@@ -437,7 +455,7 @@ static void vacate_one(mov_state *s, int src) {
437455
FOREACH_DEST(dest) {
438456
assert(s->dest_info[dest].src_type == FROM_ARGS);
439457
assert(s->dest_info[dest].src_idx == src);
440-
vacate_one(s, src);
458+
vacate_one(s, dest);
441459
}
442460
enum reg src_reg;
443461
if (s->in_rdi == src) {
@@ -459,6 +477,7 @@ static void vacate_one(mov_state *s, int src) {
459477
if (s->in_rdi == src)
460478
s->in_rdi = -1;
461479
s->dest_info[src].status = DONE;
480+
printf("Done with %d!\n", src); // FIXME
462481
# undef FOREACH_DEST
463482
break;
464483
}
@@ -468,7 +487,7 @@ static void add_dest_to_mov_state(size_t lvl, struct env *env, mov_state *s, int
468487
assert(v <= lvl);
469488
if (v >= env->args_start) {
470489
// It's from the data stack
471-
int src = lvl - v;
490+
int src = lvl - v - 1;
472491
s->dest_info[dest] = (struct dest_info_item) {
473492
.src_type = FROM_ARGS,
474493
.src_idx = src,
@@ -491,13 +510,18 @@ static void add_dest_to_mov_state(size_t lvl, struct env *env, mov_state *s, int
491510
}
492511

493512
static void do_the_moves(size_t lvl, ir term, struct env *env) {
513+
//FIXME
514+
printf("Moving for ");
515+
print_ir(term);
516+
494517
assert(lvl == term->lvl + term->arity + term->lets_len);
495518
assert(term->lvl == env->args_start);
496519

497520
size_t incoming_argc = term->arity + term->lets_len;
498521
size_t outgoing_argc = 0;
499522
for (arglist arg = term->args; arg; arg = arg->prev)
500523
++outgoing_argc;
524+
printf("Outgoing argc is %d, incoming %d\n", outgoing_argc, incoming_argc);
501525

502526

503527
// Resize the data stack
@@ -524,15 +548,21 @@ static void do_the_moves(size_t lvl, ir term, struct env *env) {
524548
for (int i = 0; i < n + 1; i++)
525549
s.src_to_dest[i] = -1;
526550

551+
int dest_start =
552+
outgoing_argc < incoming_argc ? incoming_argc - outgoing_argc : 0;
527553
int dest = 0;
554+
for (; dest < dest_start; dest++)
555+
s.dest_info[dest].status = NOT_STARTED;
528556
for (arglist arg = term->args; arg; dest++, arg = arg->prev)
529557
add_dest_to_mov_state(lvl, env, &s, dest, arg->arg);
530-
assert(dest == outgoing_argc);
531-
for (; dest < n; dest++) {
532-
s.dest_info[dest].status = NOT_STARTED;
533-
}
558+
assert(dest == n);
534559
add_dest_to_mov_state(lvl, env, &s, n, term->head);
535560

561+
// FIXME
562+
for (int i = 0; i < n + 1; i++)
563+
printf("%d->%d ", i, s.src_to_dest[i]);
564+
printf("\n");
565+
536566
// Do all the moving
537567
for (int i = 0; i < n + 1; i++) {
538568
vacate_one(&s, i);
@@ -632,7 +662,7 @@ void *compile_toplevel(ir term) {
632662
// - [X] Fix the thunk entry code
633663
// - [X] Implement parallel move for shuffling args
634664
// - [X] Tie it all together in a big compile function
635-
// - [ ] *Really* tie everything together with a main function!
665+
// - [X] *Really* tie everything together with a main function!
636666
// - [ ] Fix all the (I'm sure many) mistakes
637667
//
638668

frontend.c

+59-4
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,20 @@ static ir mkvar(size_t lvl, var v);
2222
static ir mkapp(size_t lvl, ir func, ir arg);
2323
static ir mkabs(size_t lvl, ir body);
2424

25+
static size_t *ir_arena_start = NULL;
2526
static size_t *ir_arena = NULL;
2627
static size_t *ir_arena_end = NULL;
2728
#define IR_ARENA_SIZE (32 * 1024 * 1024)
2829

2930
static void arena_init(void) {
3031
if (!ir_arena) {
31-
ir_arena = (size_t *) malloc(IR_ARENA_SIZE);
32+
ir_arena_start = ir_arena = malloc(IR_ARENA_SIZE);
3233
ir_arena_end = ir_arena + IR_ARENA_SIZE / sizeof(*ir_arena);
3334
}
3435
}
3536

3637
void free_ir(void) {
37-
free(ir_arena);
38+
free(ir_arena_start);
3839
ir_arena = ir_arena_end = NULL;
3940
}
4041

@@ -65,7 +66,8 @@ static bool is_lambda(ir e) {
6566
}
6667

6768
static ir mkabs(size_t lvl, ir body) {
68-
(void) lvl;
69+
assert(body->lvl == lvl + 1);
70+
body->lvl = lvl;
6971
body->arity++;
7072
return body;
7173
}
@@ -264,7 +266,7 @@ static ir parse_exp(const char **cursor, size_t lvl, scope s) {
264266
++*cursor;
265267
SKIP_WHITESPACE(cursor);
266268
return parse_rest_of_lambda(cursor, lvl, s);
267-
} else if (strncmp(*cursor, "λ", sizeof("λ")) == 0) {
269+
} else if (strncmp(*cursor, "λ", sizeof("λ") - 1) == 0) {
268270
*cursor += sizeof("λ") - 1;
269271
SKIP_WHITESPACE(cursor);
270272
return parse_rest_of_lambda(cursor, lvl, s);
@@ -281,3 +283,56 @@ static ir parse_exp(const char **cursor, size_t lvl, scope s) {
281283
}
282284
}
283285

286+
/*************** Pretty-printer **************/
287+
288+
static void print_var(var v);
289+
static void print_lets(size_t lvl, letlist lets);
290+
static void print_args(arglist args);
291+
static void print_term(ir term);
292+
293+
static void print_var(var v) {
294+
printf("x_%lu", v);
295+
}
296+
static void print_lets(size_t lvl, letlist lets) {
297+
for (; lets; lets = lets->next, lvl++) {
298+
printf("let ");
299+
print_var(lvl);
300+
printf(" = ");
301+
print_term(lets->val);
302+
printf(" in ");
303+
}
304+
}
305+
static void print_args(arglist args) {
306+
if (args) {
307+
print_args(args->prev);
308+
printf(" ");
309+
print_var(args->arg);
310+
}
311+
}
312+
static void print_term(ir term) {
313+
if (!term->arity && !term->lets && !term->args) {
314+
// Just a var -- no parens necessary
315+
print_var(term->head);
316+
return;
317+
}
318+
printf("(");
319+
if (term->arity) {
320+
printf("λ");
321+
for (var v = term->lvl; v < term->lvl + term->arity; v++) {
322+
printf(" ");
323+
print_var(v);
324+
}
325+
printf(". ");
326+
}
327+
print_lets(term->lvl + term->arity, term->lets);
328+
print_var(term->head);
329+
print_args(term->args);
330+
printf(")");
331+
}
332+
333+
void print_ir(ir term) {
334+
print_term(term);
335+
printf("\n");
336+
}
337+
338+

frontend.h

+4
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,8 @@ ir parse(const char *text);
3939
*/
4040
void free_ir(void);
4141

42+
/** For debugging purposes
43+
*/
44+
void print_ir(ir term);
45+
4246
#endif // FRONTEND_H

main.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@
66
#include "runtime/normalize.h"
77

88
int main(int argc, const char **argv) {
9-
const char *source = "λ x. x";
9+
const char *source = argc >= 2 ? argv[1] : "λ x. x";
1010

1111
printf("Parsing %s\n", source);
1212
ir term = parse(source);
1313

14+
printf("Parsed: ");
15+
print_ir(term);
16+
1417
printf("Compiling\n");
1518
void *code = compile_toplevel(term);
1619

runtime/builtins.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ void rt_rigid_entry_impl(void) {
8686

8787
obj *new = alloc(rt_rigid_entry, new_size);
8888
*INFO_WORD(new) = (struct info_word) {
89-
.size = INFO_WORD(self)->size,
89+
.size = new_size,
9090
.var = INFO_WORD(self)->var,
9191
};
9292

0 commit comments

Comments
 (0)