- State code now properly calls action functions and has a RET instruction. As expected,
running with the checked VM can be quite slow, since it has asserts everywhere. Some other
fixes were needed before the code actually worked:
- A_CallSpecial needs to have its arguments cast to ints.
- Some functions that set pnum/paramnum directly did not decrement it by 1. This also applies
to A_Jump, though it just uses the value of paramnum instead of changing it.
- Renamed pnum in the PARAM macros to paramnum, since pnum is already used in a few other
places for something different, so this makes searching for it easier.
This has not been tested especially thoroughly, but a first glance seems to indicate success.
SVN r2163 (scripting)
This commit is contained in:
parent
739e684549
commit
6f1bf257e9
9 changed files with 130 additions and 108 deletions
|
|
@ -251,54 +251,63 @@ extern const VMOpInfo OpInfo[NUM_OPS];
|
|||
struct VMReturn
|
||||
{
|
||||
void *Location;
|
||||
VM_SHALF RegNum; // Used to find ObjFlag index for pointers; set negative if the caller is native code and doesn't care
|
||||
VM_SHALF TagOfs; // for pointers: Offset from Location to ATag; set to 0 if the caller is native code and doesn't care
|
||||
VM_UBYTE RegType; // Same as VMParam RegType, except REGT_KONST is invalid; only used by asserts
|
||||
|
||||
void SetInt(int val)
|
||||
{
|
||||
assert(RegType == REGT_INT);
|
||||
*(int *)Location = val;
|
||||
}
|
||||
void SetFloat(double val)
|
||||
{
|
||||
assert(RegType == REGT_FLOAT);
|
||||
*(double *)Location = val;
|
||||
}
|
||||
void SetVector(const double val[3])
|
||||
{
|
||||
{
|
||||
//assert(RegType == REGT_FLOAT);
|
||||
((double *)Location)[0] = val[0];
|
||||
((double *)Location)[1] = val[1];
|
||||
((double *)Location)[2] = val[2];
|
||||
}
|
||||
void SetString(const FString &val)
|
||||
{
|
||||
assert(RegType == REGT_STRING);
|
||||
*(FString *)Location = val;
|
||||
}
|
||||
void SetPointer(void *val)
|
||||
void SetPointer(void *val, int tag)
|
||||
{
|
||||
assert(RegType == REGT_POINTER);
|
||||
*(void **)Location = val;
|
||||
if (TagOfs != 0)
|
||||
{
|
||||
*((VM_ATAG *)Location + TagOfs) = tag;
|
||||
}
|
||||
}
|
||||
|
||||
void IntAt(int *loc)
|
||||
{
|
||||
Location = loc;
|
||||
RegNum = -1;
|
||||
TagOfs = 0;
|
||||
RegType = REGT_INT;
|
||||
}
|
||||
void FloatAt(double *loc)
|
||||
{
|
||||
Location = loc;
|
||||
RegNum = -1;
|
||||
TagOfs = 0;
|
||||
RegType = REGT_FLOAT;
|
||||
}
|
||||
void StringAt(FString *loc)
|
||||
{
|
||||
Location = loc;
|
||||
RegNum = -1;
|
||||
TagOfs = 0;
|
||||
RegType = REGT_STRING;
|
||||
}
|
||||
void PointerAt(void **loc)
|
||||
{
|
||||
Location = loc;
|
||||
RegNum = -1;
|
||||
TagOfs = 0;
|
||||
RegType = REGT_POINTER;
|
||||
}
|
||||
};
|
||||
|
|
@ -863,8 +872,8 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
#define PARAM_STRING_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_STRING); FString x = param[p].s();
|
||||
#define PARAM_STATE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATE || param[p].a == NULL)); FState *x = (FState *)param[p].a;
|
||||
#define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)param[p].a;
|
||||
#define PARAM_OBJECT_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); type *x = (type *)param[p].a;
|
||||
#define PARAM_CLASS_AT(p,x,base) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); PClass *x = (PClass *)param[p].a; assert(x->IsDescendantOf(RUNTIME_CLASS(base)));
|
||||
#define PARAM_OBJECT_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); type *x = (type *)param[p].a; assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type)));
|
||||
#define PARAM_CLASS_AT(p,x,base) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); PClass *x = (PClass *)param[p].a; assert(x != NULL && x->IsDescendantOf(RUNTIME_CLASS(base)));
|
||||
|
||||
// For optional paramaters. These have dangling elses for you to fill in the default assignment. e.g.:
|
||||
// PARAM_INT_OPT(0,myint) { myint = 55; }
|
||||
|
|
@ -881,38 +890,38 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
#define PARAM_STRING_OPT_AT(p,x) FString x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_STRING); x = param[p].s(); } else
|
||||
#define PARAM_STATE_OPT_AT(p,x) FState *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATE || param[p].a == NULL)); x = (FState *)param[p].a; } else
|
||||
#define PARAM_POINTER_OPT_AT(p,x,type) type *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER); x = (type *)param[p].a; } else
|
||||
#define PARAM_OBJECT_OPT_AT(p,x,type) type *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); x = (type *)param[p].a; } else
|
||||
#define PARAM_CLASS_OPT_AT(p,x,base) PClass *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); x = (PClass *)param[p].a; assert(x->IsKindOf(RUNTIME_CLASS(base))); } else
|
||||
#define PARAM_OBJECT_OPT_AT(p,x,type) type *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); x = (type *)param[p].a; assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type))); } else
|
||||
#define PARAM_CLASS_OPT_AT(p,x,base) PClass *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); x = (PClass *)param[p].a; assert(x != NULL && x->IsDescendantOf(RUNTIME_CLASS(base))); } else
|
||||
|
||||
// The above, but with an automatically increasing position index.
|
||||
#define PARAM_PROLOGUE int pnum = -1;
|
||||
#define PARAM_PROLOGUE int paramnum = -1;
|
||||
|
||||
#define PARAM_INT(x) ++pnum; PARAM_INT_AT(pnum,x)
|
||||
#define PARAM_BOOL(x) ++pnum; PARAM_BOOL_AT(pnum,x)
|
||||
#define PARAM_NAME(x) ++pnum; PARAM_NAME_AT(pnum,x)
|
||||
#define PARAM_SOUND(x) ++pnum; PARAM_SOUND_AT(pnum,x)
|
||||
#define PARAM_COLOR(x) ++pnum; PARAM_COLOR_AT(pnum,x)
|
||||
#define PARAM_FLOAT(x) ++pnum; PARAM_FLOAT_AT(pnum,x)
|
||||
#define PARAM_FIXED(x) ++pnum; PARAM_FIXED_AT(pnum,x)
|
||||
#define PARAM_ANGLE(x) ++pnum; PARAM_ANGLE_AT(pnum,x)
|
||||
#define PARAM_STRING(x) ++pnum; PARAM_STRING_AT(pnum,x)
|
||||
#define PARAM_STATE(x) ++pnum; PARAM_STATE_AT(pnum,x)
|
||||
#define PARAM_POINTER(x,type) ++pnum; PARAM_POINTER_AT(pnum,x,type)
|
||||
#define PARAM_OBJECT(x,type) ++pnum; PARAM_OBJECT_AT(pnum,x,type)
|
||||
#define PARAM_CLASS(x,base) ++pnum; PARAM_CLASS_AT(pnum,x,base)
|
||||
#define PARAM_INT(x) ++paramnum; PARAM_INT_AT(paramnum,x)
|
||||
#define PARAM_BOOL(x) ++paramnum; PARAM_BOOL_AT(paramnum,x)
|
||||
#define PARAM_NAME(x) ++paramnum; PARAM_NAME_AT(paramnum,x)
|
||||
#define PARAM_SOUND(x) ++paramnum; PARAM_SOUND_AT(paramnum,x)
|
||||
#define PARAM_COLOR(x) ++paramnum; PARAM_COLOR_AT(paramnum,x)
|
||||
#define PARAM_FLOAT(x) ++paramnum; PARAM_FLOAT_AT(paramnum,x)
|
||||
#define PARAM_FIXED(x) ++paramnum; PARAM_FIXED_AT(paramnum,x)
|
||||
#define PARAM_ANGLE(x) ++paramnum; PARAM_ANGLE_AT(paramnum,x)
|
||||
#define PARAM_STRING(x) ++paramnum; PARAM_STRING_AT(paramnum,x)
|
||||
#define PARAM_STATE(x) ++paramnum; PARAM_STATE_AT(paramnum,x)
|
||||
#define PARAM_POINTER(x,type) ++paramnum; PARAM_POINTER_AT(paramnum,x,type)
|
||||
#define PARAM_OBJECT(x,type) ++paramnum; PARAM_OBJECT_AT(paramnum,x,type)
|
||||
#define PARAM_CLASS(x,base) ++paramnum; PARAM_CLASS_AT(paramnum,x,base)
|
||||
|
||||
#define PARAM_INT_OPT(x) ++pnum; PARAM_INT_OPT_AT(pnum,x)
|
||||
#define PARAM_BOOL_OPT(x) ++pnum; PARAM_BOOL_OPT_AT(pnum,x)
|
||||
#define PARAM_NAME_OPT(x) ++pnum; PARAM_NAME_OPT_AT(pnum,x)
|
||||
#define PARAM_SOUND_OPT(x) ++pnum; PARAM_SOUND_OPT_AT(pnum,x)
|
||||
#define PARAM_COLOR_OPT(x) ++pnum; PARAM_COLOR_OPT_AT(pnum,x)
|
||||
#define PARAM_FLOAT_OPT(x) ++pnum; PARAM_FLOAT_OPT_AT(pnum,x)
|
||||
#define PARAM_FIXED_OPT(x) ++pnum; PARAM_FIXED_OPT_AT(pnum,x)
|
||||
#define PARAM_ANGLE_OPT(x) ++pnum; PARAM_ANGLE_OPT_AT(pnum,x)
|
||||
#define PARAM_STRING_OPT(x) ++pnum; PARAM_STRING_OPT_AT(pnum,x)
|
||||
#define PARAM_STATE_OPT(x) ++pnum; PARAM_STATE_OPT_AT(pnum,x)
|
||||
#define PARAM_POINTER_OPT(x,type) ++pnum; PARAM_POINTER_OPT_AT(pnum,x,type)
|
||||
#define PARAM_OBJECT_OPT(x,type) ++pnum; PARAM_OBJECT_OPT_AT(pnum,x,type)
|
||||
#define PARAM_CLASS_OPT(x,base) ++pnum; PARAM_CLASS_OPT_AT(pnum,x,base)
|
||||
#define PARAM_INT_OPT(x) ++paramnum; PARAM_INT_OPT_AT(paramnum,x)
|
||||
#define PARAM_BOOL_OPT(x) ++paramnum; PARAM_BOOL_OPT_AT(paramnum,x)
|
||||
#define PARAM_NAME_OPT(x) ++paramnum; PARAM_NAME_OPT_AT(paramnum,x)
|
||||
#define PARAM_SOUND_OPT(x) ++paramnum; PARAM_SOUND_OPT_AT(paramnum,x)
|
||||
#define PARAM_COLOR_OPT(x) ++paramnum; PARAM_COLOR_OPT_AT(paramnum,x)
|
||||
#define PARAM_FLOAT_OPT(x) ++paramnum; PARAM_FLOAT_OPT_AT(paramnum,x)
|
||||
#define PARAM_FIXED_OPT(x) ++paramnum; PARAM_FIXED_OPT_AT(paramnum,x)
|
||||
#define PARAM_ANGLE_OPT(x) ++paramnum; PARAM_ANGLE_OPT_AT(paramnum,x)
|
||||
#define PARAM_STRING_OPT(x) ++paramnum; PARAM_STRING_OPT_AT(paramnum,x)
|
||||
#define PARAM_STATE_OPT(x) ++paramnum; PARAM_STATE_OPT_AT(paramnum,x)
|
||||
#define PARAM_POINTER_OPT(x,type) ++paramnum; PARAM_POINTER_OPT_AT(paramnum,x,type)
|
||||
#define PARAM_OBJECT_OPT(x,type) ++paramnum; PARAM_OBJECT_OPT_AT(paramnum,x,type)
|
||||
#define PARAM_CLASS_OPT(x,base) ++paramnum; PARAM_CLASS_OPT_AT(paramnum,x,base)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ void VMDumpConstants(FILE *out, const VMScriptFunction *func)
|
|||
{
|
||||
for (j = 0, k = i; j < 4 && k < func->NumKonstA; j++, k += kk)
|
||||
{
|
||||
mysnprintf(tmp, countof(tmp), "%3d. %p", k, func->KonstA[k]);
|
||||
mysnprintf(tmp, countof(tmp), "%3d. %p:%d", k, func->KonstA[k], func->KonstATags()[k]);
|
||||
printf_wrapper(out, "%-20s", tmp);
|
||||
}
|
||||
printf_wrapper(out, "\n");
|
||||
|
|
|
|||
|
|
@ -1384,7 +1384,7 @@ static void DoCast(const VMRegisters ®, const VMFrame *f, int a, int b, int c
|
|||
|
||||
static void FillReturns(const VMRegisters ®, VMFrame *frame, VMReturn *returns, const VMOP *retval, int numret)
|
||||
{
|
||||
int i, type, num;
|
||||
int i, type, regnum;
|
||||
VMReturn *ret;
|
||||
|
||||
assert(REGT_INT == 0 && REGT_FLOAT == 1 && REGT_STRING == 2 && REGT_POINTER == 3);
|
||||
|
|
@ -1392,33 +1392,35 @@ static void FillReturns(const VMRegisters ®, VMFrame *frame, VMReturn *return
|
|||
for (i = 0, ret = returns; i < numret; ++i, ++ret, ++retval)
|
||||
{
|
||||
assert(retval->op == OP_RESULT); // opcode
|
||||
ret->TagOfs = 0;
|
||||
ret->RegType = type = retval->b;
|
||||
ret->RegNum = num = retval->c;
|
||||
regnum = retval->c;
|
||||
assert(!(type & REGT_KONST));
|
||||
type &= REGT_TYPE;
|
||||
if (type < REGT_STRING)
|
||||
{
|
||||
if (type == REGT_INT)
|
||||
{
|
||||
assert(num < frame->NumRegD);
|
||||
ret->Location = ®.d[num];
|
||||
assert(regnum < frame->NumRegD);
|
||||
ret->Location = ®.d[regnum];
|
||||
}
|
||||
else // type == REGT_FLOAT
|
||||
{
|
||||
assert(num < frame->NumRegF);
|
||||
ret->Location = ®.f[num];
|
||||
assert(regnum < frame->NumRegF);
|
||||
ret->Location = ®.f[regnum];
|
||||
}
|
||||
}
|
||||
else if (type == REGT_STRING)
|
||||
{
|
||||
assert(num < frame->NumRegS);
|
||||
ret->Location = ®.s[num];
|
||||
assert(regnum < frame->NumRegS);
|
||||
ret->Location = ®.s[regnum];
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(type == REGT_POINTER);
|
||||
assert(num < frame->NumRegA);
|
||||
ret->Location = ®.a[num];
|
||||
assert(regnum < frame->NumRegA);
|
||||
ret->Location = ®.a[regnum];
|
||||
ret->TagOfs = (VM_SHALF)(&frame->GetRegATag()[regnum] - (VM_ATAG *)ret->Location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1434,7 +1436,6 @@ static void FillReturns(const VMRegisters ®, VMFrame *frame, VMReturn *return
|
|||
static void SetReturn(const VMRegisters ®, VMFrame *frame, VMReturn *ret, VM_UBYTE regtype, int regnum)
|
||||
{
|
||||
const void *src;
|
||||
VM_ATAG atag;
|
||||
VMScriptFunction *func = static_cast<VMScriptFunction *>(frame->Func);
|
||||
|
||||
assert(func != NULL && !func->Native);
|
||||
|
|
@ -1498,20 +1499,12 @@ static void SetReturn(const VMRegisters ®, VMFrame *frame, VMReturn *ret, VM_
|
|||
if (regtype & REGT_KONST)
|
||||
{
|
||||
assert(regnum < func->NumKonstA);
|
||||
ret->SetPointer(func->KonstA[regnum].v);
|
||||
atag = func->KonstATags()[regnum];
|
||||
ret->SetPointer(func->KonstA[regnum].v, func->KonstATags()[regnum]);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(regnum < frame->NumRegA);
|
||||
ret->SetPointer(reg.a[regnum]);
|
||||
atag = reg.atag[regnum];
|
||||
}
|
||||
if (ret->RegNum >= 0)
|
||||
{
|
||||
VMFrame *parent = frame->ParentFrame;
|
||||
assert(parent != NULL);
|
||||
parent->GetRegATag()[ret->RegNum] = atag;
|
||||
ret->SetPointer(reg.a[regnum], reg.atag[regnum]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue