diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index aaac4b8792..9004dc555c 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -784,7 +784,8 @@ void SetDehParams(FState *state, int codepointer) // Emit code for action parameters. MBFCodePointerFactories[codepointer](emitters, value1, value2); int count = emitters.EmitParameters(&buildit); - buildit.Emit(OP_TAIL_K, buildit.GetConstantAddress(sym->Variants[0].Implementation), count, 0); + buildit.Emit(OP_CALL_K, buildit.GetConstantAddress(sym->Variants[0].Implementation), count, 0); + buildit.Emit(OP_RET, RET_FINAL, REGT_NIL, 0); // Attach it to the state. VMScriptFunction *sfunc = new VMScriptFunction; buildit.MakeFunction(sfunc); diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 26e2ccd99b..74ab9a1c8e 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -5449,18 +5449,6 @@ FxRandom::~FxRandom() // //========================================================================== -PPrototype *FxRandom::ReturnProto() -{ - EmitTail = true; - return FxExpression::ReturnProto(); -} - -//========================================================================== -// -// -// -//========================================================================== - FxExpression *FxRandom::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); @@ -5506,23 +5494,13 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build) assert(min && max); callfunc = ((PSymbolVMFunction *)sym)->Function; - if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use - int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); - EmitterArray emitters; emitters.AddParameterPointerConst(rng); emitters.AddParameter(build, min); emitters.AddParameter(build, max); int count = emitters.EmitParameters(build); - build->Emit(opcode, build->GetConstantAddress(callfunc), count, 1); - - if (EmitTail) - { - ExpEmit call; - call.Final = true; - return call; - } + build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), count, 1); ExpEmit out(build, REGT_INT); build->Emit(OP_RESULT, 0, REGT_INT, out.RegNum); @@ -5747,22 +5725,12 @@ ExpEmit FxFRandom::Emit(VMFunctionBuilder *build) assert(min && max); callfunc = ((PSymbolVMFunction *)sym)->Function; - if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use - int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); - EmitterArray emitters; emitters.AddParameterPointerConst(rng); emitters.AddParameter(build, min); emitters.AddParameter(build, max); int count = emitters.EmitParameters(build); - build->Emit(opcode, build->GetConstantAddress(callfunc), count, 1); - - if (EmitTail) - { - ExpEmit call; - call.Final = true; - return call; - } + build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), count, 1); ExpEmit out(build, REGT_FLOAT); build->Emit(OP_RESULT, 0, REGT_FLOAT, out.RegNum); @@ -5778,7 +5746,6 @@ ExpEmit FxFRandom::Emit(VMFunctionBuilder *build) FxRandom2::FxRandom2(FRandom *r, FxExpression *m, const FScriptPosition &pos, bool nowarn) : FxExpression(EFX_Random2, pos) { - EmitTail = false; rng = r; if (m) mask = new FxIntCast(m, nowarn); else mask = new FxConstant(-1, pos); @@ -5802,18 +5769,6 @@ FxRandom2::~FxRandom2() // //========================================================================== -PPrototype *FxRandom2::ReturnProto() -{ - EmitTail = true; - return FxExpression::ReturnProto(); -} - -//========================================================================== -// -// -// -//========================================================================== - FxExpression *FxRandom2::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); @@ -5851,22 +5806,12 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build) assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = ((PSymbolVMFunction *)sym)->Function; - if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use - int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); - EmitterArray emitters; emitters.AddParameterPointerConst(rng); emitters.AddParameter(build, mask); int count = emitters.EmitParameters(build); - build->Emit(opcode, build->GetConstantAddress(callfunc), count, 1); - - if (EmitTail) - { - ExpEmit call; - call.Final = true; - return call; - } + build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), count, 1); ExpEmit out(build, REGT_INT); build->Emit(OP_RESULT, 0, REGT_INT, out.RegNum); @@ -5881,7 +5826,6 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build) FxRandomSeed::FxRandomSeed(FRandom * r, FxExpression *s, const FScriptPosition &pos, bool nowarn) : FxExpression(EFX_Random, pos) { - EmitTail = false; seed = new FxIntCast(s, nowarn); rng = r; ValueType = TypeVoid; @@ -5937,18 +5881,14 @@ ExpEmit FxRandomSeed::Emit(VMFunctionBuilder *build) assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = ((PSymbolVMFunction *)sym)->Function; - if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use - int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); - EmitterArray emitters; emitters.AddParameterPointerConst(rng); emitters.AddParameter(build, seed); int count = emitters.EmitParameters(build); - build->Emit(opcode, build->GetConstantAddress(callfunc), count, 0); + build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), count, 0); ExpEmit call; - if (EmitTail) call.Final = true; return call; } @@ -6636,7 +6576,6 @@ FxClassDefaults::FxClassDefaults(FxExpression *X, const FScriptPosition &pos) : FxExpression(EFX_ClassDefaults, pos) { obj = X; - EmitTail = false; } FxClassDefaults::~FxClassDefaults() @@ -8508,7 +8447,6 @@ FxActionSpecialCall::FxActionSpecialCall(FxExpression *self, int special, FArgum { ArgList.Push(new FxConstant(0, ScriptPosition)); } - EmitTail = false; } //========================================================================== @@ -8528,18 +8466,6 @@ FxActionSpecialCall::~FxActionSpecialCall() // //========================================================================== -PPrototype *FxActionSpecialCall::ReturnProto() -{ - EmitTail = true; - return FxExpression::ReturnProto(); -} - -//========================================================================== -// -// -// -//========================================================================== - FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); @@ -8664,16 +8590,8 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) ArgList.DeleteAndClear(); ArgList.ShrinkToFit(); - if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use int count = emitters.EmitParameters(build); selfemit.Free(build); - if (EmitTail) - { - build->Emit(OP_TAIL_K, build->GetConstantAddress(callfunc), count, 0); - ExpEmit call; - call.Final = true; - return call; - } ExpEmit dest(build, REGT_INT); build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), count, 1); @@ -8717,7 +8635,7 @@ PPrototype *FxVMFunctionCall::ReturnProto() { if (hasStringArgs) return FxExpression::ReturnProto(); - EmitTail = true; + return Function->Variants[0].Proto; } @@ -9068,12 +8986,10 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) assert(build->Registers[REGT_POINTER].GetMostUsed() >= build->NumImplicits); int count = 0; - if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use - if (count == 1) { ExpEmit reg; - if (CheckEmitCast(build, EmitTail, reg)) + if (CheckEmitCast(build, false, reg)) { ArgList.DeleteAndClear(); ArgList.ShrinkToFit(); @@ -9166,14 +9082,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) { int funcaddr = build->GetConstantAddress(vmfunc); // Emit the call - if (EmitTail) - { // Tail call - build->Emit(OP_TAIL_K, funcaddr, count, 0); - ExpEmit call; - call.Final = true; - return call; - } - else if (vmfunc->Proto->ReturnTypes.Size() > 0) + if (vmfunc->Proto->ReturnTypes.Size() > 0) { // Call, expecting one result build->Emit(OP_CALL_K, funcaddr, count, MAX(1, AssignCount)); goto handlereturns; @@ -9189,14 +9098,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) ExpEmit funcreg(build, REGT_POINTER); build->Emit(OP_VTBL, funcreg.RegNum, selfemit.RegNum, vmfunc->VirtualIndex); - if (EmitTail) - { // Tail call - build->Emit(OP_TAIL, funcreg.RegNum, count, 0); - ExpEmit call; - call.Final = true; - return call; - } - else if (vmfunc->Proto->ReturnTypes.Size() > 0) + if (vmfunc->Proto->ReturnTypes.Size() > 0) { // Call, expecting one result build->Emit(OP_CALL, funcreg.RegNum, count, MAX(1, AssignCount)); goto handlereturns; diff --git a/src/scripting/backend/codegen.h b/src/scripting/backend/codegen.h index 9e93ec6f3e..ba0bb4d410 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -404,7 +404,6 @@ public: class FxClassDefaults : public FxExpression { FxExpression *obj; - bool EmitTail; public: FxClassDefaults(FxExpression *, const FScriptPosition &); @@ -1257,7 +1256,6 @@ public: class FxRandom : public FxExpression { protected: - bool EmitTail = false; FRandom *rng; FxExpression *min, *max; @@ -1267,7 +1265,6 @@ public: FxRandom(FRandom *, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos, bool nowarn); ~FxRandom(); FxExpression *Resolve(FCompileContext&); - PPrototype *ReturnProto(); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -1313,7 +1310,6 @@ public: class FxRandom2 : public FxExpression { - bool EmitTail; FRandom * rng; FxExpression *mask; @@ -1322,7 +1318,6 @@ public: FxRandom2(FRandom *, FxExpression *m, const FScriptPosition &pos, bool nowarn); ~FxRandom2(); FxExpression *Resolve(FCompileContext&); - PPrototype *ReturnProto(); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -1336,7 +1331,6 @@ public: class FxRandomSeed : public FxExpression { protected: - bool EmitTail; FRandom *rng; FxExpression *seed; @@ -1583,7 +1577,6 @@ public: class FxActionSpecialCall : public FxExpression { int Special; - bool EmitTail; FxExpression *Self; FArgumentList ArgList; @@ -1592,7 +1585,6 @@ public: FxActionSpecialCall(FxExpression *self, int special, FArgumentList &args, const FScriptPosition &pos); ~FxActionSpecialCall(); FxExpression *Resolve(FCompileContext&); - PPrototype *ReturnProto(); ExpEmit Emit(VMFunctionBuilder *build); }; @@ -1752,7 +1744,6 @@ class FxVMFunctionCall : public FxExpression { friend class FxMultiAssign; - bool EmitTail = false; bool NoVirtual; bool hasStringArgs = false; FxExpression *Self; diff --git a/src/scripting/backend/vmbuilder.cpp b/src/scripting/backend/vmbuilder.cpp index 6c16e1a3a9..ecd8c2d290 100644 --- a/src/scripting/backend/vmbuilder.cpp +++ b/src/scripting/backend/vmbuilder.cpp @@ -606,7 +606,7 @@ size_t VMFunctionBuilder::Emit(int opcode, int opa, int opb, int opc) emit.Free(this); } - if (opcode == OP_CALL || opcode == OP_CALL_K || opcode == OP_TAIL || opcode == OP_TAIL_K) + if (opcode == OP_CALL || opcode == OP_CALL_K) { ParamChange(-opb); } diff --git a/src/scripting/backend/vmdisasm.cpp b/src/scripting/backend/vmdisasm.cpp index 53b8891c1b..ebde2ef574 100644 --- a/src/scripting/backend/vmdisasm.cpp +++ b/src/scripting/backend/vmdisasm.cpp @@ -330,7 +330,6 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction break; case OP_CALL_K: - case OP_TAIL_K: { callfunc = (VMFunction *)func->KonstA[code[i].a].o; col = printf_wrapper(out, "[%p],%d", callfunc, code[i].b); @@ -524,7 +523,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction { printf_wrapper(out, ",%d\n", code[++i].i24); } - else if (code[i].op == OP_CALL_K || code[i].op == OP_TAIL_K) + else if (code[i].op == OP_CALL_K) { printf_wrapper(out, " [%s]\n", callfunc->PrintableName.GetChars()); } diff --git a/src/scripting/vm/jit_call.cpp b/src/scripting/vm/jit_call.cpp index f8130437b7..15dc8b56ed 100644 --- a/src/scripting/vm/jit_call.cpp +++ b/src/scripting/vm/jit_call.cpp @@ -132,18 +132,6 @@ void JitCompiler::EmitCALL_K() EmitDoCall(ptr); } -void JitCompiler::EmitTAIL() -{ - EmitDoTail(regA[A]); -} - -void JitCompiler::EmitTAIL_K() -{ - auto ptr = newTempIntPtr(); - cc.mov(ptr, asmjit::imm_ptr(konsta[A].o)); - EmitDoTail(ptr); -} - void JitCompiler::EmitDoCall(asmjit::X86Gp vmfunc) { using namespace asmjit; @@ -185,50 +173,6 @@ void JitCompiler::EmitScriptCall(asmjit::X86Gp vmfunc, asmjit::X86Gp paramsptr) call->setArg(4, Imm(C)); } -void JitCompiler::EmitDoTail(asmjit::X86Gp vmfunc) -{ - // Whereas the CALL instruction uses its third operand to specify how many return values - // it expects, TAIL ignores its third operand and uses whatever was passed to this Exec call. - - // Note: this is not a true tail call, but then again, it isn't in the vmexec implementation either.. - - using namespace asmjit; - - if (NumParam < B) - I_FatalError("OP_TAIL parameter count does not match the number of preceding OP_PARAM instructions"); - - StoreInOuts(B); // Is REGT_ADDROF even allowed for (true) tail calls? - - X86Gp paramsptr = newTempIntPtr(); - cc.lea(paramsptr, x86::ptr(vmframe, offsetParams + (int)((NumParam - B) * sizeof(VMValue)))); - - auto result = newResultInt32(); - - EmitScriptTailCall(vmfunc, result, paramsptr); - - EmitPopFrame(); - cc.ret(result); - - NumParam -= B; - ParamOpcodes.Resize(ParamOpcodes.Size() - B); -} - -void JitCompiler::EmitScriptTailCall(asmjit::X86Gp vmfunc, asmjit::X86Gp result, asmjit::X86Gp paramsptr) -{ - using namespace asmjit; - - auto scriptcall = newTempIntPtr(); - cc.mov(scriptcall, x86::ptr(vmfunc, offsetof(VMScriptFunction, ScriptCall))); - - auto call = cc.call(scriptcall, FuncSignature5()); - call->setRet(0, result); - call->setArg(0, vmfunc); - call->setArg(1, paramsptr); - call->setArg(2, Imm(B)); - call->setArg(3, ret); - call->setArg(4, numret); -} - void JitCompiler::StoreInOuts(int b) { using namespace asmjit; diff --git a/src/scripting/vm/jitintern.h b/src/scripting/vm/jitintern.h index a344880545..34099158ae 100644 --- a/src/scripting/vm/jitintern.h +++ b/src/scripting/vm/jitintern.h @@ -55,9 +55,6 @@ private: void EmitDoCall(asmjit::X86Gp ptr); void EmitScriptCall(asmjit::X86Gp vmfunc, asmjit::X86Gp paramsptr); - void EmitDoTail(asmjit::X86Gp ptr); - void EmitScriptTailCall(asmjit::X86Gp vmfunc, asmjit::X86Gp result, asmjit::X86Gp paramsptr); - void StoreInOuts(int b); void LoadInOuts(int b); void LoadReturns(const VMOP *retval, int numret); diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index e7735c5cbd..c910d61b97 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -718,45 +718,6 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) pc += C; // Skip RESULTs } NEXTOP; - OP(TAIL_K): - ASSERTKA(a); - ptr = konsta[a].o; - goto Do_TAILCALL; - OP(TAIL): - ASSERTA(a); - ptr = reg.a[a]; - Do_TAILCALL: - // Whereas the CALL instruction uses its third operand to specify how many return values - // it expects, TAIL ignores its third operand and uses whatever was passed to this Exec call. - assert(B <= f->NumParam); - assert(C <= MAX_RETURNS); - { - VMFunction *call = (VMFunction *)ptr; - - if (call->VarFlags & VARF_Native) - { - try - { - VMCycles[0].Unclock(); - auto r = static_cast(call)->NativeCall(reg.param + f->NumParam - B, B, ret, numret); - VMCycles[0].Clock(); - return r; - } - catch (CVMAbortException &err) - { - err.MaybePrintMessage(); - err.stacktrace.AppendFormat("Called from %s\n", call->PrintableName.GetChars()); - // PrintParameters(reg.param + f->NumParam - B, B); - throw; - } - } - else - { // FIXME: Not a true tail call - auto sfunc = static_cast(call); - return sfunc->ScriptCall(sfunc, reg.param + f->NumParam - B, B, ret, numret); - } - } - NEXTOP; OP(RET): if (B == REGT_NIL) { // No return values diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index afa0dbfa91..a4e623e9b9 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -105,8 +105,6 @@ xx(CALL, call, RPI8I8, NOP, 0, 0) // Call function pkA with parameter count B a xx(CALL_K, call, KPI8I8, CALL, 1, REGT_POINTER) xx(VTBL, vtbl, RPRPI8, NOP, 0, 0) // dereferences a virtual method table. xx(SCOPE, scope, RPI8, NOP, 0, 0) // Scope check at runtime. -xx(TAIL, tail, RPI8, NOP, 0, 0) // Call+Ret in a single instruction -xx(TAIL_K, tail, KPI8, TAIL, 1, REGT_POINTER) xx(RESULT, result, __BCP, NOP, 0, 0) // Result should go in register encoded in BC (in caller, after CALL) xx(RET, ret, I8BCP, NOP, 0, 0) // Copy value from register encoded in BC to return value A, possibly returning xx(RETI, reti, I8I16, NOP, 0, 0) // Copy immediate from BC to return value A, possibly returning