return res;
}
+/**
+ * mono_pmip:
+ * @ip: an instruction pointer address
+ *
+ * This method is used from a debugger to get the name of the
+ * method at address @ip. This routine is typically invoked from
+ * a debugger like this:
+ *
+ * (gdb) print mono_pmip ($pc)
+ *
+ * Returns: the name of the method at address @ip.
+ */
G_GNUC_UNUSED char *
mono_pmip (void *ip)
{
return get_method_from_ip (ip);
}
-/* debug function */
+/**
+ * mono_print_method_from_ip
+ * @ip: an instruction pointer address
+ *
+ * This method is used from a debugger to get the name of the
+ * method at address @ip.
+ *
+ * This prints the name of the method at address @ip in the standard
+ * output. Unlike mono_pmip which returns a string, this routine
+ * prints the value on the standard output.
+ */
void
mono_print_method_from_ip (void *ip)
{
return ((i + 1) << 8) | MONO_REGION_FILTER | clause->flags;
if (MONO_OFFSET_IN_HANDLER (clause, offset)) {
- if (clause->flags & MONO_EXCEPTION_CLAUSE_FINALLY)
+ if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY)
return ((i + 1) << 8) | MONO_REGION_FINALLY | clause->flags;
- else
+ else if (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT)
+ return ((i + 1) << 8) | MONO_REGION_FAULT | clause->flags;
+ else if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE)
return ((i + 1) << 8) | MONO_REGION_CATCH | clause->flags;
}
}
/* handles from CEE_CEQ to CEE_CLT_UN */
static const guint16
ceqops_op_map [STACK_MAX] = {
- 0, 0, OP_LCEQ-CEE_CEQ, OP_PCEQ-CEE_CEQ, OP_FCEQ-CEE_CEQ, OP_LCEQ-CEE_CEQ
+ 0, 0, OP_LCEQ-OP_CEQ, OP_PCEQ-OP_CEQ, OP_FCEQ-OP_CEQ, OP_LCEQ-OP_CEQ
};
/*
ins->opcode = OP_LCOMPARE;
return;
case OP_CEQ:
+ ins->type = bin_comp_table [ins->inst_i0->type] [ins->inst_i1->type] ? STACK_I4: STACK_INV;
+ ins->opcode += ceqops_op_map [ins->inst_i0->type];
+ return;
+
case OP_CGT:
case OP_CGT_UN:
case OP_CLT:
case OP_CLT_UN:
- ins->type = bin_comp_table [ins->inst_i0->type] [ins->inst_i1->type] ? STACK_I4: STACK_INV;
+ ins->type = (bin_comp_table [ins->inst_i0->type] [ins->inst_i1->type] & 1) ? STACK_I4: STACK_INV;
ins->opcode += ceqops_op_map [ins->inst_i0->type];
return;
/* unops */
case STACK_R8: return &mono_defaults.double_class->byval_arg;
case STACK_MP:
/*
- * FIXME: This doesn't work because mono_class_from_mono_type ()
- * returns the original klass for a byref type, not a 'byref' class,
- * causing the JIT to create variables with the wrong type, for
- * example.
+ * this if used to be commented without any specific reason, but
+ * it breaks #80235 when commented
*/
- /*
if (ins->klass)
return &ins->klass->this_arg;
else
- */
return &mono_defaults.object_class->this_arg;
case STACK_OBJ: return &mono_defaults.object_class->byval_arg;
case STACK_VTYPE: return &ins->klass->byval_arg;
MonoInst *arg;
MONO_INST_NEW_CALL (cfg, call, ret_type_to_call_opcode (sig->ret, calli, virtual));
-
+
+#ifdef MONO_ARCH_SOFT_FLOAT
+ /* we need to convert the r4 value to an int value */
+ {
+ int i;
+ for (i = 0; i < sig->param_count; ++i) {
+ if (sig->params [i]->type == MONO_TYPE_R4) {
+ MonoInst *iargs [1];
+ int temp;
+ iargs [0] = args [i + sig->hasthis];
+
+ temp = mono_emit_jit_icall (cfg, bblock, mono_fload_r4_arg, iargs, ip);
+ NEW_TEMPLOAD (cfg, arg, temp);
+ args [i + sig->hasthis] = arg;
+ }
+ }
+ }
+#endif
+
call->inst.cil_code = ip;
call->args = args;
call->signature = sig;
call = mono_arch_call_opcode (cfg, bblock, call, virtual);
type_to_eval_stack_type (sig->ret, &call->inst);
-
+
for (arg = call->out_args; arg;) {
MonoInst *narg = arg->next;
arg->next = NULL;
}
static MonoMethodSignature *
-mono_get_element_address_signature (int arity)
+mono_get_array_new_va_signature (int arity)
{
static GHashTable *sighash = NULL;
MonoMethodSignature *res;
sighash = g_hash_table_new (NULL, NULL);
}
else if ((res = g_hash_table_lookup (sighash, GINT_TO_POINTER (arity)))) {
- LeaveCriticalSection (&jit_mutex);
+ mono_jit_unlock ();
return res;
}
/* Only set this only some archs since not all backends can handle varargs+pinvoke */
res->call_convention = MONO_CALL_VARARG;
#endif
- res->params [0] = &mono_defaults.array_class->byval_arg;
#ifdef PLATFORM_WIN32
- /*
- * The default pinvoke calling convention is STDCALL but we need CDECL.
- */
res->call_convention = MONO_CALL_C;
#endif
- for (i = 1; i <= arity; i++)
- res->params [i] = &mono_defaults.int_class->byval_arg;
+ res->params [0] = &mono_defaults.int_class->byval_arg;
+ for (i = 0; i < arity; i++)
+ res->params [i + 1] = &mono_defaults.int_class->byval_arg;
res->ret = &mono_defaults.int_class->byval_arg;
return res;
}
-static MonoMethodSignature *
-mono_get_array_new_va_signature (int arity)
+#ifdef MONO_ARCH_SOFT_FLOAT
+static void
+handle_store_float (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *ptr, MonoInst *val, const unsigned char *ip)
{
- static GHashTable *sighash = NULL;
- MonoMethodSignature *res;
- int i;
+ MonoInst *iargs [2];
+ iargs [0] = val;
+ iargs [1] = ptr;
- mono_jit_lock ();
- if (!sighash) {
- sighash = g_hash_table_new (NULL, NULL);
- }
- else if ((res = g_hash_table_lookup (sighash, GINT_TO_POINTER (arity)))) {
- mono_jit_unlock ();
- return res;
- }
+ mono_emit_jit_icall (cfg, bblock, mono_fstore_r4, iargs, ip);
+}
- res = mono_metadata_signature_alloc (mono_defaults.corlib, arity + 1);
+static int
+handle_load_float (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *ptr, const unsigned char *ip)
+{
+ MonoInst *iargs [1];
+ iargs [0] = ptr;
- res->pinvoke = 1;
-#ifdef MONO_ARCH_VARARG_ICALLS
- /* Only set this only some archs since not all backends can handle varargs+pinvoke */
- res->call_convention = MONO_CALL_VARARG;
-#endif
+ return mono_emit_jit_icall (cfg, bblock, mono_fload_r4, iargs, ip);
+}
-#ifdef PLATFORM_WIN32
- res->call_convention = MONO_CALL_C;
+#define LDLOC_SOFT_FLOAT(cfg,ins,idx,ip) do {\
+ if (header->locals [(idx)]->type == MONO_TYPE_R4 && !header->locals [(idx)]->byref) { \
+ int temp; \
+ NEW_LOCLOADA (cfg, (ins), (idx)); \
+ temp = handle_load_float (cfg, bblock, (ins), (ip)); \
+ NEW_TEMPLOAD (cfg, (ins), temp); \
+ } \
+ } while (0)
+#define STLOC_SOFT_FLOAT(cfg,ins,idx,ip) do {\
+ if (header->locals [(idx)]->type == MONO_TYPE_R4 && !header->locals [(idx)]->byref) { \
+ int temp; \
+ NEW_LOCLOADA (cfg, (ins), (idx)); \
+ handle_store_float (cfg, bblock, (ins), *sp, (ip)); \
+ MONO_INST_NEW (cfg, (ins), CEE_NOP); \
+ } \
+ } while (0)
+#define LDARG_SOFT_FLOAT(cfg,ins,idx,ip) do {\
+ if (param_types [(idx)]->type == MONO_TYPE_R4 && !param_types [(idx)]->byref) { \
+ int temp; \
+ NEW_ARGLOADA (cfg, (ins), (idx)); \
+ temp = handle_load_float (cfg, bblock, (ins), (ip)); \
+ NEW_TEMPLOAD (cfg, (ins), temp); \
+ } \
+ } while (0)
+#else
+#define LDLOC_SOFT_FLOAT(cfg,ins,idx,ip)
+#define STLOC_SOFT_FLOAT(cfg,ins,idx,ip)
+#define LDARG_SOFT_FLOAT(cfg,ins,idx,ip)
#endif
- res->params [0] = &mono_defaults.int_class->byval_arg;
- for (i = 0; i < arity; i++)
- res->params [i + 1] = &mono_defaults.int_class->byval_arg;
-
- res->ret = &mono_defaults.int_class->byval_arg;
-
- g_hash_table_insert (sighash, GINT_TO_POINTER (arity), res);
- mono_jit_unlock ();
-
- return res;
-}
-
static MonoMethod*
get_memcpy_method (void)
{
vstore->inst_left = add;
vstore->inst_right = val;
+#ifdef MONO_ARCH_SOFT_FLOAT
+ if (vstore->opcode == CEE_STIND_R4) {
+ handle_store_float (cfg, bblock, add, val, ip);
+ } else
+#endif
if (vstore->opcode == CEE_STOBJ) {
handle_stobj (cfg, bblock, add, val, ip, klass, FALSE, FALSE, TRUE);
} else
if (MONO_TYPE_ISSTRUCT (signature->params [i])) {
return FALSE;
}
+#ifdef MONO_ARCH_SOFT_FLOAT
+ /* this complicates things, fix later */
+ if (signature->params [i]->type == MONO_TYPE_R4)
+ return FALSE;
+#endif
}
/*
{
int temp, rank;
MonoInst *addr;
- MonoMethodSignature *esig;
- char icall_name [256];
- char *name;
- MonoJitICallInfo *info;
+ MonoMethod *addr_method;
+ int element_size;
rank = mono_method_signature (cmethod)->param_count - (is_set? 1: 0);
#endif
}
- /* Need to register the icall so it gets an icall wrapper */
- sprintf (icall_name, "ves_array_element_address_%d", rank);
-
- mono_jit_lock ();
- info = mono_find_jit_icall_by_name (icall_name);
- if (info == NULL) {
- esig = mono_get_element_address_signature (rank);
- name = g_strdup (icall_name);
- info = mono_register_jit_icall (ves_array_element_address, name, esig, FALSE);
-
- g_hash_table_insert (jit_icall_name_hash, name, name);
- }
- mono_jit_unlock ();
-
- /* FIXME: This uses info->sig, but it should use the signature of the wrapper */
- temp = mono_emit_native_call (cfg, bblock, mono_icall_get_wrapper (info), info->sig, sp, ip, FALSE, FALSE);
- cfg->flags |= MONO_CFG_HAS_VARARGS;
-
+ element_size = mono_class_array_element_size (cmethod->klass->element_class);
+ addr_method = mono_marshal_get_array_address (rank, element_size);
+ temp = mono_emit_method_call_spilled (cfg, bblock, addr_method, addr_method->signature, sp, ip, NULL);
NEW_TEMPLOAD (cfg, addr, temp);
return addr;
+
}
-MonoJitICallInfo **emul_opcode_map = NULL;
+static MonoJitICallInfo **emul_opcode_map = NULL;
MonoJitICallInfo *
mono_find_jit_opcode_emulation (int opcode)
{
+ g_assert (opcode >= 0 && opcode <= OP_LAST);
if (emul_opcode_map)
return emul_opcode_map [opcode];
else
store->inst_left = args [2];
store->inst_right = load;
return store;
+ } else if (cmethod->klass->image == mono_defaults.corlib) {
+ if (cmethod->name [0] == 'B' && strcmp (cmethod->name, "Break") == 0
+ && strcmp (cmethod->klass->name, "Debugger") == 0) {
+ MONO_INST_NEW (cfg, ins, CEE_BREAK);
+ return ins;
+ }
}
return mono_arch_get_inst_for_method (cfg, cmethod, fsig, args);
#define CHECK_LOCAL(num) if ((unsigned)(num) >= (unsigned)header->num_locals) UNVERIFIED
#define CHECK_OPSIZE(size) if (ip + size > end) UNVERIFIED
#define CHECK_UNVERIFIABLE(cfg) if (cfg->unverifiable) UNVERIFIED
+#define CHECK_TYPELOAD(klass) if (!(klass) || (klass)->exception_type) {cfg->exception_ptr = klass; goto load_error;}
/* offset from br.s -> br like opcodes */
#define BIG_BRANCH_OFFSET 13
return can;
}
+/*
+ * Check that the IL instructions at ip are the array initialization
+ * sequence and return the pointer to the data and the size.
+ */
+static const char*
+initialize_array_data (MonoMethod *method, gboolean aot, unsigned char *ip, MonoInst *newarr, int *out_size)
+{
+ /*
+ * newarr[System.Int32]
+ * dup
+ * ldtoken field valuetype ...
+ * call void class [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle)
+ */
+ if (ip [0] == CEE_DUP && ip [1] == CEE_LDTOKEN && ip [5] == 0x4 && ip [6] == CEE_CALL) {
+ MonoClass *klass = newarr->inst_newa_class;
+ guint32 token = read32 (ip + 7);
+ guint32 rva, field_index;
+ const char *data_ptr;
+ int size = 0;
+ MonoMethod *cmethod;
+
+ if (newarr->inst_newa_len->opcode != OP_ICONST)
+ return NULL;
+ cmethod = mini_get_method (method, token, NULL, NULL);
+ if (strcmp (cmethod->name, "InitializeArray") || strcmp (cmethod->klass->name, "RuntimeHelpers") || cmethod->klass->image != mono_defaults.corlib)
+ return NULL;
+ switch (mono_type_get_underlying_type (&klass->byval_arg)->type) {
+ case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ size = 1; break;
+ /* we need to swap on big endian, so punt. Should we handle R4 and R8 as well? */
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ size = 2; break;
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ size = 4; break;
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ size = 8; break;
+#endif
+ default:
+ return NULL;
+ }
+ size *= newarr->inst_newa_len->inst_c0;
+ *out_size = size;
+ /*g_print ("optimized in %s: size: %d, numelems: %d\n", method->name, size, newarr->inst_newa_len->inst_c0);*/
+ field_index = read32 (ip + 2) & 0xffffff;
+ mono_metadata_field_info (method->klass->image, field_index - 1, NULL, &rva, NULL);
+ data_ptr = mono_image_rva_map (method->klass->image, rva);
+ /*g_print ("field: 0x%08x, rva: %d, rva_ptr: %p\n", read32 (ip + 2), rva, data_ptr);*/
+ /* for aot code we do the lookup on load */
+ if (aot && data_ptr)
+ return GUINT_TO_POINTER (rva);
+ return data_ptr;
+ }
+ return NULL;
+}
+
/*
* mono_method_to_ir: translates IL into basic blocks containing trees
*/
mono_jit_stats.cil_code_size += header->code_size;
if (sig->is_inflated)
- generic_context = ((MonoMethodInflated *) method)->context;
+ generic_context = mono_method_get_context (method);
else if (generic_container)
generic_context = &generic_container->context;
tblock->flags |= BB_EXCEPTION_DEAD_OBJ;
if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY ||
- clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
+ clause->flags == MONO_EXCEPTION_CLAUSE_FILTER ||
+ clause->flags == MONO_EXCEPTION_CLAUSE_FAULT) {
MONO_INST_NEW (cfg, ins, OP_START_HANDLER);
MONO_ADD_INS (tblock, ins);
n = (*ip)-CEE_LDARG_0;
CHECK_ARG (n);
NEW_ARGLOAD (cfg, ins, n);
+ LDARG_SOFT_FLOAT (cfg, ins, n, ip);
ins->cil_code = ip++;
*sp++ = ins;
break;
n = (*ip)-CEE_LDLOC_0;
CHECK_LOCAL (n);
NEW_LOCLOAD (cfg, ins, n);
+ LDLOC_SOFT_FLOAT (cfg, ins, n, ip);
ins->cil_code = ip++;
*sp++ = ins;
break;
ins->cil_code = ip;
if (!dont_verify_stloc && target_type_is_incompatible (cfg, header->locals [n], *sp))
UNVERIFIED;
+ STLOC_SOFT_FLOAT (cfg, ins, n, ip);
if (ins->opcode == CEE_STOBJ) {
NEW_LOCLOADA (cfg, ins, n);
handle_stobj (cfg, bblock, ins, *sp, ip, ins->klass, FALSE, FALSE, FALSE);
CHECK_STACK_OVF (1);
CHECK_ARG (ip [1]);
NEW_ARGLOAD (cfg, ins, ip [1]);
+ LDARG_SOFT_FLOAT (cfg, ins, ip [1], ip);
ins->cil_code = ip;
*sp++ = ins;
ip += 2;
CHECK_STACK_OVF (1);
CHECK_LOCAL (ip [1]);
NEW_LOCLOAD (cfg, ins, ip [1]);
+ LDLOC_SOFT_FLOAT (cfg, ins, ip [1], ip);
ins->cil_code = ip;
*sp++ = ins;
ip += 2;
ins->cil_code = ip;
if (!dont_verify_stloc && target_type_is_incompatible (cfg, header->locals [ip [1]], *sp))
UNVERIFIED;
+ STLOC_SOFT_FLOAT (cfg, ins, ip [1], ip);
if (ins->opcode == CEE_STOBJ) {
NEW_LOCLOADA (cfg, ins, ip [1]);
handle_stobj (cfg, bblock, ins, *sp, ip, ins->klass, FALSE, FALSE, FALSE);
NEW_TEMPLOAD (cfg, iargs [0], this_temp->inst_c0);
NEW_PCONST (cfg, iargs [1], cmethod);
- NEW_PCONST (cfg, iargs [2], ((MonoMethodInflated *) cmethod)->context);
+ NEW_PCONST (cfg, iargs [2], mono_method_get_context (cmethod));
NEW_TEMPLOADA (cfg, iargs [3], this_arg_temp->inst_c0);
temp = mono_emit_jit_icall (cfg, bblock, mono_helper_compile_generic_method, iargs, ip);
sp -= 2;
ins->inst_left = sp [0];
ins->inst_right = sp [1];
+ ins->type = STACK_I4;
*sp++ = emit_tree (cfg, bblock, ins, ins->cil_code);
+ MONO_INST_NEW (cfg, ins, CEE_BRTRUE);
ADD_UNCOND (TRUE);
} else {
ADD_BINCOND (NULL);
sp -= 2;
ins->inst_left = sp [0];
ins->inst_right = sp [1];
+ ins->type = STACK_I4;
*sp++ = emit_tree (cfg, bblock, ins, ins->cil_code);
+ MONO_INST_NEW (cfg, ins, CEE_BRTRUE);
ADD_UNCOND (TRUE);
} else {
ADD_BINCOND (NULL);
ins_flag = 0;
if (ins->type == STACK_OBJ)
ins->klass = mono_defaults.object_class;
+#ifdef MONO_ARCH_SOFT_FLOAT
+ if (*ip == CEE_LDIND_R4) {
+ int temp;
+ --sp;
+ temp = handle_load_float (cfg, bblock, ins->inst_i0, ip);
+ NEW_TEMPLOAD (cfg, *sp, temp);
+ sp++;
+ }
+#endif
++ip;
break;
case CEE_STIND_REF:
case CEE_STIND_R4:
case CEE_STIND_R8:
CHECK_STACK (2);
+#ifdef MONO_ARCH_SOFT_FLOAT
+ if (*ip == CEE_STIND_R4) {
+ sp -= 2;
+ handle_store_float (cfg, bblock, sp [0], sp [1], ip);
+ ip++;
+ break;
+ }
+#endif
#if HAVE_WRITE_BARRIERS
if (*ip == CEE_STIND_REF && method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER) {
/* insert call to write barrier */
CHECK_STACK (2);
token = read32 (ip + 1);
klass = mini_get_class (method, token, generic_context);
- if (!klass)
- goto load_error;
+ CHECK_TYPELOAD (klass);
sp -= 2;
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
MonoInst *store, *load;
--sp;
token = read32 (ip + 1);
klass = mini_get_class (method, token, generic_context);
- if (!klass)
- goto load_error;
+ CHECK_TYPELOAD (klass);
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
MONO_INST_NEW (cfg, ins, CEE_LDIND_REF);
ins->cil_code = ip;
CHECK_OPSIZE (5);
token = read32 (ip + 1);
klass = mini_get_class (method, token, generic_context);
- if (!klass)
- goto load_error;
+ CHECK_TYPELOAD (klass);
if (sp [0]->type != STACK_OBJ)
UNVERIFIED;
CHECK_OPSIZE (5);
token = read32 (ip + 1);
klass = mini_get_class (method, token, generic_context);
- if (!klass)
- goto load_error;
+ CHECK_TYPELOAD (klass);
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
/* CASTCLASS */
CHECK_OPSIZE (5);
token = read32 (ip + 1);
klass = mini_get_class (method, token, generic_context);
- if (!klass)
- goto load_error;
+ CHECK_TYPELOAD (klass);
if (mono_class_is_nullable (klass)) {
int v = handle_unbox_nullable (cfg, bblock, *sp, ip, klass);
CHECK_OPSIZE (5);
token = read32 (ip + 1);
klass = mini_get_class (method, token, generic_context);
- if (!klass)
- goto load_error;
+ CHECK_TYPELOAD (klass);
if (sp [0]->type != STACK_OBJ)
UNVERIFIED;
iargs [0] = ins;
iargs [1] = sp [1];
mono_emit_method_call_spilled (cfg, bblock, write_barrier, mono_method_signature (write_barrier), iargs, ip, NULL);
+#endif
+#ifdef MONO_ARCH_SOFT_FLOAT
+ } else if (mono_type_to_stind (field->type) == CEE_STIND_R4) {
+ NEW_ICONST (cfg, offset_ins, foffset);
+ MONO_INST_NEW (cfg, ins, OP_PADD);
+ ins->cil_code = ip;
+ ins->inst_left = *sp;
+ ins->inst_right = offset_ins;
+ ins->type = STACK_MP;
+ ins->klass = mono_defaults.object_class;
+ handle_store_float (cfg, bblock, ins, sp [1], ip);
#endif
} else {
MonoInst *store;
load->inst_left = ins;
load->flags |= ins_flag;
ins_flag = 0;
+#ifdef MONO_ARCH_SOFT_FLOAT
+ if (mono_type_to_ldind (field->type) == CEE_LDIND_R4) {
+ int temp;
+ temp = handle_load_float (cfg, bblock, ins, ip);
+ NEW_TEMPLOAD (cfg, *sp, temp);
+ sp++;
+ } else
+#endif
*sp++ = load;
}
}
CHECK_OPSIZE (5);
token = read32 (ip + 1);
klass = mini_get_class (method, token, generic_context);
- if (!klass)
- goto load_error;
+ CHECK_TYPELOAD (klass);
n = mono_type_to_stind (&klass->byval_arg);
if (n == CEE_STOBJ) {
handle_stobj (cfg, bblock, sp [0], sp [1], ip, klass, FALSE, FALSE, TRUE);
CHECK_OPSIZE (5);
token = read32 (ip + 1);
klass = mini_get_class (method, token, generic_context);
- if (!klass)
- goto load_error;
+ CHECK_TYPELOAD (klass);
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
*sp++ = val;
mono_get_got_var (cfg);
klass = mini_get_class (method, token, generic_context);
- if (!klass)
- goto load_error;
+ CHECK_TYPELOAD (klass);
ins->inst_newa_class = klass;
ins->inst_newa_len = *sp;
ins->type = STACK_OBJ;
*/
if (1) {
MonoInst *store, *temp, *load;
+ const char *data_ptr;
+ int data_size = 0;
--sp;
temp = mono_compile_create_var (cfg, type_from_stack_type (ins), OP_LOCAL);
NEW_TEMPSTORE (cfg, store, temp->inst_c0, ins);
store->cil_code = ins->cil_code;
MONO_ADD_INS (bblock, store);
+ /*
+ * we inline/optimize the initialization sequence if possible.
+ * we should also allocate the array as not cleared, since we spend as much time clearing to 0 as initializing
+ * for small sizes open code the memcpy
+ * ensure the rva field is big enough
+ */
+ if ((cfg->opt & MONO_OPT_INTRINS) && ip_in_bb (cfg, bblock, ip + 6) && (data_ptr = initialize_array_data (method, cfg->compile_aot, ip, ins, &data_size))) {
+ MonoMethod *memcpy_method = get_memcpy_method ();
+ MonoInst *data_offset, *add;
+ MonoInst *iargs [3];
+ NEW_ICONST (cfg, iargs [2], data_size);
+ NEW_TEMPLOAD (cfg, load, temp->inst_c0);
+ load->cil_code = ins->cil_code;
+ NEW_ICONST (cfg, data_offset, G_STRUCT_OFFSET (MonoArray, vector));
+ MONO_INST_NEW (cfg, add, OP_PADD);
+ add->inst_left = load;
+ add->inst_right = data_offset;
+ add->cil_code = ip;
+ iargs [0] = add;
+ if (cfg->compile_aot) {
+ NEW_AOTCONST_TOKEN (cfg, iargs [1], MONO_PATCH_INFO_RVA, method->klass->image, GPOINTER_TO_UINT(data_ptr), STACK_PTR, NULL);
+ } else {
+ NEW_PCONST (cfg, iargs [1], data_ptr);
+ }
+ mono_emit_method_call_spilled (cfg, bblock, memcpy_method, memcpy_method->signature, iargs, ip, NULL);
+ ip += 11;
+ }
NEW_TEMPLOAD (cfg, load, temp->inst_c0);
load->cil_code = ins->cil_code;
*sp++ = load;
UNVERIFIED;
klass = mini_get_class (method, read32 (ip + 1), generic_context);
- if (!klass)
- goto load_error;
+ CHECK_TYPELOAD (klass);
/* we need to make sure that this array is exactly the type it needs
* to be for correctness. the wrappers are lax with their usage
* so we need to ignore them here
CHECK_OPSIZE (5);
token = read32 (ip + 1);
klass = mono_class_get_full (image, token, generic_context);
- if (!klass)
- goto load_error;
+ CHECK_TYPELOAD (klass);
mono_class_init (klass);
NEW_LDELEMA (cfg, load, sp, klass);
load->cil_code = ip;
klass = array_access_to_klass (*ip);
NEW_LDELEMA (cfg, load, sp, klass);
load->cil_code = ip;
+#ifdef MONO_ARCH_SOFT_FLOAT
+ if (*ip == CEE_LDELEM_R4) {
+ int temp;
+ temp = handle_load_float (cfg, bblock, load, ip);
+ NEW_TEMPLOAD (cfg, *sp, temp);
+ sp++;
+ ++ip;
+ break;
+ }
+#endif
MONO_INST_NEW (cfg, ins, ldelem_to_ldind [*ip - CEE_LDELEM_I1]);
ins->cil_code = ip;
ins->inst_left = load;
klass = array_access_to_klass (*ip);
NEW_LDELEMA (cfg, load, sp, klass);
load->cil_code = ip;
+#ifdef MONO_ARCH_SOFT_FLOAT
+ if (*ip == CEE_STELEM_R4) {
+ handle_store_float (cfg, bblock, load, sp [2], ip);
+ ip++;
+ break;
+ }
+#endif
MONO_INST_NEW (cfg, ins, stelem_to_stind [*ip - CEE_STELEM_I]);
ins->cil_code = ip;
ins->inst_left = load;
CHECK_OPSIZE (5);
token = read32 (ip + 1);
klass = mono_class_get_full (image, token, generic_context);
- if (!klass)
- goto load_error;
+ CHECK_TYPELOAD (klass);
mono_class_init (klass);
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
MonoMethod* helper = mono_marshal_get_stelemref ();
--sp;
CHECK_OPSIZE (5);
klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
- if (!klass)
- goto load_error;
+ CHECK_TYPELOAD (klass);
mono_class_init (klass);
ins->type = STACK_MP;
ins->inst_left = *sp;
--sp;
CHECK_OPSIZE (5);
klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
- if (!klass)
- goto load_error;
+ CHECK_TYPELOAD (klass);
mono_class_init (klass);
ins->cil_code = ip;
}
}
- /* fixme: call fault handler ? */
-
if ((handlers = mono_find_final_block (cfg, ip, target, MONO_EXCEPTION_CLAUSE_FINALLY))) {
GList *tmp;
for (tmp = handlers; tmp; tmp = tmp->next) {
token = read32 (ip + 2);
func = mono_method_get_wrapper_data (method, token);
info = mono_find_jit_icall_by_addr (func);
- g_assert (info);
+ if (info == NULL){
+ g_error ("An attempt has been made to perform an icall to address %p, "
+ "but the address has not been registered as an icall\n", info);
+ g_assert_not_reached ();
+ }
CHECK_STACK (info->sig->param_count);
sp -= info->sig->param_count;
cmp->cil_code = ip;
type_from_op (cmp);
CHECK_TYPE (cmp);
+ ins->cil_code = ip;
+ ins->type = STACK_I4;
+ ins->inst_i0 = cmp;
+#if MONO_ARCH_SOFT_FLOAT
+ if (sp [0]->type == STACK_R8) {
+ cmp->type = STACK_I4;
+ *sp++ = emit_tree (cfg, bblock, cmp, ip + 2);
+ ip += 2;
+ break;
+ }
+#endif
if ((sp [0]->type == STACK_I8) || ((sizeof (gpointer) == 8) && ((sp [0]->type == STACK_PTR) || (sp [0]->type == STACK_OBJ) || (sp [0]->type == STACK_MP))))
cmp->opcode = OP_LCOMPARE;
else
cmp->opcode = OP_COMPARE;
- ins->cil_code = ip;
- ins->type = STACK_I4;
- ins->inst_i0 = cmp;
*sp++ = ins;
/* spill it to reduce the expression complexity
* and workaround bug 54209
n = read16 (ip + 2);
CHECK_ARG (n);
NEW_ARGLOAD (cfg, ins, n);
+ LDARG_SOFT_FLOAT (cfg, ins, n, ip);
ins->cil_code = ip;
*sp++ = ins;
ip += 4;
n = read16 (ip + 2);
CHECK_LOCAL (n);
NEW_LOCLOAD (cfg, ins, n);
+ LDLOC_SOFT_FLOAT (cfg, ins, n, ip);
ins->cil_code = ip;
*sp++ = ins;
ip += 4;
if (!dont_verify_stloc && target_type_is_incompatible (cfg, header->locals [n], *sp))
UNVERIFIED;
ins->cil_code = ip;
+ STLOC_SOFT_FLOAT (cfg, ins, n, ip);
if (ins->opcode == CEE_STOBJ) {
NEW_LOCLOADA (cfg, ins, n);
handle_stobj (cfg, bblock, ins, *sp, ip, ins->klass, FALSE, FALSE, FALSE);
CHECK_OPSIZE (6);
token = read32 (ip + 2);
klass = mini_get_class (method, token, generic_context);
- if (!klass)
- goto load_error;
+ CHECK_TYPELOAD (klass);
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
MonoInst *store, *load;
NEW_PCONST (cfg, load, NULL);
CHECK_OPSIZE (6);
token = read32 (ip + 2);
constrained_call = mono_class_get_full (image, token, generic_context);
- if (!constrained_call)
- goto load_error;
+ CHECK_TYPELOAD (constrained_call);
ip += 6;
break;
case CEE_CPBLK:
token = mono_type_size (type, &ialign);
} else {
MonoClass *klass = mono_class_get_full (image, token, generic_context);
- if (!klass)
- goto load_error;
+ CHECK_TYPELOAD (klass);
mono_class_init (klass);
token = mono_class_value_size (klass, &align);
}
NEW_LOCSTORE (cfg, store, i, ins);
MONO_ADD_INS (init_localsbb, store);
} else if (t == MONO_TYPE_R4 || t == MONO_TYPE_R8) {
+#ifdef MONO_ARCH_SOFT_FLOAT
+ /* FIXME: handle init of R4 */
+#else
MONO_INST_NEW (cfg, ins, OP_R8CONST);
ins->type = STACK_R8;
ins->inst_p0 = (void*)&r8_0;
NEW_LOCSTORE (cfg, store, i, ins);
MONO_ADD_INS (init_localsbb, store);
+#endif
} else if ((t == MONO_TYPE_VALUETYPE) || (t == MONO_TYPE_TYPEDBYREF) ||
((t == MONO_TYPE_GENERICINST) && mono_type_generic_inst_is_valuetype (ptype))) {
NEW_LOCLOADA (cfg, ins, i);
dec_foreach (iargs [i], cfg);
break;
}
+#ifdef MONO_ARCH_SOFT_FLOAT
+ case OP_FBEQ:
+ case OP_FBGE:
+ case OP_FBGT:
+ case OP_FBLE:
+ case OP_FBLT:
+ case OP_FBNE_UN:
+ case OP_FBGE_UN:
+ case OP_FBGT_UN:
+ case OP_FBLE_UN:
+ case OP_FBLT_UN: {
+ if ((info = mono_find_jit_opcode_emulation (tree->opcode))) {
+ MonoCompile *cfg = data;
+ MonoInst *iargs [2];
+
+ iargs [0] = tree->inst_i0;
+ iargs [1] = tree->inst_i1;
+
+ mono_emulate_opcode (cfg, tree, iargs, info);
+
+ dec_foreach (iargs [0], cfg);
+ dec_foreach (iargs [1], cfg);
+ break;
+ } else {
+ g_assert_not_reached ();
+ }
+ break;
+ }
+ case OP_FCEQ:
+ case OP_FCGT:
+ case OP_FCGT_UN:
+ case OP_FCLT:
+ case OP_FCLT_UN: {
+ if ((info = mono_find_jit_opcode_emulation (tree->opcode))) {
+ MonoCompile *cfg = data;
+ MonoInst *iargs [2];
+
+ /* the args are in the compare opcode ... */
+ iargs [0] = tree->inst_i0;
+ iargs [1] = tree->inst_i1;
+
+ mono_emulate_opcode (cfg, tree, iargs, info);
+
+ dec_foreach (iargs [0], cfg);
+ dec_foreach (iargs [1], cfg);
+ break;
+ } else {
+ g_assert_not_reached ();
+ }
+ break;
+ }
+#endif
default:
break;
memcpy (res, patch_info, sizeof (MonoJumpInfo));
switch (patch_info->type) {
+ case MONO_PATCH_INFO_RVA:
case MONO_PATCH_INFO_LDSTR:
case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
case MONO_PATCH_INFO_LDTOKEN:
const MonoJumpInfo *ji = (MonoJumpInfo*)data;
switch (ji->type) {
+ case MONO_PATCH_INFO_RVA:
case MONO_PATCH_INFO_LDSTR:
case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
case MONO_PATCH_INFO_LDTOKEN:
return 0;
switch (ji1->type) {
+ case MONO_PATCH_INFO_RVA:
case MONO_PATCH_INFO_LDSTR:
case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
case MONO_PATCH_INFO_LDTOKEN:
target = (char*)vtable->data + patch_info->data.field->offset;
break;
}
+ case MONO_PATCH_INFO_RVA:
+ target = mono_image_rva_map (patch_info->data.token->image, patch_info->data.token->token);
+ break;
case MONO_PATCH_INFO_R4:
case MONO_PATCH_INFO_R8:
target = patch_info->data.target;
state->reg2 = mono_regstate_next_int (cfg->rs);
break;
case MB_NTERM_freg:
+#ifdef MONO_ARCH_SOFT_FLOAT
+ state->reg1 = mono_regstate_next_int (cfg->rs);
+ state->reg2 = mono_regstate_next_int (cfg->rs);
+#else
state->reg1 = mono_regstate_next_float (cfg->rs);
+#endif
break;
default:
#ifdef MONO_ARCH_ENABLE_EMIT_STATE_OPT
/* Throw a type load exception if needed */
MonoLoaderError *error = mono_loader_get_last_error ();
- mono_destroy_compile (cfg);
if (error) {
MonoException *ex = mono_loader_error_prepare_exception (error);
+ mono_destroy_compile (cfg);
mono_raise_exception (ex);
} else {
+ if (cfg->exception_ptr) {
+ MonoException *ex = mono_class_get_exception_for_failure (cfg->exception_ptr);
+ mono_destroy_compile (cfg);
+ mono_raise_exception (ex);
+ }
g_assert_not_reached ();
}
}
return runtime_invoke (obj, params, exc, compiled_method);
}
+#ifdef MONO_GET_CONTEXT
+#define GET_CONTEXT MONO_GET_CONTEXT
+#endif
+
+#ifndef GET_CONTEXT
#ifdef PLATFORM_WIN32
#define GET_CONTEXT \
struct sigcontext *ctx = (struct sigcontext*)_dummy;
#else
-#ifdef __sparc
+#ifdef MONO_ARCH_USE_SIGACTION
#define GET_CONTEXT \
void *ctx = context;
-#elif defined (MONO_ARCH_USE_SIGACTION)
+#elif defined(__sparc__)
#define GET_CONTEXT \
- void *ctx = context;
+ void *ctx = sigctx;
#else
#define GET_CONTEXT \
void **_p = (void **)&_dummy; \
struct sigcontext *ctx = (struct sigcontext *)++_p;
#endif
#endif
+#endif
#ifdef MONO_ARCH_USE_SIGACTION
#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, siginfo_t *info, void *context)
+#elif defined(__sparc__)
+#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, void *sigctx)
#else
#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy)
#endif
}
MonoDomain *
-mini_init (const char *filename)
+mini_init (const char *filename, const char *runtime_version)
{
MonoDomain *domain;
mono_aot_set_make_unreadable (TRUE);
}
- domain = mono_init_from_assembly (filename, filename);
+ if (runtime_version)
+ domain = mono_init_version (filename, runtime_version);
+ else
+ domain = mono_init_from_assembly (filename, filename);
mono_icall_init ();
mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info",
mono_register_opcode_emulation (OP_FADD, "__emul_fadd", "double double double", mono_fadd, FALSE);
mono_register_opcode_emulation (OP_FMUL, "__emul_fmul", "double double double", mono_fmul, FALSE);
mono_register_opcode_emulation (OP_FNEG, "__emul_fneg", "double double", mono_fneg, FALSE);
+ mono_register_opcode_emulation (CEE_CONV_R8, "__emul_conv_r8", "double int32", mono_conv_to_r8, FALSE);
+ mono_register_opcode_emulation (CEE_CONV_R4, "__emul_conv_r4", "double int32", mono_conv_to_r4, FALSE);
mono_register_opcode_emulation (OP_FCONV_TO_R4, "__emul_fconv_to_r4", "double double", mono_fconv_r4, FALSE);
mono_register_opcode_emulation (OP_FCONV_TO_I1, "__emul_fconv_to_i1", "int8 double", mono_fconv_i1, FALSE);
mono_register_opcode_emulation (OP_FCONV_TO_I2, "__emul_fconv_to_i2", "int16 double", mono_fconv_i2, FALSE);
mono_register_opcode_emulation (OP_FBGT_UN, "__emul_fcmp_gt_un", "uint32 double double", mono_fcmp_gt_un, FALSE);
mono_register_opcode_emulation (OP_FBLE_UN, "__emul_fcmp_le_un", "uint32 double double", mono_fcmp_le_un, FALSE);
mono_register_opcode_emulation (OP_FBGE_UN, "__emul_fcmp_ge_un", "uint32 double double", mono_fcmp_ge_un, FALSE);
+
+ mono_register_opcode_emulation (OP_FCEQ, "__emul_fcmp_ceq", "uint32 double double", mono_fceq, FALSE);
+ mono_register_opcode_emulation (OP_FCGT, "__emul_fcmp_cgt", "uint32 double double", mono_fcgt, FALSE);
+ mono_register_opcode_emulation (OP_FCGT_UN, "__emul_fcmp_cgt_un", "uint32 double double", mono_fcgt_un, FALSE);
+ mono_register_opcode_emulation (OP_FCLT, "__emul_fcmp_clt", "uint32 double double", mono_fclt, FALSE);
+ mono_register_opcode_emulation (OP_FCLT_UN, "__emul_fcmp_clt_un", "uint32 double double", mono_fclt_un, FALSE);
+
+ register_icall (mono_fload_r4, "mono_fload_r4", "double ptr", FALSE);
+ register_icall (mono_fstore_r4, "mono_fstore_r4", "void double ptr", FALSE);
+ register_icall (mono_fload_r4_arg, "mono_fload_r4_arg", "uint32 double", FALSE);
#endif
#if SIZEOF_VOID_P == 4