From 96b2cb0a4586d80da29f0482389ac50b69de2f69 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 6 Feb 2017 22:57:42 +0100 Subject: [PATCH] - fixed code generation for local dynamic arrays. - removed some code repetition by inherit all variable types which reference a PField for a variable offset from a base class so that PField replacements can be done with one set of code. --- src/scripting/codegeneration/codegen.cpp | 130 ++++------------------- src/scripting/codegeneration/codegen.h | 33 +++--- 2 files changed, 41 insertions(+), 122 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index fadc172694..f59320fa6e 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -6368,11 +6368,8 @@ ExpEmit FxClassDefaults::Emit(VMFunctionBuilder *build) //========================================================================== FxGlobalVariable::FxGlobalVariable(PField* mem, const FScriptPosition &pos) - : FxExpression(EFX_GlobalVariable, pos) + : FxMemberBase(EFX_GlobalVariable, mem, pos) { - membervar = mem; - AddressRequested = false; - AddressWritable = true; // must be true unless classx tells us otherwise if requested. } //========================================================================== @@ -6548,11 +6545,8 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build) //========================================================================== FxStackVariable::FxStackVariable(PType *type, int offset, const FScriptPosition &pos) - : FxExpression(EFX_StackVariable, pos) + : FxMemberBase(EFX_StackVariable, new PField(NAME_None, type, 0, offset), pos) { - membervar = new PField(NAME_None, type, 0, offset); - AddressRequested = false; - AddressWritable = true; // must be true unless classx tells us otherwise if requested. } //========================================================================== @@ -6651,14 +6645,16 @@ ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build) // // //========================================================================== +FxMemberBase::FxMemberBase(EFxType type, PField *f, const FScriptPosition &p) + :FxExpression(type, p), membervar(f) +{ +} + FxStructMember::FxStructMember(FxExpression *x, PField* mem, const FScriptPosition &pos) - : FxExpression(EFX_StructMember, pos) + : FxMemberBase(EFX_StructMember, mem, pos) { classx = x; - membervar = mem; - AddressRequested = false; - AddressWritable = true; // must be true unless classx tells us otherwise if requested. } //========================================================================== @@ -6730,35 +6726,13 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) else if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PStruct))) { // if this is a struct within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset. - if (classx->ExprType == EFX_ClassMember || classx->ExprType == EFX_StructMember) + if (classx->ExprType == EFX_ClassMember || classx->ExprType == EFX_StructMember || classx->ExprType == EFX_GlobalVariable || classx->ExprType == EFX_StackVariable) { - auto parentfield = static_cast(classx)->membervar; + auto parentfield = static_cast(classx)->membervar; // PFields are garbage collected so this will be automatically taken care of later. auto newfield = new PField(membervar->SymbolName, membervar->Type, membervar->Flags | parentfield->Flags, membervar->Offset + parentfield->Offset); newfield->BitValue = membervar->BitValue; - static_cast(classx)->membervar = newfield; - classx->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. - auto x = classx->Resolve(ctx); - classx = nullptr; - return x; - } - else if (classx->ExprType == EFX_GlobalVariable) - { - auto parentfield = static_cast(classx)->membervar; - auto newfield = new PField(membervar->SymbolName, membervar->Type, membervar->Flags | parentfield->Flags, membervar->Offset + parentfield->Offset); - newfield->BitValue = membervar->BitValue; - static_cast(classx)->membervar = newfield; - classx->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. - auto x = classx->Resolve(ctx); - classx = nullptr; - return x; - } - else if (classx->ExprType == EFX_StackVariable) - { - auto parentfield = static_cast(classx)->membervar; - auto newfield = new PField(membervar->SymbolName, membervar->Type, membervar->Flags | parentfield->Flags, membervar->Offset + parentfield->Offset); - newfield->BitValue = membervar->BitValue; - static_cast(classx)->ReplaceField(newfield); + static_cast(classx)->membervar = newfield; classx->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. auto x = classx->Resolve(ctx); classx = nullptr; @@ -6977,19 +6951,9 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) if (Array->IsResizableArray()) { // if this is an array within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset. - if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember) + if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember || Array->ExprType == EFX_GlobalVariable || Array->ExprType == EFX_StackVariable) { - auto parentfield = static_cast(Array)->membervar; - SizeAddr = parentfield->Offset + sizeof(void*); - } - else if (Array->ExprType == EFX_GlobalVariable) - { - auto parentfield = static_cast(Array)->membervar; - SizeAddr = parentfield->Offset + sizeof(void*); - } - else if (Array->ExprType == EFX_StackVariable) - { - auto parentfield = static_cast(Array)->membervar; + auto parentfield = static_cast(Array)->membervar; SizeAddr = parentfield->Offset + sizeof(void*); } else @@ -7011,32 +6975,12 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) } // if this is an array within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset. - if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember) + if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember || Array->ExprType == EFX_GlobalVariable || Array->ExprType == EFX_StackVariable) { - auto parentfield = static_cast(Array)->membervar; + auto parentfield = static_cast(Array)->membervar; // PFields are garbage collected so this will be automatically taken care of later. auto newfield = new PField(NAME_None, elementtype, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset); - static_cast(Array)->membervar = newfield; - Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. - auto x = Array->Resolve(ctx); - Array = nullptr; - return x; - } - else if (Array->ExprType == EFX_GlobalVariable) - { - auto parentfield = static_cast(Array)->membervar; - auto newfield = new PField(NAME_None, elementtype, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset); - static_cast(Array)->membervar = newfield; - Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. - auto x = Array->Resolve(ctx); - Array = nullptr; - return x; - } - else if (Array->ExprType == EFX_StackVariable) - { - auto parentfield = static_cast(Array)->membervar; - auto newfield = new PField(NAME_None, elementtype, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset); - static_cast(Array)->ReplaceField(newfield); + static_cast(Array)->membervar = newfield; Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. auto x = Array->Resolve(ctx); Array = nullptr; @@ -7083,17 +7027,8 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0)); auto f = new PField(NAME_None, TypeUInt32, 0, SizeAddr); - if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember) - { - static_cast(Array)->membervar = f; - static_cast(Array)->AddressRequested = false; - } - else if (Array->ExprType == EFX_GlobalVariable) - { - static_cast(Array)->membervar = f; - static_cast(Array)->AddressRequested = false; - } - + static_cast(Array)->membervar = f; + static_cast(Array)->AddressRequested = false; Array->ValueType = TypeUInt32; bound = Array->Emit(build); } @@ -7849,9 +7784,9 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) a->ValueType = NewPointer(backingtype); // Also change the field's type so the code generator can work with this (actually this requires swapping out the entire field.) - if (Self->ExprType == EFX_StructMember || Self->ExprType == EFX_ClassMember) + if (Self->ExprType == EFX_StructMember || Self->ExprType == EFX_ClassMember || Self->ExprType == EFX_StackVariable) { - auto member = static_cast(a); + auto member = static_cast(a); auto newfield = new PField(NAME_None, backingtype, 0, member->membervar->Offset); member->membervar = newfield; Self = nullptr; @@ -7859,17 +7794,6 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) member->ValueType = TypeUInt32; return member; } - else if (Self->ExprType == EFX_StackVariable) - { - auto member = static_cast(Self); - auto newfield = new PField(NAME_None, backingtype, 0, member->membervar->Offset); - member->membervar = newfield; - Self = nullptr; - delete this; - member->ValueType = TypeUInt32; - return member; - } - } else if (a->IsPointer() && Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) { @@ -7908,19 +7832,9 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) else { // Resizable arrays can only be defined in C code and they can only exist in pointer form to reduce their impact on the code generator. - if (Self->ExprType == EFX_StructMember || Self->ExprType == EFX_ClassMember) + if (Self->ExprType == EFX_StructMember || Self->ExprType == EFX_ClassMember || Self->ExprType == EFX_GlobalVariable) { - auto member = static_cast(Self); - auto newfield = new PField(NAME_None, TypeUInt32, VARF_ReadOnly, member->membervar->Offset + member->membervar->Type->Align); // the size is stored right behind the pointer. - member->membervar = newfield; - Self = nullptr; - delete this; - member->ValueType = TypeUInt32; - return member; - } - else if (Self->ExprType == EFX_GlobalVariable) - { - auto member = static_cast(Self); + auto member = static_cast(Self); auto newfield = new PField(NAME_None, TypeUInt32, VARF_ReadOnly, member->membervar->Offset + member->membervar->Type->Align); // the size is stored right behind the pointer. member->membervar = newfield; Self = nullptr; diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index c3af917296..c64ec20941 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -1314,19 +1314,30 @@ public: }; +//========================================================================== +// +// FxMemberBase +// +//========================================================================== + +class FxMemberBase : public FxExpression +{ +public: + PField *membervar; + bool AddressRequested = false; + bool AddressWritable = true; + FxMemberBase(EFxType type, PField *f, const FScriptPosition &p); +}; + //========================================================================== // // FxGlobalVariaböe // //========================================================================== -class FxGlobalVariable : public FxExpression +class FxGlobalVariable : public FxMemberBase { public: - PField *membervar; - bool AddressRequested; - bool AddressWritable; - FxGlobalVariable(PField*, const FScriptPosition&); FxExpression *Resolve(FCompileContext&); bool RequestAddress(FCompileContext &ctx, bool *writable); @@ -1343,19 +1354,17 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; + //========================================================================== // // FxClassMember // //========================================================================== -class FxStructMember : public FxExpression +class FxStructMember : public FxMemberBase { public: FxExpression *classx; - PField *membervar; - bool AddressRequested; - bool AddressWritable; FxStructMember(FxExpression*, PField*, const FScriptPosition&); ~FxStructMember(); @@ -1403,13 +1412,9 @@ public: // //========================================================================== -class FxStackVariable : public FxExpression +class FxStackVariable : public FxMemberBase { public: - PField *membervar; - bool AddressRequested; - bool AddressWritable; - FxStackVariable(PType *type, int offset, const FScriptPosition&); ~FxStackVariable(); void ReplaceField(PField *newfield);