mark methods with lowered struct params, correctly handle x86 abi for this case
authorMatthias Braun <matze@braunis.de>
Mon, 1 Oct 2007 11:11:30 +0000 (11:11 +0000)
committerMatthias Braun <matze@braunis.de>
Mon, 1 Oct 2007 11:11:30 +0000 (11:11 +0000)
[r16018]

include/libfirm/typerep.h
ir/be/beabi.c
ir/be/benode.c
ir/be/benode_t.h
ir/be/ia32/ia32_emitter.c
ir/lower/lower_calls.c

index f4b66a8..3513cc5 100644 (file)
@@ -1946,6 +1946,8 @@ typedef enum {
                                               function calls (stdcall). */
        cc_this_call        = 0x08000000, /**< The first parameter is a this pointer and is transmitted
                                               in a special way. */
+       cc_compound_ret     = 0x10000000, /**< the method returns a compound
+                                               type */
 
        cc_bits             = (0xFF << 24)  /**< the calling convention bits */
 } calling_convention;
index dfd2305..83c6a38 100644 (file)
@@ -780,6 +780,11 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
 
                 /* Clean up the stack frame if we allocated it */
                if (! no_alloc) {
+                       /* the callee pops the shadow parameter */
+                       if(get_method_calling_convention(mt) & cc_compound_ret) {
+                               stack_size -= get_mode_size_bytes(mode_P_data);
+                       }
+
                        curr_sp = be_new_IncSP(sp, irg, bl, curr_sp, -stack_size);
                        add_irn_dep(curr_sp, mem_proj);
                }
@@ -1361,15 +1366,21 @@ static ir_node *create_barrier(be_abi_irg_t *env, ir_node *bl, ir_node **mem, pm
  * @param mem     the current memory
  * @param n_res   number of return results
  */
-static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl, ir_node *mem, int n_res) {
-       be_abi_call_t *call = env->call;
+static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl,
+               ir_node *mem, int n_res)
+{
+       ir_graph      *irg         = env->birg->irg;
+       ir_entity     *entity      = get_irg_entity(irg);
+       ir_type       *method_type = get_entity_type(entity);
+       be_abi_call_t *call        = env->call;
        const arch_isa_t *isa = env->birg->main_env->arch_env->isa;
-
+       dbg_info *dbgi;
        pmap *reg_map  = pmap_create();
        ir_node *keep  = pmap_get(env->keep_map, bl);
        int in_max;
        ir_node *ret;
        int i, n;
+       unsigned pop;
        ir_node **in;
        ir_node *stack;
        const arch_register_t **regs;
@@ -1446,7 +1457,17 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl, i
        }
 
        /* The in array for the new back end return is now ready. */
-       ret = be_new_Return(irn ? get_irn_dbg_info(irn) : NULL, env->birg->irg, bl, n_res, n, in);
+       if(irn != NULL) {
+               dbgi = get_irn_dbg_info(irn);
+       } else {
+               dbgi = NULL;
+       }
+       /* we have to pop the shadow parameter in in case of struct returns */
+       pop = 0;
+       if(get_method_calling_convention(method_type) & cc_compound_ret) {
+               pop = get_mode_size_bytes(mode_P_data);
+       }
+       ret = be_new_Return(dbgi, env->birg->irg, bl, n_res, pop, n, in);
 
        /* Set the register classes of the return's parameter accordingly. */
        for(i = 0; i < n; ++i)
index 7fc22c5..ecdfeb2 100644 (file)
@@ -85,6 +85,7 @@ typedef struct {
 typedef struct {
        be_node_attr_t node_attr;
        int            num_ret_vals;  /**< number of return values */
+       unsigned       pop;           /**< number of bytes that should be popped */
 } be_return_attr_t;
 
 /** The be_Stack attribute type. */
@@ -196,6 +197,8 @@ static int Return_cmp_attr(ir_node *a, ir_node *b) {
 
        if (a_attr->num_ret_vals != b_attr->num_ret_vals)
                return 1;
+       if (a_attr->pop != b_attr->pop)
+               return 1;
 
        return _node_cmp_attr((be_node_attr_t*) a_attr, (be_node_attr_t*) b_attr);
 }
@@ -640,7 +643,7 @@ void be_Call_set_type(ir_node *call, ir_type *call_tp) {
 
 /* Construct a new be_Return. */
 ir_node *be_new_Return(dbg_info *dbg, ir_graph *irg, ir_node *block, int n_res,
-                       int n, ir_node *in[])
+                       unsigned pop, int n, ir_node *in[])
 {
        be_return_attr_t *a;
        ir_node *res;
@@ -655,17 +658,24 @@ ir_node *be_new_Return(dbg_info *dbg, ir_graph *irg, ir_node *block, int n_res,
 
        a = get_irn_attr(res);
        a->num_ret_vals = n_res;
+       a->pop          = pop;
 
        return res;
 }
 
 /* Returns the number of real returns values */
-int be_Return_get_n_rets(ir_node *ret)
+int be_Return_get_n_rets(const ir_node *ret)
 {
-       be_return_attr_t *a = get_irn_attr(ret);
+       const be_return_attr_t *a = get_irn_generic_attr_const(ret);
        return a->num_ret_vals;
 }
 
+unsigned be_Return_get_pop(const ir_node *ret)
+{
+       const be_return_attr_t *a = get_irn_generic_attr_const(ret);
+       return a->pop;
+}
+
 int be_Return_append_node(ir_node *ret, ir_node *node)
 {
        int pos;
index a8b5a73..ddd3c05 100644 (file)
@@ -335,12 +335,15 @@ enum {
  * @param bl     the block where the new node will be placed
  * @param n_res  number of "real" results
  * @param n      number of inputs
+ * @param pop    pop number of bytes on return
  * @param in     input array
  */
-ir_node *be_new_Return(dbg_info *dbg, ir_graph *irg, ir_node *bl, int n_res, int n, ir_node *in[]);
+ir_node *be_new_Return(dbg_info *dbg, ir_graph *irg, ir_node *bl, int n_res, unsigned pop, int n, ir_node *in[]);
 
 /** Returns the number of real returns values */
-int be_Return_get_n_rets(ir_node *ret);
+int be_Return_get_n_rets(const ir_node *ret);
+
+unsigned be_Return_get_pop(const ir_node *ret);
 
 /** appends a node to the return node, returns the position of the node */
 int be_Return_append_node(ir_node *ret, ir_node *node);
index 1f34969..2881ee7 100644 (file)
@@ -1752,7 +1752,13 @@ zero_neg:
 
 static void emit_be_Return(const ir_node *node)
 {
+       unsigned pop;
        be_emit_cstring("\tret");
+
+       pop = be_Return_get_pop(node);
+       if(pop > 0) {
+               be_emit_irprintf(" $%d", pop);
+       }
        be_emit_finish_line_gas(node);
 }
 
index 606d9f7..97fd3e2 100644 (file)
@@ -177,6 +177,8 @@ static ir_type *create_modified_mtd_type(const lower_params_t *lp, ir_type *mtp)
     set_method_first_variadic_param_index(lowered, first_variadic);
 
   /* associate the lowered type with the original one for easier access */
+  set_method_calling_convention(lowered,
+                 get_method_calling_convention(mtp) | cc_compound_ret);
   set_lowered_type(mtp, lowered);
 
   return lowered;