From f515069826a8fbfd488c30d59f0ea9a80bf9c752 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Thu, 14 May 2009 22:23:11 +0000 Subject: [PATCH] when inlining and return types of method-type/call-type don't match create a conv (or give up) [r25962] --- ir/opt/opt_inline.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/ir/opt/opt_inline.c b/ir/opt/opt_inline.c index 522456c13..3ec83fe0b 100644 --- a/ir/opt/opt_inline.c +++ b/ir/opt/opt_inline.c @@ -861,18 +861,22 @@ int inline_method(ir_node *call, ir_graph *called_graph) { mtp = get_entity_type(ent); ctp = get_Call_type(call); - if (get_method_n_params(mtp) > get_method_n_params(ctp)) { + n_params = get_method_n_params(mtp); + n_res = get_method_n_ress(mtp); + if (n_params > get_method_n_params(ctp)) { /* this is a bad feature of C: without a prototype, we can * call a function with less parameters than needed. Currently * we don't support this, although we could use Unknown than. */ return 0; } + if (n_res != get_method_n_ress(ctp)) { + return 0; + } /* Argh, compiling C has some bad consequences: * It is implementation dependent what happens in that case. * We support inlining, if the bitsize of the types matches AND * the same arithmetic is used. */ - n_params = get_method_n_params(mtp); for (i = n_params - 1; i >= 0; --i) { ir_type *param_tp = get_method_param_type(mtp, i); ir_type *arg_tp = get_method_param_type(ctp, i); @@ -890,6 +894,22 @@ int inline_method(ir_node *call, ir_graph *called_graph) { /* otherwise we can simply "reinterpret" the bits */ } } + for (i = n_res - 1; i >= 0; --i) { + ir_type *decl_res_tp = get_method_res_type(mtp, i); + ir_type *used_res_tp = get_method_res_type(ctp, i); + + if (decl_res_tp != used_res_tp) { + ir_mode *decl_mode = get_type_mode(decl_res_tp); + ir_mode *used_mode = get_type_mode(used_res_tp); + if (decl_mode == NULL || used_mode == NULL) + return 0; + if (get_mode_size_bits(decl_mode) != get_mode_size_bits(used_mode)) + return 0; + if (get_mode_arithmetic(decl_mode) != get_mode_arithmetic(used_mode)) + return 0; + /* otherwise we can "reinterpret" the bits */ + } + } irg = get_irn_irg(call); @@ -1115,11 +1135,18 @@ int inline_method(ir_node *call, ir_graph *called_graph) { /* Now the real results */ if (n_res > 0) { for (j = 0; j < n_res; j++) { + ir_type *res_type = get_method_res_type(ctp, j); + ir_mode *res_mode = get_type_mode(res_type); n_ret = 0; for (i = 0; i < arity; i++) { ret = get_Block_cfgpred(end_bl, i); if (is_Return(ret)) { - cf_pred[n_ret] = get_Return_res(ret, j); + ir_node *res = get_Return_res(ret, j); + if (get_irn_mode(res) != res_mode) { + ir_node *block = get_nodes_block(res); + res = new_r_Conv(irg, block, res, res_mode); + } + cf_pred[n_ret] = res; n_ret++; } } -- 2.20.1