From 1c9df61c5d8a7f9747a91d872693bb024aab8e1c Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 6 Jun 2020 00:28:10 +0200 Subject: [PATCH] Replace the native call templates with CreateNativeFunction to make it more explicit which IR types are actually used --- src/common/scripting/jit/jit.cpp | 230 +++++++++++++++++++++---- src/common/scripting/jit/jit_call.cpp | 33 ++-- src/common/scripting/jit/jit_flow.cpp | 32 +--- src/common/scripting/jit/jit_load.cpp | 36 ++-- src/common/scripting/jit/jit_math.cpp | 106 ++++-------- src/common/scripting/jit/jit_move.cpp | 91 ++++------ src/common/scripting/jit/jit_store.cpp | 10 +- src/common/scripting/jit/jitintern.h | 201 +++++++++++---------- 8 files changed, 400 insertions(+), 339 deletions(-) diff --git a/src/common/scripting/jit/jit.cpp b/src/common/scripting/jit/jit.cpp index 5662ac3cb7c..48a84eb8bb2 100644 --- a/src/common/scripting/jit/jit.cpp +++ b/src/common/scripting/jit/jit.cpp @@ -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(), 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("__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("__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("__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(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 args, const char* name, void* ptr) +{ + IRFunctionType* functype = ircontext->getFunctionType(returnType, args); + IRFunction* func = ircontext->createFunction(functype, name); + ircontext->addGlobalMapping(func, ptr); + return func; +} diff --git a/src/common/scripting/jit/jit_call.cpp b/src/common/scripting/jit/jit_call.cpp index 4f8daaf2e93..7f5f808ed83 100644 --- a/src/common/scripting/jit/jit_call.cpp +++ b/src/common/scripting/jit/jit_call.cpp @@ -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()), { 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); diff --git a/src/common/scripting/jit/jit_flow.cpp b/src/common/scripting/jit/jit_flow.cpp index 9af6611c7e4..007d05ef49d 100644 --- a/src/common/scripting/jit/jit_flow.cpp +++ b/src/common/scripting/jit/jit_flow.cpp @@ -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("__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("__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("__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("__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("__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); - } -} diff --git a/src/common/scripting/jit/jit_load.cpp b/src/common/scripting/jit/jit_load.cpp index cf8a8eea431..32411a93120 100644 --- a/src/common/scripting/jit/jit_load.cpp +++ b/src/common/scripting/jit/jit_load.cpp @@ -21,7 +21,7 @@ void JitCompiler::EmitLKF() void JitCompiler::EmitLKS() { - cc.CreateCall(GetNativeFunc("__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("__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("__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("__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("__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("__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("__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("__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); } diff --git a/src/common/scripting/jit/jit_math.cpp b/src/common/scripting/jit/jit_math.cpp index 5134e601fdf..bff40654822 100644 --- a/src/common/scripting/jit/jit_math.cpp +++ b/src/common/scripting/jit/jit_math.cpp @@ -5,34 +5,14 @@ ///////////////////////////////////////////////////////////////////////////// // String instructions. -static void ConcatString(FString* to, FString* first, FString* second) -{ - *to = *first + *second; -} - void JitCompiler::EmitCONCAT() { - cc.CreateCall(GetNativeFunc("__ConcatString", ConcatString), { LoadS(A), LoadS(B), LoadS(C) }); -} - -static int StringLength(FString* str) -{ - return static_cast(str->Len()); + cc.CreateCall(stringPlusOperator, { LoadS(A), LoadS(B), LoadS(C) }); } void JitCompiler::EmitLENS() { - StoreD(cc.CreateCall(GetNativeFunc("__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(A & CMP_BK) ? ConstS(B) : LoadS(B); IRValue* arg1 = static_cast(A & CMP_CK) ? ConstS(C) : LoadS(C); - IRValue* result; - if (static_cast(A & CMP_APPROX)) - result = cc.CreateCall(GetNativeFunc("__StringCompareNoCase", StringCompareNoCase), { arg0, arg1 }); - else - result = cc.CreateCall(GetNativeFunc("__StringCompare", StringCompare), { arg0, arg1 }); - + IRValue* result = cc.CreateCall(static_cast(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("__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("__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("__DoubleModF", DoubleModF), { ConstF(B), LoadF(C) }), A); + StoreF(cc.CreateCall(doubleModF, { ConstF(B), LoadF(C) }), A); } void JitCompiler::EmitPOWF_RR() { - StoreF(cc.CreateCall(GetNativeFunc("__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("__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("__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("__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(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("__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("__g_sqrt", g_sqrt), { dotproduct }); + IRValue* len = cc.CreateCall(doubleSqrt, { dotproduct }); StoreF(len, A); } diff --git a/src/common/scripting/jit/jit_move.cpp b/src/common/scripting/jit/jit_move.cpp index 73b1d672634..14901c6082d 100644 --- a/src/common/scripting/jit/jit_move.cpp +++ b/src/common/scripting/jit/jit_move.cpp @@ -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("__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("__CastI2S", CastI2S), { LoadS(A), LoadD(B) }); + cc.CreateCall(castI2S, { LoadS(A), LoadD(B) }); break; case CAST_U2S: - cc.CreateCall(GetNativeFunc("__CastU2S", CastU2S), { LoadS(A), LoadD(B) }); + cc.CreateCall(castU2S, { LoadS(A), LoadD(B) }); break; case CAST_F2S: - cc.CreateCall(GetNativeFunc("__CastF2S", CastF2S), { LoadS(A), LoadF(B) }); + cc.CreateCall(castF2S, { LoadS(A), LoadF(B) }); break; case CAST_V22S: - cc.CreateCall(GetNativeFunc("__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("__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("__CastP2S", CastP2S), { LoadS(A), LoadA(B) }); + cc.CreateCall(castP2S, { LoadS(A), LoadA(B) }); break; case CAST_S2I: - StoreD(cc.CreateCall(GetNativeFunc("__CastS2I", CastS2I), { LoadS(B) }), A); + StoreD(cc.CreateCall(castS2I, { LoadS(B) }), A); break; case CAST_S2F: - StoreF(cc.CreateCall(GetNativeFunc("__CastS2F", CastS2F), { LoadS(B) }), A); + StoreF(cc.CreateCall(castS2F, { LoadS(B) }), A); break; case CAST_S2N: - StoreD(cc.CreateCall(GetNativeFunc("__CastS2N", CastS2N), { LoadS(B) }), A); + StoreD(cc.CreateCall(castS2N, { LoadS(B) }), A); break; case CAST_N2S: - cc.CreateCall(GetNativeFunc("__CastN2S", CastN2S), { LoadS(A), LoadD(B) }); + cc.CreateCall(castN2S, { LoadS(A), LoadD(B) }); break; case CAST_S2Co: - StoreD(cc.CreateCall(GetNativeFunc("__CastS2Co", CastS2Co), { LoadS(B) }), A); + StoreD(cc.CreateCall(castS2Co, { LoadS(B) }), A); break; case CAST_Co2S: - cc.CreateCall(GetNativeFunc("__CastCo2S", CastCo2S), { LoadS(A), LoadD(B) }); + cc.CreateCall(castCo2S, { LoadS(A), LoadD(B) }); break; case CAST_S2So: - StoreD(cc.CreateCall(GetNativeFunc("__CastS2So", CastS2So), { LoadS(B) }), A); + StoreD(cc.CreateCall(castS2So, { LoadS(B) }), A); break; case CAST_So2S: - cc.CreateCall(GetNativeFunc("__CastSo2S", CastSo2S), { LoadS(A), LoadD(B) }); + cc.CreateCall(castSo2S, { LoadS(A), LoadD(B) }); break; case CAST_SID2S: - cc.CreateCall(GetNativeFunc("__CastSID2S", CastSID2S), { LoadS(A), LoadD(B) }); + cc.CreateCall(castSID2S, { LoadS(A), LoadD(B) }); break; case CAST_TID2S: - cc.CreateCall(GetNativeFunc("__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("__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("__DynCast", DynCast), { LoadA(B), LoadA(C) }), A); + StoreA(cc.CreateCall(dynCast, { LoadA(B), LoadA(C) }), A); } void JitCompiler::EmitDYNCAST_K() { - StoreA(cc.CreateCall(GetNativeFunc("__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("__DynCastC", DynCastC), { LoadA(B), LoadA(C) }), A); + StoreA(cc.CreateCall(dynCastC, { LoadA(B), LoadA(C) }), A); } void JitCompiler::EmitDYNCASTC_K() { - StoreA(cc.CreateCall(GetNativeFunc("__DynCastC", DynCastC), { LoadA(B), ConstA(C) }), A); + StoreA(cc.CreateCall(dynCastC, { LoadA(B), ConstA(C) }), A); } diff --git a/src/common/scripting/jit/jit_store.cpp b/src/common/scripting/jit/jit_store.cpp index fc9f925442a..8c4d207f569 100644 --- a/src/common/scripting/jit/jit_store.cpp +++ b/src/common/scripting/jit/jit_store.cpp @@ -64,27 +64,25 @@ void JitCompiler::EmitSDP_R() void JitCompiler::EmitSS() { EmitNullPointerThrow(A, X_WRITE_NIL); - cc.CreateCall(GetNativeFunc("__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("__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("__WriteBarrier", static_cast(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("__WriteBarrier", static_cast(GC::WriteBarrier)), { OffsetPtr(LoadA(A), LoadD(C)), LoadA(B) }); + cc.CreateCall(writeBarrier, { OffsetPtr(LoadA(A), LoadD(C)), LoadA(B) }); } void JitCompiler::EmitSP() diff --git a/src/common/scripting/jit/jitintern.h b/src/common/scripting/jit/jitintern.h index ed7c358d2e2..961b233bcf9 100644 --- a/src/common/scripting/jit/jitintern.h +++ b/src/common/scripting/jit/jitintern.h @@ -34,8 +34,6 @@ class JitCompiler 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 @@ class JitCompiler 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 @@ class JitCompiler IRFunctionType* GetFuncSignature(); - template IRType* GetIRType() { static_assert(std::is_pointer::value, "Unsupported type"); return ircontext->getInt8PtrTy(); } - template<> IRType* GetIRType() { return ircontext->getVoidTy(); } - template<> IRType* GetIRType() { return ircontext->getInt8Ty(); } - template<> IRType* GetIRType() { return ircontext->getInt8Ty(); } - template<> IRType* GetIRType() { return ircontext->getInt16Ty(); } - template<> IRType* GetIRType() { return ircontext->getInt16Ty(); } - template<> IRType* GetIRType() { return ircontext->getInt32Ty(); } - template<> IRType* GetIRType() { return ircontext->getInt32Ty(); } - template<> IRType* GetIRType() { return ircontext->getInt64Ty(); } - template<> IRType* GetIRType() { return ircontext->getInt64Ty(); } - template<> IRType* GetIRType() { return ircontext->getFloatTy(); } - template<> IRType* GetIRType() { return ircontext->getDoubleTy(); } - - template - IRFunctionType* GetFunctionType0() { return ircontext->getFunctionType(GetIRType(), { }); } - - template - IRFunctionType* GetFunctionType1() { return ircontext->getFunctionType(GetIRType(), { GetIRType() }); } - - template - IRFunctionType* GetFunctionType2() { return ircontext->getFunctionType(GetIRType(), { GetIRType(), GetIRType() }); } - - template - IRFunctionType* GetFunctionType3() { return ircontext->getFunctionType(GetIRType(), { GetIRType(), GetIRType(), GetIRType() }); } - - template - IRFunctionType* GetFunctionType4() { return ircontext->getFunctionType(GetIRType(), { GetIRType(), GetIRType(), GetIRType(), GetIRType() }); } - - template - IRFunctionType* GetFunctionType5() { return ircontext->getFunctionType(GetIRType(), { GetIRType(), GetIRType(), GetIRType(), GetIRType(), GetIRType() }); } - - template - IRFunctionType* GetFunctionType6() { return ircontext->getFunctionType(GetIRType(), { GetIRType(), GetIRType(), GetIRType(), GetIRType(), GetIRType(), GetIRType() }); } - - template - IRFunctionType* GetFunctionType7() { return ircontext->getFunctionType(GetIRType(), { GetIRType(), GetIRType(), GetIRType(), GetIRType(), GetIRType(), GetIRType(), GetIRType() }); } - - 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 - IRFunction* GetNativeFunc(const char* name, RetType(*func)()) { return GetNativeFunc(name, func, GetFunctionType0()); } - - template - IRFunction* GetNativeFunc(const char* name, RetType(*func)(P1 p1)) { return GetNativeFunc(name, func, GetFunctionType1()); } - - template - IRFunction* GetNativeFunc(const char* name, RetType(*func)(P1 p1, P2 p2)) { return GetNativeFunc(name, func, GetFunctionType2()); } - - template - IRFunction* GetNativeFunc(const char* name, RetType(*func)(P1 p1, P2 p2, P3 p3)) { return GetNativeFunc(name, func, GetFunctionType3()); } - - template - IRFunction* GetNativeFunc(const char* name, RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4)) { return GetNativeFunc(name, func, GetFunctionType4()); } - - template - IRFunction* GetNativeFunc(const char* name, RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)) { return GetNativeFunc(name, func, GetFunctionType5()); } - - template - IRFunction* GetNativeFunc(const char* name, RetType(*func)(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)) { return GetNativeFunc(name, func, GetFunctionType6()); } - - template - 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()); } + void GetTypes(); + void CreateNativeFunctions(); + IRFunction* CreateNativeFunction(IRType* returnType, std::vector args, const char* name, void* ptr); template void EmitComparisonOpcode(Func jmpFunc) @@ -167,13 +94,13 @@ class JitCompiler 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 @@ class JitCompiler 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 @@ class JitCompiler int offsetExtra = 0; TArray 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; };