Replace the native call templates with CreateNativeFunction to make it more explicit which IR types are actually used

This commit is contained in:
Magnus Norddahl 2020-06-06 00:28:10 +02:00
parent d3288a8dae
commit 1c9df61c5d
8 changed files with 400 additions and 339 deletions

View file

@ -2,6 +2,10 @@
#include "jit.h"
#include "jitintern.h"
#include "printf.h"
#include "v_video.h"
#include "s_soundinternal.h"
#include "texturemanager.h"
#include "palutil.h"
extern PString *TypeString;
extern PStruct *TypeVector2;
@ -158,7 +162,7 @@ void JitCompiler::CheckVMFrame()
{
if (!vmframe)
{
vmframe = irfunc->createAlloca(ircontext->getInt8Ty(), ircontext->getConstantInt(sfunc->StackSize), "vmframe");
vmframe = irfunc->createAlloca(int8Ty, ircontext->getConstantInt(sfunc->StackSize), "vmframe");
}
}
@ -166,7 +170,7 @@ IRValue* JitCompiler::GetCallReturns()
{
if (!callReturns)
{
callReturns = irfunc->createAlloca(ircontext->getInt8Ty(), ircontext->getConstantInt(sizeof(VMReturn) * MAX_RETURNS), "callReturns");
callReturns = irfunc->createAlloca(int8Ty, ircontext->getConstantInt(sizeof(VMReturn) * MAX_RETURNS), "callReturns");
}
return callReturns;
}
@ -215,6 +219,9 @@ IRBasicBlock* JitCompiler::GetLabel(size_t pos)
void JitCompiler::Setup()
{
GetTypes();
CreateNativeFunctions();
//static const char *marks = "=======================================================";
//cc.comment("", 0);
//cc.comment(marks, 56);
@ -226,7 +233,8 @@ void JitCompiler::Setup()
//cc.comment(marks, 56);
//cc.comment("", 0);
irfunc = ircontext->createFunction(GetFunctionType5<int, VMFunction*, void*, int, void*, int>(), sfunc->PrintableName.GetChars());
IRFunctionType* functype = ircontext->getFunctionType(int32Ty, { int8PtrTy, int8PtrTy, int32Ty, int8PtrTy, int32Ty });
irfunc = ircontext->createFunction(functype, sfunc->PrintableName.GetChars());
irfunc->fileInfo.push_back({ sfunc->PrintableName.GetChars(), sfunc->SourceFileName.GetChars() });
args = irfunc->args[1];
@ -323,17 +331,9 @@ void JitCompiler::SetupSimpleFrame()
StoreA(ConstValueA(nullptr), i);
}
static VMFrameStack *CreateFullVMFrame(VMScriptFunction *func, VMValue *args, int numargs)
{
VMFrameStack *stack = &GlobalVMStack;
VMFrame *newf = stack->AllocFrame(func);
VMFillParams(args, newf, numargs);
return stack;
}
void JitCompiler::SetupFullVMFrame()
{
vmframestack = cc.CreateCall(GetNativeFunc<VMFrameStack*, VMScriptFunction*, VMValue*, int>("__CreateFullVMFrame", CreateFullVMFrame), { ConstValueA(sfunc), args, numargs });
vmframestack = cc.CreateCall(createFullVMFrame, { ConstValueA(sfunc), args, numargs });
IRValue* Blocks = Load(ToInt8PtrPtr(vmframestack)); // vmframestack->Blocks
vmframe = Load(ToInt8PtrPtr(Blocks, VMFrameStack::OffsetLastFrame())); // Blocks->LastFrame
@ -351,23 +351,18 @@ void JitCompiler::SetupFullVMFrame()
StoreA(Load(ToInt8PtrPtr(vmframe, offsetA + i * sizeof(void*))), i);
}
static void PopFullVMFrame(VMFrameStack * vmframestack)
{
vmframestack->PopFrame();
}
void JitCompiler::EmitPopFrame()
{
if (sfunc->SpecialInits.Size() != 0 || sfunc->NumRegS != 0)
{
cc.CreateCall(GetNativeFunc<void, VMFrameStack*>("__PopFullVMFrame", PopFullVMFrame), { vmframestack });
cc.CreateCall(popFullVMFrame, { vmframestack });
}
}
void JitCompiler::IncrementVMCalls()
{
// VMCalls[0]++
IRValue* vmcallsptr = ircontext->getConstantInt(ircontext->getInt32PtrTy(), (uint64_t)VMCalls);
IRValue* vmcallsptr = ircontext->getConstantInt(int32PtrTy, (uint64_t)VMCalls);
cc.CreateStore(cc.CreateAdd(cc.CreateLoad(vmcallsptr), ircontext->getConstantInt(1)), vmcallsptr);
}
@ -379,34 +374,30 @@ void JitCompiler::CreateRegisters()
regS.Resize(sfunc->NumRegS);
FString regname;
IRType* type;
IRValue* arraySize = ircontext->getConstantInt(1);
type = ircontext->getInt32Ty();
for (int i = 0; i < sfunc->NumRegD; i++)
{
regname.Format("regD%d", i);
regD[i] = irfunc->createAlloca(type, arraySize, regname.GetChars());
regD[i] = irfunc->createAlloca(int32Ty, arraySize, regname.GetChars());
}
type = ircontext->getDoubleTy();
for (int i = 0; i < sfunc->NumRegF; i++)
{
regname.Format("regF%d", i);
regF[i] = irfunc->createAlloca(type, arraySize, regname.GetChars());
regF[i] = irfunc->createAlloca(doubleTy, arraySize, regname.GetChars());
}
type = ircontext->getInt8PtrTy();
for (int i = 0; i < sfunc->NumRegS; i++)
{
regname.Format("regS%d", i);
regS[i] = irfunc->createAlloca(type, arraySize, regname.GetChars());
regS[i] = irfunc->createAlloca(int8PtrTy, arraySize, regname.GetChars());
}
for (int i = 0; i < sfunc->NumRegA; i++)
{
regname.Format("regA%d", i);
regA[i] = irfunc->createAlloca(type, arraySize, regname.GetChars());
regA[i] = irfunc->createAlloca(int8PtrTy, arraySize, regname.GetChars());
}
}
@ -420,15 +411,10 @@ void JitCompiler::EmitNullPointerThrow(int index, EVMAbortException reason)
void JitCompiler::EmitThrowException(EVMAbortException reason)
{
cc.CreateCall(GetNativeFunc<void, int>("__ThrowException", &JitCompiler::ThrowException), { ConstValueD(reason) });
cc.CreateCall(throwException, { ConstValueD(reason) });
cc.CreateRet(ConstValueD(0));
}
void JitCompiler::ThrowException(int reason)
{
ThrowAbortException((EVMAbortException)reason, nullptr);
}
IRBasicBlock* JitCompiler::EmitThrowExceptionLabel(EVMAbortException reason)
{
auto bb = irfunc->createBasicBlock({});
@ -444,3 +430,181 @@ void JitCompiler::EmitNOP()
{
// The IR doesn't have a NOP instruction
}
static void ValidateCall(DObject* o, VMFunction* f, int b)
{
FScopeBarrier::ValidateCall(o->GetClass(), f, b - 1);
}
static void SetReturnString(VMReturn* ret, FString* str)
{
ret->SetString(*str);
}
static VMFrameStack* CreateFullVMFrame(VMScriptFunction* func, VMValue* args, int numargs)
{
VMFrameStack* stack = &GlobalVMStack;
VMFrame* newf = stack->AllocFrame(func);
VMFillParams(args, newf, numargs);
return stack;
}
static void PopFullVMFrame(VMFrameStack* vmframestack)
{
vmframestack->PopFrame();
}
static void ThrowException(int reason)
{
ThrowAbortException((EVMAbortException)reason, nullptr);
}
static void ThrowArrayOutOfBounds(int index, int size)
{
if (index >= size)
{
ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", size, index);
}
else
{
ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Negative current index = %i\n", index);
}
}
static DObject* ReadBarrier(DObject* p) { return GC::ReadBarrier(p); }
static void WriteBarrier(DObject* p) { GC::WriteBarrier(p); }
static void StringAssignmentOperator(FString* to, FString* from) { *to = *from; }
static void StringAssignmentOperatorCStr(FString* to, char** from) { *to = *from; }
static void StringPlusOperator(FString* to, FString* first, FString* second) { *to = *first + *second; }
static int StringLength(FString* str) { return static_cast<int>(str->Len()); }
static int StringCompareNoCase(FString* first, FString* second) { return first->CompareNoCase(*second); }
static int StringCompare(FString* first, FString* second) { return first->Compare(*second); }
static double DoubleModF(double a, double b) { return a - floor(a / b) * b; }
static double DoublePow(double a, double b) { return g_pow(a, b); }
static double DoubleAtan2(double a, double b) { return g_atan2(a, b); }
static double DoubleFabs(double a) { return fabs(a); }
static double DoubleExp(double a) { return g_exp(a); }
static double DoubleLog(double a) { return g_log(a); }
static double DoubleLog10(double a) { return g_log10(a); }
static double DoubleSqrt(double a) { return g_sqrt(a); }
static double DoubleCeil(double a) { return ceil(a); }
static double DoubleFloor(double a) { return floor(a); }
static double DoubleAcos(double a) { return g_acos(a); }
static double DoubleAsin(double a) { return g_asin(a); }
static double DoubleAtan(double a) { return g_atan(a); }
static double DoubleCos(double a) { return g_cos(a); }
static double DoubleSin(double a) { return g_sin(a); }
static double DoubleTan(double a) { return g_tan(a); }
static double DoubleCosDeg(double a) { return g_cosdeg(a); }
static double DoubleSinDeg(double a) { return g_sindeg(a); }
static double DoubleCosh(double a) { return g_cosh(a); }
static double DoubleSinh(double a) { return g_sinh(a); }
static double DoubleTanh(double a) { return g_tanh(a); }
static double DoubleRound(double a) { return round(a); }
static void CastI2S(FString* a, int b) { a->Format("%d", b); }
static void CastU2S(FString* a, int b) { a->Format("%u", b); }
static void CastF2S(FString* a, double b) { a->Format("%.5f", b); }
static void CastV22S(FString* a, double b, double b1) { a->Format("(%.5f, %.5f)", b, b1); }
static void CastV32S(FString* a, double b, double b1, double b2) { a->Format("(%.5f, %.5f, %.5f)", b, b1, b2); }
static void CastP2S(FString* a, void* b) { if (b == nullptr) *a = "null"; else a->Format("%p", b); }
static int CastS2I(FString* b) { return (int)b->ToLong(); }
static double CastS2F(FString* b) { return b->ToDouble(); }
static int CastS2N(FString* b) { return b->Len() == 0 ? NAME_None : FName(*b).GetIndex(); }
static void CastN2S(FString* a, int b) { FName name = FName(ENamedName(b)); *a = name.IsValidName() ? name.GetChars() : ""; }
static int CastS2Co(FString* b) { return V_GetColor(nullptr, *b); }
static void CastCo2S(FString* a, int b) { PalEntry c(b); a->Format("%02x %02x %02x", c.r, c.g, c.b); }
static int CastS2So(FString* b) { return FSoundID(*b); }
static void CastSo2S(FString* a, int b) { *a = soundEngine->GetSoundName(b); }
static void CastSID2S(FString* a, unsigned int b) { VM_CastSpriteIDToString(a, b); }
static void CastTID2S(FString* a, int b) { auto tex = TexMan.GetGameTexture(*(FTextureID*)&b); *a = (tex == nullptr) ? "(null)" : tex->GetName().GetChars(); }
static int CastB_S(FString* s) { return s->Len() > 0; }
static DObject* DynCast(DObject* obj, PClass* cls) { return (obj && obj->IsKindOf(cls)) ? obj : nullptr; }
static PClass* DynCastC(PClass* cls1, PClass* cls2) { return (cls1 && cls1->IsDescendantOf(cls2)) ? cls1 : nullptr; }
void JitCompiler::GetTypes()
{
voidTy = ircontext->getVoidTy();
int8Ty = ircontext->getInt8Ty();
int8PtrTy = ircontext->getInt8PtrTy();
int8PtrPtrTy = int8PtrTy->getPointerTo(ircontext);
int16Ty = ircontext->getInt16Ty();
int16PtrTy = ircontext->getInt16PtrTy();
int32Ty = ircontext->getInt32Ty();
int32PtrTy = ircontext->getInt32PtrTy();
int64Ty = ircontext->getInt64Ty();
floatTy = ircontext->getFloatTy();
floatPtrTy = ircontext->getFloatPtrTy();
doubleTy = ircontext->getDoubleTy();
doublePtrTy = ircontext->getDoublePtrTy();
}
void JitCompiler::CreateNativeFunctions()
{
validateCall = CreateNativeFunction(voidTy, { int8PtrTy, int8PtrTy, int32Ty }, "__ValidateCall", ValidateCall);
setReturnString = CreateNativeFunction(voidTy, { int8PtrTy, int8PtrTy }, "__SetReturnString", SetReturnString);
createFullVMFrame = CreateNativeFunction(int8PtrTy, { int8PtrTy, int8PtrTy, int32Ty }, "__CreateFullVMFrame", CreateFullVMFrame);
popFullVMFrame = CreateNativeFunction(voidTy, { int8PtrTy }, "__PopFullVMFrame", PopFullVMFrame);
throwException = CreateNativeFunction(voidTy, { int32Ty }, "__ThrowException", ThrowException);
throwArrayOutOfBounds = CreateNativeFunction(voidTy, { int32Ty, int32Ty }, "__ThrowArrayOutOfBounds", ThrowArrayOutOfBounds);
stringAssignmentOperator = CreateNativeFunction(voidTy, { int8PtrTy, int8PtrTy }, "__StringAssignmentOperator", StringAssignmentOperator);
stringAssignmentOperatorCStr = CreateNativeFunction(voidTy, { int8PtrTy, int8PtrTy }, "__StringAssignmentOperatorCStr", StringAssignmentOperatorCStr);
stringPlusOperator = CreateNativeFunction(voidTy, { int8PtrTy, int8PtrTy, int8PtrTy }, "__StringPlusOperator", StringPlusOperator);
stringCompare = CreateNativeFunction(voidTy, { int8PtrTy, int8PtrTy }, "__StringCompare", StringCompare);
stringCompareNoCase = CreateNativeFunction(voidTy, { int8PtrTy, int8PtrTy }, "__StringCompareNoCase", StringCompareNoCase);
stringLength = CreateNativeFunction(int32Ty, { int8PtrTy }, "__StringLength", StringLength);
readBarrier = CreateNativeFunction(int8PtrTy, { int8PtrTy }, "__ReadBarrier", ReadBarrier);
writeBarrier = CreateNativeFunction(voidTy, { int8PtrTy }, "__WriteBarrier", WriteBarrier);
doubleModF = CreateNativeFunction(doubleTy, { doubleTy, doubleTy }, "__DoubleModF", DoubleModF);
doublePow = CreateNativeFunction(doubleTy, { doubleTy, doubleTy }, "__DoublePow", DoublePow);
doubleAtan2 = CreateNativeFunction(doubleTy, { doubleTy, doubleTy }, "__DoubleAtan2", DoubleAtan2);
doubleFabs = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleFabs", DoubleFabs);
doubleExp = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleExp", DoubleExp);
doubleLog = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleLog", DoubleLog);
doubleLog10 = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleLog10", DoubleLog10);
doubleSqrt = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleSqrt", DoubleSqrt);
doubleCeil = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleCeil", DoubleCeil);
doubleFloor = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleFloor", DoubleFloor);
doubleAcos = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleAcos", DoubleAcos);
doubleAsin = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleAsin", DoubleAsin);
doubleAtan = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleAtan", DoubleAtan);
doubleCos = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleCos", DoubleCos);
doubleSin = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleSin", DoubleSin);
doubleTan = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleTan", DoubleTan);
doubleCosDeg = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleCosDeg", DoubleCosDeg);
doubleSinDeg = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleSinDeg", DoubleSinDeg);
doubleCosh = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleCosh", DoubleCosh);
doubleSinh = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleSinh", DoubleSinh);
doubleTanh = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleTanh", DoubleTanh);
doubleRound = CreateNativeFunction(doubleTy, { doubleTy }, "__DoubleRound", DoubleRound);
castI2S = CreateNativeFunction(voidTy, { int8PtrTy, int32Ty }, "__CastI2S", CastI2S);
castU2S = CreateNativeFunction(voidTy, { int8PtrTy, int32Ty }, "__CastU2S", CastU2S);
castF2S = CreateNativeFunction(voidTy, { int8PtrTy, doubleTy }, "__CastF2S", CastF2S);
castV22S = CreateNativeFunction(voidTy, { int8PtrTy, doubleTy, doubleTy }, "__CastV22S", CastV22S);
castV32S = CreateNativeFunction(voidTy, { int8PtrTy, doubleTy, doubleTy, doubleTy }, "__CastV32S", CastV32S);
castP2S = CreateNativeFunction(voidTy, { int8PtrTy, int8PtrTy }, "__CastP2S", CastP2S);
castS2I = CreateNativeFunction(int32Ty, { int8PtrTy }, "__CastS2I", CastS2I);
castS2F = CreateNativeFunction(doubleTy, { int8PtrTy }, "__CastS2F", CastS2F);
castS2N = CreateNativeFunction(int32Ty, { int8PtrTy }, "__CastS2N", CastS2N);
castN2S = CreateNativeFunction(voidTy, { int8PtrTy, int32Ty }, "__CastN2S", CastN2S);
castS2Co = CreateNativeFunction(int32Ty, { int8PtrTy }, "__CastS2Co", CastS2Co);
castCo2S = CreateNativeFunction(voidTy, { int8PtrTy, int32Ty }, "__CastCo2S", CastCo2S);
castS2So = CreateNativeFunction(int32Ty, { int8PtrTy }, "__CastS2So", CastS2So);
castSo2S = CreateNativeFunction(voidTy, { int8PtrTy, int32Ty }, "__CastSo2S", CastSo2S);
castSID2S = CreateNativeFunction(voidTy, { int8PtrTy, int32Ty }, "__CastSID2S", CastSID2S);
castTID2S = CreateNativeFunction(voidTy, { int8PtrTy, int32Ty }, "__CastTID2S", CastTID2S);
castB_S = CreateNativeFunction(int32Ty, { int8PtrTy }, "__CastB_S", CastB_S);
dynCast = CreateNativeFunction(int8PtrTy, { int8PtrTy, int8PtrTy }, "__DynCast", DynCast);
dynCastC = CreateNativeFunction(int8PtrTy, { int8PtrTy, int8PtrTy }, "__DynCastC", DynCastC);
}
IRFunction* JitCompiler::CreateNativeFunction(IRType* returnType, std::vector<IRType*> args, const char* name, void* ptr)
{
IRFunctionType* functype = ircontext->getFunctionType(returnType, args);
IRFunction* func = ircontext->createFunction(functype, name);
ircontext->addGlobalMapping(func, ptr);
return func;
}

View file

@ -85,7 +85,8 @@ void JitCompiler::EmitVMCall(IRValue* vmfunc, VMFunction* target)
IRValue* paramsptr = OffsetPtr(vmframe, offsetParams);
IRValue* scriptcall = Load(ToInt8PtrPtr(vmfunc, myoffsetof(VMScriptFunction, ScriptCall)));
IRInst* call = cc.CreateCall(cc.CreateBitCast(scriptcall, GetFunctionType5<int, VMFunction*, VMValue*, int, VMReturn*, int>()), { vmfunc, paramsptr, ConstValueD(B), GetCallReturns(), ConstValueD(C) });
IRFunctionType* functype = ircontext->getFunctionType(int32Ty, { int8PtrTy, int8PtrTy, int32Ty, int8PtrTy, int32Ty });
IRInst* call = cc.CreateCall(cc.CreateBitCast(scriptcall, functype), { vmfunc, paramsptr, ConstValueD(B), GetCallReturns(), ConstValueD(C) });
call->comment = std::string("call ") + (target ? target->PrintableName.GetChars() : "VMCall");
LoadInOuts();
@ -518,7 +519,7 @@ IRFunctionType* JitCompiler::GetFuncSignature()
{
if (ParamOpcodes[i]->op == OP_PARAMI)
{
args.push_back(ircontext->getInt32Ty());
args.push_back(int32Ty);
}
else // OP_PARAM
{
@ -532,28 +533,28 @@ IRFunctionType* JitCompiler::GetFuncSignature()
case REGT_INT | REGT_ADDROF:
case REGT_POINTER | REGT_ADDROF:
case REGT_FLOAT | REGT_ADDROF:
args.push_back(ircontext->getInt8PtrTy());
args.push_back(int8PtrTy);
break;
case REGT_INT:
case REGT_INT | REGT_KONST:
args.push_back(ircontext->getInt32Ty());
args.push_back(int32Ty);
break;
case REGT_STRING:
case REGT_STRING | REGT_KONST:
args.push_back(ircontext->getInt8PtrTy());
args.push_back(int8PtrTy);
break;
case REGT_FLOAT:
case REGT_FLOAT | REGT_KONST:
args.push_back(ircontext->getDoublePtrTy());
args.push_back(doublePtrTy);
break;
case REGT_FLOAT | REGT_MULTIREG2:
args.push_back(ircontext->getDoublePtrTy());
args.push_back(ircontext->getDoublePtrTy());
args.push_back(doublePtrTy);
args.push_back(doublePtrTy);
break;
case REGT_FLOAT | REGT_MULTIREG3:
args.push_back(ircontext->getDoublePtrTy());
args.push_back(ircontext->getDoublePtrTy());
args.push_back(ircontext->getDoublePtrTy());
args.push_back(doublePtrTy);
args.push_back(doublePtrTy);
args.push_back(doublePtrTy);
break;
default:
@ -566,7 +567,7 @@ IRFunctionType* JitCompiler::GetFuncSignature()
const VMOP *retval = pc + 1;
int numret = C;
IRType* rettype = ircontext->getVoidTy();
IRType* rettype = voidTy;
// Check if first return value can be placed in the function's real return value slot
int startret = 1;
@ -581,13 +582,13 @@ IRFunctionType* JitCompiler::GetFuncSignature()
switch (type)
{
case REGT_INT:
rettype = ircontext->getInt32Ty();
rettype = int32Ty;
break;
case REGT_FLOAT:
rettype = ircontext->getDoublePtrTy();
rettype = doublePtrTy;
break;
case REGT_POINTER:
rettype = ircontext->getInt8PtrTy();
rettype = int8PtrTy;
break;
case REGT_STRING:
default:
@ -604,7 +605,7 @@ IRFunctionType* JitCompiler::GetFuncSignature()
I_Error("Expected OP_RESULT to follow OP_CALL\n");
}
args.push_back(ircontext->getInt8PtrTy());
args.push_back(int8PtrTy);
}
return ircontext->getFunctionType(rettype, args);

View file

@ -50,23 +50,13 @@ void JitCompiler::EmitIJMP()
EmitThrowException(X_OTHER);
}
static void ValidateCall(DObject *o, VMFunction *f, int b)
{
FScopeBarrier::ValidateCall(o->GetClass(), f, b - 1);
}
void JitCompiler::EmitSCOPE()
{
auto continuebb = irfunc->createBasicBlock({});
auto exceptionbb = EmitThrowExceptionLabel(X_READ_NIL);
cc.CreateCondBr(cc.CreateICmpEQ(LoadD(A), ConstValueA(0)), exceptionbb, continuebb);
cc.SetInsertPoint(continuebb);
cc.CreateCall(GetNativeFunc<void, DObject*, VMFunction*, int>("__ValidateCall", ValidateCall), { LoadA(A), ConstA(C), ConstValueD(B) });
}
static void SetString(VMReturn* ret, FString* str)
{
ret->SetString(*str);
cc.CreateCall(validateCall, { LoadA(A), ConstA(C), ConstValueD(B) });
}
void JitCompiler::EmitRET()
@ -139,7 +129,7 @@ void JitCompiler::EmitRET()
break;
case REGT_STRING:
{
cc.CreateCall(GetNativeFunc<void, VMReturn*, FString*>("__SetString", SetString), { location, (regtype & REGT_KONST) ? ConstS(regnum) : LoadS(regnum) });
cc.CreateCall(setReturnString, { location, (regtype & REGT_KONST) ? ConstS(regnum) : LoadS(regnum) });
break;
}
case REGT_POINTER:
@ -218,7 +208,7 @@ void JitCompiler::EmitBOUND()
IRBasicBlock* exceptionbb = irfunc->createBasicBlock({});
cc.CreateCondBr(cc.CreateICmpUGE(LoadD(A), ConstValueD(BC)), exceptionbb, continuebb);
cc.SetInsertPoint(exceptionbb);
cc.CreateCall(GetNativeFunc<void, int, int>("__ThrowArrayOutOfBounds", &JitCompiler::ThrowArrayOutOfBounds), { LoadD(A), ConstValueD(BC) });
cc.CreateCall(throwArrayOutOfBounds, { LoadD(A), ConstValueD(BC) });
exceptionbb->code.front()->lineNumber = sfunc->PCToLine(pc);
cc.CreateBr(continuebb);
cc.SetInsertPoint(continuebb);
@ -230,7 +220,7 @@ void JitCompiler::EmitBOUND_K()
IRBasicBlock* exceptionbb = irfunc->createBasicBlock({});
cc.CreateCondBr(cc.CreateICmpUGE(LoadD(A), ConstD(BC)), exceptionbb, continuebb);
cc.SetInsertPoint(exceptionbb);
cc.CreateCall(GetNativeFunc<void, int, int>("__ThrowArrayOutOfBounds", &JitCompiler::ThrowArrayOutOfBounds), { LoadD(A), ConstD(BC) });
cc.CreateCall(throwArrayOutOfBounds, { LoadD(A), ConstD(BC) });
exceptionbb->code.front()->lineNumber = sfunc->PCToLine(pc);
cc.CreateBr(continuebb);
cc.SetInsertPoint(continuebb);
@ -242,20 +232,8 @@ void JitCompiler::EmitBOUND_R()
IRBasicBlock* exceptionbb = irfunc->createBasicBlock({});
cc.CreateCondBr(cc.CreateICmpUGE(LoadD(A), LoadD(B)), exceptionbb, continuebb);
cc.SetInsertPoint(exceptionbb);
cc.CreateCall(GetNativeFunc<void, int, int>("__ThrowArrayOutOfBounds", &JitCompiler::ThrowArrayOutOfBounds), { LoadD(A), LoadD(BC) });
cc.CreateCall(throwArrayOutOfBounds, { LoadD(A), LoadD(BC) });
exceptionbb->code.front()->lineNumber = sfunc->PCToLine(pc);
cc.CreateBr(continuebb);
cc.SetInsertPoint(continuebb);
}
void JitCompiler::ThrowArrayOutOfBounds(int index, int size)
{
if (index >= size)
{
ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", size, index);
}
else
{
ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Negative current index = %i\n", index);
}
}

View file

@ -21,7 +21,7 @@ void JitCompiler::EmitLKF()
void JitCompiler::EmitLKS()
{
cc.CreateCall(GetNativeFunc<void, FString*, FString*>("__CallAssignString", &JitCompiler::CallAssignString), { LoadS(A), ConstS(BC) });
cc.CreateCall(stringAssignmentOperator, { LoadS(A), ConstS(BC) });
}
void JitCompiler::EmitLKP()
@ -31,25 +31,25 @@ void JitCompiler::EmitLKP()
void JitCompiler::EmitLK_R()
{
IRValue* base = ircontext->getConstantInt(ircontext->getInt32PtrTy(), (uint64_t)&konstd[C]);
IRValue* base = ircontext->getConstantInt(int32PtrTy, (uint64_t)&konstd[C]);
StoreD(Load(OffsetPtr(base, LoadD(B))), A);
}
void JitCompiler::EmitLKF_R()
{
IRValue* base = ircontext->getConstantInt(ircontext->getDoublePtrTy(), (uint64_t)&konstf[C]);
IRValue* base = ircontext->getConstantInt(doublePtrTy, (uint64_t)&konstf[C]);
StoreF(Load(OffsetPtr(base, LoadD(B))), A);
}
void JitCompiler::EmitLKS_R()
{
IRValue* base = ircontext->getConstantInt(ircontext->getInt8PtrTy()->getPointerTo(ircontext), (uint64_t)&konsts[C]);
cc.CreateCall(GetNativeFunc<void, FString*, FString*>("__CallAssignString", &JitCompiler::CallAssignString), { LoadS(A), Load(OffsetPtr(base, LoadD(B))) });
IRValue* base = ircontext->getConstantInt(int8PtrPtrTy, (uint64_t)&konsts[C]);
cc.CreateCall(stringAssignmentOperator, { LoadS(A), Load(OffsetPtr(base, LoadD(B))) });
}
void JitCompiler::EmitLKP_R()
{
IRValue* base = ircontext->getConstantInt(ircontext->getInt8PtrTy()->getPointerTo(ircontext), (uint64_t)&konsta[C]);
IRValue* base = ircontext->getConstantInt(int8PtrPtrTy, (uint64_t)&konsta[C]);
StoreA(Load(OffsetPtr(base, LoadD(B))), A);
}
@ -174,13 +174,13 @@ void JitCompiler::EmitLDP_R()
void JitCompiler::EmitLS()
{
EmitNullPointerThrow(B, X_READ_NIL);
cc.CreateCall(GetNativeFunc<void, FString*, FString*>("__CallAssignString", &JitCompiler::CallAssignString), { LoadS(A), OffsetPtr(LoadA(B), ConstD(C)) });
cc.CreateCall(stringAssignmentOperator, { LoadS(A), OffsetPtr(LoadA(B), ConstD(C)) });
}
void JitCompiler::EmitLS_R()
{
EmitNullPointerThrow(B, X_READ_NIL);
cc.CreateCall(GetNativeFunc<void, FString*, FString*>("__CallAssignString", &JitCompiler::CallAssignString), { LoadS(A), OffsetPtr(LoadA(B), LoadD(C)) });
cc.CreateCall(stringAssignmentOperator, { LoadS(A), OffsetPtr(LoadA(B), LoadD(C)) });
}
#if 0 // Inline read barrier impl
@ -219,21 +219,16 @@ void JitCompiler::EmitLO_R()
#else
static DObject *ReadBarrier(DObject *p)
{
return GC::ReadBarrier(p);
}
void JitCompiler::EmitLO()
{
EmitNullPointerThrow(B, X_READ_NIL);
StoreA(cc.CreateCall(GetNativeFunc<DObject*, DObject*>("__ReadBarrier", ReadBarrier), { OffsetPtr(LoadA(B), ConstD(C)) }), A);
StoreA(cc.CreateCall(readBarrier, { OffsetPtr(LoadA(B), ConstD(C)) }), A);
}
void JitCompiler::EmitLO_R()
{
EmitNullPointerThrow(B, X_READ_NIL);
StoreA(cc.CreateCall(GetNativeFunc<DObject*, DObject*>("__ReadBarrier", ReadBarrier), { OffsetPtr(LoadA(B), LoadD(C)) }), A);
StoreA(cc.CreateCall(readBarrier, { OffsetPtr(LoadA(B), LoadD(C)) }), A);
}
#endif
@ -284,21 +279,16 @@ void JitCompiler::EmitLV3_R()
StoreF(Load(OffsetPtr(base, 2)), A + 2);
}
static void SetString(FString *to, char **from)
{
*to = *from;
}
void JitCompiler::EmitLCS()
{
EmitNullPointerThrow(B, X_READ_NIL);
cc.CreateCall(GetNativeFunc<void, FString*, char**>("__SetString", SetString), { LoadS(A), OffsetPtr(LoadA(B), ConstD(C)) });
cc.CreateCall(stringAssignmentOperatorCStr, { LoadS(A), OffsetPtr(LoadA(B), ConstD(C)) });
}
void JitCompiler::EmitLCS_R()
{
EmitNullPointerThrow(B, X_READ_NIL);
cc.CreateCall(GetNativeFunc<void, FString*, char**>("__SetString", SetString), { LoadS(A), OffsetPtr(LoadA(B), LoadD(C)) });
cc.CreateCall(stringAssignmentOperatorCStr, { LoadS(A), OffsetPtr(LoadA(B), LoadD(C)) });
}
void JitCompiler::EmitLBIT()
@ -307,6 +297,6 @@ void JitCompiler::EmitLBIT()
IRValue* value = Load(LoadA(B));
value = cc.CreateAnd(value, ircontext->getConstantInt(C));
value = cc.CreateICmpNE(value, ircontext->getConstantInt(0));
value = cc.CreateZExt(value, ircontext->getInt32Ty());
value = cc.CreateZExt(value, int32Ty);
StoreD(value, A);
}

View file

@ -5,34 +5,14 @@
/////////////////////////////////////////////////////////////////////////////
// String instructions.
static void ConcatString(FString* to, FString* first, FString* second)
{
*to = *first + *second;
}
void JitCompiler::EmitCONCAT()
{
cc.CreateCall(GetNativeFunc<void, FString*, FString*, FString*>("__ConcatString", ConcatString), { LoadS(A), LoadS(B), LoadS(C) });
}
static int StringLength(FString* str)
{
return static_cast<int>(str->Len());
cc.CreateCall(stringPlusOperator, { LoadS(A), LoadS(B), LoadS(C) });
}
void JitCompiler::EmitLENS()
{
StoreD(cc.CreateCall(GetNativeFunc<int, FString*>("__StringLength", StringLength), { LoadS(B) }), A);
}
static int StringCompareNoCase(FString* first, FString* second)
{
return first->CompareNoCase(*second);
}
static int StringCompare(FString* first, FString* second)
{
return first->Compare(*second);
StoreD(cc.CreateCall(stringLength, { LoadS(B) }), A);
}
void JitCompiler::EmitCMPS()
@ -42,12 +22,7 @@ void JitCompiler::EmitCMPS()
IRValue* arg0 = static_cast<bool>(A & CMP_BK) ? ConstS(B) : LoadS(B);
IRValue* arg1 = static_cast<bool>(A & CMP_CK) ? ConstS(C) : LoadS(C);
IRValue* result;
if (static_cast<bool>(A & CMP_APPROX))
result = cc.CreateCall(GetNativeFunc<int, FString*, FString*>("__StringCompareNoCase", StringCompareNoCase), { arg0, arg1 });
else
result = cc.CreateCall(GetNativeFunc<int, FString*, FString*>("__StringCompare", StringCompare), { arg0, arg1 });
IRValue* result = cc.CreateCall(static_cast<bool>(A & CMP_APPROX) ? stringCompareNoCase : stringCompare, { arg0, arg1 });
IRValue* zero = ConstValueD(0);
int method = A & CMP_METHOD_MASK;
@ -686,18 +661,13 @@ void JitCompiler::EmitDIVF_KR()
StoreF(cc.CreateFDiv(ConstF(B), LoadF(C)), A);
}
static double DoubleModF(double a, double b)
{
return a - floor(a / b) * b;
}
void JitCompiler::EmitMODF_RR()
{
IRBasicBlock* exceptionbb = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO);
IRBasicBlock* continuebb = irfunc->createBasicBlock({});
cc.CreateCondBr(cc.CreateFCmpUEQ(LoadF(C), ConstValueF(0.0)), exceptionbb, continuebb);
cc.SetInsertPoint(continuebb);
StoreF(cc.CreateCall(GetNativeFunc<double, double, double>("__DoubleModF", DoubleModF), { LoadF(B), LoadF(C) }), A);
StoreF(cc.CreateCall(doubleModF, { LoadF(B), LoadF(C) }), A);
}
void JitCompiler::EmitMODF_RK()
@ -708,7 +678,7 @@ void JitCompiler::EmitMODF_RK()
}
else
{
StoreF(cc.CreateCall(GetNativeFunc<double, double, double>("__DoubleModF", DoubleModF), { LoadF(B), ConstF(C) }), A);
StoreF(cc.CreateCall(doubleModF, { LoadF(B), ConstF(C) }), A);
}
}
@ -718,22 +688,22 @@ void JitCompiler::EmitMODF_KR()
IRBasicBlock* continuebb = irfunc->createBasicBlock({});
cc.CreateCondBr(cc.CreateFCmpUEQ(LoadF(C), ConstValueF(0.0)), exceptionbb, continuebb);
cc.SetInsertPoint(continuebb);
StoreF(cc.CreateCall(GetNativeFunc<double, double, double>("__DoubleModF", DoubleModF), { ConstF(B), LoadF(C) }), A);
StoreF(cc.CreateCall(doubleModF, { ConstF(B), LoadF(C) }), A);
}
void JitCompiler::EmitPOWF_RR()
{
StoreF(cc.CreateCall(GetNativeFunc<double, double, double>("__g_pow", g_pow), { LoadF(B), LoadF(C) }), A);
StoreF(cc.CreateCall(doublePow, { LoadF(B), LoadF(C) }), A);
}
void JitCompiler::EmitPOWF_RK()
{
StoreF(cc.CreateCall(GetNativeFunc<double, double, double>("__g_pow", g_pow), { LoadF(B), ConstF(C) }), A);
StoreF(cc.CreateCall(doublePow, { LoadF(B), ConstF(C) }), A);
}
void JitCompiler::EmitPOWF_KR()
{
StoreF(cc.CreateCall(GetNativeFunc<double, double, double>("__g_pow", g_pow), { ConstF(B), LoadF(C) }), A);
StoreF(cc.CreateCall(doublePow, { ConstF(B), LoadF(C) }), A);
}
void JitCompiler::EmitMINF_RR()
@ -814,7 +784,7 @@ void JitCompiler::EmitMAXF_RK()
void JitCompiler::EmitATAN2()
{
StoreF(cc.CreateFMul(cc.CreateCall(GetNativeFunc<double, double, double>("__g_atan2", g_atan2), { LoadF(B), LoadF(C) }), ConstValueF(180 / M_PI)), A);
StoreF(cc.CreateFMul(cc.CreateCall(doubleAtan2, { LoadF(B), LoadF(C) }), ConstValueF(180 / M_PI)), A);
}
void JitCompiler::EmitFLOP()
@ -832,38 +802,36 @@ void JitCompiler::EmitFLOP()
v = cc.CreateFMul(v, ConstValueF(M_PI / 180));
}
typedef double(*FuncPtr)(double);
const char* funcname = "";
FuncPtr func = nullptr;
IRFunction* func = nullptr;
switch (C)
{
default: I_Error("Unknown OP_FLOP subfunction");
case FLOP_ABS: func = fabs; funcname = "__fabs"; break;
case FLOP_EXP: func = g_exp; funcname = "__g_exp"; break;
case FLOP_LOG: func = g_log; funcname = "__g_log"; break;
case FLOP_LOG10: func = g_log10; funcname = "__g_log10"; break;
case FLOP_SQRT: func = g_sqrt; funcname = "__g_sqrt"; break;
case FLOP_CEIL: func = ceil; funcname = "__ceil"; break;
case FLOP_FLOOR: func = floor; funcname = "__floor"; break;
case FLOP_ACOS: func = g_acos; funcname = "__g_acos"; break;
case FLOP_ASIN: func = g_asin; funcname = "__g_asin"; break;
case FLOP_ATAN: func = g_atan; funcname = "__g_atan"; break;
case FLOP_COS: func = g_cos; funcname = "__g_cos"; break;
case FLOP_SIN: func = g_sin; funcname = "__g_sin"; break;
case FLOP_TAN: func = g_tan; funcname = "__g_tan"; break;
case FLOP_ACOS_DEG: func = g_acos; funcname = "__g_acos"; break;
case FLOP_ASIN_DEG: func = g_asin; funcname = "__g_asin"; break;
case FLOP_ATAN_DEG: func = g_atan; funcname = "__g_atan"; break;
case FLOP_COS_DEG: func = g_cosdeg; funcname = "__g_cosdeg"; break;
case FLOP_SIN_DEG: func = g_sindeg; funcname = "__g_sindeg"; break;
case FLOP_TAN_DEG: func = g_tan; funcname = "__g_tan"; break;
case FLOP_COSH: func = g_cosh; funcname = "__g_cosh"; break;
case FLOP_SINH: func = g_sinh; funcname = "__g_sinh"; break;
case FLOP_TANH: func = g_tanh; funcname = "__g_tanh"; break;
case FLOP_ROUND: func = round; funcname = "__round"; break;
case FLOP_ABS: func = doubleFabs; break;
case FLOP_EXP: func = doubleExp; break;
case FLOP_LOG: func = doubleLog; break;
case FLOP_LOG10: func = doubleLog10; break;
case FLOP_SQRT: func = doubleSqrt; break;
case FLOP_CEIL: func = doubleCeil; break;
case FLOP_FLOOR: func = doubleFloor; break;
case FLOP_ACOS: func = doubleAcos; break;
case FLOP_ASIN: func = doubleAsin; break;
case FLOP_ATAN: func = doubleAtan; break;
case FLOP_COS: func = doubleCos; break;
case FLOP_SIN: func = doubleSin; break;
case FLOP_TAN: func = doubleTan; break;
case FLOP_ACOS_DEG: func = doubleAcos; break;
case FLOP_ASIN_DEG: func = doubleAsin; break;
case FLOP_ATAN_DEG: func = doubleAtan; break;
case FLOP_COS_DEG: func = doubleCosDeg; break;
case FLOP_SIN_DEG: func = doubleSinDeg; break;
case FLOP_TAN_DEG: func = doubleTan; break;
case FLOP_COSH: func = doubleCosh; break;
case FLOP_SINH: func = doubleSinh; break;
case FLOP_TANH: func = doubleTanh; break;
case FLOP_ROUND: func = doubleRound; break;
}
IRValue* result = cc.CreateCall(GetNativeFunc<double, double>(funcname, func), { v });
IRValue* result = cc.CreateCall(func, { v });
if (C == FLOP_ACOS_DEG || C == FLOP_ASIN_DEG || C == FLOP_ATAN_DEG)
{
@ -1066,7 +1034,7 @@ void JitCompiler::EmitLENV2()
IRValue* x = LoadF(B);
IRValue* y = LoadF(B + 1);
IRValue* dotproduct = cc.CreateFAdd(cc.CreateFMul(x, x), cc.CreateFMul(y, y));
IRValue* len = cc.CreateCall(GetNativeFunc<double, double>("__g_sqrt", g_sqrt), { dotproduct });
IRValue* len = cc.CreateCall(doubleSqrt, { dotproduct });
StoreF(len, A);
}
@ -1168,7 +1136,7 @@ void JitCompiler::EmitLENV3()
IRValue* y = LoadF(B + 1);
IRValue* z = LoadF(B + 2);
IRValue* dotproduct = cc.CreateFAdd(cc.CreateFAdd(cc.CreateFMul(x, x), cc.CreateFMul(y, y)), cc.CreateFMul(z, z));
IRValue* len = cc.CreateCall(GetNativeFunc<double, double>("__g_sqrt", g_sqrt), { dotproduct });
IRValue* len = cc.CreateCall(doubleSqrt, { dotproduct });
StoreF(len, A);
}

View file

@ -1,9 +1,5 @@
#include "jitintern.h"
#include "v_video.h"
#include "s_soundinternal.h"
#include "texturemanager.h"
#include "palutil.h"
void JitCompiler::EmitMOVE()
{
@ -16,7 +12,7 @@ void JitCompiler::EmitMOVEF()
void JitCompiler::EmitMOVES()
{
cc.CreateCall(GetNativeFunc<void, FString*, FString*>("__CallAssignString", &JitCompiler::CallAssignString), { LoadS(A), LoadS(B) });
cc.CreateCall(stringAssignmentOperator, { LoadS(A), LoadS(B) });
}
void JitCompiler::EmitMOVEA()
@ -37,140 +33,111 @@ void JitCompiler::EmitMOVEV3()
StoreF(LoadF(B + 2), A + 2);
}
static void CastI2S(FString *a, int b) { a->Format("%d", b); }
static void CastU2S(FString *a, int b) { a->Format("%u", b); }
static void CastF2S(FString *a, double b) { a->Format("%.5f", b); }
static void CastV22S(FString *a, double b, double b1) { a->Format("(%.5f, %.5f)", b, b1); }
static void CastV32S(FString *a, double b, double b1, double b2) { a->Format("(%.5f, %.5f, %.5f)", b, b1, b2); }
static void CastP2S(FString *a, void *b) { if (b == nullptr) *a = "null"; else a->Format("%p", b); }
static int CastS2I(FString *b) { return (int)b->ToLong(); }
static double CastS2F(FString *b) { return b->ToDouble(); }
static int CastS2N(FString *b) { return b->Len() == 0 ? NAME_None : FName(*b).GetIndex(); }
static void CastN2S(FString *a, int b) { FName name = FName(ENamedName(b)); *a = name.IsValidName() ? name.GetChars() : ""; }
static int CastS2Co(FString *b) { return V_GetColor(nullptr, *b); }
static void CastCo2S(FString *a, int b) { PalEntry c(b); a->Format("%02x %02x %02x", c.r, c.g, c.b); }
static int CastS2So(FString *b) { return FSoundID(*b); }
static void CastSo2S(FString* a, int b) { *a = soundEngine->GetSoundName(b); }
static void CastSID2S(FString* a, unsigned int b) { VM_CastSpriteIDToString(a, b); }
static void CastTID2S(FString *a, int b) { auto tex = TexMan.GetGameTexture(*(FTextureID*)&b); *a = (tex == nullptr) ? "(null)" : tex->GetName().GetChars(); }
void JitCompiler::EmitCAST()
{
switch (C)
{
case CAST_I2F:
StoreF(cc.CreateSIToFP(LoadD(B), ircontext->getDoubleTy()), A);
StoreF(cc.CreateSIToFP(LoadD(B), doubleTy), A);
break;
case CAST_U2F:
StoreF(cc.CreateUIToFP(LoadD(B), ircontext->getDoubleTy()), A);
StoreF(cc.CreateUIToFP(LoadD(B), doubleTy), A);
break;
case CAST_F2I:
StoreD(cc.CreateFPToSI(LoadF(B), ircontext->getInt32Ty()), A);
StoreD(cc.CreateFPToSI(LoadF(B), int32Ty), A);
break;
case CAST_F2U:
StoreD(cc.CreateFPToUI(LoadF(B), ircontext->getInt32Ty()), A);
StoreD(cc.CreateFPToUI(LoadF(B), int32Ty), A);
break;
case CAST_I2S:
cc.CreateCall(GetNativeFunc<void, FString*, int>("__CastI2S", CastI2S), { LoadS(A), LoadD(B) });
cc.CreateCall(castI2S, { LoadS(A), LoadD(B) });
break;
case CAST_U2S:
cc.CreateCall(GetNativeFunc<void, FString*, int>("__CastU2S", CastU2S), { LoadS(A), LoadD(B) });
cc.CreateCall(castU2S, { LoadS(A), LoadD(B) });
break;
case CAST_F2S:
cc.CreateCall(GetNativeFunc<void, FString*, double>("__CastF2S", CastF2S), { LoadS(A), LoadF(B) });
cc.CreateCall(castF2S, { LoadS(A), LoadF(B) });
break;
case CAST_V22S:
cc.CreateCall(GetNativeFunc<void, FString*, double, double>("__CastV22S", CastV22S), { LoadS(A), LoadF(B), LoadF(B + 1) });
cc.CreateCall(castV22S, { LoadS(A), LoadF(B), LoadF(B + 1) });
break;
case CAST_V32S:
cc.CreateCall(GetNativeFunc<void, FString*, double, double, double>("__CastV32S", CastV32S), { LoadS(A), LoadF(B), LoadF(B + 1), LoadF(B + 2) });
cc.CreateCall(castV32S, { LoadS(A), LoadF(B), LoadF(B + 1), LoadF(B + 2) });
break;
case CAST_P2S:
cc.CreateCall(GetNativeFunc<void, FString*, void*>("__CastP2S", CastP2S), { LoadS(A), LoadA(B) });
cc.CreateCall(castP2S, { LoadS(A), LoadA(B) });
break;
case CAST_S2I:
StoreD(cc.CreateCall(GetNativeFunc<int, FString*>("__CastS2I", CastS2I), { LoadS(B) }), A);
StoreD(cc.CreateCall(castS2I, { LoadS(B) }), A);
break;
case CAST_S2F:
StoreF(cc.CreateCall(GetNativeFunc<double, FString*>("__CastS2F", CastS2F), { LoadS(B) }), A);
StoreF(cc.CreateCall(castS2F, { LoadS(B) }), A);
break;
case CAST_S2N:
StoreD(cc.CreateCall(GetNativeFunc<int, FString*>("__CastS2N", CastS2N), { LoadS(B) }), A);
StoreD(cc.CreateCall(castS2N, { LoadS(B) }), A);
break;
case CAST_N2S:
cc.CreateCall(GetNativeFunc<void, FString*, int>("__CastN2S", CastN2S), { LoadS(A), LoadD(B) });
cc.CreateCall(castN2S, { LoadS(A), LoadD(B) });
break;
case CAST_S2Co:
StoreD(cc.CreateCall(GetNativeFunc<int, FString*>("__CastS2Co", CastS2Co), { LoadS(B) }), A);
StoreD(cc.CreateCall(castS2Co, { LoadS(B) }), A);
break;
case CAST_Co2S:
cc.CreateCall(GetNativeFunc<void, FString*, int>("__CastCo2S", CastCo2S), { LoadS(A), LoadD(B) });
cc.CreateCall(castCo2S, { LoadS(A), LoadD(B) });
break;
case CAST_S2So:
StoreD(cc.CreateCall(GetNativeFunc<int, FString*>("__CastS2So", CastS2So), { LoadS(B) }), A);
StoreD(cc.CreateCall(castS2So, { LoadS(B) }), A);
break;
case CAST_So2S:
cc.CreateCall(GetNativeFunc<void, FString*, int>("__CastSo2S", CastSo2S), { LoadS(A), LoadD(B) });
cc.CreateCall(castSo2S, { LoadS(A), LoadD(B) });
break;
case CAST_SID2S:
cc.CreateCall(GetNativeFunc<void, FString*, unsigned int>("__CastSID2S", CastSID2S), { LoadS(A), LoadD(B) });
cc.CreateCall(castSID2S, { LoadS(A), LoadD(B) });
break;
case CAST_TID2S:
cc.CreateCall(GetNativeFunc<void, FString*, int>("__CastTID2S", CastTID2S), { LoadS(A), LoadD(B) });
cc.CreateCall(castTID2S, { LoadS(A), LoadD(B) });
break;
default:
I_Error("Unknown OP_CAST type\n");
}
}
static int CastB_S(FString *s) { return s->Len() > 0; }
void JitCompiler::EmitCASTB()
{
if (C == CASTB_I)
{
StoreD(cc.CreateZExt(cc.CreateICmpNE(LoadD(B), ConstValueD(0)), ircontext->getInt32Ty()), A);
StoreD(cc.CreateZExt(cc.CreateICmpNE(LoadD(B), ConstValueD(0)), int32Ty), A);
}
else if (C == CASTB_F)
{
StoreD(cc.CreateZExt(cc.CreateFCmpUNE(LoadF(B), ConstValueF(0.0)), ircontext->getInt32Ty()), A);
StoreD(cc.CreateZExt(cc.CreateFCmpUNE(LoadF(B), ConstValueF(0.0)), int32Ty), A);
}
else if (C == CASTB_A)
{
StoreD(cc.CreateZExt(cc.CreateICmpNE(LoadA(B), ConstValueA(0)), ircontext->getInt32Ty()), A);
StoreD(cc.CreateZExt(cc.CreateICmpNE(LoadA(B), ConstValueA(0)), int32Ty), A);
}
else
{
StoreD(cc.CreateCall(GetNativeFunc<int, FString* >("__CastB_S", CastB_S), { LoadS(B) }), A);
StoreD(cc.CreateCall(castB_S, { LoadS(B) }), A);
}
}
static DObject *DynCast(DObject *obj, PClass *cls)
{
return (obj && obj->IsKindOf(cls)) ? obj : nullptr;
}
void JitCompiler::EmitDYNCAST_R()
{
StoreA(cc.CreateCall(GetNativeFunc<DObject*, DObject*, PClass*>("__DynCast", DynCast), { LoadA(B), LoadA(C) }), A);
StoreA(cc.CreateCall(dynCast, { LoadA(B), LoadA(C) }), A);
}
void JitCompiler::EmitDYNCAST_K()
{
StoreA(cc.CreateCall(GetNativeFunc<DObject*, DObject*, PClass*>("__DynCast", DynCast), { LoadA(B), ConstA(C) }), A);
}
static PClass *DynCastC(PClass *cls1, PClass *cls2)
{
return (cls1 && cls1->IsDescendantOf(cls2)) ? cls1 : nullptr;
StoreA(cc.CreateCall(dynCast, { LoadA(B), ConstA(C) }), A);
}
void JitCompiler::EmitDYNCASTC_R()
{
StoreA(cc.CreateCall(GetNativeFunc<PClass*, PClass*, PClass*>("__DynCastC", DynCastC), { LoadA(B), LoadA(C) }), A);
StoreA(cc.CreateCall(dynCastC, { LoadA(B), LoadA(C) }), A);
}
void JitCompiler::EmitDYNCASTC_K()
{
StoreA(cc.CreateCall(GetNativeFunc<PClass*, PClass*, PClass*>("__DynCastC", DynCastC), { LoadA(B), ConstA(C) }), A);
StoreA(cc.CreateCall(dynCastC, { LoadA(B), ConstA(C) }), A);
}

View file

@ -64,27 +64,25 @@ void JitCompiler::EmitSDP_R()
void JitCompiler::EmitSS()
{
EmitNullPointerThrow(A, X_WRITE_NIL);
cc.CreateCall(GetNativeFunc<void, FString*, FString*>("__CallAssignString", &JitCompiler::CallAssignString), { OffsetPtr(LoadA(A), ConstD(C)), LoadS(B) });
cc.CreateCall(stringAssignmentOperator, { OffsetPtr(LoadA(A), ConstD(C)), LoadS(B) });
}
void JitCompiler::EmitSS_R()
{
EmitNullPointerThrow(A, X_WRITE_NIL);
cc.CreateCall(GetNativeFunc<void, FString*, FString*>("__CallAssignString", &JitCompiler::CallAssignString), { OffsetPtr(LoadA(A), LoadD(C)), LoadS(B) });
cc.CreateCall(stringAssignmentOperator, { OffsetPtr(LoadA(A), LoadD(C)), LoadS(B) });
}
void JitCompiler::EmitSO()
{
EmitNullPointerThrow(A, X_WRITE_NIL);
typedef void(*FuncPtr)(DObject*);
cc.CreateCall(GetNativeFunc<void, DObject*>("__WriteBarrier", static_cast<FuncPtr>(GC::WriteBarrier)), { OffsetPtr(LoadA(A), ConstD(C)), LoadA(B) });
cc.CreateCall(writeBarrier, { OffsetPtr(LoadA(A), ConstD(C)), LoadA(B) });
}
void JitCompiler::EmitSO_R()
{
EmitNullPointerThrow(A, X_WRITE_NIL);
typedef void(*FuncPtr)(DObject*);
cc.CreateCall(GetNativeFunc<void, DObject*>("__WriteBarrier", static_cast<FuncPtr>(GC::WriteBarrier)), { OffsetPtr(LoadA(A), LoadD(C)), LoadA(B) });
cc.CreateCall(writeBarrier, { OffsetPtr(LoadA(A), LoadD(C)), LoadA(B) });
}
void JitCompiler::EmitSP()

View file

@ -34,8 +34,6 @@ public:
IRFunction* Codegen();
// VMScriptFunction* GetScriptFunction() { return sfunc; }
private:
// Declare EmitXX functions for the opcodes:
#define xx(op, name, mode, alt, kreg, ktype) void Emit##op();
@ -59,9 +57,6 @@ private:
void EmitThrowException(EVMAbortException reason);
IRBasicBlock* EmitThrowExceptionLabel(EVMAbortException reason);
static void ThrowArrayOutOfBounds(int index, int size);
static void ThrowException(int reason);
void Setup();
void CreateRegisters();
void IncrementVMCalls();
@ -76,77 +71,9 @@ private:
IRFunctionType* GetFuncSignature();
template<typename T> IRType* GetIRType() { static_assert(std::is_pointer<T>::value, "Unsupported type"); return ircontext->getInt8PtrTy(); }
template<> IRType* GetIRType<void>() { return ircontext->getVoidTy(); }
template<> IRType* GetIRType<char>() { return ircontext->getInt8Ty(); }
template<> IRType* GetIRType<unsigned char>() { return ircontext->getInt8Ty(); }
template<> IRType* GetIRType<short>() { return ircontext->getInt16Ty(); }
template<> IRType* GetIRType<unsigned short>() { return ircontext->getInt16Ty(); }
template<> IRType* GetIRType<int>() { return ircontext->getInt32Ty(); }
template<> IRType* GetIRType<unsigned int>() { return ircontext->getInt32Ty(); }
template<> IRType* GetIRType<long long>() { return ircontext->getInt64Ty(); }
template<> IRType* GetIRType<unsigned long long>() { return ircontext->getInt64Ty(); }
template<> IRType* GetIRType<float>() { return ircontext->getFloatTy(); }
template<> IRType* GetIRType<double>() { return ircontext->getDoubleTy(); }
template<typename RetType>
IRFunctionType* GetFunctionType0() { return ircontext->getFunctionType(GetIRType<RetType>(), { }); }
template<typename RetType, typename P1>
IRFunctionType* GetFunctionType1() { return ircontext->getFunctionType(GetIRType<RetType>(), { GetIRType<P1>() }); }
template<typename RetType, typename P1, typename P2>
IRFunctionType* GetFunctionType2() { return ircontext->getFunctionType(GetIRType<RetType>(), { GetIRType<P1>(), GetIRType<P2>() }); }
template<typename RetType, typename P1, typename P2, typename P3>
IRFunctionType* GetFunctionType3() { return ircontext->getFunctionType(GetIRType<RetType>(), { GetIRType<P1>(), GetIRType<P2>(), GetIRType<P3>() }); }
template<typename RetType, typename P1, typename P2, typename P3, typename P4>
IRFunctionType* GetFunctionType4() { return ircontext->getFunctionType(GetIRType<RetType>(), { GetIRType<P1>(), GetIRType<P2>(), GetIRType<P3>(), GetIRType<P4>() }); }
template<typename RetType, typename P1, typename P2, typename P3, typename P4, typename P5>
IRFunctionType* GetFunctionType5() { return ircontext->getFunctionType(GetIRType<RetType>(), { GetIRType<P1>(), GetIRType<P2>(), GetIRType<P3>(), GetIRType<P4>(), GetIRType<P5>() }); }
template<typename RetType, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
IRFunctionType* GetFunctionType6() { return ircontext->getFunctionType(GetIRType<RetType>(), { GetIRType<P1>(), GetIRType<P2>(), GetIRType<P3>(), GetIRType<P4>(), GetIRType<P5>(), GetIRType<P6>() }); }
template<typename RetType, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
IRFunctionType* GetFunctionType7() { return ircontext->getFunctionType(GetIRType<RetType>(), { GetIRType<P1>(), GetIRType<P2>(), GetIRType<P3>(), GetIRType<P4>(), GetIRType<P5>(), GetIRType<P6>(), GetIRType<P7>() }); }
IRFunction* GetNativeFunc(const char* name, void* ptr, IRFunctionType* functype)
{
IRFunction* func = ircontext->getFunction(name);
if (!func)
{
func = ircontext->createFunction(functype, name);
ircontext->addGlobalMapping(func, ptr);
}
return func;
}
template<typename RetType>
IRFunction* GetNativeFunc(const char* name, RetType(*func)()) { return GetNativeFunc(name, func, GetFunctionType0<RetType>()); }
template<typename RetType, typename P1>
IRFunction* GetNativeFunc(const char* name, RetType(*func)(P1 p1)) { return GetNativeFunc(name, func, GetFunctionType1<RetType, P1>()); }
template<typename RetType, typename P1, typename P2>
IRFunction* GetNativeFunc(const char* name, RetType(*func)(P1 p1, P2 p2)) { return GetNativeFunc(name, func, GetFunctionType2<RetType, P1, P2>()); }
template<typename RetType, typename P1, typename P2, typename P3>
IRFunction* GetNativeFunc(const char* name, RetType(*func)(P1 p1, P2 p2, P3 p3)) { return GetNativeFunc(name, func, GetFunctionType3<RetType, P1, P2, P3>()); }
template<typename RetType, typename P1, typename P2, typename P3, typename P4>
IRFunction* GetNativeFunc(const char* name, RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4)) { return GetNativeFunc(name, func, GetFunctionType4<RetType, P1, P2, P3, P4>()); }
template<typename RetType, typename P1, typename P2, typename P3, typename P4, typename P5>
IRFunction* GetNativeFunc(const char* name, RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)) { return GetNativeFunc(name, func, GetFunctionType5<RetType, P1, P2, P3, P4, P5>()); }
template<typename RetType, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
IRFunction* GetNativeFunc(const char* name, RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)) { return GetNativeFunc(name, func, GetFunctionType6<RetType, P1, P2, P3, P4, P5, P6>()); }
template<typename RetType, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
IRFunction* GetNativeFunc(const char* name, RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)) { return GetNativeFunc(name, func, GetFunctionType7<RetType, P1, P2, P3, P4, P5, P6, P7>()); }
void GetTypes();
void CreateNativeFunctions();
IRFunction* CreateNativeFunction(IRType* returnType, std::vector<IRType*> args, const char* name, void* ptr);
template <typename Func>
void EmitComparisonOpcode(Func jmpFunc)
@ -167,13 +94,13 @@ private:
IRValue* LoadA(int index) { return cc.CreateLoad(regA[index]); }
IRValue* LoadS(int index) { return cc.CreateLoad(regS[index]); }
IRValue* ConstD(int index) { return ircontext->getConstantInt(konstd[index]); }
IRValue* ConstF(int index) { return ircontext->getConstantFloat(ircontext->getDoubleTy(), konstf[index]); }
IRValue* ConstA(int index) { return ircontext->getConstantInt(ircontext->getInt8PtrTy(), (uint64_t)konsta[index].v); }
IRValue* ConstS(int index) { return ircontext->getConstantInt(ircontext->getInt8PtrTy(), (uint64_t)&konsts[index]); }
IRValue* ConstF(int index) { return ircontext->getConstantFloat(doubleTy, konstf[index]); }
IRValue* ConstA(int index) { return ircontext->getConstantInt(int8PtrTy, (uint64_t)konsta[index].v); }
IRValue* ConstS(int index) { return ircontext->getConstantInt(int8PtrTy, (uint64_t)&konsts[index]); }
IRValue* ConstValueD(int value) { return ircontext->getConstantInt(value); }
IRValue* ConstValueF(double value) { return ircontext->getConstantFloat(ircontext->getDoubleTy(), value); }
IRValue* ConstValueA(void* value) { return ircontext->getConstantInt(ircontext->getInt8PtrTy(), (uint64_t)value); }
IRValue* ConstValueS(void* value) { return ircontext->getConstantInt(ircontext->getInt8PtrTy(), (uint64_t)value); }
IRValue* ConstValueF(double value) { return ircontext->getConstantFloat(doubleTy, value); }
IRValue* ConstValueA(void* value) { return ircontext->getConstantInt(int8PtrTy, (uint64_t)value); }
IRValue* ConstValueS(void* value) { return ircontext->getConstantInt(int8PtrTy, (uint64_t)value); }
void StoreD(IRValue* value, int index) { cc.CreateStore(value, regD[index]); }
void StoreF(IRValue* value, int index) { cc.CreateStore(value, regF[index]); }
void StoreA(IRValue* value, int index) { cc.CreateStore(value, regA[index]); }
@ -181,30 +108,28 @@ private:
IRValue* OffsetPtr(IRValue* ptr, IRValue* offset) { return cc.CreateGEP(ptr, { offset }); }
IRValue* OffsetPtr(IRValue* ptr, int offset) { return cc.CreateGEP(ptr, { ircontext->getConstantInt(offset) }); }
IRValue* ToInt8Ptr(IRValue* ptr, IRValue* offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), ircontext->getInt8PtrTy()); }
IRValue* ToInt8Ptr(IRValue* ptr, int offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), ircontext->getInt8PtrTy()); }
IRValue* ToInt16Ptr(IRValue* ptr, IRValue* offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), ircontext->getInt16PtrTy()); }
IRValue* ToInt32Ptr(IRValue* ptr, IRValue* offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), ircontext->getInt32PtrTy()); }
IRValue* ToInt32Ptr(IRValue* ptr) { return cc.CreateBitCast(ptr, ircontext->getInt32PtrTy()); }
IRValue* ToInt32Ptr(IRValue* ptr, int offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), ircontext->getInt32PtrTy()); }
IRValue* ToFloatPtr(IRValue* ptr, IRValue* offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), ircontext->getFloatPtrTy()); }
IRValue* ToDoublePtr(IRValue* ptr, IRValue* offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), ircontext->getDoublePtrTy()); }
IRValue* ToDoublePtr(IRValue* ptr, int offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), ircontext->getDoublePtrTy()); }
IRValue* ToDoublePtr(IRValue* ptr) { return cc.CreateBitCast(ptr, ircontext->getDoublePtrTy()); }
IRValue* ToInt8PtrPtr(IRValue* ptr, IRValue* offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), ircontext->getInt8PtrTy()->getPointerTo(ircontext)); }
IRValue* ToInt8PtrPtr(IRValue* ptr, int offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), ircontext->getInt8PtrTy()->getPointerTo(ircontext)); }
IRValue* ToInt8PtrPtr(IRValue* ptr) { return cc.CreateBitCast(ptr, ircontext->getInt8PtrTy()->getPointerTo(ircontext)); }
IRValue* Trunc8(IRValue* value) { return cc.CreateTrunc(value, ircontext->getInt8Ty()); }
IRValue* Trunc16(IRValue* value) { return cc.CreateTrunc(value, ircontext->getInt16Ty()); }
IRValue* FPTrunc(IRValue* value) { return cc.CreateFPTrunc(value, ircontext->getFloatTy()); }
IRValue* ZExt(IRValue* value) { return cc.CreateZExt(value, ircontext->getInt32Ty()); }
IRValue* SExt(IRValue* value) { return cc.CreateSExt(value, ircontext->getInt32Ty()); }
IRValue* FPExt(IRValue* value) { return cc.CreateFPExt(value, ircontext->getDoubleTy()); }
IRValue* ToInt8Ptr(IRValue* ptr, IRValue* offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), int8PtrTy); }
IRValue* ToInt8Ptr(IRValue* ptr, int offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), int8PtrTy); }
IRValue* ToInt16Ptr(IRValue* ptr, IRValue* offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), int16PtrTy); }
IRValue* ToInt32Ptr(IRValue* ptr, IRValue* offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), int32PtrTy); }
IRValue* ToInt32Ptr(IRValue* ptr) { return cc.CreateBitCast(ptr, int32PtrTy); }
IRValue* ToInt32Ptr(IRValue* ptr, int offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), int32PtrTy); }
IRValue* ToFloatPtr(IRValue* ptr, IRValue* offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), floatPtrTy); }
IRValue* ToDoublePtr(IRValue* ptr, IRValue* offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), doublePtrTy); }
IRValue* ToDoublePtr(IRValue* ptr, int offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), doublePtrTy); }
IRValue* ToDoublePtr(IRValue* ptr) { return cc.CreateBitCast(ptr, doublePtrTy); }
IRValue* ToInt8PtrPtr(IRValue* ptr, IRValue* offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), int8PtrPtrTy); }
IRValue* ToInt8PtrPtr(IRValue* ptr, int offset) { return cc.CreateBitCast(OffsetPtr(ptr, offset), int8PtrPtrTy); }
IRValue* ToInt8PtrPtr(IRValue* ptr) { return cc.CreateBitCast(ptr, int8PtrPtrTy); }
IRValue* Trunc8(IRValue* value) { return cc.CreateTrunc(value, int8Ty); }
IRValue* Trunc16(IRValue* value) { return cc.CreateTrunc(value, int16Ty); }
IRValue* FPTrunc(IRValue* value) { return cc.CreateFPTrunc(value, floatTy); }
IRValue* ZExt(IRValue* value) { return cc.CreateZExt(value, int32Ty); }
IRValue* SExt(IRValue* value) { return cc.CreateSExt(value, int32Ty); }
IRValue* FPExt(IRValue* value) { return cc.CreateFPExt(value, doubleTy); }
void Store(IRValue* value, IRValue* ptr) { cc.CreateStore(value, ptr); }
IRValue* Load(IRValue* ptr) { return cc.CreateLoad(ptr); }
static void CallAssignString(FString* to, FString* from) { *to = *from; }
VMScriptFunction* sfunc = nullptr;
IRContext* ircontext = nullptr;
@ -242,4 +167,74 @@ private:
int offsetExtra = 0;
TArray<JitLabel> labels;
IRType* voidTy = nullptr;
IRType* int8Ty = nullptr;
IRType* int8PtrTy = nullptr;
IRType* int8PtrPtrTy = nullptr;
IRType* int16Ty = nullptr;
IRType* int16PtrTy = nullptr;
IRType* int32Ty = nullptr;
IRType* int32PtrTy = nullptr;
IRType* int64Ty = nullptr;
IRType* floatTy = nullptr;
IRType* floatPtrTy = nullptr;
IRType* doubleTy = nullptr;
IRType* doublePtrTy = nullptr;
IRFunction* validateCall = nullptr;
IRFunction* setReturnString = nullptr;
IRFunction* createFullVMFrame = nullptr;
IRFunction* popFullVMFrame = nullptr;
IRFunction* throwException = nullptr;
IRFunction* throwArrayOutOfBounds = nullptr;
IRFunction* stringAssignmentOperator = nullptr;
IRFunction* stringAssignmentOperatorCStr = nullptr;
IRFunction* stringPlusOperator = nullptr;
IRFunction* stringCompare = nullptr;
IRFunction* stringCompareNoCase = nullptr;
IRFunction* stringLength = nullptr;
IRFunction* readBarrier = nullptr;
IRFunction* writeBarrier = nullptr;
IRFunction* doubleModF = nullptr;
IRFunction* doublePow = nullptr;
IRFunction* doubleAtan2 = nullptr;
IRFunction* doubleFabs = nullptr;
IRFunction* doubleExp = nullptr;
IRFunction* doubleLog = nullptr;
IRFunction* doubleLog10 = nullptr;
IRFunction* doubleSqrt = nullptr;
IRFunction* doubleCeil = nullptr;
IRFunction* doubleFloor = nullptr;
IRFunction* doubleAcos = nullptr;
IRFunction* doubleAsin = nullptr;
IRFunction* doubleAtan = nullptr;
IRFunction* doubleCos = nullptr;
IRFunction* doubleSin = nullptr;
IRFunction* doubleTan = nullptr;
IRFunction* doubleCosDeg = nullptr;
IRFunction* doubleSinDeg = nullptr;
IRFunction* doubleCosh = nullptr;
IRFunction* doubleSinh = nullptr;
IRFunction* doubleTanh = nullptr;
IRFunction* doubleRound = nullptr;
IRFunction* castI2S = nullptr;
IRFunction* castU2S = nullptr;
IRFunction* castF2S = nullptr;
IRFunction* castV22S = nullptr;
IRFunction* castV32S = nullptr;
IRFunction* castP2S = nullptr;
IRFunction* castS2I = nullptr;
IRFunction* castS2F = nullptr;
IRFunction* castS2N = nullptr;
IRFunction* castN2S = nullptr;
IRFunction* castS2Co = nullptr;
IRFunction* castCo2S = nullptr;
IRFunction* castS2So = nullptr;
IRFunction* castSo2S = nullptr;
IRFunction* castSID2S = nullptr;
IRFunction* castTID2S = nullptr;
IRFunction* castB_S = nullptr;
IRFunction* dynCast = nullptr;
IRFunction* dynCastC = nullptr;
};