From 1450c3dffb1e432cf4baccbe9218c310c9ba0bc9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 21 Oct 2016 10:09:01 +0200 Subject: [PATCH] - tested and fixed the regular assignment statement for both local and member variables. The generated object code can definitely use an optimization pass but that's something left for later when more things are working. Right now it creates one opcode more than necessary for all member accesses (instead of using the offset in the store command it calculates an actual address of the variable in another address register) and can create one too many for non-constant expressions being assigned to local variables (a move between two registers because the emitted expression on the right hand side does not know that it can emit to the actual variable's register.) --- src/scripting/codegeneration/codegen.cpp | 13 +++--- src/scripting/codegeneration/codegen.h | 4 +- src/scripting/vm/vmbuilder.cpp | 4 ++ src/scripting/zscript/zcc_compile.cpp | 54 ++++++++++++------------ 4 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index d3e7ef029..1b169411f 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -179,7 +179,7 @@ FxLocalVariableDeclaration *FCompileContext::FindLocalVariable(FName name) //========================================================================== ExpEmit::ExpEmit(VMFunctionBuilder *build, int type) -: RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false), Fixed(false), Final(false) +: RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false), Fixed(false), Final(false), Target(false) { } @@ -1807,16 +1807,16 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) ExpEmit FxAssign::Emit(VMFunctionBuilder *build) { - static const BYTE loadops[] = { OP_NOP, OP_LK, OP_LKF, OP_LKS, OP_LKP }; + static const BYTE loadops[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP }; assert(ValueType == Base->ValueType && IsNumeric()); assert(ValueType->GetRegType() == Right->ValueType->GetRegType()); - ExpEmit pointer = Base->Emit(build); - Address = pointer; - ExpEmit result = Right->Emit(build); assert(result.RegType <= REGT_TYPE); + ExpEmit pointer = Base->Emit(build); + Address = pointer; + if (pointer.Target) { if (result.Konst) @@ -4025,6 +4025,7 @@ FxLocalVariable::FxLocalVariable(FxLocalVariableDeclaration *var, const FScriptP : FxExpression(sc) { Variable = var; + ValueType = var->ValueType; AddressRequested = false; } @@ -5167,7 +5168,7 @@ FxExpression *FxCompoundStatement::Resolve(FCompileContext &ctx) ctx.Block = this; auto x = FxSequence::Resolve(ctx); ctx.Block = outer; - return this; + return x; } //========================================================================== diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 7a69f3989..525325276 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -193,8 +193,8 @@ struct ExpVal struct ExpEmit { - ExpEmit() : RegNum(0), RegType(REGT_NIL), Konst(false), Fixed(false), Final(false) {} - ExpEmit(int reg, int type, bool konst = false, bool fixed = false) : RegNum(reg), RegType(type), Konst(konst), Fixed(fixed), Final(false) {} + ExpEmit() : RegNum(0), RegType(REGT_NIL), Konst(false), Fixed(false), Final(false), Target(false) {} + ExpEmit(int reg, int type, bool konst = false, bool fixed = false) : RegNum(reg), RegType(type), Konst(konst), Fixed(fixed), Final(false), Target(false) {} ExpEmit(VMFunctionBuilder *build, int type); void Free(VMFunctionBuilder *build); void Reuse(VMFunctionBuilder *build); diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 0ba697495..a5f15b262 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -682,6 +682,10 @@ void FFunctionBuildList::Build() for (auto &item : mItems) { + if (item.PrintableName.CompareNoCase("Middle.StateFunction.3") == 0) + { + int a = 0; + } assert(item.Code != NULL); // We don't know the return type in advance for anonymous functions. diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index d5b3a2705..eb039f996 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2354,33 +2354,6 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) // todo. break; - case AST_AssignStmt: - { - auto assign = static_cast(ast); - switch (assign->AssignOp) - { - case ZCC_EQ: - // this ignores multi-assign statements (these should probably be disabled in the grammar.) - return new FxAssign(ConvertNode(assign->Dests), ConvertNode(assign->Sources)); - - case ZCC_MULEQ: - case ZCC_DIVEQ: - case ZCC_MODEQ: - case ZCC_ADDEQ: - case ZCC_SUBEQ: - case ZCC_LSHEQ: - case ZCC_RSHEQ: - case ZCC_ANDEQ: - case ZCC_OREQ: - case ZCC_XOREQ: - //break; - default: - Error(ast, "Invalid assign statement"); - - } - break; - } - case AST_ExprBinary: // Array syntax for randoms. They are internally stored as ExprBinary with both an identifier on the left and right side. if (fcall->Function->Operation == PEX_ArrayAccess) @@ -2400,6 +2373,33 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) break; } + case AST_AssignStmt: + { + auto assign = static_cast(ast); + switch (assign->AssignOp) + { + case ZCC_EQ: + // this ignores multi-assign statements (these should probably be disabled in the grammar.) + return new FxAssign(ConvertNode(assign->Dests), ConvertNode(assign->Sources)); + + case ZCC_MULEQ: + case ZCC_DIVEQ: + case ZCC_MODEQ: + case ZCC_ADDEQ: + case ZCC_SUBEQ: + case ZCC_LSHEQ: + case ZCC_RSHEQ: + case ZCC_ANDEQ: + case ZCC_OREQ: + case ZCC_XOREQ: + //break; + default: + Error(ast, "Invalid assign statement"); + + } + break; + } + case AST_FuncParm: { auto fparm = static_cast(ast);