diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 0402ed9ab..3895441d8 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -4324,58 +4324,32 @@ FxExpression *FxTypeCheck::Resolve(FCompileContext& ctx) // //========================================================================== -PPrototype *FxTypeCheck::ReturnProto() +ExpEmit FxTypeCheck::EmitCommon(VMFunctionBuilder *build) { - EmitTail = true; - return FxExpression::ReturnProto(); + ExpEmit castee = left->Emit(build); + ExpEmit casttype = right->Emit(build); + castee.Free(build); + casttype.Free(build); + ExpEmit ares(build, REGT_POINTER); + build->Emit(casttype.Konst ? OP_DYNCAST_K : OP_DYNCAST_R, ares.RegNum, castee.RegNum, casttype.RegNum); + return ares; } - -//========================================================================== -// -// -// -//========================================================================== - -int BuiltinTypeCheck(VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) -{ - assert(numparam == 2); - PARAM_POINTER_AT(0, obj, DObject); - PARAM_CLASS_AT(1, cls, DObject); - ACTION_RETURN_BOOL(obj && obj->IsKindOf(cls)); -} - -//========================================================================== -// -// -// -//========================================================================== - ExpEmit FxTypeCheck::Emit(VMFunctionBuilder *build) { - EmitParameter(build, left, ScriptPosition); - EmitParameter(build, right, ScriptPosition); + ExpEmit ares = EmitCommon(build); + ares.Free(build); + ExpEmit bres(build, REGT_INT); + build->Emit(OP_CASTB, bres.RegNum, ares.RegNum, CASTB_A); + return bres; +} - - PSymbol *sym = FindBuiltinFunction(NAME_BuiltinTypeCheck, BuiltinTypeCheck); - - assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); - assert(((PSymbolVMFunction *)sym)->Function != nullptr); - auto callfunc = ((PSymbolVMFunction *)sym)->Function; - - int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); - build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1); - - if (EmitTail) - { - ExpEmit call; - call.Final = true; - return call; - } - - ExpEmit out(build, REGT_INT); - build->Emit(OP_RESULT, 0, REGT_INT, out.RegNum); - return out; +void FxTypeCheck::EmitCompare(VMFunctionBuilder *build, bool invert, TArray &patchspots_yes, TArray &patchspots_no) +{ + ExpEmit ares = EmitCommon(build); + ares.Free(build); + build->Emit(OP_EQA_K, !invert, ares.RegNum, build->GetConstantAddress(nullptr, ATAG_OBJECT)); + patchspots_no.Push(build->Emit(OP_JMP, 0)); } //========================================================================== @@ -4443,27 +4417,11 @@ FxExpression *FxDynamicCast::Resolve(FCompileContext& ctx) ExpEmit FxDynamicCast::Emit(VMFunctionBuilder *build) { - ExpEmit in = expr->Emit(build); - ExpEmit out = in.Fixed ? ExpEmit(build, in.RegType) : in; - ExpEmit check(build, REGT_INT); - assert(out.RegType == REGT_POINTER); - - if (in.Fixed) build->Emit(OP_MOVEA, out.RegNum, in.RegNum); - build->Emit(OP_PARAM, 0, REGT_POINTER, in.RegNum); - build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(CastType, ATAG_OBJECT)); - - PSymbol *sym = FindBuiltinFunction(NAME_BuiltinTypeCheck, BuiltinTypeCheck); - assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); - assert(((PSymbolVMFunction *)sym)->Function != nullptr); - auto callfunc = ((PSymbolVMFunction *)sym)->Function; - - build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1); - build->Emit(OP_RESULT, 0, REGT_INT, check.RegNum); - build->Emit(OP_EQ_K, 0, check.RegNum, build->GetConstantInt(0)); - auto patch = build->Emit(OP_JMP, 0); - build->Emit(OP_LKP, out.RegNum, build->GetConstantAddress(nullptr, ATAG_OBJECT)); - build->BackpatchToHere(patch); - return out; + ExpEmit castee = expr->Emit(build); + castee.Free(build); + ExpEmit ares(build, REGT_POINTER); + build->Emit(OP_DYNCAST_K, ares.RegNum, castee.RegNum, build->GetConstantAddress(CastType, ATAG_OBJECT)); + return ares; } //========================================================================== @@ -9586,8 +9544,7 @@ int BuiltinNameToClass(VMValue *param, TArray &defaultparam, int numpar if (!cls->IsDescendantOf(desttype)) { - // Let the caller check this. The message can be enabled for diagnostic purposes. - DPrintf(DMSG_SPAMMY, "class '%s' is not compatible with '%s'\n", clsname.GetChars(), desttype->TypeName.GetChars()); + // 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); diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 49999206d..c18754cb8 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -1078,9 +1078,10 @@ public: FxTypeCheck(FxExpression*, FxExpression*); ~FxTypeCheck(); FxExpression *Resolve(FCompileContext&); - PPrototype *ReturnProto(); + ExpEmit EmitCommon(VMFunctionBuilder *build); ExpEmit Emit(VMFunctionBuilder *build); + void EmitCompare(VMFunctionBuilder *build, bool invert, TArray &patchspots_yes, TArray &patchspots_no); }; //========================================================================== diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 4152facc1..76a7156cb 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -414,6 +414,18 @@ begin: reg.f[a+1] = reg.f[B+1]; reg.f[a+2] = reg.f[B+2]; NEXTOP; + OP(DYNCAST_R) : + ASSERTA(a); ASSERTA(B); ASSERTA(C); + b = B; + reg.a[a] = (reg.a[b] && ((DObject*)(reg.a[b]))->IsKindOf((PClass*)(reg.a[C]))) ? reg.a[b] : nullptr; + reg.atag[a] = ATAG_OBJECT; + NEXTOP; + OP(DYNCAST_K) : + ASSERTA(a); ASSERTA(B); ASSERTKA(C); + b = B; + reg.a[a] = (reg.a[b] && ((DObject*)(reg.a[b]))->IsKindOf((PClass*)(konsta[C].o))) ? reg.a[b] : nullptr; + reg.atag[a] = ATAG_OBJECT; + NEXTOP; OP(CAST): if (C == CAST_I2F) { diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index 826bdb4e3..889706726 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -84,6 +84,8 @@ xx(MOVEV2, mov2, RFRF, NOP, 0, 0), // fA = fB (2 elements) xx(MOVEV3, mov3, RFRF, NOP, 0, 0), // fA = fB (3 elements) xx(CAST, cast, CAST, NOP, 0, 0), // xA = xB, conversion specified by C xx(CASTB, castb, CAST, NOP, 0, 0), // xA = !!xB, type specified by C +xx(DYNCAST_R, dyncast, RPRPRP, NOP, 0, 0), // aA = dyn_cast(aB); +xx(DYNCAST_K, dyncast, RPRPKP, NOP, 0, 0), // aA = dyn_cast(aB); // Control flow. xx(TEST, test, RII16, NOP, 0, 0), // if (dA != BC) then pc++ diff --git a/wadsrc/static/zscript/doom/bossbrain.txt b/wadsrc/static/zscript/doom/bossbrain.txt index 2a3f39265..f22e4dd2b 100644 --- a/wadsrc/static/zscript/doom/bossbrain.txt +++ b/wadsrc/static/zscript/doom/bossbrain.txt @@ -193,7 +193,7 @@ extend class Actor if (sv_killbossmonst) { int count; // Repeat until we have no more boss-spawned monsters. - ThinkerIterator it = ThinkerIterator.Create(); + ThinkerIterator it = ThinkerIterator.Create("Actor"); do // (e.g. Pain Elementals can spawn more to kill upon death.) { Actor mo; diff --git a/wadsrc/static/zscript/raven/minotaur.txt b/wadsrc/static/zscript/raven/minotaur.txt index 5e3d0cfe3..01cd63541 100644 --- a/wadsrc/static/zscript/raven/minotaur.txt +++ b/wadsrc/static/zscript/raven/minotaur.txt @@ -388,7 +388,7 @@ class Minotaur : Actor // In case pain caused him to skip his fade in. A_SetRenderStyle(1, STYLE_Normal); - MinotaurFriend mf = MinotaurFriend(self); + let mf = MinotaurFriend(self); if (mf) { if (mf.StartTime >= 0 && (level.maptime - mf.StartTime) >= MAULATORTICS) @@ -501,7 +501,7 @@ class Minotaur : Actor void A_MinotaurChase() { - MinotaurFriend mf = MinotaurFriend(self); + let mf = MinotaurFriend(self); if (!mf) { A_Chase();