예제 #1
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);
                }
            }
        }
        static bool CanRemoveAsDeadCode(SsaInstruction inst)
        {
            if (inst.Target != null && !inst.Target.IsSingleAssignment)
            {
                return(false);
            }
            switch (inst.SpecialOpCode)
            {
            case SpecialOpCode.Phi:
            case SpecialOpCode.Exception:
            case SpecialOpCode.Parameter:
            case SpecialOpCode.Uninitialized:
                return(true);

            case SpecialOpCode.None:
                return(inst.IsMoveInstruction);

            default:
                return(false);
            }
        }
예제 #3
0
        private void MakeLoadFieldCallSimple(SsaBlock block, ref int instructionIndexInBlock)
        {
            SsaInstruction inst = block.Instructions[instructionIndexInBlock];

            Debug.Assert(inst.Operands.Length == 1);
            SsaVariable operand = inst.Operands[0];

            if (operand.IsSingleAssignment && operand.Usage.Count == 1 && IsLoadAddress(operand.Definition))
            {
                // insert special "PrepareForFieldAccess" instruction in front
                block.Instructions.Insert(instructionIndexInBlock++, new SsaInstruction(
                                              inst.ParentBlock, null, operand,
                                              new SsaVariable[] { GetVariableFromLoadAddressInstruction(operand.Definition.Instruction) },
                                              specialOpCode: SpecialOpCode.PrepareForFieldAccess));

                couldSimplifySomething = true;

                // remove the loadAddressInstruction later
                redundantLoadAddressInstructions.Add(operand.Definition);
            }
        }
예제 #4
0
        private void MakeInitObjCallSimple(SsaBlock block, ref int instructionIndexInBlock)
        {
            SsaInstruction inst = block.Instructions[instructionIndexInBlock];

            Debug.Assert(inst.Operands.Length == 1);
            SsaVariable operand = inst.Operands[0];

            if (operand.IsSingleAssignment && operand.Usage.Count == 1 && IsLoadAddress(operand.Definition))
            {
                // replace instruction with special "InitObj" instruction
                block.Instructions[instructionIndexInBlock] = new SsaInstruction(
                    inst.ParentBlock, null, GetVariableFromLoadAddressInstruction(operand.Definition.Instruction), null,
                    specialOpCode: SpecialOpCode.InitObj,
                    typeOperand: (TypeReference)inst.Instruction.Operand);

                couldSimplifySomething = true;

                // remove the loadAddressInstruction later
                redundantLoadAddressInstructions.Add(operand.Definition);
            }
        }
예제 #5
0
        public static bool MakeByRefCallsSimple(SsaForm ssaForm)
        {
            SimplifyByRefCalls instance = new SimplifyByRefCalls(ssaForm);

            foreach (SsaBlock block in ssaForm.Blocks)
            {
                for (int i = 0; i < block.Instructions.Count; i++)
                {
                    SsaInstruction inst = block.Instructions[i];
                    if (inst.Instruction != null)
                    {
                        switch (inst.Instruction.OpCode.Code)
                        {
                        case Code.Call:
                        case Code.Callvirt:
                            instance.MakeByRefCallSimple(block, ref i, (IMethodSignature)inst.Instruction.Operand);
                            break;

                        case Code.Initobj:
                            instance.MakeInitObjCallSimple(block, ref i);
                            break;

                        case Code.Ldfld:
                            instance.MakeLoadFieldCallSimple(block, ref i);
                            break;
                        }
                    }
                }
            }
            instance.RemoveRedundantInstructions();
            if (instance.couldSimplifySomething)
            {
                ssaForm.ComputeVariableUsage();
            }
            return(instance.couldSimplifySomething);
        }
예제 #6
0
 static bool IsLoadAddress(SsaInstruction inst)
 {
     return inst.Instruction != null && (inst.Instruction.OpCode == OpCodes.Ldloca || inst.Instruction.OpCode == OpCodes.Ldarga);
 }
예제 #7
0
 private static bool IsLoadAddress(SsaInstruction inst)
 {
     return(inst.Instruction != null && (inst.Instruction.OpCode == OpCodes.Ldloca || inst.Instruction.OpCode == OpCodes.Ldarga));
 }
		static bool CanRemoveAsDeadCode(SsaInstruction inst)
		{
			if (inst.Target != null && !inst.Target.IsSingleAssignment)
				return false;
			switch (inst.SpecialOpCode) {
				case SpecialOpCode.Phi:
				case SpecialOpCode.Exception:
				case SpecialOpCode.Parameter:
				case SpecialOpCode.Uninitialized:
					return true;
				case SpecialOpCode.None:
					return inst.IsMoveInstruction;
				default:
					return false;
			}
		}