OPDEF(CEE_MONO_CALLI_EXTRA_ARG, "mono_calli_extra_arg", VarPop, VarPush, InlineSig, X, 2, 0xF0, 0x18, CALL)
OPDEF(CEE_MONO_LDDOMAIN, "mono_lddomain", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x19, NEXT)
OPDEF(CEE_MONO_ATOMIC_STORE_I4, "mono_atomic_store_i4", PopI+PopI, Push0, InlineI, X, 2, 0xF0, 0x1A, NEXT)
-OPDEF(CEE_MONO_GET_LAST_ERROR, "mono_get_last_error", Pop0, PushI, InlineI, X, 2, 0xF0, 0x1B, NEXT)
+OPDEF(CEE_MONO_GET_LAST_ERROR, "mono_get_last_error", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x1B, NEXT)
#ifndef OPALIAS
#define _MONO_CIL_OPALIAS_DEFINED_
#define OPALIAS(a,s,r)
src [0] = map_reg (sreg);
break;
case ArgValuetypeInReg:
- case ArgValuetypeAddrInIReg:
nsrc = ainfo->nregs;
src = g_malloc (nsrc * sizeof (int));
for (i = 0; i < ainfo->nregs; ++i)
src [i] = map_reg (ainfo->pair_regs [i]);
break;
- case ArgValuetypeAddrOnStack:
case ArgOnStack:
nsrc = ainfo->arg_size / SLOT_BYTE_SIZE;
src = g_malloc (nsrc * sizeof (int));
src = g_malloc (nsrc * sizeof (int));
src [0] = map_freg (sreg);
break;
+ case ArgValuetypeAddrInIReg:
+ nsrc = 1;
+ src = g_malloc (nsrc * sizeof (int));
+ src [0] = map_reg (ainfo->pair_regs [0]);
+ break;
+ case ArgValuetypeAddrOnStack:
+ nsrc = 1;
+ src = g_malloc (nsrc * sizeof (int));
+ // is_source_argument adds 2 because we're skipping over the old BBP and the return address
+ // XXX this is a very fragile setup as changes in alignment for the caller reg array can cause the magic number be 3
+ src [0] = map_stack_slot (sslot + (is_source_argument ? 2 : 0));
+ break;
default:
NOT_IMPLEMENTED;
break;
}
inline gboolean
-allocate_return_register_for_valyetype_win64 (ArgInfo *arg_info, ArgumentClass arg_class, guint32 arg_size, guint32 *current_int_reg, guint32 *current_float_reg)
+allocate_return_register_for_valuetype_win64 (ArgInfo *arg_info, ArgumentClass arg_class, guint32 arg_size, guint32 *current_int_reg, guint32 *current_float_reg)
{
return allocate_register_for_valuetype_win64 (arg_info, arg_class, arg_size, return_regs, RETURN_REGS, float_return_regs, FLOAT_RETURN_REGS, current_int_reg, current_float_reg);
}
/* Parameter cases. */
if (arg_class != ARG_CLASS_MEMORY && MONO_WIN64_VALUE_TYPE_FITS_REG (arg_size)) {
-
assert (arg_size == 1 || arg_size == 2 || arg_size == 4 || arg_size == 8);
/* First, try to use registers for parameter. If type is struct it can only be passed by value in integer register. */
arg_info->storage = ArgValuetypeInReg;
if (!allocate_parameter_register_for_valuetype_win64 (arg_info, !MONO_TYPE_ISSTRUCT (type) ? arg_class : ARG_CLASS_INTEGER, arg_size, current_int_reg, current_float_reg)) {
-
/* No more registers, fallback passing parameter on stack as value. */
assert (arg_info->pair_storage [0] == ArgNone && arg_info->pair_storage [1] == ArgNone && arg_info->pair_size [0] == 0 && arg_info->pair_size [1] == 0 && arg_info->nregs == 0);
*stack_size += arg_size;
}
} else {
-
/* Fallback to stack, try to pass address to parameter in register. Always use integer register to represent stack address. */
arg_info->storage = ArgValuetypeAddrInIReg;
if (!allocate_parameter_register_for_valuetype_win64 (arg_info, ARG_CLASS_INTEGER, arg_size, current_int_reg, current_float_reg)) {
-
/* No more registers, fallback passing address to parameter on stack. */
assert (arg_info->pair_storage [0] == ArgNone && arg_info->pair_storage [1] == ArgNone && arg_info->pair_size [0] == 0 && arg_info->pair_size [1] == 0 && arg_info->nregs == 0);
}
}
} else {
-
/* Return value cases. */
if (arg_class != ARG_CLASS_MEMORY && MONO_WIN64_VALUE_TYPE_FITS_REG (arg_size)) {
-
assert (arg_size == 1 || arg_size == 2 || arg_size == 4 || arg_size == 8);
/* Return value fits into return registers. If type is struct it can only be returned by value in integer register. */
arg_info->storage = ArgValuetypeInReg;
- allocate_return_register_for_valyetype_win64 (arg_info, !MONO_TYPE_ISSTRUCT (type) ? arg_class : ARG_CLASS_INTEGER, arg_size, current_int_reg, current_float_reg);
+ allocate_return_register_for_valuetype_win64 (arg_info, !MONO_TYPE_ISSTRUCT (type) ? arg_class : ARG_CLASS_INTEGER, arg_size, current_int_reg, current_float_reg);
- /* Only RAX/XMM0 should be used to return valyetype. */
+ /* Only RAX/XMM0 should be used to return valuetype. */
assert ((arg_info->pair_regs[0] == AMD64_RAX && arg_info->pair_regs[1] == ArgNone) || (arg_info->pair_regs[0] == AMD64_XMM0 && arg_info->pair_regs[1] == ArgNone));
-
} else {
-
/* Return value doesn't fit into return register, return address to allocated stack space (allocated by caller and passed as input). */
arg_info->storage = ArgValuetypeAddrInIReg;
- allocate_return_register_for_valyetype_win64 (arg_info, ARG_CLASS_INTEGER, arg_size, current_int_reg, current_float_reg);
+ allocate_return_register_for_valuetype_win64 (arg_info, ARG_CLASS_INTEGER, arg_size, current_int_reg, current_float_reg);
- /* Only RAX should be used to return valyetype address. */
+ /* Only RAX should be used to return valuetype address. */
assert (arg_info->pair_regs[0] == AMD64_RAX && arg_info->pair_regs[1] == ArgNone);
arg_size = ALIGN_TO (arg_size, sizeof (mgreg_t));
assert (klass != NULL && arg_info != NULL && type != NULL && arg_class != NULL && arg_size != NULL);
- if (pinvoke == TRUE) {
+ if (pinvoke) {
/* Calculate argument class type and size of marshalled type. */
MonoMarshalType *info = mono_marshal_load_type_info (klass);
*arg_size = info->native_size;
if ((arg_size == 0 && !arg_info->pass_empty_struct) || (arg_size == 0 && arg_info->pass_empty_struct && is_return)) {
arg_info->storage = ArgValuetypeInReg;
arg_info->pair_storage [0] = arg_info->pair_storage [1] = ArgNone;
- }
- else
- {
+ } else {
/* Alocate storage for value type. */
allocate_storage_for_valuetype_win64 (arg_info, type, is_return, arg_class, arg_size, current_int_reg, current_float_reg, stack_size);
}
}
#ifdef TARGET_WIN32
+ /* The current SIMD doesn't support the argument used by a LD_ADDR to be of type OP_VTARG_ADDR. */
+ /* This will now be used for value types > 8 or of size 3,5,6,7 as dictated by windows x64 value type ABI. */
+ /* Since OP_VTARG_ADDR needs to be resolved in mono_spill_global_vars and the SIMD implementation optimize */
+ /* away the LD_ADDR in load_simd_vreg, that will cause an error in mono_spill_global_vars since incorrect opcode */
+ /* will now have a reference to an argument that won't be fully decomposed. */
*exclude_mask |= MONO_OPT_SIMD;
#endif