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));
 }
Exemplo n.º 2
0
        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));
		}