diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index 82d82d893..1f7df3dd0 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -8072,7 +8072,6 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) { arraytype = static_cast(Array->ValueType); } - ExpEmit arrayvar = Array->Emit(build); ExpEmit start; ExpEmit bound; bool nestedarray = false; @@ -8080,31 +8079,99 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) if (SizeAddr != ~0u) { bool ismeta = Array->ExprType == EFX_ClassMember && static_cast(Array)->membervar->Flags & VARF_Meta; - - start = ExpEmit(build, REGT_POINTER); - build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0)); - + auto f = Create(NAME_None, TypeUInt32, ismeta? VARF_Meta : 0, SizeAddr); auto arraymemberbase = static_cast(Array); - auto origmembervar = arraymemberbase->membervar; - auto origaddrreq = arraymemberbase->AddressRequested; - auto origvaluetype = Array->ValueType; + if (Array->ExprType == EFX_StructMember || Array->ExprType == EFX_ClassMember) + { + struct DummyVar : public FxExpression + { + ExpEmit dummy; + DummyVar(ExpEmit e) : FxExpression(EFX_Expression,{}), dummy(e){} + ExpEmit Emit(VMFunctionBuilder *build) + { + return dummy; + }; + }; - arraymemberbase->membervar = f; - arraymemberbase->AddressRequested = false; - Array->ValueType = TypeUInt32; + //fix expression bug + FxStructMember * orig = static_cast(Array); + FxExpression * prev = orig->classx; + ExpEmit objvar = prev->Emit(build); + bool wasFixed = objvar.Fixed; - bound = Array->Emit(build); + objvar.Fixed = true; - arraymemberbase->membervar = origmembervar; - arraymemberbase->AddressRequested = origaddrreq; - Array->ValueType = origvaluetype; + orig->classx = new DummyVar(objvar); + orig->classx->ValueType = prev->ValueType; + ExpEmit arrayvar = Array->Emit(build); + start = ExpEmit(build, REGT_POINTER); + delete orig->classx; + orig->classx = prev; - arrayvar.Free(build); + build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0)); + + if(ismeta) + { + // [Jay0] + // ugh do it the old way for meta since i don't want to duplicate that code here, but this time it only double-emits the member access, not the function call, so no bad side-effects, still not "right" though + // TODO handle meta better + + auto origmembervar = arraymemberbase->membervar; + auto origaddrreq = arraymemberbase->AddressRequested; + auto origvaluetype = Array->ValueType; + + arraymemberbase->membervar = f; + arraymemberbase->AddressRequested = false; + Array->ValueType = TypeUInt32; + + bound = Array->Emit(build); + + arraymemberbase->membervar = origmembervar; + arraymemberbase->AddressRequested = origaddrreq; + Array->ValueType = origvaluetype; + } + else + { + bound = ExpEmit(build, REGT_INT); + build->Emit(OP_LW, bound.RegNum, objvar.RegNum, build->GetConstantInt((int)SizeAddr)); + } + + objvar.Fixed = wasFixed; + objvar.Free(build); + arrayvar.Free(build); + } + else + { + // [Jay0] + // now only runs for global variables and stack variables, so the double-emit is """fine""" + // TODO replace this entirely with something better still + + ExpEmit arrayvar = Array->Emit(build); + + start = ExpEmit(build, REGT_POINTER); + build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0)); + + auto origmembervar = arraymemberbase->membervar; + auto origaddrreq = arraymemberbase->AddressRequested; + auto origvaluetype = Array->ValueType; + + arraymemberbase->membervar = f; + arraymemberbase->AddressRequested = false; + Array->ValueType = TypeUInt32; + + bound = Array->Emit(build); + + arraymemberbase->membervar = origmembervar; + arraymemberbase->AddressRequested = origaddrreq; + Array->ValueType = origvaluetype; + arrayvar.Free(build); + } } else if ((Array->ExprType == EFX_ArrayElement || Array->ExprType == EFX_OutVarDereference) && Array->isStaticArray()) { + ExpEmit arrayvar = Array->Emit(build); bound = ExpEmit(build, REGT_INT); build->Emit(OP_LW, bound.RegNum, arrayvar.RegNum, build->GetConstantInt(myoffsetof(FArray, Count))); @@ -8114,7 +8181,10 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) nestedarray = true; } - else start = arrayvar; + else + { + start = Array->Emit(build); + } if (index->isConstant()) {