- added implicit initialization of reused register variables in ZScript

This commit is contained in:
alexey.lysiuk 2019-06-01 16:54:24 +03:00 committed by Rachael Alexanderson
parent d3e6ed3c9b
commit 6f1df5b5ab
3 changed files with 57 additions and 2 deletions

View file

@ -11350,8 +11350,51 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build)
{ {
if (RegNum == -1) if (RegNum == -1)
{ {
if (!(VarFlags & VARF_Out)) RegNum = build->Registers[ValueType->GetRegType()].Get(RegCount); if (!(VarFlags & VARF_Out))
else RegNum = build->Registers[REGT_POINTER].Get(1); {
const int regType = ValueType->GetRegType();
assert(regType <= REGT_TYPE);
auto& registers = build->Registers[regType];
RegNum = registers.Get(RegCount);
for (int reg = RegNum, end = RegNum + RegCount; reg < end; ++reg)
{
if (!registers.IsDirty(reg))
{
continue;
}
ScriptPosition.Message(MSG_DEBUGMSG, "Implicit initialization of variable %s\n", Name.GetChars());
switch (regType)
{
case REGT_INT:
build->Emit(OP_LI, reg, 0, 0);
break;
case REGT_FLOAT:
build->Emit(OP_LKF, reg, build->GetConstantFloat(0.0));
break;
case REGT_STRING:
build->Emit(OP_LKS, reg, build->GetConstantString(nullptr));
break;
case REGT_POINTER:
build->Emit(OP_LKP, reg, build->GetConstantAddress(nullptr));
break;
default:
assert(false);
break;
}
}
}
else
{
RegNum = build->Registers[REGT_POINTER].Get(1);
}
} }
} }
else else

View file

@ -367,6 +367,7 @@ void VMFunctionBuilder::ParamChange(int delta)
VMFunctionBuilder::RegAvailability::RegAvailability() VMFunctionBuilder::RegAvailability::RegAvailability()
{ {
memset(Used, 0, sizeof(Used)); memset(Used, 0, sizeof(Used));
memset(Dirty, 0, sizeof(Dirty));
MostUsed = 0; MostUsed = 0;
} }
@ -493,16 +494,19 @@ void VMFunctionBuilder::RegAvailability::Return(int reg, int count)
// because for that case it pushes the self pointer a second time without reallocating, so it gets freed twice. // because for that case it pushes the self pointer a second time without reallocating, so it gets freed twice.
//assert((Used[firstword] & mask) == mask); //assert((Used[firstword] & mask) == mask);
Used[firstword] &= ~mask; Used[firstword] &= ~mask;
Dirty[firstword] |= mask;
} }
else else
{ // Range is in two words. { // Range is in two words.
partialmask = mask << firstbit; partialmask = mask << firstbit;
assert((Used[firstword] & partialmask) == partialmask); assert((Used[firstword] & partialmask) == partialmask);
Used[firstword] &= ~partialmask; Used[firstword] &= ~partialmask;
Dirty[firstword] |= partialmask;
partialmask = mask >> (32 - firstbit); partialmask = mask >> (32 - firstbit);
assert((Used[firstword + 1] & partialmask) == partialmask); assert((Used[firstword + 1] & partialmask) == partialmask);
Used[firstword + 1] &= ~partialmask; Used[firstword + 1] &= ~partialmask;
Dirty[firstword + 1] |= partialmask;
} }
} }

View file

@ -37,8 +37,16 @@ public:
void Return(int reg, int count); void Return(int reg, int count);
bool Reuse(int regnum); bool Reuse(int regnum);
bool IsDirty(int reg) const
{
const int firstword = reg / 32;
const int firstbit = reg & 31;
return Dirty[firstword] & (1 << firstbit);
}
private: private:
VM_UWORD Used[256/32]; // Bitmap of used registers (bit set means reg is used) VM_UWORD Used[256/32]; // Bitmap of used registers (bit set means reg is used)
VM_UWORD Dirty[256/32];
int MostUsed; int MostUsed;
friend class VMFunctionBuilder; friend class VMFunctionBuilder;