diff --git a/src/c_cvars.cpp b/src/c_cvars.cpp index c8f1ee4c62..fe859cb49c 100644 --- a/src/c_cvars.cpp +++ b/src/c_cvars.cpp @@ -1093,7 +1093,7 @@ BitVal (bitval) ECVarType FFlagCVar::GetRealType () const { - return CVAR_Dummy; + return CVAR_DummyBool; } UCVarValue FFlagCVar::GetGenericRep (ECVarType type) const @@ -1197,7 +1197,7 @@ BitVal (bitval) ECVarType FMaskCVar::GetRealType () const { - return CVAR_Dummy; + return CVAR_DummyInt; } UCVarValue FMaskCVar::GetGenericRep (ECVarType type) const diff --git a/src/c_cvars.h b/src/c_cvars.h index be7676e895..cf6975b866 100644 --- a/src/c_cvars.h +++ b/src/c_cvars.h @@ -81,13 +81,17 @@ enum ECVarType CVAR_Float, CVAR_String, CVAR_Color, // stored as CVAR_Int - CVAR_Dummy, // just redirects to another cvar + CVAR_DummyBool, // just redirects to another cvar + CVAR_DummyInt, // just redirects to another cvar + CVAR_Dummy, // Unknown CVAR_GUID }; class FConfigFile; class AActor; +class FxCVar; + class FBaseCVar { public: @@ -211,6 +215,7 @@ void C_DeinitConsole(); class FBoolCVar : public FBaseCVar { + friend class FxCVar; public: FBoolCVar (const char *name, bool def, uint32 flags, void (*callback)(FBoolCVar &)=NULL); @@ -236,6 +241,7 @@ protected: class FIntCVar : public FBaseCVar { + friend class FxCVar; public: FIntCVar (const char *name, int def, uint32 flags, void (*callback)(FIntCVar &)=NULL); @@ -263,6 +269,7 @@ protected: class FFloatCVar : public FBaseCVar { + friend class FxCVar; public: FFloatCVar (const char *name, float def, uint32 flags, void (*callback)(FFloatCVar &)=NULL); @@ -289,6 +296,7 @@ protected: class FStringCVar : public FBaseCVar { + friend class FxCVar; public: FStringCVar (const char *name, const char *def, uint32 flags, void (*callback)(FStringCVar &)=NULL); ~FStringCVar (); @@ -315,6 +323,7 @@ protected: class FColorCVar : public FIntCVar { + friend class FxCVar; public: FColorCVar (const char *name, int def, uint32 flags, void (*callback)(FColorCVar &)=NULL); @@ -339,6 +348,7 @@ protected: class FFlagCVar : public FBaseCVar { + friend class FxCVar; public: FFlagCVar (const char *name, FIntCVar &realvar, uint32 bitval); @@ -367,6 +377,7 @@ protected: class FMaskCVar : public FBaseCVar { + friend class FxCVar; public: FMaskCVar (const char *name, FIntCVar &realvar, uint32 bitval); diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 7be1b9cf2f..9ca96de05d 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1993,7 +1993,7 @@ ExpEmit FxPreIncrDecr::Emit(VMFunctionBuilder *build) if (regtype == REGT_INT) { - build->Emit((Token == TK_Incr) ? OP_ADD_RK : OP_SUB_RK, value.RegNum, value.RegNum, build->GetConstantInt(1)); + build->Emit(OP_ADDI, value.RegNum, value.RegNum, (Token == TK_Incr) ? 1 : -1); } else { @@ -2077,7 +2077,7 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) ExpEmit assign(build, regtype); if (regtype == REGT_INT) { - build->Emit((Token == TK_Incr) ? OP_ADD_RK : OP_SUB_RK, assign.RegNum, out.RegNum, build->GetConstantInt(1)); + build->Emit(OP_ADDI, assign.RegNum, out.RegNum, (Token == TK_Incr) ? 1 : -1); } else { @@ -2094,7 +2094,7 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) if (regtype == REGT_INT) { build->Emit(OP_MOVE, out.RegNum, pointer.RegNum); - build->Emit((Token == TK_Incr) ? OP_ADD_RK : OP_SUB_RK, pointer.RegNum, pointer.RegNum, build->GetConstantInt(1)); + build->Emit(OP_ADDI, pointer.RegNum, pointer.RegNum, (Token == TK_Incr) ? 1 : -1); } else { @@ -2108,7 +2108,7 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) { if (regtype == REGT_INT) { - build->Emit((Token == TK_Incr) ? OP_ADD_RK : OP_SUB_RK, pointer.RegNum, pointer.RegNum, build->GetConstantInt(1)); + build->Emit(OP_ADDI, pointer.RegNum, pointer.RegNum, (Token == TK_Incr) ? 1 : -1); } else { @@ -5526,6 +5526,18 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as line special %d\n", Identifier.GetChars(), num); newex = new FxConstant(num, ScriptPosition); } + + auto cvar = FindCVar(Identifier.GetChars(), nullptr); + if (cvar != nullptr) + { + if (cvar->GetFlags() & CVAR_USERINFO) + { + ScriptPosition.Message(MSG_ERROR, "Cannot access userinfo CVARs directly. Use GetCVar() instead."); + delete this; + return nullptr; + } + newex = new FxCVar(cvar, ScriptPosition); + } if (newex == nullptr) { @@ -5956,6 +5968,114 @@ ExpEmit FxGlobalVariable::Emit(VMFunctionBuilder *build) } +//========================================================================== +// +// +// +//========================================================================== + +FxCVar::FxCVar(FBaseCVar *cvar, const FScriptPosition &pos) + : FxExpression(EFX_CVar, pos) +{ + CVar = cvar; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxCVar::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + switch (CVar->GetRealType()) + { + case CVAR_Bool: + case CVAR_DummyBool: + ValueType = TypeBool; + break; + + case CVAR_Int: + case CVAR_DummyInt: + ValueType = TypeSInt32; + break; + + case CVAR_Color: + ValueType = TypeColor; + break; + + case CVAR_Float: + ValueType = TypeFloat64; + break; + + case CVAR_String: + ValueType = TypeString; + break; + + default: + ScriptPosition.Message(MSG_ERROR, "Unknown CVar type for %s", CVar->GetName()); + delete this; + return nullptr; + } + return this; +} + +ExpEmit FxCVar::Emit(VMFunctionBuilder *build) +{ + ExpEmit dest(build, ValueType->GetRegType()); + ExpEmit addr(build, REGT_POINTER); + int nul = build->GetConstantInt(0); + switch (CVar->GetRealType()) + { + case CVAR_Int: + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->Value, ATAG_GENERIC)); + 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_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_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_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_LS, dest.RegNum, addr.RegNum, nul); + break; + + case CVAR_DummyBool: + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->ValueVar.Value, ATAG_GENERIC)); + build->Emit(OP_LBIT, dest.RegNum, addr.RegNum, static_cast(CVar)->BitNum); + break; + + case CVAR_DummyInt: + { + auto cv = static_cast(CVar); + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&cv->ValueVar.Value, ATAG_GENERIC)); + 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); + break; + } + + default: + assert(false && "Unsupported CVar type"); + break; + } + return dest; +} + + //========================================================================== // // diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 7f588a0eb1..a3b6451766 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -284,6 +284,7 @@ enum EFxType EFX_MultiAssign, EFX_StaticArray, EFX_StaticArrayVariable, + EFX_CVar, EFX_COUNT }; @@ -1236,6 +1237,15 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +class FxCVar : public FxExpression +{ + FBaseCVar *CVar; +public: + FxCVar(FBaseCVar*, const FScriptPosition&); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxClassMember