mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +00:00
- removed OP_TAIL.
The amount of support code for this minor optimization was quite large and this stood in the way of streamlining the VM's calling convention, so it was preferable to remove it before moving on.
This commit is contained in:
parent
4e0c5cf16c
commit
629d329f22
9 changed files with 12 additions and 219 deletions
|
@ -784,7 +784,8 @@ void SetDehParams(FState *state, int codepointer)
|
||||||
// Emit code for action parameters.
|
// Emit code for action parameters.
|
||||||
MBFCodePointerFactories[codepointer](emitters, value1, value2);
|
MBFCodePointerFactories[codepointer](emitters, value1, value2);
|
||||||
int count = emitters.EmitParameters(&buildit);
|
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.
|
// Attach it to the state.
|
||||||
VMScriptFunction *sfunc = new VMScriptFunction;
|
VMScriptFunction *sfunc = new VMScriptFunction;
|
||||||
buildit.MakeFunction(sfunc);
|
buildit.MakeFunction(sfunc);
|
||||||
|
|
|
@ -5449,18 +5449,6 @@ FxRandom::~FxRandom()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
PPrototype *FxRandom::ReturnProto()
|
|
||||||
{
|
|
||||||
EmitTail = true;
|
|
||||||
return FxExpression::ReturnProto();
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
FxExpression *FxRandom::Resolve(FCompileContext &ctx)
|
FxExpression *FxRandom::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
|
@ -5506,23 +5494,13 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build)
|
||||||
assert(min && max);
|
assert(min && max);
|
||||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
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;
|
EmitterArray emitters;
|
||||||
|
|
||||||
emitters.AddParameterPointerConst(rng);
|
emitters.AddParameterPointerConst(rng);
|
||||||
emitters.AddParameter(build, min);
|
emitters.AddParameter(build, min);
|
||||||
emitters.AddParameter(build, max);
|
emitters.AddParameter(build, max);
|
||||||
int count = emitters.EmitParameters(build);
|
int count = emitters.EmitParameters(build);
|
||||||
build->Emit(opcode, build->GetConstantAddress(callfunc), count, 1);
|
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), count, 1);
|
||||||
|
|
||||||
if (EmitTail)
|
|
||||||
{
|
|
||||||
ExpEmit call;
|
|
||||||
call.Final = true;
|
|
||||||
return call;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpEmit out(build, REGT_INT);
|
ExpEmit out(build, REGT_INT);
|
||||||
build->Emit(OP_RESULT, 0, REGT_INT, out.RegNum);
|
build->Emit(OP_RESULT, 0, REGT_INT, out.RegNum);
|
||||||
|
@ -5747,22 +5725,12 @@ ExpEmit FxFRandom::Emit(VMFunctionBuilder *build)
|
||||||
assert(min && max);
|
assert(min && max);
|
||||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
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;
|
EmitterArray emitters;
|
||||||
emitters.AddParameterPointerConst(rng);
|
emitters.AddParameterPointerConst(rng);
|
||||||
emitters.AddParameter(build, min);
|
emitters.AddParameter(build, min);
|
||||||
emitters.AddParameter(build, max);
|
emitters.AddParameter(build, max);
|
||||||
int count = emitters.EmitParameters(build);
|
int count = emitters.EmitParameters(build);
|
||||||
build->Emit(opcode, build->GetConstantAddress(callfunc), count, 1);
|
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), count, 1);
|
||||||
|
|
||||||
if (EmitTail)
|
|
||||||
{
|
|
||||||
ExpEmit call;
|
|
||||||
call.Final = true;
|
|
||||||
return call;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpEmit out(build, REGT_FLOAT);
|
ExpEmit out(build, REGT_FLOAT);
|
||||||
build->Emit(OP_RESULT, 0, REGT_FLOAT, out.RegNum);
|
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)
|
FxRandom2::FxRandom2(FRandom *r, FxExpression *m, const FScriptPosition &pos, bool nowarn)
|
||||||
: FxExpression(EFX_Random2, pos)
|
: FxExpression(EFX_Random2, pos)
|
||||||
{
|
{
|
||||||
EmitTail = false;
|
|
||||||
rng = r;
|
rng = r;
|
||||||
if (m) mask = new FxIntCast(m, nowarn);
|
if (m) mask = new FxIntCast(m, nowarn);
|
||||||
else mask = new FxConstant(-1, pos);
|
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)
|
FxExpression *FxRandom2::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
|
@ -5851,22 +5806,12 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build)
|
||||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
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;
|
EmitterArray emitters;
|
||||||
|
|
||||||
emitters.AddParameterPointerConst(rng);
|
emitters.AddParameterPointerConst(rng);
|
||||||
emitters.AddParameter(build, mask);
|
emitters.AddParameter(build, mask);
|
||||||
int count = emitters.EmitParameters(build);
|
int count = emitters.EmitParameters(build);
|
||||||
build->Emit(opcode, build->GetConstantAddress(callfunc), count, 1);
|
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), count, 1);
|
||||||
|
|
||||||
if (EmitTail)
|
|
||||||
{
|
|
||||||
ExpEmit call;
|
|
||||||
call.Final = true;
|
|
||||||
return call;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpEmit out(build, REGT_INT);
|
ExpEmit out(build, REGT_INT);
|
||||||
build->Emit(OP_RESULT, 0, REGT_INT, out.RegNum);
|
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)
|
FxRandomSeed::FxRandomSeed(FRandom * r, FxExpression *s, const FScriptPosition &pos, bool nowarn)
|
||||||
: FxExpression(EFX_Random, pos)
|
: FxExpression(EFX_Random, pos)
|
||||||
{
|
{
|
||||||
EmitTail = false;
|
|
||||||
seed = new FxIntCast(s, nowarn);
|
seed = new FxIntCast(s, nowarn);
|
||||||
rng = r;
|
rng = r;
|
||||||
ValueType = TypeVoid;
|
ValueType = TypeVoid;
|
||||||
|
@ -5937,18 +5881,14 @@ ExpEmit FxRandomSeed::Emit(VMFunctionBuilder *build)
|
||||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
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;
|
EmitterArray emitters;
|
||||||
|
|
||||||
emitters.AddParameterPointerConst(rng);
|
emitters.AddParameterPointerConst(rng);
|
||||||
emitters.AddParameter(build, seed);
|
emitters.AddParameter(build, seed);
|
||||||
int count = emitters.EmitParameters(build);
|
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;
|
ExpEmit call;
|
||||||
if (EmitTail) call.Final = true;
|
|
||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6636,7 +6576,6 @@ FxClassDefaults::FxClassDefaults(FxExpression *X, const FScriptPosition &pos)
|
||||||
: FxExpression(EFX_ClassDefaults, pos)
|
: FxExpression(EFX_ClassDefaults, pos)
|
||||||
{
|
{
|
||||||
obj = X;
|
obj = X;
|
||||||
EmitTail = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FxClassDefaults::~FxClassDefaults()
|
FxClassDefaults::~FxClassDefaults()
|
||||||
|
@ -8508,7 +8447,6 @@ FxActionSpecialCall::FxActionSpecialCall(FxExpression *self, int special, FArgum
|
||||||
{
|
{
|
||||||
ArgList.Push(new FxConstant(0, ScriptPosition));
|
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)
|
FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
|
@ -8664,16 +8590,8 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
|
||||||
ArgList.DeleteAndClear();
|
ArgList.DeleteAndClear();
|
||||||
ArgList.ShrinkToFit();
|
ArgList.ShrinkToFit();
|
||||||
|
|
||||||
if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use
|
|
||||||
int count = emitters.EmitParameters(build);
|
int count = emitters.EmitParameters(build);
|
||||||
selfemit.Free(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);
|
ExpEmit dest(build, REGT_INT);
|
||||||
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), count, 1);
|
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), count, 1);
|
||||||
|
@ -8717,7 +8635,7 @@ PPrototype *FxVMFunctionCall::ReturnProto()
|
||||||
{
|
{
|
||||||
if (hasStringArgs)
|
if (hasStringArgs)
|
||||||
return FxExpression::ReturnProto();
|
return FxExpression::ReturnProto();
|
||||||
EmitTail = true;
|
|
||||||
return Function->Variants[0].Proto;
|
return Function->Variants[0].Proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9068,12 +8986,10 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
||||||
assert(build->Registers[REGT_POINTER].GetMostUsed() >= build->NumImplicits);
|
assert(build->Registers[REGT_POINTER].GetMostUsed() >= build->NumImplicits);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use
|
|
||||||
|
|
||||||
if (count == 1)
|
if (count == 1)
|
||||||
{
|
{
|
||||||
ExpEmit reg;
|
ExpEmit reg;
|
||||||
if (CheckEmitCast(build, EmitTail, reg))
|
if (CheckEmitCast(build, false, reg))
|
||||||
{
|
{
|
||||||
ArgList.DeleteAndClear();
|
ArgList.DeleteAndClear();
|
||||||
ArgList.ShrinkToFit();
|
ArgList.ShrinkToFit();
|
||||||
|
@ -9166,14 +9082,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
int funcaddr = build->GetConstantAddress(vmfunc);
|
int funcaddr = build->GetConstantAddress(vmfunc);
|
||||||
// Emit the call
|
// Emit the call
|
||||||
if (EmitTail)
|
if (vmfunc->Proto->ReturnTypes.Size() > 0)
|
||||||
{ // Tail call
|
|
||||||
build->Emit(OP_TAIL_K, funcaddr, count, 0);
|
|
||||||
ExpEmit call;
|
|
||||||
call.Final = true;
|
|
||||||
return call;
|
|
||||||
}
|
|
||||||
else if (vmfunc->Proto->ReturnTypes.Size() > 0)
|
|
||||||
{ // Call, expecting one result
|
{ // Call, expecting one result
|
||||||
build->Emit(OP_CALL_K, funcaddr, count, MAX(1, AssignCount));
|
build->Emit(OP_CALL_K, funcaddr, count, MAX(1, AssignCount));
|
||||||
goto handlereturns;
|
goto handlereturns;
|
||||||
|
@ -9189,14 +9098,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
||||||
ExpEmit funcreg(build, REGT_POINTER);
|
ExpEmit funcreg(build, REGT_POINTER);
|
||||||
|
|
||||||
build->Emit(OP_VTBL, funcreg.RegNum, selfemit.RegNum, vmfunc->VirtualIndex);
|
build->Emit(OP_VTBL, funcreg.RegNum, selfemit.RegNum, vmfunc->VirtualIndex);
|
||||||
if (EmitTail)
|
if (vmfunc->Proto->ReturnTypes.Size() > 0)
|
||||||
{ // Tail call
|
|
||||||
build->Emit(OP_TAIL, funcreg.RegNum, count, 0);
|
|
||||||
ExpEmit call;
|
|
||||||
call.Final = true;
|
|
||||||
return call;
|
|
||||||
}
|
|
||||||
else if (vmfunc->Proto->ReturnTypes.Size() > 0)
|
|
||||||
{ // Call, expecting one result
|
{ // Call, expecting one result
|
||||||
build->Emit(OP_CALL, funcreg.RegNum, count, MAX(1, AssignCount));
|
build->Emit(OP_CALL, funcreg.RegNum, count, MAX(1, AssignCount));
|
||||||
goto handlereturns;
|
goto handlereturns;
|
||||||
|
|
|
@ -404,7 +404,6 @@ public:
|
||||||
class FxClassDefaults : public FxExpression
|
class FxClassDefaults : public FxExpression
|
||||||
{
|
{
|
||||||
FxExpression *obj;
|
FxExpression *obj;
|
||||||
bool EmitTail;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FxClassDefaults(FxExpression *, const FScriptPosition &);
|
FxClassDefaults(FxExpression *, const FScriptPosition &);
|
||||||
|
@ -1257,7 +1256,6 @@ public:
|
||||||
class FxRandom : public FxExpression
|
class FxRandom : public FxExpression
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
bool EmitTail = false;
|
|
||||||
FRandom *rng;
|
FRandom *rng;
|
||||||
FxExpression *min, *max;
|
FxExpression *min, *max;
|
||||||
|
|
||||||
|
@ -1267,7 +1265,6 @@ public:
|
||||||
FxRandom(FRandom *, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos, bool nowarn);
|
FxRandom(FRandom *, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos, bool nowarn);
|
||||||
~FxRandom();
|
~FxRandom();
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
PPrototype *ReturnProto();
|
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1313,7 +1310,6 @@ public:
|
||||||
|
|
||||||
class FxRandom2 : public FxExpression
|
class FxRandom2 : public FxExpression
|
||||||
{
|
{
|
||||||
bool EmitTail;
|
|
||||||
FRandom * rng;
|
FRandom * rng;
|
||||||
FxExpression *mask;
|
FxExpression *mask;
|
||||||
|
|
||||||
|
@ -1322,7 +1318,6 @@ public:
|
||||||
FxRandom2(FRandom *, FxExpression *m, const FScriptPosition &pos, bool nowarn);
|
FxRandom2(FRandom *, FxExpression *m, const FScriptPosition &pos, bool nowarn);
|
||||||
~FxRandom2();
|
~FxRandom2();
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
PPrototype *ReturnProto();
|
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1336,7 +1331,6 @@ public:
|
||||||
class FxRandomSeed : public FxExpression
|
class FxRandomSeed : public FxExpression
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
bool EmitTail;
|
|
||||||
FRandom *rng;
|
FRandom *rng;
|
||||||
FxExpression *seed;
|
FxExpression *seed;
|
||||||
|
|
||||||
|
@ -1583,7 +1577,6 @@ public:
|
||||||
class FxActionSpecialCall : public FxExpression
|
class FxActionSpecialCall : public FxExpression
|
||||||
{
|
{
|
||||||
int Special;
|
int Special;
|
||||||
bool EmitTail;
|
|
||||||
FxExpression *Self;
|
FxExpression *Self;
|
||||||
FArgumentList ArgList;
|
FArgumentList ArgList;
|
||||||
|
|
||||||
|
@ -1592,7 +1585,6 @@ public:
|
||||||
FxActionSpecialCall(FxExpression *self, int special, FArgumentList &args, const FScriptPosition &pos);
|
FxActionSpecialCall(FxExpression *self, int special, FArgumentList &args, const FScriptPosition &pos);
|
||||||
~FxActionSpecialCall();
|
~FxActionSpecialCall();
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
PPrototype *ReturnProto();
|
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1752,7 +1744,6 @@ class FxVMFunctionCall : public FxExpression
|
||||||
{
|
{
|
||||||
friend class FxMultiAssign;
|
friend class FxMultiAssign;
|
||||||
|
|
||||||
bool EmitTail = false;
|
|
||||||
bool NoVirtual;
|
bool NoVirtual;
|
||||||
bool hasStringArgs = false;
|
bool hasStringArgs = false;
|
||||||
FxExpression *Self;
|
FxExpression *Self;
|
||||||
|
|
|
@ -606,7 +606,7 @@ size_t VMFunctionBuilder::Emit(int opcode, int opa, int opb, int opc)
|
||||||
emit.Free(this);
|
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);
|
ParamChange(-opb);
|
||||||
}
|
}
|
||||||
|
|
|
@ -330,7 +330,6 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_CALL_K:
|
case OP_CALL_K:
|
||||||
case OP_TAIL_K:
|
|
||||||
{
|
{
|
||||||
callfunc = (VMFunction *)func->KonstA[code[i].a].o;
|
callfunc = (VMFunction *)func->KonstA[code[i].a].o;
|
||||||
col = printf_wrapper(out, "[%p],%d", callfunc, code[i].b);
|
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);
|
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());
|
printf_wrapper(out, " [%s]\n", callfunc->PrintableName.GetChars());
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,18 +132,6 @@ void JitCompiler::EmitCALL_K()
|
||||||
EmitDoCall(ptr);
|
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)
|
void JitCompiler::EmitDoCall(asmjit::X86Gp vmfunc)
|
||||||
{
|
{
|
||||||
using namespace asmjit;
|
using namespace asmjit;
|
||||||
|
@ -185,50 +173,6 @@ void JitCompiler::EmitScriptCall(asmjit::X86Gp vmfunc, asmjit::X86Gp paramsptr)
|
||||||
call->setArg(4, Imm(C));
|
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<int, VMFunction *, VMValue*, int, VMReturn*, int>());
|
|
||||||
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)
|
void JitCompiler::StoreInOuts(int b)
|
||||||
{
|
{
|
||||||
using namespace asmjit;
|
using namespace asmjit;
|
||||||
|
|
|
@ -55,9 +55,6 @@ private:
|
||||||
void EmitDoCall(asmjit::X86Gp ptr);
|
void EmitDoCall(asmjit::X86Gp ptr);
|
||||||
void EmitScriptCall(asmjit::X86Gp vmfunc, asmjit::X86Gp paramsptr);
|
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 StoreInOuts(int b);
|
||||||
void LoadInOuts(int b);
|
void LoadInOuts(int b);
|
||||||
void LoadReturns(const VMOP *retval, int numret);
|
void LoadReturns(const VMOP *retval, int numret);
|
||||||
|
|
|
@ -718,45 +718,6 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret)
|
||||||
pc += C; // Skip RESULTs
|
pc += C; // Skip RESULTs
|
||||||
}
|
}
|
||||||
NEXTOP;
|
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<VMNativeFunction *>(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<VMScriptFunction *>(call);
|
|
||||||
return sfunc->ScriptCall(sfunc, reg.param + f->NumParam - B, B, ret, numret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NEXTOP;
|
|
||||||
OP(RET):
|
OP(RET):
|
||||||
if (B == REGT_NIL)
|
if (B == REGT_NIL)
|
||||||
{ // No return values
|
{ // No return values
|
||||||
|
|
|
@ -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(CALL_K, call, KPI8I8, CALL, 1, REGT_POINTER)
|
||||||
xx(VTBL, vtbl, RPRPI8, NOP, 0, 0) // dereferences a virtual method table.
|
xx(VTBL, vtbl, RPRPI8, NOP, 0, 0) // dereferences a virtual method table.
|
||||||
xx(SCOPE, scope, RPI8, NOP, 0, 0) // Scope check at runtime.
|
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(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(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
|
xx(RETI, reti, I8I16, NOP, 0, 0) // Copy immediate from BC to return value A, possibly returning
|
||||||
|
|
Loading…
Reference in a new issue