Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wasm] Allow scalar valuetypes with r4/r8 members. #94969

Merged
merged 1 commit into from
Nov 20, 2023
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
6 changes: 5 additions & 1 deletion src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1466,9 +1466,13 @@ build_args_from_sig (MonoMethodSignature *sig, InterpFrame *frame)

#ifdef HOST_WASM
{
MonoType *etype;

/* Scalar vtypes are passed by value */
if (mini_wasm_is_scalar_vtype (sig->params [i]))
// FIXME: r4/r8
if (mini_wasm_is_scalar_vtype (sig->params [i], &etype) && etype->type != MONO_TYPE_R4 && etype->type != MONO_TYPE_R8) {
margs->iargs [int_i] = *(gpointer*)margs->iargs [int_i];
Copy link
Member

Choose a reason for hiding this comment

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

Will this work correctly for i8/u8? I'm fine with not fixing those yet though

Copy link
Contributor Author

@vargaz vargaz Nov 19, 2023

Choose a reason for hiding this comment

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

We disable those:

		} else if (size == 8 && t->type != MONO_TYPE_R8) {
			return FALSE;

}
}
#endif
int_i++;
Expand Down
40 changes: 22 additions & 18 deletions src/mono/mono/mini/mini-generic-sharing.c
Original file line number Diff line number Diff line change
Expand Up @@ -1172,6 +1172,9 @@ get_wrapper_shared_vtype (MonoType *t)
MonoClass *klass;
MonoClass *tuple_class = NULL;
int findex = 0;
#ifdef TARGET_WASM
gboolean has_fp = FALSE;
#endif

// FIXME: Map 1 member structs to primitive types on platforms where its supported

Expand Down Expand Up @@ -1199,29 +1202,31 @@ get_wrapper_shared_vtype (MonoType *t)
args [findex ++] = ftype;
if (findex >= 16)
break;
#ifdef TARGET_WASM
if (ftype->type == MONO_TYPE_R4 || ftype->type == MONO_TYPE_R8 || MONO_TYPE_ISSTRUCT (ftype))
has_fp = TRUE;
#endif
}

#ifdef TARGET_WASM
guint32 align;
int size = mono_class_value_size (klass, &align);

/* Other platforms might pass small valuestypes or valuetypes with non-int fields differently */
if (align == 4 && size <= 4 * 5) {
findex = size / align;
for (int i = 0; i < findex; ++i)
args [i] = m_class_get_byval_arg (mono_get_int32_class ());
} else if (align == 8 && size <= 8 * 5) {
findex = size / align;
for (int i = 0; i < findex; ++i)
args [i] = m_class_get_byval_arg (mono_get_int64_class ());
} else {
if (findex > 7)
return NULL;
if (!has_fp) {
guint32 align;
int size = mono_class_value_size (klass, &align);

/* Other platforms might pass small valuetypes or valuetypes with non-int fields differently */
if (align == 4 && size <= 4 * 5) {
findex = size / align;
for (int i = 0; i < findex; ++i)
args [i] = m_class_get_byval_arg (mono_get_int32_class ());
} else if (align == 8 && size <= 8 * 5) {
findex = size / align;
for (int i = 0; i < findex; ++i)
args [i] = m_class_get_byval_arg (mono_get_int64_class ());
}
}
#else
#endif
if (findex > 7)
return NULL;
#endif

switch (findex) {
case 0:
Expand Down Expand Up @@ -1395,7 +1400,6 @@ get_wrapper_shared_type (MonoType *t)
return get_wrapper_shared_type_full (t, FALSE);
}


/* Returns the intptr type for types that are passed in a single register */
static MonoType*
get_wrapper_shared_type_reg (MonoType *t, gboolean pinvoke)
Expand Down
8 changes: 4 additions & 4 deletions src/mono/mono/mini/mini-llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1609,7 +1609,7 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo *
break;
case LLVMArgWasmVtypeAsScalar:
g_assert (cinfo->ret.esize);
ret_type = LLVMIntType (cinfo->ret.esize * 8);
ret_type = type_to_llvm_type (ctx, cinfo->ret.etype);
break;
default:
break;
Expand Down Expand Up @@ -1741,7 +1741,7 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo *
break;
case LLVMArgWasmVtypeAsScalar:
g_assert (ainfo->esize);
param_types [pindex ++] = LLVMIntType (ainfo->esize * 8);
param_types [pindex ++] = type_to_llvm_type (ctx, ainfo->etype);
break;
case LLVMArgGsharedvtFixed:
case LLVMArgGsharedvtFixedVtype:
Expand Down Expand Up @@ -4021,7 +4021,7 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder)
/* The argument is received as a scalar */
ctx->addresses [reg] = build_alloca_address (ctx, t);

LLVMValueRef dest = convert (ctx, ctx->addresses [reg]->value, pointer_type (LLVMIntType (ainfo->esize * 8)));
LLVMValueRef dest = convert (ctx, ctx->addresses [reg]->value, pointer_type (LLVMTypeOf (arg)));
LLVMBuildStore (ctx->builder, arg, dest);
break;
}
Expand Down Expand Up @@ -4684,7 +4684,7 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
break;
case LLVMArgWasmVtypeAsScalar: {
g_assert (addresses [reg]);
LLVMTypeRef etype = LLVMIntType (ainfo->esize * 8);
LLVMTypeRef etype = type_to_llvm_type (ctx, ainfo->etype);
args [pindex] = LLVMBuildLoad2 (ctx->builder, etype, convert (ctx, addresses [reg]->value, pointer_type (etype)), "");
break;
}
Expand Down
31 changes: 23 additions & 8 deletions src/mono/mono/mini/mini-wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ typedef enum {

typedef struct {
ArgStorage storage : 8;
MonoType *type;
MonoType *type, *etype;
} ArgInfo;

struct CallInfo {
Expand All @@ -49,7 +49,7 @@ struct CallInfo {
// WASM ABI: https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md

static ArgStorage
get_storage (MonoType *type, gboolean is_return)
get_storage (MonoType *type, MonoType **etype, gboolean is_return)
{
switch (type->type) {
case MONO_TYPE_I1:
Expand Down Expand Up @@ -84,7 +84,7 @@ get_storage (MonoType *type, gboolean is_return)
/* fall through */
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_TYPEDBYREF: {
if (mini_wasm_is_scalar_vtype (type))
if (mini_wasm_is_scalar_vtype (type, etype))
return ArgVtypeAsScalar;
return is_return ? ArgValuetypeAddrInIReg : ArgValuetypeAddrOnStack;
}
Expand Down Expand Up @@ -117,7 +117,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)

/* return value */
cinfo->ret.type = mini_get_underlying_type (sig->ret);
cinfo->ret.storage = get_storage (cinfo->ret.type, TRUE);
cinfo->ret.storage = get_storage (cinfo->ret.type, &cinfo->ret.etype, TRUE);

if (sig->hasthis)
cinfo->args [0].storage = ArgOnStack;
Expand All @@ -128,7 +128,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
int i;
for (i = 0; i < sig->param_count; ++i) {
cinfo->args [i + sig->hasthis].type = mini_get_underlying_type (sig->params [i]);
cinfo->args [i + sig->hasthis].storage = get_storage (cinfo->args [i + sig->hasthis].type, FALSE);
cinfo->args [i + sig->hasthis].storage = get_storage (cinfo->args [i + sig->hasthis].type, &cinfo->args [i + sig->hasthis].etype, FALSE);
}

return cinfo;
Expand Down Expand Up @@ -348,6 +348,7 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)

if (cinfo->ret.storage == ArgVtypeAsScalar) {
linfo->ret.storage = LLVMArgWasmVtypeAsScalar;
linfo->ret.etype = cinfo->ret.etype;
linfo->ret.esize = mono_class_value_size (mono_class_from_mono_type_internal (cinfo->ret.type), NULL);
} else if (mini_type_is_vtype (sig->ret)) {
/* Vtype returned using a hidden argument */
Expand All @@ -374,6 +375,7 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
case ArgVtypeAsScalar:
linfo->args [i].storage = LLVMArgWasmVtypeAsScalar;
linfo->args [i].type = ainfo->type;
linfo->args [i].etype = ainfo->etype;
linfo->args [i].esize = mono_class_value_size (mono_class_from_mono_type_internal (ainfo->type), NULL);
break;
case ArgValuetypeAddrInIReg:
Expand Down Expand Up @@ -739,19 +741,22 @@ mono_wasm_get_debug_level (void)

/* Return whenever TYPE represents a vtype with only one scalar member */
gboolean
mini_wasm_is_scalar_vtype (MonoType *type)
mini_wasm_is_scalar_vtype (MonoType *type, MonoType **etype)
{
MonoClass *klass;
MonoClassField *field;
gpointer iter;

if (etype)
*etype = NULL;

if (!MONO_TYPE_ISSTRUCT (type))
return FALSE;
klass = mono_class_from_mono_type_internal (type);
mono_class_init_internal (klass);

int size = mono_class_value_size (klass, NULL);
if (size == 0 || size >= 8)
if (size == 0 || size > 8)
return FALSE;

iter = NULL;
Expand All @@ -765,12 +770,22 @@ mini_wasm_is_scalar_vtype (MonoType *type)
return FALSE;
MonoType *t = mini_get_underlying_type (field->type);
if (MONO_TYPE_ISSTRUCT (t)) {
if (!mini_wasm_is_scalar_vtype (t))
if (!mini_wasm_is_scalar_vtype (t, etype))
return FALSE;
} else if (!((MONO_TYPE_IS_PRIMITIVE (t) || MONO_TYPE_IS_REFERENCE (t) || MONO_TYPE_IS_POINTER (t)))) {
return FALSE;
} else if (size == 8 && t->type != MONO_TYPE_R8) {
return FALSE;
} else {
if (etype)
*etype = t;
}
}

if (etype) {
if (!(*etype))
*etype = mono_get_int32_type ();
}

return TRUE;
}
2 changes: 1 addition & 1 deletion src/mono/mono/mini/mini-wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,6 @@ void mono_wasm_main_thread_schedule_timer (void *timerHandler, int shortestDueTi
void mono_wasm_print_stack_trace (void);

gboolean
mini_wasm_is_scalar_vtype (MonoType *type);
mini_wasm_is_scalar_vtype (MonoType *type, MonoType **etype);

#endif /* __MONO_MINI_WASM_H__ */
2 changes: 2 additions & 0 deletions src/mono/mono/mini/mini.h
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,8 @@ typedef struct {
/* Parameter index in the LLVM signature */
int pindex;
MonoType *type;
/* Only if storage == LLVMArgWasmVtypeAsScalar */
MonoType *etype;
/* Only if storage == LLVMArgAsFpArgs. Dummy fp args to insert before this arg */
int ndummy_fpargs;
} LLVMArgInfo;
Expand Down
Loading