public SsaInstruction(SsaBlock parentBlock, Instruction instruction, SsaVariable target, SsaVariable[] operands, Instruction[] prefixes = null, SpecialOpCode specialOpCode = SpecialOpCode.None, TypeReference typeOperand = null) { this.ParentBlock = parentBlock; this.Instruction = instruction; this.Prefixes = prefixes ?? emptyInstructionArray; this.Target = target; this.Operands = operands ?? emptyVariableArray; this.SpecialOpCode = specialOpCode; this.TypeOperand = typeOperand; Debug.Assert((typeOperand != null) == (specialOpCode == SpecialOpCode.Exception || specialOpCode == SpecialOpCode.InitObj)); }
private void MakeByRefCallSimple(SsaBlock block, ref int instructionIndexInBlock, IMethodSignature targetMethod) { SsaInstruction inst = block.Instructions[instructionIndexInBlock]; for (int i = 0; i < inst.Operands.Length; i++) { SsaVariable operand = inst.Operands[i]; if (operand.IsSingleAssignment && operand.Usage.Count == 1 && IsLoadAddress(operand.Definition)) { // address is used for this method call only Instruction loadAddressInstruction = operand.Definition.Instruction; // find target parameter type: bool isOut; if (i == 0 && targetMethod.HasThis) { isOut = false; } else { ParameterDefinition parameter = targetMethod.Parameters[i - (targetMethod.HasThis ? 1 : 0)]; isOut = parameter.IsOut; } SsaVariable addressTakenOf = GetVariableFromLoadAddressInstruction(loadAddressInstruction); // insert "Prepare" instruction on front SpecialOpCode loadOpCode = isOut ? SpecialOpCode.PrepareByOutCall : SpecialOpCode.PrepareByRefCall; block.Instructions.Insert(instructionIndexInBlock++, new SsaInstruction( block, null, operand, new SsaVariable[] { addressTakenOf }, specialOpCode: loadOpCode)); // insert "WriteAfterByRefOrOutCall" instruction after call block.Instructions.Insert(instructionIndexInBlock + 1, new SsaInstruction( block, null, addressTakenOf, new SsaVariable[] { operand }, specialOpCode: SpecialOpCode.WriteAfterByRefOrOutCall)); couldSimplifySomething = true; // remove the loadAddressInstruction later // (later because it might be defined in the current block and we don't want instructionIndex to become invalid) redundantLoadAddressInstructions.Add(operand.Definition); } } }
public SsaInstruction(SsaBlock parentBlock, Instruction instruction, SsaVariable target, SsaVariable[] operands, Instruction[] prefixes = null, SpecialOpCode specialOpCode = SpecialOpCode.None, TypeReference typeOperand = null) { this.ParentBlock = parentBlock; this.Instruction = instruction; this.Prefixes = prefixes ?? emptyInstructionArray; this.Target = target; this.Operands = operands ?? emptyVariableArray; this.SpecialOpCode = specialOpCode; this.TypeOperand = typeOperand; Debug.Assert((typeOperand != null) == (specialOpCode == SpecialOpCode.Exception || specialOpCode == SpecialOpCode.InitObj)); }