@@ -105,16 +105,16 @@ static void init_code_buf(void) {
105
105
size_t len = 8 * 1024 * 1024 ;
106
106
code_buf = mmap (NULL , len , PROT_READ | PROT_WRITE , MAP_PRIVATE | MAP_ANONYMOUS , -1 , 0 );
107
107
if (!code_buf )
108
- failwith ("Couldn't allocate buffer for code" );
108
+ failwith ("Couldn't allocate buffer for code\n " );
109
109
code_buf_start = code_buf ;
110
110
code_buf_end = code_buf_start + len ;
111
111
}
112
112
113
113
void compile_finalize (void ) {
114
114
// mprotect it
115
115
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 ));
118
118
}
119
119
120
120
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) {
197
197
}
198
198
199
199
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 );
205
207
}
206
208
207
209
@@ -224,15 +226,16 @@ static void write_header(uint32_t size, uint32_t tag) {
224
226
}
225
227
226
228
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)
228
231
assert (envc < INT_MAX );
229
232
230
233
write_header (envc == 0 ? 0 : envc + 1 , FUN );
231
234
void * code_start = code_buf ;
232
235
233
236
CODE (
234
- // cmp % r15, argc
235
- 0x4c , 0x39 , 0x3c , 0x25 , U32 ( argc ) ,
237
+ // cmp r15, argc
238
+ 0x49 , 0x83 , 0xff , ( uint8_t ) argc ,
236
239
// jge rest_of_code (+12)
237
240
0x7d , 12 ,
238
241
// movabs rt_too_few_args, %rdi
@@ -312,14 +315,17 @@ static void heap_check(size_t bytes_allocated) {
312
315
static void load_var (size_t lvl , struct env * this_env , enum reg dest , var v ) {
313
316
assert (v < lvl );
314
317
if (v >= this_env -> args_start ) {
315
- load_arg (dest , lvl - v );
318
+ load_arg (dest , lvl - v - 1 );
316
319
} else {
317
320
assert (this_env -> upvals [v ].is_used );
318
321
load_env_item (dest , SELF , this_env -> upvals [v ].env_idx );
319
322
}
320
323
}
321
324
322
325
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
+
323
329
size_t words_allocated = 0 ;
324
330
for (size_t i = 0 ; i < n ; i ++ ) {
325
331
if (locals [i ].env -> envc == 0 )
@@ -392,11 +398,15 @@ typedef struct {
392
398
393
399
// Store src to all its destinations, so that it can be overwritten afterwards.
394
400
static void vacate_one (mov_state * s , int src ) {
401
+ printf ("Vacating %d\n" ); // FIXME
402
+
395
403
switch (s -> dest_info [src ].status ) {
396
404
case DONE :
405
+ printf ("It was done\n" ); // FIXME
397
406
break ;
398
407
399
408
case IN_PROGRESS :
409
+ printf ("A Cycle!\n" ); // FIXME
400
410
// A cycle! Use rdi as a temporary register to break the cycle
401
411
assert (s -> in_rdi == -1 );
402
412
s -> in_rdi = src ;
@@ -407,6 +417,14 @@ static void vacate_one(mov_state *s, int src) {
407
417
break ;
408
418
409
419
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
+
410
428
# define FOREACH_DEST (dest ) \
411
429
for (int dest = s->src_to_dest[src]; dest != -1; dest = s->dest_info[dest].next_with_same_src)
412
430
@@ -421,9 +439,9 @@ static void vacate_one(mov_state *s, int src) {
421
439
enum reg self = s -> in_rdi == s -> n ? RDI : SELF ;
422
440
if (dest == s -> n ) {
423
441
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 );
425
443
blackhole_self ();
426
- MOV_RR (SELF , RDI );
444
+ MOV_RR (SELF , RSI );
427
445
} else {
428
446
load_env_item (SELF , self , s -> dest_info [dest ].src_idx );
429
447
}
@@ -437,7 +455,7 @@ static void vacate_one(mov_state *s, int src) {
437
455
FOREACH_DEST (dest ) {
438
456
assert (s -> dest_info [dest ].src_type == FROM_ARGS );
439
457
assert (s -> dest_info [dest ].src_idx == src );
440
- vacate_one (s , src );
458
+ vacate_one (s , dest );
441
459
}
442
460
enum reg src_reg ;
443
461
if (s -> in_rdi == src ) {
@@ -459,6 +477,7 @@ static void vacate_one(mov_state *s, int src) {
459
477
if (s -> in_rdi == src )
460
478
s -> in_rdi = -1 ;
461
479
s -> dest_info [src ].status = DONE ;
480
+ printf ("Done with %d!\n" , src ); // FIXME
462
481
# undef FOREACH_DEST
463
482
break ;
464
483
}
@@ -468,7 +487,7 @@ static void add_dest_to_mov_state(size_t lvl, struct env *env, mov_state *s, int
468
487
assert (v <= lvl );
469
488
if (v >= env -> args_start ) {
470
489
// It's from the data stack
471
- int src = lvl - v ;
490
+ int src = lvl - v - 1 ;
472
491
s -> dest_info [dest ] = (struct dest_info_item ) {
473
492
.src_type = FROM_ARGS ,
474
493
.src_idx = src ,
@@ -491,13 +510,18 @@ static void add_dest_to_mov_state(size_t lvl, struct env *env, mov_state *s, int
491
510
}
492
511
493
512
static void do_the_moves (size_t lvl , ir term , struct env * env ) {
513
+ //FIXME
514
+ printf ("Moving for " );
515
+ print_ir (term );
516
+
494
517
assert (lvl == term -> lvl + term -> arity + term -> lets_len );
495
518
assert (term -> lvl == env -> args_start );
496
519
497
520
size_t incoming_argc = term -> arity + term -> lets_len ;
498
521
size_t outgoing_argc = 0 ;
499
522
for (arglist arg = term -> args ; arg ; arg = arg -> prev )
500
523
++ outgoing_argc ;
524
+ printf ("Outgoing argc is %d, incoming %d\n" , outgoing_argc , incoming_argc );
501
525
502
526
503
527
// Resize the data stack
@@ -524,15 +548,21 @@ static void do_the_moves(size_t lvl, ir term, struct env *env) {
524
548
for (int i = 0 ; i < n + 1 ; i ++ )
525
549
s .src_to_dest [i ] = -1 ;
526
550
551
+ int dest_start =
552
+ outgoing_argc < incoming_argc ? incoming_argc - outgoing_argc : 0 ;
527
553
int dest = 0 ;
554
+ for (; dest < dest_start ; dest ++ )
555
+ s .dest_info [dest ].status = NOT_STARTED ;
528
556
for (arglist arg = term -> args ; arg ; dest ++ , arg = arg -> prev )
529
557
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 );
534
559
add_dest_to_mov_state (lvl , env , & s , n , term -> head );
535
560
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
+
536
566
// Do all the moving
537
567
for (int i = 0 ; i < n + 1 ; i ++ ) {
538
568
vacate_one (& s , i );
@@ -632,7 +662,7 @@ void *compile_toplevel(ir term) {
632
662
// - [X] Fix the thunk entry code
633
663
// - [X] Implement parallel move for shuffling args
634
664
// - [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!
636
666
// - [ ] Fix all the (I'm sure many) mistakes
637
667
//
638
668
0 commit comments