From b9501a7291d43b0dbf4bb1ec5abdba6cf20d8efa Mon Sep 17 00:00:00 2001 From: Marisa Heit Date: Thu, 28 Jul 2022 23:17:19 -0500 Subject: [PATCH] Fix definition order of ZScript structs Do a first pass over the Structs array in CompileAllFields() to reorder them such that if a struct uses other structs, those structs will be resolved first. --- src/common/scripting/core/types.cpp | 4 + src/common/scripting/core/types.h | 1 + src/common/scripting/frontend/zcc_compile.cpp | 79 ++++++++++++++++++- src/common/scripting/frontend/zcc_compile.h | 3 + 4 files changed, 86 insertions(+), 1 deletion(-) diff --git a/src/common/scripting/core/types.cpp b/src/common/scripting/core/types.cpp index 01f83ba8910..fb844c62a68 100644 --- a/src/common/scripting/core/types.cpp +++ b/src/common/scripting/core/types.cpp @@ -334,6 +334,7 @@ void PType::StaticInit() TypeVector2->moveOp = OP_MOVEV2; TypeVector2->RegType = REGT_FLOAT; TypeVector2->RegCount = 2; + TypeVector2->isOrdered = true; TypeVector3 = new PStruct(NAME_Vector3, nullptr); TypeVector3->AddField(NAME_X, TypeFloat64); @@ -347,6 +348,7 @@ void PType::StaticInit() TypeVector3->moveOp = OP_MOVEV3; TypeVector3->RegType = REGT_FLOAT; TypeVector3->RegCount = 3; + TypeVector3->isOrdered = true; TypeFVector2 = new PStruct(NAME_FVector2, nullptr); @@ -358,6 +360,7 @@ void PType::StaticInit() TypeFVector2->moveOp = OP_MOVEV2; TypeFVector2->RegType = REGT_FLOAT; TypeFVector2->RegCount = 2; + TypeFVector2->isOrdered = true; TypeFVector3 = new PStruct(NAME_FVector3, nullptr); TypeFVector3->AddField(NAME_X, TypeFloat32); @@ -371,6 +374,7 @@ void PType::StaticInit() TypeFVector3->moveOp = OP_MOVEV3; TypeFVector3->RegType = REGT_FLOAT; TypeFVector3->RegCount = 3; + TypeFVector3->isOrdered = true; Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_sByte, TypeSInt8)); Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Byte, TypeUInt8)); diff --git a/src/common/scripting/core/types.h b/src/common/scripting/core/types.h index e8d07e91a7c..959d66bdacd 100644 --- a/src/common/scripting/core/types.h +++ b/src/common/scripting/core/types.h @@ -537,6 +537,7 @@ class PStruct : public PContainerType PStruct(FName name, PTypeBase *outer, bool isnative = false); bool isNative; + bool isOrdered = false; // Some internal structs require explicit construction and destruction of fields the VM cannot handle directly so use these two functions for it. VMFunction *mConstructor = nullptr; VMFunction *mDestructor = nullptr; diff --git a/src/common/scripting/frontend/zcc_compile.cpp b/src/common/scripting/frontend/zcc_compile.cpp index 9e3daeaef0f..66d68b9b4d0 100644 --- a/src/common/scripting/frontend/zcc_compile.cpp +++ b/src/common/scripting/frontend/zcc_compile.cpp @@ -1325,7 +1325,7 @@ void ZCCCompiler::CompileAllFields() { // Create copies of the arrays which can be altered auto Classes = this->Classes; - auto Structs = this->Structs; + auto Structs = OrderStructs(); TMap HasNativeChildren; // first step: Look for native classes with native children. @@ -1612,6 +1612,83 @@ bool ZCCCompiler::CompileFields(PContainerType *type, TArray ZCCCompiler::OrderStructs() +{ + TArray new_order; + + for (auto struct_def : Structs) + { + if (std::find(new_order.begin(), new_order.end(), struct_def) != new_order.end()) + { + continue; + } + AddStruct(new_order, struct_def); + } + return new_order; +} + +//========================================================================== +// +// ZCCCompiler :: AddStruct +// +// Adds a struct to the Structs array, preceded by all its dependant structs +// +//========================================================================== + +void ZCCCompiler::AddStruct(TArray &new_order, ZCC_StructWork *my_def) +{ + PStruct *my_type = static_cast(my_def->Type()); + if (my_type) + { + if (my_type->isOrdered) + { + return; + } + my_type->isOrdered = true; + } + + // Find all struct fields and add them before this one + for (const auto field : my_def->Fields) + { + PType *fieldtype = DetermineType(my_type, field, field->Names->Name, field->Type, true, true); + if (fieldtype->isStruct() && !static_cast(fieldtype)->isOrdered) + { + AddStruct(new_order, StructTypeToWork(static_cast(fieldtype))); + } + } + new_order.Push(my_def); +} + +//========================================================================== +// +// ZCCCompiler :: StructTypeToWork +// +// Find the ZCC_StructWork that corresponds to a PStruct +// +//========================================================================== + +ZCC_StructWork *ZCCCompiler::StructTypeToWork(const PStruct *type) const +{ + assert(type->isStruct()); + for (auto &def : Structs) + { + if (def->Type() == type) + { + return def; + } + } + assert(false && "Struct not found"); + return nullptr; +} + //========================================================================== // // ZCCCompiler :: FieldFlagsToString diff --git a/src/common/scripting/frontend/zcc_compile.h b/src/common/scripting/frontend/zcc_compile.h index ca1beb3f25c..adfadaff150 100644 --- a/src/common/scripting/frontend/zcc_compile.h +++ b/src/common/scripting/frontend/zcc_compile.h @@ -135,6 +135,9 @@ class ZCCCompiler PType *DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes, bool formember); PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PContainerType *cls, bool *nosize); PType *ResolveUserType(ZCC_BasicType *type, PSymbolTable *sym, bool nativetype); + TArray OrderStructs(); + void AddStruct(TArray &new_order, ZCC_StructWork *struct_def); + ZCC_StructWork *StructTypeToWork(const PStruct *type) const; void CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool forclass);