mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-01-24 18:31:33 +00:00
- catch and rethrow c++ exceptions
This commit is contained in:
parent
47485194f4
commit
f321f64a05
6 changed files with 41 additions and 39 deletions
|
@ -303,6 +303,19 @@ void JitCompiler::EmitThrowException(EVMAbortException reason, asmjit::X86Gp arg
|
||||||
cc.ret(vReg);
|
cc.ret(vReg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JitCompiler::EmitCheckForException()
|
||||||
|
{
|
||||||
|
auto noexception = cc.newLabel();
|
||||||
|
auto exceptResult = newTempInt32();
|
||||||
|
cc.mov(exceptResult, asmjit::x86::dword_ptr(exceptInfo, 0 * 4));
|
||||||
|
cc.cmp(exceptResult, (int)-1);
|
||||||
|
cc.je(noexception);
|
||||||
|
asmjit::X86Gp vReg = newTempInt32();
|
||||||
|
cc.mov(vReg, 0);
|
||||||
|
cc.ret(vReg);
|
||||||
|
cc.bind(noexception);
|
||||||
|
}
|
||||||
|
|
||||||
asmjit::X86Gp JitCompiler::CheckRegD(int r0, int r1)
|
asmjit::X86Gp JitCompiler::CheckRegD(int r0, int r1)
|
||||||
{
|
{
|
||||||
if (r0 != r1)
|
if (r0 != r1)
|
||||||
|
|
|
@ -180,15 +180,7 @@ void JitCompiler::EmitDoCall(asmjit::X86Gp ptr)
|
||||||
call->setArg(5, callReturns);
|
call->setArg(5, callReturns);
|
||||||
call->setArg(6, exceptInfo);
|
call->setArg(6, exceptInfo);
|
||||||
|
|
||||||
auto noexception = cc.newLabel();
|
EmitCheckForException();
|
||||||
auto exceptResult = newTempInt32();
|
|
||||||
cc.mov(exceptResult, x86::dword_ptr(exceptInfo, 0 * 4));
|
|
||||||
cc.cmp(exceptResult, (int)-1);
|
|
||||||
cc.je(noexception);
|
|
||||||
X86Gp vReg = newTempInt32();
|
|
||||||
cc.mov(vReg, 0);
|
|
||||||
cc.ret(vReg);
|
|
||||||
cc.bind(noexception);
|
|
||||||
|
|
||||||
LoadInOuts(B);
|
LoadInOuts(B);
|
||||||
LoadReturns(pc + 1, C);
|
LoadReturns(pc + 1, C);
|
||||||
|
@ -414,8 +406,8 @@ int JitCompiler::DoCall(VMFrameStack *stack, VMFunction *call, int b, int c, VMV
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
// To do: store full exception in exceptinfo
|
|
||||||
exceptinfo->reason = X_OTHER;
|
exceptinfo->reason = X_OTHER;
|
||||||
|
exceptinfo->cppException = std::current_exception();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,30 +79,24 @@ void JitCompiler::EmitSCOPE()
|
||||||
auto f = newTempIntPtr();
|
auto f = newTempIntPtr();
|
||||||
cc.mov(f, asmjit::imm_ptr(konsta[C].v));
|
cc.mov(f, asmjit::imm_ptr(konsta[C].v));
|
||||||
|
|
||||||
auto result = newResultInt32();
|
|
||||||
typedef int(*FuncPtr)(DObject*, VMFunction*, int);
|
typedef int(*FuncPtr)(DObject*, VMFunction*, int);
|
||||||
auto call = CreateCall<int, DObject*, VMFunction*, int>([](DObject *o, VMFunction *f, int b) -> int {
|
auto call = CreateCall<void, DObject*, VMFunction*, int, JitExceptionInfo *>([](DObject *o, VMFunction *f, int b, JitExceptionInfo *exceptinfo) {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
FScopeBarrier::ValidateCall(o->GetClass(), f, b - 1);
|
FScopeBarrier::ValidateCall(o->GetClass(), f, b - 1);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
catch (const CVMAbortException &)
|
catch (...)
|
||||||
{
|
{
|
||||||
// To do: pass along the exception info
|
exceptinfo->reason = X_OTHER;
|
||||||
return 0;
|
exceptinfo->cppException = std::current_exception();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
call->setRet(0, result);
|
|
||||||
call->setArg(0, regA[A]);
|
call->setArg(0, regA[A]);
|
||||||
call->setArg(1, f);
|
call->setArg(1, f);
|
||||||
call->setArg(2, asmjit::Imm(B));
|
call->setArg(2, asmjit::Imm(B));
|
||||||
|
call->setArg(3, exceptInfo);
|
||||||
|
|
||||||
auto notzero = cc.newLabel();
|
EmitCheckForException();
|
||||||
cc.test(result, result);
|
|
||||||
cc.jnz(notzero);
|
|
||||||
EmitThrowException(X_OTHER);
|
|
||||||
cc.bind(notzero);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompiler::EmitRET()
|
void JitCompiler::EmitRET()
|
||||||
|
@ -259,7 +253,7 @@ void JitCompiler::EmitRETI()
|
||||||
void JitCompiler::EmitNEW()
|
void JitCompiler::EmitNEW()
|
||||||
{
|
{
|
||||||
auto result = newResultIntPtr();
|
auto result = newResultIntPtr();
|
||||||
auto call = CreateCall<DObject*, PClass*, int>([](PClass *cls, int c) -> DObject* {
|
auto call = CreateCall<DObject*, PClass*, int, JitExceptionInfo *>([](PClass *cls, int c, JitExceptionInfo *exceptinfo) -> DObject* {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!cls->ConstructNative)
|
if (!cls->ConstructNative)
|
||||||
|
@ -279,21 +273,20 @@ void JitCompiler::EmitNEW()
|
||||||
if (c) FScopeBarrier::ValidateNew(cls, c - 1);
|
if (c) FScopeBarrier::ValidateNew(cls, c - 1);
|
||||||
return cls->CreateNew();
|
return cls->CreateNew();
|
||||||
}
|
}
|
||||||
catch (const CVMAbortException &)
|
catch (...)
|
||||||
{
|
{
|
||||||
// To do: pass along the exception info
|
exceptinfo->reason = X_OTHER;
|
||||||
|
exceptinfo->cppException = std::current_exception();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
call->setRet(0, result);
|
call->setRet(0, result);
|
||||||
call->setArg(0, regA[B]);
|
call->setArg(0, regA[B]);
|
||||||
call->setArg(1, asmjit::Imm(C));
|
call->setArg(1, asmjit::Imm(C));
|
||||||
|
call->setArg(2, exceptInfo);
|
||||||
|
|
||||||
|
EmitCheckForException();
|
||||||
|
|
||||||
auto notnull = cc.newLabel();
|
|
||||||
cc.test(result, result);
|
|
||||||
cc.jnz(notnull);
|
|
||||||
EmitThrowException(X_OTHER);
|
|
||||||
cc.bind(notnull);
|
|
||||||
cc.mov(regA[A], result);
|
cc.mov(regA[A], result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,27 +310,26 @@ void JitCompiler::EmitNEW_K()
|
||||||
auto result = newResultIntPtr();
|
auto result = newResultIntPtr();
|
||||||
auto regcls = newTempIntPtr();
|
auto regcls = newTempIntPtr();
|
||||||
cc.mov(regcls, asmjit::imm_ptr(konsta[B].v));
|
cc.mov(regcls, asmjit::imm_ptr(konsta[B].v));
|
||||||
auto call = CreateCall<DObject*, PClass*, int>([](PClass *cls, int c) -> DObject* {
|
auto call = CreateCall<DObject*, PClass*, int, JitExceptionInfo *>([](PClass *cls, int c, JitExceptionInfo *exceptinfo) -> DObject* {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (c) FScopeBarrier::ValidateNew(cls, c - 1);
|
if (c) FScopeBarrier::ValidateNew(cls, c - 1);
|
||||||
return cls->CreateNew();
|
return cls->CreateNew();
|
||||||
}
|
}
|
||||||
catch (const CVMAbortException &)
|
catch (...)
|
||||||
{
|
{
|
||||||
// To do: pass along the exception info
|
exceptinfo->reason = X_OTHER;
|
||||||
|
exceptinfo->cppException = std::current_exception();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
call->setRet(0, result);
|
call->setRet(0, result);
|
||||||
call->setArg(0, regcls);
|
call->setArg(0, regcls);
|
||||||
call->setArg(1, asmjit::Imm(C));
|
call->setArg(1, asmjit::Imm(C));
|
||||||
|
call->setArg(2, exceptInfo);
|
||||||
|
|
||||||
|
EmitCheckForException();
|
||||||
|
|
||||||
auto notnull = cc.newLabel();
|
|
||||||
cc.test(result, result);
|
|
||||||
cc.jnz(notnull);
|
|
||||||
EmitThrowException(X_OTHER);
|
|
||||||
cc.bind(notnull);
|
|
||||||
cc.mov(regA[A], result);
|
cc.mov(regA[A], result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,6 +131,7 @@ private:
|
||||||
void EmitNullPointerThrow(int index, EVMAbortException reason);
|
void EmitNullPointerThrow(int index, EVMAbortException reason);
|
||||||
void EmitThrowException(EVMAbortException reason);
|
void EmitThrowException(EVMAbortException reason);
|
||||||
void EmitThrowException(EVMAbortException reason, asmjit::X86Gp arg1);
|
void EmitThrowException(EVMAbortException reason, asmjit::X86Gp arg1);
|
||||||
|
void EmitCheckForException();
|
||||||
|
|
||||||
asmjit::X86Gp CheckRegD(int r0, int r1);
|
asmjit::X86Gp CheckRegD(int r0, int r1);
|
||||||
asmjit::X86Xmm CheckRegF(int r0, int r1);
|
asmjit::X86Xmm CheckRegF(int r0, int r1);
|
||||||
|
|
|
@ -86,7 +86,10 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret)
|
||||||
int result = sfunc->JitFunc(stack, ret, numret, &exceptInfo);
|
int result = sfunc->JitFunc(stack, ret, numret, &exceptInfo);
|
||||||
if (exceptInfo.reason != -1)
|
if (exceptInfo.reason != -1)
|
||||||
{
|
{
|
||||||
ThrowAbortException(sfunc, exceptInfo.pcOnJitAbort, (EVMAbortException)exceptInfo.reason, nullptr);
|
if (exceptInfo.cppException)
|
||||||
|
std::rethrow_exception(exceptInfo.cppException);
|
||||||
|
else
|
||||||
|
ThrowAbortException(sfunc, exceptInfo.pcOnJitAbort, (EVMAbortException)exceptInfo.reason, nullptr);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -443,6 +443,7 @@ struct JitExceptionInfo
|
||||||
int32_t reason; // EVMAbortException
|
int32_t reason; // EVMAbortException
|
||||||
int32_t args[3];
|
int32_t args[3];
|
||||||
VMOP* pcOnJitAbort;
|
VMOP* pcOnJitAbort;
|
||||||
|
std::exception_ptr cppException;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef int(*JitFuncPtr)(VMFrameStack *stack, VMReturn *ret, int numret, JitExceptionInfo *exceptInfo);
|
typedef int(*JitFuncPtr)(VMFrameStack *stack, VMReturn *ret, int numret, JitExceptionInfo *exceptInfo);
|
||||||
|
|
Loading…
Reference in a new issue