diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 69b7c814a..ab3f009e7 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -724,7 +724,7 @@ static int CreatePlaySoundFunc(VMFunctionBuilder &buildit, int value1, int value // misc1 = state, misc2 = probability static int CreateRandomJumpFunc(VMFunctionBuilder &buildit, int value1, int value2) { // A_Jump - int statereg = buildit.GetConstantAddress(FindState(value1), ATAG_STATE); + int statereg = buildit.GetConstantAddress(FindState(value1)); buildit.EmitParamInt(value2); // maxchance buildit.Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, statereg); // jumpto diff --git a/src/dobject.h b/src/dobject.h index f12bfc501..18a6f14b5 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -200,6 +200,14 @@ protected: enum { MetaClassNum = CLASSREG_PClass }; // Per-instance variables. There are four. +#ifdef _DEBUG +public: + enum + { + MAGIC_ID = 0x1337cafe + }; + uint32_t MagicID = MAGIC_ID; // only used by the VM for checking native function parameter types. +#endif private: PClass *Class; // This object's type public: diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 055274d3d..1b2c0b3db 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -2723,7 +2723,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnItem) PARAM_BOOL_DEF (useammo) PARAM_BOOL_DEF (transfer_translation); - if (numret > 1) ret[1].SetPointer(nullptr, ATAG_OBJECT); + if (numret > 1) ret[1].SetObject(nullptr); if (missile == NULL) { @@ -2760,7 +2760,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnItem) int flags = (transfer_translation ? SIXF_TRANSFERTRANSLATION : 0) + (useammo ? SIXF_SETMASTER : 0); bool res = InitSpawnedItem(self, mo, flags); // for an inventory item's use state if (numret > 0) ret[0].SetInt(res); - if (numret > 1) ret[1].SetPointer(mo, ATAG_OBJECT); + if (numret > 1) ret[1].SetObject(mo); return MIN(numret, 2); } @@ -2787,7 +2787,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnItemEx) PARAM_INT_DEF (chance) PARAM_INT_DEF (tid) - if (numret > 1) ret[1].SetPointer(nullptr, ATAG_OBJECT); + if (numret > 1) ret[1].SetObject(nullptr); if (missile == NULL) { @@ -2852,7 +2852,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnItemEx) mo->Angles.Yaw = angle; } if (numret > 0) ret[0].SetInt(res); - if (numret > 1) ret[1].SetPointer(mo, ATAG_OBJECT); + if (numret > 1) ret[1].SetObject(mo); return MIN(numret, 2); } @@ -2872,7 +2872,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrowGrenade) PARAM_FLOAT_DEF (zvel) PARAM_BOOL_DEF (useammo) - if (numret > 1) ret[1].SetPointer(nullptr, ATAG_OBJECT); + if (numret > 1) ret[1].SetObject(nullptr); if (missile == NULL) { @@ -2934,7 +2934,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrowGrenade) if (!P_CheckMissileSpawn(bo, self->radius)) bo = nullptr; if (numret > 0) ret[0].SetInt(true); - if (numret > 1) ret[1].SetPointer(bo, ATAG_OBJECT); + if (numret > 1) ret[1].SetObject(bo); return MIN(numret, 2); } else @@ -4363,7 +4363,7 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_CheckForReload) if (numret > 0) { - ret->SetPointer(NULL, ATAG_STATE); + ret->SetPointer(NULL); numret = 1; } @@ -4381,7 +4381,7 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_CheckForReload) // Go back to the refire frames, instead of continuing on to the reload frames. if (numret != 0) { - ret->SetPointer(jump, ATAG_STATE); + ret->SetPointer(jump); } } else @@ -4903,7 +4903,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Teleport) } if (numret > 0) { - ret[0].SetPointer(NULL, ATAG_STATE); + ret[0].SetPointer(NULL); } if (!ref) @@ -5039,7 +5039,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Teleport) } if (numret > 0) { - ret[0].SetPointer(teleport_state, ATAG_STATE); + ret[0].SetPointer(teleport_state); } return numret; } @@ -5337,7 +5337,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Warp) } if (numret > 0) { - ret[0].SetPointer(NULL, ATAG_STATE); + ret[0].SetPointer(NULL); } if ((flags & WARPF_USETID)) @@ -5363,7 +5363,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Warp) // in this case, you have the statejump to help you handle all the success anyway. if (numret > 0) { - ret[0].SetPointer(success_state, ATAG_STATE); + ret[0].SetPointer(success_state); } } else if (numret > 1) diff --git a/src/p_map.cpp b/src/p_map.cpp index 6f3f01cf4..d2d98d237 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -2054,7 +2054,7 @@ DEFINE_ACTION_FUNCTION(AActor, TestMobjZ) if (numret > 1) { numret = 2; - ret[1].SetPointer(on, ATAG_OBJECT); + ret[1].SetObject(on); } if (numret > 0) { @@ -4685,7 +4685,7 @@ DEFINE_ACTION_FUNCTION(AActor, LineAttack) int acdmg; if (puffType == nullptr) puffType = PClass::FindActor("BulletPuff"); // P_LineAttack does not work without a puff to take info from. auto puff = P_LineAttack(self, angle, distance, pitch, damage, damageType, puffType, flags, victim, &acdmg); - if (numret > 0) ret[0].SetPointer(puff, ATAG_OBJECT); + if (numret > 0) ret[0].SetObject(puff); if (numret > 1) ret[1].SetInt(acdmg), numret = 2; return numret; } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 08a2f922f..6a543f091 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -7247,8 +7247,8 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnPlayerMissile) AActor *missileactor; if (numparam == 2) angle = self->Angles.Yaw; AActor *misl = P_SpawnPlayerMissile(self, x, y, z, type, angle, lt, &missileactor, nofreeaim, noautoaim, aimflags); - if (numret > 0) ret[0].SetPointer(misl, ATAG_OBJECT); - if (numret > 1) ret[1].SetPointer(missileactor, ATAG_OBJECT), numret = 2; + if (numret > 0) ret[0].SetObject(misl); + if (numret > 1) ret[1].SetObject(missileactor), numret = 2; return numret; } @@ -7692,7 +7692,7 @@ FDropItem *AActor::GetDropItems() const DEFINE_ACTION_FUNCTION(AActor, GetDropItems) { PARAM_SELF_PROLOGUE(AActor); - ACTION_RETURN_OBJECT(self->GetDropItems()); + ACTION_RETURN_POINTER(self->GetDropItems()); } double AActor::GetGravity() const diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index 7dac68e1a..b64478c77 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -112,7 +112,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindLowestFloorSurrounding) vertex_t *v; double h = self->FindLowestFloorSurrounding(&v); if (numret > 0) ret[0].SetFloat(h); - if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC); + if (numret > 1) ret[1].SetPointer(v); return numret; } @@ -161,7 +161,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindHighestFloorSurrounding) vertex_t *v; double h = self->FindHighestFloorSurrounding(&v); if (numret > 0) ret[0].SetFloat(h); - if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC); + if (numret > 1) ret[1].SetPointer(v); return numret; } @@ -224,7 +224,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindNextHighestFloor) vertex_t *v; double h = self->FindNextHighestFloor(&v); if (numret > 0) ret[0].SetFloat(h); - if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC); + if (numret > 1) ret[1].SetPointer(v); return numret; } @@ -286,7 +286,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindNextLowestFloor) vertex_t *v; double h = self->FindNextLowestFloor(&v); if (numret > 0) ret[0].SetFloat(h); - if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC); + if (numret > 1) ret[1].SetPointer(v); return numret; } @@ -348,7 +348,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindNextLowestCeiling) vertex_t *v; double h = self->FindNextLowestCeiling(&v); if (numret > 0) ret[0].SetFloat(h); - if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC); + if (numret > 1) ret[1].SetPointer(v); return numret; } @@ -411,7 +411,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindNextHighestCeiling) vertex_t *v; double h = self->FindNextHighestCeiling(&v); if (numret > 0) ret[0].SetFloat(h); - if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC); + if (numret > 1) ret[1].SetPointer(v); return numret; } @@ -459,7 +459,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindLowestCeilingSurrounding) vertex_t *v; double h = self->FindLowestCeilingSurrounding(&v); if (numret > 0) ret[0].SetFloat(h); - if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC); + if (numret > 1) ret[1].SetPointer(v); return numret; } @@ -508,7 +508,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindHighestCeilingSurrounding) vertex_t *v; double h = self->FindHighestCeilingSurrounding(&v); if (numret > 0) ret[0].SetFloat(h); - if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC); + if (numret > 1) ret[1].SetPointer(v); return numret; } @@ -744,7 +744,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindHighestFloorPoint) vertex_t *v; double h = self->FindHighestFloorPoint(&v); if (numret > 0) ret[0].SetFloat(h); - if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC); + if (numret > 1) ret[1].SetPointer(v); return numret; } @@ -793,7 +793,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindLowestCeilingPoint) vertex_t *v; double h = self->FindLowestCeilingPoint(&v); if (numret > 0) ret[0].SetFloat(h); - if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC); + if (numret > 1) ret[1].SetPointer(v); return numret; } @@ -1207,7 +1207,7 @@ DEFINE_ACTION_FUNCTION(_Sector, HighestCeilingAt) sector_t *s; double h = self->HighestCeilingAt(DVector2(x, y), &s); if (numret > 0) ret[0].SetFloat(h); - if (numret > 1) ret[1].SetPointer(s, ATAG_GENERIC); + if (numret > 1) ret[1].SetPointer(s); return numret; } @@ -1242,7 +1242,7 @@ DEFINE_ACTION_FUNCTION(_Sector, LowestFloorAt) sector_t *s; double h = self->LowestFloorAt(DVector2(x, y), &s); if (numret > 0) ret[0].SetFloat(h); - if (numret > 1) ret[1].SetPointer(s, ATAG_GENERIC); + if (numret > 1) ret[1].SetPointer(s); return numret; } @@ -1309,12 +1309,12 @@ DEFINE_ACTION_FUNCTION(_Sector, NextHighestCeilingAt) if (numret > 2) { - ret[2].SetPointer(resultff, ATAG_GENERIC); + ret[2].SetPointer(resultff); numret = 3; } if (numret > 1) { - ret[1].SetPointer(resultsec, ATAG_GENERIC); + ret[1].SetPointer(resultsec); } if (numret > 0) { @@ -1387,12 +1387,12 @@ DEFINE_ACTION_FUNCTION(_Sector, NextLowestFloorAt) if (numret > 2) { - ret[2].SetPointer(resultff, ATAG_GENERIC); + ret[2].SetPointer(resultff); numret = 3; } if (numret > 1) { - ret[1].SetPointer(resultsec, ATAG_GENERIC); + ret[1].SetPointer(resultsec); } if (numret > 0) { diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 93fca44ed..656fe3ec5 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -385,7 +385,7 @@ void FxExpression::EmitCompare(VMFunctionBuilder *build, bool invert, TArrayEmit(OP_EQA_K, !invert, op.RegNum, build->GetConstantAddress(0, ATAG_GENERIC)); + build->Emit(OP_EQA_K, !invert, op.RegNum, build->GetConstantAddress(0)); break; case REGT_STRING: @@ -588,11 +588,7 @@ ExpEmit FxConstant::Emit(VMFunctionBuilder *build) else if (regtype == REGT_POINTER) { VM_ATAG tag = ATAG_GENERIC; - if (value.Type == TypeState) - { - tag = ATAG_STATE; - } - else if (value.Type->GetLoadOp() != OP_LP) + if (value.Type->GetLoadOp() != OP_LP) { tag = ATAG_OBJECT; } @@ -2998,7 +2994,7 @@ texcheck: auto * countptr = &ptr->Count; ExpEmit bndp(build, REGT_POINTER); ExpEmit bndc(build, REGT_INT); - build->Emit(OP_LKP, bndp.RegNum, build->GetConstantAddress(countptr, ATAG_GENERIC)); + build->Emit(OP_LKP, bndp.RegNum, build->GetConstantAddress(countptr)); build->Emit(OP_LW, bndc.RegNum, bndp.RegNum, build->GetConstantInt(0)); build->Emit(OP_BOUND_R, to.RegNum, bndc.RegNum); bndp.Free(build); @@ -5536,7 +5532,7 @@ 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, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG)); + build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng)); if (min != nullptr && max != nullptr) { EmitParameter(build, min, ScriptPosition); @@ -5657,7 +5653,7 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = ((PSymbolVMFunction *)sym)->Function; - build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG)); + build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng)); build->EmitParamInt(0); build->EmitParamInt(choices.Size() - 1); build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 3, 1); @@ -5787,7 +5783,7 @@ 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, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG)); + build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng)); if (min != nullptr && max != nullptr) { EmitParameter(build, min, ScriptPosition); @@ -5882,7 +5878,7 @@ 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, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG)); + build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng)); EmitParameter(build, mask, ScriptPosition); build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1); @@ -6661,7 +6657,7 @@ ExpEmit FxGlobalVariable::Emit(VMFunctionBuilder *build) { ExpEmit obj(build, REGT_POINTER); - build->Emit(OP_LKP, obj.RegNum, build->GetConstantAddress((void*)(intptr_t)membervar->Offset, ATAG_GENERIC)); + build->Emit(OP_LKP, obj.RegNum, build->GetConstantAddress((void*)(intptr_t)membervar->Offset)); if (AddressRequested) { return obj; @@ -6744,34 +6740,34 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build) switch (CVar->GetRealType()) { case CVAR_Int: - build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->Value, ATAG_GENERIC)); + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->Value)); build->Emit(OP_LW, dest.RegNum, addr.RegNum, nul); break; case CVAR_Color: - build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->Value, ATAG_GENERIC)); + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->Value)); build->Emit(OP_LW, dest.RegNum, addr.RegNum, nul); break; case CVAR_Float: - build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->Value, ATAG_GENERIC)); + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->Value)); build->Emit(OP_LSP, dest.RegNum, addr.RegNum, nul); break; case CVAR_Bool: - build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->Value, ATAG_GENERIC)); + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->Value)); build->Emit(OP_LBU, dest.RegNum, addr.RegNum, nul); break; case CVAR_String: - build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->Value, ATAG_GENERIC)); + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->Value)); build->Emit(OP_LCS, dest.RegNum, addr.RegNum, nul); break; case CVAR_DummyBool: { auto cv = static_cast(CVar); - build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&cv->ValueVar.Value, ATAG_GENERIC)); + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&cv->ValueVar.Value)); build->Emit(OP_LW, dest.RegNum, addr.RegNum, nul); build->Emit(OP_SRL_RI, dest.RegNum, dest.RegNum, cv->BitNum); build->Emit(OP_AND_RK, dest.RegNum, dest.RegNum, build->GetConstantInt(1)); @@ -6781,7 +6777,7 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build) case CVAR_DummyInt: { auto cv = static_cast(CVar); - build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&cv->ValueVar.Value, ATAG_GENERIC)); + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&cv->ValueVar.Value)); build->Emit(OP_LW, dest.RegNum, addr.RegNum, nul); build->Emit(OP_AND_RK, dest.RegNum, dest.RegNum, build->GetConstantInt(cv->BitVal)); build->Emit(OP_SRL_RI, dest.RegNum, dest.RegNum, cv->BitNum); @@ -8967,7 +8963,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) { // pass self as stateowner, otherwise all attempts of the subfunction to retrieve a state from a name would fail. build->Emit(OP_PARAM, 0, selfemit.RegType, selfemit.RegNum); - build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(nullptr, ATAG_GENERIC)); + build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(nullptr)); } count += 2; } @@ -10690,9 +10686,9 @@ int BuiltinNameToClass(VMValue *param, TArray &defaultparam, int numpar // Let the caller check this. Making this an error with a message is only taking away options from the user. cls = nullptr; } - ret->SetPointer(const_cast(cls), ATAG_OBJECT); + ret->SetObject(const_cast(cls)); } - else ret->SetPointer(nullptr, ATAG_OBJECT); + else ret->SetObject(nullptr); return 1; } diff --git a/src/scripting/backend/vmbuilder.h b/src/scripting/backend/vmbuilder.h index a5274794a..1f318a7e5 100644 --- a/src/scripting/backend/vmbuilder.h +++ b/src/scripting/backend/vmbuilder.h @@ -51,7 +51,7 @@ public: // Returns the constant register holding the value. unsigned GetConstantInt(int val); unsigned GetConstantFloat(double val); - unsigned GetConstantAddress(void *ptr, VM_ATAG tag); + unsigned GetConstantAddress(void *ptr, VM_ATAG tag = ATAG_GENERIC); unsigned GetConstantString(FString str); unsigned AllocConstantsInt(unsigned int count, int *values); diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index b95be74e3..6ceb8583d 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -181,20 +181,6 @@ enum { ATAG_GENERIC, // pointer to something; we don't care what 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 (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.) }; enum EVMAbortException @@ -366,6 +352,7 @@ struct VMReturn assert(RegType == REGT_STRING); *(FString *)Location = val; } + void SetPointer(void *val, int tag) { assert(RegType == REGT_POINTER); @@ -376,6 +363,26 @@ struct VMReturn } } + void SetPointer(void *val) + { + assert(RegType == REGT_POINTER); + *(void **)Location = val; + if (TagOfs != 0) + { + *((VM_ATAG *)Location + TagOfs) = ATAG_GENERIC; + } + } + + void SetObject(DObject *val) + { + assert(RegType == REGT_POINTER); + *(void **)Location = val; + if (TagOfs != 0) + { + *((VM_ATAG *)Location + TagOfs) = ATAG_OBJECT; + } + } + void IntAt(int *loc) { Location = loc; @@ -852,8 +859,18 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction // variable name at position

void NullParam(const char *varname); +#ifdef _DEBUG +bool AssertObject(void * ob); +#endif + #define PARAM_NULLCHECK(ptr, var) (ptr == nullptr? NullParam(#var), ptr : ptr) +#define ASSERTINT(p) assert((p).Type == REGT_INT) +#define ASSERTFLOAT(p) assert((p).Type == REGT_FLOAT) +#define ASSERTSTRING(p) assert((p).Type == REGT_STRING) +#define ASSERTOBJECT(p) assert((p).Type == REGT_POINTER && AssertObject(p.a)) +#define ASSERTPOINTER(p) assert((p).Type == REGT_POINTER) + // For required parameters. #define PARAM_INT_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); int x = param[p].i; #define PARAM_UINT_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); unsigned x = param[p].i; @@ -868,19 +885,13 @@ void NullParam(const char *varname); #define PARAM_STATE_ACTION_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); FState *x = (FState *)StateLabels.GetState(param[p].i, stateowner->GetClass()); #define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)param[p].a; #define PARAM_POINTERTYPE_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; 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)); base::MetaClass *x = (base::MetaClass *)param[p].a; assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base))); +#define PARAM_OBJECT_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && AssertObject(param[p].a)); 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 && AssertObject(param[p].a)); base::MetaClass *x = (base::MetaClass *)param[p].a; assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base))); #define PARAM_POINTER_NOT_NULL_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)PARAM_NULLCHECK(param[p].a, #x); -#define PARAM_OBJECT_NOT_NULL_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_NULLCHECK(param[p].a, #x); assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type))); -#define PARAM_CLASS_NOT_NULL_AT(p,x,base) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); base::MetaClass *x = (base::MetaClass *)PARAM_NULLCHECK(param[p].a, #x); assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base))); +#define PARAM_OBJECT_NOT_NULL_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (AssertObject(param[p].a))); type *x = (type *)PARAM_NULLCHECK(param[p].a, #x); assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type))); +#define PARAM_CLASS_NOT_NULL_AT(p,x,base) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (AssertObject(param[p].a))); base::MetaClass *x = (base::MetaClass *)PARAM_NULLCHECK(param[p].a, #x); assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base))); #define PARAM_EXISTS(p) ((p) < numparam) -#define ASSERTINT(p) assert((p).Type == REGT_INT) -#define ASSERTFLOAT(p) assert((p).Type == REGT_FLOAT) -#define ASSERTSTRING(p) assert((p).Type == REGT_STRING) -#define ASSERTOBJECT(p) assert((p).Type == REGT_POINTER && ((p).atag == ATAG_OBJECT || (p).a == nullptr)) -#define ASSERTPOINTER(p) assert((p).Type == REGT_POINTER && (p).atag == ATAG_GENERIC) -#define ASSERTSTATE(p) assert((p).Type == REGT_POINTER && ((p).atag == ATAG_GENERIC || (p).atag == ATAG_STATE)) #define PARAM_INT_DEF_AT(p,x) int x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = param[p].i; } else { ASSERTINT(defaultparam[p]); x = defaultparam[p].i; } #define PARAM_BOOL_DEF_AT(p,x) bool x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = !!param[p].i; } else { ASSERTINT(defaultparam[p]); x = !!defaultparam[p].i; } @@ -1030,9 +1041,9 @@ struct AFuncDesc class AActor; -#define ACTION_RETURN_STATE(v) do { FState *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_STATE); return 1; } return 0; } while(0) -#define ACTION_RETURN_POINTER(v) do { void *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_GENERIC); return 1; } return 0; } while(0) -#define ACTION_RETURN_OBJECT(v) do { auto state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_OBJECT); return 1; } return 0; } while(0) +#define ACTION_RETURN_STATE(v) do { FState *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state); return 1; } return 0; } while(0) +#define ACTION_RETURN_POINTER(v) do { void *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state); return 1; } return 0; } while(0) +#define ACTION_RETURN_OBJECT(v) do { auto state = v; if (numret > 0) { assert(ret != NULL); ret->SetObject(state); return 1; } return 0; } while(0) #define ACTION_RETURN_FLOAT(v) do { double u = v; if (numret > 0) { assert(ret != nullptr); ret->SetFloat(u); return 1; } return 0; } while(0) #define ACTION_RETURN_VEC2(v) do { DVector2 u = v; if (numret > 0) { assert(ret != nullptr); ret[0].SetVector2(u); return 1; } return 0; } while(0) #define ACTION_RETURN_VEC3(v) do { DVector3 u = v; if (numret > 0) { assert(ret != nullptr); ret[0].SetVector(u); return 1; } return 0; } while(0) diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index f8fb4bfd2..8d6c188f0 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -82,7 +82,6 @@ void ThrowVMException(VMException *x); #define ASSERTF(x) assert((unsigned)(x) < f->NumRegF) #define ASSERTA(x) assert((unsigned)(x) < f->NumRegA) #define ASSERTS(x) assert((unsigned)(x) < f->NumRegS) -#define ASSERTO(x) assert((unsigned)(x) < f->NumRegA && reg.atag[x] == ATAG_OBJECT) #define ASSERTKD(x) assert(sfunc != NULL && (unsigned)(x) < sfunc->NumKonstD) #define ASSERTKF(x) assert(sfunc != NULL && (unsigned)(x) < sfunc->NumKonstF) @@ -235,3 +234,23 @@ void VMFillParams(VMValue *params, VMFrame *callee, int numparam) } +#ifdef _DEBUG +bool AssertObject(void * ob) +{ + auto obj = (DObject*)ob; + if (obj == nullptr) return true; +#ifdef _MSC_VER + __try + { + return obj->MagicID == DObject::MAGIC_ID; + } + __except (1) + { + return false; + } +#else + // No SEH on non-Microsoft compilers. :( + return obj->MagicID == DObject::MAGIC_ID; +#endif +} +#endif diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 672dfe8ca..1147bb1b6 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -110,13 +110,13 @@ begin: NEXTOP; OP(CLSS): - ASSERTA(a); ASSERTO(B); + ASSERTA(a); ASSERTA(B); reg.a[a] = ((DObject*)reg.a[B])->GetClass(); // I wish this could be done without a special opcode but there's really no good way to guarantee initialization of the Class pointer... reg.atag[a] = ATAG_OBJECT; NEXTOP; OP(META): - ASSERTA(a); ASSERTO(B); + ASSERTA(a); ASSERTA(B); reg.a[a] = ((DObject*)reg.a[B])->GetClass()->Meta; // I wish this could be done without a special opcode but there's really no good way to guarantee initialization of the Class pointer... reg.atag[a] = ATAG_OBJECT; NEXTOP; @@ -657,7 +657,6 @@ begin: OP(CALL_K): ASSERTKA(a); - assert(konstatag[a] == ATAG_OBJECT); ptr = konsta[a].o; goto Do_CALL; OP(CALL): @@ -713,7 +712,6 @@ begin: NEXTOP; OP(TAIL_K): ASSERTKA(a); - assert(konstatag[a] == ATAG_OBJECT); ptr = konsta[a].o; goto Do_TAILCALL; OP(TAIL): @@ -851,7 +849,7 @@ begin: else if (a == 1) { ASSERTKA(B); - assert(konstatag[B] == ATAG_OBJECT); + assert(AssertObject(konsta[B].o)); ThrowVMException((VMException *)konsta[B].o); } else @@ -1709,7 +1707,6 @@ begin: { assert(pc->a == 3); ASSERTKA(b); - assert(konstatag[b] == ATAG_OBJECT); type = (PClass *)konsta[b].o; } ASSERTA(pc->c); @@ -1831,16 +1828,7 @@ static void DoCast(const VMRegisters ®, const VMFrame *f, int a, int b, int c { ASSERTS(a); ASSERTA(b); if (reg.a[b] == nullptr) reg.s[a] = "null"; - else if (reg.atag[b] == ATAG_OBJECT) - { - auto op = static_cast(reg.a[b]); - if (op->IsKindOf(RUNTIME_CLASS(PClass))) reg.s[a].Format("Class<%s>", static_cast(op)->TypeName.GetChars()); - else reg.s[a].Format("Object<%p>", ((DObject*)reg.a[b])->GetClass()->TypeName.GetChars()); - } - else - { - reg.s[a].Format("%s<%p>", "Pointer", reg.a[b]); - } + else reg.s[a].Format("%p", reg.a[b]); break; }