NODE(sl_node_def_t, def) { sl_vm_insn_t insn; sl_compile_state_t sub_cs; size_t i, on_reg; init_compile_state(&sub_cs, cs->vm, cs, node->req_arg_count + node->opt_arg_count + 1); for(i = 0; i < node->req_arg_count; i++) { st_insert(sub_cs.vars, (st_data_t)node->req_args[i], (st_data_t)(i + 1)); } for(i = 0; i < node->opt_arg_count; i++) { st_insert(sub_cs.vars, (st_data_t)node->opt_args[i].name, (st_data_t)(node->req_arg_count + i + 1)); } sub_cs.section->name = node->name; sub_cs.section->req_registers = node->req_arg_count; sub_cs.section->arg_registers = node->req_arg_count + node->opt_arg_count; sub_cs.section->opt_skip = sl_alloc(cs->vm->arena, sizeof(size_t) * (node->opt_arg_count + 1)); for(i = 0; i < node->opt_arg_count; i++) { sub_cs.section->opt_skip[i] = sub_cs.section->insns_count; compile_node(&sub_cs, node->opt_args[i].default_value, node->req_arg_count + i + 1); } sub_cs.section->opt_skip[node->opt_arg_count] = sub_cs.section->insns_count; compile_node(&sub_cs, node->body, 0); insn.opcode = SL_OP_RETURN; emit(&sub_cs, insn); insn.uint = 0; emit(&sub_cs, insn); if(node->on) { on_reg = reg_alloc(cs); compile_node(cs, node->on, on_reg); insn.opcode = SL_OP_DEFINE_ON; emit(cs, insn); insn.uint = on_reg; emit(cs, insn); reg_free(cs, on_reg); } else { insn.opcode = SL_OP_DEFINE; emit(cs, insn); } insn.imm = node->name; emit(cs, insn); insn.section = sub_cs.section; emit(cs, insn); insn.uint = dest; emit(cs, insn); }
static void emit_assignment(sl_compile_state_t* cs, sl_node_base_t* lval, size_t reg) { sl_node_assign_var_t a_var; sl_node_send_t send; size_t dest_reg = reg_alloc(cs); sl_node__register_t node; node.base.type = SL_NODE__REGISTER; node.base.line = 0; node.reg = reg; switch(lval->type) { case SL_NODE_VAR: a_var.base.type = SL_NODE_ASSIGN_VAR; break; case SL_NODE_IVAR: a_var.base.type = SL_NODE_ASSIGN_IVAR; break; case SL_NODE_CVAR: a_var.base.type = SL_NODE_ASSIGN_CVAR; break; case SL_NODE_CONST: a_var.base.type = SL_NODE_ASSIGN_CONST; break; case SL_NODE_ARRAY: a_var.base.type = SL_NODE_ASSIGN_ARRAY; break; case SL_NODE_SEND: /* special case that turns a.b = 1 into a.send("b=", 1) */ /* this is separate to the other method of handling send assignments which also handles compound assignments. */ memcpy(&send, lval, sizeof(sl_node_send_t)); send.id = sl_id_make_setter(cs->vm, send.id); sl_node_base_t** args = sl_alloc(cs->vm->arena, sizeof(sl_node_base_t*) * (send.arg_count + 1)); memcpy(args, send.args, sizeof(sl_node_base_t*) * send.arg_count); args[send.arg_count++] = (sl_node_base_t*)&node; send.args = args; compile_node(cs, (sl_node_base_t*)&send, dest_reg); reg_free(cs, dest_reg); return; default: { SLVAL err = sl_make_cstring(cs->vm, "Invalid lval in assignment"); err = sl_make_error2(cs->vm, cs->vm->lib.SyntaxError, err); sl_error_add_frame(cs->vm, err, sl_make_cstring(cs->vm, "<compiler>"), sl_make_cstring(cs->vm, (char*)cs->section->filename), sl_make_int(cs->vm, lval->line)); sl_throw(cs->vm, err); } } a_var.base.line = 0; a_var.lval = (void*)lval; a_var.rval = (sl_node_base_t*)&node; compile_node(cs, (sl_node_base_t*)&a_var, dest_reg); reg_free(cs, dest_reg); }
void reg_alloc(rd_instr * code, rd_vlist * vlist, rd_vlist * mem_list, unsigned int reg_offset, unsigned int reg_num, unsigned int match_types, unsigned int assign_type){ rga_reg_offset = reg_offset; num_registers = reg_num; rga_match_types = match_types; flow_graph * graph = flow_generate_graph(code, vlist, reg_offset, reg_num, match_types); initialise(vlist, reg_num); build(graph); #ifdef DEBUG_MODE debug(); #endif make_worklist(); while(true){ if(!rga_node_list_isempty(simplifyWorklist)){ simplify(); }else if(!rga_move_list_isempty(worklistMoves)){ coalesce(); }else if(!rga_node_list_isempty(freezeWorklist)){ freeze(); }else if(!rga_node_list_isempty(spillWorklist)){ select_spill(); }else{ break; } } assign_colours(); if(!rga_node_list_isempty(spilledNodes)){ rewrite_program(graph, vlist, mem_list); #ifdef DEBUG_MODE rdgen_show(); #endif clean_up(); reg_alloc(code, vlist, mem_list, reg_offset, reg_num, match_types, assign_type); }else{ assign_registers(vlist, assign_type); clean_up(); } }
NODE(sl_node_def_t, def) { sl_compile_state_t sub_cs; size_t i, on_reg; size_t init_regs = 1 + node->req_arg_count + node->opt_arg_count; if(node->rest_arg) { init_regs++; } init_compile_state(&sub_cs, cs->vm, cs, init_regs); for(i = 0; i < node->req_arg_count; i++) { sl_st_insert(sub_cs.vars, (sl_st_data_t)node->req_args[i], (sl_st_data_t)(i + 1)); } for(i = 0; i < node->opt_arg_count; i++) { sl_st_insert(sub_cs.vars, (sl_st_data_t)node->opt_args[i].name, (sl_st_data_t)(node->req_arg_count + i + 1)); } if(node->rest_arg) { sl_st_insert(sub_cs.vars, (sl_st_data_t)node->rest_arg, (sl_st_data_t)(node->req_arg_count + node->opt_arg_count + 1)); sub_cs.section->has_extra_rest_arg = 1; } sub_cs.section->name = node->name; sub_cs.section->req_registers = node->req_arg_count; sub_cs.section->arg_registers = node->req_arg_count + node->opt_arg_count; sub_cs.section->opt_skip = sl_alloc(cs->vm->arena, sizeof(size_t) * (node->opt_arg_count + 1)); for(i = 0; i < node->opt_arg_count; i++) { sub_cs.section->opt_skip[i] = sub_cs.section->insns_count; compile_node(&sub_cs, node->opt_args[i].default_value, node->req_arg_count + i + 1); } sub_cs.section->opt_skip[node->opt_arg_count] = sub_cs.section->insns_count; compile_node(&sub_cs, node->body, 0); op_return(&sub_cs, 0); if(node->on) { on_reg = reg_alloc(cs); compile_node(cs, node->on, on_reg); op_define_on(cs, on_reg, node->name, node->doc, sub_cs.section, dest); reg_free(cs, on_reg); } else { op_define(cs, node->name, node->doc, sub_cs.section, dest); } }
void gen_mov_code(int num) { int reg = reg_alloc(); /* need argument? */ printf("mov r%d, #%d\n", reg, num); }