diff options
author | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 13:02:25 -0700 |
---|---|---|
committer | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 16:13:41 -0700 |
commit | 17fdde66d94155fc62a034fa6658995bef6fd6e5 (patch) | |
tree | b5e5073a2a7b15cdbe826faa5c763e270a505729 /ICSharpCode.Decompiler/FlowAnalysis/SsaInstruction.cs | |
download | xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.gz xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.bz2 xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.zip |
Initial import
Diffstat (limited to 'ICSharpCode.Decompiler/FlowAnalysis/SsaInstruction.cs')
-rw-r--r-- | ICSharpCode.Decompiler/FlowAnalysis/SsaInstruction.cs | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/SsaInstruction.cs b/ICSharpCode.Decompiler/FlowAnalysis/SsaInstruction.cs new file mode 100644 index 00000000..c9375852 --- /dev/null +++ b/ICSharpCode.Decompiler/FlowAnalysis/SsaInstruction.cs @@ -0,0 +1,191 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Diagnostics; +using System.IO; + +using ICSharpCode.Decompiler.Disassembler; +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace ICSharpCode.Decompiler.FlowAnalysis +{ + public enum SpecialOpCode + { + /// <summary> + /// No special op code: SsaInstruction has a normal IL instruction + /// </summary> + None, + /// <summary> + /// Φ function: chooses the appropriate variable based on which CFG edge was used to enter this block + /// </summary> + Phi, + /// <summary> + /// Variable is read from before passing it by ref. + /// This instruction constructs a managed reference to the variable. + /// </summary> + PrepareByRefCall, + /// <summary> + /// This instruction constructs a managed reference to the variable. + /// The variable is not really read from. + /// </summary> + PrepareByOutCall, + /// <summary> + /// This instruction constructs a managed reference to the variable. + /// The reference is used for a field access on a value type. + /// </summary> + PrepareForFieldAccess, + /// <summary> + /// Variable is written to after passing it by ref or out. + /// </summary> + WriteAfterByRefOrOutCall, + /// <summary> + /// Variable is not initialized. + /// </summary> + Uninitialized, + /// <summary> + /// Value is passed in as parameter + /// </summary> + Parameter, + /// <summary> + /// Value is a caught exception. + /// TypeOperand is set to the exception type. + /// </summary> + Exception, + /// <summary> + /// Initialize a value type. Unlike the real initobj instruction, this one does not take an address + /// but assigns to the target variable. + /// TypeOperand is set to the type being created. + /// </summary> + InitObj + } + + public sealed class SsaInstruction + { + public readonly SsaBlock ParentBlock; + public readonly SpecialOpCode SpecialOpCode; + + /// <summary> + /// The original IL instruction. + /// May be null for "invented" instructions (SpecialOpCode != None). + /// </summary> + public readonly Instruction Instruction; + + /// <summary> + /// Prefixes in front of the IL instruction. + /// </summary> + public readonly Instruction[] Prefixes; + + /// <summary> + /// Gets the type operand. This is used only in combination with some special opcodes. + /// </summary> + public readonly TypeReference TypeOperand; + + public SsaVariable Target; + public SsaVariable[] Operands; + + static readonly SsaVariable[] emptyVariableArray = {}; + static readonly Instruction[] emptyInstructionArray = {}; + + public SsaInstruction(SsaBlock parentBlock, Instruction instruction, SsaVariable target, SsaVariable[] operands, + Instruction[] prefixes = null, SpecialOpCode specialOpCode = SpecialOpCode.None, + TypeReference typeOperand = null) + { + ParentBlock = parentBlock; + Instruction = instruction; + Prefixes = prefixes ?? emptyInstructionArray; + Target = target; + Operands = operands ?? emptyVariableArray; + SpecialOpCode = specialOpCode; + TypeOperand = typeOperand; + Debug.Assert((typeOperand != null) == (specialOpCode == SpecialOpCode.Exception || specialOpCode == SpecialOpCode.InitObj)); + } + + /// <summary> + /// Gets whether this instruction is a simple assignment from one variable to another. + /// </summary> + public bool IsMoveInstruction { + get { + return Target != null && Operands.Length == 1 && Instruction != null && OpCodeInfo.Get(Instruction.OpCode).IsMoveInstruction; + } + } + + public void ReplaceVariableInOperands(SsaVariable oldVar, SsaVariable newVar) + { + for (int i = 0; i < Operands.Length; i++) { + if (Operands[i] == oldVar) + Operands[i] = newVar; + } + } + + public override string ToString() + { + StringWriter w = new StringWriter(); + WriteTo(w); + return w.ToString(); + } + + public void WriteTo(TextWriter writer) + { + foreach (Instruction prefix in Prefixes) { + DisassemblerHelpers.WriteTo(prefix, new PlainTextOutput(writer)); + writer.WriteLine(); + } + if (Instruction != null && Instruction.Offset >= 0) { + writer.Write(CecilExtensions.OffsetToString(Instruction.Offset)); + writer.Write(": "); + } + if (Target != null) { + writer.Write(Target.ToString()); + writer.Write(" = "); + } + if (IsMoveInstruction) { + writer.Write(Operands[0].ToString()); + if (Instruction != null) { + writer.Write(" (" + Instruction.OpCode.Name + ")"); + } + } else { + if (Instruction == null) { + writer.Write(SpecialOpCode.ToString()); + } else { + writer.Write(Instruction.OpCode.Name); + if(null != Instruction.Operand) { + writer.Write(' '); + DisassemblerHelpers.WriteOperand(new PlainTextOutput(writer), Instruction.Operand); + writer.Write(' '); + } + } + if (TypeOperand != null) { + writer.Write(' '); + writer.Write(TypeOperand.ToString()); + writer.Write(' '); + } + if (Operands.Length > 0) { + writer.Write('('); + for (int i = 0; i < Operands.Length; i++) { + if (i > 0) + writer.Write(", "); + writer.Write(Operands[i].ToString()); + } + writer.Write(')'); + } + } + } + } +} |