public static bool TryCreateIndirection(Namescope scope, ref Expression e, out Expression s) { if (e.NeedsIndirection()) { var v = new Variable(e.Source, null, scope.GetUniqueIdentifier("ind"), e.ReturnType, VariableType.Indirection); var a = e as AddressOf; var q = e as SequenceOp; if (q?.Right is AddressOf) { a = q.Right as AddressOf; q.Right = a.ActualValue; } s = new StoreLocal(e.Source, v, e.ActualValue); e = new LoadLocal(e.Source, v); if (a != null) { e = new AddressOf(e, a.AddressType); } return(true); } s = null; return(false); }
void GetIndirection(ref Expression e) { Variable var; var s = e as LoadArgument; if (s != null && GetIndirection(s.Index, s.Parameter, out var)) { e = new LoadLocal(s.Source, var); } }
public override void Begin(ref Expression e, ExpressionUsage u) { switch (e.ExpressionType) { case ExpressionType.CapturedArgument: { var s = e as CapturedArgument; e = new LoadArgument(s.Source, s.Function, s.ParameterIndex); } break; case ExpressionType.CapturedLocal: { var s = e as CapturedLocal; e = new LoadLocal(s.Source, s.Variable); } break; case ExpressionType.AddressOf: { var s = e as AddressOf; switch (s.Operand.ExpressionType) { case ExpressionType.LoadField: { var v = s.Operand as LoadField; if (TransformedVars.Contains(v.Field)) { e = s.Operand; Begin(ref e, u); } } break; case ExpressionType.LoadLocal: { var v = s.Operand as LoadLocal; if (TransformedVars.Contains(v.Variable)) { e = s.Operand; Begin(ref e, u); } } break; } } break; } }
private static void DoSpliceEq(TypedInstructionCollection instructions, BasicBlock block) { int index = block.Last.Index; // ldloc.0 V_0 // ldnull // beq 2F LoadArg arg = null; LoadLocal local = null; if (instructions[index - 1].Untyped.OpCode.Code == Code.Ldnull) { arg = instructions[block.Last.Index - 2] as LoadArg; local = instructions[block.Last.Index - 2] as LoadLocal; } else if (instructions[index - 2].Untyped.OpCode.Code == Code.Ldnull) { arg = instructions[block.Last.Index - 1] as LoadArg; local = instructions[block.Last.Index - 1] as LoadLocal; } if (arg != null || local != null) { TypedInstruction instruction = instructions[block.Last.Index]; Code code = instruction.Untyped.OpCode.Code; if (code == Code.Bne_Un || code == Code.Bne_Un_S) { if (arg != null) { DoSpliceNull(block, FirstNullArgBlockLen - arg.Arg, FirstNonNullArgBlockLen - arg.Arg); } else { DoSpliceNull(block, FirstNullLocalBlockLen - local.Variable, FirstNonNullLocalBlockLen - local.Variable); } } else { if (arg != null) { DoSpliceNull(block, FirstNonNullArgBlockLen - arg.Arg, FirstNullArgBlockLen - arg.Arg); } else { DoSpliceNull(block, FirstNonNullLocalBlockLen - local.Variable, FirstNullLocalBlockLen - local.Variable); } } } }
private TypeReference DoGetType(int index, int nth) { TypeReference type = null; int i = m_info.Tracker.GetStackIndex(index, nth); if (i >= 0) { do // TODO: would be nice to do something with load constant instructions as well { LoadArg arg = m_info.Instructions[i] as LoadArg; if (arg != null && arg.Arg >= 1) { ParameterDefinition p = m_info.Method.Parameters[arg.Arg - 1]; type = p.ParameterType; break; } LoadField field = m_info.Instructions[i] as LoadField; if (field != null) { type = field.Field.FieldType; break; } LoadLocal local = m_info.Instructions[i] as LoadLocal; if (local != null) { VariableDefinition v = m_info.Method.Body.Variables[local.Variable]; type = v.VariableType; break; } LoadStaticField sfield = m_info.Instructions[i] as LoadStaticField; if (sfield != null) { type = sfield.Field.FieldType; break; } Box box = m_info.Instructions[i] as Box; if (box != null) { type = box.Type; break; } }while (false); } return(type); }
public void VisitBinary(BinaryOp op) { if (m_offset < 0 && (op.Untyped.OpCode.Code == Code.Div || op.Untyped.OpCode.Code == Code.Div_Un)) { do { LoadConstantInt load1 = m_info.Instructions[op.Index - 1] as LoadConstantInt; if (load1 != null) { if (load1.Value == 0) { m_offset = op.Untyped.Offset; Log.DebugLine(this, "zero constant denominator at {0:X2}", m_offset); } break; } LoadLocal load2 = m_info.Instructions[op.Index - 1] as LoadLocal; if (load2 != null) { if (DoIsIntType(load2.Type)) { State state = m_info.Tracker.State(op.Index - 1); long? value = state.Locals[load2.Variable]; if (value.HasValue && value.Value == 0) { m_offset = op.Untyped.Offset; Log.DebugLine(this, "zero local denominator at {0:X2}", m_offset); } } break; } LoadArg load3 = m_info.Instructions[op.Index - 1] as LoadArg; if (load3 != null) { if (DoIsIntType(load3.Type)) { State state2 = m_info.Tracker.State(op.Index - 1); long? value2 = state2.Arguments[m_info.Method.HasThis ? load3.Arg : load3.Arg - 1]; if (value2.HasValue && value2.Value == 0) { m_offset = op.Untyped.Offset; Log.DebugLine(this, "zero arg denominator at {0:X2}", m_offset); } } break; } }while (false); } }
// stloc.0 V_0 // ldloc.0 V_0 private bool DoStoresLocal(int index) { bool found = false; if (index > 0) { LoadLocal load = m_info.Instructions[index] as LoadLocal; StoreLocal store = m_info.Instructions[index - 1] as StoreLocal; found = load != null && store != null && load.Variable == store.Variable; } return(found); }
// ldloc.0 V_0 // call System.Void System.Threading.Monitor::Enter(System.Object) public void VisitCall(Call call) { if (m_needsCheck && m_offset < 0) { if (call.Target.ToString() == "System.Void System.Threading.Monitor::Enter(System.Object)") { LoadLocal local = m_info.Instructions[call.Index - 1] as LoadLocal; if (local != null && m_thisLocals.IndexOf(local.Variable) >= 0) { m_offset = call.Untyped.Offset; Log.DebugLine(this, "found lock(this) at {0:X2}", m_offset); } } } }
private List <int> DoGetDisposableLoads(int index, int variable) { List <int> loads = new List <int>(); for (int i = index; i < m_info.Instructions.Length; ++i) { LoadLocal load = m_info.Instructions[i] as LoadLocal; if (load != null && load.Variable == variable) { loads.Add(i); Log.DebugLine(this, "found load at offset {0:X2}", load.Untyped.Offset); } } return(loads); }
private TypeReference DoGetThisType(Call call) { TypeReference self = null; if (call.Target.HasThis) { int index = call.GetThisIndex(m_info); if (index >= 0) { do { LoadArg arg = m_info.Instructions[index] as LoadArg; if (arg != null) { self = arg.Type; break; } LoadField field = m_info.Instructions[index] as LoadField; if (field != null) { self = field.Field.FieldType; break; } LoadStaticField sfield = m_info.Instructions[index] as LoadStaticField; if (sfield != null) { self = sfield.Field.FieldType; break; } LoadLocal local = m_info.Instructions[index] as LoadLocal; if (local != null) { self = local.Type; break; } }while (false); } } return(self); }
private void RegisterTestMethods() { var registryObject = ILFactory.NewObject(_source, _testRegistryType); var registryVariable = new Variable(_source, _mainConstructor, "registry", _testRegistryType, VariableType.Default, registryObject); var body = new Scope(_source); body.Statements.Add(new CallConstructor(_source, _appClass.Constructors[0])); body.Statements.Add(new VariableDeclaration(registryVariable)); var methods = _methods; if (_testOptions.Filter != null) { var regex = new Regex(_testOptions.Filter, RegexOptions.CultureInvariant); methods = methods.Where(m => regex.IsMatch(m.FullName)).ToList(); } methods.Sort((a, b) => string.Compare(a.FullName, b.FullName, StringComparison.InvariantCultureIgnoreCase)); var ret = new List <TestMethod>(); foreach (var method in methods) { var testMethod = CreateTestMethod(method); var invokerMethod = CreateInvoker(method); var invokerInstance = InstantiateTestFixture(invokerMethod); var testExpression = RegisterTest(testMethod, new LoadLocal(_source, registryVariable), new NewDelegate(_source, _actionType, invokerInstance, invokerMethod)); body.Statements.Add(testExpression); ret.Add(testMethod); } var registryExpr = new LoadLocal(_source, registryVariable); var testSetupConstruction = ILFactory.NewObject(_source, _testSetupType, registryExpr); body.Statements.Add(new StoreField(_source, new This(_source, _mainClass), _testSetupField, testSetupConstruction)); _mainConstructor.SetBody(body); }
Expression EnqueueLocal(Source src, MetaProperty mp, MetaLocation loc, Expression e) { // TODO: Bugs without if test. if (e is PlaceholderArray) { var var = new Variable(src, null, Generator.CreateLocalName(mp, loc, e), e.ReturnType, VariableType.Default, new PlaceholderValue(mp, loc, e, CurrentMetaPropertyStage)); LocalQueue.Add(var); var result = new LoadLocal(e.Source, var); LoadHistory.Add(result); if (result.ReturnType is FixedArrayType) { return(new AddressOf(result)); } return(result); } return(e); }
private static void DoSpliceTrue(TypedInstructionCollection instructions, BasicBlock block) { int index = block.Last.Index; // ldarg.1 a1 // brtrue 10 (not taken is the first branch) LoadArg arg = instructions[index - 1] as LoadArg; LoadLocal local = instructions[index - 1] as LoadLocal; if (arg != null || local != null) { TypedInstruction instruction = instructions[index]; Code code = instruction.Untyped.OpCode.Code; if (code == Code.Brtrue || code == Code.Brtrue_S) { if (arg != null) { DoSpliceNull(block, FirstNullArgBlockLen - arg.Arg, FirstNonNullArgBlockLen - arg.Arg); } else { DoSpliceNull(block, FirstNullLocalBlockLen - local.Variable, FirstNonNullLocalBlockLen - local.Variable); } } else { if (arg != null) { DoSpliceNull(block, FirstNonNullArgBlockLen - arg.Arg, FirstNullArgBlockLen - arg.Arg); } else { DoSpliceNull(block, FirstNonNullLocalBlockLen - local.Variable, FirstNullLocalBlockLen - local.Variable); } } } }
static Expression CreateAssertIndirection(ref Expression e, List <StoreLocal> locals, Namescope scope) { switch (e.ExpressionType) { case ExpressionType.AddressOf: return(CreateAssertIndirection(ref (e as AddressOf).Operand, locals, scope)); case ExpressionType.LoadLocal: case ExpressionType.LoadArgument: case ExpressionType.LoadField: case ExpressionType.LoadElement: case ExpressionType.Invalid: case ExpressionType.Constant: return(e); } var v = new Variable(e.Source, null, scope.GetUniqueIdentifier("assert"), e.ReturnType); var s = new StoreLocal(e.Source, v, e); var l = new LoadLocal(e.Source, v); locals.Add(s); return(e = l); }
private void DoCheckLoad(TypedInstruction instruction) { LoadConstantInt load = m_info.Instructions[instruction.Index - 1] as LoadConstantInt; if (load != null) { if (load.Value < 0 || load.Value > 255) { m_offset = instruction.Untyped.Offset; Log.DebugLine(this, "bad exit at {0:X2}", m_offset); } } LoadLocal local = m_info.Instructions[instruction.Index - 1] as LoadLocal; if (local != null) { Log.DebugLine(this, "{0} at {1:X2}", instruction.Untyped.OpCode, instruction.Untyped.Offset); if (m_candidateLoads.IndexOf(local.Variable) < 0) { m_candidateLoads.Add(local.Variable); } } }
private int DoCheckCatch(TypedInstructionCollection instructions, CatchBlock cb, int varIndex) { int offset = -1; // Loop through all of the instructions in the catch block, for (int index = cb.Index; index < cb.Index + cb.Length && offset < 0; ++index) { TypedInstruction instruction = instructions[index]; // if we find a throw instruction, if (instruction.Untyped.OpCode.Code == Code.Throw) { // and it's preceded by a load from varIndex then we have a problem. LoadLocal load = instructions[index - 1] as LoadLocal; if (load != null && load.Variable == varIndex) { offset = instruction.Untyped.Offset; Log.DebugLine(this, "bad throw at {0:X2}", offset); } } } return(offset); }
private bool DoMatch(CodeBlock lhs, CodeBlock rhs, int count) { Log.DebugLine(this, " lhs: {0} at {1:X2}", lhs.Method, lhs.Instructions[lhs.Index].Untyped.Offset); Log.DebugLine(this, " rhs: {0} at {1:X2}", rhs.Method, rhs.Instructions[rhs.Index].Untyped.Offset); Log.DebugLine(this, " count: {0}", count); for (int i = 0; i < count; ++i) { TypedInstruction left = lhs.Instructions[lhs.Index + i]; TypedInstruction right = rhs.Instructions[rhs.Index + i]; LoadLocal load1 = left as LoadLocal; LoadLocal load2 = right as LoadLocal; LoadLocalAddress load1b = left as LoadLocalAddress; LoadLocalAddress load2b = right as LoadLocalAddress; StoreLocal store1 = left as StoreLocal; StoreLocal store2 = right as StoreLocal; if (load1 != null && load2 != null) { // If we have real names for the local variables (from the mdb file) then // life is good and we can compare the names. If not we're stuck: we can't // simply use the variable index because we'll get false positives. if (!load1.RealName) { Log.DebugLine(this, " can't match local name"); return(false); } // This should be a temporary in which case we can't use the variable index. else if (load1.Name.StartsWith("V_") && load1.Type.FullName != load2.Type.FullName) { Log.DebugLine(this, " {0} != {1} ({2} and {3})", left, right, load1.Type.FullName, load2.Type.FullName); return(false); } else if (!load1.Name.StartsWith("V_") && load1.Name != load2.Name) { Log.DebugLine(this, " {0} != {1} ({2} and {3})", left, right, load1.Name, load2.Name); return(false); } } else if (load1b != null && load2b != null) { if (!load1b.RealName) { Log.DebugLine(this, " can't match local name"); return(false); } else if (load1b.Name.StartsWith("V_") && load1b.Type.FullName != load2b.Type.FullName) { Log.DebugLine(this, " {0} != {1} ({2} and {3})", left, right, load1b.Type.FullName, load2b.Type.FullName); return(false); } else if (!load1b.Name.StartsWith("V_") && load1b.Name != load2b.Name) { Log.DebugLine(this, " {0} != {1} ({2} and {3})", left, right, load1b.Name, load2b.Name); return(false); } } else if (store1 != null && store2 != null) { if (!store1.RealName) { Log.DebugLine(this, " can't match local name"); return(false); } else if (store1.Name.StartsWith("V_") && store1.Type.FullName != store2.Type.FullName) { Log.DebugLine(this, " {0} != {1} ({2} and {3})", left, right, store1.Type.FullName, store2.Type.FullName); return(false); } else if (!store1.Name.StartsWith("V_") && store1.Name != store2.Name) { Log.DebugLine(this, " {0} != {1} ({2} and {3})", left, right, store1.Name, store2.Name); return(false); } } else if (!left.Untyped.Matches(right.Untyped)) { Log.DebugLine(this, " {0} != {1}", left, right); return(false); } } return(true); }
public override void Begin(ref Expression e, ExpressionUsage u) { CurrentExpression = e; switch (e.ExpressionType) { case ExpressionType.LoadArgument: { var s = e as LoadArgument; if (ParameterVariables[s.Index] != null) { e = new LoadLocal(s.Source, ParameterVariables[s.Index]); } break; } case ExpressionType.StoreArgument: { var s = e as StoreArgument; if (MustCopyType(s.Parameter.Type) && MustCopyValue(s.Value)) { e = Assign(new LoadArgument(s.Source, s.Function, s.Index), s.Value); } else if (ParameterVariables[s.Index] != null) { e = new StoreLocal(s.Source, ParameterVariables[s.Index], s.Value); } break; } case ExpressionType.StoreField: { var s = e as StoreField; OnObject(ref s.Object); if (MustCopyType(s.Field.ReturnType) && MustCopyValue(s.Value)) { e = Assign(new LoadField(s.Source, s.Object, s.Field), s.Value); } break; } case ExpressionType.StoreThis: { var s = e as StoreThis; e = Assign(new This(s.Source, s.ReturnType), s.Value); break; } case ExpressionType.StoreLocal: { var s = e as StoreLocal; if (MustCopyType(s.Variable.ValueType) && MustCopyValue(s.Value)) { e = Assign(new LoadLocal(s.Source, s.Variable), s.Value); } break; } case ExpressionType.StoreElement: { var s = e as StoreElement; if (MustCopyType(s.Array.ReturnType.ElementType) && MustCopyValue(s.Value)) { e = Assign(new LoadElement(s.Source, s.Array, s.Index), s.Value); } break; } case ExpressionType.CallMethod: { var s = e as CallMethod; if (MustCopyBeforeCall(s.Method)) { OnObject(ref s.Object); } break; } case ExpressionType.GetProperty: { var s = e as GetProperty; if (MustCopyBeforeCall(s.Property.GetMethod)) { OnObject(ref s.Object); } break; } case ExpressionType.SetProperty: { var s = e as SetProperty; if (MustCopyBeforeCall(s.Property.SetMethod)) { OnObject(ref s.Object); } break; } case ExpressionType.AddListener: { var s = e as AddListener; if (MustCopyBeforeCall(s.Event.AddMethod)) { OnObject(ref s.Object); } break; } case ExpressionType.RemoveListener: { var s = e as RemoveListener; if (MustCopyBeforeCall(s.Event.RemoveMethod)) { OnObject(ref s.Object); } break; } } ParentExpression = e; }
protected override void ProcessNext() { if (DmlTokens.IsMatch(CurrentToken, DmlTokens.AT) || DmlTokens.IsMatch(CurrentToken, DmlTokens.DOLLAR) || DmlTokens.IsNonKeywordName(CurrentToken) || DmlTokens.IsBuiltin(CurrentToken)) { Instruction load; string badName = "Invalid syntax; invalid name \"{0}\"."; if (DmlTokens.IsMatch(CurrentToken, DmlTokens.AT)) { Advance(exception: new DmlSyntaxError("Invalid syntax: global identifier `@` must be followed by a name.")); if (!DmlTokens.IsName(CurrentToken)) { throw new DmlSyntaxError(String.Format(badName, CurrentToken)); } load = new LoadGlobal(CurrentToken); } else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.DOLLAR)) { Advance(exception: new DmlSyntaxError("Invalid syntax: identifier `$` must be followed by a name.")); if (DmlTokens.IsName(CurrentToken)) { switch (CurrentToken) { case DmlTokens.INTRINSIC_DIRECTION: load = LoadIntrinsicBulletProperty.Direction; break; case DmlTokens.INTRINSIC_SPEED: load = LoadIntrinsicBulletProperty.Speed; break; case DmlTokens.INTRINSIC_COLOUR: load = LoadIntrinsicBulletProperty.Colour; break; case DmlTokens.INTRINSIC_ORIGIN: load = LoadIntrinsicBulletProperty.Origin; break; case DmlTokens.INTRINSIC_POSITION: load = LoadIntrinsicBulletProperty.Position; break; case DmlTokens.INTRINSIC_VELOCITY: load = LoadIntrinsicBulletProperty.Velocity; break; case DmlTokens.INTRINSIC_TIME: load = LoadIntrinsicBulletProperty.Time; break; default: load = new LoadInstanceBound(CurrentToken); break; } } else { throw new DmlSyntaxError(String.Format(badName, CurrentToken)); } } else if (DmlTokens.IsName(CurrentToken)) { load = new LoadLocal(CurrentToken); } else { load = new LoadConstant(BuiltinsDict.Builtins[CurrentToken]); } bool isCall = false; // Check if this is a function call. // We actually want to catch the ParserError thrown by Advance() in this case // because it's very possible the expression could end with a name. if (NextToken != null) { Advance(); if (DmlTokens.IsMatch(CurrentToken, DmlTokens.LPAR)) { isCall = true; ParseFuncCall(load); } else { Reverse(); } } if (!isCall) { instructions.Add(load); } } else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.KW_TRUE)) { instructions.Add(new LoadConstant(new DmlObject(DmlType.Bool, true))); } else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.KW_FALSE)) { instructions.Add(new LoadConstant(new DmlObject(DmlType.Bool, false))); } else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.KW_NULL)) { instructions.Add(new LoadConstant(new DmlObject(DmlType.Null, null))); } // Check for a left parenthesis. else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.LPAR)) { // We know this will never be the start of a function call because // that case would be caught by the above if block. operators.Push(CurrentToken); } // Check for a right parenthesis. else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.RPAR)) { // By the shunting-yard algorithm, we pop every operator until we find a left // parenthesis. If we don't find one, then there are mismatched parentheses. if (operators.Count == 0 || !operators.Contains(DmlTokens.LPAR)) { throw DmlSyntaxError.MismatchedParentheses(); } string top; while (operators.Count > 0) { top = operators.First(); if (DmlTokens.IsMatch(top, DmlTokens.LPAR)) { operators.Pop(); break; } instructions.Add(OPERATOR_INSTRUCTIONS[operators.Pop()]); } } // Check if the next token is a valid mathematical operator. else if (IsOperator(CurrentToken)) { if (operators.Count == 0) { operators.Push(CurrentToken); } // If there are prior operators, pop them and add them to the instructions according to their // associativity and precedence. else { string top; while (operators.Count > 0) { top = operators.First(); if ((IsLeftAssociative(top) && OPERATOR_PRECEDENCE[top] >= OPERATOR_PRECEDENCE[CurrentToken]) || (IsRightAssociative(top) && OPERATOR_PRECEDENCE[top] > OPERATOR_PRECEDENCE[CurrentToken])) { instructions.Add(OPERATOR_INSTRUCTIONS[operators.Pop()]); } else { break; } } operators.Push(CurrentToken); } } // Check for a number. else if (DmlTokens.IsNumber(CurrentToken)) { instructions.Add(new LoadConstant(new DmlObject(DmlType.Number, Double.Parse(CurrentToken)))); } // Check for True. else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.KW_TRUE)) { instructions.Add(new LoadConstant(new DmlObject(DmlType.Bool, true))); } // Check for False. else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.KW_FALSE)) { instructions.Add(new LoadConstant(new DmlObject(DmlType.Bool, false))); } // Check for Null. else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.KW_NULL)) { instructions.Add(new LoadConstant(new DmlObject(DmlType.Null, null))); } else if (DmlTokens.IsString(CurrentToken)) { instructions.Add(new LoadConstant(new DmlObject(DmlType.String, CurrentToken))); } // Check for Lambda. else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.KW_LAMBDA)) { throw new NotImplementedException("This hasn't been implemented yet, sorry!"); } else { throw DmlSyntaxError.InvalidTokenForContext(CurrentToken, "expression"); } }
public static bool IsIntOperand(MethodInfo info, int index, int nth) { bool isInt = false; int i = info.Tracker.GetStackIndex(index, nth); if (i >= 0) { do { LoadArg arg = info.Instructions[i] as LoadArg; if (arg != null && arg.Arg >= 1) { ParameterDefinition p = info.Method.Parameters[arg.Arg - 1]; if (p.ParameterType.FullName == "System.Int32") { isInt = true; } break; } LoadConstantInt constant = info.Instructions[i] as LoadConstantInt; if (constant != null) { Code code = constant.Untyped.OpCode.Code; switch (code) { case Code.Ldc_I4_M1: case Code.Ldc_I4_0: case Code.Ldc_I4_1: case Code.Ldc_I4_2: case Code.Ldc_I4_3: case Code.Ldc_I4_4: case Code.Ldc_I4_5: case Code.Ldc_I4_6: case Code.Ldc_I4_7: case Code.Ldc_I4_8: case Code.Ldc_I4_S: case Code.Ldc_I4: isInt = true; break; } break; } LoadField field = info.Instructions[i] as LoadField; if (field != null) { if (field.Field.FieldType.FullName == "System.Int32") { isInt = true; } break; } LoadLocal local = info.Instructions[i] as LoadLocal; if (local != null) { VariableDefinition v = info.Method.Body.Variables[local.Variable]; if (v.VariableType.FullName == "System.Int32") { isInt = true; } break; } LoadStaticField sfield = info.Instructions[i] as LoadStaticField; if (sfield != null) { if (sfield.Field.FieldType.FullName == "System.Int32") { isInt = true; } break; } }while (false); } return(isInt); }
public override void Begin(ref Expression e, ExpressionUsage u) { switch (e.ExpressionType) { case ExpressionType.FixOp: { var s = (FixOp)e; GetIndirection(ref s.Operand); break; } case ExpressionType.AddressOf: { var s = (AddressOf)e; switch (s.AddressType) { case AddressType.Out: case AddressType.Ref: GetIndirection(ref s.Operand); break; } break; } case ExpressionType.StoreField: { var s = e as StoreField; OnObject(ref s.Object); break; } case ExpressionType.StoreElement: { var s = e as StoreElement; OnObject(ref s.Array); break; } case ExpressionType.StoreArgument: { Variable var; var s = e as StoreArgument; if (GetIndirection(s.Index, s.Parameter, out var)) { e = new StoreLocal(s.Source, var, s.Value); Begin(ref e, u); } else { VerifyPointer(s.Parameter, s.Value); } break; } case ExpressionType.LoadArgument: { Variable var; var s = e as LoadArgument; if (GetIndirection(s.Index, s.Parameter, out var)) { e = new LoadLocal(s.Source, var); Begin(ref e, u); } break; } case ExpressionType.StoreLocal: { var s = e as StoreLocal; VerifyPointer(s.Variable, s.Value); break; } case ExpressionType.LoadField: { var s = e as LoadField; OnObject(ref s.Object); break; } case ExpressionType.LoadElement: { var s = e as LoadElement; OnObject(ref s.Array); break; } case ExpressionType.AddListener: case ExpressionType.RemoveListener: case ExpressionType.GetProperty: case ExpressionType.SetProperty: case ExpressionType.CallMethod: case ExpressionType.CallDelegate: { var s = (CallExpression)e; OnObject(ref s.Object); if (!s.Function.ReturnType.IsVoid && ( Backend.IsConstrained(s.Function) || s.Object is Base && s.Function.IsVirtual) ) { s.Storage = new Variable(s.Source, Function, Type.GetUniqueIdentifier("ret"), s.Function.ReturnType, VariableType.Indirection); Variables.Add(s.Storage); } break; } case ExpressionType.NewDelegate: { var s = (NewDelegate)e; OnObject(ref s.Object); break; } case ExpressionType.NewArray: { var s = e as NewArray; // Structs with non-trivial copy-ctor cannot be passed through '...' (uInitArray<T>) if (s.Initializers != null && IsNonTrivialStruct(s.ArrayType.ElementType)) { var v = new Variable(s.Source, null, Type.GetUniqueIdentifier("array"), s.ReturnType); e = new StoreLocal(s.Source, v, new NewArray(s.Source, s.ArrayType, new Constant(s.Source, Essentials.Int, s.Initializers.Length))); for (int i = 0; i < s.Initializers.Length; i++) { e = new SequenceOp(e, new StoreElement(s.Source, new LoadLocal(s.Source, v), new Constant(s.Source, Essentials.Int, i), s.Initializers[i])); } e = new SequenceOp(e, new LoadLocal(s.Source, v)); } break; } } }
private bool DoIsBad(int index) { bool bad = false; do { LoadArg arg = m_info.Instructions[index] as LoadArg; if (arg != null && arg.Arg >= 1) { Log.DebugLine(this, "arg: {0}", arg.Arg); ParameterDefinition p = m_info.Method.Parameters[arg.Arg - 1]; Log.DebugLine(this, "param {0} is of type {1}", arg.Arg, p.ParameterType.FullName); if (DoIsBad(p.ParameterType)) { bad = true; } break; } LoadLocal local = m_info.Instructions[index] as LoadLocal; if (local != null) { Log.DebugLine(this, "local: {0}", local.Variable); TypeReference type = m_info.Method.Body.Variables[local.Variable].VariableType; Log.DebugLine(this, "local {0} is of type {1}", local.Variable, type.FullName); if (DoIsBad(type)) { bad = true; } break; } LoadField field = m_info.Instructions[index] as LoadField; if (field != null) { Log.DebugLine(this, "field: {0}", field.Field.Name); TypeReference type = field.Field.FieldType; Log.DebugLine(this, "field {0} is of type {1}", field.Field.Name, type.FullName); if (DoIsBad(type)) { bad = true; } break; } LoadStaticField sfield = m_info.Instructions[index] as LoadStaticField; if (sfield != null) { Log.DebugLine(this, "static field: {0}", sfield.Field.Name); TypeReference type = sfield.Field.FieldType; Log.DebugLine(this, "static field {0} is of type {1}", sfield.Field.Name, type.FullName); if (DoIsBad(type)) { bad = true; } break; } }while (false); return(bad); }
private void DoStackPushes(List <StackEntry> stack, int index, List <StackEntry> oldStack) { long?value; TypedInstruction instruction = m_instructions[index]; switch (instruction.Untyped.OpCode.Code) { case Code.Add: case Code.Sub: case Code.Mul: case Code.Div: case Code.Div_Un: case Code.Rem: case Code.Rem_Un: case Code.And: case Code.Or: case Code.Xor: case Code.Shl: case Code.Shr: case Code.Shr_Un: case Code.Neg: case Code.Not: case Code.Add_Ovf: case Code.Add_Ovf_Un: case Code.Mul_Ovf: case Code.Mul_Ovf_Un: case Code.Sub_Ovf: case Code.Sub_Ovf_Un: stack.Add(new StackEntry(null, index)); // could compute these, but we don't care too much about integer values atm break; case Code.Arglist: // push non-null case Code.Box: case Code.Ldarga: case Code.Ldarga_S: case Code.Ldelema: case Code.Ldflda: case Code.Ldftn: case Code.Ldind_Ref: case Code.Ldloca: case Code.Ldloca_S: case Code.Ldobj: case Code.Ldsflda: case Code.Ldstr: case Code.Ldtoken: case Code.Ldvirtftn: case Code.Localloc: case Code.Mkrefany: case Code.Newarr: case Code.Newobj: case Code.Refanytype: case Code.Refanyval: case Code.Unbox: case Code.Unbox_Any: stack.Add(new StackEntry(1, index)); break; case Code.Call: case Code.Calli: case Code.Callvirt: Call call = instruction as Call; if (call.Target.ReturnType.ReturnType.ToString() != "System.Void") { stack.Add(new StackEntry(null, index)); } break; case Code.Castclass: value = oldStack.Back().Value; if (value.HasValue && value.Value == 0) { stack.Add(new StackEntry(0, index)); } else { stack.Add(new StackEntry(1, index)); } break; case Code.Ceq: // push indeterminate case Code.Cgt: case Code.Cgt_Un: case Code.Clt: case Code.Clt_Un: case Code.Ckfinite: case Code.Conv_I1: case Code.Conv_I2: case Code.Conv_I4: case Code.Conv_I8: case Code.Conv_U4: case Code.Conv_U8: case Code.Conv_R4: case Code.Conv_R8: case Code.Conv_U2: case Code.Conv_U1: case Code.Conv_I: case Code.Conv_R_Un: case Code.Conv_U: case Code.Ldelem_I1: case Code.Ldelem_U1: case Code.Ldelem_I2: case Code.Ldelem_U2: case Code.Ldelem_I4: case Code.Ldelem_U4: case Code.Ldelem_I8: case Code.Ldelem_I: case Code.Ldelem_R4: case Code.Ldelem_R8: case Code.Ldelem_Ref: case Code.Ldelem_Any: case Code.Ldind_I1: case Code.Ldind_U1: case Code.Ldind_I2: case Code.Ldind_U2: case Code.Ldind_I4: case Code.Ldind_U4: case Code.Ldind_I8: case Code.Ldind_I: case Code.Ldind_R4: case Code.Ldind_R8: case Code.Ldfld: case Code.Ldsfld: case Code.Ldlen: case Code.Sizeof: stack.Add(new StackEntry(null, index)); break; case Code.Conv_Ovf_I1: // push previous value case Code.Conv_Ovf_U1: case Code.Conv_Ovf_I2: case Code.Conv_Ovf_U2: case Code.Conv_Ovf_I4: case Code.Conv_Ovf_U4: case Code.Conv_Ovf_I8: case Code.Conv_Ovf_U8: case Code.Conv_Ovf_I: case Code.Conv_Ovf_U: case Code.Conv_Ovf_I1_Un: case Code.Conv_Ovf_I2_Un: case Code.Conv_Ovf_I4_Un: case Code.Conv_Ovf_I8_Un: case Code.Conv_Ovf_U1_Un: case Code.Conv_Ovf_U2_Un: case Code.Conv_Ovf_U4_Un: case Code.Conv_Ovf_U8_Un: case Code.Conv_Ovf_I_Un: case Code.Conv_Ovf_U_Un: value = oldStack.Back().Value; stack.Add(new StackEntry(value, index)); break; case Code.Dup: value = oldStack.Back().Value; stack.Add(new StackEntry(value, index)); stack.Add(new StackEntry(value, index)); break; case Code.Isinst: value = oldStack.Back().Value; if (value.HasValue && value.Value == 0) { stack.Add(new StackEntry(0, index)); } else { stack.Add(new StackEntry(null, index)); } break; case Code.Ldarg_0: case Code.Ldarg_1: case Code.Ldarg_2: case Code.Ldarg_3: case Code.Ldarg: case Code.Ldarg_S: LoadArg arg = instruction as LoadArg; value = m_state.Arguments[arg.Arg]; stack.Add(new StackEntry(value, index)); break; case Code.Ldc_I4_M1: case Code.Ldc_I4_0: case Code.Ldc_I4_1: case Code.Ldc_I4_2: case Code.Ldc_I4_3: case Code.Ldc_I4_4: case Code.Ldc_I4_5: case Code.Ldc_I4_6: case Code.Ldc_I4_7: case Code.Ldc_I4_8: case Code.Ldc_I4_S: case Code.Ldc_I4: case Code.Ldc_I8: LoadConstantInt constant = instruction as LoadConstantInt; stack.Add(new StackEntry(constant.Value, index)); break; case Code.Ldc_R4: case Code.Ldc_R8: LoadConstantFloat constant2 = instruction as LoadConstantFloat; if (constant2.Value == 0.0) { stack.Add(new StackEntry(0, index)); } else { stack.Add(new StackEntry(null, index)); } break; case Code.Ldloc_0: case Code.Ldloc_1: case Code.Ldloc_2: case Code.Ldloc_3: case Code.Ldloc: case Code.Ldloc_S: LoadLocal local = instruction as LoadLocal; value = m_state.Locals[local.Variable]; stack.Add(new StackEntry(value, index)); break; case Code.Ldnull: // push null stack.Add(new StackEntry(0, index)); break; default: DBC.Assert(instruction.Untyped.OpCode.StackBehaviourPush == StackBehaviour.Push0, "Expected {0} to push nothing", instruction.Untyped.OpCode); break; } }
public virtual void WriteLoadLocal(LoadLocal s, ExpressionUsage u) { Write(s.Variable.Name); }
private bool DoIsFloat(int index) { TypedInstruction instruction = m_info.Instructions[index]; TypeReference type = null; do { LoadArg arg = instruction as LoadArg; if (arg != null && arg.Arg >= 1) { type = m_info.Method.Parameters[arg.Arg - 1].ParameterType; break; } LoadLocal local = instruction as LoadLocal; if (local != null) { type = m_info.Method.Body.Variables[local.Variable].VariableType; break; } LoadField field = instruction as LoadField; if (field != null) { type = field.Field.FieldType; break; } LoadStaticField sfield = instruction as LoadStaticField; if (sfield != null) { type = sfield.Field.FieldType; break; } LoadConstantFloat cf = instruction as LoadConstantFloat; if (cf != null) { return(cf.Value != double.PositiveInfinity && cf.Value != double.NegativeInfinity); } BinaryOp binary = instruction as BinaryOp; if (binary != null) { int j = m_info.Tracker.GetStackIndex(instruction.Index, 0); int k = m_info.Tracker.GetStackIndex(instruction.Index, 1); if (j >= 0 && k >= 0) { if (DoIsFloat(j) && DoIsFloat(k)) { return(true); } } } if (instruction.Untyped.OpCode.Code == Code.Conv_R4 || instruction.Untyped.OpCode.Code == Code.Conv_R8 || instruction.Untyped.OpCode.Code == Code.Conv_R_Un) { return(true); } Call call = instruction as Call; if (call != null) { type = call.Target.ReturnType.ReturnType; break; } }while (false); return(type != null && (type.FullName == "System.Single" || type.FullName == "System.Double")); }
bool VisitVariableDeclaration(VariableDeclaration s, Scope scope, ref int i, ref int endIndex) { var mpv = s.Variable.OptionalValue as PlaceholderValue; if (mpv != null) { Parent = s; Begin(ref mpv.Value); mpv.Value.Visit(this); End(ref mpv.Value); FlushLocalQueue(scope, ref i, ref endIndex); var var = s.Variable; var fa = mpv.Value as PlaceholderArray; if (fa != null && CurrentMetaPropertyStage > MetaStage.Volatile) { var.OptionalValue = null; scope.Statements[i] = new FixedArrayDeclaration(var, fa.OptionalInitializer); EmittedValues.Add(mpv, new StageValue(new AddressOf(new LoadLocal(mpv.Source, var)), CurrentMetaPropertyStage, CurrentMetaPropertyStage)); return(true); } else { var.OptionalValue = mpv.Value; } var key = var.OptionalValue.ToString(); var found = false; for (int j = 0; j < i; j++) { if (scope.Statements[j] is VariableDeclaration) { var pvar = (scope.Statements[j] as VariableDeclaration).Variable; if (pvar.ValueType.Equals(var.ValueType) && pvar.OptionalValue != null && pvar.OptionalValue.ToString() == key) { Expression value = new LoadLocal(s.Source, pvar); if (value.ReturnType is FixedArrayType) { value = new AddressOf(value); } foreach (var load in LoadHistory) { if (load.Variable == var) { load.Variable = pvar; } } EmittedValues.Add(mpv, new StageValue(value, CurrentMetaPropertyStage, CurrentMetaPropertyStage)); scope.Statements.RemoveAt(i--); found = true; endIndex--; break; } } } if (!found) { Expression value = new LoadLocal(s.Source, var); if (value.ReturnType is FixedArrayType) { value = new AddressOf(value); } EmittedValues.Add(mpv, new StageValue(value, CurrentMetaPropertyStage, CurrentMetaPropertyStage)); } return(true); } return(false); }