faluco@739: /** faluco@739: * vim: set ts=4 : faluco@739: * =============================================================== faluco@739: * SourceMod, Copyright (C) 2004-2007 AlliedModders LLC. faluco@739: * All rights reserved. faluco@739: * =============================================================== faluco@739: * faluco@739: * This file is part of the SourceMod/SourcePawn SDK. This file may only be faluco@739: * used or modified under the Terms and Conditions of its License Agreement, faluco@739: * which is found in public/licenses/LICENSE.txt. As of this notice, derivative faluco@739: * works must be licensed under the GNU General Public License (version 2 or faluco@739: * greater). A copy of the GPL is included under public/licenses/GPL.txt. faluco@739: * faluco@739: * To view the latest information, see: http://www.sourcemod.net/license.php faluco@739: * faluco@739: * Version: $Id$ faluco@739: */ faluco@739: faluco@739: #include faluco@739: #include "extension.h" faluco@739: #include faluco@739: #include faluco@739: #include "jit_call.h" faluco@739: faluco@739: jit_uint32_t g_StackUsage = 0; faluco@739: jit_uint32_t g_RegDecoder = 0; faluco@739: faluco@739: /******************** faluco@739: * Assembly Helpers * faluco@739: ********************/ faluco@739: faluco@739: inline jit_uint8_t _DecodeRegister3(jit_uint32_t val) faluco@739: { faluco@739: switch (val % 3) faluco@739: { faluco@739: case 0: faluco@739: { faluco@739: return REG_EAX; faluco@739: } faluco@739: case 1: faluco@739: { faluco@739: return REG_EDX; faluco@739: } faluco@739: case 2: faluco@739: { faluco@739: return REG_ECX; faluco@739: } faluco@739: } faluco@739: faluco@739: /* Should never happen */ faluco@739: return 0xFF; faluco@739: } faluco@739: faluco@739: /******************** faluco@739: * Assembly Opcodes * faluco@739: ********************/ faluco@739: faluco@739: inline void Write_Execution_Prologue(JitWriter *jit, bool is_void, bool has_params) faluco@739: { faluco@739: //push ebp faluco@739: //mov ebp, esp faluco@739: //if !is_void faluco@739: // push edi faluco@739: // mov edi, [ebp+12] faluco@739: //if has_params faluco@739: // push ebx faluco@739: // mov ebx, [ebp+8] faluco@739: IA32_Push_Reg(jit, REG_EBP); faluco@739: IA32_Mov_Reg_Rm(jit, REG_EBP, REG_ESP, MOD_REG); faluco@739: if (!is_void) faluco@739: { faluco@739: IA32_Push_Reg(jit, REG_EDI); faluco@739: IA32_Mov_Reg_Rm_Disp8(jit, REG_EDI, REG_EBP, 12); faluco@739: } faluco@739: if (has_params) faluco@739: { faluco@739: IA32_Push_Reg(jit, REG_EBX); faluco@739: IA32_Mov_Reg_Rm_Disp8(jit, REG_EBX, REG_EBP, 8); faluco@739: } faluco@739: } faluco@739: faluco@739: inline void Write_Function_Epilogue(JitWriter *jit, bool is_void, bool has_params) faluco@739: { faluco@739: //if has_params faluco@739: // pop ebx faluco@739: //if !is_void faluco@739: // pop edi faluco@739: //mov esp, ebp faluco@739: //pop ebp faluco@739: //ret faluco@739: if (has_params) faluco@739: { faluco@739: IA32_Pop_Reg(jit, REG_EBX); faluco@739: } faluco@739: if (!is_void) faluco@739: { faluco@739: IA32_Pop_Reg(jit, REG_EDI); faluco@739: } faluco@739: IA32_Mov_Reg_Rm(jit, REG_ESP, REG_EBP, MOD_REG); faluco@739: IA32_Pop_Reg(jit, REG_EBP); faluco@739: IA32_Return(jit); faluco@739: } faluco@739: faluco@739: inline void Write_PushPOD(JitWriter *jit, const PassEncode *pEnc) faluco@739: { faluco@739: jit_uint8_t reg = _DecodeRegister3(g_RegDecoder++); faluco@739: faluco@739: if (pEnc->info.flags & PASSFLAG_BYVAL) faluco@739: { faluco@739: switch (pEnc->info.size) faluco@739: { faluco@739: case 1: faluco@739: { faluco@739: //xor reg, reg faluco@739: //mov reg, BYTE PTR [ebx+] faluco@739: //push reg faluco@739: IA32_Xor_Reg_Rm(jit, reg, reg, MOD_REG); faluco@739: if (pEnc->offset < SCHAR_MAX) faluco@739: { faluco@739: IA32_Mov_Reg8_Rm8_Disp8(jit, reg, REG_EBX, (jit_int8_t)pEnc->offset); faluco@739: } else if (!pEnc->offset) { faluco@739: IA32_Mov_Reg8_Rm8(jit, reg, REG_EBX, MOD_MEM_REG); faluco@739: } else { faluco@739: IA32_Mov_Reg8_Rm8_Disp32(jit, reg, REG_EBX, pEnc->offset); faluco@739: } faluco@739: IA32_Push_Reg(jit, reg); faluco@739: faluco@739: g_StackUsage += 4; faluco@739: break; faluco@739: } faluco@739: case 2: faluco@739: { faluco@739: //xor reg, reg faluco@739: //mov reg, WORD PTR [ebx+] faluco@739: //push reg faluco@739: IA32_Xor_Reg_Rm(jit, reg, reg, MOD_REG); faluco@739: jit->write_ubyte(IA32_16BIT_PREFIX); faluco@739: if (pEnc->offset < SCHAR_MAX) faluco@739: { faluco@739: IA32_Mov_Reg_Rm_Disp8(jit, reg, REG_EBX, (jit_int8_t)pEnc->offset); faluco@739: } else if (!pEnc->offset) { faluco@739: IA32_Mov_Reg_Rm(jit, reg, REG_EBX, MOD_MEM_REG); faluco@739: } else { faluco@739: IA32_Mov_Reg_Rm_Disp32(jit, reg, REG_EBX, pEnc->offset); faluco@739: } faluco@739: IA32_Push_Reg(jit, reg); faluco@739: faluco@739: g_StackUsage += 4; faluco@739: break; faluco@739: } faluco@739: case 4: faluco@739: { faluco@739: //mov reg, DWORD PTR [ebx+] faluco@739: //push reg faluco@739: if (pEnc->offset < SCHAR_MAX) faluco@739: { faluco@739: IA32_Mov_Reg_Rm_Disp8(jit, reg, REG_EBX, (jit_int8_t)pEnc->offset); faluco@739: } else if (!pEnc->offset) { faluco@739: IA32_Mov_Reg_Rm(jit, reg, REG_EBX, MOD_MEM_REG); faluco@739: } else { faluco@739: IA32_Mov_Reg_Rm_Disp32(jit, reg, REG_EBX, pEnc->offset); faluco@739: } faluco@739: IA32_Push_Reg(jit, reg); faluco@739: faluco@739: g_StackUsage += 4; faluco@739: break; faluco@739: } faluco@739: case 8: faluco@739: { faluco@739: //mov reg, DWORD PTR [ebx++4] faluco@739: //mov reg2, DWORD PTR [ebx+] faluco@739: //push reg faluco@739: //push reg2 faluco@739: jit_uint8_t reg2 = _DecodeRegister3(g_RegDecoder++); faluco@739: faluco@739: if (pEnc->offset+4 < SCHAR_MAX) faluco@739: { faluco@739: IA32_Mov_Reg_Rm_Disp8(jit, reg, REG_EBX, (jit_int8_t)(pEnc->offset+4)); faluco@739: } else { faluco@739: IA32_Mov_Reg_Rm_Disp32(jit, reg, REG_EBX, pEnc->offset+4); faluco@739: } faluco@739: if (pEnc->offset < SCHAR_MAX) faluco@739: { faluco@739: IA32_Mov_Reg_Rm_Disp8(jit, reg2, REG_EBX, (jit_int8_t)pEnc->offset); faluco@739: } else if (!pEnc->offset) { faluco@739: IA32_Mov_Reg_Rm(jit, reg, REG_EBX, MOD_MEM_REG); faluco@739: } else { faluco@739: IA32_Mov_Reg_Rm_Disp32(jit, reg2, REG_EBX, pEnc->offset); faluco@739: } faluco@739: IA32_Push_Reg(jit, reg); faluco@739: IA32_Push_Reg(jit, reg2); faluco@739: faluco@739: g_StackUsage += 8; faluco@739: break; faluco@739: } faluco@739: } faluco@739: } else if (pEnc->info.flags & PASSFLAG_BYREF) { faluco@739: //lea reg, [ebx+] faluco@739: //push reg faluco@739: if (!pEnc->offset) faluco@739: { faluco@739: IA32_Push_Reg(jit, REG_EBX); faluco@739: g_StackUsage += 4; faluco@739: return; faluco@739: } faluco@739: if (pEnc->offset < SCHAR_MAX) faluco@739: { faluco@739: IA32_Lea_DispRegImm8(jit, reg, REG_EBX, (jit_int8_t)pEnc->offset); faluco@739: } else { faluco@739: IA32_Lea_DispRegImm32(jit, reg, REG_EBX, pEnc->offset); faluco@739: } faluco@739: IA32_Push_Reg(jit, reg); faluco@739: faluco@739: g_StackUsage += 4; faluco@739: } faluco@739: } faluco@739: faluco@739: inline void Write_PushFloat(JitWriter *jit, const PassEncode *pEnc) faluco@739: { faluco@739: if (pEnc->info.flags & PASSFLAG_BYVAL) faluco@739: { faluco@739: switch (pEnc->info.size) faluco@739: { faluco@739: case 4: faluco@739: { faluco@739: //fld DWORD PTR [ebx+] faluco@739: //push reg faluco@739: //fstp DWORD PTR [esp] faluco@739: if (pEnc->offset < SCHAR_MAX) faluco@739: { faluco@739: IA32_Fld_Mem32_Disp8(jit, REG_EBX, (jit_int8_t)pEnc->offset); faluco@739: } else { faluco@739: IA32_Fld_Mem32_Disp32(jit, REG_EBX, pEnc->offset); faluco@739: } faluco@739: IA32_Push_Reg(jit, _DecodeRegister3(g_RegDecoder++)); faluco@739: IA32_Fstp_Mem32(jit, REG_ESP, REG_NOIDX, NOSCALE); faluco@739: g_StackUsage += 4; faluco@739: break; faluco@739: } faluco@739: case 8: faluco@739: { faluco@739: //fld QWORD PTR [ebx+] faluco@739: //sub esp, 8 faluco@739: //fstp QWORD PTR [esp] faluco@739: if (pEnc->offset < SCHAR_MAX) faluco@739: { faluco@739: IA32_Fld_Mem64_Disp8(jit, REG_EBX, (jit_int8_t)pEnc->offset); faluco@739: } else { faluco@739: IA32_Fld_Mem64_Disp32(jit, REG_EBX, pEnc->offset); faluco@739: } faluco@739: IA32_Sub_Rm_Imm8(jit, REG_ESP, 8, MOD_REG); faluco@739: IA32_Fstp_Mem64(jit, REG_ESP, REG_NOIDX, NOSCALE); faluco@739: g_StackUsage += 8; faluco@739: break; faluco@739: } faluco@739: } faluco@739: } else if (pEnc->info.flags & PASSFLAG_BYREF) { faluco@739: //lea reg, [ebx+] faluco@739: //push reg faluco@739: if (!pEnc->offset) faluco@739: { faluco@739: IA32_Push_Reg(jit, REG_EBX); faluco@739: g_StackUsage += 4; faluco@739: return; faluco@739: } faluco@739: faluco@739: jit_uint8_t reg = _DecodeRegister3(g_RegDecoder++); faluco@739: if (pEnc->offset < SCHAR_MAX) faluco@739: { faluco@739: IA32_Lea_DispRegImm8(jit, reg, REG_EBX, (jit_int8_t)pEnc->offset); faluco@739: } else { faluco@739: IA32_Lea_DispRegImm32(jit, reg, REG_EBX, pEnc->offset); faluco@739: } faluco@739: IA32_Push_Reg(jit, reg); faluco@739: faluco@739: g_StackUsage += 4; faluco@739: } faluco@739: } faluco@739: faluco@739: inline void Write_PushObject(JitWriter *jit, const PassEncode *pEnc) faluco@739: { faluco@739: if (pEnc->info.flags & PASSFLAG_BYVAL) faluco@739: { faluco@739: #ifdef PLATFORM_POSIX faluco@739: if (pEnc->info.flags & PASSFLAG_ODTOR) faluco@739: { faluco@739: goto push_byref; faluco@739: } faluco@739: #endif faluco@739: jit_uint32_t dwords = pEnc->info.size >> 2; faluco@739: jit_uint32_t bytes = pEnc->info.size & 0x3; faluco@739: faluco@739: //sub esp, faluco@739: //cld faluco@739: //push edi faluco@739: //push esi faluco@739: //lea edi, [esp+8] faluco@739: //lea esi, [ebx+] faluco@739: //if dwords faluco@739: // mov ecx, faluco@739: // rep movsd faluco@739: //if bytes faluco@739: // mov ecx, faluco@739: // rep movsb faluco@739: //pop esi faluco@739: //pop edi faluco@739: if (pEnc->info.size < SCHAR_MAX) faluco@739: { faluco@739: IA32_Sub_Rm_Imm8(jit, REG_ESP, (jit_int8_t)pEnc->info.size, MOD_REG); faluco@739: } else { faluco@739: IA32_Sub_Rm_Imm32(jit, REG_ESP, pEnc->info.size, MOD_REG); faluco@739: } faluco@739: IA32_Cld(jit); faluco@739: IA32_Push_Reg(jit, REG_EDI); faluco@739: IA32_Push_Reg(jit, REG_ESI); faluco@739: IA32_Lea_Reg_DispRegMultImm8(jit, REG_EDI, REG_NOIDX, REG_ESP, NOSCALE, 8); faluco@739: if (pEnc->offset < SCHAR_MAX) faluco@739: { faluco@739: IA32_Lea_DispRegImm8(jit, REG_ESI, REG_EBX, (jit_int8_t)pEnc->offset); faluco@739: } else if (!pEnc->offset) { faluco@739: IA32_Mov_Reg_Rm(jit, REG_ESI, REG_EBX, MOD_REG); faluco@739: } else { faluco@739: IA32_Lea_DispRegImm32(jit, REG_ESI, REG_EBX, pEnc->offset); faluco@739: } faluco@739: if (dwords) faluco@739: { faluco@739: IA32_Mov_Reg_Imm32(jit, REG_ECX, dwords); faluco@739: IA32_Rep(jit); faluco@739: IA32_Movsd(jit); faluco@739: } faluco@739: if (bytes) faluco@739: { faluco@739: IA32_Mov_Reg_Imm32(jit, REG_ECX, bytes); faluco@739: IA32_Rep(jit); faluco@739: IA32_Movsb(jit); faluco@739: } faluco@739: IA32_Pop_Reg(jit, REG_ESI); faluco@739: IA32_Pop_Reg(jit, REG_EDI); faluco@739: faluco@739: g_StackUsage += pEnc->info.size; faluco@739: } else if (pEnc->info.flags & PASSFLAG_BYREF) { faluco@739: #ifdef PLATFORM_POSIX faluco@739: push_byref: faluco@739: #endif faluco@739: if (!pEnc->offset) faluco@739: { faluco@739: IA32_Push_Reg(jit, REG_EBX); faluco@739: g_StackUsage += 4; faluco@739: return; faluco@739: } faluco@739: faluco@739: //lea reg, [ebx+] faluco@739: //push reg faluco@739: jit_uint8_t reg = _DecodeRegister3(g_RegDecoder++); faluco@739: if (pEnc->offset < SCHAR_MAX) faluco@739: { faluco@739: IA32_Lea_DispRegImm8(jit, reg, REG_EBX, (jit_int8_t)pEnc->offset); faluco@739: } else { faluco@739: IA32_Lea_DispRegImm32(jit, reg, REG_EBX, pEnc->offset); faluco@739: } faluco@739: IA32_Push_Reg(jit, reg); faluco@739: faluco@739: g_StackUsage += 4; faluco@739: } faluco@739: } faluco@739: faluco@739: inline void Write_PushThisPtr(JitWriter *jit) faluco@739: { faluco@739: #ifdef PLATFORM_POSIX faluco@739: //mov reg, [ebx] faluco@739: //push reg faluco@739: jit_uint8_t reg = _DecodeRegister3(g_RegDecoder++); faluco@739: faluco@739: IA32_Mov_Reg_Rm(jit, reg, REG_EBX, MOD_MEM_REG); faluco@739: IA32_Push_Reg(jit, reg); faluco@739: faluco@739: g_StackUsage += 4; faluco@739: #elif defined PLATFORM_WINDOWS faluco@739: //mov ecx, [ebx] faluco@739: IA32_Mov_Reg_Rm(jit, REG_ECX, REG_EBX, MOD_MEM_REG); faluco@739: #endif faluco@739: } faluco@739: faluco@739: inline void Write_PushRetBuffer(JitWriter *jit) faluco@739: { faluco@739: //push edi faluco@739: IA32_Push_Reg(jit, REG_EDI); faluco@739: } faluco@739: faluco@739: inline void Write_CallFunction(JitWriter *jit, FuncAddrMethod method, CallWrapper *pWrapper) faluco@739: { faluco@739: if (method == FuncAddr_Direct) faluco@739: { faluco@739: //call faluco@739: jitoffs_t call = IA32_Call_Imm32(jit, 0); faluco@739: IA32_Write_Jump32_Abs(jit, call, pWrapper->m_Addrs[ADDR_CALLEE]); faluco@739: } else if (method == FuncAddr_VTable) { faluco@739: //*(this + thisOffs + vtblOffs)[vtblIdx] faluco@739: //mov edx, [ebx] faluco@739: //mov eax, [edx++] faluco@739: //mov edx, [eax+*4] faluco@739: //call edx faluco@739: jit_uint32_t total_offs = pWrapper->m_VtInfo.thisOffs + pWrapper->m_VtInfo.vtblOffs; faluco@739: jit_uint32_t vfunc_pos = pWrapper->m_VtInfo.vtblIdx * 4; faluco@739: faluco@739: IA32_Mov_Reg_Rm(jit, REG_EDX, REG_EBX, MOD_MEM_REG); faluco@739: if (total_offs < SCHAR_MAX) faluco@739: { faluco@739: IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EDX, (jit_int8_t)total_offs); faluco@739: } else if (!total_offs) { faluco@739: IA32_Mov_Reg_Rm(jit, REG_EAX, REG_EDX, MOD_MEM_REG); faluco@739: } else { faluco@739: IA32_Mov_Reg_Rm_Disp32(jit, REG_EAX, REG_EDX, total_offs); faluco@739: } faluco@739: if (vfunc_pos < SCHAR_MAX) faluco@739: { faluco@739: IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, (jit_int8_t)vfunc_pos); faluco@739: } else if (!vfunc_pos) { faluco@739: IA32_Mov_Reg_Rm(jit, REG_EDX, REG_EAX, MOD_MEM_REG); faluco@739: } else { faluco@739: IA32_Mov_Reg_Rm_Disp32(jit, REG_EDX, REG_EAX, vfunc_pos); faluco@739: } faluco@739: IA32_Call_Reg(jit, REG_EDX); faluco@739: } faluco@739: } faluco@739: faluco@739: inline void Write_RectifyStack(JitWriter *jit, jit_uint32_t value) faluco@739: { faluco@739: //add esp, faluco@739: if (value < SCHAR_MAX) faluco@739: { faluco@739: IA32_Add_Rm_Imm8(jit, REG_ESP, (jit_int8_t)value, MOD_REG); faluco@739: } else { faluco@739: IA32_Add_Rm_Imm32(jit, REG_ESP, value, MOD_REG); faluco@739: } faluco@739: } faluco@739: faluco@739: inline void Write_MovRet2Buf(JitWriter *jit, const PassInfo *pRet) faluco@739: { faluco@739: if (pRet->type == PassType_Float) faluco@739: { faluco@739: switch (pRet->size) faluco@739: { faluco@739: case 4: faluco@739: { faluco@739: //fstp DWORD PTR [edi] faluco@739: IA32_Fstp_Mem32(jit, REG_EDI, REG_NOIDX, NOSCALE); faluco@739: break; faluco@739: } faluco@739: case 8: faluco@739: { faluco@739: //fstp QWORD PTR [edi] faluco@739: IA32_Fstp_Mem64(jit, REG_EDI, REG_NOIDX, NOSCALE); faluco@739: break; faluco@739: } faluco@739: } faluco@739: return; faluco@739: } faluco@739: faluco@739: switch (pRet->size) faluco@739: { faluco@739: case 1: faluco@739: { faluco@739: //mov BYTE PTR [edi], al faluco@739: IA32_Mov_Rm8_Reg8(jit, REG_EDI, REG_EAX, MOD_MEM_REG); faluco@739: break; faluco@739: } faluco@739: case 2: faluco@739: { faluco@739: //mov WORD PTR [edi], ax faluco@739: jit->write_ubyte(IA32_16BIT_PREFIX); faluco@739: IA32_Mov_Rm_Reg(jit, REG_EDI, REG_EAX, MOD_MEM_REG); faluco@739: break; faluco@739: } faluco@739: case 4: faluco@739: { faluco@739: //mov DWORD PTR [edi], eax faluco@739: IA32_Mov_Rm_Reg(jit, REG_EDI, REG_EAX, MOD_MEM_REG); faluco@739: break; faluco@739: } faluco@739: case 8: faluco@739: { faluco@739: //mov DWORD PTR [edi], eax faluco@739: //mov DWORD PTR [edi+4], edx faluco@739: IA32_Mov_Rm_Reg(jit, REG_EDI, REG_EAX, MOD_MEM_REG); faluco@739: IA32_Mov_Rm_Reg_Disp8(jit, REG_EDI, REG_EDX, 4); faluco@739: break; faluco@739: } faluco@739: } faluco@739: } faluco@739: faluco@739: /****************************** faluco@739: * Assembly Compiler Function * faluco@739: ******************************/ faluco@739: faluco@739: void JIT_Compile(CallWrapper *pWrapper, FuncAddrMethod method) faluco@739: { faluco@739: JitWriter writer; faluco@739: JitWriter *jit = &writer; faluco@739: faluco@739: jit_uint32_t CodeSize = 0; faluco@739: bool Needs_Retbuf = false; faluco@739: CallConvention Convention = pWrapper->GetCallConvention(); faluco@739: jit_uint32_t ParamCount = pWrapper->GetParamCount(); faluco@739: const PassInfo *pRet = pWrapper->GetReturnInfo(); faluco@739: faluco@739: writer.outbase = NULL; faluco@739: writer.outptr = NULL; faluco@739: faluco@739: jit_rewind: faluco@739: /* Write function prologue */ ds@742: Write_Execution_Prologue(jit, (pRet) ? false : true, (ParamCount || Convention == CallConv_ThisCall)); faluco@739: faluco@739: /* Write parameter push code */ faluco@739: for (jit_int32_t i=ParamCount-1; i>=0; i--) faluco@739: { faluco@739: const PassEncode *pEnc = pWrapper->GetParamInfo(i); faluco@739: switch (pEnc->info.type) faluco@739: { faluco@739: case PassType_Basic: faluco@739: { faluco@739: Write_PushPOD(jit, pEnc); faluco@739: break; faluco@739: } faluco@739: case PassType_Float: faluco@739: { faluco@739: Write_PushFloat(jit, pEnc); faluco@739: break; faluco@739: } faluco@739: case PassType_Object: faluco@739: { faluco@739: Write_PushObject(jit, pEnc); faluco@739: break; faluco@739: } faluco@739: } faluco@739: } faluco@739: faluco@739: /* Prepare the this ptr if applicable */ faluco@739: if (Convention == CallConv_ThisCall) faluco@739: { faluco@739: Write_PushThisPtr(jit); faluco@739: } faluco@739: faluco@739: /* Skip the return buffer stuff if this is a void function */ faluco@739: if (!pRet) faluco@739: { faluco@739: goto skip_retbuffer; faluco@739: } faluco@739: faluco@739: if ((pRet->type == PassType_Object) && (pRet->flags & PASSFLAG_BYVAL)) faluco@739: { faluco@739: #ifdef PLATFORM_POSIX faluco@739: Needs_Retbuf = true; faluco@739: #elif defined PLATFORM_WINDOWS faluco@739: if ((Convention == CallConv_ThisCall) || faluco@739: ((Convention == CallConv_Cdecl) && faluco@739: ((pRet->size > 8) || (pRet->flags & PASSFLAG_ODTOR|PASSFLAG_OCTOR|PASSFLAG_OASSIGNOP)))) faluco@739: { faluco@739: Needs_Retbuf = true; faluco@739: } faluco@739: #endif faluco@739: } faluco@739: faluco@739: /* Prepare the return buffer in case we are returning objects by value. */ faluco@739: if (Needs_Retbuf) faluco@739: { faluco@739: Write_PushRetBuffer(jit); faluco@739: } faluco@739: faluco@739: skip_retbuffer: faluco@739: /* Write the calling code */ faluco@739: Write_CallFunction(jit, method, pWrapper); faluco@739: faluco@739: /* Clean up the calling stack */ faluco@739: #ifdef PLATFORM_WINDOWS faluco@739: if ((ParamCount || Needs_Retbuf) && (Convention == CallConv_Cdecl)) faluco@739: { faluco@739: /* Pop all parameters from the stack + hidden return pointer */ faluco@739: jit_uint32_t total = (Needs_Retbuf) ? g_StackUsage + sizeof(void *) : g_StackUsage; faluco@739: Write_RectifyStack(jit, total); faluco@739: #elif defined PLATFORM_POSIX faluco@739: if (ParamCount) faluco@739: { faluco@739: /* Pop all parameters from the stack */ faluco@739: Write_RectifyStack(jit, g_StackUsage); faluco@739: #endif faluco@739: } faluco@739: faluco@739: /* Copy the return type to the return buffer if the function is not void */ faluco@739: if (pRet && !Needs_Retbuf) faluco@739: { faluco@739: Write_MovRet2Buf(jit, pRet); faluco@739: } faluco@739: faluco@739: /* Write Function Epilogue */ faluco@739: Write_Function_Epilogue(jit, (pRet) ? false : true, (ParamCount) ? true : false); faluco@739: faluco@739: if (writer.outbase == NULL) faluco@739: { faluco@739: CodeSize = writer.get_outputpos(); faluco@739: writer.outbase = (jitcode_t)g_SPEngine->ExecAlloc(CodeSize); faluco@739: writer.outptr = writer.outbase; faluco@739: pWrapper->m_Addrs[ADDR_CODEBASE] = writer.outbase; faluco@739: g_StackUsage = 0; faluco@739: g_RegDecoder = 0; faluco@739: Needs_Retbuf = false; faluco@739: goto jit_rewind; faluco@739: } faluco@739: }