Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 36 additions & 23 deletions src/mono/mono/mini/mini-arm64.c
Original file line number Diff line number Diff line change
Expand Up @@ -1530,15 +1530,26 @@ is_hfa (MonoType *t, int *out_nfields, int *out_esize, int *field_offsets)
}

static void
add_valuetype (CallInfo *cinfo, ArgInfo *ainfo, MonoType *t)
add_valuetype (CallInfo *cinfo, ArgInfo *ainfo, MonoType *t, gboolean is_return)
{
int i, size, align_size, nregs, nfields, esize;
int field_offsets [16];
guint32 align;
MonoClass *klass;

klass = mono_class_from_mono_type_internal (t);
size = mini_type_stack_size_full (t, &align, cinfo->pinvoke);
align_size = ALIGN_TO (size, 8);

if (m_class_is_simd_type (klass) && size <= 16 && !cinfo->pinvoke && !is_return && cinfo->fr < FP_PARAM_REGS) {
ainfo->storage = ArgInSIMDReg;
ainfo->reg = cinfo->fr;
ainfo->nregs = 1;
ainfo->size = size;
cinfo->fr ++;
return;
}

nregs = align_size / 8;
if (is_hfa (t, &nfields, &esize, field_offsets)) {
/*
Expand Down Expand Up @@ -1594,7 +1605,7 @@ add_valuetype (CallInfo *cinfo, ArgInfo *ainfo, MonoType *t)
}

static void
add_param (CallInfo *cinfo, ArgInfo *ainfo, MonoType *t)
add_param (CallInfo *cinfo, ArgInfo *ainfo, MonoType *t, gboolean is_return)
{
MonoType *ptype;

Expand Down Expand Up @@ -1646,7 +1657,7 @@ add_param (CallInfo *cinfo, ArgInfo *ainfo, MonoType *t)
break;
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_TYPEDBYREF:
add_valuetype (cinfo, ainfo, ptype);
add_valuetype (cinfo, ainfo, ptype, is_return);
break;
case MONO_TYPE_VOID:
ainfo->storage = ArgNone;
Expand All @@ -1661,7 +1672,7 @@ add_param (CallInfo *cinfo, ArgInfo *ainfo, MonoType *t)
ainfo->storage = ArgVtypeByRef;
ainfo->gsharedvt = TRUE;
} else {
add_valuetype (cinfo, ainfo, ptype);
add_valuetype (cinfo, ainfo, ptype, is_return);
}
break;
case MONO_TYPE_VAR:
Expand Down Expand Up @@ -1703,7 +1714,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
#endif

/* Return value */
add_param (cinfo, &cinfo->ret, sig->ret);
add_param (cinfo, &cinfo->ret, sig->ret, TRUE);
if (cinfo->ret.storage == ArgVtypeByRef)
cinfo->ret.reg = ARMREG_R8;
/* Reset state */
Expand All @@ -1724,10 +1735,10 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
cinfo->gr = PARAM_REGS;
cinfo->fr = FP_PARAM_REGS;
/* Emit the signature cookie just before the implicit arguments */
add_param (cinfo, &cinfo->sig_cookie, mono_get_int_type ());
add_param (cinfo, &cinfo->sig_cookie, mono_get_int_type (), FALSE);
}

add_param (cinfo, ainfo, sig->params [pindex]);
add_param (cinfo, ainfo, sig->params [pindex], FALSE);
if (ainfo->storage == ArgVtypeByRef) {
/* Pass the argument address in the next register */
if (cinfo->gr >= PARAM_REGS) {
Expand All @@ -1749,7 +1760,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
cinfo->gr = PARAM_REGS;
cinfo->fr = FP_PARAM_REGS;
/* Emit the signature cookie just before the implicit arguments */
add_param (cinfo, &cinfo->sig_cookie, mono_get_int_type ());
add_param (cinfo, &cinfo->sig_cookie, mono_get_int_type (), FALSE);
}

cinfo->stack_usage = ALIGN_TO (cinfo->stack_usage, MONO_ARCH_FRAME_ALIGNMENT);
Expand Down Expand Up @@ -2601,6 +2612,7 @@ mono_arch_allocate_vars (MonoCompile *cfg)
break;
case ArgVtypeInIRegs:
case ArgHFA:
case ArgInSIMDReg:
ins->opcode = OP_REGOFFSET;
ins->inst_basereg = cfg->frame_reg;
/* These arguments are saved to the stack in the prolog */
Expand Down Expand Up @@ -2806,21 +2818,6 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
break;
}
case ArgVtypeInIRegs:
#if 0
/* FIXME: the non-LLVM codegen should also pass arguments in registers or
* else there could a mismatch when LLVM code calls non-LLVM code
*
* See https://github.com/dotnet/runtime/issues/73454
*/
if ((t->type == MONO_TYPE_GENERICINST) && !cfg->full_aot && !sig->pinvoke) {
MonoClass *klass = mono_class_from_mono_type_internal (t);
if (mini_class_is_simd (cfg, klass)) {
lainfo->storage = LLVMArgVtypeInSIMDReg;
break;
}
}
#endif

lainfo->storage = LLVMArgAsIArgs;
lainfo->nslots = ainfo->nregs;
break;
Expand All @@ -2839,6 +2836,9 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
lainfo->nslots = ainfo->size / 8;
}
break;
case ArgInSIMDReg:
lainfo->storage = LLVMArgVtypeInSIMDReg;
break;
default:
g_assert_not_reached ();
break;
Expand Down Expand Up @@ -3001,6 +3001,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
case ArgVtypeByRef:
case ArgVtypeByRefOnStack:
case ArgVtypeOnStack:
case ArgInSIMDReg:
case ArgHFA: {
MonoInst *ins;
guint32 align;
Expand Down Expand Up @@ -3110,6 +3111,15 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, ARMREG_SP, ainfo->offset + (i * 8), load->dreg);
}
break;
case ArgInSIMDReg:
MONO_INST_NEW (cfg, load, OP_LOADX_MEMBASE);
load->dreg = mono_alloc_ireg (cfg);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be a alloc_xreg (even though internally it seems to do the same thing)

load->inst_basereg = src->dreg;
load->inst_offset = 0;
load->klass = src->klass;
MONO_ADD_INS (cfg->cbb, load);
add_outarg_reg (cfg, call, ArgInFReg, ainfo->reg, load);
break;
default:
g_assert_not_reached ();
break;
Expand Down Expand Up @@ -5584,6 +5594,9 @@ emit_move_args (MonoCompile *cfg, guint8 *code)
code = emit_strfpx (code, ainfo->reg + part, ins->inst_basereg, ins->inst_offset + ainfo->foffsets [part]);
}
break;
case ArgInSIMDReg:
code = emit_strfpq (code, ainfo->reg, ins->inst_basereg, ins->inst_offset);
break;
default:
g_assert_not_reached ();
break;
Expand Down
4 changes: 3 additions & 1 deletion src/mono/mono/mini/mini-arm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,11 +222,13 @@ typedef enum {
ArgOnStackR4,
/*
* Vtype passed in consecutive int registers.
* ainfo->reg is the firs register,
* ainfo->reg is the first register,
* ainfo->nregs is the number of registers,
* ainfo->size is the size of the structure.
*/
ArgVtypeInIRegs,
/* SIMD arg in NEON register */
ArgInSIMDReg,
ArgVtypeByRef,
ArgVtypeByRefOnStack,
ArgVtypeOnStack,
Expand Down