@ -34,13 +34,15 @@ struct label {
static uint32_t stack_depth = 0 ;
static uint32_t stack_frame = 0 ;
static struct stack_frame stack_frames [ MAX_STACK_FRAMES ] ;
static uint32_t label_depth ;
static uint32_t label_depth = 0 ;
static struct label labels [ MAX_LABELS ] ;
void init ( var * argc , var * argv , var * env ) {
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();
x86_inst_mov_r64_r64 ( BP , SP ) ;
// TODO: replace with add, once I implement add
x86_inst_add_r64_imm8 ( BP , 8 * 3 ) ;
* env = stack_depth + + ;
* argv = stack_depth + + ;
@ -58,10 +60,10 @@ void enter(void) {
void leave ( var * args ) {
assert ( stack_frame > 0 ) ;
struct stack_frame frame = stack_frames [ stack_frame ] ;
define ( frame . label_depth , args ) ;
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 ) ;
}
label declare ( uint32_t argc ) {
@ -73,7 +75,7 @@ label declare(uint32_t argc) {
}
label declare_exit ( uint32_t argc ) {
label label = stack_frames [ stack_frame ] . label_depth ;
label label = stack_frames [ stack_frame - 1 ] . label_depth ;
labels [ label ] . argc = argc ;
return label ;
}
@ -81,10 +83,49 @@ label declare_exit(uint32_t argc) {
void define ( label l , var * args ) {
struct label * label = & labels [ l ] ;
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 ;
for ( uint32_t i = 0 ; i < label - > argc ; i + + ) {
args [ i ] = frame - > 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 ;
}
void load_var ( reg reg , var var ) {
// the stack grows downward, so the bottom of the stack, BP, points to nothing;
// subtracting 8 causes it to point to the first variable, 0.
// (each variable is 8 bytes.)
x86_inst_mov_r64_m64_disp ( reg , BP , - ( var * 8 ) - 8 ) ;
}
var push_var ( reg reg ) {
x86_inst_push_r64 ( reg ) ;
return stack_depth + + ;
}
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 ;
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);
}
for ( uint32_t arg = 0 ; arg < label - > argc ; arg + + ) {
load_var ( AX , args [ arg ] ) ;
x86_inst_push_r64 ( AX ) ;
}
}
void jump ( label l , var * args ) {
struct label * label = & labels [ l ] ;
load_args ( label , args ) ;
inst_jump ( label - > symbol ) ;
}
@ -92,20 +133,18 @@ void jump_table(size_t branches, label* labels, var index, var* args) {
assert ( 0 ) ; // UNIMPLEMENTED
}
void jump_if ( label label , var cond , var * args ) {
//assert(0); // UNIMPLEMENTED
}
void load_var ( reg reg , var var ) {
// the stack grows downward, so the bottom of the stack, BP, points to nothing;
// subtracting 8 causes it to point to the first variable, 0.
// (each variable is 8 bytes.)
x86_inst_mov_r64_m64_disp ( reg , BP , - ( var * 8 ) - 8 ) ;
void jump_if ( label l , var cond , var * args ) {
struct label * label = & labels [ l ] ;
load_var ( BX , cond ) ;
load_args ( label , args ) ;
inst_jump_if_not_zero ( label - > symbol , BX ) ;
}
var push_var ( reg reg ) {
x86_inst_push_r64 ( reg ) ;
return stack_depth + + ;
void jump_unless ( label l , var cond , var * args ) {
struct label * label = & labels [ l ] ;
load_var ( BX , cond ) ;
load_args ( label , args ) ;
inst_jump_if_zero ( label - > symbol , BX ) ;
}
var lit ( uint64_t lit ) {