- implemented pass-by-reference arguments - so far only for memory based variables.
- changed Dehacked weapon function lookup to check the symbol table instead of directly referencing the VM functions. Once scriptified these pointers will no longer be available. - removed all special ATAGs from the VM. While well intentioned any pointer tagged with them is basically unusable because it'd trigger asserts all over the place. - scriptified A_Punch for testing pass-by-reference parameters and stack variables.
This commit is contained in:
parent
7ff5069617
commit
3ce699bf9b
20 changed files with 205 additions and 126 deletions
|
|
@ -3547,7 +3547,7 @@ ExpEmit FxShift::Emit(VMFunctionBuilder *build)
|
|||
if (!op1.Konst)
|
||||
{
|
||||
op1.Free(build);
|
||||
instr = InstrMap[index][op2.Konst? 0:2];
|
||||
instr = InstrMap[index][op2.Konst? 2:0];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -7067,7 +7067,8 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
|
|||
SAFE_RESOLVE_OPT(Self, ctx);
|
||||
bool failed = false;
|
||||
auto proto = Function->Variants[0].Proto;
|
||||
auto argtypes = proto->ArgumentTypes;
|
||||
auto &argtypes = proto->ArgumentTypes;
|
||||
auto &argflags = Function->Variants[0].ArgFlags;
|
||||
|
||||
int implicit = Function->GetImplicitArgs();
|
||||
|
||||
|
|
@ -7100,8 +7101,29 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
|
|||
}
|
||||
assert(type != nullptr);
|
||||
|
||||
FxExpression *x = new FxTypeCast(ArgList[i], type, false);
|
||||
x = x->Resolve(ctx);
|
||||
FxExpression *x;
|
||||
if (!(argflags[i + implicit] & VARF_Ref))
|
||||
{
|
||||
x = new FxTypeCast(ArgList[i], type, false);
|
||||
x = x->Resolve(ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool writable;
|
||||
ArgList[i] = ArgList[i]->Resolve(ctx); // nust be resolved before the address is requested.
|
||||
ArgList[i]->RequestAddress(ctx, &writable);
|
||||
ArgList[i]->ValueType = NewPointer(ArgList[i]->ValueType);
|
||||
// For a reference argument the types must match 100%.
|
||||
if (type != ArgList[i]->ValueType)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Type mismatch in reference argument", Function->SymbolName.GetChars());
|
||||
x = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = ArgList[i];
|
||||
}
|
||||
}
|
||||
failed |= (x == nullptr);
|
||||
ArgList[i] = x;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ void SetImplicitArgs(TArray<PType *> *args, TArray<DWORD> *argflags, TArray<FNam
|
|||
{
|
||||
args->Push(NewPointer(cls));
|
||||
}
|
||||
args->Push(TypeState/*Info*/); // fixme: TypeState is not the correct type here!!!
|
||||
args->Push(NewPointer(NewStruct("FStateParamInfo", nullptr)));
|
||||
}
|
||||
if (argflags != nullptr)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -388,7 +388,7 @@ static FFlagDef InventoryFlagDefs[] =
|
|||
DEFINE_DEPRECATED_FLAG(INTERHUBSTRIP),
|
||||
};
|
||||
|
||||
static FFlagDef WeaponFlagDefs[] =
|
||||
FFlagDef WeaponFlagDefs[] =
|
||||
{
|
||||
// Weapon flags
|
||||
DEFINE_FLAG(WIF, NOAUTOFIRE, AWeapon, WeaponFlags),
|
||||
|
|
@ -411,12 +411,14 @@ static FFlagDef WeaponFlagDefs[] =
|
|||
DEFINE_FLAG(WIF, NOAUTOAIM, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, NODEATHDESELECT, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, NODEATHINPUT, AWeapon, WeaponFlags),
|
||||
|
||||
DEFINE_DUMMY_FLAG(NOLMS, false),
|
||||
DEFINE_FLAG(WIF, ALT_USES_BOTH, AWeapon, WeaponFlags),
|
||||
|
||||
DEFINE_DUMMY_FLAG(NOLMS, false),
|
||||
DEFINE_DUMMY_FLAG(ALLOW_WITH_RESPAWN_INVUL, false),
|
||||
};
|
||||
|
||||
|
||||
|
||||
static FFlagDef PlayerPawnFlagDefs[] =
|
||||
{
|
||||
// PlayerPawn flags
|
||||
|
|
|
|||
|
|
@ -157,13 +157,15 @@ enum
|
|||
ATAG_OBJECT, // pointer to an object; will be followed by GC
|
||||
|
||||
// The following are all for documentation during debugging and are
|
||||
// functionally no different than ATAG_GENERIC.
|
||||
// functionally no different than ATAG_GENERIC (meaning they are useless because they trigger asserts all over the place.)
|
||||
|
||||
/*
|
||||
ATAG_FRAMEPOINTER, // pointer to extra stack frame space for this function
|
||||
ATAG_DREGISTER, // pointer to a data register
|
||||
ATAG_FREGISTER, // pointer to a float register
|
||||
ATAG_SREGISTER, // pointer to a string register
|
||||
ATAG_AREGISTER, // pointer to an address register
|
||||
*/
|
||||
|
||||
ATAG_RNG, // pointer to FRandom
|
||||
ATAG_STATE = ATAG_GENERIC, // pointer to FState (cannot have its own type because there's no means to track inside the VM.)
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ begin:
|
|||
OP(LFP):
|
||||
ASSERTA(a); assert(sfunc != NULL); assert(sfunc->ExtraSpace > 0);
|
||||
reg.a[a] = f->GetExtra();
|
||||
reg.atag[a] = ATAG_FRAMEPOINTER;
|
||||
reg.atag[a] = ATAG_GENERIC; // using ATAG_FRAMEPOINTER will cause endless asserts.
|
||||
NEXTOP;
|
||||
|
||||
OP(LB):
|
||||
|
|
@ -461,7 +461,7 @@ begin:
|
|||
break;
|
||||
case REGT_INT | REGT_ADDROF:
|
||||
assert(C < f->NumRegD);
|
||||
::new(param) VMValue(®.d[C], ATAG_DREGISTER);
|
||||
::new(param) VMValue(®.d[C], ATAG_GENERIC);
|
||||
break;
|
||||
case REGT_INT | REGT_KONST:
|
||||
assert(C < sfunc->NumKonstD);
|
||||
|
|
@ -473,7 +473,7 @@ begin:
|
|||
break;
|
||||
case REGT_STRING | REGT_ADDROF:
|
||||
assert(C < f->NumRegS);
|
||||
::new(param) VMValue(®.s[C], ATAG_SREGISTER);
|
||||
::new(param) VMValue(®.s[C], ATAG_GENERIC);
|
||||
break;
|
||||
case REGT_STRING | REGT_KONST:
|
||||
assert(C < sfunc->NumKonstS);
|
||||
|
|
@ -485,7 +485,7 @@ begin:
|
|||
break;
|
||||
case REGT_POINTER | REGT_ADDROF:
|
||||
assert(C < f->NumRegA);
|
||||
::new(param) VMValue(®.a[C], ATAG_AREGISTER);
|
||||
::new(param) VMValue(®.a[C], ATAG_GENERIC);
|
||||
break;
|
||||
case REGT_POINTER | REGT_KONST:
|
||||
assert(C < sfunc->NumKonstA);
|
||||
|
|
@ -512,7 +512,7 @@ begin:
|
|||
break;
|
||||
case REGT_FLOAT | REGT_ADDROF:
|
||||
assert(C < f->NumRegF);
|
||||
::new(param) VMValue(®.f[C], ATAG_FREGISTER);
|
||||
::new(param) VMValue(®.f[C], ATAG_GENERIC);
|
||||
break;
|
||||
case REGT_FLOAT | REGT_KONST:
|
||||
assert(C < sfunc->NumKonstF);
|
||||
|
|
|
|||
|
|
@ -2160,6 +2160,7 @@ void ZCCCompiler::InitFunctions()
|
|||
if ((flags & VARF_Out) || (type != TypeVector2 && type != TypeVector3))
|
||||
{
|
||||
type = NewPointer(type);
|
||||
flags |= VARF_Ref;
|
||||
}
|
||||
else if (type == TypeVector2)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue