1
0
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:
Pavol Marko 2007-11-02 12:41:00 +00:00
parent 2c8203f263
commit b7e00841b0
4 changed files with 118 additions and 28 deletions

View File

@ -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);

View File

@ -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

View File

@ -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(); \

View File

@ -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(); \