{
MonoInst *vtable_arg;
int context_used;
+ gboolean use_op_generic_class_init = FALSE;
*out_bblock = cfg->cbb;
}
#ifdef MONO_ARCH_HAVE_OP_GENERIC_CLASS_INIT
- MonoInst *ins;
+ if (!COMPILE_LLVM (cfg))
+ use_op_generic_class_init = TRUE;
+#endif
- /*
- * Using an opcode instead of emitting IR here allows the hiding of the call inside the opcode,
- * so this doesn't have to clobber any regs and it doesn't break basic blocks.
- */
- /*
- * For LLVM, this requires that the code in the generic trampoline obtain the vtable argument according to
- * the normal calling convention of the platform.
- */
- MONO_INST_NEW (cfg, ins, OP_GENERIC_CLASS_INIT);
- ins->sreg1 = vtable_arg->dreg;
- MONO_ADD_INS (cfg->cbb, ins);
-#else
- static int byte_offset = -1;
- static guint8 bitmask;
- int bits_reg, inited_reg;
- MonoBasicBlock *inited_bb;
- MonoInst *args [16];
+ if (use_op_generic_class_init) {
+ MonoInst *ins;
- if (byte_offset < 0)
- mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
+ /*
+ * Using an opcode instead of emitting IR here allows the hiding of the call inside the opcode,
+ * so this doesn't have to clobber any regs and it doesn't break basic blocks.
+ */
+ MONO_INST_NEW (cfg, ins, OP_GENERIC_CLASS_INIT);
+ ins->sreg1 = vtable_arg->dreg;
+ MONO_ADD_INS (cfg->cbb, ins);
+ } else {
+ static int byte_offset = -1;
+ static guint8 bitmask;
+ int bits_reg, inited_reg;
+ MonoBasicBlock *inited_bb;
+ MonoInst *args [16];
- bits_reg = alloc_ireg (cfg);
- inited_reg = alloc_ireg (cfg);
+ if (byte_offset < 0)
+ mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU1_MEMBASE, bits_reg, vtable_arg->dreg, byte_offset);
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, inited_reg, bits_reg, bitmask);
+ bits_reg = alloc_ireg (cfg);
+ inited_reg = alloc_ireg (cfg);
- NEW_BBLOCK (cfg, inited_bb);
+ MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU1_MEMBASE, bits_reg, vtable_arg->dreg, byte_offset);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, inited_reg, bits_reg, bitmask);
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, inited_reg, 0);
- MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, inited_bb);
+ NEW_BBLOCK (cfg, inited_bb);
- args [0] = vtable_arg;
- mono_emit_jit_icall (cfg, mono_generic_class_init, args);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, inited_reg, 0);
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, inited_bb);
- MONO_START_BB (cfg, inited_bb);
- *out_bblock = inited_bb;
-#endif
+ args [0] = vtable_arg;
+ mono_emit_jit_icall (cfg, mono_generic_class_init, args);
+
+ MONO_START_BB (cfg, inited_bb);
+ *out_bblock = inited_bb;
+ }
}
CHECK_FAILURE (ctx);
break;
}
- case OP_GENERIC_CLASS_INIT: {
- static int byte_offset = -1;
- static guint8 bitmask;
- LLVMValueRef flags_load, cmp;
- MonoMethodSignature *sig;
- const char *icall_name;
- LLVMValueRef callee;
- LLVMBasicBlockRef init_bb, noinit_bb;
- LLVMValueRef args [16];
-
- if (byte_offset < 0)
- mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
-
- flags_load = emit_load (ctx, bb, &builder, 1, convert (ctx, lhs, LLVMPointerType (LLVMInt8Type(), 0)), "", FALSE);
- set_metadata_flag (flags_load, "mono.nofail.load");
- cmp = LLVMBuildICmp (builder, LLVMIntEQ, LLVMBuildAnd (builder, flags_load, LLVMConstInt (LLVMInt8Type (), bitmask, 0), ""), LLVMConstInt (LLVMInt8Type (), 1, FALSE), "");
-
- callee = ctx->lmodule->generic_class_init_tramp;
- if (!callee) {
- icall_name = "specific_trampoline_generic_class_init";
- sig = mono_metadata_signature_alloc (mono_get_corlib (), 1);
- sig->ret = &mono_get_void_class ()->byval_arg;
- sig->params [0] = &mono_get_intptr_class ()->byval_arg;
- if (cfg->compile_aot) {
- callee = get_plt_entry (ctx, sig_to_llvm_sig (ctx, sig), MONO_PATCH_INFO_INTERNAL_METHOD, icall_name);
- } else {
- callee = LLVMAddFunction (module, icall_name, sig_to_llvm_sig (ctx, sig));
- LLVMAddGlobalMapping (ctx->lmodule->ee, callee, resolve_patch (cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name));
- }
- mono_memory_barrier ();
- ctx->lmodule->generic_class_init_tramp = callee;
- }
-
- init_bb = gen_bb (ctx, "INIT_BB");
- noinit_bb = gen_bb (ctx, "NOINIT_BB");
-
- LLVMBuildCondBr (ctx->builder, cmp, noinit_bb, init_bb);
-
- builder = create_builder (ctx);
- ctx->builder = builder;
- LLVMPositionBuilderAtEnd (builder, init_bb);
- args [0] = convert (ctx, lhs, IntPtrType ());
- emit_call (ctx, bb, &builder, callee, args, 1);
- LLVMBuildBr (builder, noinit_bb);
-
- builder = create_builder (ctx);
- ctx->builder = builder;
- LLVMPositionBuilderAtEnd (builder, noinit_bb);
-
- ctx->bblocks [bb->block_num].end_bblock = noinit_bb;
- break;
- }
case OP_AOTCONST: {
guint32 got_offset;
LLVMValueRef indexes [2];