diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index aef7f438238d33..57cd057ee82b5c 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -1367,15 +1367,27 @@ mono_create_rgctx_var (MonoCompile *cfg) if (!cfg->rgctx_var) { cfg->rgctx_var = mono_compile_create_var (cfg, mono_get_int_type (), OP_LOCAL); /* force the var to be stack allocated */ - cfg->rgctx_var->flags |= MONO_INST_VOLATILE; + if (!cfg->llvm_only) + cfg->rgctx_var->flags |= MONO_INST_VOLATILE; } } +static MonoInst * +mono_get_mrgctx_var (MonoCompile *cfg) +{ + g_assert (cfg->gshared); + + mono_create_rgctx_var (cfg); + + return cfg->rgctx_var; +} + static MonoInst * mono_get_vtable_var (MonoCompile *cfg) { g_assert (cfg->gshared); + /* The mrgctx and the vtable are stored in the same var */ mono_create_rgctx_var (cfg); return cfg->rgctx_var; @@ -2467,17 +2479,27 @@ emit_get_rgctx (MonoCompile *cfg, int context_used) g_assert (method->is_inflated && mono_method_get_context (method)->method_inst); } - mrgctx_loc = mono_get_vtable_var (cfg); - EMIT_NEW_TEMPLOAD (cfg, mrgctx_var, mrgctx_loc->inst_c0); - + if (cfg->llvm_only) { + mrgctx_var = mono_get_mrgctx_var (cfg); + } else { + /* Volatile */ + mrgctx_loc = mono_get_mrgctx_var (cfg); + g_assert (mrgctx_loc->flags & MONO_INST_VOLATILE); + EMIT_NEW_TEMPLOAD (cfg, mrgctx_var, mrgctx_loc->inst_c0); + } return mrgctx_var; } else if (method->flags & METHOD_ATTRIBUTE_STATIC || m_class_is_valuetype (method->klass)) { MonoInst *vtable_loc, *vtable_var; g_assert (!this_ins); - vtable_loc = mono_get_vtable_var (cfg); - EMIT_NEW_TEMPLOAD (cfg, vtable_var, vtable_loc->inst_c0); + if (cfg->llvm_only) { + vtable_var = mono_get_vtable_var (cfg); + } else { + vtable_loc = mono_get_vtable_var (cfg); + g_assert (vtable_loc->flags & MONO_INST_VOLATILE); + EMIT_NEW_TEMPLOAD (cfg, vtable_var, vtable_loc->inst_c0); + } if (method->is_inflated && mono_method_get_context (method)->method_inst) { MonoInst *mrgctx_var = vtable_var; diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 77a7c1c38ee695..3ba22d6cf7b503 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -3447,7 +3447,7 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder) #ifdef TARGET_WASM // For GC stack scanning to work, have to spill all reference variables to the stack // Some ref variables have type intptr - if (ctx->has_safepoints && (MONO_TYPE_IS_REFERENCE (var->inst_vtype) || var->inst_vtype->type == MONO_TYPE_I)) + if (ctx->has_safepoints && (MONO_TYPE_IS_REFERENCE (var->inst_vtype) || var->inst_vtype->type == MONO_TYPE_I) && var != ctx->cfg->rgctx_var) var->flags |= MONO_INST_INDIRECT; #endif @@ -3601,7 +3601,7 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder) if (!mini_type_is_vtype (sig->params [i])) emit_volatile_store (ctx, cfg->args [i + sig->hasthis]->dreg); - if (sig->hasthis && !cfg->rgctx_var && cfg->gshared) { + if (sig->hasthis && !cfg->rgctx_var && cfg->gshared && !cfg->llvm_only) { LLVMValueRef this_alloc; /* @@ -3618,17 +3618,23 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder) } if (cfg->rgctx_var) { - LLVMValueRef rgctx_alloc, store; + if (!(cfg->rgctx_var->flags & MONO_INST_VOLATILE)) { + /* FIXME: This could be volatile even in llvmonly mode if used inside a clause etc. */ + g_assert (!ctx->addresses [cfg->rgctx_var->dreg]); + ctx->values [cfg->rgctx_var->dreg] = ctx->rgctx_arg; + } else { + LLVMValueRef rgctx_alloc, store; - /* - * We handle the rgctx arg similarly to the this pointer. - */ - g_assert (ctx->addresses [cfg->rgctx_var->dreg]); - rgctx_alloc = ctx->addresses [cfg->rgctx_var->dreg]; - /* This volatile store will keep the alloca alive */ - store = mono_llvm_build_store (builder, convert (ctx, ctx->rgctx_arg, IntPtrType ()), rgctx_alloc, TRUE, LLVM_BARRIER_NONE); + /* + * We handle the rgctx arg similarly to the this pointer. + */ + g_assert (ctx->addresses [cfg->rgctx_var->dreg]); + rgctx_alloc = ctx->addresses [cfg->rgctx_var->dreg]; + /* This volatile store will keep the alloca alive */ + store = mono_llvm_build_store (builder, convert (ctx, ctx->rgctx_arg, IntPtrType ()), rgctx_alloc, TRUE, LLVM_BARRIER_NONE); - set_metadata_flag (rgctx_alloc, "mono.this"); + set_metadata_flag (rgctx_alloc, "mono.this"); + } } /* Initialize the method if needed */ @@ -4323,9 +4329,13 @@ mono_llvm_emit_match_exception_call (EmitContext *ctx, LLVMBuilderRef builder, g args [1] = LLVMConstInt (LLVMInt32Type (), region_start, 0); args [2] = LLVMConstInt (LLVMInt32Type (), region_end, 0); if (ctx->cfg->rgctx_var) { - LLVMValueRef rgctx_alloc = ctx->addresses [ctx->cfg->rgctx_var->dreg]; - g_assert (rgctx_alloc); - args [3] = LLVMBuildLoad (builder, convert (ctx, rgctx_alloc, LLVMPointerType (IntPtrType (), 0)), ""); + if (ctx->cfg->llvm_only) { + args [3] = convert (ctx, ctx->rgctx_arg, IntPtrType ()); + } else { + LLVMValueRef rgctx_alloc = ctx->addresses [ctx->cfg->rgctx_var->dreg]; + g_assert (rgctx_alloc); + args [3] = LLVMBuildLoad (builder, convert (ctx, rgctx_alloc, LLVMPointerType (IntPtrType (), 0)), ""); + } } else { args [3] = LLVMConstInt (IntPtrType (), 0, 0); } diff --git a/src/mono/mono/mini/mini.h b/src/mono/mono/mini/mini.h index b7d70c2ffcb336..dccb37d51deed5 100644 --- a/src/mono/mono/mini/mini.h +++ b/src/mono/mono/mini/mini.h @@ -1287,7 +1287,8 @@ typedef struct { MonoInst *domainvar; /* a cache for the current domain */ MonoInst *got_var; /* Global Offset Table variable */ MonoInst **locals; - MonoInst *rgctx_var; /* Runtime generic context variable (for static generic methods) */ + /* Variable holding the mrgctx/vtable address for gshared methods */ + MonoInst *rgctx_var; MonoInst **args; MonoType **arg_types; MonoMethod *current_method; /* The method currently processed by method_to_ir () */