Author: zoltan
Date: 2005-07-19 16:33:21 -0400 (Tue, 19 Jul 2005)
New Revision: 47434

Modified:
   trunk/mono/mono/mini/ChangeLog
   trunk/mono/mono/mini/mini-ia64.c
   trunk/mono/mono/mini/mini-ia64.h
Log:
2005-07-19  Zoltan Varga  <[EMAIL PROTECTED]>

        * mini-ia64.h mini-ia64.c: Finish pinvoke support.


Modified: trunk/mono/mono/mini/ChangeLog
===================================================================
--- trunk/mono/mono/mini/ChangeLog      2005-07-19 20:30:27 UTC (rev 47433)
+++ trunk/mono/mono/mini/ChangeLog      2005-07-19 20:33:21 UTC (rev 47434)
@@ -1,3 +1,7 @@
+2005-07-19  Zoltan Varga  <[EMAIL PROTECTED]>
+
+       * mini-ia64.h mini-ia64.c: Finish pinvoke support.
+
 2005-07-19  Martin Baulig  <[EMAIL PROTECTED]>
 
        * exceptions-amd64.c (throw_exception): Call

Modified: trunk/mono/mono/mini/mini-ia64.c
===================================================================
--- trunk/mono/mono/mini/mini-ia64.c    2005-07-19 20:30:27 UTC (rev 47433)
+++ trunk/mono/mono/mini/mini-ia64.c    2005-07-19 20:33:21 UTC (rev 47434)
@@ -113,20 +113,25 @@
        ArgOnStack,
        ArgValuetypeAddrInIReg,
        ArgAggregate,
-       ArgAggregateReturnInReg,
+       ArgSingleHFA,
+       ArgDoubleHFA,
        ArgNone /* only in pair_storage */
 } ArgStorage;
 
+typedef enum {
+       AggregateNormal,
+       AggregateSingleHFA,
+       AggregateDoubleHFA
+} AggregateType;
+
 typedef struct {
        gint16 offset;
        gint8  reg;
        ArgStorage storage;
 
-       /* Only if storage == ArgAggregate/ArgAggregateReturnInReg */
-       int nregs;
-
        /* Only if storage == ArgAggregate */
-       int nslots;
+       int nregs, nslots;
+       AggregateType atype;
 } ArgInfo;
 
 typedef struct {
@@ -219,32 +224,56 @@
        g_assert (info);
        for (i = 0; i < info->num_fields; ++i) {
                guint32 ftype = info->fields [i].field->type->type;
-               if ((info->fields [i].field->type->byref) && 
+               if (!(info->fields [i].field->type->byref) && 
                        ((ftype == MONO_TYPE_R4) || (ftype == MONO_TYPE_R8))) {
                        if (hfa_type == 0)
                                hfa_type = ftype;
                        else if (hfa_type != ftype)
                                is_hfa = FALSE;
                }
+               else
+                       is_hfa = FALSE;
        }
        if (hfa_type == 0)
                is_hfa = FALSE;
 
-       if (is_hfa)
-               NOT_IMPLEMENTED;
+       ainfo->storage = ArgAggregate;
+       ainfo->atype = AggregateNormal;
 
+       if (is_hfa) {
+               ainfo->atype = hfa_type == MONO_TYPE_R4 ? AggregateSingleHFA : 
AggregateDoubleHFA;
+               if (is_return) {
+                       if (info->num_fields <= 8) {
+                               ainfo->reg = 8;
+                               ainfo->nregs = info->num_fields;
+                               ainfo->nslots = ainfo->nregs;
+                               return;
+                       }
+                       /* Fall through */
+               }
+               else {
+                       if ((*fr) + info->num_fields > 8)
+                               NOT_IMPLEMENTED;
+
+                       ainfo->reg = 8 + (*fr);
+                       ainfo->nregs = info->num_fields;
+                       ainfo->nslots = ainfo->nregs;
+                       (*fr) += info->num_fields;
+                       return;
+               }
+       }
+
        /* This also handles returning of TypedByRef used by some icalls */
        if (is_return) {
                if (size <= 32) {
-                       ainfo->storage = ArgAggregateReturnInReg;
                        ainfo->reg = IA64_R8;
                        ainfo->nregs = (size + 7) / 8;
+                       ainfo->nslots = ainfo->nregs;
                        return;
                }
                NOT_IMPLEMENTED;
        }
 
-       ainfo->storage = ArgAggregate;
        ainfo->reg = (*gr);
        ainfo->offset = *stack_size;
        ainfo->nslots = (size + 7) / 8;
@@ -644,6 +673,14 @@
                        cfg->ret->opcode = OP_REGVAR;
                        cfg->ret->inst_c0 = cfg->arch.reg_in0 + cinfo->ret.reg;
                        break;
+               case ArgAggregate:
+                       /* Allocate a local to hold the result, the epilog will 
copy it to the correct place */
+                       offset = ALIGN_TO (offset, 8);
+                       offset += cinfo->ret.nslots * 8;
+                       cfg->ret->opcode = OP_REGOFFSET;
+                       cfg->ret->inst_basereg = cfg->frame_reg;
+                       cfg->ret->inst_offset = - offset;
+                       break;
                default:
                        g_assert_not_reached ();
                }
@@ -708,6 +745,7 @@
                                inst->inst_offset = ARGS_OFFSET + ainfo->offset;
                                break;
                        case ArgAggregate:
+                               inreg = FALSE;
                                break;
                        default:
                                NOT_IMPLEMENTED;
@@ -717,12 +755,17 @@
                                inst->opcode = OP_REGOFFSET;
                                inst->inst_basereg = cfg->frame_reg;
                                /* These arguments are saved to the stack in 
the prolog */
-                               if (ainfo->storage == ArgAggregate) {
-                                       NOT_IMPLEMENTED;
-                                       offset += 2 * sizeof (gpointer);
+                               switch (ainfo->storage) {
+                               case ArgAggregate:
+                                       if (ainfo->atype == AggregateSingleHFA)
+                                               offset += ainfo->nslots * 4;
+                                       else
+                                               offset += ainfo->nslots * 8;
+                                       break;
+                               default:
+                                       offset += sizeof (gpointer);
+                                       break;
                                }
-                               else
-                                       offset += sizeof (gpointer);
                                offset = ALIGN_TO (offset, sizeof (gpointer));
                                inst->inst_offset = - offset;
                        }
@@ -737,7 +780,17 @@
 void
 mono_arch_create_vars (MonoCompile *cfg)
 {
-       g_assert_not_reached ();
+       MonoMethodSignature *sig;
+       CallInfo *cinfo;
+
+       sig = mono_method_signature (cfg->method);
+
+       cinfo = get_call_info (sig, FALSE);
+
+       if (cinfo->ret.storage == ArgAggregate)
+               cfg->ret_var_is_local = TRUE;
+
+       g_free (cinfo);
 }
 
 static void
@@ -788,7 +841,7 @@
 
        cinfo = get_call_info (sig, sig->pinvoke);
 
-       if (cinfo->ret.storage == ArgAggregateReturnInReg) {
+       if (cinfo->ret.storage == ArgAggregate) {
                /* The code in emit_this_vret_arg needs a local */
                cfg->arch.ret_var_addr_local = mono_compile_create_var (cfg, 
&mono_defaults.int_class->byval_arg, OP_LOCAL);
                ((MonoInst*)cfg->arch.ret_var_addr_local)->flags |= 
MONO_INST_VOLATILE;
@@ -880,26 +933,44 @@
                                         * Part of the structure is passed in 
registers.
                                         */
                                        for (i = 0; i < ainfo->nregs; ++i) {
+                                               int offset, load_op, dest_reg, 
arg_storage;
+
                                                slot = ainfo->reg + i;
+                                               
+                                               if (ainfo->atype == 
AggregateSingleHFA) {
+                                                       load_op = CEE_LDIND_R4;
+                                                       offset = i * 4;
+                                                       dest_reg = ainfo->reg + 
i;
+                                                       arg_storage = 
ArgInFloatReg;
+                                               } else if (ainfo->atype == 
AggregateDoubleHFA) {
+                                                       load_op = CEE_LDIND_R8;
+                                                       offset = i * 8;
+                                                       dest_reg = ainfo->reg + 
i;
+                                                       arg_storage = 
ArgInFloatReg;
+                                               } else {
+                                                       load_op = CEE_LDIND_I;
+                                                       offset = i * 8;
+                                                       dest_reg = 
cfg->arch.reg_out0 + ainfo->reg + i;
+                                                       arg_storage = ArgInIReg;
+                                               }
 
                                                MONO_INST_NEW (cfg, load, 
CEE_LDIND_I);
                                                load->ssa_op = MONO_SSA_LOAD;
                                                load->inst_i0 = (cfg)->varinfo 
[vtaddr->inst_c0];
 
-                                               NEW_ICONST (cfg, offset_ins, (i 
* sizeof (gpointer)));
+                                               NEW_ICONST (cfg, offset_ins, 
offset);
                                                MONO_INST_NEW (cfg, load2, 
CEE_ADD);
                                                load2->inst_left = load;
                                                load2->inst_right = offset_ins;
 
-                                               MONO_INST_NEW (cfg, load, 
CEE_LDIND_I);
+                                               MONO_INST_NEW (cfg, load, 
load_op);
                                                load->inst_left = load2;
 
                                                if (i == 0)
                                                        set_reg = arg;
                                                else
                                                        MONO_INST_NEW (cfg, 
set_reg, OP_OUTARG_REG);
-                                               add_outarg_reg (cfg, call, 
set_reg, ArgInIReg, cfg->arch.reg_out0 + slot, load);
-
+                                               add_outarg_reg (cfg, call, 
set_reg, arg_storage, dest_reg, load);
                                                if (set_reg != call->out_args) {
                                                        set_reg->next = 
call->out_args;
                                                        call->out_args = 
set_reg;
@@ -1930,7 +2001,9 @@
        case OP_VCALL_REG:
        case OP_VCALL_MEMBASE:
                cinfo = get_call_info (((MonoCallInst*)ins)->signature, FALSE);
-               if (cinfo->ret.storage == ArgAggregateReturnInReg) {
+               ArgStorage storage = cinfo->ret.storage;
+
+               if (storage == ArgAggregate) {
                        MonoInst *local = 
(MonoInst*)cfg->arch.ret_var_addr_local;
 
                        /* Load address of stack space allocated for the return 
value */
@@ -1939,7 +2012,19 @@
                        ia64_ld8 (code, GP_SCRATCH_REG, GP_SCRATCH_REG);
 
                        for (i = 0; i < cinfo->ret.nregs; ++i) {
-                               ia64_st8_inc_imm_hint (code, GP_SCRATCH_REG, 
cinfo->ret.reg + i, 8, 0);
+                               switch (cinfo->ret.atype) {
+                               case AggregateNormal:
+                                       ia64_st8_inc_imm_hint (code, 
GP_SCRATCH_REG, cinfo->ret.reg + i, 8, 0);
+                                       break;
+                               case AggregateSingleHFA:
+                                       ia64_stfs_inc_imm_hint (code, 
GP_SCRATCH_REG, cinfo->ret.reg + i, 4, 0);
+                                       break;
+                               case AggregateDoubleHFA:
+                                       ia64_stfd_inc_imm_hint (code, 
GP_SCRATCH_REG, cinfo->ret.reg + i, 8, 0);
+                                       break;
+                               default:
+                                       g_assert_not_reached ();
+                               }
                        }
                }
                g_free (cinfo);
@@ -3225,8 +3310,30 @@
                                break;
                        case ArgOnStack:
                                break;
+                       case ArgAggregate:
+                               if (ainfo->nslots != ainfo->nregs)
+                                       NOT_IMPLEMENTED;
+
+                               g_assert (inst->opcode == OP_REGOFFSET);
+                               ia64_adds_imm (code, GP_SCRATCH_REG, 
inst->inst_offset, inst->inst_basereg);
+                               for (i = 0; i < ainfo->nregs; ++i) {
+                                       switch (ainfo->atype) {
+                                       case AggregateNormal:
+                                               ia64_st8_inc_imm_hint (code, 
GP_SCRATCH_REG, cfg->arch.reg_in0 + ainfo->reg + i, sizeof (gpointer), 0);
+                                               break;
+                                       case AggregateSingleHFA:
+                                               ia64_stfs_inc_imm_hint (code, 
GP_SCRATCH_REG, ainfo->reg + i, 4, 0);
+                                               break;
+                                       case AggregateDoubleHFA:
+                                               ia64_stfd_inc_imm_hint (code, 
GP_SCRATCH_REG, ainfo->reg + i, sizeof (gpointer), 0);
+                                               break;
+                                       default:
+                                               NOT_IMPLEMENTED;
+                                       }
+                               }
+                               break;
                        default:
-                               NOT_IMPLEMENTED;
+                               g_assert_not_reached ();
                        }
                }
 
@@ -3271,11 +3378,12 @@
 mono_arch_emit_epilog (MonoCompile *cfg)
 {
        MonoMethod *method = cfg->method;
-       int pos;
+       int i, pos;
        int max_epilog_size = 16 * 4;
        Ia64CodegenState code;
        guint8 *buf;
        CallInfo *cinfo;
+       ArgInfo *ainfo;
 
        cfg->arch.epilog_begin_offset = cfg->code_len;
 
@@ -3303,8 +3411,32 @@
 
        /* Load returned vtypes into registers if needed */
        cinfo = get_call_info (mono_method_signature (method), FALSE);
-       if (cinfo->ret.storage == ArgAggregate) {
-               NOT_IMPLEMENTED;
+       ainfo = &cinfo->ret;
+       switch (ainfo->storage) {
+       case ArgAggregate:
+               if (ainfo->nslots != ainfo->nregs)
+                       NOT_IMPLEMENTED;
+
+               g_assert (cfg->ret->opcode == OP_REGOFFSET);
+               ia64_adds_imm (code, GP_SCRATCH_REG, cfg->ret->inst_offset, 
cfg->ret->inst_basereg);
+               for (i = 0; i < ainfo->nregs; ++i) {
+                       switch (ainfo->atype) {
+                       case AggregateNormal:
+                               ia64_ld8_inc_imm_hint (code, ainfo->reg + i, 
GP_SCRATCH_REG, sizeof (gpointer), 0);
+                               break;
+                       case AggregateSingleHFA:
+                               ia64_ldfs_inc_imm_hint (code, ainfo->reg + i, 
GP_SCRATCH_REG, 4, 0);
+                               break;
+                       case AggregateDoubleHFA:
+                               ia64_ldfd_inc_imm_hint (code, ainfo->reg + i, 
GP_SCRATCH_REG, sizeof (gpointer), 0);
+                               break;
+                       default:
+                               g_assert_not_reached ();
+                       }
+               }
+               break;
+       default:
+               break;
        }
        g_free (cinfo);
 
@@ -3622,13 +3754,13 @@
                CallInfo * cinfo = get_call_info (inst->signature, FALSE);
                MonoInst *vtarg;
 
-               if (cinfo->ret.storage == ArgAggregateReturnInReg) {
+               if (cinfo->ret.storage == ArgAggregate) {
                        MonoInst *local = 
(MonoInst*)cfg->arch.ret_var_addr_local;
 
                        /* 
-                        * The valuetype is in r8..r11 after the call, need to 
be copied to
-                        * the stack. Save the address to a local here, so the 
call instruction
-                        * can access it.
+                        * The valuetype is in registers after the call, need 
to be copied 
+                        * to the stack. Save the address to a local here, so 
the call 
+                        * instruction can access it.
                         */
                        g_assert (local->opcode == OP_REGOFFSET);
                        MONO_EMIT_NEW_STORE_MEMBASE (cfg, 
OP_STOREI8_MEMBASE_REG, local->inst_basereg, local->inst_offset, vt_reg);

Modified: trunk/mono/mono/mini/mini-ia64.h
===================================================================
--- trunk/mono/mono/mini/mini-ia64.h    2005-07-19 20:30:27 UTC (rev 47433)
+++ trunk/mono/mono/mini/mini-ia64.h    2005-07-19 20:33:21 UTC (rev 47434)
@@ -176,5 +176,6 @@
 #define MONO_ARCH_HAVE_PIC_AOT 1
 #define MONO_ARCH_HAVE_CREATE_TRAMPOLINE_FROM_TOKEN 1
 #define MONO_ARCH_HAVE_SAVE_UNWIND_INFO 1
+#define MONO_ARCH_HAVE_CREATE_VARS 1
 
 #endif /* __MONO_MINI_IA64_H__ */  

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to