public StateData(StateData other, int memVarsCount) { if (other == null) throw new ArgumentNullException("other"); if (memVarsCount < 0) throw new ArgumentOutOfRangeException("memVarsCount"); _registers = (CompilerVar[])other._registers.Clone(); Contract.Assume(_registers.Length == other._registers.Length); UsedGP = other.UsedGP; UsedMM = other.UsedMM; UsedXMM = other.UsedXMM; ChangedGP = other.ChangedGP; ChangedMM = other.ChangedMM; ChangedXMM = other.ChangedXMM; MemVarsData = new CompilerVar[memVarsCount]; }
protected override CompilerItem TranslateImpl(CompilerContext cc) { // translate using Instruction CompilerItem ret = base.TranslateImpl(cc); // we jump with item if it's InstructionCode.JMP (unconditional) and points to yet unknown location. if (Code == InstructionCode.Jmp && !JumpTarget.IsTranslated) { cc.AddBackwardCode(this); ret = JumpTarget; } else { _state = cc.SaveState(); if (JumpTarget.IsTranslated) { DoJump(cc); } else { // state is not known, so we need to call DoJump() later. Compiler will do it for us. cc.AddForwardJump(this); JumpTarget.State = _state; } // Mark next code as unrecheable, cleared by a next label (ETarget). if (Code == InstructionCode.Jmp) { cc.Unreachable = true; } } // Need to traverse over all active variables and unuse them if their scope ends here if (cc.Active != null) { CompilerVar first = cc.Active; CompilerVar var = first; do { cc.UnuseVarOnEndOfScope(this, var); var = var.NextActive; } while (var != first); } return ret; }
internal void RestoreState(StateData state, int targetOffset = Operand.InvalidValue) { // 16 + 8 + 16 = GP + MMX + XMM registers. const int STATE_REGS_COUNT = 16 + 8 + 16; StateData fromState = _state; StateData toState = state; // No change, rare... if (fromState == toState) return; int @base; int i; // TODO: 16 + 8 + 16 is cryptic, make constants instead! // -------------------------------------------------------------------------- // Set target state to all variables. vdata->tempInt is target state in this // function. // -------------------------------------------------------------------------- { // UNUSED. CompilerVar vdata = _active; if (vdata != null) { do { vdata.Temp = VariableState.Unused; vdata = vdata.NextActive; } while (vdata != _active); } // MEMORY. for (i = 0; i < toState.MemVarsData.Length; i++) { toState.MemVarsData[i].Temp = VariableState.Memory; } // REGISTER. for (i = 0; i < StateData.RegisterCount; i++) { if ((vdata = toState.Registers[i]) != null) vdata.Temp = VariableState.Register; } } #if false // -------------------------------------------------------------------------- // [GP-Registers Switch] // -------------------------------------------------------------------------- // TODO. for (i = 0; i < RegNum.GP; i++) { VarData fromVar = fromState.GP[i]; VarData toVar = toState.GP[i]; if (fromVar != toVar) { if (fromVar != null) { if (toVar != null) { if (fromState.GP[to
internal void AssignState(StateData state) { Contract.Requires(state != null); Compiler compiler = Compiler; _state.CopyFrom(state); _state.MemVarsData = new CompilerVar[0]; int i; CompilerVar vdata; // Unuse all variables first. vdata = _active; if (vdata != null) { do { vdata.State = VariableState.Unused; vdata = vdata.NextActive; } while (vdata != _active); } // Assign variables stored in memory which are not unused. for (i = 0; i < state.MemVarsData.Length; i++) { state.MemVarsData[i].State = VariableState.Memory; } // Assign allocated variables. for (i = 0; i < RegNum.GP; i++) { RegisterMask mask = RegisterMask.FromIndex((RegIndex)i); if ((vdata = _state.GP[i]) != null) { vdata.State = VariableState.Register; vdata.RegisterIndex = (RegIndex)i; vdata.Changed = (_state.ChangedGP & mask) != RegisterMask.Zero; } } for (i = 0; i < RegNum.MM; i++) { RegisterMask mask = RegisterMask.FromIndex((RegIndex)i); if ((vdata = _state.MM[i]) != null) { vdata.State = VariableState.Register; vdata.RegisterIndex = (RegIndex)i; vdata.Changed = (_state.ChangedMM & mask) != RegisterMask.Zero; } } for (i = 0; i < RegNum.XMM; i++) { RegisterMask mask = RegisterMask.FromIndex((RegIndex)i); if ((vdata = _state.XMM[i]) != null) { vdata.State = VariableState.Register; vdata.RegisterIndex = (RegIndex)i; vdata.Changed = (_state.ChangedXMM & mask) != RegisterMask.Zero; } } }
protected override CompilerItem TranslateImpl(CompilerContext cc) { // If this Target was already translated, it's needed to change the current // state and return null to tell CompilerContext to process next untranslated // item. if (IsTranslated) { cc.RestoreState(_state); return null; } if (cc.Unreachable) { // If the context has "isUnreachable" flag set and there is no state then // it means that this code will be never called. This is a problem, because // we are unable to assign a state to current location so we can't allocate // registers for variables used inside. So instead of doing anything wrong // we remove the unreachable code. if (_state == null) return RemoveUnreachableItems(); // Assign state to the compiler context. cc.Unreachable = false; cc.AssignState(_state); } else { _state = cc.SaveState(); } return Next; }
internal void CopyFrom(StateData other) { Contract.Requires(other != null); Array.Copy(other._registers, _registers, _registers.Length); UsedGP = other.UsedGP; UsedMM = other.UsedMM; UsedXMM = other.UsedXMM; ChangedGP = other.ChangedGP; ChangedMM = other.ChangedMM; ChangedXMM = other.ChangedXMM; }