1
0
mirror of https://github.com/alliedmodders/metamod-source.git synced 2025-02-20 13:54:14 +01:00

POD returns work on GCC

--HG--
branch : hookman_autogen
extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/branches/hookman_autogen%40549
This commit is contained in:
Pavol Marko 2007-11-08 18:17:26 +00:00
parent d4bd0261f1
commit e9089e6730
5 changed files with 47 additions and 10 deletions

View File

@ -441,19 +441,25 @@ namespace SourceHook
added_to_stack += ret;
}
return added_to_stack;
}
// It is IMPORTANT that PushMemRetPtr doesn't touch ecx and eax
jit_int32_t GenContext::PushMemRetPtr(jit_int32_t save_ret_to, jit_int32_t v_place_for_memret)
{
// Memory return support
if (m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem)
{
// push address where to save it!
int reg = NextRegEBX_ECX_EDX();
int reg = REG_EDX;
IA32_Lea_DispRegImmAuto(&m_HookFunc, reg, REG_EBP,
MemRetWithTempObj() ? v_place_for_memret : save_ret_to);
IA32_Push_Reg(&m_HookFunc, reg);
added_to_stack += SIZE_PTR;
return (SH_COMP==SH_COMP_MSVC) ? 4 : 0; // varargs funcs on msvc might need this.
// gcc doesn't: callee cleans the memret ptr, caller the other params :s
}
return added_to_stack;
return 0;
}
void GenContext::SaveRetVal(int v_where, int v_place_for_memret)
@ -891,6 +897,7 @@ namespace SourceHook
IA32_Mov_Reg_Rm(&m_HookFunc, REG_ECX, REG_EAX, MOD_REG);
GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX));
gcc_clean_bytes += PushMemRetPtr(v_plugin_ret, v_place_for_memret);
IA32_Mov_Reg_Rm(&m_HookFunc, REG_EAX, REG_ECX, MOD_MEM_REG);
IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EAX, 2*SIZE_PTR);
IA32_Call_Reg(&m_HookFunc, REG_EAX);
@ -1006,6 +1013,7 @@ namespace SourceHook
IA32_Push_Reg(&m_HookFunc, REG_ECX);
// on msvc, simply leave it in ecx
#endif
gcc_clean_bytes += PushMemRetPtr(v_orig_ret, v_place_for_memret);
// call
IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EBP, v_vfnptr_origentry);
@ -1193,11 +1201,11 @@ namespace SourceHook
// on msvc, save thisptr
#if SH_COMP == SH_COMP_MSVC
const jit_int8_t v_this = -4;
jit_int8_t v_this = -4;
const int addstackoffset = -4;
IA32_Push_Reg(&m_HookFunc, REG_ECX);
#elif SH_COMP == SH_COMP_GCC
const jit_int8_t v_this = 12; // first param
jit_int8_t v_this = 12; // first param
const int addstackoffset = 0;
#endif
@ -1249,8 +1257,17 @@ namespace SourceHook
jit_int32_t v_memret_addr = 0;
if (m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem)
{
#if SH_COMP == SH_COMP_GCC
// gcc: now: first param = mem ret addr
// second param = this pointer
// third param = actual first param
v_memret_addr = 12;
v_this += 4;
param_base_offs += SIZE_PTR;
#elif SH_COMP == SH_COMP_MSVC
v_memret_addr = param_base_offs;
param_base_offs += SIZE_PTR;
#endif
}
jit_int32_t v_ret_ptr = -28 + addstackoffset;
@ -1380,8 +1397,14 @@ namespace SourceHook
IA32_Pop_Reg(&m_HookFunc, REG_EBX);
IA32_Pop_Reg(&m_HookFunc, REG_EBP);
MSVC_ONLY(IA32_Return_Popstack(&m_HookFunc, GetParamsStackSize()));
GCC_ONLY(IA32_Return(&m_HookFunc)); // :TODO: ?? Memory return? Should I pop 4 bytes then?
// gcc: Remove 4 bytes from stack on memory return
#if SH_COMP == SH_COMP_GCC
if (m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem)
IA32_Return_Popstack(&m_HookFunc, SIZE_PTR);
else
IA32_Return(&m_HookFunc);
#endif
// Store pointer for later use
// m_HookfuncVfnPtr is a pointer to a void* because SH expects a pointer
// into the hookman's vtable

View File

@ -196,6 +196,7 @@ namespace SourceHook
jit_int32_t PushBasic(jit_int32_t param_offset, const IntPassInfo &pi);
jit_int32_t PushFloat(jit_int32_t param_offset, const IntPassInfo &pi);
jit_int32_t PushObject(jit_int32_t param_offset, const IntPassInfo &pi, jit_int32_t v_place_fbrr);
jit_int32_t PushMemRetPtr(jit_int32_t save_ret_to, jit_int32_t v_place_for_memret);
void DestroyParams(jit_int32_t fbrr_base);
// Ret val processing

View File

@ -133,7 +133,7 @@ namespace
} \
template <> struct MakeRet< PodRet##size > \
{ \
static PodRet##size Do(int a) \
static PodRet##size Do(int a) NO_OPTIMIZE \
{ \
PodRet##size x; \
memset(reinterpret_cast<void*>(x.actPod.x), a, size); \
@ -155,7 +155,7 @@ namespace
} \
template <> struct MakeRet< ObjRet##size > \
{ \
static ObjRet##size Do(int a) \
static ObjRet##size Do(int a) NO_OPTIMIZE \
{ \
ObjRet##size x; \
memset(reinterpret_cast<void*>(x.actObj.x), a, size); \
@ -639,6 +639,7 @@ bool TestHookManGen(std::string &error)
/* no hooks - no hooks */
PtrBuf_Clear();
asm("int $3");
obj13 = pTest110->Func(5);
g_Inside_LeafFunc = true;

View File

@ -92,6 +92,12 @@ template <class T> struct MyRefCarrier<T&>
};
};
#if SH_COMP==SH_COMP_GCC
#define NO_OPTIMIZE __attribute__((noinline))
#else
#define NO_OPTIMIZE
#endif
// Return value maker
template <class T>
struct MakeRet

View File

@ -92,6 +92,12 @@ template <class T> struct MyRefCarrier<T&>
};
};
#if SH_COMP==SH_COMP_GCC
#define NO_OPTIMIZE __attribute__((noinline))
#else
#define NO_OPTIMIZE
#endif
// Return value maker
template <class T>
struct MakeRet