PageRenderTime 42ms CodeModel.GetById 15ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 0ms

/ICSharpCode.Decompiler/FlowAnalysis/SsaInstruction.cs

http://github.com/icsharpcode/ILSpy
C# | 191 lines | 111 code | 14 blank | 66 comment | 33 complexity | eb6ef6c763e310373acf269bc2f50824 MD5 | raw file
  1// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
  2// 
  3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
  4// software and associated documentation files (the "Software"), to deal in the Software
  5// without restriction, including without limitation the rights to use, copy, modify, merge,
  6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
  7// to whom the Software is furnished to do so, subject to the following conditions:
  8// 
  9// The above copyright notice and this permission notice shall be included in all copies or
 10// substantial portions of the Software.
 11// 
 12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
 15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 17// DEALINGS IN THE SOFTWARE.
 18
 19using System;
 20using System.Diagnostics;
 21using System.IO;
 22
 23using ICSharpCode.Decompiler.Disassembler;
 24using Mono.Cecil;
 25using Mono.Cecil.Cil;
 26
 27namespace ICSharpCode.Decompiler.FlowAnalysis
 28{
 29	public enum SpecialOpCode
 30	{
 31		/// <summary>
 32		/// No special op code: SsaInstruction has a normal IL instruction
 33		/// </summary>
 34		None,
 35		/// <summary>
 36		/// Φ function: chooses the appropriate variable based on which CFG edge was used to enter this block
 37		/// </summary>
 38		Phi,
 39		/// <summary>
 40		/// Variable is read from before passing it by ref.
 41		/// This instruction constructs a managed reference to the variable.
 42		/// </summary>
 43		PrepareByRefCall,
 44		/// <summary>
 45		/// This instruction constructs a managed reference to the variable.
 46		/// The variable is not really read from.
 47		/// </summary>
 48		PrepareByOutCall,
 49		/// <summary>
 50		/// This instruction constructs a managed reference to the variable.
 51		/// The reference is used for a field access on a value type.
 52		/// </summary>
 53		PrepareForFieldAccess,
 54		/// <summary>
 55		/// Variable is written to after passing it by ref or out.
 56		/// </summary>
 57		WriteAfterByRefOrOutCall,
 58		/// <summary>
 59		/// Variable is not initialized.
 60		/// </summary>
 61		Uninitialized,
 62		/// <summary>
 63		/// Value is passed in as parameter
 64		/// </summary>
 65		Parameter,
 66		/// <summary>
 67		/// Value is a caught exception.
 68		/// TypeOperand is set to the exception type.
 69		/// </summary>
 70		Exception,
 71		/// <summary>
 72		/// Initialize a value type. Unlike the real initobj instruction, this one does not take an address
 73		/// but assigns to the target variable.
 74		/// TypeOperand is set to the type being created.
 75		/// </summary>
 76		InitObj
 77	}
 78	
 79	public sealed class SsaInstruction
 80	{
 81		public readonly SsaBlock ParentBlock;
 82		public readonly SpecialOpCode SpecialOpCode;
 83		
 84		/// <summary>
 85		/// The original IL instruction.
 86		/// May be null for "invented" instructions (SpecialOpCode != None).
 87		/// </summary>
 88		public readonly Instruction Instruction;
 89		
 90		/// <summary>
 91		/// Prefixes in front of the IL instruction.
 92		/// </summary>
 93		public readonly Instruction[] Prefixes;
 94		
 95		/// <summary>
 96		/// Gets the type operand. This is used only in combination with some special opcodes.
 97		/// </summary>
 98		public readonly TypeReference TypeOperand;
 99		
100		public SsaVariable Target;
101		public SsaVariable[] Operands;
102		
103		static readonly SsaVariable[] emptyVariableArray = {};
104		static readonly Instruction[] emptyInstructionArray = {};
105		
106		public SsaInstruction(SsaBlock parentBlock, Instruction instruction, SsaVariable target, SsaVariable[] operands,
107		                      Instruction[] prefixes = null, SpecialOpCode specialOpCode = SpecialOpCode.None,
108		                      TypeReference typeOperand = null)
109		{
110			this.ParentBlock = parentBlock;
111			this.Instruction = instruction;
112			this.Prefixes = prefixes ?? emptyInstructionArray;
113			this.Target = target;
114			this.Operands = operands ?? emptyVariableArray;
115			this.SpecialOpCode = specialOpCode;
116			this.TypeOperand = typeOperand;
117			Debug.Assert((typeOperand != null) == (specialOpCode == SpecialOpCode.Exception || specialOpCode == SpecialOpCode.InitObj));
118		}
119		
120		/// <summary>
121		/// Gets whether this instruction is a simple assignment from one variable to another.
122		/// </summary>
123		public bool IsMoveInstruction {
124			get {
125				return Target != null && Operands.Length == 1 && Instruction != null && OpCodeInfo.Get(Instruction.OpCode).IsMoveInstruction;
126			}
127		}
128		
129		public void ReplaceVariableInOperands(SsaVariable oldVar, SsaVariable newVar)
130		{
131			for (int i = 0; i < this.Operands.Length; i++) {
132				if (this.Operands[i] == oldVar)
133					this.Operands[i] = newVar;
134			}
135		}
136		
137		public override string ToString()
138		{
139			StringWriter w = new StringWriter();
140			WriteTo(w);
141			return w.ToString();
142		}
143		
144		public void WriteTo(TextWriter writer)
145		{
146			foreach (Instruction prefix in this.Prefixes) {
147				Disassembler.DisassemblerHelpers.WriteTo(prefix, new PlainTextOutput(writer));
148				writer.WriteLine();
149			}
150			if (Instruction != null && Instruction.Offset >= 0) {
151				writer.Write(CecilExtensions.OffsetToString(Instruction.Offset));
152				writer.Write(": ");
153			}
154			if (Target != null) {
155				writer.Write(Target.ToString());
156				writer.Write(" = ");
157			}
158			if (IsMoveInstruction) {
159				writer.Write(Operands[0].ToString());
160				if (Instruction != null) {
161					writer.Write(" (" + Instruction.OpCode.Name + ")");
162				}
163			} else {
164				if (Instruction == null) {
165					writer.Write(SpecialOpCode.ToString());
166				} else {
167					writer.Write(Instruction.OpCode.Name);
168					if(null != Instruction.Operand) {
169						writer.Write(' ');
170						Disassembler.DisassemblerHelpers.WriteOperand(new PlainTextOutput(writer), Instruction.Operand);
171						writer.Write(' ');
172					}
173				}
174				if (TypeOperand != null) {
175					writer.Write(' ');
176					writer.Write(TypeOperand.ToString());
177					writer.Write(' ');
178				}
179				if (Operands.Length > 0) {
180					writer.Write('(');
181					for (int i = 0; i < Operands.Length; i++) {
182						if (i > 0)
183							writer.Write(", ");
184						writer.Write(Operands[i].ToString());
185					}
186					writer.Write(')');
187				}
188			}
189		}
190	}
191}