From 3357af32e59ef8be735685a941c5c5a44cb5fd7e Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 3 Apr 2016 16:07:51 -0500 Subject: [PATCH] Generalize FxArrayElement to work with all numeric elements (not just 32-bit ints) --- src/thingdef/thingdef_expression.cpp | 32 ++++++++++++++++++++-------- src/thingdef/thingdef_parse.cpp | 1 - 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 7ecc3c3c47..0312126d45 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -2994,10 +2994,10 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) } ValueType = arraytype->ElementType; - if (ValueType->GetRegType() != REGT_INT) + if (ValueType->GetRegType() != REGT_INT && ValueType->GetRegType() != REGT_FLOAT) { // int arrays only for now - ScriptPosition.Message(MSG_ERROR, "Only integer arrays are supported."); + ScriptPosition.Message(MSG_ERROR, "Only numeric arrays are supported."); delete this; return NULL; } @@ -3014,7 +3014,10 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) { ExpEmit start = Array->Emit(build); - ExpEmit dest(build, REGT_INT); + PArray *const arraytype = static_cast(Array->ValueType); + PType *const elementtype = arraytype->ElementType; + ExpEmit dest(build, elementtype->GetRegType()); + if (start.Konst) { ExpEmit tmpstart(build, REGT_POINTER); @@ -3024,19 +3027,30 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) if (index->isConstant()) { unsigned indexval = static_cast(index)->GetValue().GetInt(); - if (indexval >= static_cast(Array->ValueType)->ElementCount) + if (indexval >= arraytype->ElementCount) { I_Error("Array index out of bounds"); } - indexval <<= 2; - build->Emit(OP_LW, dest.RegNum, start.RegNum, build->GetConstantInt(indexval)); + indexval *= arraytype->ElementSize; + build->Emit(arraytype->ElementType->GetLoadOp(), dest.RegNum, + start.RegNum, build->GetConstantInt(indexval)); } else { ExpEmit indexv(index->Emit(build)); - build->Emit(OP_SLL_RI, indexv.RegNum, indexv.RegNum, 2); - build->Emit(OP_BOUND, indexv.RegNum, static_cast(Array->ValueType)->ElementCount); - build->Emit(OP_LW_R, dest.RegNum, start.RegNum, indexv.RegNum); + int shiftbits = 0; + while (1 << shiftbits < arraytype->ElementSize) + { + shiftbits++; + } + assert(1 << shiftbits == arraytype->ElementSize && "Element sizes other than power of 2 are not implemented"); + build->Emit(OP_BOUND, indexv.RegNum, arraytype->ElementCount); + if (shiftbits > 0) + { + build->Emit(OP_SLL_RI, indexv.RegNum, indexv.RegNum, shiftbits); + } + build->Emit(arraytype->ElementType->GetLoadOp() + 1, // added 1 to use the *_R version that + dest.RegNum, start.RegNum, indexv.RegNum); // takes the offset from a register indexv.Free(build); } start.Free(build); diff --git a/src/thingdef/thingdef_parse.cpp b/src/thingdef/thingdef_parse.cpp index cc2c71e34b..3119305086 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/thingdef/thingdef_parse.cpp @@ -588,7 +588,6 @@ static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cl sym->Offset = cls->Extend(type); if (symt->AddSymbol(sym) == NULL) { - delete sym; sc.ScriptMessage ("'%s' is already defined in '%s'.", symname.GetChars(), cls ? cls->TypeName.GetChars() : "Global"); FScriptPosition::ErrorCounter++;