void FunctionContext::initialize() { Function *fn = function(); fn->attach_context(this); FBlock *fb = fun_block(); if (fb->pstart) delete fb->pstart; // may be previously defined! fb->pstart = 0; fb->nargs = 0; // crucial to clear this! // and switch to the function compile context! Parser::set_function_code(true); // *change 1.2.9 This is now retired; this is called explicitly before main() // *fix 1.2.5 Ensure that any library initializations occur before a program is run! //if (fn->name()=="main") { // Parser::code().compile(Expressions::function_call("_init_lib",NULL),DROP_VALUE); //} }
void FunctionContext::finalize() { UCContext& code = Parser::code(); // if the last instruction was a trival RETURN jump, ignore it! int op = code.last_pi()->opcode; Label *ret_lbl = Parser::state.return_label(); // cerr << "ret fun " << ret_lbl << std::endl; if (op == JMP && code.last_pi()->data == code.ip_offset()) { // cerr << "removing ret " << std::endl; ret_lbl->remove(code.last_pi()); // take out this JMP code.backspace(); // skip back ret_lbl->here(); // repatch all other instances of return jump } else if (ret_lbl && op == UNWIND) ret_lbl->here(-1); LocalContext::finalize(); // *fix 1.1.0 Finalizing the context often generates an UNWIND; // ensure that all returns jump to it first! if (ret_lbl && code.last_pi()->opcode == UNWIND) ret_lbl->here(-1); // appropriate RETx instruction code.emit_return(m_function->return_type()); fun_block()->finalize(size()); // and switch to back to the static compile context... Parser::set_function_code(false); // update the module structure with our line number range int lstart, lend; function()->line_nos()->lookup_range(lstart,lend); if (lstart < 0 || lend < 0) lstart = 0; Module *pm = Module::current(); if(pm) { pm->add_function(function(),lstart,lend); function()->line_nos()->module(pm->id()); } else function()->line_nos()->module(0); }