/// <summary> /// Retrieves the local stack operand at the specified <paramref name="index"/>. /// </summary> /// <param name="index">The index of the stack operand to retrieve.</param> /// <returns>The operand at the specified index.</returns> /// <exception cref="System.ArgumentOutOfRangeException">The <paramref name="index"/> is not valid.</exception> public Operand GetLocalOperand(int index) { // HACK: Returning a new instance here breaks object identity. We should reuse operands, // which represent the same memory location. If we need to move a variable in an optimization // stage to a different memory location, it should actually be a new one so sharing object // only saves runtime space/perf. Debug.Assert(_localsSig != null, "Method doesn't have _locals."); Debug.Assert(index <= _localsSig.Types.Length, "Invalid local index requested."); if (_localsSig == null || _localsSig.Types.Length <= index) { throw new ArgumentOutOfRangeException("index", index, "Invalid parameter index"); } Operand local = null; if (_locals.Count > index) { local = _locals[index]; } if (local == null) { local = new LocalVariableOperand(_architecture.StackFrameRegister, String.Format("L_{0}", index), index, _localsSig.Types[index]); _locals[index] = local; } return(local); }
/// <summary> /// Retrieves the local stack operand at the specified <paramref name="index"/>. /// </summary> /// <param name="index">The index of the stack operand to retrieve.</param> /// <returns>The operand at the specified index.</returns> /// <exception cref="System.ArgumentOutOfRangeException">The <paramref name="index"/> is not valid.</exception> public Operand GetLocalOperand(int index) { // HACK: Returning a new instance here breaks object identity. We should reuse operands, // which represent the same memory location. If we need to move a variable in an optimization // stage to a different memory location, it should actually be a new one so sharing object // only saves runtime space/perf. // PG: Isn't that implemented below? Comment seems out of date with code Debug.Assert(localsSig != null, @"Method doesn't have locals."); Debug.Assert(index < localsSig.Locals.Length, @"Invalid local index requested."); if (localsSig == null || localsSig.Locals.Length < index) { throw new ArgumentOutOfRangeException(@"index", index, @"Invalid parameter index"); } Operand local = locals[index]; if (local == null) { VariableSignature localVariable = localsSig.Locals[index]; //ScheduleDependencyForCompilation(localVariable.Type); local = new LocalVariableOperand(architecture.StackFrameRegister, String.Format("L_{0}", index), index, localVariable.Type); locals[index] = local; } return(local); }
/// <summary> /// Collects all local variables assignments into a list. /// </summary> /// <param name="locals">Holds all locals found by the stage.</param> /// <param name="block">The block.</param> private void CollectLocalVariables(List <StackOperand> locals, BasicBlock block) { for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext()) { // Does this instruction define a new stack variable? foreach (Operand op in ctx.Results) { // The instruction list may not be in SSA form, so we have to check existence again here unfortunately. // FIXME: Allow us to detect the state of blocks LocalVariableOperand lvop = op as LocalVariableOperand; if (lvop != null && !locals.Contains(lvop)) { locals.Add(lvop); } } } }