ArgInfo ret;
ArgInfo sigCookie;
size_data sz;
+ int vret_arg_index;
ArgInfo args [1];
} CallInfo;
gpointer mono_arch_get_lmf_addr (void);
static guint8 * emit_load_volatile_arguments (guint8 *, MonoCompile *);
static void catch_SIGILL(int, siginfo_t *, void *);
+static __inline__ void emit_unwind_regs(MonoCompile *, guint8 *, int, int, long);
/*========================= End of Prototypes ======================*/
/*========================= End of Function ========================*/
+/*------------------------------------------------------------------*/
+/* */
+/* Name - emit_unwind_regs. */
+/* */
+/* Function - Determines if a value can be returned in one or */
+/* two registers. */
+/* */
+/*------------------------------------------------------------------*/
+
+static void __inline__
+emit_unwind_regs(MonoCompile *cfg, guint8 *code, int start, int end, long offset)
+{
+ int i;
+
+ for (i = start; i < end; i++) {
+ mono_emit_unwind_op_offset (cfg, code, i, offset);
+ offset += sizeof(gulong);
+ }
+}
+
+/*========================= End of Function ========================*/
+
/*------------------------------------------------------------------*/
/* */
/* Name - retFitsInReg. */
{
int stackSize = cfg->stack_usage;
+ if (cfg->frame_reg != STK_BASE)
+ s390_lgr (code, STK_BASE, cfg->frame_reg);
+
if (s390_is_imm16 (stackSize)) {
s390_aghi (code, STK_BASE, stackSize);
} else {
/* */
/*------------------------------------------------------------------*/
-// static void inline
-static void
+static void inline
add_general (guint *gr, size_data *sz, ArgInfo *ainfo)
{
if (*gr > S390_LAST_ARG_REG) {
static CallInfo *
get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig, gboolean is_pinvoke)
{
- guint i, fr, gr, size;
+ guint i, fr, gr, size, pstart;
int nParm = sig->hasthis + sig->param_count;
MonoType *ret_type;
guint32 simpletype, align;
else
size = mono_class_value_size (klass, &align);
- cinfo->ret.reg = s390_r2;
cinfo->struct_ret = 1;
cinfo->ret.size = size;
cinfo->ret.vtsize = size;
- gr++;
break;
}
case MONO_TYPE_TYPEDBYREF:
size = sizeof (MonoTypedRef);
- cinfo->ret.reg = s390_r2;
cinfo->struct_ret = 1;
cinfo->ret.size = size;
cinfo->ret.vtsize = size;
- gr++;
break;
case MONO_TYPE_VOID:
break;
g_error ("Can't handle as return value 0x%x", sig->ret->type);
}
- if (sig->hasthis) {
- cinfo->args[nParm].size = sizeof(gpointer);
- add_general (&gr, sz, cinfo->args+nParm);
- nParm++;
+
+ pstart = 0;
+ /*
+ * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
+ * the first argument, allowing 'this' to be always passed in the first arg reg.
+ * Also do this if the first argument is a reference type, since virtual calls
+ * are sometimes made using calli without sig->hasthis set, like in the delegate
+ * invoke wrappers.
+ */
+ if (cinfo->struct_ret && !is_pinvoke &&
+ (sig->hasthis ||
+ (sig->param_count > 0 &&
+ MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (gsctx, sig->params [0]))))) {
+ if (sig->hasthis) {
+ cinfo->args[nParm].size = sizeof (gpointer);
+ add_general (&gr, sz, cinfo->args + nParm);
+ } else {
+ cinfo->args[nParm].size = sizeof (gpointer);
+ add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
+ pstart = 1;
+ }
+ nParm ++;
+ cinfo->vret_arg_index = 1;
+ cinfo->ret.reg = gr;
+ gr ++;
+ } else {
+ /* this */
+ if (sig->hasthis) {
+ cinfo->args[nParm].size = sizeof (gpointer);
+ add_general (&gr, sz, cinfo->args + nParm);
+ nParm ++;
+ }
+
+ if (cinfo->struct_ret) {
+ cinfo->ret.reg = gr;
+ gr ++;
+ }
}
if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
/* parameters. */
/*----------------------------------------------------------*/
- for (i = 0; i < sig->param_count; ++i) {
+ for (i = pstart; i < sig->param_count; ++i) {
MonoType *ptype;
/*--------------------------------------------------*/
size = sizeof (gpointer);
- inst->opcode = OP_REGOFFSET;
+ inst->opcode = OP_REGOFFSET;
inst->inst_basereg = frame_reg;
- offset = S390_ALIGN (offset, sizeof (gpointer));
- inst->inst_offset = offset;
+ offset = S390_ALIGN (offset, sizeof (gpointer));
+ inst->inst_offset = offset;
/* Add a level of indirection */
MONO_INST_NEW (cfg, indir, 0);
- *indir = *inst;
- inst->opcode = OP_VTARG_ADDR;
+ *indir = *inst;
+ inst->opcode = OP_VTARG_ADDR;
inst->inst_left = indir;
}
break;
case RegTypeStructByVal :
size = cinfo->args[iParm].size;
offset = S390_ALIGN(offset, size);
- inst->opcode = OP_REGOFFSET;
+ inst->opcode = OP_REGOFFSET;
inst->inst_basereg = frame_reg;
- inst->inst_offset = offset;
+ inst->inst_offset = offset;
break;
default :
if (cinfo->args [iParm].reg == STK_BASE) {
? sizeof(int)
: sizeof(long));
offset = S390_ALIGN(offset, size);
- inst->inst_offset = offset;
+ if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
+ inst->inst_offset = offset;
+ else
+ inst->inst_offset = offset + (8 - size);
}
break;
}
(iParm < sig->sentinelpos))
cfg->sig_cookie += size;
- offset += size;
+ offset += MAX(size, 8);
}
curinst++;
}
mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
}
- header = mono_method_get_header (cfg->method);
+ header = cfg->header;
if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
frmReg = s390_r11;
else
short *o[1];
s390_basr (code, s390_r13, 0);
s390_j (code, 10);
- s390_llong (code, 0x41e0000000000000);
- s390_llong (code, 0x41f0000000000000);
+ s390_llong (code, 0x41e0000000000000llu);
+ s390_llong (code, 0x41f0000000000000llu);
s390_ldr (code, s390_f15, sreg);
s390_cdb (code, s390_f15, 0, s390_r13, 4);
s390_jl (code, 0); CODEPTR (code, o[0]);
}
code = backUpStackPtr(cfg, code);
- s390_lg (code, s390_r14, 0, STK_BASE, S390_RET_ADDR_OFFSET);
+ s390_lg (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
mono_add_patch_info (cfg, code - cfg->native_code,
MONO_PATCH_INFO_METHOD_JUMP,
ins->inst_p0);
case OP_START_HANDLER: {
MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
- S390_LONG (code, stg, stg, s390_r14, 0,
+ S390_LONG (code, stg, stg, s390_r14, 0,
spvar->inst_basereg,
spvar->inst_offset);
}
if (ins->sreg1 != s390_r2)
s390_lgr(code, s390_r2, ins->sreg1);
- S390_LONG (code, lg, lg, s390_r14, 0,
+ S390_LONG (code, lg, lg, s390_r14, 0,
spvar->inst_basereg,
spvar->inst_offset);
s390_br (code, s390_r14);
case OP_ENDFINALLY: {
MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
- S390_LONG (code, lg, lg, s390_r14, 0,
+ S390_LONG (code, lg, lg, s390_r14, 0,
spvar->inst_basereg,
spvar->inst_offset);
s390_br (code, s390_r14);
void
mono_arch_patch_code (MonoMethod *method, MonoDomain *domain,
- guint8 *code, MonoJumpInfo *ji, gboolean run_cctors)
+ guint8 *code, MonoJumpInfo *ji, MonoCodeManager *dyn_code_mp, gboolean run_cctors)
{
MonoJumpInfo *patch_info;
MonoBasicBlock *bb;
MonoMethodSignature *sig;
MonoInst *inst;
- int alloc_size, pos, max_offset, i;
+ long alloc_size, pos, max_offset, i, cfa_offset = 0;
guint8 *code;
+ guint32 size;
CallInfo *cinfo;
int tracing = 0;
int lmfOffset;
cfg->native_code = code = g_malloc (cfg->code_size);
+ mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
+ emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
+ mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
if (cfg->arch.bkchain_reg != -1)
s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
alloc_size = cfg->stack_offset;
- cfg->stack_usage = alloc_size;
+ cfg->stack_usage = cfa_offset = alloc_size;
+ mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
s390_lgr (code, s390_r11, STK_BASE);
if (s390_is_imm16 (alloc_size)) {
s390_aghi (code, STK_BASE, -alloc_size);
if (cfg->frame_reg != STK_BASE)
s390_lgr (code, s390_r11, STK_BASE);
+ mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
+
/* compute max_offset in order to use short forward jumps
* we always do it on s390 because the immediate displacement
* for jumps is too small
cinfo = get_call_info (cfg, cfg->mempool, sig, sig->pinvoke);
if (cinfo->struct_ret) {
- ArgInfo *ainfo = &cinfo->ret;
- inst = cfg->vret_addr;
+ ArgInfo *ainfo = &cinfo->ret;
+ inst = cfg->vret_addr;
inst->backend.size = ainfo->vtsize;
s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
}
s390_lgr (code, s390_r13, STK_BASE);
s390_aghi (code, s390_r13, alloc_size);
}
- switch (ainfo->size) {
+
+ size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
+ ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
+ : ainfo->size);
+
+ switch (size) {
case 1:
if (ainfo->reg == STK_BASE)
s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
if (method->save_lmf)
restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
- if (cfg->flags & MONO_CFG_HAS_ALLOCA)
+ if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
+// if (cfg->frame_reg != STK_BASE)
+// s390_lgr (code, STK_BASE, cfg->frame_reg);
s390_lg (code, STK_BASE, 0, STK_BASE, 0);
- else
+ } else
code = backUpStackPtr(cfg, code);
s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
/*------------------------------------------------------------------*/
gpointer
-mono_arch_get_this_arg_from_call (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, mgreg_t *regs, guint8 *code)
+mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
{
MonoLMF *lmf = (MonoLMF *) ((gchar *) regs - sizeof(MonoLMF));
- /* FIXME: handle returning a struct */
- if (MONO_TYPE_ISSTRUCT (sig->ret))
- return (gpointer) lmf->gregs [s390_r3];
return (gpointer) lmf->gregs [s390_r2];
}
s390_lg (code, s390_r1, 0, s390_r1, 0);
}
s390_br (code, s390_r1);
- target = S390_RELATIVE(item->jmp_code, code);
+ target = S390_RELATIVE(code, item->jmp_code);
s390_patch_rel(item->jmp_code+2, target);
s390_basr (code, s390_r13, s390_r0);
s390_j (code, 6);
}
/*========================= End of Function ========================*/
-
-/*------------------------------------------------------------------*/
-/* */
-/* Name - mono_arch_find_this_argument. */
-/* */
-/* Function - */
-/* */
-/*------------------------------------------------------------------*/
-
-MonoObject *
-mono_arch_find_this_argument (mgreg_t *regs, MonoMethod *method,
- MonoGenericSharingContext *gsctx)
-{
- return mono_arch_get_this_arg_from_call (gsctx, mono_method_signature (method), regs, NULL);
-}
-
-/*========================= End of Function ========================*/