Revert "AsmJit update"

This reverts commit 747b3dfcfe.

# Conflicts:
#	libraries/asmjit/asmjit/core/compiler.h

This had to be reverted because it breaks exception handling which is a critical problem.
With the updated code any exception thrown inside code that had a JITed call stack would crash.
This commit is contained in:
Christoph Oelckers 2019-10-07 20:34:55 +02:00
commit 523fd0bf3a
166 changed files with 45117 additions and 51918 deletions

View file

@ -17,13 +17,6 @@ JitFuncPtr JitCompile(VMScriptFunction *sfunc)
using namespace asmjit;
StringLogger logger;
// Keep annotations to make it easier to process the debug log in case of error.
logger.setFlags(
FormatOptions::kFlagDebugRA |
FormatOptions::kFlagRegCasts |
FormatOptions::kFlagAnnotations);
try
{
ThrowingErrorHandler errorHandler;
@ -58,11 +51,11 @@ void JitDumpLog(FILE *file, VMScriptFunction *sfunc)
JitCompiler compiler(&code, sfunc);
compiler.Codegen();
fwrite(logger.data(), logger.dataSize(), 1, file);
fwrite(logger.getString(), logger.getLength(), 1, file);
}
catch (const std::exception &e)
{
fwrite(logger.data(), logger.dataSize(), 1, file);
fwrite(logger.getString(), logger.getLength(), 1, file);
FString err;
err.Format("Unexpected JIT error: %s\n", e.what());
@ -76,7 +69,7 @@ void JitDumpLog(FILE *file, VMScriptFunction *sfunc)
static void OutputJitLog(const asmjit::StringLogger &logger)
{
// Write line by line since I_FatalError seems to cut off long strings
const char *pos = logger.data();
const char *pos = logger.getString();
const char *end = pos;
while (*end)
{
@ -101,7 +94,7 @@ static const char *OpNames[NUM_OPS] =
#undef xx
};
asmjit::FuncNode *JitCompiler::Codegen()
asmjit::CCFunc *JitCompiler::Codegen()
{
Setup();
@ -136,7 +129,7 @@ asmjit::FuncNode *JitCompiler::Codegen()
cc.comment(lineinfo.GetChars(), lineinfo.Len());
}
labels[i].cursor = cc.cursor();
labels[i].cursor = cc.getCursor();
ResetTemp();
EmitOpcode();
@ -148,7 +141,7 @@ asmjit::FuncNode *JitCompiler::Codegen()
cc.endFunc();
cc.finalize();
auto code = cc.code();
auto code = cc.getCode ();
for (unsigned int j = 0; j < LineInfo.Size (); j++)
{
auto info = LineInfo[j];
@ -158,7 +151,7 @@ asmjit::FuncNode *JitCompiler::Codegen()
continue;
}
info.InstructionIndex = code->labelOffset(info.Label);
info.InstructionIndex = code->getLabelOffset (info.Label);
LineInfo[j] = info;
}
@ -184,7 +177,7 @@ void JitCompiler::EmitOpcode()
void JitCompiler::BindLabels()
{
asmjit::BaseNode *cursor = cc.cursor();
asmjit::CBNode *cursor = cc.getCursor();
unsigned int size = labels.Size();
for (unsigned int i = 0; i < size; i++)
{
@ -202,7 +195,7 @@ void JitCompiler::CheckVMFrame()
{
if (!vmframeAllocated)
{
auto cursor = cc.cursor();
auto cursor = cc.getCursor();
cc.setCursor(vmframeCursor);
auto vmstack = cc.newStack(sfunc->StackSize, 16, "vmstack");
@ -214,11 +207,11 @@ void JitCompiler::CheckVMFrame()
}
}
asmjit::x86::Gp JitCompiler::GetCallReturns()
asmjit::X86Gp JitCompiler::GetCallReturns()
{
if (!callReturnsAllocated)
{
auto cursor = cc.cursor();
auto cursor = cc.getCursor();
cc.setCursor(callReturnsCursor);
auto stackalloc = cc.newStack(sizeof(VMReturn) * MAX_RETURNS, alignof(VMReturn), "stackalloc");
callReturns = cc.newIntPtr("callReturns");
@ -252,14 +245,14 @@ void JitCompiler::Setup()
ret = cc.newIntPtr("ret"); // VMReturn *ret
numret = cc.newInt32("numret"); // int numret
func = cc.addFunc(FuncSignatureT<int, VMFunction *, void *, int, void *, int>());
func = cc.addFunc(FuncSignature5<int, VMFunction *, void *, int, void *, int>());
cc.setArg(0, unusedFunc);
cc.setArg(1, args);
cc.setArg(2, numargs);
cc.setArg(3, ret);
cc.setArg(4, numret);
callReturnsCursor = cc.cursor();
callReturnsCursor = cc.getCursor();
konstd = sfunc->KonstD;
konstf = sfunc->KonstF;
@ -299,7 +292,7 @@ void JitCompiler::SetupSimpleFrame()
// This is a simple frame with no constructors or destructors. Allocate it on the stack ourselves.
vmframeCursor = cc.cursor();
vmframeCursor = cc.getCursor();
int argsPos = 0;
int regd = 0, regf = 0, rega = 0;
@ -367,7 +360,7 @@ void JitCompiler::SetupFullVMFrame()
stack = cc.newIntPtr("stack");
auto allocFrame = CreateCall<VMFrameStack *, VMScriptFunction *, VMValue *, int>(CreateFullVMFrame);
allocFrame->setRet(0, stack);
allocFrame->setArg(0, imm(sfunc));
allocFrame->setArg(0, imm_ptr(sfunc));
allocFrame->setArg(1, args);
allocFrame->setArg(2, numargs);
@ -408,7 +401,7 @@ void JitCompiler::IncrementVMCalls()
// VMCalls[0]++
auto vmcallsptr = newTempIntPtr();
auto vmcalls = newTempInt32();
cc.mov(vmcallsptr, asmjit::imm(VMCalls));
cc.mov(vmcallsptr, asmjit::imm_ptr(VMCalls));
cc.mov(vmcalls, asmjit::x86::dword_ptr(vmcallsptr));
cc.add(vmcalls, (int)1);
cc.mov(asmjit::x86::dword_ptr(vmcallsptr), vmcalls);
@ -467,7 +460,7 @@ void JitCompiler::EmitThrowException(EVMAbortException reason)
asmjit::Label JitCompiler::EmitThrowExceptionLabel(EVMAbortException reason)
{
auto label = cc.newLabel();
auto cursor = cc.cursor();
auto cursor = cc.getCursor();
cc.bind(label);
EmitThrowException(reason);
cc.setCursor(cursor);
@ -480,7 +473,7 @@ asmjit::Label JitCompiler::EmitThrowExceptionLabel(EVMAbortException reason)
return label;
}
asmjit::x86::Gp JitCompiler::CheckRegD(int r0, int r1)
asmjit::X86Gp JitCompiler::CheckRegD(int r0, int r1)
{
if (r0 != r1)
{
@ -494,7 +487,7 @@ asmjit::x86::Gp JitCompiler::CheckRegD(int r0, int r1)
}
}
asmjit::x86::Xmm JitCompiler::CheckRegF(int r0, int r1)
asmjit::X86Xmm JitCompiler::CheckRegF(int r0, int r1)
{
if (r0 != r1)
{
@ -508,7 +501,7 @@ asmjit::x86::Xmm JitCompiler::CheckRegF(int r0, int r1)
}
}
asmjit::x86::Xmm JitCompiler::CheckRegF(int r0, int r1, int r2)
asmjit::X86Xmm JitCompiler::CheckRegF(int r0, int r1, int r2)
{
if (r0 != r1 && r0 != r2)
{
@ -522,7 +515,7 @@ asmjit::x86::Xmm JitCompiler::CheckRegF(int r0, int r1, int r2)
}
}
asmjit::x86::Xmm JitCompiler::CheckRegF(int r0, int r1, int r2, int r3)
asmjit::X86Xmm JitCompiler::CheckRegF(int r0, int r1, int r2, int r3)
{
if (r0 != r1 && r0 != r2 && r0 != r3)
{
@ -536,7 +529,7 @@ asmjit::x86::Xmm JitCompiler::CheckRegF(int r0, int r1, int r2, int r3)
}
}
asmjit::x86::Gp JitCompiler::CheckRegS(int r0, int r1)
asmjit::X86Gp JitCompiler::CheckRegS(int r0, int r1)
{
if (r0 != r1)
{
@ -550,7 +543,7 @@ asmjit::x86::Gp JitCompiler::CheckRegS(int r0, int r1)
}
}
asmjit::x86::Gp JitCompiler::CheckRegA(int r0, int r1)
asmjit::X86Gp JitCompiler::CheckRegA(int r0, int r1)
{
if (r0 != r1)
{

View file

@ -61,14 +61,14 @@ void JitCompiler::EmitCALL_K()
else
{
auto ptr = newTempIntPtr();
cc.mov(ptr, asmjit::imm(target));
cc.mov(ptr, asmjit::imm_ptr(target));
EmitVMCall(ptr, target);
}
pc += C; // Skip RESULTs
}
void JitCompiler::EmitVMCall(asmjit::x86::Gp vmfunc, VMFunction *target)
void JitCompiler::EmitVMCall(asmjit::X86Gp vmfunc, VMFunction *target)
{
using namespace asmjit;
@ -83,14 +83,14 @@ void JitCompiler::EmitVMCall(asmjit::x86::Gp vmfunc, VMFunction *target)
FillReturns(pc + 1, C);
x86::Gp paramsptr = newTempIntPtr();
X86Gp paramsptr = newTempIntPtr();
cc.lea(paramsptr, x86::ptr(vmframe, offsetParams));
auto scriptcall = newTempIntPtr();
cc.mov(scriptcall, x86::ptr(vmfunc, myoffsetof(VMScriptFunction, ScriptCall)));
auto result = newResultInt32();
auto call = cc.call(scriptcall, FuncSignatureT<int, VMFunction *, VMValue*, int, VMReturn*, int>());
auto call = cc.call(scriptcall, FuncSignature5<int, VMFunction *, VMValue*, int, VMReturn*, int>());
call->setRet(0, result);
call->setArg(0, vmfunc);
call->setArg(1, paramsptr);
@ -109,9 +109,9 @@ int JitCompiler::StoreCallParams()
{
using namespace asmjit;
x86::Gp stackPtr = newTempIntPtr();
x86::Gp tmp = newTempIntPtr();
x86::Xmm tmp2 = newTempXmmSd();
X86Gp stackPtr = newTempIntPtr();
X86Gp tmp = newTempIntPtr();
X86Xmm tmp2 = newTempXmmSd();
int numparams = 0;
for (unsigned int i = 0; i < ParamOpcodes.Size(); i++)
@ -150,7 +150,7 @@ int JitCompiler::StoreCallParams()
cc.mov(x86::ptr(vmframe, offsetParams + slot * sizeof(VMValue) + myoffsetof(VMValue, a)), regS[bc]);
break;
case REGT_STRING | REGT_KONST:
cc.mov(tmp, asmjit::imm(&konsts[bc]));
cc.mov(tmp, asmjit::imm_ptr(&konsts[bc]));
cc.mov(x86::ptr(vmframe, offsetParams + slot * sizeof(VMValue) + myoffsetof(VMValue, sp)), tmp);
break;
case REGT_POINTER:
@ -162,7 +162,7 @@ int JitCompiler::StoreCallParams()
cc.mov(x86::ptr(vmframe, offsetParams + slot * sizeof(VMValue) + myoffsetof(VMValue, a)), stackPtr);
break;
case REGT_POINTER | REGT_KONST:
cc.mov(tmp, asmjit::imm(konsta[bc].v));
cc.mov(tmp, asmjit::imm_ptr(konsta[bc].v));
cc.mov(x86::ptr(vmframe, offsetParams + slot * sizeof(VMValue) + myoffsetof(VMValue, a)), tmp);
break;
case REGT_FLOAT:
@ -193,7 +193,7 @@ int JitCompiler::StoreCallParams()
cc.mov(x86::ptr(vmframe, offsetParams + slot * sizeof(VMValue) + myoffsetof(VMValue, a)), stackPtr);
break;
case REGT_FLOAT | REGT_KONST:
cc.mov(tmp, asmjit::imm(konstf + bc));
cc.mov(tmp, asmjit::imm_ptr(konstf + bc));
cc.movsd(tmp2, asmjit::x86::qword_ptr(tmp));
cc.movsd(x86::qword_ptr(vmframe, offsetParams + slot * sizeof(VMValue) + myoffsetof(VMValue, f)), tmp2);
break;
@ -330,7 +330,7 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target)
assert(ParamOpcodes.Size() > 0);
const VMOP *param = ParamOpcodes[0];
const int bc = param->i16u;
asmjit::x86::Gp *reg = nullptr;
asmjit::X86Gp *reg = nullptr;
switch (param->a & REGT_TYPE)
{
@ -345,14 +345,14 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target)
cc.jz(label);
}
asmjit::BaseNode *cursorBefore = cc.cursor();
auto call = cc.call(imm(target->DirectNativeCall), CreateFuncSignature());
asmjit::CBNode *cursorBefore = cc.getCursor();
auto call = cc.call(imm_ptr(target->DirectNativeCall), CreateFuncSignature());
call->setInlineComment(target->PrintableName.GetChars());
asmjit::BaseNode *cursorAfter = cc.cursor();
asmjit::CBNode *cursorAfter = cc.getCursor();
cc.setCursor(cursorBefore);
x86::Gp tmp;
x86::Xmm tmp2;
X86Gp tmp;
X86Xmm tmp2;
int numparams = 0;
for (unsigned int i = 0; i < ParamOpcodes.Size(); i++)
@ -384,7 +384,7 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target)
break;
case REGT_STRING | REGT_KONST:
tmp = newTempIntPtr();
cc.mov(tmp, imm(&konsts[bc]));
cc.mov(tmp, imm_ptr(&konsts[bc]));
call->setArg(slot, tmp);
break;
case REGT_POINTER:
@ -392,7 +392,7 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target)
break;
case REGT_POINTER | REGT_KONST:
tmp = newTempIntPtr();
cc.mov(tmp, imm(konsta[bc].v));
cc.mov(tmp, imm_ptr(konsta[bc].v));
call->setArg(slot, tmp);
break;
case REGT_FLOAT:
@ -411,7 +411,7 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target)
case REGT_FLOAT | REGT_KONST:
tmp = newTempIntPtr();
tmp2 = newTempXmmSd();
cc.mov(tmp, asmjit::imm(konstf + bc));
cc.mov(tmp, asmjit::imm_ptr(konstf + bc));
cc.movsd(tmp2, asmjit::x86::qword_ptr(tmp));
call->setArg(slot, tmp2);
break;
@ -580,7 +580,7 @@ asmjit::FuncSignature JitCompiler::CreateFuncSignature()
{
if (ParamOpcodes[i]->op == OP_PARAMI)
{
args.Push(Type::IdOfT<int>::kTypeId);
args.Push(TypeIdOf<int>::kTypeId);
key += "i";
}
else // OP_PARAM
@ -595,33 +595,33 @@ asmjit::FuncSignature JitCompiler::CreateFuncSignature()
case REGT_INT | REGT_ADDROF:
case REGT_POINTER | REGT_ADDROF:
case REGT_FLOAT | REGT_ADDROF:
args.Push(Type::IdOfT<void*>::kTypeId);
args.Push(TypeIdOf<void*>::kTypeId);
key += "v";
break;
case REGT_INT:
case REGT_INT | REGT_KONST:
args.Push(Type::IdOfT<int>::kTypeId);
args.Push(TypeIdOf<int>::kTypeId);
key += "i";
break;
case REGT_STRING:
case REGT_STRING | REGT_KONST:
args.Push(Type::IdOfT<void*>::kTypeId);
args.Push(TypeIdOf<void*>::kTypeId);
key += "s";
break;
case REGT_FLOAT:
case REGT_FLOAT | REGT_KONST:
args.Push(Type::IdOfT<double>::kTypeId);
args.Push(TypeIdOf<double>::kTypeId);
key += "f";
break;
case REGT_FLOAT | REGT_MULTIREG2:
args.Push(Type::IdOfT<double>::kTypeId);
args.Push(Type::IdOfT<double>::kTypeId);
args.Push(TypeIdOf<double>::kTypeId);
args.Push(TypeIdOf<double>::kTypeId);
key += "ff";
break;
case REGT_FLOAT | REGT_MULTIREG3:
args.Push(Type::IdOfT<double>::kTypeId);
args.Push(Type::IdOfT<double>::kTypeId);
args.Push(Type::IdOfT<double>::kTypeId);
args.Push(TypeIdOf<double>::kTypeId);
args.Push(TypeIdOf<double>::kTypeId);
args.Push(TypeIdOf<double>::kTypeId);
key += "fff";
break;
@ -635,7 +635,7 @@ asmjit::FuncSignature JitCompiler::CreateFuncSignature()
const VMOP *retval = pc + 1;
int numret = C;
uint32_t rettype = Type::IdOfT<void>::kTypeId;
uint32_t rettype = TypeIdOf<void>::kTypeId;
// Check if first return value can be placed in the function's real return value slot
int startret = 1;
@ -650,15 +650,15 @@ asmjit::FuncSignature JitCompiler::CreateFuncSignature()
switch (type)
{
case REGT_INT:
rettype = Type::IdOfT<int>::kTypeId;
rettype = TypeIdOf<int>::kTypeId;
key += "ri";
break;
case REGT_FLOAT:
rettype = Type::IdOfT<double>::kTypeId;
rettype = TypeIdOf<double>::kTypeId;
key += "rf";
break;
case REGT_POINTER:
rettype = Type::IdOfT<void*>::kTypeId;
rettype = TypeIdOf<void*>::kTypeId;
key += "rv";
break;
case REGT_STRING:
@ -676,7 +676,7 @@ asmjit::FuncSignature JitCompiler::CreateFuncSignature()
I_Error("Expected OP_RESULT to follow OP_CALL\n");
}
args.Push(Type::IdOfT<void*>::kTypeId);
args.Push(TypeIdOf<void*>::kTypeId);
key += "v";
}
@ -685,6 +685,6 @@ asmjit::FuncSignature JitCompiler::CreateFuncSignature()
if (!cachedArgs) cachedArgs.reset(new TArray<uint8_t>(args));
FuncSignature signature;
signature.init(CallConv::kIdHost, FuncSignature::kNoVarArgs, rettype, cachedArgs->Data(), cachedArgs->Size());
signature.init(CallConv::kIdHost, rettype, cachedArgs->Data(), cachedArgs->Size());
return signature;
}

View file

@ -57,7 +57,7 @@ void JitCompiler::EmitSCOPE()
cc.jz(label);
auto f = newTempIntPtr();
cc.mov(f, asmjit::imm(konsta[C].v));
cc.mov(f, asmjit::imm_ptr(konsta[C].v));
typedef int(*FuncPtr)(DObject*, VMFunction*, int);
auto call = CreateCall<void, DObject*, VMFunction*, int>(ValidateCall);
@ -77,7 +77,7 @@ void JitCompiler::EmitRET()
if (B == REGT_NIL)
{
EmitPopFrame();
x86::Gp vReg = newTempInt32();
X86Gp vReg = newTempInt32();
cc.mov(vReg, 0);
cc.ret(vReg);
}
@ -86,8 +86,8 @@ void JitCompiler::EmitRET()
int a = A;
int retnum = a & ~RET_FINAL;
x86::Gp reg_retnum = newTempInt32();
x86::Gp location = newTempIntPtr();
X86Gp reg_retnum = newTempInt32();
X86Gp location = newTempIntPtr();
Label L_endif = cc.newLabel();
cc.mov(reg_retnum, retnum);
@ -161,7 +161,7 @@ void JitCompiler::EmitRET()
cc.add(ptr, (int)(retnum * sizeof(VMReturn)));
auto call = CreateCall<void, VMReturn*, FString*>(SetString);
call->setArg(0, ptr);
if (regtype & REGT_KONST) call->setArg(1, asmjit::imm(&konsts[regnum]));
if (regtype & REGT_KONST) call->setArg(1, asmjit::imm_ptr(&konsts[regnum]));
else call->setArg(1, regS[regnum]);
break;
}
@ -171,7 +171,7 @@ void JitCompiler::EmitRET()
if (regtype & REGT_KONST)
{
auto ptr = newTempIntPtr();
cc.mov(ptr, asmjit::imm(konsta[regnum].v));
cc.mov(ptr, asmjit::imm_ptr(konsta[regnum].v));
cc.mov(x86::qword_ptr(location), ptr);
}
else
@ -184,7 +184,7 @@ void JitCompiler::EmitRET()
if (regtype & REGT_KONST)
{
auto ptr = newTempIntPtr();
cc.mov(ptr, asmjit::imm(konsta[regnum].v));
cc.mov(ptr, asmjit::imm_ptr(konsta[regnum].v));
cc.mov(x86::dword_ptr(location), ptr);
}
else
@ -218,8 +218,8 @@ void JitCompiler::EmitRETI()
int a = A;
int retnum = a & ~RET_FINAL;
x86::Gp reg_retnum = newTempInt32();
x86::Gp location = newTempIntPtr();
X86Gp reg_retnum = newTempInt32();
X86Gp location = newTempIntPtr();
Label L_endif = cc.newLabel();
cc.mov(reg_retnum, retnum);
@ -251,7 +251,7 @@ void JitCompiler::EmitTHROW()
void JitCompiler::EmitBOUND()
{
auto cursor = cc.cursor();
auto cursor = cc.getCursor();
auto label = cc.newLabel();
cc.bind(label);
auto call = CreateCall<void, int, int>(&JitCompiler::ThrowArrayOutOfBounds);
@ -270,7 +270,7 @@ void JitCompiler::EmitBOUND()
void JitCompiler::EmitBOUND_K()
{
auto cursor = cc.cursor();
auto cursor = cc.getCursor();
auto label = cc.newLabel();
cc.bind(label);
auto call = CreateCall<void, int, int>(&JitCompiler::ThrowArrayOutOfBounds);
@ -289,7 +289,7 @@ void JitCompiler::EmitBOUND_K()
void JitCompiler::EmitBOUND_R()
{
auto cursor = cc.cursor();
auto cursor = cc.getCursor();
auto label = cc.newLabel();
cc.bind(label);
auto call = CreateCall<void, int, int>(&JitCompiler::ThrowArrayOutOfBounds);

View file

@ -17,7 +17,7 @@ void JitCompiler::EmitLK()
void JitCompiler::EmitLKF()
{
auto base = newTempIntPtr();
cc.mov(base, asmjit::imm(konstf + BC));
cc.mov(base, asmjit::imm_ptr(konstf + BC));
cc.movsd(regF[A], asmjit::x86::qword_ptr(base));
}
@ -25,7 +25,7 @@ void JitCompiler::EmitLKS()
{
auto call = CreateCall<void, FString*, FString*>(&JitCompiler::CallAssignString);
call->setArg(0, regS[A]);
call->setArg(1, asmjit::imm(konsts + BC));
call->setArg(1, asmjit::imm_ptr(konsts + BC));
}
void JitCompiler::EmitLKP()
@ -36,26 +36,26 @@ void JitCompiler::EmitLKP()
void JitCompiler::EmitLK_R()
{
auto base = newTempIntPtr();
cc.mov(base, asmjit::imm(konstd + C));
cc.mov(regD[A], asmjit::x86::ptr(base, regD[B].cloneAs(base), 2));
cc.mov(base, asmjit::imm_ptr(konstd + C));
cc.mov(regD[A], asmjit::x86::ptr(base, regD[B], 2));
}
void JitCompiler::EmitLKF_R()
{
auto base = newTempIntPtr();
cc.mov(base, asmjit::imm(konstf + C));
cc.movsd(regF[A], asmjit::x86::qword_ptr(base, regD[B].cloneAs(base), 3));
cc.mov(base, asmjit::imm_ptr(konstf + C));
cc.movsd(regF[A], asmjit::x86::qword_ptr(base, regD[B], 3));
}
void JitCompiler::EmitLKS_R()
{
auto base = newTempIntPtr();
cc.mov(base, asmjit::imm(konsts + C));
cc.mov(base, asmjit::imm_ptr(konsts + C));
auto ptr = newTempIntPtr();
if (cc.is64Bit())
cc.lea(ptr, asmjit::x86::ptr(base, regD[B].cloneAs(base), 3));
cc.lea(ptr, asmjit::x86::ptr(base, regD[B], 3));
else
cc.lea(ptr, asmjit::x86::ptr(base, regD[B].cloneAs(base), 2));
cc.lea(ptr, asmjit::x86::ptr(base, regD[B], 2));
auto call = CreateCall<void, FString*, FString*>(&JitCompiler::CallAssignString);
call->setArg(0, regS[A]);
call->setArg(1, ptr);
@ -64,11 +64,11 @@ void JitCompiler::EmitLKS_R()
void JitCompiler::EmitLKP_R()
{
auto base = newTempIntPtr();
cc.mov(base, asmjit::imm(konsta + C));
cc.mov(base, asmjit::imm_ptr(konsta + C));
if (cc.is64Bit())
cc.mov(regA[A], asmjit::x86::ptr(base, regD[B].cloneAs(base), 3));
cc.mov(regA[A], asmjit::x86::ptr(base, regD[B], 3));
else
cc.mov(regA[A], asmjit::x86::ptr(base, regD[B].cloneAs(base), 2));
cc.mov(regA[A], asmjit::x86::ptr(base, regD[B], 2));
}
void JitCompiler::EmitLFP()
@ -107,7 +107,7 @@ void JitCompiler::EmitLB()
void JitCompiler::EmitLB_R()
{
EmitNullPointerThrow(B, X_READ_NIL);
cc.movsx(regD[A], asmjit::x86::byte_ptr(regA[B], regD[C].cloneAs(regA[B])));
cc.movsx(regD[A], asmjit::x86::byte_ptr(regA[B], regD[C]));
}
void JitCompiler::EmitLH()
@ -119,7 +119,7 @@ void JitCompiler::EmitLH()
void JitCompiler::EmitLH_R()
{
EmitNullPointerThrow(B, X_READ_NIL);
cc.movsx(regD[A], asmjit::x86::word_ptr(regA[B], regD[C].cloneAs(regA[B])));
cc.movsx(regD[A], asmjit::x86::word_ptr(regA[B], regD[C]));
}
void JitCompiler::EmitLW()
@ -131,7 +131,7 @@ void JitCompiler::EmitLW()
void JitCompiler::EmitLW_R()
{
EmitNullPointerThrow(B, X_READ_NIL);
cc.mov(regD[A], asmjit::x86::dword_ptr(regA[B], regD[C].cloneAs(regA[B])));
cc.mov(regD[A], asmjit::x86::dword_ptr(regA[B], regD[C]));
}
void JitCompiler::EmitLBU()
@ -143,19 +143,19 @@ void JitCompiler::EmitLBU()
void JitCompiler::EmitLBU_R()
{
EmitNullPointerThrow(B, X_READ_NIL);
cc.movzx(regD[A], asmjit::x86::byte_ptr(regA[B], regD[C].cloneAs(regA[B])));
cc.movzx(regD[A].r8Lo(), asmjit::x86::byte_ptr(regA[B], regD[C]));
}
void JitCompiler::EmitLHU()
{
EmitNullPointerThrow(B, X_READ_NIL);
cc.movzx(regD[A], asmjit::x86::word_ptr(regA[B], konstd[C]));
cc.movzx(regD[A].r16(), asmjit::x86::word_ptr(regA[B], konstd[C]));
}
void JitCompiler::EmitLHU_R()
{
EmitNullPointerThrow(B, X_READ_NIL);
cc.movzx(regD[A], asmjit::x86::word_ptr(regA[B], regD[C].cloneAs(regA[B])));
cc.movzx(regD[A].r16(), asmjit::x86::word_ptr(regA[B], regD[C]));
}
void JitCompiler::EmitLSP()
@ -169,7 +169,7 @@ void JitCompiler::EmitLSP_R()
{
EmitNullPointerThrow(B, X_READ_NIL);
cc.xorpd(regF[A], regF[A]);
cc.cvtss2sd(regF[A], asmjit::x86::dword_ptr(regA[B], regD[C].cloneAs(regA[B])));
cc.cvtss2sd(regF[A], asmjit::x86::dword_ptr(regA[B], regD[C]));
}
void JitCompiler::EmitLDP()
@ -181,7 +181,7 @@ void JitCompiler::EmitLDP()
void JitCompiler::EmitLDP_R()
{
EmitNullPointerThrow(B, X_READ_NIL);
cc.movsd(regF[A], asmjit::x86::qword_ptr(regA[B], regD[C].cloneAs(regA[B])));
cc.movsd(regF[A], asmjit::x86::qword_ptr(regA[B], regD[C]));
}
void JitCompiler::EmitLS()
@ -198,7 +198,7 @@ void JitCompiler::EmitLS_R()
{
EmitNullPointerThrow(B, X_READ_NIL);
auto ptr = newTempIntPtr();
cc.lea(ptr, asmjit::x86::ptr(regA[B], regD[C].cloneAs(regA[B])));
cc.lea(ptr, asmjit::x86::ptr(regA[B], regD[C]));
auto call = CreateCall<void, FString*, FString*>(&JitCompiler::CallAssignString);
call->setArg(0, regS[A]);
call->setArg(1, ptr);
@ -234,7 +234,7 @@ void JitCompiler::EmitLO_R()
{
EmitNullPointerThrow(B, X_READ_NIL);
cc.mov(regA[A], asmjit::x86::ptr(regA[B], regD[C].cloneAs(regA[B])));
cc.mov(regA[A], asmjit::x86::ptr(regA[B], regD[C]));
EmitReadBarrier();
}
@ -264,7 +264,7 @@ void JitCompiler::EmitLO_R()
EmitNullPointerThrow(B, X_READ_NIL);
auto ptr = newTempIntPtr();
cc.mov(ptr, asmjit::x86::ptr(regA[B], regD[C].cloneAs(regA[B])));
cc.mov(ptr, asmjit::x86::ptr(regA[B], regD[C]));
auto result = newResultIntPtr();
auto call = CreateCall<DObject*, DObject*>(ReadBarrier);
@ -284,7 +284,7 @@ void JitCompiler::EmitLP()
void JitCompiler::EmitLP_R()
{
EmitNullPointerThrow(B, X_READ_NIL);
cc.mov(regA[A], asmjit::x86::ptr(regA[B], regD[C].cloneAs(regA[B])));
cc.mov(regA[A], asmjit::x86::ptr(regA[B], regD[C]));
}
void JitCompiler::EmitLV2()
@ -300,7 +300,7 @@ void JitCompiler::EmitLV2_R()
{
EmitNullPointerThrow(B, X_READ_NIL);
auto tmp = newTempIntPtr();
cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], regD[C].cloneAs(regA[B])));
cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], regD[C]));
cc.movsd(regF[A], asmjit::x86::qword_ptr(tmp));
cc.movsd(regF[A + 1], asmjit::x86::qword_ptr(tmp, 8));
}
@ -319,7 +319,7 @@ void JitCompiler::EmitLV3_R()
{
EmitNullPointerThrow(B, X_READ_NIL);
auto tmp = newTempIntPtr();
cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], regD[C].cloneAs(regA[B])));
cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], regD[C]));
cc.movsd(regF[A], asmjit::x86::qword_ptr(tmp));
cc.movsd(regF[A + 1], asmjit::x86::qword_ptr(tmp, 8));
cc.movsd(regF[A + 2], asmjit::x86::qword_ptr(tmp, 16));
@ -344,7 +344,7 @@ void JitCompiler::EmitLCS_R()
{
EmitNullPointerThrow(B, X_READ_NIL);
auto ptr = newTempIntPtr();
cc.lea(ptr, asmjit::x86::ptr(regA[B], regD[C].cloneAs(regA[B])));
cc.lea(ptr, asmjit::x86::ptr(regA[B], regD[C]));
auto call = CreateCall<void, FString*, char**>(SetString);
call->setArg(0, regS[A]);
call->setArg(1, ptr);
@ -356,5 +356,5 @@ void JitCompiler::EmitLBIT()
cc.movsx(regD[A], asmjit::x86::byte_ptr(regA[B]));
cc.and_(regD[A], C);
cc.cmp(regD[A], 0);
cc.setne(regD[A].r8());
cc.setne(regD[A]);
}

View file

@ -51,10 +51,10 @@ void JitCompiler::EmitCMPS()
auto result = newResultInt32();
call->setRet(0, result);
if (static_cast<bool>(A & CMP_BK)) call->setArg(0, asmjit::imm(&konsts[B]));
if (static_cast<bool>(A & CMP_BK)) call->setArg(0, asmjit::imm_ptr(&konsts[B]));
else call->setArg(0, regS[B]);
if (static_cast<bool>(A & CMP_CK)) call->setArg(1, asmjit::imm(&konsts[C]));
if (static_cast<bool>(A & CMP_CK)) call->setArg(1, asmjit::imm_ptr(&konsts[C]));
else call->setArg(1, regS[C]);
int method = A & CMP_METHOD_MASK;
@ -84,7 +84,7 @@ void JitCompiler::EmitSLL_RR()
auto rc = CheckRegD(C, A);
if (A != B)
cc.mov(regD[A], regD[B]);
cc.shl(regD[A], rc.r8());
cc.shl(regD[A], rc);
}
void JitCompiler::EmitSLL_RI()
@ -98,7 +98,7 @@ void JitCompiler::EmitSLL_KR()
{
auto rc = CheckRegD(C, A);
cc.mov(regD[A], konstd[B]);
cc.shl(regD[A], rc.r8());
cc.shl(regD[A], rc);
}
void JitCompiler::EmitSRL_RR()
@ -106,7 +106,7 @@ void JitCompiler::EmitSRL_RR()
auto rc = CheckRegD(C, A);
if (A != B)
cc.mov(regD[A], regD[B]);
cc.shr(regD[A], rc.r8());
cc.shr(regD[A], rc);
}
void JitCompiler::EmitSRL_RI()
@ -120,7 +120,7 @@ void JitCompiler::EmitSRL_KR()
{
auto rc = CheckRegD(C, A);
cc.mov(regD[A], konstd[B]);
cc.shr(regD[A], rc.r8());
cc.shr(regD[A], rc);
}
void JitCompiler::EmitSRA_RR()
@ -128,7 +128,7 @@ void JitCompiler::EmitSRA_RR()
auto rc = CheckRegD(C, A);
if (A != B)
cc.mov(regD[A], regD[B]);
cc.sar(regD[A], rc.r8());
cc.sar(regD[A], rc);
}
void JitCompiler::EmitSRA_RI()
@ -142,7 +142,7 @@ void JitCompiler::EmitSRA_KR()
{
auto rc = CheckRegD(C, A);
cc.mov(regD[A], konstd[B]);
cc.sar(regD[A], rc.r8());
cc.sar(regD[A], rc);
}
void JitCompiler::EmitADD_RR()
@ -228,7 +228,7 @@ void JitCompiler::EmitDIV_RK()
auto konstTmp = newTempIntPtr();
cc.mov(tmp0, regD[B]);
cc.cdq(tmp1, tmp0);
cc.mov(konstTmp, asmjit::imm(&konstd[C]));
cc.mov(konstTmp, asmjit::imm_ptr(&konstd[C]));
cc.idiv(tmp1, tmp0, asmjit::x86::ptr(konstTmp));
cc.mov(regD[A], tmp0);
}
@ -277,7 +277,7 @@ void JitCompiler::EmitDIVU_RK()
auto konstTmp = newTempIntPtr();
cc.mov(tmp0, regD[B]);
cc.mov(tmp1, 0);
cc.mov(konstTmp, asmjit::imm(&konstd[C]));
cc.mov(konstTmp, asmjit::imm_ptr(&konstd[C]));
cc.div(tmp1, tmp0, asmjit::x86::ptr(konstTmp));
cc.mov(regD[A], tmp0);
}
@ -326,7 +326,7 @@ void JitCompiler::EmitMOD_RK()
auto konstTmp = newTempIntPtr();
cc.mov(tmp0, regD[B]);
cc.cdq(tmp1, tmp0);
cc.mov(konstTmp, asmjit::imm(&konstd[C]));
cc.mov(konstTmp, asmjit::imm_ptr(&konstd[C]));
cc.idiv(tmp1, tmp0, asmjit::x86::ptr(konstTmp));
cc.mov(regD[A], tmp1);
}
@ -375,7 +375,7 @@ void JitCompiler::EmitMODU_RK()
auto konstTmp = newTempIntPtr();
cc.mov(tmp0, regD[B]);
cc.mov(tmp1, 0);
cc.mov(konstTmp, asmjit::imm(&konstd[C]));
cc.mov(konstTmp, asmjit::imm_ptr(&konstd[C]));
cc.div(tmp1, tmp0, asmjit::x86::ptr(konstTmp));
cc.mov(regD[A], tmp1);
}
@ -586,7 +586,7 @@ void JitCompiler::EmitLT_KR()
{
EmitComparisonOpcode([&](bool check, asmjit::Label& fail, asmjit::Label& success) {
auto tmp = newTempIntPtr();
cc.mov(tmp, asmjit::imm(&konstd[B]));
cc.mov(tmp, asmjit::imm_ptr(&konstd[B]));
cc.cmp(asmjit::x86::ptr(tmp), regD[C]);
if (check) cc.jl(fail);
else cc.jnl(fail);
@ -615,7 +615,7 @@ void JitCompiler::EmitLE_KR()
{
EmitComparisonOpcode([&](bool check, asmjit::Label& fail, asmjit::Label& success) {
auto tmp = newTempIntPtr();
cc.mov(tmp, asmjit::imm(&konstd[B]));
cc.mov(tmp, asmjit::imm_ptr(&konstd[B]));
cc.cmp(asmjit::x86::ptr(tmp), regD[C]);
if (check) cc.jle(fail);
else cc.jnle(fail);
@ -644,7 +644,7 @@ void JitCompiler::EmitLTU_KR()
{
EmitComparisonOpcode([&](bool check, asmjit::Label& fail, asmjit::Label& success) {
auto tmp = newTempIntPtr();
cc.mov(tmp, asmjit::imm(&konstd[B]));
cc.mov(tmp, asmjit::imm_ptr(&konstd[B]));
cc.cmp(asmjit::x86::ptr(tmp), regD[C]);
if (check) cc.jb(fail);
else cc.jnb(fail);
@ -673,7 +673,7 @@ void JitCompiler::EmitLEU_KR()
{
EmitComparisonOpcode([&](bool check, asmjit::Label& fail, asmjit::Label& success) {
auto tmp = newTempIntPtr();
cc.mov(tmp, asmjit::imm(&konstd[B]));
cc.mov(tmp, asmjit::imm_ptr(&konstd[B]));
cc.cmp(asmjit::x86::ptr(tmp), regD[C]);
if (check) cc.jbe(fail);
else cc.jnbe(fail);
@ -696,7 +696,7 @@ void JitCompiler::EmitADDF_RK()
auto tmp = newTempIntPtr();
if (A != B)
cc.movsd(regF[A], regF[B]);
cc.mov(tmp, asmjit::imm(&konstf[C]));
cc.mov(tmp, asmjit::imm_ptr(&konstf[C]));
cc.addsd(regF[A], asmjit::x86::qword_ptr(tmp));
}
@ -713,7 +713,7 @@ void JitCompiler::EmitSUBF_RK()
auto tmp = newTempIntPtr();
if (A != B)
cc.movsd(regF[A], regF[B]);
cc.mov(tmp, asmjit::imm(&konstf[C]));
cc.mov(tmp, asmjit::imm_ptr(&konstf[C]));
cc.subsd(regF[A], asmjit::x86::qword_ptr(tmp));
}
@ -721,7 +721,7 @@ void JitCompiler::EmitSUBF_KR()
{
auto rc = CheckRegF(C, A);
auto tmp = newTempIntPtr();
cc.mov(tmp, asmjit::imm(&konstf[B]));
cc.mov(tmp, asmjit::imm_ptr(&konstf[B]));
cc.movsd(regF[A], asmjit::x86::qword_ptr(tmp));
cc.subsd(regF[A], rc);
}
@ -739,7 +739,7 @@ void JitCompiler::EmitMULF_RK()
auto tmp = newTempIntPtr();
if (A != B)
cc.movsd(regF[A], regF[B]);
cc.mov(tmp, asmjit::imm(&konstf[C]));
cc.mov(tmp, asmjit::imm_ptr(&konstf[C]));
cc.mulsd(regF[A], asmjit::x86::qword_ptr(tmp));
}
@ -766,7 +766,7 @@ void JitCompiler::EmitDIVF_RK()
{
auto tmp = newTempIntPtr();
cc.movsd(regF[A], regF[B]);
cc.mov(tmp, asmjit::imm(&konstf[C]));
cc.mov(tmp, asmjit::imm_ptr(&konstf[C]));
cc.divsd(regF[A], asmjit::x86::qword_ptr(tmp));
}
}
@ -775,7 +775,7 @@ void JitCompiler::EmitDIVF_KR()
{
auto rc = CheckRegF(C, A);
auto tmp = newTempIntPtr();
cc.mov(tmp, asmjit::imm(&konstf[B]));
cc.mov(tmp, asmjit::imm_ptr(&konstf[B]));
cc.movsd(regF[A], asmjit::x86::qword_ptr(tmp));
cc.divsd(regF[A], rc);
}
@ -810,7 +810,7 @@ void JitCompiler::EmitMODF_RK()
else
{
auto tmpPtr = newTempIntPtr();
cc.mov(tmpPtr, asmjit::imm(&konstf[C]));
cc.mov(tmpPtr, asmjit::imm_ptr(&konstf[C]));
auto tmp = newTempXmmSd();
cc.movsd(tmp, asmjit::x86::qword_ptr(tmpPtr));
@ -859,7 +859,7 @@ void JitCompiler::EmitPOWF_RK()
{
auto tmp = newTempIntPtr();
auto tmp2 = newTempXmmSd();
cc.mov(tmp, asmjit::imm(&konstf[C]));
cc.mov(tmp, asmjit::imm_ptr(&konstf[C]));
cc.movsd(tmp2, asmjit::x86::qword_ptr(tmp));
auto result = newResultXmmSd();
@ -874,7 +874,7 @@ void JitCompiler::EmitPOWF_KR()
{
auto tmp = newTempIntPtr();
auto tmp2 = newTempXmmSd();
cc.mov(tmp, asmjit::imm(&konstf[B]));
cc.mov(tmp, asmjit::imm_ptr(&konstf[B]));
cc.movsd(tmp2, asmjit::x86::qword_ptr(tmp));
auto result = newResultXmmSd();
@ -897,7 +897,7 @@ void JitCompiler::EmitMINF_RK()
{
auto rb = CheckRegF(B, A);
auto tmp = newTempIntPtr();
cc.mov(tmp, asmjit::imm(&konstf[C]));
cc.mov(tmp, asmjit::imm_ptr(&konstf[C]));
cc.movsd(regF[A], asmjit::x86::qword_ptr(tmp));
cc.minpd(regF[A], rb); // minsd requires SSE 4.1
}
@ -914,7 +914,7 @@ void JitCompiler::EmitMAXF_RK()
{
auto rb = CheckRegF(B, A);
auto tmp = newTempIntPtr();
cc.mov(tmp, asmjit::imm(&konstf[C]));
cc.mov(tmp, asmjit::imm_ptr(&konstf[C]));
cc.movsd(regF[A], asmjit::x86::qword_ptr(tmp));
cc.maxpd(regF[A], rb); // maxsd requires SSE 4.1
}
@ -930,7 +930,7 @@ void JitCompiler::EmitATAN2()
static const double constant = 180 / M_PI;
auto tmp = newTempIntPtr();
cc.mov(tmp, asmjit::imm(&constant));
cc.mov(tmp, asmjit::imm_ptr(&constant));
cc.mulsd(regF[A], asmjit::x86::qword_ptr(tmp));
}
@ -938,7 +938,7 @@ void JitCompiler::EmitFLOP()
{
if (C == FLOP_NEG)
{
auto mask = cc.newDoubleConst(asmjit::ConstPool::kScopeLocal, -0.0);
auto mask = cc.newDoubleConst(asmjit::kConstScopeLocal, -0.0);
auto maskXmm = newTempXmmSd();
cc.movsd(maskXmm, mask);
if (A != B)
@ -954,7 +954,7 @@ void JitCompiler::EmitFLOP()
{
static const double constant = M_PI / 180;
auto tmp = newTempIntPtr();
cc.mov(tmp, asmjit::imm(&constant));
cc.mov(tmp, asmjit::imm_ptr(&constant));
cc.mulsd(v, asmjit::x86::qword_ptr(tmp));
}
@ -998,7 +998,7 @@ void JitCompiler::EmitFLOP()
{
static const double constant = 180 / M_PI;
auto tmp = newTempIntPtr();
cc.mov(tmp, asmjit::imm(&constant));
cc.mov(tmp, asmjit::imm_ptr(&constant));
cc.mulsd(regF[A], asmjit::x86::qword_ptr(tmp));
}
}
@ -1025,10 +1025,10 @@ void JitCompiler::EmitEQF_R()
auto tmp = newTempXmmSd();
const int64_t absMaskInt = 0x7FFFFFFFFFFFFFFF;
auto absMask = cc.newDoubleConst(asmjit::ConstPool::kScopeLocal, reinterpret_cast<const double&>(absMaskInt));
auto absMask = cc.newDoubleConst(asmjit::kConstScopeLocal, reinterpret_cast<const double&>(absMaskInt));
auto absMaskXmm = newTempXmmPd();
auto epsilon = cc.newDoubleConst(asmjit::ConstPool::kScopeLocal, VM_EPSILON);
auto epsilon = cc.newDoubleConst(asmjit::kConstScopeLocal, VM_EPSILON);
auto epsilonXmm = newTempXmmSd();
cc.movsd(tmp, regF[B]);
@ -1051,7 +1051,7 @@ void JitCompiler::EmitEQF_K()
bool approx = static_cast<bool>(A & CMP_APPROX);
if (!approx) {
auto konstTmp = newTempIntPtr();
cc.mov(konstTmp, asmjit::imm(&konstf[C]));
cc.mov(konstTmp, asmjit::imm_ptr(&konstf[C]));
cc.ucomisd(regF[B], x86::qword_ptr(konstTmp));
if (check) {
cc.jp(success);
@ -1067,13 +1067,13 @@ void JitCompiler::EmitEQF_K()
auto subTmp = newTempXmmSd();
const int64_t absMaskInt = 0x7FFFFFFFFFFFFFFF;
auto absMask = cc.newDoubleConst(ConstPool::kScopeLocal, reinterpret_cast<const double&>(absMaskInt));
auto absMask = cc.newDoubleConst(kConstScopeLocal, reinterpret_cast<const double&>(absMaskInt));
auto absMaskXmm = newTempXmmPd();
auto epsilon = cc.newDoubleConst(ConstPool::kScopeLocal, VM_EPSILON);
auto epsilon = cc.newDoubleConst(kConstScopeLocal, VM_EPSILON);
auto epsilonXmm = newTempXmmSd();
cc.mov(konstTmp, asmjit::imm(&konstf[C]));
cc.mov(konstTmp, asmjit::imm_ptr(&konstf[C]));
cc.movsd(subTmp, regF[B]);
cc.subsd(subTmp, x86::qword_ptr(konstTmp));
@ -1106,7 +1106,7 @@ void JitCompiler::EmitLTF_RK()
auto constTmp = newTempIntPtr();
auto xmmTmp = newTempXmmSd();
cc.mov(constTmp, asmjit::imm(&konstf[C]));
cc.mov(constTmp, asmjit::imm_ptr(&konstf[C]));
cc.movsd(xmmTmp, asmjit::x86::qword_ptr(constTmp));
cc.ucomisd(xmmTmp, regF[B]);
@ -1121,7 +1121,7 @@ void JitCompiler::EmitLTF_KR()
if (static_cast<bool>(A & CMP_APPROX)) I_Error("CMP_APPROX not implemented for LTF_KR.\n");
auto tmp = newTempIntPtr();
cc.mov(tmp, asmjit::imm(&konstf[B]));
cc.mov(tmp, asmjit::imm_ptr(&konstf[B]));
cc.ucomisd(regF[C], asmjit::x86::qword_ptr(tmp));
if (check) cc.ja(fail);
@ -1147,7 +1147,7 @@ void JitCompiler::EmitLEF_RK()
auto constTmp = newTempIntPtr();
auto xmmTmp = newTempXmmSd();
cc.mov(constTmp, asmjit::imm(&konstf[C]));
cc.mov(constTmp, asmjit::imm_ptr(&konstf[C]));
cc.movsd(xmmTmp, asmjit::x86::qword_ptr(constTmp));
cc.ucomisd(xmmTmp, regF[B]);
@ -1162,7 +1162,7 @@ void JitCompiler::EmitLEF_KR()
if (static_cast<bool>(A & CMP_APPROX)) I_Error("CMP_APPROX not implemented for LEF_KR.\n");
auto tmp = newTempIntPtr();
cc.mov(tmp, asmjit::imm(&konstf[B]));
cc.mov(tmp, asmjit::imm_ptr(&konstf[B]));
cc.ucomisd(regF[C], asmjit::x86::qword_ptr(tmp));
if (check) cc.jae(fail);
@ -1175,7 +1175,7 @@ void JitCompiler::EmitLEF_KR()
void JitCompiler::EmitNEGV2()
{
auto mask = cc.newDoubleConst(asmjit::ConstPool::kScopeLocal, -0.0);
auto mask = cc.newDoubleConst(asmjit::kConstScopeLocal, -0.0);
auto maskXmm = newTempXmmSd();
cc.movsd(maskXmm, mask);
cc.movsd(regF[A], regF[B]);
@ -1230,7 +1230,7 @@ void JitCompiler::EmitMULVF2_RK()
auto tmp = newTempIntPtr();
cc.movsd(regF[A], regF[B]);
cc.movsd(regF[A + 1], regF[B + 1]);
cc.mov(tmp, asmjit::imm(&konstf[C]));
cc.mov(tmp, asmjit::imm_ptr(&konstf[C]));
cc.mulsd(regF[A], asmjit::x86::qword_ptr(tmp));
cc.mulsd(regF[A + 1], asmjit::x86::qword_ptr(tmp));
}
@ -1249,7 +1249,7 @@ void JitCompiler::EmitDIVVF2_RK()
auto tmp = newTempIntPtr();
cc.movsd(regF[A], regF[B]);
cc.movsd(regF[A + 1], regF[B + 1]);
cc.mov(tmp, asmjit::imm(&konstf[C]));
cc.mov(tmp, asmjit::imm_ptr(&konstf[C]));
cc.divsd(regF[A], asmjit::x86::qword_ptr(tmp));
cc.divsd(regF[A + 1], asmjit::x86::qword_ptr(tmp));
}
@ -1284,7 +1284,7 @@ void JitCompiler::EmitEQV2_K()
void JitCompiler::EmitNEGV3()
{
auto mask = cc.newDoubleConst(asmjit::ConstPool::kScopeLocal, -0.0);
auto mask = cc.newDoubleConst(asmjit::kConstScopeLocal, -0.0);
auto maskXmm = newTempXmmSd();
cc.movsd(maskXmm, mask);
cc.movsd(regF[A], regF[B]);
@ -1389,7 +1389,7 @@ void JitCompiler::EmitMULVF3_RK()
cc.movsd(regF[A], regF[B]);
cc.movsd(regF[A + 1], regF[B + 1]);
cc.movsd(regF[A + 2], regF[B + 2]);
cc.mov(tmp, asmjit::imm(&konstf[C]));
cc.mov(tmp, asmjit::imm_ptr(&konstf[C]));
cc.mulsd(regF[A], asmjit::x86::qword_ptr(tmp));
cc.mulsd(regF[A + 1], asmjit::x86::qword_ptr(tmp));
cc.mulsd(regF[A + 2], asmjit::x86::qword_ptr(tmp));
@ -1412,7 +1412,7 @@ void JitCompiler::EmitDIVVF3_RK()
cc.movsd(regF[A], regF[B]);
cc.movsd(regF[A + 1], regF[B + 1]);
cc.movsd(regF[A + 2], regF[B + 2]);
cc.mov(tmp, asmjit::imm(&konstf[C]));
cc.mov(tmp, asmjit::imm_ptr(&konstf[C]));
cc.divsd(regF[A], asmjit::x86::qword_ptr(tmp));
cc.divsd(regF[A + 1], asmjit::x86::qword_ptr(tmp));
cc.divsd(regF[A + 2], asmjit::x86::qword_ptr(tmp));
@ -1461,7 +1461,7 @@ void JitCompiler::EmitADDA_RR()
cc.je(label);
auto tmpptr = newTempIntPtr();
cc.mov(tmpptr.r32(), regD[C]);
cc.mov(tmpptr, regD[C]);
cc.add(tmp, tmpptr);
cc.bind(label);
@ -1488,9 +1488,8 @@ void JitCompiler::EmitADDA_RK()
void JitCompiler::EmitSUBA()
{
auto tmp = newTempIntPtr();
cc.mov(tmp.r32(), regD[C]);
cc.sub(tmp, regA[B]);
cc.neg(tmp);
cc.mov(tmp, regA[B]);
cc.sub(tmp, regD[C]);
cc.mov(regA[A], tmp);
}
@ -1507,14 +1506,14 @@ void JitCompiler::EmitEQA_K()
{
EmitComparisonOpcode([&](bool check, asmjit::Label& fail, asmjit::Label& success) {
auto tmp = newTempIntPtr();
cc.mov(tmp, asmjit::imm(konsta[C].v));
cc.mov(tmp, asmjit::imm_ptr(konsta[C].v));
cc.cmp(regA[B], tmp);
if (check) cc.je(fail);
else cc.jne(fail);
});
}
void JitCompiler::CallSqrt(const asmjit::x86::Xmm &a, const asmjit::x86::Xmm &b)
void JitCompiler::CallSqrt(const asmjit::X86Xmm &a, const asmjit::X86Xmm &b)
{
auto result = newResultXmmSd();
auto call = CreateCall<double, double>(g_sqrt);

View file

@ -57,9 +57,9 @@ static void CastTID2S(FString *a, int b) { auto tex = TexMan.GetTexture(*(FTextu
void JitCompiler::EmitCAST()
{
asmjit::x86::Gp tmp, resultD;
asmjit::x86::Xmm resultF;
asmjit::FuncCallNode *call = nullptr;
asmjit::X86Gp tmp, resultD;
asmjit::X86Xmm resultF;
asmjit::CCFuncCall *call = nullptr;
switch (C)
{
@ -185,7 +185,7 @@ void JitCompiler::EmitCASTB()
if (C == CASTB_I)
{
cc.cmp(regD[B], (int)0);
cc.setne(regD[A].r8());
cc.setne(regD[A]);
cc.movzx(regD[A], regD[A].r8Lo()); // not sure if this is needed
}
else if (C == CASTB_F)
@ -196,13 +196,13 @@ void JitCompiler::EmitCASTB()
cc.mov(one, 1);
cc.xor_(regD[A], regD[A]);
cc.ucomisd(regF[B], zero);
cc.setp(regD[A].r8());
cc.setp(regD[A]);
cc.cmovne(regD[A], one);
}
else if (C == CASTB_A)
{
cc.test(regA[B], regA[B]);
cc.setne(regD[A].r8());
cc.setne(regD[A]);
cc.movzx(regD[A], regD[A].r8Lo()); // not sure if this is needed
}
else
@ -234,7 +234,7 @@ void JitCompiler::EmitDYNCAST_K()
{
auto result = newResultIntPtr();
auto c = newTempIntPtr();
cc.mov(c, asmjit::imm(konsta[C].o));
cc.mov(c, asmjit::imm_ptr(konsta[C].o));
auto call = CreateCall<DObject*, DObject*, PClass*>(DynCast);
call->setRet(0, result);
call->setArg(0, regA[B]);
@ -262,7 +262,7 @@ void JitCompiler::EmitDYNCASTC_K()
using namespace asmjit;
auto result = newResultIntPtr();
auto c = newTempIntPtr();
cc.mov(c, asmjit::imm(konsta[C].o));
cc.mov(c, asmjit::imm_ptr(konsta[C].o));
typedef PClass*(*FuncPtr)(PClass*, PClass*);
auto call = CreateCall<PClass*, PClass*, PClass*>(DynCastC);
call->setRet(0, result);

View file

@ -36,7 +36,7 @@ asmjit::CodeInfo GetHostCodeInfo()
if (firstCall)
{
asmjit::JitRuntime rt;
codeInfo = rt.codeInfo();
codeInfo = rt.getCodeInfo();
firstCall = false;
}
@ -56,12 +56,13 @@ static void *AllocJitMemory(size_t size)
}
else
{
const size_t bytesToAllocate = asmjit::Support::alignUp(MAX(size_t(1024 * 1024), size), VirtMem::info().pageGranularity);
void *p;
if (VirtMem::alloc(&p, bytesToAllocate, VirtMem::kAccessReadWrite | VirtMem::kAccessExecute) != asmjit::kErrorOk)
const size_t bytesToAllocate = MAX(size_t(1024 * 1024), size);
size_t allocatedSize = 0;
void *p = OSUtils::allocVirtualMemory(bytesToAllocate, &allocatedSize, OSUtils::kVMWritable | OSUtils::kVMExecutable);
if (!p)
return nullptr;
JitBlocks.Push((uint8_t*)p);
JitBlockSize = bytesToAllocate;
JitBlockSize = allocatedSize;
JitBlockPos = size;
return p;
}
@ -79,15 +80,19 @@ static void *AllocJitMemory(size_t size)
#define UWOP_SAVE_XMM128_FAR 9
#define UWOP_PUSH_MACHFRAME 10
static TArray<uint16_t> CreateUnwindInfoWindows(asmjit::FuncNode *func)
static TArray<uint16_t> CreateUnwindInfoWindows(asmjit::CCFunc *func)
{
using namespace asmjit;
FuncFrame frame = func->frame();
FuncFrameLayout layout;
Error error = layout.init(func->getDetail(), func->getFrameInfo());
if (error != kErrorOk)
I_Error("FuncFrameLayout.init failed");
// We need a dummy assembler for instruction size calculations
// We need a dummy emitter for instruction size calculations
CodeHolder code;
code.init(GetHostCodeInfo());
x86::Assembler assembler(&code);
X86Assembler assembler(&code);
X86Emitter *emitter = assembler.asEmitter();
// Build UNWIND_CODE codes:
@ -96,26 +101,26 @@ static TArray<uint16_t> CreateUnwindInfoWindows(asmjit::FuncNode *func)
// Note: this must match exactly what X86Internal::emitProlog does
x86::Gp zsp = assembler.zsp(); // ESP|RSP register.
x86::Gp zbp = assembler.zsp(); // EBP|RBP register.
zbp.setId(x86::Gp::kIdBp);
x86::Gp gpReg = assembler.zsp(); // General purpose register (temporary).
x86::Gp saReg = assembler.zsp(); // Stack-arguments base register.
uint32_t gpSaved = frame.savedRegs(x86::Reg::kGroupGp);
X86Gp zsp = emitter->zsp(); // ESP|RSP register.
X86Gp zbp = emitter->zsp(); // EBP|RBP register.
zbp.setId(X86Gp::kIdBp);
X86Gp gpReg = emitter->zsp(); // General purpose register (temporary).
X86Gp saReg = emitter->zsp(); // Stack-arguments base register.
uint32_t gpSaved = layout.getSavedRegs(X86Reg::kKindGp);
if (frame.hasPreservedFP())
if (layout.hasPreservedFP())
{
// Emit: 'push zbp'
// 'mov zbp, zsp'.
gpSaved &= ~Support::bitMask(x86::Gp::kIdBp);
assembler.push(zbp);
gpSaved &= ~Utils::mask(X86Gp::kIdBp);
emitter->push(zbp);
opoffset = (uint32_t)assembler.offset();
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_PUSH_NONVOL;
opinfo = x86::Gp::kIdBp;
opinfo = X86Gp::kIdBp;
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
assembler.mov(zbp, zsp);
emitter->mov(zbp, zsp);
}
if (gpSaved)
@ -125,48 +130,48 @@ static TArray<uint16_t> CreateUnwindInfoWindows(asmjit::FuncNode *func)
if (!(i & 0x1)) continue;
// Emit: 'push gp' sequence.
gpReg.setId(regId);
assembler.push(gpReg);
emitter->push(gpReg);
opoffset = (uint32_t)assembler.offset();
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_PUSH_NONVOL;
opinfo = regId;
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
}
}
uint32_t saRegId = frame.saRegId();
if (saRegId != BaseReg::kIdBad && saRegId != x86::Gp::kIdSp)
uint32_t stackArgsRegId = layout.getStackArgsRegId();
if (stackArgsRegId != Globals::kInvalidRegId && stackArgsRegId != X86Gp::kIdSp)
{
saReg.setId(saRegId);
if (!(frame.hasPreservedFP() && saRegId == x86::Gp::kIdBp))
saReg.setId(stackArgsRegId);
if (!(layout.hasPreservedFP() && stackArgsRegId == X86Gp::kIdBp))
{
// Emit: 'mov saReg, zsp'.
assembler.mov(saReg, zsp);
emitter->mov(saReg, zsp);
}
}
if (frame.hasDynamicAlignment())
if (layout.hasDynamicAlignment())
{
// Emit: 'and zsp, StackAlignment'.
assembler.and_(zsp, -static_cast<int32_t>(frame.finalStackAlignment()));
emitter->and_(zsp, -static_cast<int32_t>(layout.getStackAlignment()));
}
if (frame.hasStackAdjustment())
if (layout.hasStackAdjustment())
{
// Emit: 'sub zsp, StackAdjustment'.
assembler.sub(zsp, frame.stackAdjustment());
emitter->sub(zsp, layout.getStackAdjustment());
uint32_t stackadjust = frame.stackAdjustment();
uint32_t stackadjust = layout.getStackAdjustment();
if (stackadjust <= 128)
{
opoffset = (uint32_t)assembler.offset();
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_ALLOC_SMALL;
opinfo = stackadjust / 8 - 1;
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
}
else if (stackadjust <= 512 * 1024 - 8)
{
opoffset = (uint32_t)assembler.offset();
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_ALLOC_LARGE;
opinfo = 0;
codes.Push(stackadjust / 8);
@ -174,7 +179,7 @@ static TArray<uint16_t> CreateUnwindInfoWindows(asmjit::FuncNode *func)
}
else
{
opoffset = (uint32_t)assembler.offset();
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_ALLOC_LARGE;
opinfo = 1;
codes.Push((uint16_t)(stackadjust >> 16));
@ -183,22 +188,21 @@ static TArray<uint16_t> CreateUnwindInfoWindows(asmjit::FuncNode *func)
}
}
if (frame.hasDynamicAlignment() && frame.hasDAOffset())
if (layout.hasDynamicAlignment() && layout.hasDsaSlotUsed())
{
// Emit: 'mov [zsp + dsaSlot], saReg'.
x86::Mem saMem = x86::ptr(zsp, int32_t(frame.daOffset()));
assembler.mov(saMem, saReg);
X86Mem saMem = x86::ptr(zsp, layout._dsaSlot);
emitter->mov(saMem, saReg);
}
uint32_t xmmSaved = frame.savedRegs(x86::Reg::kGroupVec);
uint32_t xmmSaved = layout.getSavedRegs(X86Reg::kKindVec);
if (xmmSaved)
{
int vecOffset = frame.nonGpSaveOffset();
x86::Mem vecBase = x86::ptr(zsp, vecOffset);
x86::Reg vecReg = x86::xmm(0);
bool avx = frame.isAvxEnabled();
bool aligned = frame.hasAlignedVecSR();
uint32_t vecInst = aligned ? (avx ? x86::Inst::kIdVmovaps : x86::Inst::kIdMovaps) : (avx ? x86::Inst::kIdVmovups : x86::Inst::kIdMovups);
X86Mem vecBase = x86::ptr(zsp, layout.getVecStackOffset());
X86Reg vecReg = x86::xmm(0);
bool avx = layout.isAvxEnabled();
bool aligned = layout.hasAlignedVecSR();
uint32_t vecInst = aligned ? (avx ? X86Inst::kIdVmovaps : X86Inst::kIdMovaps) : (avx ? X86Inst::kIdVmovups : X86Inst::kIdMovups);
uint32_t vecSize = 16;
for (uint32_t i = xmmSaved, regId = 0; i; i >>= 1, regId++)
{
@ -206,24 +210,24 @@ static TArray<uint16_t> CreateUnwindInfoWindows(asmjit::FuncNode *func)
// Emit 'movaps|movups [zsp + X], xmm0..15'.
vecReg.setId(regId);
assembler.emit(vecInst, vecBase, vecReg);
emitter->emit(vecInst, vecBase, vecReg);
vecBase.addOffsetLo32(static_cast<int32_t>(vecSize));
if (vecBase.offsetLo32() / vecSize < (1 << 16))
if (vecBase.getOffsetLo32() / vecSize < (1 << 16))
{
opoffset = (uint32_t)assembler.offset();
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_SAVE_XMM128;
opinfo = regId;
codes.Push(vecBase.offsetLo32() / vecSize);
codes.Push(vecBase.getOffsetLo32() / vecSize);
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
}
else
{
opoffset = (uint32_t)assembler.offset();
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_SAVE_XMM128_FAR;
opinfo = regId;
codes.Push((uint16_t)(vecBase.offsetLo32() >> 16));
codes.Push((uint16_t)vecBase.offsetLo32());
codes.Push((uint16_t)(vecBase.getOffsetLo32() >> 16));
codes.Push((uint16_t)vecBase.getOffsetLo32());
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
}
}
@ -232,7 +236,7 @@ static TArray<uint16_t> CreateUnwindInfoWindows(asmjit::FuncNode *func)
// Build the UNWIND_INFO structure:
uint16_t version = 1, flags = 0, frameRegister = 0, frameOffset = 0;
uint16_t sizeOfProlog = (uint16_t)assembler.offset();
uint16_t sizeOfProlog = (uint16_t)assembler.getOffset();
uint16_t countOfCodes = (uint16_t)codes.Size();
TArray<uint16_t> info;
@ -252,14 +256,10 @@ void *AddJitFunction(asmjit::CodeHolder* code, JitCompiler *compiler)
{
using namespace asmjit;
FuncNode *func = compiler->Codegen();
if (code->flatten() != kErrorOk)
return nullptr;
if (code->resolveUnresolvedLinks() != kErrorOk)
return nullptr;
CCFunc *func = compiler->Codegen();
size_t estimatedCodeSize = Support::alignUp(code->codeSize(), 16);
if (estimatedCodeSize == 0)
size_t codeSize = code->getCodeSize();
if (codeSize == 0)
return nullptr;
#ifdef _WIN64
@ -271,24 +271,24 @@ void *AddJitFunction(asmjit::CodeHolder* code, JitCompiler *compiler)
size_t functionTableSize = 0;
#endif
uint8_t *p = (uint8_t *)AllocJitMemory(estimatedCodeSize + unwindInfoSize + functionTableSize);
codeSize = (codeSize + 15) / 16 * 16;
uint8_t *p = (uint8_t *)AllocJitMemory(codeSize + unwindInfoSize + functionTableSize);
if (!p)
return nullptr;
if (code->relocateToBase((uintptr_t)p) != kErrorOk)
size_t relocSize = code->relocate(p);
if (relocSize == 0)
return nullptr;
size_t codeSize = code->codeSize();
for (Section* section : code->sections())
memcpy(p + size_t(section->offset()), section->data(), size_t(section->bufferSize()));
size_t unwindStart = Support::alignUp(codeSize, 16);
size_t unwindStart = relocSize;
unwindStart = (unwindStart + 15) / 16 * 16;
JitBlockPos -= codeSize - unwindStart;
#ifdef _WIN64
uint8_t *baseaddr = JitBlocks.Last();
uint8_t *startaddr = p;
uint8_t *endaddr = p + codeSize;
uint8_t *endaddr = p + relocSize;
uint8_t *unwindptr = p + unwindStart;
memcpy(unwindptr, &unwindInfo[0], unwindInfoSize);
@ -403,7 +403,7 @@ static void WriteCIE(TArray<uint8_t> &stream, const TArray<uint8_t> &cieInstruct
unsigned int lengthPos = stream.Size();
WriteUInt32(stream, 0); // Length
WriteUInt32(stream, 0); // CIE ID
WriteUInt8(stream, 1); // CIE Version
WriteUInt8(stream, 'z');
WriteUInt8(stream, 'R'); // fde encoding
@ -428,7 +428,7 @@ static void WriteFDE(TArray<uint8_t> &stream, const TArray<uint8_t> &fdeInstruct
WriteUInt32(stream, 0); // Length
uint32_t offsetToCIE = stream.Size() - cieLocation;
WriteUInt32(stream, offsetToCIE);
functionStart = stream.Size();
WriteUInt64(stream, 0); // func start
WriteUInt64(stream, 0); // func size
@ -486,7 +486,7 @@ static void WriteRegisterStackLocation(TArray<uint8_t> &instructions, int dwarfR
WriteULEB128(instructions, stackLocation);
}
static TArray<uint8_t> CreateUnwindInfoUnix(asmjit::FuncNode *func, unsigned int &functionStart)
static TArray<uint8_t> CreateUnwindInfoUnix(asmjit::CCFunc *func, unsigned int &functionStart)
{
using namespace asmjit;
@ -499,67 +499,71 @@ static TArray<uint8_t> CreateUnwindInfoUnix(asmjit::FuncNode *func, unsigned int
//
// The CFI_Parser<A>::decodeFDE parser on the other side..
// https://github.com/llvm-mirror/libunwind/blob/master/src/DwarfParser.hpp
// Asmjit -> DWARF register id
int dwarfRegId[16];
dwarfRegId[x86::Gp::kIdAx] = 0;
dwarfRegId[x86::Gp::kIdDx] = 1;
dwarfRegId[x86::Gp::kIdCx] = 2;
dwarfRegId[x86::Gp::kIdBx] = 3;
dwarfRegId[x86::Gp::kIdSi] = 4;
dwarfRegId[x86::Gp::kIdDi] = 5;
dwarfRegId[x86::Gp::kIdBp] = 6;
dwarfRegId[x86::Gp::kIdSp] = 7;
dwarfRegId[x86::Gp::kIdR8] = 8;
dwarfRegId[x86::Gp::kIdR9] = 9;
dwarfRegId[x86::Gp::kIdR10] = 10;
dwarfRegId[x86::Gp::kIdR11] = 11;
dwarfRegId[x86::Gp::kIdR12] = 12;
dwarfRegId[x86::Gp::kIdR13] = 13;
dwarfRegId[x86::Gp::kIdR14] = 14;
dwarfRegId[x86::Gp::kIdR15] = 15;
dwarfRegId[X86Gp::kIdAx] = 0;
dwarfRegId[X86Gp::kIdDx] = 1;
dwarfRegId[X86Gp::kIdCx] = 2;
dwarfRegId[X86Gp::kIdBx] = 3;
dwarfRegId[X86Gp::kIdSi] = 4;
dwarfRegId[X86Gp::kIdDi] = 5;
dwarfRegId[X86Gp::kIdBp] = 6;
dwarfRegId[X86Gp::kIdSp] = 7;
dwarfRegId[X86Gp::kIdR8] = 8;
dwarfRegId[X86Gp::kIdR9] = 9;
dwarfRegId[X86Gp::kIdR10] = 10;
dwarfRegId[X86Gp::kIdR11] = 11;
dwarfRegId[X86Gp::kIdR12] = 12;
dwarfRegId[X86Gp::kIdR13] = 13;
dwarfRegId[X86Gp::kIdR14] = 14;
dwarfRegId[X86Gp::kIdR15] = 15;
int dwarfRegRAId = 16;
int dwarfRegXmmId = 17;
TArray<uint8_t> cieInstructions;
TArray<uint8_t> fdeInstructions;
uint8_t returnAddressReg = dwarfRegRAId;
int stackOffset = 8; // Offset from RSP to the Canonical Frame Address (CFA) - stack position where the CALL return address is stored
WriteDefineCFA(cieInstructions, dwarfRegId[x86::Gp::kIdSp], stackOffset);
WriteDefineCFA(cieInstructions, dwarfRegId[X86Gp::kIdSp], stackOffset);
WriteRegisterStackLocation(cieInstructions, returnAddressReg, stackOffset);
FuncFrameLayout layout;
Error error = layout.init(func->getDetail(), func->getFrameInfo());
if (error != kErrorOk)
I_Error("FuncFrameLayout.init failed");
FuncFrame frame = func->frame();
// We need a dummy assembler for instruction size calculations
// We need a dummy emitter for instruction size calculations
CodeHolder code;
code.init(GetHostCodeInfo());
x86::Assembler assembler(&code);
X86Assembler assembler(&code);
X86Emitter *emitter = assembler.asEmitter();
uint64_t lastOffset = 0;
// Note: the following code must match exactly what X86Internal::emitProlog does
x86::Gp zsp = assembler.zsp(); // ESP|RSP register.
x86::Gp zbp = assembler.zsp(); // EBP|RBP register.
zbp.setId(x86::Gp::kIdBp);
x86::Gp gpReg = assembler.zsp(); // General purpose register (temporary).
x86::Gp saReg = assembler.zsp(); // Stack-arguments base register.
uint32_t gpSaved = frame.savedRegs(x86::Reg::kGroupGp);
X86Gp zsp = emitter->zsp(); // ESP|RSP register.
X86Gp zbp = emitter->zsp(); // EBP|RBP register.
zbp.setId(X86Gp::kIdBp);
X86Gp gpReg = emitter->zsp(); // General purpose register (temporary).
X86Gp saReg = emitter->zsp(); // Stack-arguments base register.
uint32_t gpSaved = layout.getSavedRegs(X86Reg::kKindGp);
if (frame.hasPreservedFP())
if (layout.hasPreservedFP())
{
// Emit: 'push zbp'
// 'mov zbp, zsp'.
gpSaved &= ~Support::bitMask(x86::Gp::kIdBp);
assembler.push(zbp);
gpSaved &= ~Utils::mask(X86Gp::kIdBp);
emitter->push(zbp);
stackOffset += 8;
WriteAdvanceLoc(fdeInstructions, assembler.offset(), lastOffset);
WriteAdvanceLoc(fdeInstructions, assembler.getOffset(), lastOffset);
WriteDefineStackOffset(fdeInstructions, stackOffset);
WriteRegisterStackLocation(fdeInstructions, dwarfRegId[x86::Gp::kIdBp], stackOffset);
WriteRegisterStackLocation(fdeInstructions, dwarfRegId[X86Gp::kIdBp], stackOffset);
assembler.mov(zbp, zsp);
emitter->mov(zbp, zsp);
}
if (gpSaved)
@ -569,60 +573,58 @@ static TArray<uint8_t> CreateUnwindInfoUnix(asmjit::FuncNode *func, unsigned int
if (!(i & 0x1)) continue;
// Emit: 'push gp' sequence.
gpReg.setId(regId);
assembler.push(gpReg);
emitter->push(gpReg);
stackOffset += 8;
WriteAdvanceLoc(fdeInstructions, assembler.offset(), lastOffset);
WriteAdvanceLoc(fdeInstructions, assembler.getOffset(), lastOffset);
WriteDefineStackOffset(fdeInstructions, stackOffset);
WriteRegisterStackLocation(fdeInstructions, dwarfRegId[regId], stackOffset);
}
}
uint32_t saRegId = frame.saRegId();
if (saRegId != BaseReg::kIdBad && saRegId != x86::Gp::kIdSp)
uint32_t stackArgsRegId = layout.getStackArgsRegId();
if (stackArgsRegId != Globals::kInvalidRegId && stackArgsRegId != X86Gp::kIdSp)
{
saReg.setId(saRegId);
if (frame.hasPreservedFP()) {
if (saRegId != x86::Gp::kIdBp)
assembler.mov(saReg, zbp);
}
else {
assembler.mov(saReg, zsp);
saReg.setId(stackArgsRegId);
if (!(layout.hasPreservedFP() && stackArgsRegId == X86Gp::kIdBp))
{
// Emit: 'mov saReg, zsp'.
emitter->mov(saReg, zsp);
}
}
if (frame.hasDynamicAlignment())
if (layout.hasDynamicAlignment())
{
// Emit: 'and zsp, StackAlignment'.
assembler.and_(zsp, -static_cast<int32_t>(frame.finalStackAlignment()));
emitter->and_(zsp, -static_cast<int32_t>(layout.getStackAlignment()));
}
if (frame.hasStackAdjustment())
if (layout.hasStackAdjustment())
{
// Emit: 'sub zsp, StackAdjustment'.
assembler.sub(zsp, frame.stackAdjustment());
emitter->sub(zsp, layout.getStackAdjustment());
stackOffset += frame.stackAdjustment();
WriteAdvanceLoc(fdeInstructions, assembler.offset(), lastOffset);
stackOffset += layout.getStackAdjustment();
WriteAdvanceLoc(fdeInstructions, assembler.getOffset(), lastOffset);
WriteDefineStackOffset(fdeInstructions, stackOffset);
}
if (frame.hasDynamicAlignment() && frame.hasDAOffset())
if (layout.hasDynamicAlignment() && layout.hasDsaSlotUsed())
{
// Emit: 'mov [zsp + dsaSlot], saReg'.
x86::Mem saMem = x86::ptr(zsp, int32_t(frame.daOffset()));
assembler.mov(saMem, saReg);
X86Mem saMem = x86::ptr(zsp, layout._dsaSlot);
emitter->mov(saMem, saReg);
}
uint32_t xmmSaved = frame.savedRegs(x86::Reg::kGroupVec);
uint32_t xmmSaved = layout.getSavedRegs(X86Reg::kKindVec);
if (xmmSaved)
{
int vecOffset = frame.nonGpSaveOffset();
x86::Mem vecBase = x86::ptr(zsp, vecOffset);
x86::Reg vecReg = x86::xmm(0);
bool avx = frame.isAvxEnabled();
bool aligned = frame.hasAlignedVecSR();
uint32_t vecInst = aligned ? (avx ? x86::Inst::kIdVmovaps : x86::Inst::kIdMovaps) : (avx ? x86::Inst::kIdVmovups : x86::Inst::kIdMovups);
int vecOffset = layout.getVecStackOffset();
X86Mem vecBase = x86::ptr(zsp, layout.getVecStackOffset());
X86Reg vecReg = x86::xmm(0);
bool avx = layout.isAvxEnabled();
bool aligned = layout.hasAlignedVecSR();
uint32_t vecInst = aligned ? (avx ? X86Inst::kIdVmovaps : X86Inst::kIdMovaps) : (avx ? X86Inst::kIdVmovups : X86Inst::kIdMovups);
uint32_t vecSize = 16;
for (uint32_t i = xmmSaved, regId = 0; i; i >>= 1, regId++)
{
@ -630,10 +632,10 @@ static TArray<uint8_t> CreateUnwindInfoUnix(asmjit::FuncNode *func, unsigned int
// Emit 'movaps|movups [zsp + X], xmm0..15'.
vecReg.setId(regId);
assembler.emit(vecInst, vecBase, vecReg);
emitter->emit(vecInst, vecBase, vecReg);
vecBase.addOffsetLo32(static_cast<int32_t>(vecSize));
WriteAdvanceLoc(fdeInstructions, assembler.offset(), lastOffset);
WriteAdvanceLoc(fdeInstructions, assembler.getOffset(), lastOffset);
WriteRegisterStackLocation(fdeInstructions, dwarfRegXmmId + regId, stackOffset - vecOffset);
vecOffset += static_cast<int32_t>(vecSize);
}
@ -650,37 +652,33 @@ void *AddJitFunction(asmjit::CodeHolder* code, JitCompiler *compiler)
{
using namespace asmjit;
FuncNode *func = compiler->Codegen();
if (code->flatten() != kErrorOk)
return nullptr;
if (code->resolveUnresolvedLinks() != kErrorOk)
return nullptr;
CCFunc *func = compiler->Codegen();
size_t estimatedCodeSize = Support::alignUp(code->codeSize(), 16);
if (estimatedCodeSize == 0)
size_t codeSize = code->getCodeSize();
if (codeSize == 0)
return nullptr;
unsigned int fdeFunctionStart = 0;
TArray<uint8_t> unwindInfo = CreateUnwindInfoUnix(func, fdeFunctionStart);
size_t unwindInfoSize = unwindInfo.Size();
uint8_t *p = (uint8_t *)AllocJitMemory(estimatedCodeSize + unwindInfoSize);
codeSize = (codeSize + 15) / 16 * 16;
uint8_t *p = (uint8_t *)AllocJitMemory(codeSize + unwindInfoSize);
if (!p)
return nullptr;
if (code->relocateToBase((uintptr_t)p) != kErrorOk)
size_t relocSize = code->relocate(p);
if (relocSize == 0)
return nullptr;
size_t codeSize = code->codeSize();
for (Section* section : code->sections())
memcpy(p + size_t(section->offset()), section->data(), size_t(section->bufferSize()));
size_t unwindStart = Support::alignUp(codeSize, 16);
size_t unwindStart = relocSize;
unwindStart = (unwindStart + 15) / 16 * 16;
JitBlockPos -= codeSize - unwindStart;
uint8_t *baseaddr = JitBlocks.Last();
uint8_t *startaddr = p;
uint8_t *endaddr = p + codeSize;
uint8_t *endaddr = p + relocSize;
uint8_t *unwindptr = p + unwindStart;
memcpy(unwindptr, &unwindInfo[0], unwindInfoSize);
@ -704,7 +702,7 @@ void *AddJitFunction(asmjit::CodeHolder* code, JitCompiler *compiler)
uint64_t length64 = *((uint64_t *)(entry + 4));
if (length64 == 0)
break;
uint64_t offset = *((uint64_t *)(entry + 12));
if (offset != 0)
{
@ -752,7 +750,7 @@ void JitRelease()
#endif
for (auto p : JitBlocks)
{
asmjit::VirtMem::release(p, 1024 * 1024);
asmjit::OSUtils::releaseVirtualMemory(p, 1024 * 1024);
}
JitDebugInfo.Clear();
JitFrames.Clear();

View file

@ -133,8 +133,8 @@ void JitCompiler::EmitSV2_R()
{
EmitNullPointerThrow(A, X_WRITE_NIL);
auto tmp = newTempIntPtr();
cc.mov(tmp.r32(), regD[C]);
cc.add(tmp, regA[A]);
cc.mov(tmp, regA[A]);
cc.add(tmp, regD[C]);
cc.movsd(asmjit::x86::qword_ptr(tmp), regF[B]);
cc.movsd(asmjit::x86::qword_ptr(tmp, 8), regF[B + 1]);
}
@ -154,8 +154,8 @@ void JitCompiler::EmitSV3_R()
{
EmitNullPointerThrow(A, X_WRITE_NIL);
auto tmp = newTempIntPtr();
cc.mov(tmp.r32(), regD[C]);
cc.add(tmp, regA[A]);
cc.mov(tmp, regA[A]);
cc.add(tmp, regD[C]);
cc.movsd(asmjit::x86::qword_ptr(tmp), regF[B]);
cc.movsd(asmjit::x86::qword_ptr(tmp, 8), regF[B + 1]);
cc.movsd(asmjit::x86::qword_ptr(tmp, 16), regF[B + 2]);
@ -166,11 +166,11 @@ void JitCompiler::EmitSBIT()
EmitNullPointerThrow(A, X_WRITE_NIL);
auto tmp1 = newTempInt32();
auto tmp2 = newTempInt32();
cc.movzx(tmp1, asmjit::x86::byte_ptr(regA[A]));
cc.mov(tmp1, asmjit::x86::byte_ptr(regA[A]));
cc.mov(tmp2, tmp1);
cc.or_(tmp1, (int)C);
cc.and_(tmp2, ~(int)C);
cc.test(regD[B], regD[B]);
cc.cmove(tmp1, tmp2);
cc.mov(asmjit::x86::byte_ptr(regA[A]), tmp1.r8());
cc.mov(asmjit::x86::byte_ptr(regA[A]), tmp1);
}

View file

@ -5,6 +5,7 @@
#include "stats.h"
// To do: get cmake to define these..
#define ASMJIT_BUILD_EMBED
#define ASMJIT_STATIC
#include <asmjit/asmjit.h>
@ -36,7 +37,7 @@ class JitCompiler
public:
JitCompiler(asmjit::CodeHolder *code, VMScriptFunction *sfunc) : cc(code), sfunc(sfunc) { }
asmjit::FuncNode *Codegen();
asmjit::CCFunc *Codegen();
VMScriptFunction *GetScriptFunction() { return sfunc; }
TArray<JitLineInfo> LineInfo;
@ -60,7 +61,7 @@ private:
void EmitPopFrame();
void EmitNativeCall(VMNativeFunction *target);
void EmitVMCall(asmjit::x86::Gp ptr, VMFunction *target);
void EmitVMCall(asmjit::X86Gp ptr, VMFunction *target);
void EmitVtbl(const VMOP *op);
int StoreCallParams();
@ -119,10 +120,10 @@ private:
auto tmp = newTempXmmSd();
const int64_t absMaskInt = 0x7FFFFFFFFFFFFFFF;
auto absMask = cc.newDoubleConst(asmjit::ConstPool::kScopeLocal, reinterpret_cast<const double&>(absMaskInt));
auto absMask = cc.newDoubleConst(asmjit::kConstScopeLocal, reinterpret_cast<const double&>(absMaskInt));
auto absMaskXmm = newTempXmmPd();
auto epsilon = cc.newDoubleConst(asmjit::ConstPool::kScopeLocal, VM_EPSILON);
auto epsilon = cc.newDoubleConst(asmjit::kConstScopeLocal, VM_EPSILON);
auto epsilonXmm = newTempXmmSd();
for (int i = 0; i < N; i++)
@ -160,37 +161,37 @@ private:
return (uint64_t)(ptrdiff_t)d;
}
void CallSqrt(const asmjit::x86::Xmm &a, const asmjit::x86::Xmm &b);
void CallSqrt(const asmjit::X86Xmm &a, const asmjit::X86Xmm &b);
static void CallAssignString(FString* to, FString* from) {
*to = *from;
}
template<typename RetType, typename P1>
asmjit::FuncCallNode *CreateCall(RetType(*func)(P1 p1)) { return cc.call(asmjit::imm(reinterpret_cast<void*>(static_cast<RetType(*)(P1)>(func))), asmjit::FuncSignatureT<RetType, P1>()); }
asmjit::CCFuncCall *CreateCall(RetType(*func)(P1 p1)) { return cc.call(asmjit::imm_ptr(reinterpret_cast<void*>(static_cast<RetType(*)(P1)>(func))), asmjit::FuncSignature1<RetType, P1>()); }
template<typename RetType, typename P1, typename P2>
asmjit::FuncCallNode *CreateCall(RetType(*func)(P1 p1, P2 p2)) { return cc.call(asmjit::imm(reinterpret_cast<void*>(static_cast<RetType(*)(P1, P2)>(func))), asmjit::FuncSignatureT<RetType, P1, P2>()); }
asmjit::CCFuncCall *CreateCall(RetType(*func)(P1 p1, P2 p2)) { return cc.call(asmjit::imm_ptr(reinterpret_cast<void*>(static_cast<RetType(*)(P1, P2)>(func))), asmjit::FuncSignature2<RetType, P1, P2>()); }
template<typename RetType, typename P1, typename P2, typename P3>
asmjit::FuncCallNode *CreateCall(RetType(*func)(P1 p1, P2 p2, P3 p3)) { return cc.call(asmjit::imm(reinterpret_cast<void*>(static_cast<RetType(*)(P1, P2, P3)>(func))), asmjit::FuncSignatureT<RetType, P1, P2, P3>()); }
asmjit::CCFuncCall *CreateCall(RetType(*func)(P1 p1, P2 p2, P3 p3)) { return cc.call(asmjit::imm_ptr(reinterpret_cast<void*>(static_cast<RetType(*)(P1, P2, P3)>(func))), asmjit::FuncSignature3<RetType, P1, P2, P3>()); }
template<typename RetType, typename P1, typename P2, typename P3, typename P4>
asmjit::FuncCallNode *CreateCall(RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4)) { return cc.call(asmjit::imm(reinterpret_cast<void*>(static_cast<RetType(*)(P1, P2, P3, P4)>(func))), asmjit::FuncSignatureT<RetType, P1, P2, P3, P4>()); }
asmjit::CCFuncCall *CreateCall(RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4)) { return cc.call(asmjit::imm_ptr(reinterpret_cast<void*>(static_cast<RetType(*)(P1, P2, P3, P4)>(func))), asmjit::FuncSignature4<RetType, P1, P2, P3, P4>()); }
template<typename RetType, typename P1, typename P2, typename P3, typename P4, typename P5>
asmjit::FuncCallNode *CreateCall(RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)) { return cc.call(asmjit::imm(reinterpret_cast<void*>(static_cast<RetType(*)(P1, P2, P3, P4, P5)>(func))), asmjit::FuncSignatureT<RetType, P1, P2, P3, P4, P5>()); }
asmjit::CCFuncCall *CreateCall(RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)) { return cc.call(asmjit::imm_ptr(reinterpret_cast<void*>(static_cast<RetType(*)(P1, P2, P3, P4, P5)>(func))), asmjit::FuncSignature5<RetType, P1, P2, P3, P4, P5>()); }
template<typename RetType, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
asmjit::FuncCallNode *CreateCall(RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)) { return cc.call(asmjit::imm(reinterpret_cast<void*>(static_cast<RetType(*)(P1, P2, P3, P4, P5, P6)>(func))), asmjit::FuncSignatureT<RetType, P1, P2, P3, P4, P5, P6>()); }
asmjit::CCFuncCall *CreateCall(RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)) { return cc.call(asmjit::imm_ptr(reinterpret_cast<void*>(static_cast<RetType(*)(P1, P2, P3, P4, P5, P6)>(func))), asmjit::FuncSignature6<RetType, P1, P2, P3, P4, P5, P6>()); }
template<typename RetType, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
asmjit::FuncCallNode *CreateCall(RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)) { return cc.call(asmjit::imm(reinterpret_cast<void*>(static_cast<RetType(*)(P1, P2, P3, P4, P5, P6, P7)>(func))), asmjit::FuncSignatureT<RetType, P1, P2, P3, P4, P5, P6, P7>()); }
asmjit::CCFuncCall *CreateCall(RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)) { return cc.call(asmjit::imm_ptr(reinterpret_cast<void*>(static_cast<RetType(*)(P1, P2, P3, P4, P5, P6, P7)>(func))), asmjit::FuncSignature7<RetType, P1, P2, P3, P4, P5, P6, P7>()); }
FString regname;
size_t tmpPosInt32, tmpPosInt64, tmpPosIntPtr, tmpPosXmmSd, tmpPosXmmSs, tmpPosXmmPd, resultPosInt32, resultPosIntPtr, resultPosXmmSd;
std::vector<asmjit::x86::Gp> regTmpInt32, regTmpInt64, regTmpIntPtr, regResultInt32, regResultIntPtr;
std::vector<asmjit::x86::Xmm> regTmpXmmSd, regTmpXmmSs, regTmpXmmPd, regResultXmmSd;
std::vector<asmjit::X86Gp> regTmpInt32, regTmpInt64, regTmpIntPtr, regResultInt32, regResultIntPtr;
std::vector<asmjit::X86Xmm> regTmpXmmSd, regTmpXmmSs, regTmpXmmPd, regResultXmmSd;
void ResetTemp()
{
@ -216,16 +217,16 @@ private:
return tmpVector[tmpPos++];
}
asmjit::x86::Gp newTempInt32() { return newTempRegister(regTmpInt32, tmpPosInt32, "tmpDword", [&](const char *name) { return cc.newInt32(name); }); }
asmjit::x86::Gp newTempInt64() { return newTempRegister(regTmpInt64, tmpPosInt64, "tmpQword", [&](const char *name) { return cc.newInt64(name); }); }
asmjit::x86::Gp newTempIntPtr() { return newTempRegister(regTmpIntPtr, tmpPosIntPtr, "tmpPtr", [&](const char *name) { return cc.newIntPtr(name); }); }
asmjit::x86::Xmm newTempXmmSd() { return newTempRegister(regTmpXmmSd, tmpPosXmmSd, "tmpXmmSd", [&](const char *name) { return cc.newXmmSd(name); }); }
asmjit::x86::Xmm newTempXmmSs() { return newTempRegister(regTmpXmmSs, tmpPosXmmSs, "tmpXmmSs", [&](const char *name) { return cc.newXmmSs(name); }); }
asmjit::x86::Xmm newTempXmmPd() { return newTempRegister(regTmpXmmPd, tmpPosXmmPd, "tmpXmmPd", [&](const char *name) { return cc.newXmmPd(name); }); }
asmjit::X86Gp newTempInt32() { return newTempRegister(regTmpInt32, tmpPosInt32, "tmpDword", [&](const char *name) { return cc.newInt32(name); }); }
asmjit::X86Gp newTempInt64() { return newTempRegister(regTmpInt64, tmpPosInt64, "tmpQword", [&](const char *name) { return cc.newInt64(name); }); }
asmjit::X86Gp newTempIntPtr() { return newTempRegister(regTmpIntPtr, tmpPosIntPtr, "tmpPtr", [&](const char *name) { return cc.newIntPtr(name); }); }
asmjit::X86Xmm newTempXmmSd() { return newTempRegister(regTmpXmmSd, tmpPosXmmSd, "tmpXmmSd", [&](const char *name) { return cc.newXmmSd(name); }); }
asmjit::X86Xmm newTempXmmSs() { return newTempRegister(regTmpXmmSs, tmpPosXmmSs, "tmpXmmSs", [&](const char *name) { return cc.newXmmSs(name); }); }
asmjit::X86Xmm newTempXmmPd() { return newTempRegister(regTmpXmmPd, tmpPosXmmPd, "tmpXmmPd", [&](const char *name) { return cc.newXmmPd(name); }); }
asmjit::x86::Gp newResultInt32() { return newTempRegister(regResultInt32, resultPosInt32, "resultDword", [&](const char *name) { return cc.newInt32(name); }); }
asmjit::x86::Gp newResultIntPtr() { return newTempRegister(regResultIntPtr, resultPosIntPtr, "resultPtr", [&](const char *name) { return cc.newIntPtr(name); }); }
asmjit::x86::Xmm newResultXmmSd() { return newTempRegister(regResultXmmSd, resultPosXmmSd, "resultXmmSd", [&](const char *name) { return cc.newXmmSd(name); }); }
asmjit::X86Gp newResultInt32() { return newTempRegister(regResultInt32, resultPosInt32, "resultDword", [&](const char *name) { return cc.newInt32(name); }); }
asmjit::X86Gp newResultIntPtr() { return newTempRegister(regResultIntPtr, resultPosIntPtr, "resultPtr", [&](const char *name) { return cc.newIntPtr(name); }); }
asmjit::X86Xmm newResultXmmSd() { return newTempRegister(regResultXmmSd, resultPosXmmSd, "resultXmmSd", [&](const char *name) { return cc.newXmmSd(name); }); }
void EmitReadBarrier();
@ -236,22 +237,22 @@ private:
static void ThrowArrayOutOfBounds(int index, int size);
static void ThrowException(int reason);
asmjit::x86::Gp CheckRegD(int r0, int r1);
asmjit::x86::Xmm CheckRegF(int r0, int r1);
asmjit::x86::Xmm CheckRegF(int r0, int r1, int r2);
asmjit::x86::Xmm CheckRegF(int r0, int r1, int r2, int r3);
asmjit::x86::Gp CheckRegS(int r0, int r1);
asmjit::x86::Gp CheckRegA(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, int r2);
asmjit::X86Xmm CheckRegF(int r0, int r1, int r2, int r3);
asmjit::X86Gp CheckRegS(int r0, int r1);
asmjit::X86Gp CheckRegA(int r0, int r1);
asmjit::x86::Compiler cc;
asmjit::X86Compiler cc;
VMScriptFunction *sfunc;
asmjit::FuncNode *func = nullptr;
asmjit::x86::Gp args;
asmjit::x86::Gp numargs;
asmjit::x86::Gp ret;
asmjit::x86::Gp numret;
asmjit::x86::Gp stack;
asmjit::CCFunc *func = nullptr;
asmjit::X86Gp args;
asmjit::X86Gp numargs;
asmjit::X86Gp ret;
asmjit::X86Gp numret;
asmjit::X86Gp stack;
int offsetParams;
int offsetF;
@ -263,29 +264,29 @@ private:
TArray<const VMOP *> ParamOpcodes;
void CheckVMFrame();
asmjit::x86::Gp GetCallReturns();
asmjit::X86Gp GetCallReturns();
bool vmframeAllocated = false;
asmjit::BaseNode *vmframeCursor = nullptr;
asmjit::x86::Gp vmframe;
asmjit::CBNode *vmframeCursor = nullptr;
asmjit::X86Gp vmframe;
bool callReturnsAllocated = false;
asmjit::BaseNode *callReturnsCursor = nullptr;
asmjit::x86::Gp callReturns;
asmjit::CBNode *callReturnsCursor = nullptr;
asmjit::X86Gp callReturns;
const int *konstd;
const double *konstf;
const FString *konsts;
const FVoidObj *konsta;
TArray<asmjit::x86::Gp> regD;
TArray<asmjit::x86::Xmm> regF;
TArray<asmjit::x86::Gp> regA;
TArray<asmjit::x86::Gp> regS;
TArray<asmjit::X86Gp> regD;
TArray<asmjit::X86Xmm> regF;
TArray<asmjit::X86Gp> regA;
TArray<asmjit::X86Gp> regS;
struct OpcodeLabel
{
asmjit::BaseNode *cursor = nullptr;
asmjit::CBNode *cursor = nullptr;
asmjit::Label label;
bool inUse = false;
};
@ -326,7 +327,7 @@ public:
class ThrowingErrorHandler : public asmjit::ErrorHandler
{
public:
void handleError(asmjit::Error err, const char *message, asmjit::BaseEmitter *origin) override
bool handleError(asmjit::Error err, const char *message, asmjit::CodeEmitter *origin) override
{
throw AsmJitException(err, message);
}