void c54x_expand_epilogue() { int r; emit_insn(gen_frame(gen_rtx_REG (QImode, STACK_POINTER_REGNUM), gen_rtx_CONST_INT(VOIDmode, -get_frame_size()))); for(r = FIRST_PSEUDO_REGISTER - 1; r > 0; r--) { if(c54x_save_register_p(r)) { emit_insn(gen_popqi(gen_rtx_REG(QImode, r))); } } emit_insn(gen_return()); }
void Compiler::handle_ik_meth(const JInst& jinst) { if (jinst.opcode == OPCODE_INVOKESTATIC || jinst.opcode == OPCODE_INVOKESPECIAL || jinst.opcode == OPCODE_INVOKEVIRTUAL || jinst.opcode == OPCODE_INVOKEINTERFACE) { JavaByteCodes opkod = jinst.opcode; ::std::vector<jtype> args; jtype retType; bool is_static = opkod == OPCODE_INVOKESTATIC; get_args_info(is_static, jinst.op0, args, &retType); Method_Handle meth = NULL; unsigned short cpIndex = (unsigned short)jinst.op0; bool lazy = m_lazy_resolution; bool resolve = !lazy || class_cp_is_entry_resolved(m_klass, cpIndex); if (!resolve) { assert(lazy); gen_invoke(opkod, NULL, cpIndex, args, retType); return; } if (opkod == OPCODE_INVOKESTATIC) { meth = resolve_static_method(m_compileHandle, m_klass, jinst.op0); if (meth != NULL) { Class_Handle klass = method_get_class(meth); if (!class_is_initialized(klass)) { gen_call_vm(ci_helper_o, rt_helper_init_class, 0, klass); } } } else if (opkod == OPCODE_INVOKEVIRTUAL) { meth = resolve_virtual_method(m_compileHandle, m_klass, jinst.op0); } else if (opkod == OPCODE_INVOKEINTERFACE) { // BUG and HACK - all in one: // An 'org/eclipse/ui/keys/KeyStroke::hashCode' (e3.0) does // invokeinterface on java/util/SortedSet::hashCode(), but the // entry get resolved into the 'java/lang/Object::hashCode' ! // later: for eclipse 3.1.1 the same problem happens with // org/eclipse/jdt/internal/core/JavaProject::equals // which tries to resolve // 'org/eclipse/core/resources/IProject::equals (Ljava/lang/Object;)Z' meth = resolve_interface_method(m_compileHandle, m_klass, jinst.op0); // //*** workaround here: if (meth != NULL && !class_is_interface(method_get_class(meth))) { opkod = OPCODE_INVOKEVIRTUAL; } } else { assert(opkod == OPCODE_INVOKESPECIAL); meth = resolve_special_method(m_compileHandle, m_klass, jinst.op0); } // if class to call to is available, but method is not found in the class // meth here will be equal to NULL and lazy resolution call will be // generated in gen_invoke gen_invoke(opkod, meth, cpIndex, args, retType); return; } switch(jinst.opcode) { case OPCODE_IRETURN: { SYNC_FIRST(static const CallSig cs(CCONV_MANAGED, i32)); gen_return(cs); break; } case OPCODE_LRETURN: { SYNC_FIRST(static const CallSig cs(CCONV_MANAGED, i64)); gen_return(cs); break; } case OPCODE_FRETURN: { SYNC_FIRST(static const CallSig cs(CCONV_MANAGED, flt32)); gen_return(cs); break; } case OPCODE_DRETURN: { SYNC_FIRST(static const CallSig cs(CCONV_MANAGED, dbl64)); gen_return(cs); break; } case OPCODE_ARETURN: { SYNC_FIRST(static const CallSig cs(CCONV_MANAGED, jobj)); gen_return(cs); break; } case OPCODE_RETURN: { SYNC_FIRST(static const CallSig cs(CCONV_MANAGED, jvoid)); gen_return(cs); break; } default: assert(false); break; }; }
LLVMValueRef gen_expr(compile_t* c, ast_t* ast) { LLVMValueRef ret; bool has_scope = ast_has_scope(ast); bool has_source = codegen_hassource(c); if(has_scope) { codegen_pushscope(c); // Dwarf a new lexical scope, if necessary. if(has_source) dwarf_lexicalscope(&c->dwarf, ast); } switch(ast_id(ast)) { case TK_SEQ: ret = gen_seq(c, ast); break; case TK_FVARREF: case TK_FLETREF: ret = gen_fieldload(c, ast); break; case TK_PARAMREF: ret = gen_param(c, ast); break; case TK_VAR: case TK_LET: ret = gen_localdecl(c, ast); break; case TK_VARREF: case TK_LETREF: ret = gen_localload(c, ast); break; case TK_IF: ret = gen_if(c, ast); break; case TK_WHILE: ret = gen_while(c, ast); break; case TK_REPEAT: ret = gen_repeat(c, ast); break; case TK_TRY: case TK_TRY_NO_CHECK: ret = gen_try(c, ast); break; case TK_MATCH: ret = gen_match(c, ast); break; case TK_CALL: ret = gen_call(c, ast); break; case TK_CONSUME: ret = gen_expr(c, ast_childidx(ast, 1)); break; case TK_RECOVER: ret = gen_expr(c, ast_childidx(ast, 1)); break; case TK_BREAK: ret = gen_break(c, ast); break; case TK_CONTINUE: ret = gen_continue(c, ast); break; case TK_RETURN: ret = gen_return(c, ast); break; case TK_ERROR: ret = gen_error(c, ast); break; case TK_IS: ret = gen_is(c, ast); break; case TK_ISNT: ret = gen_isnt(c, ast); break; case TK_ASSIGN: ret = gen_assign(c, ast); break; case TK_THIS: ret = gen_this(c, ast); break; case TK_TRUE: ret = LLVMConstInt(c->i1, 1, false); break; case TK_FALSE: ret = LLVMConstInt(c->i1, 0, false); break; case TK_INT: ret = gen_int(c, ast); break; case TK_FLOAT: ret = gen_float(c, ast); break; case TK_STRING: ret = gen_string(c, ast); break; case TK_TUPLE: ret = gen_tuple(c, ast); break; case TK_FFICALL: ret = gen_ffi(c, ast); break; case TK_AMP: ret = gen_addressof(c, ast); break; case TK_IDENTITY: ret = gen_identity(c, ast); break; case TK_DONTCARE: ret = GEN_NOVALUE; break; case TK_COMPILER_INTRINSIC: ast_error(ast, "unimplemented compiler intrinsic"); LLVMBuildUnreachable(c->builder); ret = GEN_NOVALUE; break; default: ast_error(ast, "not implemented (codegen unknown)"); return NULL; } if(has_scope) { codegen_popscope(c); if(has_source) dwarf_finish(&c->dwarf); } return ret; }
void expand_epilogue (void) { int i; int interrupt_func_p = cfun->machine->is_interrupt; int main_p = MAIN_NAME_P (DECL_NAME (current_function_decl)); int wakeup_func_p = cfun->machine->is_wakeup; int cfp = cfun->machine->is_critical; int ree = cfun->machine->is_reenterant; int save_prologue_p = msp430_save_prologue_function_p (current_function_decl); /*int function_size;*/ HOST_WIDE_INT size = get_frame_size(); rtx insn; last_insn_address = 0; jump_tables_size = 0; epilogue_size = 0; /*function_size = (INSN_ADDRESSES (INSN_UID (get_last_insn ())) - INSN_ADDRESSES (INSN_UID (get_insns ())));*/ if (cfun->machine->is_OS_task || cfun->machine->is_naked) { emit_jump_insn (gen_return ()); /* Otherwise, epilogue with 0 instruction causes a segmentation fault */ return; } if (msp430_empty_epilogue ()) { if (!return_issued) { /*fprintf (file, "\t%s\n", msp430_emit_return (NULL, NULL, NULL));*/ emit_jump_insn (gen_return ()); epilogue_size++; } /*fprintf (file, "\n\t/ * epilogue: not required * /\n");*/ goto done_epilogue; } if ((cfp || interrupt_func_p) && ree) ree = 0; if (cfp && interrupt_func_p) cfp = 0; /*fprintf (file, "\n\t/ * epilogue : frame size = %d * /\n", size);*/ if (main_p) { int totalsize = (size + 1) & ~1; if ((ACCUMULATE_OUTGOING_ARGS) && (!cfun->machine->is_leaf || cfun->calls_alloca) && crtl->outgoing_args_size) totalsize += crtl->outgoing_args_size; if (totalsize) { msp430_fh_add_sp_const(totalsize); /*fprintf (file, "\tadd\t#%d, r1\n", (size + 1) & ~1);*/ } /*fprintf (file, "\tbr\t#%s\n", msp430_endup);*/ msp430_fh_br_to_symbol_plus_offset(msp430_endup, 0); epilogue_size += 4; if (size == 1 || size == 2 || size == 4 || size == 8) epilogue_size--; } else { int totalsize = (size + 1) & ~1; if ((ACCUMULATE_OUTGOING_ARGS) && (!cfun->machine->is_leaf || cfun->calls_alloca) && crtl->outgoing_args_size) totalsize += crtl->outgoing_args_size; if (ree) { /*fprintf (file, "\teint\n");*/ insn = emit_insn (gen_enable_interrupt()); epilogue_size += 1; } if (totalsize) { /*fprintf (file, "\tadd\t#%d, r1\n", (size + 1) & ~1);*/ msp430_fh_add_sp_const(totalsize); if (size == 1 || size == 2 || size == 4 || size == 8) epilogue_size += 1; else epilogue_size += 2; } if ((TARGET_SAVE_PROLOGUE || save_prologue_p) && !interrupt_func_p && msp430_func_num_saved_regs () > 2) { /*fprintf (file, "\tbr\t#__epilogue_restorer+%d\n",(8 - msp430_func_num_saved_regs ()) * 2);*/ msp430_fh_br_to_symbol_plus_offset("__epilogue_restorer", (8 - msp430_func_num_saved_regs ()) * 2); epilogue_size += 2; } else if ((TARGET_SAVE_PROLOGUE || save_prologue_p) && interrupt_func_p) { /*fprintf (file, "\tbr\t#__epilogue_restorer_intr+%d\n", (12 - msp430_func_num_saved_regs ()) * 2);*/ msp430_fh_br_to_symbol_plus_offset("__epilogue_restorer_intr", (12 - msp430_func_num_saved_regs ()) * 2); } else { for (i = 4; i < 16; i++) { if ((df_regs_ever_live_p(i) && (!call_used_regs[i] || interrupt_func_p)) || (!cfun->machine->is_leaf && (call_used_regs[i] && interrupt_func_p))) { /*fprintf (file, "\tpop\tr%d\n", i);*/ msp430_fh_emit_pop_reg(i); epilogue_size += 1; } } if (interrupt_func_p && wakeup_func_p) { /*fprintf (file, "\tbic\t#0xf0,0(r1)\n");*/ msp430_fh_bic_deref_sp(0xF0); epilogue_size += 3; } emit_jump_insn (gen_return ()); /*fprintf (file, "\tret\n");*/ epilogue_size += 1; } } /*fprintf (file, "\t/ * epilogue end (size=%d) * /\n", epilogue_size);*/ done_epilogue: /*fprintf (file, "\t/ * function %s size %d (%d) * /\n", current_function_name, prologue_size + function_size + epilogue_size, function_size);*/ msp430_commands_in_file += prologue_size + /*function_size +*/ epilogue_size; msp430_commands_in_prologues += prologue_size; msp430_commands_in_epilogues += epilogue_size; }
LLVMValueRef gen_expr(compile_t* c, ast_t* ast) { LLVMValueRef ret; bool has_scope = ast_has_scope(ast); if(has_scope) codegen_pushscope(c, ast); switch(ast_id(ast)) { case TK_SEQ: ret = gen_seq(c, ast); break; case TK_FVARREF: case TK_FLETREF: ret = gen_fieldload(c, ast); break; case TK_EMBEDREF: ret = gen_fieldptr(c, ast); break; case TK_PARAMREF: ret = gen_param(c, ast); break; case TK_VAR: case TK_LET: case TK_MATCH_CAPTURE: ret = gen_localdecl(c, ast); break; case TK_VARREF: case TK_LETREF: ret = gen_localload(c, ast); break; case TK_IF: ret = gen_if(c, ast); break; case TK_WHILE: ret = gen_while(c, ast); break; case TK_REPEAT: ret = gen_repeat(c, ast); break; case TK_TRY: case TK_TRY_NO_CHECK: ret = gen_try(c, ast); break; case TK_MATCH: ret = gen_match(c, ast); break; case TK_CALL: ret = gen_call(c, ast); break; case TK_CONSUME: ret = gen_expr(c, ast_childidx(ast, 1)); break; case TK_RECOVER: ret = gen_expr(c, ast_childidx(ast, 1)); break; case TK_BREAK: ret = gen_break(c, ast); break; case TK_CONTINUE: ret = gen_continue(c, ast); break; case TK_RETURN: ret = gen_return(c, ast); break; case TK_ERROR: ret = gen_error(c, ast); break; case TK_IS: ret = gen_is(c, ast); break; case TK_ISNT: ret = gen_isnt(c, ast); break; case TK_ASSIGN: ret = gen_assign(c, ast); break; case TK_THIS: ret = gen_this(c, ast); break; case TK_TRUE: ret = LLVMConstInt(c->i1, 1, false); break; case TK_FALSE: ret = LLVMConstInt(c->i1, 0, false); break; case TK_INT: ret = gen_int(c, ast); break; case TK_FLOAT: ret = gen_float(c, ast); break; case TK_STRING: ret = gen_string(c, ast); break; case TK_TUPLE: ret = gen_tuple(c, ast); break; case TK_FFICALL: ret = gen_ffi(c, ast); break; case TK_ADDRESS: ret = gen_addressof(c, ast); break; case TK_DIGESTOF: ret = gen_digestof(c, ast); break; case TK_DONTCARE: ret = GEN_NOVALUE; break; case TK_COMPILE_INTRINSIC: ast_error(c->opt->check.errors, ast, "unimplemented compile intrinsic"); return NULL; case TK_COMPILE_ERROR: { ast_t* reason_seq = ast_child(ast); ast_t* reason = ast_child(reason_seq); ast_error(c->opt->check.errors, ast, "compile error: %s", ast_name(reason)); return NULL; } default: ast_error(c->opt->check.errors, ast, "not implemented (codegen unknown)"); return NULL; } if(has_scope) codegen_popscope(c); return ret; }
renderbuffer(context& _context) : globject(gen_return(glGenRenderbuffers)) {}