- moved all code related to function calls into the helper class so that all future work on the calling convention is in one place only.
This commit is contained in:
parent
cbedcff559
commit
fe0a341e0c
4 changed files with 64 additions and 99 deletions
|
|
@ -5494,7 +5494,7 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build)
|
|||
assert(min && max);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
EmitterArray emitters;
|
||||
FunctionCallEmitter emitters;
|
||||
|
||||
emitters.AddParameterPointerConst(rng);
|
||||
emitters.AddParameter(build, min);
|
||||
|
|
@ -5601,7 +5601,7 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build)
|
|||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
EmitterArray emitters;
|
||||
FunctionCallEmitter emitters;
|
||||
emitters.AddParameterPointerConst(rng);
|
||||
emitters.AddParameterIntConst(0);
|
||||
emitters.AddParameterIntConst(choices.Size() - 1);
|
||||
|
|
@ -5722,7 +5722,7 @@ ExpEmit FxFRandom::Emit(VMFunctionBuilder *build)
|
|||
assert(min && max);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
EmitterArray emitters;
|
||||
FunctionCallEmitter emitters;
|
||||
emitters.AddParameterPointerConst(rng);
|
||||
emitters.AddParameter(build, min);
|
||||
emitters.AddParameter(build, max);
|
||||
|
|
@ -5800,7 +5800,7 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build)
|
|||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
EmitterArray emitters;
|
||||
FunctionCallEmitter emitters;
|
||||
|
||||
emitters.AddParameterPointerConst(rng);
|
||||
emitters.AddParameter(build, mask);
|
||||
|
|
@ -5872,7 +5872,7 @@ ExpEmit FxRandomSeed::Emit(VMFunctionBuilder *build)
|
|||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
EmitterArray emitters;
|
||||
FunctionCallEmitter emitters;
|
||||
|
||||
emitters.AddParameterPointerConst(rng);
|
||||
emitters.AddParameter(build, seed);
|
||||
|
|
@ -8539,7 +8539,7 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
unsigned i = 0;
|
||||
|
||||
EmitterArray emitters;
|
||||
FunctionCallEmitter emitters;
|
||||
|
||||
emitters.AddParameterIntConst(abs(Special)); // pass special number
|
||||
emitters.AddParameter(build, Self);
|
||||
|
|
@ -8983,7 +8983,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
|||
bool staticcall = ((vmfunc->VarFlags & VARF_Final) || vmfunc->VirtualIndex == ~0u || NoVirtual);
|
||||
|
||||
count = 0;
|
||||
EmitterArray emitters;
|
||||
FunctionCallEmitter emitters;
|
||||
// Emit code to pass implied parameters
|
||||
ExpEmit selfemit;
|
||||
if (Function->Variants[0].Flags & VARF_Method)
|
||||
|
|
@ -9054,63 +9054,18 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
|||
break;
|
||||
}
|
||||
}
|
||||
count = emitters.EmitParameters(build);
|
||||
|
||||
ArgList.DeleteAndClear();
|
||||
ArgList.ShrinkToFit();
|
||||
|
||||
// Get a constant register for this function
|
||||
if (staticcall)
|
||||
{
|
||||
int funcaddr = build->GetConstantAddress(vmfunc);
|
||||
// Emit the call
|
||||
if (vmfunc->Proto->ReturnTypes.Size() > 0)
|
||||
{ // Call, expecting one result
|
||||
build->Emit(OP_CALL_K, funcaddr, count, MAX(1, AssignCount));
|
||||
goto handlereturns;
|
||||
}
|
||||
else
|
||||
{ // Call, expecting no results
|
||||
build->Emit(OP_CALL_K, funcaddr, count, 0);
|
||||
return ExpEmit();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ExpEmit funcreg(build, REGT_POINTER);
|
||||
emitters.AddTarget(vmfunc, staticcall? -1 : selfemit.RegNum);
|
||||
int resultcount = vmfunc->Proto->ReturnTypes.Size() == 0 ? 0 : MAX(AssignCount, 1);
|
||||
|
||||
build->Emit(OP_VTBL, funcreg.RegNum, selfemit.RegNum, vmfunc->VirtualIndex);
|
||||
if (vmfunc->Proto->ReturnTypes.Size() > 0)
|
||||
{ // Call, expecting one result
|
||||
build->Emit(OP_CALL, funcreg.RegNum, count, MAX(1, AssignCount));
|
||||
goto handlereturns;
|
||||
}
|
||||
else
|
||||
{ // Call, expecting no results
|
||||
build->Emit(OP_CALL, funcreg.RegNum, count, 0);
|
||||
return ExpEmit();
|
||||
}
|
||||
}
|
||||
handlereturns:
|
||||
if (AssignCount == 0)
|
||||
assert((unsigned)resultcount <= vmfunc->Proto->ReturnTypes.Size());
|
||||
for (int i = 0; i < resultcount; i++)
|
||||
{
|
||||
// Regular call, will not write to ReturnRegs
|
||||
ExpEmit reg(build, vmfunc->Proto->ReturnTypes[0]->GetRegType(), vmfunc->Proto->ReturnTypes[0]->GetRegCount());
|
||||
build->Emit(OP_RESULT, 0, EncodeRegType(reg), reg.RegNum);
|
||||
return reg;
|
||||
emitters.AddReturn(vmfunc->Proto->ReturnTypes[i]->GetRegType(), vmfunc->Proto->ReturnTypes[i]->GetRegCount());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Multi-Assignment call, this must fill in the ReturnRegs array so that the multi-assignment operator can dispatch the return values.
|
||||
assert((unsigned)AssignCount <= vmfunc->Proto->ReturnTypes.Size());
|
||||
for (int i = 0; i < AssignCount; i++)
|
||||
{
|
||||
ExpEmit reg(build, vmfunc->Proto->ReturnTypes[i]->GetRegType(), vmfunc->Proto->ReturnTypes[i]->GetRegCount());
|
||||
build->Emit(OP_RESULT, 0, EncodeRegType(reg), reg.RegNum);
|
||||
ReturnRegs.Push(reg);
|
||||
}
|
||||
}
|
||||
return ExpEmit();
|
||||
return emitters.EmitCall(build, resultcount > 1? &ReturnRegs : nullptr);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
@ -10621,7 +10576,7 @@ ExpEmit FxReturnStatement::Emit(VMFunctionBuilder *build)
|
|||
assert(pstr->mDestructor != nullptr);
|
||||
ExpEmit reg(build, REGT_POINTER);
|
||||
build->Emit(OP_ADDA_RK, reg.RegNum, build->FramePointer.RegNum, build->GetConstantInt(build->ConstructedStructs[i]->StackOffset));
|
||||
EmitterArray emitters;
|
||||
FunctionCallEmitter emitters;
|
||||
emitters.AddParameter(reg, false);
|
||||
emitters.AddTarget(pstr->mDestructor);
|
||||
emitters.EmitCall(build);
|
||||
|
|
@ -10816,7 +10771,7 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
return ExpEmit(build->GetConstantAddress(nullptr), REGT_POINTER, true);
|
||||
}
|
||||
EmitterArray emitters;
|
||||
FunctionCallEmitter emitters;
|
||||
emitters.AddParameter(build, basex);
|
||||
emitters.AddParameterPointerConst(const_cast<PClass *>(desttype));
|
||||
|
||||
|
|
@ -10925,7 +10880,7 @@ ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
ExpEmit clsname = basex->Emit(build);
|
||||
|
||||
EmitterArray emitters;
|
||||
FunctionCallEmitter emitters;
|
||||
|
||||
emitters.AddParameter(clsname, false);
|
||||
emitters.AddParameterPointerConst(desttype);
|
||||
|
|
@ -11311,7 +11266,7 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
ExpEmit reg(build, REGT_POINTER);
|
||||
build->Emit(OP_ADDA_RK, reg.RegNum, build->FramePointer.RegNum, build->GetConstantInt(StackOffset));
|
||||
EmitterArray emitters;
|
||||
FunctionCallEmitter emitters;
|
||||
emitters.AddParameter(reg, false);
|
||||
emitters.AddTarget(pstr->mConstructor);
|
||||
emitters.EmitCall(build);
|
||||
|
|
@ -11338,7 +11293,7 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build)
|
|||
{
|
||||
ExpEmit reg(build, REGT_POINTER);
|
||||
build->Emit(OP_ADDA_RK, reg.RegNum, build->FramePointer.RegNum, build->GetConstantInt(StackOffset));
|
||||
EmitterArray emitters;
|
||||
FunctionCallEmitter emitters;
|
||||
emitters.AddParameter(reg, false);
|
||||
emitters.AddTarget(pstr->mDestructor);
|
||||
emitters.EmitCall(build);
|
||||
|
|
|
|||
|
|
@ -931,7 +931,7 @@ void FFunctionBuildList::DumpJit()
|
|||
}
|
||||
|
||||
|
||||
void EmitterArray::AddParameter(VMFunctionBuilder *build, FxExpression *operand)
|
||||
void FunctionCallEmitter::AddParameter(VMFunctionBuilder *build, FxExpression *operand)
|
||||
{
|
||||
ExpEmit where = operand->Emit(build);
|
||||
|
||||
|
|
@ -958,7 +958,7 @@ void EmitterArray::AddParameter(VMFunctionBuilder *build, FxExpression *operand)
|
|||
});
|
||||
}
|
||||
|
||||
void EmitterArray::AddParameter(ExpEmit &emit, bool reference)
|
||||
void FunctionCallEmitter::AddParameter(ExpEmit &emit, bool reference)
|
||||
{
|
||||
numparams += emit.RegCount;
|
||||
emitters.push_back([=](VMFunctionBuilder *build) ->int
|
||||
|
|
@ -970,7 +970,7 @@ void EmitterArray::AddParameter(ExpEmit &emit, bool reference)
|
|||
});
|
||||
}
|
||||
|
||||
void EmitterArray::AddParameterPointerConst(void *konst)
|
||||
void FunctionCallEmitter::AddParameterPointerConst(void *konst)
|
||||
{
|
||||
numparams++;
|
||||
emitters.push_back([=](VMFunctionBuilder *build) ->int
|
||||
|
|
@ -980,7 +980,7 @@ void EmitterArray::AddParameterPointerConst(void *konst)
|
|||
});
|
||||
}
|
||||
|
||||
void EmitterArray::AddParameterPointer(int index, bool konst)
|
||||
void FunctionCallEmitter::AddParameterPointer(int index, bool konst)
|
||||
{
|
||||
numparams++;
|
||||
emitters.push_back([=](VMFunctionBuilder *build) ->int
|
||||
|
|
@ -990,7 +990,7 @@ void EmitterArray::AddParameterPointer(int index, bool konst)
|
|||
});
|
||||
}
|
||||
|
||||
void EmitterArray::AddParameterFloatConst(double konst)
|
||||
void FunctionCallEmitter::AddParameterFloatConst(double konst)
|
||||
{
|
||||
numparams++;
|
||||
emitters.push_back([=](VMFunctionBuilder *build) ->int
|
||||
|
|
@ -1000,7 +1000,7 @@ void EmitterArray::AddParameterFloatConst(double konst)
|
|||
});
|
||||
}
|
||||
|
||||
void EmitterArray::AddParameterIntConst(int konst)
|
||||
void FunctionCallEmitter::AddParameterIntConst(int konst)
|
||||
{
|
||||
numparams++;
|
||||
emitters.push_back([=](VMFunctionBuilder *build) ->int
|
||||
|
|
@ -1018,7 +1018,7 @@ void EmitterArray::AddParameterIntConst(int konst)
|
|||
});
|
||||
}
|
||||
|
||||
void EmitterArray::AddParameterStringConst(const FString &konst)
|
||||
void FunctionCallEmitter::AddParameterStringConst(const FString &konst)
|
||||
{
|
||||
numparams++;
|
||||
emitters.push_back([=](VMFunctionBuilder *build) ->int
|
||||
|
|
@ -1028,7 +1028,7 @@ void EmitterArray::AddParameterStringConst(const FString &konst)
|
|||
});
|
||||
}
|
||||
|
||||
int EmitterArray::EmitParameters(VMFunctionBuilder *build)
|
||||
ExpEmit FunctionCallEmitter::EmitCall(VMFunctionBuilder *build, TArray<ExpEmit> *ReturnRegs)
|
||||
{
|
||||
int paramcount = 0;
|
||||
for (auto &func : emitters)
|
||||
|
|
@ -1036,18 +1036,27 @@ int EmitterArray::EmitParameters(VMFunctionBuilder *build)
|
|||
paramcount += func(build);
|
||||
}
|
||||
assert(paramcount == numparams);
|
||||
return paramcount;
|
||||
}
|
||||
|
||||
if (virtualselfreg == -1)
|
||||
{
|
||||
build->Emit(OP_CALL_K, build->GetConstantAddress(target), paramcount, returns.Size());
|
||||
}
|
||||
else
|
||||
{
|
||||
ExpEmit funcreg(build, REGT_POINTER);
|
||||
|
||||
ExpEmit EmitterArray::EmitCall(VMFunctionBuilder *build)
|
||||
{
|
||||
int count = EmitParameters(build);
|
||||
build->Emit(OP_CALL_K, build->GetConstantAddress(target), count, returns.Size());
|
||||
if (returns.Size() == 0) return ExpEmit();
|
||||
build->Emit(OP_VTBL, funcreg.RegNum, virtualselfreg, target->VirtualIndex);
|
||||
build->Emit(OP_CALL, funcreg.RegNum, paramcount, returns.Size());
|
||||
}
|
||||
|
||||
ExpEmit out(build, returns[0]);
|
||||
build->Emit(OP_RESULT, 0, returns[0], out.RegNum);
|
||||
return out;
|
||||
assert(returns.Size() < 2 || ReturnRegs != nullptr);
|
||||
for (unsigned i = 0; i < returns.Size(); i++)
|
||||
{
|
||||
ExpEmit reg(build, returns[i].first, returns[i].second);
|
||||
build->Emit(OP_RESULT, 0, EncodeRegType(reg), reg.RegNum);
|
||||
if (ReturnRegs) ReturnRegs->Push(reg);
|
||||
else return reg;
|
||||
}
|
||||
return ExpEmit();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -163,13 +163,14 @@ extern FFunctionBuildList FunctionBuildList;
|
|||
//==========================================================================
|
||||
extern int EncodeRegType(ExpEmit reg);
|
||||
|
||||
class EmitterArray
|
||||
class FunctionCallEmitter
|
||||
{
|
||||
// std::function and TArray are not compatible so this has to use std::vector instead.
|
||||
std::vector<std::function<int(VMFunctionBuilder *)>> emitters;
|
||||
TArray<int> returns;
|
||||
TArray<std::pair<int, int>> returns;
|
||||
unsigned numparams = 0; // This counts the number of pushed elements, which can differ from the number of emitters with vectors.
|
||||
VMFunction *target = nullptr;
|
||||
int virtualselfreg = -1;
|
||||
|
||||
public:
|
||||
void AddParameter(VMFunctionBuilder *build, FxExpression *operand);
|
||||
|
|
@ -179,15 +180,15 @@ public:
|
|||
void AddParameterFloatConst(double konst);
|
||||
void AddParameterIntConst(int konst);
|
||||
void AddParameterStringConst(const FString &konst);
|
||||
int EmitParameters(VMFunctionBuilder *build);
|
||||
ExpEmit EmitCall(VMFunctionBuilder *build);
|
||||
void AddReturn(int regtype)
|
||||
ExpEmit EmitCall(VMFunctionBuilder *build, TArray<ExpEmit> *ReturnRegs = nullptr);
|
||||
void AddReturn(int regtype, int regcount = 1)
|
||||
{
|
||||
returns.Push(regtype);
|
||||
returns.Push({ regtype, regcount });
|
||||
}
|
||||
void AddTarget(VMFunction *func)
|
||||
void AddTarget(VMFunction *func, int virtreg = -1)
|
||||
{
|
||||
target = func;
|
||||
virtualselfreg = virtreg;
|
||||
}
|
||||
unsigned Count() const
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue