#include "jit-icalls.c"
+#include "aliasing.h"
+
/*
* this is used to determine when some branch optimizations are possible: we exclude FP compares
* because they have weird semantics with NaNs.
#define NEW_LOCLOADA(cfg,dest,num) do { \
(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- (dest)->ssa_op = MONO_SSA_MAYBE_LOAD; \
+ (dest)->ssa_op = MONO_SSA_ADDRESS_TAKEN; \
(dest)->inst_i0 = (cfg)->varinfo [locals_offset + (num)]; \
(dest)->inst_i0->flags |= MONO_INST_INDIRECT; \
(dest)->opcode = OP_LDADDR; \
#define NEW_RETLOADA(cfg,dest) do { \
(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- (dest)->ssa_op = MONO_SSA_MAYBE_LOAD; \
+ (dest)->ssa_op = MONO_SSA_ADDRESS_TAKEN; \
(dest)->inst_i0 = (cfg)->ret; \
(dest)->inst_i0->flags |= MONO_INST_INDIRECT; \
(dest)->opcode = cfg->ret_var_is_local ? OP_LDADDR : CEE_LDIND_I; \
#define NEW_ARGLOADA(cfg,dest,num) do { \
if (arg_array [(num)]->opcode == OP_ICONST) goto inline_failure; \
(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- (dest)->ssa_op = MONO_SSA_MAYBE_LOAD; \
+ (dest)->ssa_op = MONO_SSA_ADDRESS_TAKEN; \
(dest)->inst_i0 = arg_array [(num)]; \
(dest)->inst_i0->flags |= MONO_INST_INDIRECT; \
(dest)->opcode = OP_LDADDR; \
#define NEW_TEMPLOADA(cfg,dest,num) do { \
(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- (dest)->ssa_op = MONO_SSA_MAYBE_LOAD; \
+ (dest)->ssa_op = MONO_SSA_ADDRESS_TAKEN; \
(dest)->inst_i0 = (cfg)->varinfo [(num)]; \
(dest)->inst_i0->flags |= MONO_INST_INDIRECT; \
(dest)->opcode = OP_LDADDR; \
res = mono_metadata_signature_alloc (mono_defaults.corlib, arity + 1);
+ 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;
res = mono_metadata_signature_alloc (mono_defaults.corlib, arity + 1);
+ 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;
return mono_emit_jit_icall (cfg, bblock, alloc_ftn, iargs, ip);
}
+
+/**
+ * Handles unbox of a Nullable<T>, returning a temp variable
+ * where the result is stored
+ */
+static int
+handle_unbox_nullable (MonoCompile* cfg, MonoBasicBlock* bblock, MonoInst* val, const guchar *ip, MonoClass* klass)
+{
+ MonoMethod* method = mono_class_get_method_from_name (klass, "Unbox", 1);
+ return mono_emit_method_call_spilled (cfg, bblock, method, mono_method_signature (method), &val, ip, NULL);
+}
+
+
+
static MonoInst *
handle_box (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *val, const guchar *ip, MonoClass *klass)
{
MonoInst *dest, *vtoffset, *add, *vstore;
int temp;
+ if (mono_class_is_nullable (klass)) {
+ MonoMethod* method = mono_class_get_method_from_name (klass, "Box", 1);
+ temp = mono_emit_method_call_spilled (cfg, bblock, method, mono_method_signature (method), &val, ip, NULL);
+ NEW_TEMPLOAD (cfg, dest, temp);
+ return dest;
+ }
+
+
temp = handle_alloc (cfg, bblock, klass, TRUE, ip);
NEW_TEMPLOAD (cfg, dest, temp);
NEW_ICONST (cfg, vtoffset, sizeof (MonoObject));
return ins;
} else
return NULL;
- } else if (mini_class_is_system_array (cmethod->klass)) {
+ } else if (cmethod->klass == mono_defaults.array_class) {
if (cmethod->name [0] != 'g')
return NULL;
image = method->klass->image;
header = mono_method_get_header (method);
- generic_container = ((MonoMethodNormal *)method)->generic_container;
+ generic_container = method->generic_container;
sig = mono_method_signature (method);
num_args = sig->hasthis + sig->param_count;
ip = (unsigned char*)header->code;
goto load_error;
fsig = mono_method_get_signature (cmethod, image, token);
- if (mono_method_signature (cmethod)->pinvoke) {
- /* Happens with String ctors */
- cmethod = mono_marshal_get_native_wrapper (cmethod);
- fsig = mono_method_signature (cmethod);
- }
-
mono_class_init (cmethod->klass);
if (mono_use_security_manager) {
break;
}
+ if (mono_class_is_nullable (klass)) {
+ int v = handle_unbox_nullable (cfg, bblock, *sp, ip, klass);
+ NEW_TEMPLOAD (cfg, *sp, v);
+ sp ++;
+ ip += 5;
+ break;
+ }
+
MONO_INST_NEW (cfg, ins, OP_UNBOXCAST);
ins->type = STACK_OBJ;
ins->inst_left = *sp;
if (!klass)
goto load_error;
+ if (mono_class_is_nullable (klass)) {
+ int v = handle_unbox_nullable (cfg, bblock, *sp, ip, klass);
+ NEW_TEMPLOAD (cfg, *sp, v);
+ sp ++;
+ ip += 5;
+ break;
+ }
+
/* Needed by the code generated in inssel.brg */
mono_get_got_var (cfg);
case CEE_STIND_R4:
case CEE_STIND_R8:
case CEE_STOBJ:
- if (tree->ssa_op == MONO_SSA_NOP) {
+ if ((tree->ssa_op == MONO_SSA_NOP) || (tree->ssa_op & MONO_SSA_ADDRESS_TAKEN)) {
memset (acp, 0, sizeof (MonoInst *) * acp_size);
return;
}
MonoCompile *cfg;
MonoJitInfo *jinfo;
int dfn = 0, i, code_size_ratio;
+ gboolean deadce_has_run = FALSE;
if (!header)
return NULL;
cfg->compile_aot = compile_aot;
cfg->intvars = mono_mempool_alloc0 (cfg->mempool, sizeof (guint16) * STACK_MAX *
mono_method_get_header (method)->max_stack);
-
+ cfg->aliasing_info = NULL;
+
if (cfg->verbose_level > 2)
g_print ("converting method %s\n", mono_method_full_name (method, TRUE));
#else
/* fixme: add all optimizations which requires SSA */
- if (cfg->opt & (MONO_OPT_DEADCE | MONO_OPT_ABCREM | MONO_OPT_SSAPRE)) {
+ if (cfg->opt & (MONO_OPT_SSA | MONO_OPT_ABCREM | MONO_OPT_SSAPRE)) {
if (!(cfg->comp_done & MONO_COMP_SSA) && !header->num_clauses && !cfg->disable_ssa) {
mono_local_cprop (cfg);
mono_ssa_compute (cfg);
}
if (cfg->comp_done & MONO_COMP_SSA) {
- mono_ssa_deadce (cfg);
+ //mono_ssa_deadce (cfg);
//mono_ssa_strength_reduction (cfg);
+ if (cfg->opt & MONO_OPT_SSAPRE) {
+ mono_perform_ssapre (cfg);
+ //mono_local_cprop (cfg);
+ }
+
+ if (cfg->opt & MONO_OPT_DEADCE) {
+ mono_ssa_deadce (cfg);
+ deadce_has_run = TRUE;
+ }
+
if ((cfg->flags & MONO_CFG_HAS_LDELEMA) && (cfg->opt & MONO_OPT_ABCREM))
mono_perform_abc_removal (cfg);
- if (cfg->opt & MONO_OPT_SSAPRE)
- mono_perform_ssapre (cfg);
-
mono_ssa_remove (cfg);
if (cfg->opt & MONO_OPT_BRANCH)
if (cfg->opt & MONO_OPT_LINEARS) {
GList *vars, *regs;
+
+ /* For now, compute aliasing info only if needed for deadce... */
+ if ((cfg->opt & MONO_OPT_DEADCE) && (! deadce_has_run) && (header->num_clauses == 0)) {
+ cfg->aliasing_info = mono_build_aliasing_information (cfg);
+ }
/* fixme: maybe we can avoid to compute livenesss here if already computed ? */
cfg->comp_done &= ~MONO_COMP_LIVENESS;
if (!(cfg->comp_done & MONO_COMP_LIVENESS))
mono_analyze_liveness (cfg);
+ if (cfg->aliasing_info != NULL) {
+ mono_aliasing_deadce (cfg->aliasing_info);
+ deadce_has_run = TRUE;
+ }
+
if ((vars = mono_arch_get_allocatable_int_vars (cfg))) {
regs = mono_arch_get_global_int_regs (cfg);
if (cfg->got_var)
regs = g_list_delete_link (regs, regs);
mono_linear_scan (cfg, vars, regs, &cfg->used_int_regs);
}
+
+ if (cfg->aliasing_info != NULL) {
+ mono_destroy_aliasing_information (cfg->aliasing_info);
+ cfg->aliasing_info = NULL;
+ }
}
//mono_print_code (cfg);