- 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:
Christoph Oelckers 2018-11-18 10:02:31 +01:00 committed by drfrag
parent a900390683
commit 6727301330
4 changed files with 67 additions and 102 deletions

View file

@ -645,7 +645,7 @@ static int GetLine (void)
// misc1 = vrange (arg +3), misc2 = hrange (arg+4)
static void CreateMushroomFunc(EmitterArray &emitters, int value1, int value2)
static void CreateMushroomFunc(FunctionCallEmitter &emitters, int value1, int value2)
{ // A_Mushroom
emitters.AddParameterPointerConst(PClass::FindClass("FatShot")); // itemtype
emitters.AddParameterIntConst(0); // numspawns
@ -655,7 +655,7 @@ static void CreateMushroomFunc(EmitterArray &emitters, int value1, int value2)
}
// misc1 = type (arg +0), misc2 = Z-pos (arg +2)
static void CreateSpawnFunc(EmitterArray &emitters, int value1, int value2)
static void CreateSpawnFunc(FunctionCallEmitter &emitters, int value1, int value2)
{ // A_SpawnItem
if (InfoNames[value1-1] == nullptr)
{
@ -670,13 +670,13 @@ static void CreateSpawnFunc(EmitterArray &emitters, int value1, int value2)
// misc1 = angle (in degrees) (arg +0 but factor in current actor angle too)
static void CreateTurnFunc(EmitterArray &emitters, int value1, int value2)
static void CreateTurnFunc(FunctionCallEmitter &emitters, int value1, int value2)
{ // A_Turn
emitters.AddParameterFloatConst(value1); // angle
}
// misc1 = angle (in degrees) (arg +0)
static void CreateFaceFunc(EmitterArray &emitters, int value1, int value2)
static void CreateFaceFunc(FunctionCallEmitter &emitters, int value1, int value2)
{ // A_FaceTarget
emitters.AddParameterFloatConst(value1); // angle
emitters.AddParameterIntConst(0); // flags
@ -684,7 +684,7 @@ static void CreateFaceFunc(EmitterArray &emitters, int value1, int value2)
}
// misc1 = damage, misc 2 = sound
static void CreateScratchFunc(EmitterArray &emitters, int value1, int value2)
static void CreateScratchFunc(FunctionCallEmitter &emitters, int value1, int value2)
{ // A_CustomMeleeAttack
emitters.AddParameterIntConst(value1); // damage
emitters.AddParameterIntConst(value2 ? (int)SoundMap[value2 - 1] : 0); // hit sound
@ -694,7 +694,7 @@ static void CreateScratchFunc(EmitterArray &emitters, int value1, int value2)
}
// misc1 = sound, misc2 = attenuation none (true) or normal (false)
static void CreatePlaySoundFunc(EmitterArray &emitters, int value1, int value2)
static void CreatePlaySoundFunc(FunctionCallEmitter &emitters, int value1, int value2)
{ // A_PlaySound
emitters.AddParameterIntConst(value1 ? (int)SoundMap[value1 - 1] : 0); // soundid
emitters.AddParameterIntConst(CHAN_BODY); // channel
@ -705,14 +705,14 @@ static void CreatePlaySoundFunc(EmitterArray &emitters, int value1, int value2)
}
// misc1 = state, misc2 = probability
static void CreateRandomJumpFunc(EmitterArray &emitters, int value1, int value2)
static void CreateRandomJumpFunc(FunctionCallEmitter &emitters, int value1, int value2)
{ // A_Jump
emitters.AddParameterIntConst(value2); // maxchance
emitters.AddParameterPointerConst(FindState(value1)); // jumpto
}
// misc1 = Boom linedef type, misc2 = sector tag
static void CreateLineEffectFunc(EmitterArray &emitters, int value1, int value2)
static void CreateLineEffectFunc(FunctionCallEmitter &emitters, int value1, int value2)
{ // A_LineEffect
// This is the second MBF codepointer that couldn't be translated easily.
// Calling P_TranslateLineDef() here was a simple matter, as was adding an
@ -724,7 +724,7 @@ static void CreateLineEffectFunc(EmitterArray &emitters, int value1, int value2)
}
// No misc, but it's basically A_Explode with an added effect
static void CreateNailBombFunc(EmitterArray &emitters, int value1, int value2)
static void CreateNailBombFunc(FunctionCallEmitter &emitters, int value1, int value2)
{ // A_Explode
// This one does not actually have MBF-style parameters. But since
// we're aliasing it to an extension of A_Explode...
@ -740,7 +740,7 @@ static void CreateNailBombFunc(EmitterArray &emitters, int value1, int value2)
}
// This array must be in sync with the Aliases array in DEHSUPP.
static void (*MBFCodePointerFactories[])(EmitterArray&, int, int) =
static void (*MBFCodePointerFactories[])(FunctionCallEmitter&, int, int) =
{
// Die and Detonate are not in this list because these codepointers have
// no dehacked arguments and therefore do not need special handling.
@ -787,7 +787,7 @@ void SetDehParams(FState *state, int codepointer)
// self, stateowner, state (all are pointers)
buildit.Registers[REGT_POINTER].Get(numargs);
// Emit code to pass the standard action function parameters.
EmitterArray emitters;
FunctionCallEmitter emitters;
for (int i = 0; i < numargs; i++)
{
emitters.AddParameterPointer(i, false);

View file

@ -5502,7 +5502,7 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build)
assert(min && max);
callfunc = ((PSymbolVMFunction *)sym)->Function;
EmitterArray emitters;
FunctionCallEmitter emitters;
emitters.AddParameterPointerConst(rng);
emitters.AddParameter(build, min);
@ -5609,7 +5609,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);
@ -5730,7 +5730,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);
@ -5808,7 +5808,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);
@ -5880,7 +5880,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);
@ -8552,7 +8552,7 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
{
unsigned i = 0;
EmitterArray emitters;
FunctionCallEmitter emitters;
emitters.AddParameterIntConst(abs(Special)); // pass special number
emitters.AddParameter(build, Self);
@ -8996,7 +8996,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)
@ -9067,63 +9067,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);
}
//==========================================================================
@ -10634,7 +10589,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);
@ -10829,7 +10784,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));
@ -10938,7 +10893,7 @@ ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
{
ExpEmit clsname = basex->Emit(build);
EmitterArray emitters;
FunctionCallEmitter emitters;
emitters.AddParameter(clsname, false);
emitters.AddParameterPointerConst(desttype);
@ -11324,7 +11279,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);
@ -11351,7 +11306,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);

View file

@ -934,7 +934,7 @@ void FFunctionBuildList::DumpJit()
}
void EmitterArray::AddParameter(VMFunctionBuilder *build, FxExpression *operand)
void FunctionCallEmitter::AddParameter(VMFunctionBuilder *build, FxExpression *operand)
{
ExpEmit where = operand->Emit(build);
@ -961,7 +961,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
@ -973,7 +973,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
@ -983,7 +983,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
@ -993,7 +993,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
@ -1003,7 +1003,7 @@ void EmitterArray::AddParameterFloatConst(double konst)
});
}
void EmitterArray::AddParameterIntConst(int konst)
void FunctionCallEmitter::AddParameterIntConst(int konst)
{
numparams++;
emitters.push_back([=](VMFunctionBuilder *build) ->int
@ -1021,7 +1021,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
@ -1031,7 +1031,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)
@ -1039,18 +1039,27 @@ int EmitterArray::EmitParameters(VMFunctionBuilder *build)
paramcount += func(build);
}
assert(paramcount == numparams);
return paramcount;
}
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();
ExpEmit out(build, returns[0]);
build->Emit(OP_RESULT, 0, returns[0], out.RegNum);
return out;
if (virtualselfreg == -1)
{
build->Emit(OP_CALL_K, build->GetConstantAddress(target), paramcount, returns.Size());
}
else
{
ExpEmit funcreg(build, REGT_POINTER);
build->Emit(OP_VTBL, funcreg.RegNum, virtualselfreg, target->VirtualIndex);
build->Emit(OP_CALL, funcreg.RegNum, paramcount, returns.Size());
}
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();
}

View file

@ -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
{