for (k = 0; k < param_count; k++) {
if (csig->pinvoke)
- size = mono_type_native_stack_size (csig->params [k], &align);
+ size = mono_type_native_stack_size (csig->params [k], (guint32*)&align);
else
size = mini_type_stack_size (NULL, csig->params [k], &align);
if (!cachelinesize) {
#ifdef __APPLE__
- int mib [3], len;
+ int mib [3];
+ size_t len;
mib [0] = CTL_HW;
mib [1] = HW_CACHELINE;
len = sizeof (cachelinesize);
- if (sysctl(mib, 2, &cachelinesize, &len, NULL, 0) == -1) {
+ if (sysctl(mib, 2, &cachelinesize, (size_t*)&len, NULL, 0) == -1) {
perror ("sysctl");
cachelinesize = 128;
} else {
}
}
- if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (n == sig->sentinelpos)) {
+ if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (i == sig->sentinelpos)) {
/* Prevent implicit arguments and sig_cookie from
being passed in registers */
gr = PPC_LAST_ARG_REG + 1;
return cinfo;
}
+static void
+allocate_tailcall_valuetype_addrs (MonoCompile *cfg)
+{
+#if !PPC_PASS_STRUCTS_BY_VALUE
+ MonoMethodSignature *sig = mono_method_signature (cfg->method);
+ int num_structs = 0;
+ int i;
+
+ if (!(cfg->flags & MONO_CFG_HAS_TAIL))
+ return;
+
+ for (i = 0; i < sig->param_count; ++i) {
+ MonoType *type = mono_type_get_underlying_type (sig->params [i]);
+ if (type->type == MONO_TYPE_VALUETYPE)
+ num_structs++;
+ }
+
+ if (num_structs) {
+ cfg->tailcall_valuetype_addrs =
+ mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst*) * num_structs);
+ for (i = 0; i < num_structs; ++i) {
+ cfg->tailcall_valuetype_addrs [i] =
+ mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+ cfg->tailcall_valuetype_addrs [i]->flags |= MONO_INST_INDIRECT;
+ }
+ }
+#endif
+}
/*
* Set var information according to the calling convention. ppc version.
MonoInst *inst;
int i, offset, size, align, curinst;
int frame_reg = ppc_sp;
+ gint32 *offsets;
+ guint32 locals_stack_size, locals_stack_align;
+
+ allocate_tailcall_valuetype_addrs (m);
m->flags |= MONO_CFG_HAS_SPILLUP;
m->sig_cookie += sizeof (gpointer);
}
- curinst = m->locals_start;
- for (i = curinst; i < m->num_varinfo; ++i) {
- inst = m->varinfo [i];
- if ((inst->flags & MONO_INST_IS_DEAD) || inst->opcode == OP_REGVAR)
- continue;
-
- /* inst->backend.is_pinvoke indicates native sized value types, this is used by the
- * pinvoke wrappers when they call functions returning structure */
- if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype) && inst->inst_vtype->type != MONO_TYPE_TYPEDBYREF)
- size = mono_class_native_size (mono_class_from_mono_type (inst->inst_vtype), &align);
- else
- size = mono_type_size (inst->inst_vtype, &align);
-
- offset += align - 1;
- offset &= ~(align - 1);
- inst->inst_offset = offset;
- inst->opcode = OP_REGOFFSET;
- inst->inst_basereg = frame_reg;
- offset += size;
- //g_print ("allocating local %d to %d\n", i, inst->inst_offset);
+ offsets = mono_allocate_stack_slots_full (m, FALSE, &locals_stack_size, &locals_stack_align);
+ if (locals_stack_align) {
+ offset += (locals_stack_align - 1);
+ offset &= ~(locals_stack_align - 1);
+ }
+ for (i = m->locals_start; i < m->num_varinfo; i++) {
+ if (offsets [i] != -1) {
+ MonoInst *inst = m->varinfo [i];
+ inst->opcode = OP_REGOFFSET;
+ inst->inst_basereg = frame_reg;
+ inst->inst_offset = offset + offsets [i];
+ /*
+ g_print ("allocating local %d (%s) to %d\n",
+ i, mono_type_get_name (inst->inst_vtype), inst->inst_offset);
+ */
+ }
}
+ offset += locals_stack_size;
curinst = 0;
if (sig->hasthis) {
inst->opcode = OP_REGOFFSET;
inst->inst_basereg = frame_reg;
if (sig->pinvoke) {
- size = mono_type_native_stack_size (sig->params [i], &align);
+ size = mono_type_native_stack_size (sig->params [i], (guint32*)&align);
inst->backend.is_pinvoke = 1;
} else {
size = mono_type_size (sig->params [i], &align);
{
int sig_reg = mono_alloc_ireg (cfg);
- MONO_EMIT_NEW_ICONST (cfg, sig_reg, call->signature);
+ MONO_EMIT_NEW_ICONST (cfg, sig_reg, (guint32)call->signature);
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
ppc_r1, cinfo->sig_cookie.offset, sig_reg);
}
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);
+ int dreg = mono_alloc_freg (cfg);
- mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, TRUE);
+ if (ainfo->size == 4) {
+ MONO_EMIT_NEW_UNALU (cfg, OP_FCONV_TO_R4, dreg, in->dreg);
+ } else {
+ MONO_INST_NEW (cfg, ins, OP_FMOVE);
+ ins->dreg = dreg;
+ ins->sreg1 = in->dreg;
+ MONO_ADD_INS (cfg->cbb, ins);
+ }
+
+ mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
cfg->flags |= MONO_CFG_HAS_FPOUT;
}
} else {
int ovf_size = ainfo->vtsize;
int doffset = ainfo->offset;
int i, soffset, dreg;
- int size = 0;
if (ainfo->regtype == RegTypeStructByVal) {
+ guint32 size = 0;
soffset = 0;
- /*
- Darwin needs some special handling for 1 and 2 byte arguments
- */
#ifdef __APPLE__
+ /*
+ * Darwin pinvokes needs some special handling for 1
+ * and 2 byte arguments
+ */
g_assert (ins->klass);
- size = mono_class_native_size (ins->klass, NULL);
+ if (call->signature->pinvoke)
+ size = mono_class_native_size (ins->klass, NULL);
if (size == 2 || size == 1) {
int tmpr = mono_alloc_ireg (cfg);
if (size == 1)
cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
code = cfg->native_code + offset;
}
-handle_enum:
+
switch (rtype) {
case MONO_TYPE_VOID:
/* special case string .ctor icall */
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);
+ if (ins->opcode == OP_ICONV_TO_R4)
+ MONO_EMIT_NEW_UNALU (cfg, OP_FCONV_TO_R4, ins->dreg, ins->dreg);
ins->opcode = OP_NOP;
break;
}
return code;
}
-static unsigned char*
-mono_emit_stack_alloc (guchar *code, MonoInst* tree)
-{
-#if 0
- int sreg = tree->sreg1;
- x86_alu_reg_reg (code, X86_SUB, X86_ESP, tree->sreg1);
- if (tree->flags & MONO_INST_INIT) {
- int offset = 0;
- if (tree->dreg != X86_EAX && sreg != X86_EAX) {
- x86_push_reg (code, X86_EAX);
- offset += 4;
- }
- if (tree->dreg != X86_ECX && sreg != X86_ECX) {
- x86_push_reg (code, X86_ECX);
- offset += 4;
- }
- if (tree->dreg != X86_EDI && sreg != X86_EDI) {
- x86_push_reg (code, X86_EDI);
- offset += 4;
- }
-
- x86_shift_reg_imm (code, X86_SHR, sreg, 2);
- if (sreg != X86_ECX)
- x86_mov_reg_reg (code, X86_ECX, sreg, 4);
- x86_alu_reg_reg (code, X86_XOR, X86_EAX, X86_EAX);
-
- x86_lea_membase (code, X86_EDI, X86_ESP, offset);
- x86_cld (code);
- x86_prefix (code, X86_REP_PREFIX);
- x86_stosl (code);
-
- if (tree->dreg != X86_EDI && sreg != X86_EDI)
- x86_pop_reg (code, X86_EDI);
- if (tree->dreg != X86_ECX && sreg != X86_ECX)
- x86_pop_reg (code, X86_ECX);
- if (tree->dreg != X86_EAX && sreg != X86_EAX)
- x86_pop_reg (code, X86_EAX);
- }
-#endif
- return code;
-}
-
typedef struct {
guchar *code;
const guchar *target;
MonoInst *inst;
CallInfo *cinfo;
guint32 i, pos;
+ int struct_index = 0;
/* FIXME: Generate intermediate code instead */
cinfo = calculate_sizes (sig, sig->pinvoke);
if (MONO_TYPE_ISSTRUCT (sig->ret)) {
- /* FIXME: */
- NOT_IMPLEMENTED;
+ ArgInfo *ainfo = &cinfo->ret;
+ inst = cfg->vret_addr;
+ g_assert (ppc_is_imm16 (inst->inst_offset));
+ ppc_lwz (code, ainfo->reg, inst->inst_offset, inst->inst_basereg);
}
for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
ArgInfo *ainfo = cinfo->args + i;
break;
case RegTypeBase:
- case RegTypeStructByVal:
- case RegTypeStructByAddr:
/* FIXME: */
NOT_IMPLEMENTED;
+ case RegTypeStructByVal: {
+ guint32 size = 0;
+
+ /* FIXME: */
+ if (ainfo->vtsize)
+ NOT_IMPLEMENTED;
+#ifdef __APPLE__
+ /*
+ * Darwin pinvokes needs some special handling
+ * for 1 and 2 byte arguments
+ */
+ if (method->signature->pinvoke)
+ size = mono_class_native_size (inst->klass, NULL);
+ if (size == 1 || size == 2) {
+ /* FIXME: */
+ NOT_IMPLEMENTED;
+ } else
+#endif
+ for (i = 0; i < ainfo->size; ++i) {
+ ppc_lwz (code, ainfo->reg + i,
+ inst->inst_offset + i * sizeof (gpointer), inst->inst_basereg);
+ }
+ break;
+ }
+
+ case RegTypeStructByAddr: {
+ MonoInst *addr = cfg->tailcall_valuetype_addrs [struct_index];
+
+ g_assert (ppc_is_imm16 (addr->inst_offset));
+ g_assert (!ainfo->offset);
+ ppc_lwz (code, ainfo->reg, addr->inst_offset, addr->inst_basereg);
+
+ struct_index++;
+ break;
+ }
+
default:
g_assert_not_reached ();
}
mono_debug_record_line_number (cfg, ins, offset);
switch (ins->opcode) {
+ case OP_RELAXED_NOP:
case OP_NOP:
case OP_DUMMY_USE:
case OP_DUMMY_STORE:
CallInfo *cinfo;
int tracing = 0;
int lmf_offset = 0;
+ int tailcall_struct_index;
if (mono_jit_trace_calls != NULL && mono_trace_eval (method))
tracing = 1;
ppc_stwx (code, ainfo->reg, ppc_r11, inst->inst_basereg);
}
}
+
+ tailcall_struct_index = 0;
for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
ArgInfo *ainfo = cinfo->args + i;
inst = cfg->args [pos];
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))
+ if (sig->pinvoke && 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) {
-/*
-Darwin handles 1 and 2 byte structs specially by loading h/b into the arg
-register. Should this case include linux/ppc?
-*/
#if __APPLE__
+ /*
+ * Darwin handles 1 and 2 byte
+ * structs specially by
+ * loading h/b into the arg
+ * register. Only done for
+ * pinvokes.
+ */
if (size == 2)
ppc_sth (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg);
else if (size == 1)
ppc_stb (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg);
- else
+ else
#endif
ppc_stw (code, ainfo->reg + cur_reg, doffset, inst->inst_basereg);
soffset += sizeof (gpointer);
} else {
ppc_mr (code, ppc_r11, ainfo->reg);
}
+
+ if (cfg->tailcall_valuetype_addrs) {
+ MonoInst *addr = cfg->tailcall_valuetype_addrs [tailcall_struct_index];
+
+ g_assert (ppc_is_imm16 (addr->inst_offset));
+ ppc_stw (code, ppc_r11, addr->inst_offset, addr->inst_basereg);
+
+ tailcall_struct_index++;
+ }
+
g_assert (ppc_is_imm16 (inst->inst_offset));
code = emit_memcpy (code, ainfo->vtsize, inst->inst_basereg, inst->inst_offset, ppc_r11, 0);
/*g_print ("copy in %s: %d bytes from %d to offset: %d\n", method->name, ainfo->vtsize, ainfo->reg, inst->inst_offset);*/
void
mono_arch_emit_epilog (MonoCompile *cfg)
{
- MonoJumpInfo *patch_info;
MonoMethod *method = cfg->method;
int pos, i;
int max_epilog_size = 16 + 20*4;