Generalize FxArrayElement to work with all numeric elements (not just 32-bit ints)

This commit is contained in:
Randy Heit 2016-04-03 16:07:51 -05:00
parent 0cc2705b99
commit 3357af32e5
2 changed files with 23 additions and 10 deletions

View file

@ -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<PArray*>(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<FxConstant *>(index)->GetValue().GetInt();
if (indexval >= static_cast<PArray*>(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<PArray*>(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);

View file

@ -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++;