mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2025-02-20 13:54:14 +01:00
Completed support for reference returns + added simple test for it
--HG-- branch : hookman_autogen extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/branches/hookman_autogen%40539
This commit is contained in:
parent
2c8203f263
commit
b7e00841b0
@ -965,35 +965,46 @@ namespace SourceHook
|
||||
m_HookFunc.rewrite(tmppos2, static_cast<jit_uint32_t>(counter2));
|
||||
|
||||
// *v_orig_ret = *v_override_ret
|
||||
if (m_Proto.GetRet().pAssignOperator)
|
||||
if (m_Proto.GetRet().flags & PassInfo::PassFlag_ByRef)
|
||||
{
|
||||
// lea edx, [ebp + v_override_ret] <-- src addr
|
||||
// lea ecx, [ebp + v_orig_ret] <-- dest addr
|
||||
// gcc: push ecx
|
||||
// push edx <-- src addr
|
||||
// call it
|
||||
// mov ecx, [ebp + v_override_ret]
|
||||
// mov [ebp + v_orig_ret], ecx
|
||||
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EDX, REG_EBP, v_override_ret);
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_orig_ret);
|
||||
#if SH_COMP == SH_COMP_GCC
|
||||
IA32_Push_Reg(&m_HookFunc, REG_ECX);
|
||||
#endif
|
||||
IA32_Push_Reg(&m_HookFunc, REG_EDX);
|
||||
|
||||
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pAssignOperator));
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||
IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_ECX, REG_EBP, v_override_ret);
|
||||
IA32_Mov_Rm_Reg_DispAuto(&m_HookFunc, REG_EBP, REG_ECX, v_orig_ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
// bitwise copy
|
||||
BitwiseCopy_Setup();
|
||||
if (m_Proto.GetRet().pAssignOperator)
|
||||
{
|
||||
// lea edx, [ebp + v_override_ret] <-- src addr
|
||||
// lea ecx, [ebp + v_orig_ret] <-- dest addr
|
||||
// gcc: push ecx
|
||||
// push edx <-- src addr
|
||||
// call it
|
||||
|
||||
//lea edi, [ebp+v_orig_ret] <-- destination
|
||||
//lea esi, [ebp+v_override_ret] <-- src
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EDI, REG_EBP, v_orig_ret);
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ESI, REG_EBP, v_override_ret);
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EDX, REG_EBP, v_override_ret);
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_orig_ret);
|
||||
#if SH_COMP == SH_COMP_GCC
|
||||
IA32_Push_Reg(&m_HookFunc, REG_ECX);
|
||||
#endif
|
||||
IA32_Push_Reg(&m_HookFunc, REG_EDX);
|
||||
|
||||
BitwiseCopy_Do(m_Proto.GetRet().size);
|
||||
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pAssignOperator));
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||
}
|
||||
else
|
||||
{
|
||||
// bitwise copy
|
||||
BitwiseCopy_Setup();
|
||||
|
||||
//lea edi, [ebp+v_orig_ret] <-- destination
|
||||
//lea esi, [ebp+v_override_ret] <-- src
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EDI, REG_EBP, v_orig_ret);
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ESI, REG_EBP, v_override_ret);
|
||||
|
||||
BitwiseCopy_Do(m_Proto.GetRet().size);
|
||||
}
|
||||
}
|
||||
|
||||
// skip don't call label target:
|
||||
@ -1194,7 +1205,8 @@ namespace SourceHook
|
||||
IA32_Mov_Rm_Imm32_Disp8(&m_HookFunc, REG_EBP, MRES_IGNORED, v_status);
|
||||
|
||||
// Call constructors for ret vars if required
|
||||
if(m_Proto.GetRet().pNormalCtor)
|
||||
if((m_Proto.GetRet().flags & PassInfo::PassFlag_ByVal) &&
|
||||
m_Proto.GetRet().pNormalCtor)
|
||||
{
|
||||
// :TODO: Gcc version
|
||||
|
||||
@ -1256,7 +1268,8 @@ namespace SourceHook
|
||||
DoReturn(v_ret_ptr, v_memret_addr);
|
||||
|
||||
// Call destructors of orig_ret/ ...
|
||||
if(m_Proto.GetRet().pDtor)
|
||||
if((m_Proto.GetRet().flags & PassInfo::PassFlag_ByVal) &&
|
||||
m_Proto.GetRet().pDtor)
|
||||
{
|
||||
// Preserve return value in EAX(:EDX)
|
||||
IA32_Push_Reg(&m_HookFunc, REG_EAX);
|
||||
|
@ -371,6 +371,40 @@ namespace
|
||||
THGM_SETUP_RI(110, ObjRet13, SourceHook::PassInfo::PassType_Object,
|
||||
SourceHook::PassInfo::PassFlag_ByVal | SourceHook::PassInfo::PassFlag_OCtor | SourceHook::PassInfo::PassFlag_ODtor |
|
||||
SourceHook::PassInfo::PassFlag_CCtor | SourceHook::PassInfo::PassFlag_AssignOp);
|
||||
|
||||
MAKE_OBJRET(111);
|
||||
ObjRet111 g_O111_0;
|
||||
ObjRet111 g_O111_1;
|
||||
ObjRet111 g_O111_2;
|
||||
ObjRet111 g_O111_3;
|
||||
ObjRet111 g_O111_4;
|
||||
|
||||
template <>
|
||||
struct MakeRet< ObjRet111& >
|
||||
{
|
||||
static ObjRet111 &Do(int a)
|
||||
{
|
||||
switch (a)
|
||||
{
|
||||
case 0:
|
||||
return g_O111_0;
|
||||
case 1:
|
||||
return g_O111_1;
|
||||
case 2:
|
||||
return g_O111_2;
|
||||
case 3:
|
||||
return g_O111_3;
|
||||
default:
|
||||
return g_O111_4;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
THGM_MAKE_TEST0(111, ObjRet111& );
|
||||
THGM_SETUP_PI0(111);
|
||||
THGM_SETUP_RI(111, ObjRet111& , SourceHook::PassInfo::PassType_Object,
|
||||
SourceHook::PassInfo::PassFlag_ByRef | SourceHook::PassInfo::PassFlag_OCtor | SourceHook::PassInfo::PassFlag_ODtor |
|
||||
SourceHook::PassInfo::PassFlag_CCtor | SourceHook::PassInfo::PassFlag_AssignOp);
|
||||
}
|
||||
|
||||
bool TestHookManGen(std::string &error)
|
||||
@ -378,6 +412,15 @@ bool TestHookManGen(std::string &error)
|
||||
GET_SHPTR(g_SHPtr);
|
||||
g_PLID = 1337;
|
||||
|
||||
// 5 Global constructors (g_O111_*)
|
||||
CHECK_STATES((&g_States,
|
||||
new State_ObjOCtor_Called(111),
|
||||
new State_ObjOCtor_Called(111),
|
||||
new State_ObjOCtor_Called(111),
|
||||
new State_ObjOCtor_Called(111),
|
||||
new State_ObjOCtor_Called(111),
|
||||
NULL), "GlobCtors");
|
||||
|
||||
THGM_DO_TEST_void(0, ());
|
||||
|
||||
THGM_DO_TEST_void(1, (100));
|
||||
@ -750,6 +793,10 @@ bool TestHookManGen(std::string &error)
|
||||
THGM_REMOVE_HOOK(110, 3);
|
||||
THGM_REMOVE_HOOK(110, 4);
|
||||
|
||||
|
||||
// RefRet
|
||||
THGM_DO_TEST(111, ());
|
||||
|
||||
// Shutdown now!
|
||||
// If we don't SH will auto-shutdown _after_ genc's destructor is called
|
||||
// -> crash
|
||||
|
@ -518,6 +518,7 @@ std::ostream& operator <<(std::ostream &os,const ParamState6<0, p1, p2, p3, p4,
|
||||
|
||||
#define THGM_MAKE_TEST0(id, ret_type) \
|
||||
struct TestClass##id; \
|
||||
typedef ret_type RetType##id; \
|
||||
typedef ParamState0<0 > ParamState_m##id; \
|
||||
MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \
|
||||
MAKE_STATE_3(State_Deleg1_##id, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \
|
||||
@ -728,6 +729,7 @@ std::ostream& operator <<(std::ostream &os,const ParamState6<0, p1, p2, p3, p4,
|
||||
|
||||
#define THGM_MAKE_TEST1(id, ret_type, param1) \
|
||||
struct TestClass##id; \
|
||||
typedef ret_type RetType##id; \
|
||||
typedef ParamState1<0, param1 > ParamState_m##id; \
|
||||
MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \
|
||||
MAKE_STATE_3(State_Deleg1_##id, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \
|
||||
@ -938,6 +940,7 @@ std::ostream& operator <<(std::ostream &os,const ParamState6<0, p1, p2, p3, p4,
|
||||
|
||||
#define THGM_MAKE_TEST2(id, ret_type, param1, param2) \
|
||||
struct TestClass##id; \
|
||||
typedef ret_type RetType##id; \
|
||||
typedef ParamState2<0, param1, param2 > ParamState_m##id; \
|
||||
MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \
|
||||
MAKE_STATE_3(State_Deleg1_##id, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \
|
||||
@ -1148,6 +1151,7 @@ std::ostream& operator <<(std::ostream &os,const ParamState6<0, p1, p2, p3, p4,
|
||||
|
||||
#define THGM_MAKE_TEST3(id, ret_type, param1, param2, param3) \
|
||||
struct TestClass##id; \
|
||||
typedef ret_type RetType##id; \
|
||||
typedef ParamState3<0, param1, param2, param3 > ParamState_m##id; \
|
||||
MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \
|
||||
MAKE_STATE_3(State_Deleg1_##id, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \
|
||||
@ -1358,6 +1362,7 @@ std::ostream& operator <<(std::ostream &os,const ParamState6<0, p1, p2, p3, p4,
|
||||
|
||||
#define THGM_MAKE_TEST4(id, ret_type, param1, param2, param3, param4) \
|
||||
struct TestClass##id; \
|
||||
typedef ret_type RetType##id; \
|
||||
typedef ParamState4<0, param1, param2, param3, param4 > ParamState_m##id; \
|
||||
MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \
|
||||
MAKE_STATE_3(State_Deleg1_##id, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \
|
||||
@ -1568,6 +1573,7 @@ std::ostream& operator <<(std::ostream &os,const ParamState6<0, p1, p2, p3, p4,
|
||||
|
||||
#define THGM_MAKE_TEST5(id, ret_type, param1, param2, param3, param4, param5) \
|
||||
struct TestClass##id; \
|
||||
typedef ret_type RetType##id; \
|
||||
typedef ParamState5<0, param1, param2, param3, param4, param5 > ParamState_m##id; \
|
||||
MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \
|
||||
MAKE_STATE_3(State_Deleg1_##id, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \
|
||||
@ -1778,6 +1784,7 @@ std::ostream& operator <<(std::ostream &os,const ParamState6<0, p1, p2, p3, p4,
|
||||
|
||||
#define THGM_MAKE_TEST6(id, ret_type, param1, param2, param3, param4, param5, param6) \
|
||||
struct TestClass##id; \
|
||||
typedef ret_type RetType##id; \
|
||||
typedef ParamState6<0, param1, param2, param3, param4, param5, param6 > ParamState_m##id; \
|
||||
MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \
|
||||
MAKE_STATE_3(State_Deleg1_##id, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \
|
||||
@ -2015,10 +2022,21 @@ std::ostream& operator <<(std::ostream &os,const ParamState6<0, p1, p2, p3, p4,
|
||||
THGM_REMOVE_HOOK(id, 3); \
|
||||
THGM_REMOVE_HOOK(id, 4);
|
||||
|
||||
template<class T>
|
||||
T ComparableRef(T x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T* ComparableRef(T& x)
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
|
||||
#define THGM_CALLS(id, call_params, exp_ret_norm, exp_ret_shcall, err) \
|
||||
CHECK_COND(pTest##id->Func call_params == exp_ret_norm, err " /retcallnorm"); \
|
||||
CHECK_COND(SH_CALL(pTest##id, &TestClass##id::Func) call_params == exp_ret_shcall, err " /retcallshcall");
|
||||
CHECK_COND(ComparableRef<RetType##id>(pTest##id->Func call_params) == ComparableRef<RetType##id>(MakeRet< RetType##id >::Do(exp_ret_norm)), err " /retcallnorm"); \
|
||||
CHECK_COND(ComparableRef<RetType##id>(SH_CALL(pTest##id, &TestClass##id::Func) call_params) == ComparableRef<RetType##id>(MakeRet< RetType##id >::Do(exp_ret_shcall)), err " /retcallshcall");
|
||||
|
||||
#define THGM_DO_TEST(id, call_params) \
|
||||
setuppi_##id(); \
|
||||
|
@ -260,6 +260,7 @@ std::ostream& operator <<(std::ostream &os,const ParamState$1<0@[$2,1,$1:, p$2@]
|
||||
|
||||
#define THGM_MAKE_TEST$1(id, ret_type@[$2,1,$1:, param$2@]) \
|
||||
struct TestClass##id; \
|
||||
typedef ret_type RetType##id; \
|
||||
typedef ParamState$1<0@[$2,1,$1:, param$2@] > ParamState_m##id; \
|
||||
MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \
|
||||
MAKE_STATE_3(State_Deleg1_##id, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \
|
||||
@ -497,10 +498,21 @@ std::ostream& operator <<(std::ostream &os,const ParamState$1<0@[$2,1,$1:, p$2@]
|
||||
THGM_REMOVE_HOOK(id, 3); \
|
||||
THGM_REMOVE_HOOK(id, 4);
|
||||
|
||||
template<class T>
|
||||
T ComparableRef(T x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T* ComparableRef(T& x)
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
|
||||
#define THGM_CALLS(id, call_params, exp_ret_norm, exp_ret_shcall, err) \
|
||||
CHECK_COND(pTest##id->Func call_params == exp_ret_norm, err " /retcallnorm"); \
|
||||
CHECK_COND(SH_CALL(pTest##id, &TestClass##id::Func) call_params == exp_ret_shcall, err " /retcallshcall");
|
||||
CHECK_COND(ComparableRef<RetType##id>(pTest##id->Func call_params) == ComparableRef<RetType##id>(MakeRet< RetType##id >::Do(exp_ret_norm)), err " /retcallnorm"); \
|
||||
CHECK_COND(ComparableRef<RetType##id>(SH_CALL(pTest##id, &TestClass##id::Func) call_params) == ComparableRef<RetType##id>(MakeRet< RetType##id >::Do(exp_ret_shcall)), err " /retcallshcall");
|
||||
|
||||
#define THGM_DO_TEST(id, call_params) \
|
||||
setuppi_##id(); \
|
||||
|
Loading…
x
Reference in New Issue
Block a user