* (C) 2003 Ximian, Inc.
* Copyright 2003-2011 Novell, Inc (http://www.novell.com)
* Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include "mini.h"
#include <string.h>
amd64_patch (code, target);
}
-typedef enum {
- ArgInIReg,
- ArgInFloatSSEReg,
- ArgInDoubleSSEReg,
- ArgOnStack,
- ArgValuetypeInReg,
- ArgValuetypeAddrInIReg,
- /* gsharedvt argument passed by addr */
- ArgGSharedVtInReg,
- ArgGSharedVtOnStack,
- ArgNone /* only in pair_storage */
-} ArgStorage;
-
-typedef struct {
- gint16 offset;
- gint8 reg;
- ArgStorage storage : 8;
- gboolean is_gsharedvt_return_value : 1;
-
- /* Only if storage == ArgValuetypeInReg */
- ArgStorage pair_storage [2];
- gint8 pair_regs [2];
- /* The size of each pair (bytes) */
- int pair_size [2];
- int nregs;
- /* Only if storage == ArgOnStack */
- int arg_size; // Bytes, will always be rounded up/aligned to 8 byte boundary
-} ArgInfo;
-
-typedef struct {
- int nargs;
- guint32 stack_usage;
- guint32 reg_usage;
- guint32 freg_usage;
- gboolean need_stack_align;
- /* The index of the vret arg in the argument list */
- int vret_arg_index;
- ArgInfo ret;
- ArgInfo sig_cookie;
- ArgInfo args [1];
-} CallInfo;
-
#define DEBUG(a) if (cfg->verbose_level > 1) a
static void inline
cinfo = (CallInfo *)g_malloc0 (sizeof (CallInfo) + (sizeof (ArgInfo) * n));
cinfo->nargs = n;
+ cinfo->gsharedvt = mini_is_gsharedvt_variable_signature (sig);
gr = 0;
fr = 0;
break;
}
if (mini_is_gsharedvt_type (ret_type)) {
- cinfo->ret.storage = ArgValuetypeAddrInIReg;
- cinfo->ret.is_gsharedvt_return_value = 1;
+ cinfo->ret.storage = ArgGsharedvtVariableInReg;
break;
}
/* fall through */
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
g_assert (mini_is_gsharedvt_type (ret_type));
- cinfo->ret.storage = ArgValuetypeAddrInIReg;
- cinfo->ret.is_gsharedvt_return_value = 1;
+ cinfo->ret.storage = ArgGsharedvtVariableInReg;
break;
case MONO_TYPE_VOID:
break;
* are sometimes made using calli without sig->hasthis set, like in the delegate
* invoke wrappers.
*/
- if (cinfo->ret.storage == ArgValuetypeAddrInIReg && !is_pinvoke && (sig->hasthis || (sig->param_count > 0 && MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
+ ArgStorage ret_storage = cinfo->ret.storage;
+ if ((ret_storage == ArgValuetypeAddrInIReg || ret_storage == ArgGsharedvtVariableInReg) && !is_pinvoke && (sig->hasthis || (sig->param_count > 0 && MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
if (sig->hasthis) {
add_general (&gr, &stack_size, cinfo->args + 0);
} else {
pstart = 1;
}
add_general (&gr, &stack_size, &cinfo->ret);
- cinfo->ret.storage = ArgValuetypeAddrInIReg;
+ cinfo->ret.storage = ret_storage;
cinfo->vret_arg_index = 1;
} else {
/* this */
if (sig->hasthis)
add_general (&gr, &stack_size, cinfo->args + 0);
- if (cinfo->ret.storage == ArgValuetypeAddrInIReg) {
+ if (ret_storage == ArgValuetypeAddrInIReg || ret_storage == ArgGsharedvtVariableInReg) {
add_general (&gr, &stack_size, &cinfo->ret);
- cinfo->ret.storage = ArgValuetypeAddrInIReg;
+ cinfo->ret.storage = ret_storage;
}
}
mono_aot_register_jit_icall ("mono_amd64_throw_corlib_exception", mono_amd64_throw_corlib_exception);
mono_aot_register_jit_icall ("mono_amd64_resume_unwind", mono_amd64_resume_unwind);
mono_aot_register_jit_icall ("mono_amd64_get_original_ip", mono_amd64_get_original_ip);
-#if defined(ENABLE_GSHAREDVT)
+#if defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
mono_aot_register_jit_icall ("mono_amd64_start_gsharedvt_call", mono_amd64_start_gsharedvt_call);
#endif
cfg->ret->dreg = cinfo->ret.reg;
break;
case ArgValuetypeAddrInIReg:
+ case ArgGsharedvtVariableInReg:
/* The register is volatile */
cfg->vret_addr->opcode = OP_REGOFFSET;
cfg->vret_addr->inst_basereg = cfg->frame_reg;
cfg->ret_var_is_local = TRUE;
sig_ret = mini_get_underlying_type (sig->ret);
- if (cinfo->ret.storage == ArgValuetypeAddrInIReg) {
+ if (cinfo->ret.storage == ArgValuetypeAddrInIReg || cinfo->ret.storage == ArgGsharedvtVariableInReg) {
cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
if (G_UNLIKELY (cfg->verbose_level > 1)) {
printf ("vret_addr = ");
break;
}
case ArgValuetypeAddrInIReg:
+ case ArgGsharedvtVariableInReg:
/* Vtype returned using a hidden argument */
linfo->ret.storage = LLVMArgVtypeRetAddr;
linfo->vret_arg_index = cinfo->vret_arg_index;
MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, ((MonoInst*)cfg->arch.vret_addr_loc)->dreg, call->vret_var->dreg);
}
break;
- case ArgValuetypeAddrInIReg: {
+ case ArgValuetypeAddrInIReg:
+ case ArgGsharedvtVariableInReg: {
MonoInst *vtarg;
MONO_INST_NEW (cfg, vtarg, OP_MOVE);
vtarg->sreg1 = call->vret_var->dreg;
pindex = 1;
}
- if (dinfo->cinfo->ret.storage == ArgValuetypeAddrInIReg)
+ if (dinfo->cinfo->ret.storage == ArgValuetypeAddrInIReg || dinfo->cinfo->ret.storage == ArgGsharedvtVariableInReg)
p->regs [greg ++] = PTR_TO_GREG(ret);
for (i = pindex; i < sig->param_count; i++) {
/* Fall through */
}
case MONO_TYPE_VALUETYPE:
- if (dinfo->cinfo->ret.storage == ArgValuetypeAddrInIReg) {
+ if (dinfo->cinfo->ret.storage == ArgValuetypeAddrInIReg || dinfo->cinfo->ret.storage == ArgGsharedvtVariableInReg) {
/* Nothing to do */
} else {
ArgInfo *ainfo = &dinfo->cinfo->ret;
return code;
}
-#define REAL_PRINT_REG(text,reg) \
-mono_assert (reg >= 0); \
-amd64_push_reg (code, AMD64_RAX); \
-amd64_push_reg (code, AMD64_RDX); \
-amd64_push_reg (code, AMD64_RCX); \
-amd64_push_reg (code, reg); \
-amd64_push_imm (code, reg); \
-amd64_push_imm (code, text " %d %p\n"); \
-amd64_mov_reg_imm (code, AMD64_RAX, printf); \
-amd64_call_reg (code, AMD64_RAX); \
-amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, 3*4); \
-amd64_pop_reg (code, AMD64_RCX); \
-amd64_pop_reg (code, AMD64_RDX); \
-amd64_pop_reg (code, AMD64_RAX);
-
/* benchmark and set based on cpu */
#define LOOP_ALIGNMENT 8
#define bb_is_loop_start(bb) ((bb)->loop_body_start && (bb)->nesting)
amd64_alu_reg_imm (code, X86_CMP, AMD64_RAX, X86_FP_C0);
amd64_pop_reg (code, AMD64_RAX);
amd64_fstp (code, 0);
- EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "ArithmeticException");
+ EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, 16);
break;
case OP_TLS_GET: {
}
}
-#if defined(ENABLE_GSHAREDVT) && defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
-
-#include "../../../mono-extensions/mono/mini/mini-amd64-gsharedvt.c"
-
-#endif /* !ENABLE_GSHAREDVT */
+CallInfo*
+mono_arch_get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
+{
+ return get_call_info (mp, sig);
+}