if (type->byref)
return OP_MOVE;
- type = mini_replace_type (type);
+ type = mini_get_underlying_type (cfg, type);
handle_enum:
switch (type->type) {
case MONO_TYPE_I1:
{
MonoClass *klass;
- type = mini_replace_type (type);
+ type = mini_get_underlying_type (cfg, type);
inst->klass = klass = mono_class_from_mono_type (type);
if (type->byref) {
inst->type = STACK_MP;
static int
ret_type_to_call_opcode (MonoCompile *cfg, MonoType *type, int calli, int virt, MonoGenericSharingContext *gsctx)
{
- if (type->byref)
- return calli? OP_CALL_REG: virt? OP_CALL_MEMBASE: OP_CALL;
-
handle_enum:
- type = mini_get_basic_type_from_generic (gsctx, type);
- type = mini_replace_type (type);
+ type = mini_get_underlying_type (cfg, type);
switch (type->type) {
case MONO_TYPE_VOID:
return calli? OP_VOIDCALL_REG: virt? OP_VOIDCALL_MEMBASE: OP_VOIDCALL;
MonoType *simple_type;
MonoClass *klass;
- target = mini_replace_type (target);
if (target->byref) {
/* FIXME: check that the pointed to types match */
if (arg->type == STACK_MP)
return 1;
}
- simple_type = mono_type_get_underlying_type (target);
+ simple_type = mini_get_underlying_type (cfg, target);
switch (simple_type->type) {
case MONO_TYPE_VOID:
return 1;
call->args = args;
call->signature = sig;
call->rgctx_reg = rgctx;
- sig_ret = mini_replace_type (sig->ret);
+ sig_ret = mini_get_underlying_type (cfg, sig->ret);
type_to_eval_stack_type ((cfg), sig_ret, &call->inst);
MonoInst *ins;
int t;
- rtype = mini_replace_type (rtype);
+ rtype = mini_get_underlying_type (cfg, rtype);
t = rtype->type;
if (rtype->byref) {
{
int t;
- rtype = mini_replace_type (rtype);
+ rtype = mini_get_underlying_type (cfg, rtype);
t = rtype->type;
if (rtype->byref) {
token = read32 (ip + 2);
klass = mini_get_class (cfg->current_method, token, cfg->generic_context);
CHECK_TYPELOAD (klass);
- type = mini_replace_type (&klass->byval_arg);
+ type = mini_get_underlying_type (cfg, &klass->byval_arg);
emit_init_local (cfg, local, type, TRUE);
return ip + 6;
}
emit_pop_lmf (cfg);
if (cfg->ret) {
- MonoType *ret_type = mini_replace_type (mono_method_signature (method)->ret);
+ MonoType *ret_type = mini_get_underlying_type (cfg, mono_method_signature (method)->ret);
if (seq_points && !sym_seq_points) {
/*
c1 = get_call_info (NULL, NULL, caller_sig);
c2 = get_call_info (NULL, NULL, callee_sig);
res = c1->stack_usage >= c2->stack_usage;
- callee_ret = mini_replace_type (callee_sig->ret);
+ callee_ret = mini_get_underlying_type (cfg, callee_sig->ret);
if (callee_ret && MONO_TYPE_ISSTRUCT (callee_ret) && c2->ret.storage != ArgValuetypeInReg)
/* An address on the callee's stack is passed as the first argument */
res = FALSE;
sig = mono_method_signature (cfg->method);
cinfo = cfg->arch.cinfo;
- sig_ret = mini_replace_type (sig->ret);
+ sig_ret = mini_get_underlying_type (cfg, sig->ret);
/*
* Contrary to mono_arch_allocate_vars (), the information should describe
sig = mono_method_signature (cfg->method);
cinfo = cfg->arch.cinfo;
- sig_ret = mini_replace_type (sig->ret);
+ sig_ret = mini_get_underlying_type (cfg, sig->ret);
mono_arch_compute_omit_fp (cfg);
if (cinfo->ret.storage == ArgValuetypeInReg)
cfg->ret_var_is_local = TRUE;
- sig_ret = mini_replace_type (sig->ret);
+ sig_ret = mini_get_underlying_type (cfg, sig->ret);
if ((cinfo->ret.storage != ArgValuetypeInReg) && MONO_TYPE_ISSTRUCT (sig_ret)) {
cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
if (G_UNLIKELY (cfg->verbose_level > 1)) {
MonoType *t, *sig_ret;
n = sig->param_count + sig->hasthis;
- sig_ret = mini_replace_type (sig->ret);
+ sig_ret = mini_get_underlying_type (cfg, sig->ret);
cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (n == sig->sentinelpos))
emit_sig_cookie (cfg, call, cinfo);
- sig_ret = mini_replace_type (sig->ret);
+ sig_ret = mini_get_underlying_type (cfg, sig->ret);
if (sig_ret && MONO_TYPE_ISSTRUCT (sig_ret)) {
MonoInst *vtarg;
void
mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
{
- MonoType *ret = mini_replace_type (mono_method_signature (method)->ret);
+ MonoType *ret = mini_get_underlying_type (cfg, mono_method_signature (method)->ret);
if (ret->type == MONO_TYPE_R4) {
if (COMPILE_LLVM (cfg))
guchar *code = p;
int save_mode = SAVE_NONE;
MonoMethod *method = cfg->method;
- MonoType *ret_type = mini_replace_type (mono_method_signature (method)->ret);
+ MonoType *ret_type = mini_get_underlying_type (cfg, mono_method_signature (method)->ret);
int i;
switch (ret_type->type) {
* the extra stack space would be left on the stack after the tail call.
*/
res = c1->stack_usage >= c2->stack_usage;
- callee_ret = mini_replace_type (callee_sig->ret);
+ callee_ret = mini_get_underlying_type (cfg, callee_sig->ret);
if (callee_ret && MONO_TYPE_ISSTRUCT (callee_ret) && c2->ret.storage != RegTypeStructByVal)
/* An address on the callee's stack is passed as the first argument */
res = FALSE;
if (!cfg->arch.cinfo)
cfg->arch.cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
cinfo = cfg->arch.cinfo;
- sig_ret = mini_replace_type (sig->ret);
+ sig_ret = mini_get_underlying_type (cfg, sig->ret);
mono_arch_compute_omit_fp (cfg);
static LLVMTypeRef
type_to_llvm_type (EmitContext *ctx, MonoType *t)
{
- t = mini_replace_type (t);
-
if (t->byref)
return LLVMPointerType (LLVMInt8Type (), 0);
+
+ t = mini_get_underlying_type (ctx->cfg, t);
switch (t->type) {
case MONO_TYPE_VOID:
return LLVMVoidType ();
if (sinfo)
memset (sinfo, 0, sizeof (LLVMSigInfo));
- rtype = mini_replace_type (sig->ret);
+ rtype = mini_get_underlying_type (ctx->cfg, sig->ret);
ret_type = type_to_llvm_type (ctx, rtype);
CHECK_FAILURE (ctx);
/* Special case structs with only a float member */
if (info->num_fields == 1) {
- int ftype = mini_replace_type (info->fields [0].field->type)->type;
+ int ftype = mini_type_get_underlying_type (gsctx, info->fields [0].field->type)->type;
if ((info->native_size == 8) && (ftype == MONO_TYPE_R8)) {
ainfo->storage = ArgValuetypeInReg;
ainfo->pair_storage [0] = ArgOnDoubleFpStack;
* the extra stack space would be left on the stack after the tail call.
*/
res = c1->stack_usage >= c2->stack_usage;
- callee_ret = mini_replace_type (callee_sig->ret);
+ callee_ret = mini_get_underlying_type (cfg, callee_sig->ret);
if (callee_ret && MONO_TYPE_ISSTRUCT (callee_ret) && c2->ret.storage != ArgValuetypeInReg)
/* An address on the callee's stack is passed as the first argument */
res = FALSE;
sig = mono_method_signature (cfg->method);
cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
- sig_ret = mini_replace_type (sig->ret);
+ sig_ret = mini_get_underlying_type (cfg, sig->ret);
if (cinfo->ret.storage == ArgValuetypeInReg)
cfg->ret_var_is_local = TRUE;
sig = call->signature;
n = sig->param_count + sig->hasthis;
- sig_ret = mini_replace_type (sig->ret);
+ sig_ret = mini_get_underlying_type (cfg, sig->ret);
cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
call->call_info = cinfo;
guint
mono_type_to_store_membase (MonoCompile *cfg, MonoType *type)
{
- if (type->byref)
- return OP_STORE_MEMBASE_REG;
-
- type = mini_replace_type (type);
+ type = mini_get_underlying_type (cfg, type);
handle_enum:
switch (type->type) {
goto handle_enum;
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
- if (mini_type_var_is_vt (cfg, type))
- return OP_STOREV_MEMBASE;
- else
- return OP_STORE_MEMBASE_REG;
+ g_assert (mini_type_var_is_vt (cfg, type));
+ return OP_STOREV_MEMBASE;
default:
g_error ("unknown type 0x%02x in type_to_store_membase", type->type);
}
guint
mono_type_to_load_membase (MonoCompile *cfg, MonoType *type)
{
- if (type->byref)
- return OP_LOAD_MEMBASE;
-
- type = mini_replace_type (type);
+ type = mini_get_underlying_type (cfg, type);
switch (type->type) {
case MONO_TYPE_I1:
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
g_assert (cfg->generic_sharing_context);
- if (mini_type_var_is_vt (cfg, type))
- return OP_LOADV_MEMBASE;
- else
- return OP_LOAD_MEMBASE;
+ g_assert (mini_type_var_is_vt (cfg, type));
+ return OP_LOADV_MEMBASE;
default:
g_error ("unknown type 0x%02x in type_to_load_membase", type->type);
}
static guint
mini_type_to_ldind (MonoCompile* cfg, MonoType *type)
{
- if (cfg->generic_sharing_context && !type->byref) {
- if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) {
- if (mini_type_var_is_vt (cfg, type))
- return CEE_LDOBJ;
- else
- return CEE_LDIND_REF;
- }
+ type = mini_get_underlying_type (cfg, type);
+ if (cfg->generic_sharing_context && !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
+ g_assert (mini_type_var_is_vt (cfg, type));
+ return CEE_LDOBJ;
}
return mono_type_to_ldind (type);
}
guint
mini_type_to_stind (MonoCompile* cfg, MonoType *type)
{
- type = mini_replace_type (type);
-
- if (cfg->generic_sharing_context && !type->byref) {
- if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) {
- if (mini_type_var_is_vt (cfg, type))
- return CEE_STOBJ;
- else
- return CEE_STIND_REF;
- }
+ type = mini_get_underlying_type (cfg, type);
+ if (cfg->generic_sharing_context && !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
+ g_assert (mini_type_var_is_vt (cfg, type));
+ return CEE_STOBJ;
}
return mono_type_to_stind (type);
}
int num = cfg->num_varinfo;
gboolean regpair;
- type = mini_replace_type (type);
+ type = mini_get_underlying_type (cfg, type);
if ((num + 1) >= cfg->varinfo_count) {
int orig_count = cfg->varinfo_count;
if (type->byref) {
mono_mark_vreg_as_mp (cfg, vreg);
} else {
- MonoType *t = mini_replace_type (type);
- if ((MONO_TYPE_ISSTRUCT (t) && inst->klass->has_references) || mini_type_is_reference (cfg, t)) {
+ if ((MONO_TYPE_ISSTRUCT (type) && inst->klass->has_references) || mini_type_is_reference (cfg, type)) {
inst->flags |= MONO_INST_GC_TRACK;
mono_mark_vreg_as_ref (cfg, vreg);
}
mono_compile_create_var (MonoCompile *cfg, MonoType *type, int opcode)
{
int dreg;
- type = mini_replace_type (type);
+ type = mini_get_underlying_type (cfg, type);
if (mono_type_is_long (type))
dreg = mono_alloc_dreg (cfg, STACK_I8);
* Transform a MonoInst into a load from the variable of index var_index.
*/
void
-mono_compile_make_var_load (MonoCompile *cfg, MonoInst *dest, gssize var_index) {
+mono_compile_make_var_load (MonoCompile *cfg, MonoInst *dest, gssize var_index)
+{
memset (dest, 0, sizeof (MonoInst));
dest->inst_i0 = cfg->varinfo [var_index];
dest->opcode = mini_type_to_ldind (cfg, dest->inst_i0->inst_vtype);
return mini_native_type_replace_type (type);
}
+/*
+ * mini_get_underlying_type:
+ *
+ * Return the type the JIT will use during compilation.
+ * Handles: byref, enums, native types, generic sharing.
+ * For gsharedvt types, it will return the original VAR/MVAR.
+ */
+MonoType*
+mini_get_underlying_type (MonoCompile *cfg, MonoType *type)
+{
+ type = mini_type_get_underlying_type (cfg->generic_sharing_context, type);
+ return mini_native_type_replace_type (type);
+}
+
void
mini_jit_init (void)
{
MonoGenericContext* mini_class_get_context (MonoClass *class) MONO_INTERNAL;
MonoType* mini_replace_type (MonoType *type) MONO_LLVM_INTERNAL;
+MonoType* mini_get_underlying_type (MonoCompile *cfg, MonoType *type) MONO_LLVM_INTERNAL;
MonoType* mini_get_basic_type_from_generic (MonoGenericSharingContext *gsctx, MonoType *type) MONO_INTERNAL;
MonoType* mini_type_get_underlying_type (MonoGenericSharingContext *gsctx, MonoType *type) MONO_INTERNAL;
MonoMethod* mini_get_shared_method (MonoMethod *method) MONO_INTERNAL;