String GDMonoMethod::get_ret_type_full_name() const { MonoMethodSignature *method_sig = mono_method_signature(mono_method); char *ret_str = mono_type_full_name(mono_signature_get_return_type(method_sig)); String res = ret_str; mono_free(ret_str); return res; }
void GDMonoMethod::_update_signature(MonoMethodSignature *p_method_sig) { params_count = mono_signature_get_param_count(p_method_sig); MonoType *ret_type = mono_signature_get_return_type(p_method_sig); if (ret_type) { return_type.type_encoding = mono_type_get_type(ret_type); if (return_type.type_encoding != MONO_TYPE_VOID) { MonoClass *ret_type_class = mono_class_from_mono_type(ret_type); return_type.type_class = GDMono::get_singleton()->get_class(ret_type_class); } } void *iter = NULL; MonoType *param_raw_type; while ((param_raw_type = mono_signature_get_params(p_method_sig, &iter)) != NULL) { ManagedType param_type; param_type.type_encoding = mono_type_get_type(param_raw_type); MonoClass *param_type_class = mono_class_from_mono_type(param_raw_type); param_type.type_class = GDMono::get_singleton()->get_class(param_type_class); param_types.push_back(param_type); } }
GDMonoProperty::GDMonoProperty(MonoProperty *p_mono_property, GDMonoClass *p_owner) { owner = p_owner; mono_property = p_mono_property; name = mono_property_get_name(mono_property); MonoMethod *prop_method = mono_property_get_get_method(mono_property); if (prop_method) { MonoMethodSignature *getter_sig = mono_method_signature(prop_method); MonoType *ret_type = mono_signature_get_return_type(getter_sig); type.type_encoding = mono_type_get_type(ret_type); MonoClass *ret_type_class = mono_class_from_mono_type(ret_type); type.type_class = GDMono::get_singleton()->get_class(ret_type_class); } else { prop_method = mono_property_get_set_method(mono_property); MonoMethodSignature *setter_sig = mono_method_signature(prop_method); void *iter = NULL; MonoType *param_raw_type = mono_signature_get_params(setter_sig, &iter); type.type_encoding = mono_type_get_type(param_raw_type); MonoClass *param_type_class = mono_class_from_mono_type(param_raw_type); type.type_class = GDMono::get_singleton()->get_class(param_type_class); } attrs_fetched = false; attributes = NULL; }
void MonoMethod::cacheSignature() const { MonoMethodSignature* methodSignature = mono_method_signature(mMethod); MonoType* returnType = mono_signature_get_return_type(methodSignature); if (returnType != nullptr) { ::MonoClass* returnClass = mono_class_from_mono_type(returnType); if (returnClass != nullptr) mCachedReturnType = MonoManager::instance().findClass(returnClass); } mCachedNumParameters = (UINT32)mono_signature_get_param_count(methodSignature); if (mCachedParameters != nullptr) { bs_free(mCachedParameters); mCachedParameters = nullptr; } if (mCachedNumParameters > 0) { mCachedParameters = (MonoClass**)bs_alloc(mCachedNumParameters * sizeof(MonoClass*)); void* iter = nullptr; for (UINT32 i = 0; i < mCachedNumParameters; i++) { MonoType* curParamType = mono_signature_get_params(methodSignature, &iter); ::MonoClass* rawClass = mono_class_from_mono_type(curParamType); mCachedParameters[i] = MonoManager::instance().findClass(rawClass); } } mIsStatic = !mono_signature_is_instance(methodSignature); mHasCachedSignature = true; }
void CPipeServer::GetMethodSignature() { void *method = (void *)ReadQword(); void *methodsignature = mono_method_signature(method); char *sig = mono_signature_get_desc(methodsignature, TRUE); int paramcount = mono_signature_get_param_count(methodsignature); char **names=(char **)calloc(sizeof(char *), paramcount); int i; mono_method_get_param_names(method, (const char **)names); WriteByte(paramcount); for (i = 0; i < paramcount; i++) { if (names[i]) { WriteByte(strlen(names[i])); Write(names[i], strlen(names[i])); } else WriteByte(0); } free(names); WriteWord(strlen(sig)); Write(sig, strlen(sig)); g_free(sig); //12/5/2014:send the returntype as well void *returntype = mono_signature_get_return_type(methodsignature); if (returntype) { char *tname = mono_type_get_name(returntype); if (tname) { WriteByte(strlen(tname)); Write(tname, strlen(tname)); g_free(tname); } else WriteByte(0); } else WriteByte(0); }
String GDMonoMethod::get_full_name_no_class() const { String res; MonoMethodSignature *method_sig = mono_method_signature(mono_method); char *ret_str = mono_type_full_name(mono_signature_get_return_type(method_sig)); res += ret_str; mono_free(ret_str); res += " "; res += name; res += "("; char *sig_desc = mono_signature_get_desc(method_sig, true); res += sig_desc; mono_free(sig_desc); res += ")"; return res; }
gpointer mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, gboolean gsharedvt_in, gint32 vcall_offset, gboolean calli) { GSharedVtCallInfo *info; CallInfo *caller_cinfo, *callee_cinfo; MonoMethodSignature *caller_sig, *callee_sig; int aindex, i; gboolean var_ret = FALSE; CallInfo *cinfo, *gcinfo; MonoMethodSignature *sig, *gsig; GPtrArray *map; if (gsharedvt_in) { caller_sig = normal_sig; callee_sig = gsharedvt_sig; caller_cinfo = mono_arch_get_call_info (NULL, caller_sig); callee_cinfo = mono_arch_get_call_info (NULL, callee_sig); } else { callee_sig = normal_sig; caller_sig = gsharedvt_sig; callee_cinfo = mono_arch_get_call_info (NULL, callee_sig); caller_cinfo = mono_arch_get_call_info (NULL, caller_sig); } /* * If GSHAREDVT_IN is true, this means we are transitioning from normal to gsharedvt code. The caller uses the * normal call signature, while the callee uses the gsharedvt signature. * If GSHAREDVT_IN is false, its the other way around. */ /* sig/cinfo describes the normal call, while gsig/gcinfo describes the gsharedvt call */ if (gsharedvt_in) { sig = caller_sig; gsig = callee_sig; cinfo = caller_cinfo; gcinfo = callee_cinfo; } else { sig = callee_sig; gsig = caller_sig; cinfo = callee_cinfo; gcinfo = caller_cinfo; } 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.storage == ArgGsharedvtVariableInReg) { /* * The return type is gsharedvt */ var_ret = TRUE; } /* * The stack looks like this: * <arguments> * <trampoline frame> * <call area> * We have to map the stack slots in <arguments> to the stack slots in <call area>. */ map = g_ptr_array_new (); for (aindex = 0; aindex < cinfo->nargs; ++aindex) { ArgInfo *src_info = &caller_cinfo->args [aindex]; ArgInfo *dst_info = &callee_cinfo->args [aindex]; int *src = NULL, *dst = NULL; int nsrc = -1, ndst = -1, nslots = 0; int arg_marshal = GSHAREDVT_ARG_NONE; int arg_slots = 0; // Size in quadwords DEBUG_AMD64_GSHAREDVT_PRINT ("-- arg %d in (%s) out (%s)\n", aindex, arg_info_desc (src_info), arg_info_desc (dst_info)); switch (src_info->storage) { case ArgInIReg: case ArgInDoubleSSEReg: case ArgInFloatSSEReg: case ArgValuetypeInReg: case ArgOnStack: nsrc = get_arg_slots (src_info, &src, TRUE); break; case ArgGSharedVtInReg: handle_marshal_when_src_gsharedvt (dst_info, &arg_marshal, &arg_slots); handle_map_when_gsharedvt_in_reg (src_info, &nsrc, &src); break; case ArgGSharedVtOnStack: 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 } switch (dst_info->storage) { case ArgInIReg: case ArgInDoubleSSEReg: case ArgInFloatSSEReg: case ArgOnStack: case ArgValuetypeInReg: ndst = get_arg_slots (dst_info, &dst, FALSE); break; case ArgGSharedVtInReg: handle_marshal_when_dst_gsharedvt (src_info, &arg_marshal); handle_map_when_gsharedvt_in_reg (dst_info, &ndst, &dst); break; case ArgGSharedVtOnStack: 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 (nsrc) src [0] |= (arg_marshal << SRC_DESCRIPTOR_MARSHAL_SHIFT) | (arg_slots << SLOT_COUNT_SHIFT); /* Merge and add to the global list*/ nslots = MIN (nsrc, ndst); DEBUG_AMD64_GSHAREDVT_PRINT ("nsrc %d ndst %d\n", nsrc, ndst); for (i = 0; i < nslots; ++i) add_to_map (map, src [i], dst [i]); g_free (src); g_free (dst); } 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 (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 = mono_domain_alloc0 (mono_domain_get (), sizeof (GSharedVtCallInfo) + (map->len * sizeof (int))); info->addr = addr; info->stack_usage = callee_cinfo->stack_usage; info->ret_marshal = GSHAREDVT_RET_NONE; info->gsharedvt_in = gsharedvt_in ? 1 : 0; info->vret_slot = -1; info->calli = calli; if (var_ret) { 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 { info->vret_arg_reg = -1; } #ifdef DEBUG_AMD64_GSHAREDVT printf ("final map:\n"); for (i = 0; i < map->len; i += 2) { printf ("\t[%d] src %x dst %x\n ", i / 2, GPOINTER_TO_UINT (g_ptr_array_index (map, i)), GPOINTER_TO_UINT (g_ptr_array_index (map, i + 1))); } #endif info->vcall_offset = vcall_offset; info->map_count = map->len / 2; for (i = 0; i < map->len; ++i) info->map [i] = GPOINTER_TO_UINT (g_ptr_array_index (map, i)); g_ptr_array_free (map, TRUE); /* Compute return value marshalling */ if (var_ret) { /* Compute return value marshalling */ switch (cinfo->ret.storage) { case ArgInIReg: if (!gsharedvt_in || sig->ret->byref) { info->ret_marshal = GSHAREDVT_RET_IREGS_1; } else { MonoType *ret = sig->ret; // Unwrap enums if (ret->type == MONO_TYPE_VALUETYPE) 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_I4: info->ret_marshal = GSHAREDVT_RET_I4; break; case MONO_TYPE_U4: info->ret_marshal = GSHAREDVT_RET_U4; break; case MONO_TYPE_I: 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); } } break; case ArgValuetypeInReg: info->ret_marshal = GSHAREDVT_RET_IREGS_1 - 1 + cinfo->ret.nregs; g_assert (cinfo->ret.nregs == 1); // ABI supports 2-register return but we do not implement this. break; case ArgInDoubleSSEReg: case ArgInFloatSSEReg: info->ret_marshal = GSHAREDVT_RET_R8; break; case ArgValuetypeAddrInIReg: break; default: g_error ("Can't marshal return of storage [%d] %s", (int)cinfo->ret.storage, storage_name (cinfo->ret.storage)); } if (gsharedvt_in && cinfo->ret.storage != ArgValuetypeAddrInIReg) { /* Allocate stack space for the return value */ info->vret_slot = map_stack_slot (info->stack_usage / sizeof (gpointer)); info->stack_usage += mono_type_stack_size_internal (normal_sig->ret, NULL, FALSE) + sizeof (gpointer); } DEBUG_AMD64_GSHAREDVT_PRINT ("RET marshal is %s\n", ret_marshal_name [info->ret_marshal]); } 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; }
/* * ex, v = mono.call_method (obj, method, args) * method 被调用的method方法(MonoMethod*) * thiz 被调用的method的this指针, static函数请填0 * args 参数表 * 返回值 : * ex : 若无异常发生, 该值为nil * v : 函数返回值 */ static int l_call_method (lua_State *L) { if (lua_gettop (L) < 2) luaL_error (L, "call_method need lest 2 args."); MonoObject *obj = (MonoObject*)lua_touserdata (L, 1); MonoMethod *method = (MonoMethod*)lua_touserdata (L, 2); if (!method) luaL_error (L, "call_method need 2th arg not nil."); MonoObject *ex = 0; void *ret = call_method (L, 3, obj, method, &ex); if (ex) lua_pushlightuserdata (L, ex); else lua_pushnil (L); MonoMethodSignature *sig = mono_method_signature (method); MonoType *ret_type = mono_signature_get_return_type (sig); if (mono_type_is_reference (ret_type)) { lua_pushlightuserdata (L, ret); } else { switch (mono_type_get_type (ret_type)) { case MONO_TYPE_VOID: lua_pushnil (L); break; case MONO_TYPE_BOOLEAN: lua_pushboolean (L, *(bool*)mono_object_unbox (obj)); break; case MONO_TYPE_U2: case MONO_TYPE_CHAR: /*char 用int来表示*/ lua_pushinteger (L, *(uint16_t*)mono_object_unbox (obj)); break; case MONO_TYPE_I1: lua_pushinteger(L, *(int8_t*)mono_object_unbox (obj)); break; case MONO_TYPE_U1: lua_pushinteger(L, *(uint8_t*)mono_object_unbox (obj)); break; case MONO_TYPE_I2: lua_pushinteger (L, *(int16_t*)mono_object_unbox (obj)); break; case MONO_TYPE_I4: lua_pushinteger(L, *(int32_t*)mono_object_unbox (obj)); break; case MONO_TYPE_VALUETYPE: case MONO_TYPE_U4: lua_pushinteger(L, *(uint32_t*)mono_object_unbox (obj)); break; case MONO_TYPE_I8: case MONO_TYPE_U8: { void *v = mono_object_unbox (obj); memcpy (lua_newuserdata (L, sizeof (int64_t)), v, sizeof (int64_t)); break; } case MONO_TYPE_R4: lua_pushnumber(L, *(float*)mono_object_unbox (obj)); break; case MONO_TYPE_R8: lua_pushnumber(L, *(double*)mono_object_unbox (obj)); break; case MONO_TYPE_I: case MONO_TYPE_U: luaL_error (L, "donot support the intptr & uintptr."); case MONO_TYPE_MVAR: luaL_error (L, "generic method dont be supported."); case MONO_TYPE_PTR: luaL_error (L, "dont support the ptr type."); default: luaL_error (L, "unknow method args type : 0x%02X", mono_type_get_type (ret_type)); } } return 2; }
mioType mioMethod::getReturnType() const { if (!mmethod) { return nullptr; } MonoMethodSignature *sig = mono_method_signature(mmethod); return mono_signature_get_return_type(sig); }