public static StackPushInformation CreateCopy(string stackName, StackPushInformation pushInformation) { return(new StackPushInformation(stackName) { FromCopy = pushInformation }); }
public static StackPushInformation CreateFromStack(string stackName, StackPushInformation stack) { return(new StackPushInformation(stackName) { FromStack = stack, IsReference = stack.IsReference }); }
private bool LdArgTransactions(Node node, IList <StackPushInformation> stackTransactions) { // Get argument index int argumentIndex = node.OpCode.GetArgumentIndex(node.Operand); if (node.Block.Method.Definition.HasThis) { // Handle this argument if (argumentIndex == 0) { stackTransactions.Add( StackPushInformation.CreateFromThisArgument(node.PushStackNames.Single(), node.Block.Method.Definition.DeclaringType)); return(true); } // Decrement with 1 to get correct argument argumentIndex--; } // Get argument ArgumentInformation argument = _argumentInformations[argumentIndex]; bool isReference = node.OpCode.Code == Code.Ldarga || node.OpCode.Code == Code.Ldarga_S; stackTransactions.Add(StackPushInformation.CreateFromArgument(node.PushStackNames.Single(), argument, isReference)); return(true); }
internal void AddStackInformation(string stLocPopName, StackPushInformation stTrans) { if (!_fromStackInformation.Any(s => s.StackName == stLocPopName)) { _fromStackInformation.Add(stTrans); } NotAssignedStackInformation.Remove(stLocPopName); }
private bool LdFldTransactions(Node node, List <StackPushInformation> stackTransactions) { // Get field index FieldDefinition field = node.OpCode.GetField(node.Operand).Resolve(); bool isReference = node.OpCode.Code == Code.Ldflda || node.OpCode.Code == Code.Ldsflda; stackTransactions.Add(StackPushInformation.CreateFromField(node.PushStackNames.Single(), field, isReference)); return(true); }
private bool LdLocTransactions(Node node, List <StackPushInformation> stackTransactions) { // Get variable index int variableIndex = node.OpCode.GetVariableIndex(node.Operand); // Get argument var variable = _variableDefinitions[variableIndex]; bool isReference = node.OpCode.Code == Code.Ldloca || node.OpCode.Code == Code.Ldloca_S; stackTransactions.Add(StackPushInformation.CreateFromVariable(node.PushStackNames.Single(), variable, isReference)); return(true); }
private bool NewObjTransactions(Node node, IList <StackPushInformation> stackTransactions) { if (node.Operand is MethodReference constructor) { // Resolve the new initilized type var type = constructor.DeclaringType.Resolve(); stackTransactions.Add(StackPushInformation.CreateFromNewObj(node.PushStackNames.Single(), type)); return(true); } // The operand should be a MethodReference - if not - we currently don't handle it throw new NotSupportedException(); }
private bool CallTransactions(Node node, IList <StackPushInformation> stackTransactions) { if (node.Operand is MethodReference method) { // Resolve the result type and detect if it's a void method var returnType = GetGenericType(method, method.ReturnType); if (returnType.IsVoid()) { return(false); } // Get method definition var methodDefinition = method.Resolve(); stackTransactions.Add(StackPushInformation.CreateFromMethodCall(node.PushStackNames.Single(), methodDefinition)); return(true); } // The operand should be a MethodReference - if not - we currently don't handle it throw new NotSupportedException(); }
public override void Visit(Node node) { // Add and get list with stack transactions if (!_stackTransactions.ContainsKey(node)) { _stackTransactions.Add(node, new List <StackPushInformation>()); } List <StackPushInformation> stackTransactions = _stackTransactions[node]; // If there are already tranactions registrered we just skip the node if (stackTransactions.Any()) { return; } // Switch on opcode switch (node.OpCode.Code) { case Code.Newobj: _changed |= NewObjTransactions(node, stackTransactions); break; case Code.Call: case Code.Calli: case Code.Callvirt: _changed |= CallTransactions(node, stackTransactions); break; case Code.Ldarg: case Code.Ldarga: _changed |= LdArgTransactions(node, stackTransactions); break; // Load field case Code.Ldfld: case Code.Ldflda: // Load static field case Code.Ldsfld: case Code.Ldsflda: _changed |= LdFldTransactions(node, stackTransactions); break; case Code.Ldloc: case Code.Ldloca: _changed |= LdLocTransactions(node, stackTransactions); break; case Code.Stloc: case Code.Stloc_S: // Get variable index int variableIndex = node.OpCode.GetVariableIndex(node.Operand); // Get argument var variable = _variableDefinitions[variableIndex]; // Get pop var stLocPopName = node.PopStackNames.Single(); // Find stack tranaction var stTrans = _stackTransactions.SelectMany(e => e.Value).SingleOrDefault(e => e.StackName == stLocPopName); if (stTrans == null) { variable.AddStackInformation(stLocPopName); break; } // Add transaction to index variable.AddStackInformation(stLocPopName, stTrans); break; case Code.Ldc_I8: stackTransactions.Add(StackPushInformation.CreateFromConstant(node.PushStackNames.Single(), (long)node.Operand)); // Set changed _changed = true; break; case Code.Ldc_R8: stackTransactions.Add(StackPushInformation.CreateFromFloatingPointConstant(node.PushStackNames.Single(), (double)node.Operand)); // Set changed _changed = true; break; case Code.Ldnull: stackTransactions.Add(StackPushInformation.CreateFromNull(node.PushStackNames.Single())); // Set changed _changed = true; break; case Code.Ldstr: stackTransactions.Add(StackPushInformation.CreateFromString(node.PushStackNames.Single(), node.Operand as string)); // Set changed _changed = true; break; case Code.Neg: case Code.Not: case Code.Dup: // Get pop instruction var popName = node.PopStackNames.Single(); var popNode = node.Block.Method.Blocks.SelectMany(e => e.Nodes) .Distinct().SingleOrDefault(n => n.PushStackNames.Any(e => e == popName)); // If we cannot find it - we wait if (popNode == null) { break; } // Get transaction for this node if (!_stackTransactions.ContainsKey(popNode)) { break; } // Get sources (there should only be one source) var source = _stackTransactions[popNode].SingleOrDefault(transaction => transaction.StackName == popName); if (source == null) { break; } // Get pushName var pushNames = node.PushStackNames.OrderBy(e => e); foreach (var pushName in pushNames) { // Add transaction stackTransactions.Add(StackPushInformation.CreateCopy(pushName, source)); } // Set changed _changed = true; break; case Code.Castclass: // TODO: Easy to implement break; case Code.Isinst: // TODO: break; case Code.Ldtoken: case Code.Ldftn: case Code.Ldvirtftn: break; case Code.Ceq: case Code.Cgt: case Code.Cgt_Un: case Code.Clt: case Code.Clt_Un: // TODO: break; case Code.Add: case Code.Add_Ovf: case Code.Add_Ovf_Un: case Code.Sub: case Code.Sub_Ovf: case Code.Sub_Ovf_Un: case Code.Mul: case Code.Mul_Ovf: case Code.Mul_Ovf_Un: case Code.Div: case Code.Div_Un: case Code.Rem: case Code.Rem_Un: // TODO: break; case Code.And: case Code.Or: case Code.Xor: // TODO: break; case Code.Box: case Code.Unbox: case Code.Unbox_Any: // TODO: break; case Code.Conv_I1: case Code.Conv_I2: case Code.Conv_I4: case Code.Conv_I8: // TODO: break; case Code.Conv_R4: case Code.Conv_R8: case Code.Conv_R_Un: // TODO: break; case Code.Sizeof: // TODO: break; case Code.Ldobj: // TODO: break; case Code.Newarr: case Code.Ldelem_Any: case Code.Ldelem_I1: case Code.Ldelem_I2: case Code.Ldelem_I4: case Code.Ldelem_I8: case Code.Ldelem_R4: case Code.Ldelem_R8: case Code.Ldelem_Ref: case Code.Ldlen: break; default: // We need to handle all nodes which pushes to the stack Debug.Assert(node.PushCountFromStack == 0); break; } base.Visit(node); }