diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index 74ccf1ba2..3ae20a83d 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -858,6 +858,7 @@ public: FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); ExpEmit Emit(VMFunctionBuilder *build, bool tailcall); + bool CheckEmitCast(VMFunctionBuilder *build, bool returnit, ExpEmit ®); unsigned GetArgCount() const { return ArgList == NULL ? 0 : ArgList->Size(); } VMFunction *GetVMFunction() const { return Function->Variants[0].Implementation; } bool IsDirectFunction(); diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index bacb83e0f..5eb77aa80 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -3356,6 +3356,14 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build, bool tailcall) assert(build->Registers[REGT_POINTER].GetMostUsed() >= 3); int count = GetArgCount(); + if (count == 1) + { + ExpEmit reg; + if (CheckEmitCast(build, tailcall, reg)) + { + return reg; + } + } // Emit code to pass implied parameters if (Function->Flags & VARF_Method) { @@ -3399,6 +3407,47 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build, bool tailcall) } } +//========================================================================== +// +// If calling one of the casting kludge functions, don't bother calling the +// function; just use the parameter directly. Returns true if this was a +// kludge function, false otherwise. +// +//========================================================================== + +bool FxVMFunctionCall::CheckEmitCast(VMFunctionBuilder *build, bool returnit, ExpEmit ®) +{ + FName funcname = Function->SymbolName; + if (funcname == NAME___decorate_internal_int__ || + funcname == NAME___decorate_internal_bool__ || + funcname == NAME___decorate_internal_state__) + { + FxExpression *arg = (*ArgList)[0]; + if (returnit) + { + if (arg->isConstant() && + (funcname == NAME___decorate_internal_int__ || + funcname == NAME___decorate_internal_bool__)) + { // Use immediate version for integers in range + build->EmitRetInt(0, true, static_cast(arg)->GetValue().Int); + } + else + { + ExpEmit where = arg->Emit(build); + build->Emit(OP_RET, RET_FINAL, where.RegType | (where.Konst ? REGT_KONST : 0), where.RegNum); + where.Free(build); + } + reg = ExpEmit(); + } + else + { + reg = arg->Emit(build); + } + return true; + } + return false; +} + //========================================================================== // //