@ -38,10 +38,7 @@ static uint32_t label_depth = 0;
static struct label labels [ MAX_LABELS ] ;
void init_ir ( var * argc , var * argv , var * env ) {
assert ( stack_depth = = 0 ) ;
// seems like this should be necessary. it really feels like there's some
// off-by-one arrows going on around here, but I can't figure it out.
//enter();
assert ( stack_depth = = 0 & & stack_frame = = 0 ) ;
x86_inst_mov_r64_r64 ( BP , SP ) ;
x86_inst_add_r64_imm8 ( BP , 8 * 3 ) ;
* env = stack_depth + + ;
@ -51,7 +48,8 @@ void init_ir(var* argc, var* argv, var* env) {
void enter ( void ) {
assert ( stack_frame < MAX_STACK_FRAMES ) ;
struct stack_frame frame = { stack_depth , label_depth } ;
printf ( " ENTERING: %i, %i \n " , stack_depth , label_depth ) ;
struct stack_frame frame = { . depth = stack_depth , . label_depth = label_depth } ;
stack_frames [ stack_frame ] = frame ;
stack_frame + + ;
// exit label
@ -61,15 +59,16 @@ void enter(void) {
void leave ( var * args ) {
assert ( stack_frame > 0 ) ;
struct stack_frame frame = stack_frames [ stack_frame - 1 ] ;
stack_frame - - ;
stack_depth = frame . depth ;
label_depth = frame . label_depth ;
define ( frame . label_depth , args ) ;
stack_frame - - ;
}
label declare ( uint32_t argc ) {
assert ( label_depth < MAX_LABELS ) ;
symbol sym = new_symbol ( ) ;
struct label label = { stack_frame , argc , sym } ;
struct label label = { . frame = stack_frame , . argc = argc , . symbol = sym } ;
labels [ label_depth ] = label ;
return label_depth + + ;
}
@ -82,18 +81,13 @@ label declare_exit(uint32_t argc) {
void define ( label l , var * args ) {
struct label * label = & labels [ l ] ;
printf ( " DEFINING %i (%i) \n " , l , label - > argc ) ;
define_executable_symbol ( label - > symbol ) ;
// possibly wrong. do I need to do any clean-up of the old frame here?
stack_frame = label - > frame ;
struct stack_frame * frame = & stack_frames [ stack_frame - 1 ] ;
label_depth = frame - > label_depth ;
assert ( label - > frame = = stack_frame ) ;
for ( uint32_t i = 0 ; i < label - > argc ; i + + ) {
args [ i ] = frame- > depth + i ;
args [ i ] = stack_depth + i ;
}
// probably wrong. seems like I ought to create a new frame or something?
// wouldn't this make the old frame too deep?
// but on the other hand, if I enter a new frame, how do I decide when to leave it?
frame - > depth + = label - > argc ;
stack_depth + = label - > argc ;
}
void load_var ( reg reg , var var ) {
@ -109,13 +103,11 @@ var push_var(reg reg) {
}
void load_args ( struct label * label , var * args ) {
struct stack_frame * cur_frame = & stack_frames [ stack_frame - 1 ] ;
struct stack_frame * dest_frame = & stack_frames [ label - > frame ] ;
uint32_t depth_diff = cur_frame- > depth - dest_frame - > depth ;
uint32_t depth_diff = stack_ depth - dest_frame - > depth ;
if ( depth_diff > 0 ) {
// FIXME: should be immX!!!
// FIXME: this should be necessary! stack depth is never getting decreased!
//x86_inst_add_r64_imm8(SP, depth_diff);
x86_inst_add_r64_imm8 ( SP , depth_diff ) ;
}
for ( uint32_t arg = 0 ; arg < label - > argc ; arg + + ) {
load_var ( AX , args [ arg ] ) ;
@ -125,6 +117,7 @@ void load_args(struct label* label, var* args) {
void jump ( label l , var * args ) {
struct label * label = & labels [ l ] ;
printf ( " JUMP %i (%i) \n " , l , label - > argc ) ;
load_args ( label , args ) ;
inst_jump ( label - > symbol ) ;
}
@ -135,6 +128,7 @@ void jump_table(size_t branches, label* labels, var index, var* args) {
void jump_if ( label l , var cond , var * args ) {
struct label * label = & labels [ l ] ;
printf ( " JUMP_IF %i (%i) \n " , l , label - > argc ) ;
load_var ( BX , cond ) ;
load_args ( label , args ) ;
inst_jump_if_not_zero ( label - > symbol , BX ) ;
@ -142,6 +136,7 @@ void jump_if(label l, var cond, var* args) {
void jump_unless ( label l , var cond , var * args ) {
struct label * label = & labels [ l ] ;
printf ( " JUMP_UNLESS %i (%i) \n " , l , label - > argc ) ;
load_var ( BX , cond ) ;
load_args ( label , args ) ;
inst_jump_if_zero ( label - > symbol , BX ) ;