mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 21:11:39 +00:00
- fixed: A VM function's NumArgs value needs to count stack arguments, not logical ones, meaning that for vectors each element needs to count separately.
- renamed VMFunction::Defaults to DefaultArgs to make searching easier. - let ZCCCompiler process vector defaults for function parameters.
This commit is contained in:
parent
06ec6318a9
commit
9eeb56212b
7 changed files with 54 additions and 17 deletions
|
@ -466,12 +466,20 @@ public:
|
||||||
class FxVectorValue : public FxExpression
|
class FxVectorValue : public FxExpression
|
||||||
{
|
{
|
||||||
FxExpression *xyz[3];
|
FxExpression *xyz[3];
|
||||||
bool isConst; // gets set to true if all element are const
|
bool isConst; // gets set to true if all element are const (used by function defaults parser)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
friend class ZCCCompiler;
|
||||||
|
|
||||||
FxVectorValue(FxExpression *x, FxExpression *y, FxExpression *z, const FScriptPosition &sc);
|
FxVectorValue(FxExpression *x, FxExpression *y, FxExpression *z, const FScriptPosition &sc);
|
||||||
~FxVectorValue();
|
~FxVectorValue();
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
bool isConstVector(int dim)
|
||||||
|
{
|
||||||
|
if (!isConst) return false;
|
||||||
|
return dim == 2 ? xyz[2] == nullptr : xyz[2] != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
|
@ -643,7 +643,7 @@ public:
|
||||||
bool Native;
|
bool Native;
|
||||||
BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action
|
BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action
|
||||||
FName Name;
|
FName Name;
|
||||||
TArray<VMValue> Defaults;
|
TArray<VMValue> DefaultArgs;
|
||||||
|
|
||||||
class PPrototype *Proto;
|
class PPrototype *Proto;
|
||||||
|
|
||||||
|
|
|
@ -722,7 +722,13 @@ void FFunctionBuildList::Build()
|
||||||
// Emit code
|
// Emit code
|
||||||
item.Code->Emit(&buildit);
|
item.Code->Emit(&buildit);
|
||||||
buildit.MakeFunction(sfunc);
|
buildit.MakeFunction(sfunc);
|
||||||
sfunc->NumArgs = item.Func->Variants[0].Proto->ArgumentTypes.Size();
|
sfunc->NumArgs = 0;
|
||||||
|
// NumArgs for the VMFunction must be the amount of stack elements, which can differ from the amount of logical function arguments if vectors are in the list.
|
||||||
|
// For the VM a vector is 2 or 3 args, depending on size.
|
||||||
|
for (auto s : item.Func->Variants[0].Proto->ArgumentTypes)
|
||||||
|
{
|
||||||
|
sfunc->NumArgs += s->GetRegCount();
|
||||||
|
}
|
||||||
|
|
||||||
if (dump != nullptr)
|
if (dump != nullptr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -188,14 +188,14 @@ void VMFillParams(VMValue *params, VMFrame *callee, int numparam)
|
||||||
const VMRegisters calleereg(callee);
|
const VMRegisters calleereg(callee);
|
||||||
|
|
||||||
assert(calleefunc != NULL && !calleefunc->Native);
|
assert(calleefunc != NULL && !calleefunc->Native);
|
||||||
assert(numparam == calleefunc->NumArgs || ((int)calleefunc->Defaults.Size() == calleefunc->NumArgs));
|
assert(numparam == calleefunc->NumArgs || ((int)calleefunc->DefaultArgs.Size() == calleefunc->NumArgs));
|
||||||
assert(REGT_INT == 0 && REGT_FLOAT == 1 && REGT_STRING == 2 && REGT_POINTER == 3);
|
assert(REGT_INT == 0 && REGT_FLOAT == 1 && REGT_STRING == 2 && REGT_POINTER == 3);
|
||||||
|
|
||||||
regd = regf = regs = rega = 0;
|
regd = regf = regs = rega = 0;
|
||||||
for (int i = 0; i < calleefunc->NumArgs; ++i)
|
for (int i = 0; i < calleefunc->NumArgs; ++i)
|
||||||
{
|
{
|
||||||
// get all actual parameters and fill the rest from the defaults.
|
// get all actual parameters and fill the rest from the defaults.
|
||||||
VMValue &p = i < numparam? params[i] : calleefunc->Defaults[i];
|
VMValue &p = i < numparam? params[i] : calleefunc->DefaultArgs[i];
|
||||||
if (p.Type < REGT_STRING)
|
if (p.Type < REGT_STRING)
|
||||||
{
|
{
|
||||||
if (p.Type == REGT_INT)
|
if (p.Type == REGT_INT)
|
||||||
|
|
|
@ -544,7 +544,7 @@ begin:
|
||||||
FillReturns(reg, f, returns, pc+1, C);
|
FillReturns(reg, f, returns, pc+1, C);
|
||||||
if (call->Native)
|
if (call->Native)
|
||||||
{
|
{
|
||||||
numret = static_cast<VMNativeFunction *>(call)->NativeCall(stack, reg.param + f->NumParam - B, call->Defaults, B, returns, C);
|
numret = static_cast<VMNativeFunction *>(call)->NativeCall(stack, reg.param + f->NumParam - B, call->DefaultArgs, B, returns, C);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -588,7 +588,7 @@ begin:
|
||||||
|
|
||||||
if (call->Native)
|
if (call->Native)
|
||||||
{
|
{
|
||||||
return static_cast<VMNativeFunction *>(call)->NativeCall(stack, reg.param + f->NumParam - B, call->Defaults, B, ret, numret);
|
return static_cast<VMNativeFunction *>(call)->NativeCall(stack, reg.param + f->NumParam - B, call->DefaultArgs, B, ret, numret);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // FIXME: Not a true tail call
|
{ // FIXME: Not a true tail call
|
||||||
|
|
|
@ -415,7 +415,7 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur
|
||||||
{
|
{
|
||||||
if (func->Native)
|
if (func->Native)
|
||||||
{
|
{
|
||||||
return static_cast<VMNativeFunction *>(func)->NativeCall(this, params, func->Defaults, numparams, results, numresults);
|
return static_cast<VMNativeFunction *>(func)->NativeCall(this, params, func->DefaultArgs, numparams, results, numresults);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -2022,7 +2022,8 @@ void ZCCCompiler::InitFunctions()
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
VMValue vmval; // default is REGT_NIL which means 'no default value' here.
|
int elementcount = 1;
|
||||||
|
VMValue vmval[3]; // default is REGT_NIL which means 'no default value' here.
|
||||||
if (p->Type != nullptr)
|
if (p->Type != nullptr)
|
||||||
{
|
{
|
||||||
auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false);
|
auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false);
|
||||||
|
@ -2036,6 +2037,14 @@ void ZCCCompiler::InitFunctions()
|
||||||
{
|
{
|
||||||
type = NewPointer(type);
|
type = NewPointer(type);
|
||||||
}
|
}
|
||||||
|
else if (type == TypeVector2)
|
||||||
|
{
|
||||||
|
elementcount = 2;
|
||||||
|
}
|
||||||
|
else if (type == TypeVector3)
|
||||||
|
{
|
||||||
|
elementcount = 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (type->GetRegType() == REGT_NIL && type != TypeVector2 && type != TypeVector3)
|
if (type->GetRegType() == REGT_NIL && type != TypeVector2 && type != TypeVector3)
|
||||||
{
|
{
|
||||||
|
@ -2055,7 +2064,21 @@ void ZCCCompiler::InitFunctions()
|
||||||
|
|
||||||
if (x != nullptr)
|
if (x != nullptr)
|
||||||
{
|
{
|
||||||
if (!x->isConstant())
|
// Vectors need special treatment because they use more than one entry in the Defaults and do not report as actual constants
|
||||||
|
if (type == TypeVector2 && x->ExprType == EFX_VectorValue && static_cast<FxVectorValue *>(x)->isConstVector(2))
|
||||||
|
{
|
||||||
|
auto vx = static_cast<FxVectorValue *>(x);
|
||||||
|
vmval[0] = static_cast<FxConstant *>(vx->xyz[0])->GetValue().GetFloat();
|
||||||
|
vmval[1] = static_cast<FxConstant *>(vx->xyz[1])->GetValue().GetFloat();
|
||||||
|
}
|
||||||
|
else if (type == TypeVector3 && x->ExprType == EFX_VectorValue && static_cast<FxVectorValue *>(x)->isConstVector(3))
|
||||||
|
{
|
||||||
|
auto vx = static_cast<FxVectorValue *>(x);
|
||||||
|
vmval[0] = static_cast<FxConstant *>(vx->xyz[0])->GetValue().GetFloat();
|
||||||
|
vmval[1] = static_cast<FxConstant *>(vx->xyz[1])->GetValue().GetFloat();
|
||||||
|
vmval[2] = static_cast<FxConstant *>(vx->xyz[2])->GetValue().GetFloat();
|
||||||
|
}
|
||||||
|
else if (!x->isConstant())
|
||||||
{
|
{
|
||||||
Error(p, "Default parameter %s is not constant in %s", FName(p->Name).GetChars(), FName(f->Name).GetChars());
|
Error(p, "Default parameter %s is not constant in %s", FName(p->Name).GetChars(), FName(f->Name).GetChars());
|
||||||
}
|
}
|
||||||
|
@ -2070,22 +2093,22 @@ void ZCCCompiler::InitFunctions()
|
||||||
switch (type->GetRegType())
|
switch (type->GetRegType())
|
||||||
{
|
{
|
||||||
case REGT_INT:
|
case REGT_INT:
|
||||||
vmval = cnst->GetValue().GetInt();
|
vmval[0] = cnst->GetValue().GetInt();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REGT_FLOAT:
|
case REGT_FLOAT:
|
||||||
vmval = cnst->GetValue().GetFloat();
|
vmval[0] = cnst->GetValue().GetFloat();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REGT_POINTER:
|
case REGT_POINTER:
|
||||||
if (type->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
if (type->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||||
vmval = (DObject*)cnst->GetValue().GetPointer();
|
vmval[0] = (DObject*)cnst->GetValue().GetPointer();
|
||||||
else
|
else
|
||||||
vmval = cnst->GetValue().GetPointer();
|
vmval[0] = cnst->GetValue().GetPointer();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REGT_STRING:
|
case REGT_STRING:
|
||||||
vmval = cnst->GetValue().GetString();
|
vmval[0] = cnst->GetValue().GetString();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -2112,7 +2135,7 @@ void ZCCCompiler::InitFunctions()
|
||||||
argflags.Push(0);
|
argflags.Push(0);
|
||||||
argnames.Push(NAME_None);
|
argnames.Push(NAME_None);
|
||||||
}
|
}
|
||||||
argdefaults.Push(vmval);
|
for(int i=0;i<elementcount;i++) argdefaults.Push(vmval[i]);
|
||||||
p = static_cast<decltype(p)>(p->SiblingNext);
|
p = static_cast<decltype(p)>(p->SiblingNext);
|
||||||
} while (p != f->Params);
|
} while (p != f->Params);
|
||||||
}
|
}
|
||||||
|
@ -2131,7 +2154,7 @@ void ZCCCompiler::InitFunctions()
|
||||||
}
|
}
|
||||||
if (sym->Variants[0].Implementation != nullptr && hasdefault) // do not copy empty default lists, they only waste space and processing time.
|
if (sym->Variants[0].Implementation != nullptr && hasdefault) // do not copy empty default lists, they only waste space and processing time.
|
||||||
{
|
{
|
||||||
sym->Variants[0].Implementation->Defaults = std::move(argdefaults);
|
sym->Variants[0].Implementation->DefaultArgs = std::move(argdefaults);
|
||||||
}
|
}
|
||||||
// todo: Check inheritance.
|
// todo: Check inheritance.
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue