diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 974be598a..10c2632af 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -11272,6 +11272,7 @@ FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, Name = name; RegCount = type == TypeVector2 ? 2 : type == TypeVector3 ? 3 : 1; Init = initval; + clearExpr = nullptr; } FxLocalVariableDeclaration::~FxLocalVariableDeclaration() @@ -11282,6 +11283,15 @@ FxLocalVariableDeclaration::~FxLocalVariableDeclaration() FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); + + if (IsDynamicArray()) + { + auto stackVar = new FxStackVariable(ValueType, StackOffset, ScriptPosition); + FArgumentList argsList; + clearExpr = new FxMemberFunctionCall(stackVar, "Clear", argsList, ScriptPosition); + SAFE_RESOLVE(clearExpr, ctx); + } + if (ctx.Block == nullptr) { ScriptPosition.Message(MSG_ERROR, "Variable declaration outside compound statement"); @@ -11476,6 +11486,10 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build) } if (pstr->mDestructor != nullptr) build->ConstructedStructs.Push(this); } + else if (ValueType->isDynArray()) + { + ClearDynamicArray(build); + } } return ExpEmit(); } @@ -11507,6 +11521,11 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build) // For that all local stack variables need to live for the entire execution of a function. } +void FxLocalVariableDeclaration::ClearDynamicArray(VMFunctionBuilder *build) +{ + assert(clearExpr != nullptr); + clearExpr->Emit(build); +} FxStaticArray::FxStaticArray(PType *type, FName name, FArgumentList &args, const FScriptPosition &pos) : FxLocalVariableDeclaration(NewArray(type, args.Size()), name, nullptr, VARF_Static|VARF_ReadOnly, pos) @@ -11591,7 +11610,6 @@ FxLocalArrayDeclaration::FxLocalArrayDeclaration(PType *type, FName name, FArgum { ExprType = EFX_LocalArrayDeclaration; values = std::move(args); - clearExpr = nullptr; } FxExpression *FxLocalArrayDeclaration::Resolve(FCompileContext &ctx) @@ -11607,16 +11625,6 @@ FxExpression *FxLocalArrayDeclaration::Resolve(FCompileContext &ctx) auto elementType = (static_cast (ValueType))->ElementType; auto elementCount = (static_cast (ValueType))->ElementCount; - // We HAVE to clear dynamic arrays before initializing them - if (IsDynamicArray()) - { - FArgumentList argsList; - argsList.Clear(); - - clearExpr = new FxMemberFunctionCall(stackVar, "Clear", argsList, (const FScriptPosition) ScriptPosition); - SAFE_RESOLVE(clearExpr, ctx); - } - if (values.Size() > elementCount) { ScriptPosition.Message(MSG_ERROR, "Initializer contains more elements than the array can contain"); @@ -11673,9 +11681,11 @@ ExpEmit FxLocalArrayDeclaration::Emit(VMFunctionBuilder *build) { assert(!(VarFlags & VARF_Out)); // 'out' variables should never be initialized, they can only exist as function parameters. - if (IsDynamicArray() && clearExpr != nullptr) + const bool isDynamicArray = IsDynamicArray(); + + if (isDynamicArray) { - clearExpr->Emit(build); + ClearDynamicArray(build); } auto elementSizeConst = build->GetConstantInt(static_cast(ValueType)->ElementSize); @@ -11686,7 +11696,7 @@ ExpEmit FxLocalArrayDeclaration::Emit(VMFunctionBuilder *build) { ExpEmit emitval = v->Emit(build); - if (IsDynamicArray()) + if (isDynamicArray) { continue; } diff --git a/src/scripting/backend/codegen.h b/src/scripting/backend/codegen.h index aa05c7d06..26f2011b2 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -2131,6 +2131,12 @@ class FxLocalVariableDeclaration : public FxExpression FxExpression *Init; int VarFlags; int RegCount; + +protected: + FxExpression *clearExpr; + + void ClearDynamicArray(VMFunctionBuilder *build); + public: int StackOffset = -1; int RegNum = -1; @@ -2194,7 +2200,6 @@ class FxLocalArrayDeclaration : public FxLocalVariableDeclaration { PType *ElementType; FArgumentList values; - FxExpression *clearExpr; public: