[llvm] Implement support for GC_SAFE_POINT.
authorZoltan Varga <vargaz@gmail.com>
Wed, 26 Aug 2015 18:47:24 +0000 (14:47 -0400)
committerZoltan Varga <vargaz@gmail.com>
Wed, 26 Aug 2015 18:47:28 +0000 (14:47 -0400)
mono/mini/mini-llvm.c

index af00dcd9841a504a4cfcc938128f3dbb4f0ba59e..ee281f871157c9c5538aaad068bb2a874cb59e5a 100644 (file)
@@ -45,7 +45,7 @@ void bzero (void *to, size_t count) { memset (to, 0, count); }
   */
 typedef struct {
        LLVMModuleRef module;
-       LLVMValueRef throw, rethrow, throw_corlib_exception;
+       LLVMValueRef throw, rethrow, throw_corlib_exception, state_poll;
        GHashTable *llvm_types;
        LLVMValueRef got_var;
        const char *got_symbol;
@@ -4725,6 +4725,61 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
 
                case OP_DUMMY_USE:
                        break;
+               case OP_GC_SAFE_POINT: {
+                       LLVMValueRef callee, cmp, val;
+                       LLVMTypeRef llvm_sig;
+                       const char *icall_name;
+                       LLVMBasicBlockRef poll_bb, cont_bb;
+
+                       poll_bb = gen_bb (ctx, "POLL_BB");
+                       cont_bb = gen_bb (ctx, "NOPOLL_BB");
+
+                       val = LLVMBuildLoad (ctx->builder, convert (ctx, lhs, LLVMPointerType (LLVMInt8Type (), 0)), "");
+                       cmp = LLVMBuildICmp (builder, LLVMIntEQ, val, LLVMConstInt (LLVMTypeOf (val), 0, FALSE), "");
+                       LLVMBuildCondBr (ctx->builder, cmp, cont_bb, poll_bb);
+
+                       builder = ctx->builder = create_builder (ctx);
+                       LLVMPositionBuilderAtEnd (builder, poll_bb);
+
+                       MonoMethodSignature *sig = mono_metadata_signature_alloc (mono_get_corlib (), 0);
+                       sig->ret = &mono_get_void_class ()->byval_arg;
+                       icall_name = "mono_threads_state_poll";
+                       llvm_sig = sig_to_llvm_sig (ctx, sig);
+
+                       if (ctx->cfg->compile_aot) {
+                               callee = ctx->lmodule->state_poll;
+                               if (!callee) {
+                                       MonoMethodSignature *sig = mono_metadata_signature_alloc (mono_get_corlib (), 0);
+                                       sig->ret = &mono_get_void_class ()->byval_arg;
+                                       llvm_sig = sig_to_llvm_sig (ctx, sig);
+
+                                       callee = get_plt_entry (ctx, llvm_sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
+                               }
+                       } else {
+                               callee = ctx->lmodule->state_poll;
+                               if (!callee) {
+                                       MonoMethodSignature *sig = mono_metadata_signature_alloc (mono_get_corlib (), 0);
+                                       sig->ret = &mono_get_void_class ()->byval_arg;
+                                       llvm_sig = sig_to_llvm_sig (ctx, sig);
+
+                                       callee = LLVMAddFunction (ctx->module, icall_name, llvm_sig);
+                                       LLVMAddGlobalMapping (ctx->lmodule->ee, callee, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name));
+                                       ctx->lmodule->state_poll = callee;
+                               }
+                       }
+                       //
+                       // FIXME: This can use the PreserveAll cconv to avoid clobbering registers.
+                       // It requires the wrapper to also use that calling convention.
+                       //
+                       val = emit_call (ctx, bb, &builder, callee, NULL, 0);
+                       LLVMBuildBr (builder, cont_bb);
+
+                       builder = ctx->builder = create_builder (ctx);
+                       LLVMPositionBuilderAtEnd (builder, cont_bb);
+
+                       bblocks [bb->block_num].end_bblock = cont_bb;
+                       break;
+               }
 
                        /*
                         * EXCEPTION HANDLING