-/*
- * mini-amd64-gsharedvt.c: libcorkscrew-based native unwinder
+/**
+ * \file
+ * libcorkscrew-based native unwinder
*
* Authors:
* Zoltan Varga <vargaz@gmail.com>
* Rodrigo Kumpera <kumpera@gmail.com>
* Andi McClure <andi.mcclure@xamarin.com>
+ * Johan Lorensson <johan.lorensson@xamarin.com>
*
* Copyright 2015 Xamarin, Inc (http://www.xamarin.com)
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
#include <mono/metadata/appdomain.h>
#include <mono/metadata/marshal.h>
#include <mono/metadata/tabledefs.h>
-#include <mono/metadata/mono-debug-debugger.h>
#include <mono/metadata/profiler-private.h>
#include <mono/metadata/gc-internals.h>
#include <mono/arch/amd64/amd64-codegen.h>
case ArgOnStack: return "ArgOnStack";
case ArgValuetypeInReg: return "ArgValuetypeInReg";
case ArgValuetypeAddrInIReg: return "ArgValuetypeAddrInIReg";
+ case ArgValuetypeAddrOnStack: return "ArgValuetypeAddrOnStack";
case ArgGSharedVtInReg: return "ArgGSharedVtInReg";
case ArgGSharedVtOnStack: return "ArgGSharedVtOnStack";
case ArgNone: return "ArgNone";
/*
* Slot mapping:
+ *
+ * System V:
* 0..5 - rdi, rsi, rdx, rcx, r8, r9
* 6..13 - xmm0..xmm7
* 14.. - stack slots
+ *
+ * Windows:
+ * 0..3 - rcx, rdx, r8, r9
+ * 4..7 - xmm0..xmm3
+ * 8.. - stack slots
+ *
*/
static inline int
map_reg (int reg)
bits 24:32 - slot count
*/
#define SRC_DESCRIPTOR_MARSHAL_SHIFT 16
-#define SRC_DESCRIPTOR_MARSHAL_MASK 0x0Ff
+#define SRC_DESCRIPTOR_MARSHAL_MASK 0x0ff
#define SLOT_COUNT_SHIFT 24
#define SLOT_COUNT_MASK 0xff
src = g_malloc (nsrc * sizeof (int));
src [0] = map_freg (sreg);
break;
+ case ArgValuetypeAddrInIReg:
+ nsrc = 1;
+ src = g_malloc (nsrc * sizeof (int));
+ src [0] = map_reg (ainfo->pair_regs [0]);
+ break;
+ case ArgValuetypeAddrOnStack:
+ nsrc = 1;
+ src = g_malloc (nsrc * sizeof (int));
+ // is_source_argument adds 2 because we're skipping over the old BBP and the return address
+ // XXX this is a very fragile setup as changes in alignment for the caller reg array can cause the magic number be 3
+ src [0] = map_stack_slot (sslot + (is_source_argument ? 2 : 0));
+ break;
default:
NOT_IMPLEMENTED;
break;
*arg_marshal = GSHAREDVT_ARG_BYREF_TO_BYVAL;
*arg_slots = dst_info->nregs;
break;
+ case ArgValuetypeAddrInIReg:
+ case ArgValuetypeAddrOnStack:
+ *arg_marshal = GSHAREDVT_ARG_NONE;
+ *arg_slots = dst_info->nregs;
+ break;
default:
NOT_IMPLEMENTED; // Inappropriate value: if dst and src are gsharedvt at once, we shouldn't be here
break;
case ArgOnStack:
*arg_marshal = GSHAREDVT_ARG_BYVAL_TO_BYREF;
break;
+ case ArgValuetypeAddrInIReg:
+ case ArgValuetypeAddrOnStack:
+ *arg_marshal = GSHAREDVT_ARG_NONE;
+ break;
default:
NOT_IMPLEMENTED; // See above
break;
DEBUG_AMD64_GSHAREDVT_PRINT ("source sig: (%s) return (%s)\n", mono_signature_get_desc (caller_sig, FALSE), mono_type_full_name (mono_signature_get_return_type (caller_sig))); // Leak
DEBUG_AMD64_GSHAREDVT_PRINT ("dest sig: (%s) return (%s)\n", mono_signature_get_desc (callee_sig, FALSE), mono_type_full_name (mono_signature_get_return_type (callee_sig)));
- if (gcinfo->ret.is_gsharedvt_return_value) {
+ if (gcinfo->ret.storage == ArgGsharedvtVariableInReg) {
/*
* The return type is gsharedvt
*/
handle_marshal_when_src_gsharedvt (dst_info, &arg_marshal, &arg_slots);
handle_map_when_gsharedvt_on_stack (src_info, &nsrc, &src, TRUE);
break;
+ case ArgValuetypeAddrInIReg:
+ case ArgValuetypeAddrOnStack:
+ nsrc = get_arg_slots (src_info, &src, TRUE);
+ break;
default:
g_error ("Gsharedvt can't handle source arg type %d", (int)src_info->storage); // Inappropriate value: ArgValuetypeAddrInIReg is for returns only
}
handle_marshal_when_dst_gsharedvt (src_info, &arg_marshal);
handle_map_when_gsharedvt_on_stack (dst_info, &ndst, &dst, FALSE);
break;
+ case ArgValuetypeAddrInIReg:
+ case ArgValuetypeAddrOnStack:
+ ndst = get_arg_slots (dst_info, &dst, FALSE);
+ break;
default:
g_error ("Gsharedvt can't handle dest arg type %d", (int)dst_info->storage); // See above
}
+
+ if (arg_marshal == GSHAREDVT_ARG_BYREF_TO_BYVAL && dst_info->byte_arg_size) {
+ /* Have to load less than 4 bytes */
+ // FIXME: Signed types
+ switch (dst_info->byte_arg_size) {
+ case 1:
+ arg_marshal = GSHAREDVT_ARG_BYREF_TO_BYVAL_U1;
+ break;
+ case 2:
+ arg_marshal = GSHAREDVT_ARG_BYREF_TO_BYVAL_U2;
+ break;
+ default:
+ arg_marshal = GSHAREDVT_ARG_BYREF_TO_BYVAL_U4;
+ break;
+ }
+ }
+
if (nsrc)
src [0] |= (arg_marshal << SRC_DESCRIPTOR_MARSHAL_SHIFT) | (arg_slots << SLOT_COUNT_SHIFT);
DEBUG_AMD64_GSHAREDVT_PRINT ("-- return in (%s) out (%s) var_ret %d\n", arg_info_desc (&caller_cinfo->ret), arg_info_desc (&callee_cinfo->ret), var_ret);
if (cinfo->ret.storage == ArgValuetypeAddrInIReg) {
- /* Both the caller and the callee pass the vtype ret address in r8 */
- g_assert (cinfo->ret.storage == gcinfo->ret.storage);
+ /* Both the caller and the callee pass the vtype ret address in r8 (System V) and RCX or RDX (Windows) */
+ g_assert (gcinfo->ret.storage == ArgValuetypeAddrInIReg || gcinfo->ret.storage == ArgGsharedvtVariableInReg);
add_to_map (map, map_reg (cinfo->ret.reg), map_reg (cinfo->ret.reg));
}
info->calli = calli;
if (var_ret) {
- g_assert (gcinfo->ret.is_gsharedvt_return_value);
+ g_assert (gcinfo->ret.storage == ArgGsharedvtVariableInReg);
info->vret_arg_reg = map_reg (gcinfo->ret.reg);
DEBUG_AMD64_GSHAREDVT_PRINT ("mapping vreg_arg_reg to %d in reg %s\n", info->vret_arg_reg, mono_arch_regname (gcinfo->ret.reg));
} else {
} else {
MonoType *ret = sig->ret;
- // Unwrap enums
- if (ret->type == MONO_TYPE_VALUETYPE)
- ret = mini_type_get_underlying_type (ret);
-
+ ret = mini_type_get_underlying_type (ret);
switch (ret->type) {
case MONO_TYPE_I1:
info->ret_marshal = GSHAREDVT_RET_I1;
break;
- case MONO_TYPE_BOOLEAN:
case MONO_TYPE_U1:
info->ret_marshal = GSHAREDVT_RET_U1;
break;
case MONO_TYPE_I2:
info->ret_marshal = GSHAREDVT_RET_I2;
break;
- case MONO_TYPE_CHAR:
case MONO_TYPE_U2:
info->ret_marshal = GSHAREDVT_RET_U2;
break;
case MONO_TYPE_U:
case MONO_TYPE_PTR:
case MONO_TYPE_FNPTR:
- case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT:
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_STRING:
case MONO_TYPE_U8:
case MONO_TYPE_I8:
info->ret_marshal = GSHAREDVT_RET_I8;
break;
-
+ case MONO_TYPE_GENERICINST:
+ g_assert (!mono_type_generic_inst_is_valuetype (ret));
+ info->ret_marshal = GSHAREDVT_RET_I8;
+ break;
default:
g_error ("Gsharedvt can't handle dst type [%d]", (int)sig->ret->type);
}
info->stack_usage = ALIGN_TO (info->stack_usage, MONO_ARCH_FRAME_ALIGNMENT);
+ g_free (callee_cinfo);
+ g_free (caller_cinfo);
+
DEBUG_AMD64_GSHAREDVT_PRINT ("allocated an info at %p stack usage %d\n", info, info->stack_usage);
return info;
}
-#endif
\ No newline at end of file
+#endif