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

[llvmonly] Emit stubs for methods which failed compilation. #32162

Merged
merged 1 commit into from
Feb 14, 2020
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
1 change: 1 addition & 0 deletions src/mono/mono/metadata/jit-icall-reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ MONO_JIT_ICALL (mini_llvmonly_resolve_generic_virtual_iface_call) \
MONO_JIT_ICALL (mini_llvmonly_resolve_iface_call_gsharedvt) \
MONO_JIT_ICALL (mini_llvmonly_resolve_vcall_gsharedvt) \
MONO_JIT_ICALL (mini_llvmonly_throw_nullref_exception) \
MONO_JIT_ICALL (mini_llvmonly_throw_missing_method_exception) \
MONO_JIT_ICALL (mono_amd64_resume_unwind) \
MONO_JIT_ICALL (mono_amd64_start_gsharedvt_call) \
MONO_JIT_ICALL (mono_amd64_throw_corlib_exception) \
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/mini/aot-runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "mini.h"

/* Version number of the AOT file format */
#define MONO_AOT_FILE_VERSION 172
#define MONO_AOT_FILE_VERSION 173

#define MONO_AOT_TRAMP_PAGE_SIZE 16384

Expand Down
12 changes: 12 additions & 0 deletions src/mono/mono/mini/llvmonly-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -843,3 +843,15 @@ mini_llvmonly_throw_nullref_exception (void)

mono_llvm_throw_corlib_exception (ex_token_index);
}

static GENERATE_GET_CLASS_WITH_CACHE (missing_method, "System", "MissingMethodException")

void
mini_llvmonly_throw_missing_method_exception (void)
{
MonoClass *klass = mono_class_get_missing_method_class ();

guint32 ex_token_index = m_class_get_type_token (klass) - MONO_TOKEN_TYPE_DEF;

mono_llvm_throw_corlib_exception (ex_token_index);
}
2 changes: 2 additions & 0 deletions src/mono/mono/mini/llvmonly-runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,6 @@ G_EXTERN_C void mini_llvm_init_gshared_method_vtable (MonoAotFileInfo *info, gp

G_EXTERN_C void mini_llvmonly_throw_nullref_exception (void);

G_EXTERN_C void mini_llvmonly_throw_missing_method_exception (void);

#endif
70 changes: 54 additions & 16 deletions src/mono/mono/mini/mini-llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -3771,16 +3771,11 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder)
* it needs to continue normally, or return back to the exception handling system.
*/
for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
int clause_index;
char name [128];

if (!(bb->region != -1 && (bb->flags & BB_EXCEPTION_HANDLER)))
continue;

clause_index = MONO_REGION_CLAUSE_INDEX (bb->region);
g_hash_table_insert (ctx->region_to_handler, GUINT_TO_POINTER (mono_get_block_region_notry (cfg, bb->region)), bb);
g_hash_table_insert (ctx->clause_to_handler, GINT_TO_POINTER (clause_index), bb);

if (bb->in_scount == 0) {
LLVMValueRef val;

Expand All @@ -3794,14 +3789,6 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder)
if (!ctx->ex_var)
ctx->ex_var = LLVMBuildAlloca (builder, ObjRefType (), "exvar");
}

/*
* Create a new bblock which CALL_HANDLER/landing pads can branch to, because branching to the
* LLVM bblock containing a landing pad causes problems for the
* LLVM optimizer passes.
*/
sprintf (name, "BB%d_CALL_HANDLER_TARGET", bb->block_num);
ctx->bblocks [bb->block_num].call_handler_target_bb = LLVMAppendBasicBlock (ctx->lmethod, name);
}
ctx->builder = old_builder;
}
Expand Down Expand Up @@ -8513,6 +8500,7 @@ emit_method_inner (EmitContext *ctx)
LLVMValueRef *values = ctx->values;
int i, max_block_num, bb_index;
gboolean last = FALSE;
gboolean llvmonly_fail = FALSE;
LLVMCallInfo *linfo;
LLVMModuleRef lmodule = ctx->lmodule;
BBInfo *bblocks;
Expand Down Expand Up @@ -8679,8 +8667,14 @@ emit_method_inner (EmitContext *ctx)
for (i = 0; i < header->num_clauses; ++i) {
clause = &header->clauses [i];
if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY && clause->flags != MONO_EXCEPTION_CLAUSE_FAULT && clause->flags != MONO_EXCEPTION_CLAUSE_NONE) {
set_failure (ctx, "non-finally/catch/fault clause.");
return;
if (cfg->llvm_only) {
// FIXME: Treat unhandled opcodes like __arglist the same way
// It would require deleting the already emitted code
llvmonly_fail = TRUE;
} else {
set_failure (ctx, "non-finally/catch/fault clause.");
return;
}
}
}
if (header->num_clauses || (cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_NOINLINING) || cfg->no_inline)
Expand Down Expand Up @@ -8875,6 +8869,33 @@ emit_method_inner (EmitContext *ctx)
LLVMPositionBuilderAtEnd (entry_builder, entry_bb);
emit_entry_bb (ctx, entry_builder);

if (llvmonly_fail)
/*
* In llvmonly mode, we want to emit an llvm method for every method even if it fails to compile,
* so direct calls can be made from outside the assembly.
*/
goto after_codegen_1;

for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
int clause_index;
char name [128];

if (!(bb->region != -1 && (bb->flags & BB_EXCEPTION_HANDLER)))
continue;

clause_index = MONO_REGION_CLAUSE_INDEX (bb->region);
g_hash_table_insert (ctx->region_to_handler, GUINT_TO_POINTER (mono_get_block_region_notry (cfg, bb->region)), bb);
g_hash_table_insert (ctx->clause_to_handler, GINT_TO_POINTER (clause_index), bb);

/*
* Create a new bblock which CALL_HANDLER/landing pads can branch to, because branching to the
* LLVM bblock containing a landing pad causes problems for the
* LLVM optimizer passes.
*/
sprintf (name, "BB%d_CALL_HANDLER_TARGET", bb->block_num);
ctx->bblocks [bb->block_num].call_handler_target_bb = LLVMAppendBasicBlock (ctx->lmethod, name);
}

// Make landing pads first
ctx->exc_meta = g_hash_table_new_full (NULL, NULL, NULL, NULL);

Expand Down Expand Up @@ -8994,6 +9015,24 @@ emit_method_inner (EmitContext *ctx)

ctx->module->max_method_idx = MAX (ctx->module->max_method_idx, cfg->method_index);

after_codegen_1:

if (llvmonly_fail) {
/*
* FIXME: Maybe fallback to interpreter
*/
static LLVMTypeRef sig;

ctx->builder = create_builder (ctx);
LLVMPositionBuilderAtEnd (ctx->builder, ctx->inited_bb);

if (!sig)
sig = LLVMFunctionType0 (LLVMVoidType (), FALSE);
LLVMValueRef callee = get_callee (ctx, sig, MONO_PATCH_INFO_JIT_ICALL_ADDR, GUINT_TO_POINTER (MONO_JIT_ICALL_mini_llvmonly_throw_missing_method_exception));
LLVMBuildCall (ctx->builder, callee, NULL, 0, "");
LLVMBuildUnreachable (ctx->builder);
}

/* Initialize the method if needed */
if (cfg->compile_aot && !ctx->module->llvm_disable_self_init) {
// FIXME: Add more shared got entries
Expand Down Expand Up @@ -9036,7 +9075,6 @@ emit_method_inner (EmitContext *ctx)
if (mini_get_debug_options ()->llvm_disable_inlining)
mono_llvm_add_func_attr (method, LLVM_ATTR_NO_INLINE);


after_codegen:
if (cfg->llvm_only) {
g_ptr_array_add (ctx->module->cfgs, cfg);
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/mini-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -4667,6 +4667,7 @@ register_icalls (void)
register_icall (mini_llvmonly_init_delegate, mono_icall_sig_void_object, TRUE);
register_icall (mini_llvmonly_init_delegate_virtual, mono_icall_sig_void_object_object_ptr, TRUE);
register_icall (mini_llvmonly_throw_nullref_exception, mono_icall_sig_void, TRUE);
register_icall (mini_llvmonly_throw_missing_method_exception, mono_icall_sig_void, TRUE);

register_icall (mono_get_assembly_object, mono_icall_sig_object_ptr, TRUE);
register_icall (mono_get_method_object, mono_icall_sig_object_ptr, TRUE);
Expand Down