#include "mini.h"
#include "mini-ppc.h"
-static gboolean arch_handle_exception (MonoContext *ctx, gpointer obj, gboolean test_only);
-
/*
struct sigcontext {
if (!rethrow)
mono_ex->stack_trace = NULL;
}
- arch_handle_exception (&ctx, exc, FALSE);
+ mono_handle_exception (&ctx, exc, (gpointer)eip, FALSE);
restore_context (&ctx);
g_assert_not_reached ();
//ppc_break (code);
if (by_name) {
ppc_mr (code, ppc_r5, ppc_r3);
- ppc_load (code, ppc_r3, mono_defaults.corlib);
+ ppc_load (code, ppc_r3, (guint32)mono_defaults.corlib);
ppc_load (code, ppc_r4, "System");
ppc_load (code, ppc_r0, mono_exception_from_name);
ppc_mtctr (code, ppc_r0);
*new_ctx = *ctx;
setup_context (new_ctx);
- if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) {
+ if (*lmf && (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->ebp)) {
/* remove any unused lmf */
*lmf = (*lmf)->previous_lmf;
}
if (!ji->method->wrapper_type)
*managed = TRUE;
- sframe = (MonoPPCStackFrame*)MONO_CONTEXT_GET_BP (ctx);
+ sframe = (MonoPPCStackFrame*)MONO_CONTEXT_GET_SP (ctx);
MONO_CONTEXT_SET_BP (new_ctx, sframe->sp);
if (ji->method->save_lmf) {
memcpy (&new_ctx->fregs, (char*)sframe->sp - sizeof (double) * MONO_SAVED_FREGS, sizeof (double) * MONO_SAVED_FREGS);
*new_ctx = *ctx;
setup_context (new_ctx);
- if (!(*lmf)->method)
- return (gpointer)-1;
-
if ((ji = mono_jit_info_table_find (domain, (gpointer)(*lmf)->eip))) {
} else {
+ if (!(*lmf)->method)
+ return (gpointer)-1;
+
memset (res, 0, sizeof (MonoJitInfo));
res->method = (*lmf)->method;
}
- /*sframe = (MonoPPCStackFrame*)MONO_CONTEXT_GET_BP (ctx);
+ /*sframe = (MonoPPCStackFrame*)MONO_CONTEXT_GET_SP (ctx);
MONO_CONTEXT_SET_BP (new_ctx, sframe->sp);
MONO_CONTEXT_SET_IP (new_ctx, sframe->lr);*/
MONO_CONTEXT_SET_BP (new_ctx, (*lmf)->ebp);
MONO_CONTEXT_SET_IP (new_ctx, (*lmf)->eip);
memcpy (&new_ctx->regs, (*lmf)->iregs, sizeof (gulong) * MONO_SAVED_GREGS);
memcpy (&new_ctx->fregs, (*lmf)->fregs, sizeof (double) * MONO_SAVED_FREGS);
+
+ /* FIXME: what about trampoline LMF frames? see exceptions-x86.c */
+
*lmf = (*lmf)->previous_lmf;
return ji ? ji : res;
restore_context = mono_arch_get_restore_context ();
mono_arch_sigctx_to_monoctx (sigctx, &mctx);
- arch_handle_exception (&mctx, obj, test_only);
+ mono_handle_exception (&mctx, obj, (gpointer)mctx.sc_ir, test_only);
restore_context (&mctx);
}
uc_copy = (ucontext_t*)(sp + 16);
memcpy (uc_copy, uc, sizeof (os_ucontext));
#ifdef __linux__
- uc_copy->uc_mcontext.uc_regs = (char*)uc_copy + offsetof(ucontext_t, uc_mcontext.uc_regs);
+ uc_copy->uc_mcontext.uc_regs = (gpointer)((char*)uc_copy + ((char*)uc->uc_mcontext.uc_regs - (char*)uc));
#endif
+ g_assert (mono_arch_ip_from_context (uc) == mono_arch_ip_from_context (uc_copy));
/* at the return form the signal handler execution starts in altstack_handle_and_restore() */
UCONTEXT_REG_LNK(uc) = UCONTEXT_REG_NIP(uc);
UCONTEXT_REG_NIP(uc) = (unsigned long)altstack_handle_and_restore;
mono_arch_sigctx_to_monoctx (ctx, &mctx);
- result = arch_handle_exception (&mctx, obj, test_only);
+ result = mono_handle_exception (&mctx, obj, (gpointer)mctx.sc_ir, test_only);
/* restore the context so that returning from the signal handler will invoke
* the catch clause
*/
return result;
}
-/**
- * arch_handle_exception:
- * @ctx: saved processor state
- * @obj: the exception object
- * @test_only: only test if the exception is caught, but dont call handlers
- *
- *
- */
-static gboolean
-arch_handle_exception (MonoContext *ctx, gpointer obj, gboolean test_only)
-{
- MonoDomain *domain = mono_domain_get ();
- MonoJitInfo *ji, rji;
- static int (*call_filter) (MonoContext *, gpointer, gpointer) = NULL;
- MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
- MonoLMF *lmf = jit_tls->lmf;
- GList *trace_ips = NULL;
- MonoException *mono_ex;
- MonoArray *initial_trace_ips = NULL;
- int frame_count = 0;
- gboolean has_dynamic_methods = FALSE;
-
- g_assert (ctx != NULL);
- if (!obj) {
- MonoException *ex = mono_get_exception_null_reference ();
- ex->message = mono_string_new (domain,
- "Object reference not set to an instance of an object");
- obj = (MonoObject *)ex;
- }
-
- if (mono_object_isinst (obj, mono_defaults.exception_class)) {
- mono_ex = (MonoException*)obj;
- initial_trace_ips = mono_ex->trace_ips;
- } else {
- mono_ex = NULL;
- }
-
-
- if (!call_filter)
- call_filter = mono_arch_get_call_filter ();
-
- g_assert (jit_tls->end_of_stack);
- g_assert (jit_tls->abort_func);
-
- if (!test_only) {
- MonoContext ctx_cp = *ctx;
- setup_context (&ctx_cp);
- if (mono_jit_trace_calls != NULL)
- g_print ("EXCEPTION handling: %s\n", mono_object_class (obj)->name);
- if (!arch_handle_exception (&ctx_cp, obj, TRUE)) {
- if (mono_break_on_exc)
- G_BREAKPOINT ();
- mono_unhandled_exception (obj);
- }
- }
-
- memset (&rji, 0, sizeof (rji));
-
- while (1) {
- MonoContext new_ctx;
-
- setup_context (&new_ctx);
- ji = mono_find_jit_info (domain, jit_tls, &rji, &rji, ctx, &new_ctx,
- NULL, &lmf, NULL, NULL);
- if (!ji) {
- g_warning ("Exception inside function without unwind info");
- g_assert_not_reached ();
- }
-
- if (ji != (gpointer)-1) {
- frame_count ++;
-
- if (test_only && ji->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && mono_ex) {
- /*
- * Avoid overwriting the stack trace if the exception is
- * rethrown. Also avoid giant stack traces during a stack
- * overflow.
- */
- if (!initial_trace_ips && (frame_count < 1000)) {
- trace_ips = g_list_prepend (trace_ips, MONO_CONTEXT_GET_IP (ctx));
-
- }
- }
-
- if (ji->method->dynamic)
- has_dynamic_methods = TRUE;
-
- if (ji->num_clauses) {
- int i;
-
- g_assert (ji->clauses);
-
- for (i = 0; i < ji->num_clauses; i++) {
- MonoJitExceptionInfo *ei = &ji->clauses [i];
- gboolean filtered = FALSE;
-
- if (ei->try_start <= MONO_CONTEXT_GET_IP (ctx) &&
- MONO_CONTEXT_GET_IP (ctx) <= ei->try_end) {
- /* catch block */
-
- if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) || (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)) {
- /* store the exception object int cfg->excvar */
- g_assert (ei->exvar_offset);
- /* need to use the frame pointer (ppc_r31), not r1 (regs start from register r13): methods with clauses always have r31 */
- *((gpointer *)((char *)(ctx->regs [ppc_r31-13]) + ei->exvar_offset)) = obj;
- }
-
- if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
- filtered = call_filter (ctx, ei->data.filter, mono_ex);
-
- if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE &&
- mono_object_isinst (obj, ei->data.catch_class)) || filtered) {
- if (test_only) {
- if (mono_ex && !initial_trace_ips) {
- trace_ips = g_list_reverse (trace_ips);
- mono_ex->trace_ips = glist_to_array (trace_ips, mono_defaults.int_class);
- if (has_dynamic_methods)
- /* These methods could go away anytime, so compute the stack trace now */
- mono_ex->stack_trace = ves_icall_System_Exception_get_trace (mono_ex);
- }
- g_list_free (trace_ips);
- return TRUE;
- }
- if (mono_jit_trace_calls != NULL)
- g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
- /*printf ("stack for catch: %p\n", MONO_CONTEXT_GET_BP (ctx));*/
- MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
- jit_tls->lmf = lmf;
- return 0;
- }
- if (!test_only && ei->try_start <= MONO_CONTEXT_GET_IP (ctx) &&
- MONO_CONTEXT_GET_IP (ctx) < ei->try_end &&
- (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT)) {
- if (mono_jit_trace_calls != NULL)
- g_print ("EXCEPTION: fault clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
- call_filter (ctx, ei->handler_start, NULL);
- }
- if (!test_only && ei->try_start <= MONO_CONTEXT_GET_IP (ctx) &&
- MONO_CONTEXT_GET_IP (ctx) < ei->try_end &&
- (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY)) {
- if (mono_jit_trace_calls != NULL)
- g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
- call_filter (ctx, ei->handler_start, NULL);
- }
-
- }
- }
- }
- }
-
- *ctx = new_ctx;
- setup_context (ctx);
-
- if ((ji == (gpointer)-1) || MONO_CONTEXT_GET_BP (ctx) >= jit_tls->end_of_stack) {
- if (!test_only) {
- jit_tls->lmf = lmf;
- jit_tls->abort_func (obj);
- g_assert_not_reached ();
- } else {
- if (mono_ex && !initial_trace_ips) {
- trace_ips = g_list_reverse (trace_ips);
- mono_ex->trace_ips = glist_to_array (trace_ips, mono_defaults.int_class);
- if (has_dynamic_methods)
- /* These methods could go away anytime, so compute the stack trace now */
- mono_ex->stack_trace = ves_icall_System_Exception_get_trace (mono_ex);
- }
- g_list_free (trace_ips);
- return FALSE;
- }
- }
- }
-
- g_assert_not_reached ();
-}
-
gboolean
mono_arch_has_unwind_info (gconstpointer addr)
{
#include <sys/sysctl.h>
#endif
+/* From ir-emit.h */
+static inline guint32
+alloc_ireg (MonoCompile *cfg)
+{
+ return cfg->next_vreg ++;
+}
+
+static inline guint32
+alloc_lreg (MonoCompile *cfg)
+{
+#if SIZEOF_VOID_P == 8
+ return cfg->next_vreg ++;
+#else
+ /* Use a pair of consecutive vregs */
+ guint32 res = cfg->next_vreg;
+
+ cfg->next_vreg += 3;
+
+ return res;
+#endif
+}
+
+static inline guint32
+alloc_freg (MonoCompile *cfg)
+{
+#ifdef MONO_ARCH_SOFT_FLOAT
+ /* Allocate an lvreg so float ops can be decomposed into long ops */
+ return alloc_lreg (cfg);
+#else
+ /* Allocate these from the same pool as the int regs */
+ return cfg->next_vreg ++;
+#endif
+}
+
+static inline guint32
+alloc_dreg (MonoCompile *cfg, MonoStackType stack_type)
+{
+ switch (stack_type) {
+ case STACK_I4:
+ case STACK_PTR:
+ case STACK_MP:
+ case STACK_OBJ:
+ return alloc_ireg (cfg);
+ case STACK_R8:
+ return alloc_freg (cfg);
+ case STACK_I8:
+ return alloc_lreg (cfg);
+ case STACK_VTYPE:
+ return alloc_ireg (cfg);
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+#ifdef MONO_ARCH_SOFT_FLOAT
+#define DECOMPOSE_INTO_REGPAIR(stack_type) ((stack_type) == STACK_I8 || (stack_type) == STACK_R8)
+#else
+#define DECOMPOSE_INTO_REGPAIR(stack_type) ((stack_type) == STACK_I8)
+#endif
+
+#define NEW_VARLOADA(cfg,dest,var,vartype) do { \
+ MONO_INST_NEW ((cfg), (dest), OP_LDADDR); \
+ (dest)->inst_p0 = (var); \
+ (var)->flags |= MONO_INST_INDIRECT; \
+ (dest)->type = STACK_MP; \
+ (dest)->klass = (var)->klass; \
+ (dest)->dreg = alloc_dreg ((cfg), STACK_MP); \
+ if (SIZEOF_VOID_P == 4 && DECOMPOSE_INTO_REGPAIR ((var)->type)) { MonoInst *var1 = get_vreg_to_inst (cfg, (var)->dreg + 1); MonoInst *var2 = get_vreg_to_inst (cfg, (var)->dreg + 2); g_assert (var1); g_assert (var2); var1->flags |= MONO_INST_INDIRECT; var2->flags |= MONO_INST_INDIRECT; } \
+ } while (0)
+
+#define EMIT_NEW_VARLOADA(cfg,dest,var,vartype) do { NEW_VARLOADA ((cfg), (dest), (var), (vartype)); MONO_ADD_INS ((cfg)->cbb, (dest)); } while (0)
+
#define FORCE_INDIR_CALL 1
enum {
}
#if __APPLE__
-/* size == 4 is checked already */
static gboolean
-has_only_a_r4_field (MonoClass *klass)
+has_only_a_r48_field (MonoClass *klass)
{
gpointer iter;
MonoClassField *f;
+ gboolean have_field = FALSE;
iter = NULL;
while ((f = mono_class_get_fields (klass, &iter))) {
if (!(f->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
- if (!f->type->byref && f->type->type == MONO_TYPE_R4)
- return TRUE;
- return FALSE;
+ if (have_field)
+ return FALSE;
+ if (!f->type->byref && (f->type->type == MONO_TYPE_R4 || f->type->type == MONO_TYPE_R8))
+ have_field = TRUE;
+ else
+ return FALSE;
}
}
- return FALSE;
+ return have_field;
}
#endif
else
size = mono_class_value_size (klass, NULL);
#if __APPLE__
- if (size == 4 && has_only_a_r4_field (klass)) {
- cinfo->args [n].size = 4;
+ if ((size == 4 || size == 8) && has_only_a_r48_field (klass)) {
+ cinfo->args [n].size = size;
/* It was 7, now it is 8 in LinuxPPC */
if (fr <= PPC_LAST_FPARG_REG) {
cinfo->args [n].reg = fr;
fr ++;
FP_ALSO_IN_REG (gr ++);
- ALWAYS_ON_STACK (stack_size += 4);
+ if (size == 8)
+ FP_ALSO_IN_REG (gr ++);
+ ALWAYS_ON_STACK (stack_size += size);
} else {
cinfo->args [n].offset = PPC_STACK_PARAM_OFFSET + stack_size;
cinfo->args [n].regtype = RegTypeBase;
cinfo->args [n].reg = ppc_sp; /* in the caller*/
- stack_size += 4;
+ stack_size += 8;
}
n++;
break;
{
int align_size = size;
int nwords = 0;
+ int rest = PPC_LAST_ARG_REG - gr + 1;
+ int n_in_regs;
align_size += (sizeof (gpointer) - 1);
align_size &= ~(sizeof (gpointer) - 1);
nwords = (align_size + sizeof (gpointer) -1 ) / sizeof (gpointer);
+ n_in_regs = rest >= nwords? nwords: rest;
cinfo->args [n].regtype = RegTypeStructByVal;
if (gr > PPC_LAST_ARG_REG || (size >= 3 && size % 4 != 0)) {
cinfo->args [n].size = 0;
cinfo->args [n].vtsize = nwords;
} else {
- int rest = PPC_LAST_ARG_REG - gr + 1;
- int n_in_regs = rest >= nwords? nwords: rest;
cinfo->args [n].size = n_in_regs;
cinfo->args [n].vtsize = nwords - n_in_regs;
cinfo->args [n].reg = gr;
- gr += n_in_regs;
}
+ gr += n_in_regs;
cinfo->args [n].offset = PPC_STACK_PARAM_OFFSET + stack_size;
/*g_print ("offset for arg %d at %d\n", n, PPC_STACK_PARAM_OFFSET + stack_size);*/
stack_size += nwords * sizeof (gpointer);
curinst = 0;
if (MONO_TYPE_ISSTRUCT (sig->ret)) {
m->ret->opcode = OP_REGVAR;
- m->ret->inst_c0 = ppc_r3;
+ m->ret->inst_c0 = m->ret->dreg = ppc_r3;
} else {
- /* FIXME: handle long and FP values */
+ /* FIXME: handle long values? */
switch (mono_type_get_underlying_type (sig->ret)->type) {
case MONO_TYPE_VOID:
break;
+ case MONO_TYPE_R4:
+ case MONO_TYPE_R8:
+ m->ret->opcode = OP_REGVAR;
+ m->ret->inst_c0 = m->ret->dreg = ppc_f1;
+ break;
default:
m->ret->opcode = OP_REGVAR;
- m->ret->inst_c0 = ppc_r3;
+ m->ret->inst_c0 = m->ret->dreg = ppc_r3;
break;
}
}
if (inst->opcode != OP_REGVAR) {
inst->opcode = OP_REGOFFSET;
inst->inst_basereg = frame_reg;
- size = mono_type_size (sig->params [i], &align);
+ if (sig->pinvoke) {
+ size = mono_type_native_stack_size (sig->params [i], &align);
+ inst->backend.is_pinvoke = 1;
+ } else {
+ size = mono_type_size (sig->params [i], &align);
+ }
offset += align - 1;
offset &= ~(align - 1);
inst->inst_offset = offset;
/* change sign? */
m->stack_offset = offset;
+ if (m->new_ir && sig->call_convention == MONO_CALL_VARARG) {
+ CallInfo *cinfo = calculate_sizes (m->method->signature, m->method->signature->pinvoke);
+
+ m->sig_cookie = cinfo->sig_cookie.offset;
+
+ g_free(cinfo);
+ }
}
void
mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, FALSE);
}
} else if (ainfo->regtype == RegTypeStructByAddr) {
- if (ainfo->offset) {
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, ppc_r1, ainfo->offset, in->dreg);
- } else {
- MONO_INST_NEW (cfg, ins, OP_MOVE);
- ins->dreg = mono_alloc_ireg (cfg);
- ins->sreg1 = in->dreg;
- MONO_ADD_INS (cfg->cbb, ins);
-
- mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, FALSE);
- }
+ MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
+ ins->opcode = OP_OUTARG_VT;
+ ins->sreg1 = in->dreg;
+ ins->klass = in->klass;
+ ins->inst_p0 = call;
+ ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
+ memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
+ MONO_ADD_INS (cfg->cbb, ins);
} else if (ainfo->regtype == RegTypeStructByVal) {
/* this is further handled in mono_arch_emit_outarg_vt () */
MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, ppc_r1, ainfo->offset, in->dreg);
}
} else if (ainfo->regtype == RegTypeFP) {
- MONO_INST_NEW (cfg, ins, OP_FMOVE);
- ins->dreg = mono_alloc_freg (cfg);
- ins->sreg1 = in->dreg;
- MONO_ADD_INS (cfg->cbb, ins);
+ if (t->type == MONO_TYPE_VALUETYPE) {
+ /* this is further handled in mono_arch_emit_outarg_vt () */
+ MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
+ ins->opcode = OP_OUTARG_VT;
+ ins->sreg1 = in->dreg;
+ ins->klass = in->klass;
+ ins->inst_p0 = call;
+ ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
+ memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
+ MONO_ADD_INS (cfg->cbb, ins);
+
+ cfg->flags |= MONO_CFG_HAS_FPOUT;
+ } else {
+ MONO_INST_NEW (cfg, ins, OP_FMOVE);
+ ins->dreg = mono_alloc_freg (cfg);
+ ins->sreg1 = in->dreg;
+ MONO_ADD_INS (cfg->cbb, ins);
- mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, TRUE);
- cfg->flags |= MONO_CFG_HAS_FPOUT;
+ mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, TRUE);
+ cfg->flags |= MONO_CFG_HAS_FPOUT;
+ }
} else {
g_assert_not_reached ();
}
int i, soffset, dreg;
int size = 0;
- soffset = 0;
- /*
- Darwin needs some special handling for 1 and 2 byte arguments
- */
+ if (ainfo->regtype == RegTypeStructByVal) {
+ soffset = 0;
+ /*
+ Darwin needs some special handling for 1 and 2 byte arguments
+ */
#ifdef __APPLE__
- g_assert (ins->klass);
- size = mono_class_native_size (ins->klass, NULL);
- if (size == 2 || size == 1) {
- int tmpr = mono_alloc_ireg (cfg);
- if (size == 1)
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI1_MEMBASE, tmpr, src->dreg, soffset);
- else
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI2_MEMBASE, tmpr, src->dreg, soffset);
- dreg = mono_alloc_ireg (cfg);
- MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, dreg, tmpr);
- mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, FALSE);
- } else
+ g_assert (ins->klass);
+ size = mono_class_native_size (ins->klass, NULL);
+ if (size == 2 || size == 1) {
+ int tmpr = mono_alloc_ireg (cfg);
+ if (size == 1)
+ MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI1_MEMBASE, tmpr, src->dreg, soffset);
+ else
+ MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI2_MEMBASE, tmpr, src->dreg, soffset);
+ dreg = mono_alloc_ireg (cfg);
+ MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, dreg, tmpr);
+ mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, FALSE);
+ } else
#endif
- for (i = 0; i < ainfo->size; ++i) {
- dreg = mono_alloc_ireg (cfg);
- MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, src->dreg, soffset);
- mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg + i, FALSE);
- soffset += sizeof (gpointer);
+ for (i = 0; i < ainfo->size; ++i) {
+ dreg = mono_alloc_ireg (cfg);
+ MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, src->dreg, soffset);
+ mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg + i, FALSE);
+ soffset += sizeof (gpointer);
+ }
+ if (ovf_size != 0)
+ mini_emit_memcpy2 (cfg, ppc_r1, doffset + soffset, src->dreg, soffset, ovf_size * sizeof (gpointer), 0);
+ } else if (ainfo->regtype == RegTypeFP) {
+ int tmpr = mono_alloc_freg (cfg);
+ if (ainfo->size == 4)
+ MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, tmpr, src->dreg, 0);
+ else
+ MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, tmpr, src->dreg, 0);
+ dreg = mono_alloc_freg (cfg);
+ MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, dreg, tmpr);
+ mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
+ } else {
+ MonoInst *vtcopy = mono_compile_create_var (cfg, &src->klass->byval_arg, OP_LOCAL);
+ MonoInst *load;
+ guint32 size;
+
+ /* FIXME: alignment? */
+ if (call->signature->pinvoke) {
+ size = mono_type_native_stack_size (&src->klass->byval_arg, NULL);
+ vtcopy->backend.is_pinvoke = 1;
+ } else {
+ size = mini_type_stack_size (cfg->generic_sharing_context, &src->klass->byval_arg, NULL);
+ }
+ if (size > 0)
+ g_assert (ovf_size > 0);
+
+ EMIT_NEW_VARLOADA (cfg, load, vtcopy, vtcopy->inst_vtype);
+ mini_emit_memcpy2 (cfg, load->dreg, 0, src->dreg, 0, size, 0);
+
+ if (ainfo->offset)
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, ppc_r1, ainfo->offset, load->dreg);
+ else
+ mono_call_inst_add_outarg_reg (cfg, call, load->dreg, ainfo->reg, FALSE);
}
- //g_print ("vt size: %d at R%d + %d\n", doffset, vt->inst_basereg, vt->inst_offset);
- if (ovf_size != 0)
- mini_emit_memcpy2 (cfg, ppc_r1, doffset + soffset, src->dreg, soffset, ovf_size * sizeof (gpointer), 0);
}
void
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, ppc_sp, -8, msw_reg);
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_XOR_IMM, xored, ins->sreg1, 0x80000000);
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, ppc_sp, -4, xored);
- MONO_EMIT_NEW_LOAD_R8 (cfg, adj_reg, &adjust_val);
+ MONO_EMIT_NEW_LOAD_R8 (cfg, adj_reg, (gpointer)&adjust_val);
MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, tmp_reg, ppc_sp, -8);
MONO_EMIT_NEW_BIALU (cfg, OP_FSUB, ins->dreg, tmp_reg, adj_reg);
ins->opcode = OP_NOP;
case OP_R8CONST:
case OP_R4CONST:
NEW_INS (cfg, temp, OP_ICONST);
- temp->inst_c0 = ins->inst_p0;
+ temp->inst_c0 = (guint32)ins->inst_p0;
temp->dreg = mono_regstate_next_int (cfg->rs);
ins->inst_basereg = temp->dreg;
ins->inst_offset = 0;
typedef struct {
guchar *code;
- guchar *target;
+ const guchar *target;
int absolute;
int found;
} PatchData;
guint32 *endthunks = (guint32*)(code + bsize);
guint32 load [2];
guchar *templ;
- int i, count = 0;
+ int count = 0;
int difflow, diffhigh;
/* always ensure a call from pdata->code can reach to the thunks without further thunks */
}
static void
-handle_thunk (int absolute, guchar *code, guchar *target) {
+handle_thunk (int absolute, guchar *code, const guchar *target) {
MonoDomain *domain = mono_domain_get ();
PatchData pdata;
}
void
-ppc_patch (guchar *code, guchar *target)
+ppc_patch (guchar *code, const guchar *target)
{
guint32 ins = *(guint32*)code;
guint32 prim = ins >> 26;
}
break;
case OP_IDIV: {
- guint32 *divisor_is_m1;
+ guint8 *divisor_is_m1;
/* XER format: SO, OV, CA, reserved [21 bits], count [8 bits]
*/
ppc_cmpi (code, 0, 0, ins->sreg2, -1);
g_assert_not_reached ();
break;
case OP_LOCALLOC: {
- guint32 * zero_loop_jump, * zero_loop_start;
+ guint8 * zero_loop_jump, * zero_loop_start;
/* keep alignment */
int alloca_waste = PPC_STACK_PARAM_OFFSET + cfg->param_area + 31;
int area_offset = alloca_waste;
break;
case OP_LCONV_TO_OVF_I4_2:
case OP_LCONV_TO_OVF_I: {
- guint32 *negative_branch, *msword_positive_branch, *msword_negative_branch, *ovf_ex_target;
+ guint8 *negative_branch, *msword_positive_branch, *msword_negative_branch, *ovf_ex_target;
// Check if its negative
ppc_cmpi (code, 0, 0, ins->sreg1, 0);
negative_branch = code;
for (patch_info = ji; patch_info; patch_info = patch_info->next) {
unsigned char *ip = patch_info->ip.i + code;
- const unsigned char *target;
+ unsigned char *target;
target = mono_resolve_patch_target (method, domain, code, patch_info, run_cctors);
int size = 0;
g_assert (ppc_is_imm16 (inst->inst_offset));
g_assert (ppc_is_imm16 (inst->inst_offset + ainfo->size * sizeof (gpointer)));
+ /* FIXME: what if there is no class? */
if (mono_class_from_mono_type (inst->inst_vtype))
size = mono_class_native_size (mono_class_from_mono_type (inst->inst_vtype), NULL);
for (cur_reg = 0; cur_reg < ainfo->size; ++cur_reg) {
mono_arch_emit_exceptions (MonoCompile *cfg)
{
MonoJumpInfo *patch_info;
- int nthrows, i;
+ int i;
guint8 *code;
const guint8* exc_throw_pos [MONO_EXC_INTRINS_NUM] = {NULL};
guint8 exc_throw_found [MONO_EXC_INTRINS_NUM] = {0};
- guint32 code_size;
- int exc_count = 0;
int max_epilog_size = 50;
/* count the number of exception infos */
} else if (patch_info->type == MONO_PATCH_INFO_BB_OVF)
max_epilog_size += 12;
else if (patch_info->type == MONO_PATCH_INFO_EXC_OVF) {
- MonoOvfJump *ovfj = patch_info->data.target;
+ MonoOvfJump *ovfj = (MonoOvfJump*)patch_info->data.target;
i = exception_id_by_name (ovfj->data.exception);
if (!exc_throw_found [i]) {
max_epilog_size += 24;
for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
switch (patch_info->type) {
case MONO_PATCH_INFO_BB_OVF: {
- MonoOvfJump *ovfj = patch_info->data.target;
+ MonoOvfJump *ovfj = (MonoOvfJump*)patch_info->data.target;
unsigned char *ip = patch_info->ip.i + cfg->native_code;
/* patch the initial jump */
ppc_patch (ip, code);
break;
}
case MONO_PATCH_INFO_EXC_OVF: {
- MonoOvfJump *ovfj = patch_info->data.target;
+ MonoOvfJump *ovfj = (MonoOvfJump*)patch_info->data.target;
MonoJumpInfo *newji;
unsigned char *ip = patch_info->ip.i + cfg->native_code;
unsigned char *bcl = code;
} else {
ins = (guint32*) ((char*)ins + val);
}
- code = &val;
+ code = (guint32*)&val;
ppc_li (code, ppc_r0, 0x7FF2);
if (ins [1] == val) {
/* Darwin on G4, implement */
tls_mode = TLS_MODE_FAILED;
return;
} else {
- code = &val;
+ code = (guint32*)&val;
ppc_mfspr (code, ppc_r3, 104);
if (ins [1] != val) {
tls_mode = TLS_MODE_FAILED;