mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 23:02:08 +00:00
Generalize FxArrayElement to work with all numeric elements (not just 32-bit ints)
This commit is contained in:
parent
0cc2705b99
commit
3357af32e5
2 changed files with 23 additions and 10 deletions
|
@ -2994,10 +2994,10 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueType = arraytype->ElementType;
|
ValueType = arraytype->ElementType;
|
||||||
if (ValueType->GetRegType() != REGT_INT)
|
if (ValueType->GetRegType() != REGT_INT && ValueType->GetRegType() != REGT_FLOAT)
|
||||||
{
|
{
|
||||||
// int arrays only for now
|
// 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;
|
delete this;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -3014,7 +3014,10 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
|
||||||
ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
|
ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
ExpEmit start = Array->Emit(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)
|
if (start.Konst)
|
||||||
{
|
{
|
||||||
ExpEmit tmpstart(build, REGT_POINTER);
|
ExpEmit tmpstart(build, REGT_POINTER);
|
||||||
|
@ -3024,19 +3027,30 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
|
||||||
if (index->isConstant())
|
if (index->isConstant())
|
||||||
{
|
{
|
||||||
unsigned indexval = static_cast<FxConstant *>(index)->GetValue().GetInt();
|
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");
|
I_Error("Array index out of bounds");
|
||||||
}
|
}
|
||||||
indexval <<= 2;
|
indexval *= arraytype->ElementSize;
|
||||||
build->Emit(OP_LW, dest.RegNum, start.RegNum, build->GetConstantInt(indexval));
|
build->Emit(arraytype->ElementType->GetLoadOp(), dest.RegNum,
|
||||||
|
start.RegNum, build->GetConstantInt(indexval));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ExpEmit indexv(index->Emit(build));
|
ExpEmit indexv(index->Emit(build));
|
||||||
build->Emit(OP_SLL_RI, indexv.RegNum, indexv.RegNum, 2);
|
int shiftbits = 0;
|
||||||
build->Emit(OP_BOUND, indexv.RegNum, static_cast<PArray*>(Array->ValueType)->ElementCount);
|
while (1 << shiftbits < arraytype->ElementSize)
|
||||||
build->Emit(OP_LW_R, dest.RegNum, start.RegNum, indexv.RegNum);
|
{
|
||||||
|
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);
|
indexv.Free(build);
|
||||||
}
|
}
|
||||||
start.Free(build);
|
start.Free(build);
|
||||||
|
|
|
@ -588,7 +588,6 @@ static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cl
|
||||||
sym->Offset = cls->Extend(type);
|
sym->Offset = cls->Extend(type);
|
||||||
if (symt->AddSymbol(sym) == NULL)
|
if (symt->AddSymbol(sym) == NULL)
|
||||||
{
|
{
|
||||||
delete sym;
|
|
||||||
sc.ScriptMessage ("'%s' is already defined in '%s'.",
|
sc.ScriptMessage ("'%s' is already defined in '%s'.",
|
||||||
symname.GetChars(), cls ? cls->TypeName.GetChars() : "Global");
|
symname.GetChars(), cls ? cls->TypeName.GetChars() : "Global");
|
||||||
FScriptPosition::ErrorCounter++;
|
FScriptPosition::ErrorCounter++;
|
||||||
|
|
Loading…
Reference in a new issue