mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-03-17 16:32:20 +00:00
Merge branch 'asmjit' of https://github.com/coelckers/gzdoom
This commit is contained in:
commit
58407c6c8e
5 changed files with 276 additions and 209 deletions
|
@ -634,126 +634,102 @@ static int GetLine (void)
|
|||
|
||||
|
||||
// misc1 = vrange (arg +3), misc2 = hrange (arg+4)
|
||||
static int CreateMushroomFunc(VMFunctionBuilder &buildit, int value1, int value2)
|
||||
static void CreateMushroomFunc(EmitterArray &emitters, int value1, int value2)
|
||||
{ // A_Mushroom
|
||||
int typereg = buildit.GetConstantAddress(PClass::FindClass("FatShot"));
|
||||
buildit.Emit(OP_PARAM, REGT_POINTER | REGT_KONST, typereg); // itemtype
|
||||
buildit.Emit(OP_PARAMI, 0); // numspawns
|
||||
buildit.Emit(OP_PARAMI, 1); // flag
|
||||
// vrange
|
||||
buildit.Emit(OP_PARAM, REGT_FLOAT | REGT_KONST, buildit.GetConstantFloat(value1? DEHToDouble(value1) : 4.0));
|
||||
// hrange
|
||||
buildit.Emit(OP_PARAM, REGT_FLOAT | REGT_KONST, buildit.GetConstantFloat(value2? DEHToDouble(value2) : 0.5));
|
||||
return 5;
|
||||
emitters.AddParameterPointerConst(PClass::FindClass("FatShot")); // itemtype
|
||||
emitters.AddParameterIntConst(0); // numspawns
|
||||
emitters.AddParameterIntConst(1); // flag MSF_Classic
|
||||
emitters.AddParameterFloatConst(value1? DEHToDouble(value1) : 4.0); // vrange
|
||||
emitters.AddParameterFloatConst(value2? DEHToDouble(value2) : 0.5); // hrange
|
||||
}
|
||||
|
||||
// misc1 = type (arg +0), misc2 = Z-pos (arg +2)
|
||||
static int CreateSpawnFunc(VMFunctionBuilder &buildit, int value1, int value2)
|
||||
static void CreateSpawnFunc(EmitterArray &emitters, int value1, int value2)
|
||||
{ // A_SpawnItem
|
||||
if (InfoNames[value1-1] == NULL)
|
||||
if (InfoNames[value1-1] == nullptr)
|
||||
{
|
||||
I_Error("No class found for dehackednum %d!\n", value1+1);
|
||||
return 0;
|
||||
}
|
||||
int typereg = buildit.GetConstantAddress(InfoNames[value1-1]);
|
||||
int heightreg = buildit.GetConstantFloat(value2);
|
||||
int distreg = buildit.GetConstantFloat(0);
|
||||
|
||||
buildit.Emit(OP_PARAM, REGT_POINTER | REGT_KONST, typereg); // itemtype
|
||||
buildit.Emit(OP_PARAM, REGT_FLOAT | REGT_KONST, distreg); // distance
|
||||
buildit.Emit(OP_PARAM, REGT_FLOAT | REGT_KONST, heightreg); // height
|
||||
buildit.Emit(OP_PARAMI, 0); // useammo
|
||||
buildit.Emit(OP_PARAMI, 0); // transfer_translation
|
||||
return 5;
|
||||
emitters.AddParameterPointerConst(InfoNames[value1-1]); // itemtype
|
||||
emitters.AddParameterFloatConst(value2); // distance
|
||||
emitters.AddParameterFloatConst(0); // height
|
||||
emitters.AddParameterIntConst(0); // useammo
|
||||
emitters.AddParameterIntConst(0); // transfer_translation
|
||||
}
|
||||
|
||||
|
||||
// misc1 = angle (in degrees) (arg +0 but factor in current actor angle too)
|
||||
static int CreateTurnFunc(VMFunctionBuilder &buildit, int value1, int value2)
|
||||
static void CreateTurnFunc(EmitterArray &emitters, int value1, int value2)
|
||||
{ // A_Turn
|
||||
buildit.Emit(OP_PARAM, REGT_FLOAT | REGT_KONST, buildit.GetConstantFloat(value1)); // angle
|
||||
return 1;
|
||||
emitters.AddParameterFloatConst(value1); // angle
|
||||
}
|
||||
|
||||
// misc1 = angle (in degrees) (arg +0)
|
||||
static int CreateFaceFunc(VMFunctionBuilder &buildit, int value1, int value2)
|
||||
static void CreateFaceFunc(EmitterArray &emitters, int value1, int value2)
|
||||
{ // A_FaceTarget
|
||||
buildit.Emit(OP_PARAM, REGT_FLOAT | REGT_KONST, buildit.GetConstantFloat(value1)); // angle
|
||||
buildit.Emit(OP_PARAMI, 0); // flags
|
||||
buildit.Emit(OP_PARAMI, AAPTR_DEFAULT); // ptr
|
||||
return 3;
|
||||
emitters.AddParameterFloatConst(value1); // angle
|
||||
emitters.AddParameterIntConst(0); // flags
|
||||
emitters.AddParameterIntConst(AAPTR_DEFAULT); // ptr
|
||||
}
|
||||
|
||||
// misc1 = damage, misc 2 = sound
|
||||
static int CreateScratchFunc(VMFunctionBuilder &buildit, int value1, int value2)
|
||||
static void CreateScratchFunc(EmitterArray &emitters, int value1, int value2)
|
||||
{ // A_CustomMeleeAttack
|
||||
buildit.EmitParamInt(value1); // damage
|
||||
buildit.EmitParamInt(value2? SoundMap[value2 - 1] : 0); // hit sound
|
||||
buildit.Emit(OP_PARAMI, 0); // miss sound
|
||||
buildit.Emit(OP_PARAMI, NAME_None); // damage type
|
||||
buildit.Emit(OP_PARAMI, true); // bleed
|
||||
return 5;
|
||||
emitters.AddParameterIntConst(value1); // damage
|
||||
emitters.AddParameterIntConst(value2 ? (int)SoundMap[value2 - 1] : 0); // hit sound
|
||||
emitters.AddParameterIntConst(0); // miss sound
|
||||
emitters.AddParameterIntConst(NAME_None); // damage type
|
||||
emitters.AddParameterIntConst(true); // bleed
|
||||
}
|
||||
|
||||
// misc1 = sound, misc2 = attenuation none (true) or normal (false)
|
||||
static int CreatePlaySoundFunc(VMFunctionBuilder &buildit, int value1, int value2)
|
||||
static void CreatePlaySoundFunc(EmitterArray &emitters, int value1, int value2)
|
||||
{ // A_PlaySound
|
||||
int float1 = buildit.GetConstantFloat(1);
|
||||
int attenreg = buildit.GetConstantFloat(value2 ? ATTN_NONE : ATTN_NORM);
|
||||
|
||||
buildit.EmitParamInt(SoundMap[value1-1]); // soundid
|
||||
buildit.Emit(OP_PARAMI, CHAN_BODY); // channel
|
||||
buildit.Emit(OP_PARAM, REGT_FLOAT | REGT_KONST, float1); // volume
|
||||
buildit.Emit(OP_PARAMI, false); // looping
|
||||
buildit.Emit(OP_PARAM, REGT_FLOAT | REGT_KONST, attenreg); // attenuation
|
||||
buildit.Emit(OP_PARAMI, false); // local
|
||||
return 6;
|
||||
emitters.AddParameterIntConst(value1 ? (int)SoundMap[value1 - 1] : 0); // soundid
|
||||
emitters.AddParameterIntConst(CHAN_BODY); // channel
|
||||
emitters.AddParameterFloatConst(1); // volume
|
||||
emitters.AddParameterIntConst(false); // looping
|
||||
emitters.AddParameterFloatConst(value2 ? ATTN_NONE : ATTN_NORM); // attenuation
|
||||
emitters.AddParameterIntConst(false); // local
|
||||
}
|
||||
|
||||
// misc1 = state, misc2 = probability
|
||||
static int CreateRandomJumpFunc(VMFunctionBuilder &buildit, int value1, int value2)
|
||||
static void CreateRandomJumpFunc(EmitterArray &emitters, int value1, int value2)
|
||||
{ // A_Jump
|
||||
int statereg = buildit.GetConstantAddress(FindState(value1));
|
||||
|
||||
buildit.EmitParamInt(value2); // maxchance
|
||||
buildit.Emit(OP_PARAM, REGT_POINTER | REGT_KONST, statereg); // jumpto
|
||||
return 2;
|
||||
emitters.AddParameterIntConst(value2); // maxchance
|
||||
emitters.AddParameterPointerConst(FindState(value1)); // jumpto
|
||||
}
|
||||
|
||||
// misc1 = Boom linedef type, misc2 = sector tag
|
||||
static int CreateLineEffectFunc(VMFunctionBuilder &buildit, int value1, int value2)
|
||||
static void CreateLineEffectFunc(EmitterArray &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
|
||||
// extra parameter to A_CallSpecial so as to replicate the LINEDONE stuff,
|
||||
// but unfortunately DEHACKED lumps are processed before the map translation
|
||||
// arrays are initialized so this didn't work.
|
||||
buildit.EmitParamInt(value1); // special
|
||||
buildit.EmitParamInt(value2); // tag
|
||||
return 2;
|
||||
emitters.AddParameterIntConst(value1); // special
|
||||
emitters.AddParameterIntConst(value2); // tag
|
||||
}
|
||||
|
||||
// No misc, but it's basically A_Explode with an added effect
|
||||
static int CreateNailBombFunc(VMFunctionBuilder &buildit, int value1, int value2)
|
||||
static void CreateNailBombFunc(EmitterArray &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...
|
||||
int typereg = buildit.GetConstantAddress(PClass::FindClass(NAME_BulletPuff));
|
||||
buildit.Emit(OP_PARAMI, -1); // damage
|
||||
buildit.Emit(OP_PARAMI, -1); // distance
|
||||
buildit.Emit(OP_PARAMI, 1); // flags (1=XF_HURTSOURCE)
|
||||
buildit.Emit(OP_PARAMI, 0); // alert
|
||||
buildit.Emit(OP_PARAMI, 0); // fulldamagedistance
|
||||
buildit.Emit(OP_PARAMI, 30); // nails
|
||||
buildit.Emit(OP_PARAMI, 10); // naildamage
|
||||
buildit.Emit(OP_PARAM, REGT_POINTER | REGT_KONST, typereg); // itemtype
|
||||
buildit.Emit(OP_PARAMI, NAME_None); // damage type
|
||||
|
||||
return 9;
|
||||
emitters.AddParameterIntConst(-1); // damage
|
||||
emitters.AddParameterIntConst(-1); // distance
|
||||
emitters.AddParameterIntConst(1); // flags (1=XF_HURTSOURCE)
|
||||
emitters.AddParameterIntConst(0); // alert
|
||||
emitters.AddParameterIntConst(0); // fulldamagedistance
|
||||
emitters.AddParameterIntConst(30); // nails
|
||||
emitters.AddParameterIntConst(10); // naildamage
|
||||
emitters.AddParameterPointerConst(PClass::FindClass(NAME_BulletPuff)); // itemtype
|
||||
emitters.AddParameterIntConst(NAME_None); // damage type
|
||||
}
|
||||
|
||||
// This array must be in sync with the Aliases array in DEHSUPP.
|
||||
static int (*MBFCodePointerFactories[])(VMFunctionBuilder&, int, int) =
|
||||
static void (*MBFCodePointerFactories[])(EmitterArray&, int, int) =
|
||||
{
|
||||
// Die and Detonate are not in this list because these codepointers have
|
||||
// no dehacked arguments and therefore do not need special handling.
|
||||
|
@ -800,13 +776,15 @@ 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;
|
||||
for (int i = 0; i < numargs; i++)
|
||||
{
|
||||
buildit.Emit(OP_PARAM, REGT_POINTER, i);
|
||||
emitters.AddParameterPointer(i, false);
|
||||
}
|
||||
// Emit code for action parameters.
|
||||
int argcount = MBFCodePointerFactories[codepointer](buildit, value1, value2);
|
||||
buildit.Emit(OP_TAIL_K, buildit.GetConstantAddress(sym->Variants[0].Implementation), numargs + argcount, 0);
|
||||
MBFCodePointerFactories[codepointer](emitters, value1, value2);
|
||||
int count = emitters.EmitParameters(&buildit);
|
||||
buildit.Emit(OP_TAIL_K, buildit.GetConstantAddress(sym->Variants[0].Implementation), count, 0);
|
||||
// Attach it to the state.
|
||||
VMScriptFunction *sfunc = new VMScriptFunction;
|
||||
buildit.MakeFunction(sfunc);
|
||||
|
|
|
@ -485,7 +485,7 @@ PPrototype *FxExpression::ReturnProto()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static int EncodeRegType(ExpEmit reg)
|
||||
int EncodeRegType(ExpEmit reg)
|
||||
{
|
||||
int regtype = reg.RegType;
|
||||
if (reg.Fixed && reg.Target)
|
||||
|
@ -508,36 +508,6 @@ static int EncodeRegType(ExpEmit reg)
|
|||
return regtype;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static int EmitParameter(VMFunctionBuilder *build, FxExpression *operand, const FScriptPosition &pos, TArray<ExpEmit> *tempstrings = nullptr)
|
||||
{
|
||||
ExpEmit where = operand->Emit(build);
|
||||
|
||||
if (where.RegType == REGT_NIL)
|
||||
{
|
||||
pos.Message(MSG_ERROR, "Attempted to pass a non-value");
|
||||
build->Emit(OP_PARAM, where.RegType, where.RegNum);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
build->Emit(OP_PARAM, EncodeRegType(where), where.RegNum);
|
||||
if (tempstrings != nullptr && where.RegType == REGT_STRING && !where.Fixed && !where.Konst)
|
||||
{
|
||||
tempstrings->Push(where); // keep temp strings until after the function call.
|
||||
}
|
||||
else
|
||||
{
|
||||
where.Free(build);
|
||||
}
|
||||
return where.RegCount;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -5539,10 +5509,13 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build)
|
|||
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);
|
||||
|
||||
build->Emit(OP_PARAM, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng));
|
||||
EmitParameter(build, min, ScriptPosition);
|
||||
EmitParameter(build, max, ScriptPosition);
|
||||
build->Emit(opcode, build->GetConstantAddress(callfunc), 3, 1);
|
||||
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)
|
||||
{
|
||||
|
@ -5653,10 +5626,12 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build)
|
|||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
build->Emit(OP_PARAM, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng));
|
||||
build->EmitParamInt(0);
|
||||
build->EmitParamInt(choices.Size() - 1);
|
||||
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), 3, 1);
|
||||
EmitterArray emitters;
|
||||
emitters.AddParameterPointerConst(rng);
|
||||
emitters.AddParameterIntConst(0);
|
||||
emitters.AddParameterIntConst(choices.Size() - 1);
|
||||
int count = emitters.EmitParameters(build);
|
||||
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), count, 1);
|
||||
|
||||
ExpEmit resultreg(build, REGT_INT);
|
||||
build->Emit(OP_RESULT, 0, REGT_INT, resultreg.RegNum);
|
||||
|
@ -5775,10 +5750,12 @@ ExpEmit FxFRandom::Emit(VMFunctionBuilder *build)
|
|||
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);
|
||||
|
||||
build->Emit(OP_PARAM, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng));
|
||||
EmitParameter(build, min, ScriptPosition);
|
||||
EmitParameter(build, max, ScriptPosition);
|
||||
build->Emit(opcode, build->GetConstantAddress(callfunc), 3, 1);
|
||||
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)
|
||||
{
|
||||
|
@ -5877,9 +5854,12 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build)
|
|||
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);
|
||||
|
||||
build->Emit(OP_PARAM, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng));
|
||||
EmitParameter(build, mask, ScriptPosition);
|
||||
build->Emit(opcode, build->GetConstantAddress(callfunc), 2, 1);
|
||||
EmitterArray emitters;
|
||||
|
||||
emitters.AddParameterPointerConst(rng);
|
||||
emitters.AddParameter(build, mask);
|
||||
int count = emitters.EmitParameters(build);
|
||||
build->Emit(opcode, build->GetConstantAddress(callfunc), count, 1);
|
||||
|
||||
if (EmitTail)
|
||||
{
|
||||
|
@ -5960,9 +5940,12 @@ ExpEmit FxRandomSeed::Emit(VMFunctionBuilder *build)
|
|||
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);
|
||||
|
||||
build->Emit(OP_PARAM, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng));
|
||||
EmitParameter(build, seed, ScriptPosition);
|
||||
build->Emit(opcode, build->GetConstantAddress(callfunc), 2, 0);
|
||||
EmitterArray emitters;
|
||||
|
||||
emitters.AddParameterPointerConst(rng);
|
||||
emitters.AddParameter(build, seed);
|
||||
int count = emitters.EmitParameters(build);
|
||||
build->Emit(opcode, build->GetConstantAddress(callfunc), count, 0);
|
||||
|
||||
ExpEmit call;
|
||||
if (EmitTail) call.Final = true;
|
||||
|
@ -8642,10 +8625,13 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
unsigned i = 0;
|
||||
|
||||
build->Emit(OP_PARAMI, abs(Special)); // pass special number
|
||||
EmitterArray emitters;
|
||||
|
||||
emitters.AddParameterIntConst(abs(Special)); // pass special number
|
||||
|
||||
ExpEmit selfemit(Self->Emit(build));
|
||||
build->Emit(OP_PARAM, selfemit.Konst ? REGT_POINTER | REGT_KONST : REGT_POINTER, selfemit.RegNum); // pass special number
|
||||
emitters.AddParameterPointer(selfemit.RegNum, selfemit.Konst);
|
||||
|
||||
for (; i < ArgList.Size(); ++i)
|
||||
{
|
||||
FxExpression *argex = ArgList[i];
|
||||
|
@ -8653,20 +8639,18 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
assert(argex->ValueType == TypeName);
|
||||
assert(argex->isConstant());
|
||||
build->EmitParamInt(-static_cast<FxConstant *>(argex)->GetValue().GetName());
|
||||
emitters.AddParameterIntConst(-static_cast<FxConstant *>(argex)->GetValue().GetName());
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(argex->ValueType->GetRegType() == REGT_INT);
|
||||
if (argex->isConstant())
|
||||
{
|
||||
build->EmitParamInt(static_cast<FxConstant *>(argex)->GetValue().GetInt());
|
||||
emitters.AddParameterIntConst(static_cast<FxConstant *>(argex)->GetValue().GetInt());
|
||||
}
|
||||
else
|
||||
{
|
||||
ExpEmit arg(argex->Emit(build));
|
||||
build->Emit(OP_PARAM, arg.RegType, arg.RegNum);
|
||||
arg.Free(build);
|
||||
emitters.AddParameter(build, argex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8681,16 +8665,18 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
|
|||
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), 2 + i, 0);
|
||||
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), 2 + i, 1);
|
||||
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), count, 1);
|
||||
build->Emit(OP_RESULT, 0, REGT_INT, dest.RegNum);
|
||||
return dest;
|
||||
}
|
||||
|
@ -9079,8 +9065,6 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
|
|||
|
||||
ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
TArray<ExpEmit> tempstrings;
|
||||
|
||||
assert(build->Registers[REGT_POINTER].GetMostUsed() >= build->NumImplicits);
|
||||
int count = 0;
|
||||
|
||||
|
@ -9093,7 +9077,6 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
ArgList.DeleteAndClear();
|
||||
ArgList.ShrinkToFit();
|
||||
for (auto & exp : tempstrings) exp.Free(build);
|
||||
return reg;
|
||||
}
|
||||
}
|
||||
|
@ -9102,6 +9085,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
|||
bool staticcall = ((vmfunc->VarFlags & VARF_Final) || vmfunc->VirtualIndex == ~0u || NoVirtual);
|
||||
|
||||
count = 0;
|
||||
EmitterArray emitters;
|
||||
// Emit code to pass implied parameters
|
||||
ExpEmit selfemit;
|
||||
if (Function->Variants[0].Flags & VARF_Method)
|
||||
|
@ -9128,64 +9112,51 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
|||
}
|
||||
}
|
||||
|
||||
if ((selfemit.Fixed && selfemit.Target) || selfemit.RegType == REGT_STRING)
|
||||
{
|
||||
// Address of a local variable.
|
||||
build->Emit(OP_PARAM, selfemit.RegType | REGT_ADDROF, selfemit.RegNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
build->Emit(OP_PARAM, selfemit.RegType, selfemit.RegNum);
|
||||
}
|
||||
count += 1;
|
||||
emitters.AddParameter(selfemit, (selfemit.Fixed && selfemit.Target) || selfemit.RegType == REGT_STRING);
|
||||
if (Function->Variants[0].Flags & VARF_Action)
|
||||
{
|
||||
static_assert(NAP == 3, "This code needs to be updated if NAP changes");
|
||||
if (build->NumImplicits == NAP && selfemit.RegNum == 0) // only pass this function's stateowner and stateinfo if the subfunction is run in self's context.
|
||||
{
|
||||
build->Emit(OP_PARAM, REGT_POINTER, 1);
|
||||
build->Emit(OP_PARAM, REGT_POINTER, 2);
|
||||
emitters.AddParameterPointer(1, false);
|
||||
emitters.AddParameterPointer(2, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// pass self as stateowner, otherwise all attempts of the subfunction to retrieve a state from a name would fail.
|
||||
build->Emit(OP_PARAM, selfemit.RegType, selfemit.RegNum);
|
||||
build->Emit(OP_PARAM, REGT_POINTER | REGT_KONST, build->GetConstantAddress(nullptr));
|
||||
emitters.AddParameter(selfemit, (selfemit.Fixed && selfemit.Target) || selfemit.RegType == REGT_STRING);
|
||||
emitters.AddParameterPointerConst(nullptr);
|
||||
}
|
||||
count += 2;
|
||||
}
|
||||
if (staticcall) selfemit.Free(build);
|
||||
}
|
||||
else staticcall = true;
|
||||
// Emit code to pass explicit parameters
|
||||
for (unsigned i = 0; i < ArgList.Size(); ++i)
|
||||
{
|
||||
count += EmitParameter(build, ArgList[i], ScriptPosition, &tempstrings);
|
||||
emitters.AddParameter(build, ArgList[i]);
|
||||
}
|
||||
// Complete the parameter list from the defaults.
|
||||
auto &defaults = Function->Variants[0].Implementation->DefaultArgs;
|
||||
for (unsigned i = count; i < defaults.Size(); i++)
|
||||
for (unsigned i = emitters.Count(); i < defaults.Size(); i++)
|
||||
{
|
||||
FxConstant *constant;
|
||||
switch (defaults[i].Type)
|
||||
{
|
||||
default:
|
||||
case REGT_INT:
|
||||
constant = new FxConstant(defaults[i].i, ScriptPosition);
|
||||
emitters.AddParameterIntConst(defaults[i].i);
|
||||
break;
|
||||
case REGT_FLOAT:
|
||||
constant = new FxConstant(defaults[i].f, ScriptPosition);
|
||||
emitters.AddParameterFloatConst(defaults[i].f);
|
||||
break;
|
||||
case REGT_POINTER:
|
||||
constant = new FxConstant(defaults[i].a, ScriptPosition);
|
||||
emitters.AddParameterPointerConst(defaults[i].a);
|
||||
break;
|
||||
case REGT_STRING:
|
||||
constant = new FxConstant(defaults[i].s(), ScriptPosition);
|
||||
emitters.AddParameterStringConst(defaults[i].s());
|
||||
break;
|
||||
}
|
||||
count += EmitParameter(build, constant, ScriptPosition, &tempstrings);
|
||||
delete constant;
|
||||
}
|
||||
count = emitters.EmitParameters(build);
|
||||
|
||||
ArgList.DeleteAndClear();
|
||||
ArgList.ShrinkToFit();
|
||||
|
@ -9200,7 +9171,6 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
|||
build->Emit(OP_TAIL_K, funcaddr, count, 0);
|
||||
ExpEmit call;
|
||||
call.Final = true;
|
||||
for (auto & exp : tempstrings) exp.Free(build);
|
||||
return call;
|
||||
}
|
||||
else if (vmfunc->Proto->ReturnTypes.Size() > 0)
|
||||
|
@ -9211,13 +9181,11 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
|||
else
|
||||
{ // Call, expecting no results
|
||||
build->Emit(OP_CALL_K, funcaddr, count, 0);
|
||||
for (auto & exp : tempstrings) exp.Free(build);
|
||||
return ExpEmit();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
selfemit.Free(build);
|
||||
ExpEmit funcreg(build, REGT_POINTER);
|
||||
|
||||
build->Emit(OP_VTBL, funcreg.RegNum, selfemit.RegNum, vmfunc->VirtualIndex);
|
||||
|
@ -9226,7 +9194,6 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
|||
build->Emit(OP_TAIL, funcreg.RegNum, count, 0);
|
||||
ExpEmit call;
|
||||
call.Final = true;
|
||||
for (auto & exp : tempstrings) exp.Free(build);
|
||||
return call;
|
||||
}
|
||||
else if (vmfunc->Proto->ReturnTypes.Size() > 0)
|
||||
|
@ -9237,7 +9204,6 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
|||
else
|
||||
{ // Call, expecting no results
|
||||
build->Emit(OP_CALL, funcreg.RegNum, count, 0);
|
||||
for (auto & exp : tempstrings) exp.Free(build);
|
||||
return ExpEmit();
|
||||
}
|
||||
}
|
||||
|
@ -9247,7 +9213,6 @@ handlereturns:
|
|||
// 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);
|
||||
for (auto & exp : tempstrings) exp.Free(build);
|
||||
return reg;
|
||||
}
|
||||
else
|
||||
|
@ -9261,7 +9226,6 @@ handlereturns:
|
|||
ReturnRegs.Push(reg);
|
||||
}
|
||||
}
|
||||
for (auto & exp : tempstrings) exp.Free(build);
|
||||
return ExpEmit();
|
||||
}
|
||||
|
||||
|
@ -10773,9 +10737,10 @@ 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));
|
||||
build->Emit(OP_PARAM, reg.RegType, reg.RegNum);
|
||||
build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mDestructor), 1, 0);
|
||||
reg.Free(build);
|
||||
EmitterArray emitters;
|
||||
emitters.AddParameter(reg, false);
|
||||
int count = emitters.EmitParameters(build);
|
||||
build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mDestructor), count, 0);
|
||||
}
|
||||
|
||||
// If we return nothing, use a regular RET opcode.
|
||||
|
@ -10970,8 +10935,9 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
|
|||
ExpEmit clsname = basex->Emit(build);
|
||||
assert(!clsname.Konst);
|
||||
ExpEmit dest(build, REGT_POINTER);
|
||||
build->Emit(OP_PARAM, clsname.RegType, clsname.RegNum);
|
||||
build->Emit(OP_PARAM, REGT_POINTER | REGT_KONST, build->GetConstantAddress(const_cast<PClass *>(desttype)));
|
||||
EmitterArray emitters;
|
||||
emitters.AddParameter(clsname, false);
|
||||
emitters.AddParameterPointerConst(const_cast<PClass *>(desttype));
|
||||
|
||||
// Call the BuiltinNameToClass function to convert from 'name' to class.
|
||||
VMFunction *callfunc;
|
||||
|
@ -10981,9 +10947,9 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
|
|||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), 2, 1);
|
||||
int count = emitters.EmitParameters(build);
|
||||
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), count, 1);
|
||||
build->Emit(OP_RESULT, 0, REGT_POINTER, dest.RegNum);
|
||||
clsname.Free(build);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
@ -11079,8 +11045,10 @@ ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
ExpEmit clsname = basex->Emit(build);
|
||||
|
||||
build->Emit(OP_PARAM, clsname.RegType, clsname.RegNum);
|
||||
build->Emit(OP_PARAM, REGT_POINTER | REGT_KONST, build->GetConstantAddress(desttype));
|
||||
EmitterArray emitters;
|
||||
|
||||
emitters.AddParameter(clsname, false);
|
||||
emitters.AddParameterPointerConst(desttype);
|
||||
|
||||
VMFunction *callfunc;
|
||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinClassCast, BuiltinClassCast);
|
||||
|
@ -11088,9 +11056,9 @@ ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
|
|||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
clsname.Free(build);
|
||||
ExpEmit dest(build, REGT_POINTER);
|
||||
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), 2, 1);
|
||||
int count = emitters.EmitParameters(build);
|
||||
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), count, 1);
|
||||
build->Emit(OP_RESULT, 0, REGT_POINTER, dest.RegNum);
|
||||
return dest;
|
||||
}
|
||||
|
@ -11465,9 +11433,10 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
ExpEmit reg(build, REGT_POINTER);
|
||||
build->Emit(OP_ADDA_RK, reg.RegNum, build->FramePointer.RegNum, build->GetConstantInt(StackOffset));
|
||||
build->Emit(OP_PARAM, reg.RegType, reg.RegNum);
|
||||
build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mConstructor), 1, 0);
|
||||
reg.Free(build);
|
||||
EmitterArray emitters;
|
||||
emitters.AddParameter(reg, false);
|
||||
int count = emitters.EmitParameters(build);
|
||||
build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mConstructor), count, 0);
|
||||
}
|
||||
if (pstr->mDestructor != nullptr) build->ConstructedStructs.Push(this);
|
||||
}
|
||||
|
@ -11491,9 +11460,10 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build)
|
|||
{
|
||||
ExpEmit reg(build, REGT_POINTER);
|
||||
build->Emit(OP_ADDA_RK, reg.RegNum, build->FramePointer.RegNum, build->GetConstantInt(StackOffset));
|
||||
build->Emit(OP_PARAM, reg.RegType, reg.RegNum);
|
||||
build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mDestructor), 1, 0);
|
||||
reg.Free(build);
|
||||
EmitterArray emitters;
|
||||
emitters.AddParameter(reg, false);
|
||||
int count = emitters.EmitParameters(build);
|
||||
build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mDestructor), count, 0);
|
||||
}
|
||||
build->ConstructedStructs.Delete(build->ConstructedStructs.Find(this));
|
||||
}
|
||||
|
|
|
@ -654,28 +654,6 @@ size_t VMFunctionBuilder::Emit(int opcode, int opabc)
|
|||
return Code.Push(op);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// VMFunctionBuilder :: EmitParamInt
|
||||
//
|
||||
// Passes a constant integer parameter, using either PARAMI and an immediate
|
||||
// value or PARAM and a constant register, as appropriate.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
size_t VMFunctionBuilder::EmitParamInt(int value)
|
||||
{
|
||||
// Immediates for PARAMI must fit in 24 bits.
|
||||
if (((value << 8) >> 8) == value)
|
||||
{
|
||||
return Emit(OP_PARAMI, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Emit(OP_PARAM, REGT_INT | REGT_KONST, GetConstantInt(value));
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// VMFunctionBuilder :: EmitLoadInt
|
||||
|
@ -951,3 +929,112 @@ void FFunctionBuildList::DumpJit()
|
|||
|
||||
fclose(dump);
|
||||
}
|
||||
|
||||
|
||||
void EmitterArray::AddParameter(VMFunctionBuilder *build, FxExpression *operand)
|
||||
{
|
||||
ExpEmit where = operand->Emit(build);
|
||||
|
||||
if (where.RegType == REGT_NIL)
|
||||
{
|
||||
operand->ScriptPosition.Message(MSG_ERROR, "Attempted to pass a non-value");
|
||||
}
|
||||
numparams += where.RegCount;
|
||||
|
||||
emitters.push_back([=](VMFunctionBuilder *build) -> int
|
||||
{
|
||||
auto op = where;
|
||||
if (op.RegType == REGT_NIL)
|
||||
{
|
||||
build->Emit(OP_PARAM, op.RegType, op.RegNum);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
build->Emit(OP_PARAM, EncodeRegType(op), op.RegNum);
|
||||
op.Free(build);
|
||||
return op.RegCount;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void EmitterArray::AddParameter(ExpEmit &emit, bool reference)
|
||||
{
|
||||
numparams += emit.RegCount;
|
||||
emitters.push_back([=](VMFunctionBuilder *build) ->int
|
||||
{
|
||||
build->Emit(OP_PARAM, emit.RegType + (reference * REGT_ADDROF), emit.RegNum);
|
||||
auto op = emit;
|
||||
op.Free(build);
|
||||
return emit.RegCount;
|
||||
});
|
||||
}
|
||||
|
||||
void EmitterArray::AddParameterPointerConst(void *konst)
|
||||
{
|
||||
numparams++;
|
||||
emitters.push_back([=](VMFunctionBuilder *build) ->int
|
||||
{
|
||||
build->Emit(OP_PARAM, REGT_POINTER | REGT_KONST, build->GetConstantAddress(konst));
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
void EmitterArray::AddParameterPointer(int index, bool konst)
|
||||
{
|
||||
numparams++;
|
||||
emitters.push_back([=](VMFunctionBuilder *build) ->int
|
||||
{
|
||||
build->Emit(OP_PARAM, konst ? REGT_POINTER | REGT_KONST : REGT_POINTER, index);
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
void EmitterArray::AddParameterFloatConst(double konst)
|
||||
{
|
||||
numparams++;
|
||||
emitters.push_back([=](VMFunctionBuilder *build) ->int
|
||||
{
|
||||
build->Emit(OP_PARAM, REGT_FLOAT | REGT_KONST, build->GetConstantFloat(konst));
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
void EmitterArray::AddParameterIntConst(int konst)
|
||||
{
|
||||
numparams++;
|
||||
emitters.push_back([=](VMFunctionBuilder *build) ->int
|
||||
{
|
||||
// Immediates for PARAMI must fit in 24 bits.
|
||||
if (((konst << 8) >> 8) == konst)
|
||||
{
|
||||
build->Emit(OP_PARAMI, konst);
|
||||
}
|
||||
else
|
||||
{
|
||||
build->Emit(OP_PARAM, REGT_INT | REGT_KONST, build->GetConstantInt(konst));
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
void EmitterArray::AddParameterStringConst(const FString &konst)
|
||||
{
|
||||
numparams++;
|
||||
emitters.push_back([=](VMFunctionBuilder *build) ->int
|
||||
{
|
||||
build->Emit(OP_PARAM, REGT_STRING | REGT_KONST, build->GetConstantString(konst));
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
int EmitterArray::EmitParameters(VMFunctionBuilder *build)
|
||||
{
|
||||
int paramcount = 0;
|
||||
for (auto &func : emitters)
|
||||
{
|
||||
paramcount += func(build);
|
||||
}
|
||||
assert(paramcount == numparams);
|
||||
return paramcount;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "dobject.h"
|
||||
#include "vmintern.h"
|
||||
#include <vector>
|
||||
|
||||
class VMFunctionBuilder;
|
||||
class FxExpression;
|
||||
|
@ -68,7 +69,6 @@ public:
|
|||
size_t Emit(int opcode, int opa, int opb, int opc);
|
||||
size_t Emit(int opcode, int opa, VM_SHALF opbc);
|
||||
size_t Emit(int opcode, int opabc);
|
||||
size_t EmitParamInt(int value);
|
||||
size_t EmitLoadInt(int regnum, int value);
|
||||
size_t EmitRetInt(int retnum, bool final, int value);
|
||||
|
||||
|
@ -154,4 +154,34 @@ public:
|
|||
};
|
||||
|
||||
extern FFunctionBuildList FunctionBuildList;
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Function call parameter collector
|
||||
//
|
||||
//==========================================================================
|
||||
extern int EncodeRegType(ExpEmit reg);
|
||||
|
||||
class EmitterArray
|
||||
{
|
||||
// std::function and TArray are not compatible so this has to use std::vector instead.
|
||||
std::vector<std::function<int(VMFunctionBuilder *)>> emitters;
|
||||
unsigned numparams = 0;
|
||||
|
||||
public:
|
||||
void AddParameter(VMFunctionBuilder *build, FxExpression *operand);
|
||||
void AddParameter(ExpEmit &emit, bool reference);
|
||||
void AddParameterPointerConst(void *konst);
|
||||
void AddParameterPointer(int index, bool konst);
|
||||
void AddParameterFloatConst(double konst);
|
||||
void AddParameterIntConst(int konst);
|
||||
void AddParameterStringConst(const FString &konst);
|
||||
int EmitParameters(VMFunctionBuilder *build);
|
||||
unsigned Count() const
|
||||
{
|
||||
return numparams;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -283,6 +283,7 @@ public:
|
|||
unsigned start = Count;
|
||||
|
||||
Grow(item.Size());
|
||||
Count += item.Size();
|
||||
|
||||
for (unsigned i = 0; i < item.Size(); i++)
|
||||
{
|
||||
|
@ -296,6 +297,7 @@ public:
|
|||
unsigned start = Count;
|
||||
|
||||
Grow(item.Size());
|
||||
Count += item.Size();
|
||||
|
||||
for (unsigned i = 0; i < item.Size(); i++)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue