public override Statement VisitAssignmentStatement(AssignmentStatement assignment) { if (assignment == null) return null; assignment.Source = this.VisitExpression(assignment.Source); assignment.Target = this.VisitTargetExpression(assignment.Target); return assignment; }
public override void VisitAssignmentStatement(AssignmentStatement assignment) { if (assignment.Target is Local && IsResultExpression(assignment.Source)) { exemptResultLocal = (Local) assignment.Target; } base.VisitAssignmentStatement(assignment); }
//public override Block VisitBlock(Block block) { // if(block.Statements != null && block.Statements.Count == 1) { // Return r = block.Statements[0] as Return; // if(r != null) { // Statement s = this.VisitReturn(r); // Block retBlock = s as Block; // if(retBlock != null) { // block.Statements = retBlock.Statements; // return block; // } else { // return base.VisitBlock(block); // } // } else { // return base.VisitBlock(block); // } // } else { // return base.VisitBlock(block); // } //} public override Statement VisitReturn(Return Return) { if (Return == null) { return null; } returnCount++; this.lastReturnSourceContext = Return.SourceContext; StatementList stmts = new StatementList(); Return.Expression = this.VisitExpression(Return.Expression); if (Return.Expression != null) { MethodCall mc = Return.Expression as MethodCall; if (mc != null && mc.IsTailCall) { mc.IsTailCall = false; } var assgnmt = new AssignmentStatement(result, Return.Expression); assgnmt.SourceContext = Return.SourceContext; stmts.Add(assgnmt); } // the branch is a "leave" out of the try block that the body will be // in. var branch = new Branch(null, newExit, false, false, this.leaveExceptionBody); branch.SourceContext = Return.SourceContext; stmts.Add(branch); return new Block(stmts); }
/// <summary> /// Returns true the assignment was done from local variable that holds parameter expression /// to the indexer. /// </summary> private bool ExpressionTreeInitialization(AssignmentStatement assignment) { if (assignment == null || assignment.Source == null) return false; var sourceAsLocal = assignment.Source as Local; return NameUtils.IsExpressionTreeLocal(sourceAsLocal); }
public override Statement VisitAssignmentStatement(AssignmentStatement assignment) { this.VisitExpression(assignment.Target); Write(" {0} ", GetAssignmentOperator(assignment.Operator)); this.VisitExpression(assignment.Source); return assignment; }
private AssignmentStatement ParseStoreField(){ Expression rhvalue = PopOperand(); Expression thisob = PopOperand(); AssignmentStatement s = new AssignmentStatement(new MemberBinding(thisob, this.GetMemberFromToken(), this.isVolatile, this.alignment), rhvalue); return s; }
// The method added by Jiri Adamek // It generates NAtiveZOM calls private void GenerateNativeZOMCall(Block block, MethodCall call, bool callIsAsync, AssignmentStatement assignmentStatement) { ZMethod method = (ZMethod)((MemberBinding)call.Callee).BoundMember; // Eventually, this will be checked by an earlier phase. Debug.Assert(method.Parameters.Count == call.Operands.Count); // Asynchronous calls Debug.Assert(!callIsAsync, "async not supporrted for NativeZOM calls"); // Debugging - parameters for (int i = 0, n = call.Operands.Count; i < n; i++) { Parameter param = method.Parameters[i]; Debug.Assert(param != null); // In fact, call.operands[i] MAY BE null due to the error recovery (if the type of the // expression does not match the type in the method definition) // // Debug.Assert(call.Operands[i] != null); Debug.Assert((param.Flags & ParameterFlags.Out) == 0, "out parameters not supported for NativeZOM calls"); } Expression typename = new QualifiedIdentifier(new Identifier("Microsoft.Zing"), method.DeclaringType.Name); Expression callee; if (!method.IsStatic) { callee = Templates.GetExpressionTemplate("NativeZOMCallee"); Replacer.Replace(callee, "_TypeName", typename); Expression pointer = this.VisitExpression(((MemberBinding)call.Callee).TargetObject); Replacer.Replace(callee, "_Pointer", pointer); Replacer.Replace(callee, "_MethodName", method.Name); } else { callee = Templates.GetExpressionTemplate("NativeZOMStaticCall"); Replacer.Replace(callee, "_ClassName", typename); Replacer.Replace(callee, "_MethodName", method.Name); } ExpressionList argumentList = new ExpressionList(); argumentList.Add(Templates.GetExpressionTemplate("NativeZOMCallFirstArgument")); foreach (Expression operand in call.Operands) argumentList.Add(this.VisitExpression(operand)); MethodCall nativeCall = new MethodCall(callee, argumentList); Statement newStatement; if (assignmentStatement != null) { newStatement = Templates.GetStatementTemplate("NativeZOMCallWithAssignment"); Replacer.Replace(newStatement, "_Dest", this.VisitExpression(assignmentStatement.Target)); Replacer.Replace(newStatement, "_Source", nativeCall); } else { newStatement = new ExpressionStatement(nativeCall); } block.Statements.Add(newStatement); }
public override Statement VisitAssignmentStatement(AssignmentStatement assignment) { if (assignment.Source == null || assignment.Target == null) return null; Expression normalizedSource = this.VisitExpression(assignment.Source); Expression normalizedTarget = this.VisitExpression(assignment.Target); assignment.Source = normalizedSource; assignment.Target = normalizedTarget; if (inExpressionStatement) return assignment; else { // This form shows up in initialized local variables. We have to wrap the // assignment back up to get the decompiler to generate appropriate code. ExpressionStatement exprStmt = new ExpressionStatement(new AssignmentExpression(assignment)); exprStmt.SourceContext = assignment.SourceContext; return exprStmt; } }
public override Expression VisitOldExpression(OldExpression oldExpression) { if (this.topLevelClosureClass != null) { #region In Closure ==> Create a field // Since we're within a closure, we can't create a local to hold the value of the old expression // but instead have to create a field for it. That field can be a member of the top-level // closure class since nothing mentioned in the old expression (except possibly for the // bound variables of enclosing quantifications) should be anything captured from // an inner anonymous delegate. // BUT, first we have to know if the old expression depends on any of the bound // variables of the closures in which it is located. If not, then we can implement // it as a scalar and just generate the assignment "closure_class.field := e" for // "Old(e)" to take a snapshot of e's value in the prestate. If it does depend on // any of the bound variables, then we need to generate a set of for-loops that // compute the indices and values of e for each tuple of indices so it can be retrieved // (given the indices) in the post-state. CollectBoundVariables cbv = new CollectBoundVariables(this.stackOfBoundVariables); cbv.VisitExpression(oldExpression.expression); SubstituteClosureClassWithinOldExpressions subst = new SubstituteClosureClassWithinOldExpressions(this.closureLocals); Expression e = subst.VisitExpression(oldExpression.expression); if (cbv.FoundVariables.Count == 0) { #region Use a scalar for the old variable Local closureLocal; if (!this.closureLocals.TryGetValue(this.topLevelClosureClass, out closureLocal)) { Contract.Assume(false, "can't find closure local!"); } #region Define a scalar var clTemplate = HelperMethods.Unspecialize(this.topLevelClosureClass); Field f = new Field(clTemplate, null, FieldFlags.CompilerControlled | FieldFlags.Public, Identifier.For("_old" + oldExpression.expression.UniqueKey.ToString()), // unique name for this old expr. oldExpression.Type, null); clTemplate.Members.Add(f); // now produce properly instantiated field f = (Field)Rewriter.GetMemberInstanceReference(f, this.topLevelClosureClass); #endregion #region Generate code to store value in prestate this.prestateValuesOfOldExpressions.Statements.Add(new AssignmentStatement(new MemberBinding(closureLocal, f), e)); #endregion #region Return expression to be used in poststate // Return an expression that will evaluate in the poststate to the value of the old // expression in the prestate. This will be this.up.f where "up" is the field C# // generated to point to the instance of the top-level closure class. if (this.PointerToTopLevelClosureClass == null) { // then the old expression occurs in the top-level closure class. Just return "this.f" // where "this" refers to the top-level closure class. return new MemberBinding(new This(this.currentClosureClass), f); } else { return new MemberBinding( new MemberBinding(new This(this.currentClosureClass), this.PointerToTopLevelClosureClass), f); } #endregion #endregion } else { // the Old expression *does* depend upon at least one of the bound variable // in a ForAll or Exists expression #region Use an indexed variable for the old variable TypeNode oldVariableTypeDomain; #region Decide if domain is one-dimensional or not bool oneDimensional = cbv.FoundVariables.Count == 1 && cbv.FoundVariables[0].Type.IsValueType; if (oneDimensional) { // a one-dimensional old-expression can use the index variable directly oldVariableTypeDomain = cbv.FoundVariables[0].Type; } else { oldVariableTypeDomain = SystemTypes.GenericList.GetTemplateInstance(this.module, SystemTypes.Int32); } #endregion TypeNode oldVariableTypeRange = oldExpression.Type; TypeNode oldVariableType = SystemTypes.GenericDictionary.GetTemplateInstance(this.module, oldVariableTypeDomain, oldVariableTypeRange); Local closureLocal; if (!this.closureLocals.TryGetValue(this.topLevelClosureClass, out closureLocal)) { Contract.Assume(false, "can't find closure local"); } #region Define an indexed variable var clTemplate = HelperMethods.Unspecialize(this.topLevelClosureClass); Field f = new Field(clTemplate, null, FieldFlags.CompilerControlled | FieldFlags.Assembly, // can't be private or protected because it needs to be accessed from inner (closure) classes that don't inherit from the class this field is added to. Identifier.For("_old" + oldExpression.expression.UniqueKey.ToString()), // unique name for this old expr. oldVariableType, null); clTemplate.Members.Add(f); // instantiate f f = (Field)Rewriter.GetMemberInstanceReference(f, closureLocal.Type); #endregion #region Generate code to initialize the indexed variable Statement init = new AssignmentStatement( new MemberBinding(closureLocal, f), new Construct(new MemberBinding(null, oldVariableType.GetConstructor()), null)); this.prestateValuesOfOldExpressions.Statements.Add(init); #endregion #region Generate code to store values in prestate #region Create assignment: this.closure.f[i,j,k,...] = e; Method setItem = oldVariableType.GetMethod(Identifier.For("set_Item"), oldVariableTypeDomain, oldVariableTypeRange); Expression index; if (oneDimensional) { index = cbv.FoundVariables[0]; } else { //InstanceInitializer ctor = // ContractNodes.TupleClass.GetConstructor(SystemTypes.Int32.GetArrayType(1)); //Expression index = new Construct(new MemberBinding(null,ctor),new ExpressionList( index = Literal.Null; } MethodCall mc = new MethodCall(new MemberBinding(new MemberBinding(closureLocal, f), setItem), new ExpressionList(index, e)); Statement stat = new ExpressionStatement(mc); #endregion List<Local> locals = new List<Local>(this.stackOfBoundVariables.Count); TrivialHashtable paramMap = new TrivialHashtable(); #region Generate a local for each bound variable to use in for-loop foreach (Variable v in this.stackOfBoundVariables) { Local l = new Local(Identifier.Empty, v.Type); paramMap[v.UniqueKey] = l; locals.Add(l); } #endregion #region Substitute locals for bound variables in old expression *AND* in inner loop bounds SubstituteParameters sps = new SubstituteParameters(paramMap, this.stackOfBoundVariables); sps.Visit(stat); #endregion #region Create nested for-loops around assignment // keep track of when the first variable is used (from innermost to outermost) // as soon as the first one is needed because the old expression depends on it, // then keep all enclosing loops. It would be possible to keep only those where // the necessary loops have loop bounds that depend on an enclosing loop, but I // haven't calculated that, so just keep them all. For instance, if the old expression // depends on j and the loops are "for i,0,n" and inside that "for j,0,i", then need // both loops. If the inner loop bounds were 0 and n, then wouldn't need the outer // loop. bool usedAVariable = false; for (int i = this.stackOfBoundVariables.Count - 1; 0 <= i; i--) { if (!usedAVariable && !cbv.FoundVariables.Contains(this.stackOfBoundVariables[i])) continue; usedAVariable = true; Expression lowerBound = new Duplicator(this.module, this.currentClosureClass).VisitExpression( this.stackOfMethods[i].Operands[0]); lowerBound = subst.VisitExpression(lowerBound); lowerBound = sps.VisitExpression(lowerBound); Expression upperBound = new Duplicator(this.module, this.currentClosureClass).VisitExpression( this.stackOfMethods[i].Operands[1]); upperBound = subst.VisitExpression(upperBound); upperBound = sps.VisitExpression(upperBound); stat = RewriteHelper.GenerateForLoop(locals[i], lowerBound, upperBound, stat); } #endregion this.prestateValuesOfOldExpressions.Statements.Add(stat); #endregion #region Return expression to be used in poststate Method getItem = oldVariableType.GetMethod(Identifier.For("get_Item"), oldVariableTypeDomain); if (oneDimensional) { index = cbv.FoundReferences[0]; } else { //InstanceInitializer ctor = // ContractNodes.TupleClass.GetConstructor(SystemTypes.Int32.GetArrayType(1)); //Expression index = new Construct(new MemberBinding(null,ctor),new ExpressionList( index = Literal.Null; } // Return an expression that will evaluate in the poststate to the value of the old // expression in the prestate. This will be this.up.f[i,j,k,...] where "up" is the field C# // generated to point to the instance of the top-level closure class. MemberBinding thisDotF; if (this.PointerToTopLevelClosureClass == null) { // then the old expression occurs in the top-level closure class. Just return "this.f" // where "this" refers to the top-level closure class. Contract.Assume(f != null); thisDotF = new MemberBinding(new This(clTemplate), HelperMethods.Unspecialize(f)); } else { thisDotF = new MemberBinding( new MemberBinding(new This(clTemplate), this.PointerToTopLevelClosureClass), f); } return new MethodCall(new MemberBinding(thisDotF, getItem), new ExpressionList(index)); #endregion #endregion } #endregion } else { #region Not in closure ==> Create a local variable Local l = GetLocalForOldExpression(oldExpression); #region Make sure local can be seen in the debugger (for the entire method, unfortunately) if (currentMethod.LocalList == null) { currentMethod.LocalList = new LocalList(); } currentMethod.LocalList.Add(l); currentMethod.Body.HasLocals = true; #endregion this.prestateValuesOfOldExpressions.Statements.Add( new AssignmentStatement(l, oldExpression.expression)); // Return an expression that will evaluate in the poststate to the value of the old // expression in the prestate. When we're not in a closure, this is just the local // itself. return l; #endregion } }
/// <summary> /// </summary> /// <param name="cons">Cloned</param> /// <returns></returns> public override Expression VisitConstruct(Construct cons) { ExpressionList operands = this.VisitExpressionList(cons.Operands); MemberBinding mb = this.VisitExpression(cons.Constructor) as MemberBinding; if (mb == null) return null; Debug.Assert(mb.TargetObject == null, "constructor target not null!"); if ( this.expandAllocations ) { // Now split the expression into 3: // allocTemp = new T; // allocTemp..ctor(args...); // allocTemp // For value types, the construction is even more involved: // valTemp = new VT; // allocTemp = &valTemp; // allocTemp..ctor(args...); // valTemp if (mb.BoundMember != null && mb.BoundMember.DeclaringType != null && mb.BoundMember.DeclaringType.IsValueType) { Variable valTemp = StackVariable.NEWValueTemp(mb.BoundMember.DeclaringType); Construct newcons = new Construct(new MemberBinding(null, mb.BoundMember), new ExpressionList(0), mb.BoundMember.DeclaringType); AssignmentStatement new_stat = new AssignmentStatement(valTemp, newcons); new_stat.SourceContext = this.current_source_context; new_stats.Add(new_stat); Variable allocTemp = StackVariable.NEWTemp(mb.BoundMember.DeclaringType); new_stats.Add(new AssignmentStatement(allocTemp, new UnaryExpression(valTemp, NodeType.AddressOf, mb.BoundMember.DeclaringType.GetReferenceType()), NodeType.Nop)); mb.TargetObject = allocTemp; ExpressionStatement call_stat = new ExpressionStatement(new MethodCall(mb, operands, NodeType.Call, Cci.SystemTypes.Void)); call_stat.SourceContext = this.current_source_context; new_stats.Add(call_stat); return valTemp; } else { Variable vtemp = StackVariable.NEWTemp(mb.BoundMember.DeclaringType); Construct newcons = new Construct(new MemberBinding(null, mb.BoundMember), new ExpressionList(0), mb.BoundMember.DeclaringType); AssignmentStatement new_stat = new AssignmentStatement(vtemp, newcons); new_stat.SourceContext = this.current_source_context; new_stats.Add(new_stat); mb.TargetObject = vtemp; ExpressionStatement call_stat = new ExpressionStatement(new MethodCall(mb, operands, NodeType.Call, Cci.SystemTypes.Void)); call_stat.SourceContext = this.current_source_context; new_stats.Add(call_stat); return vtemp; } } else { Construct newcons = new Construct(mb, operands, mb.BoundMember.DeclaringType); newcons.SourceContext = this.current_source_context; return newcons; } }
public override Statement VisitAssignmentStatement(AssignmentStatement assignment) { assignment = (AssignmentStatement)assignment.Clone(); Expression target = assignment.Target; Expression source = assignment.Source; if (assignment.SourceContext.Document == null) { assignment.SourceContext = this.current_source_context; } if((target == null) || (source == null)) throw new ApplicationException("Strange CCI format " + CodePrinter.StatementToString(assignment)); switch(target.NodeType) { case NodeType.AddressDereference: assignment.Target = (Expression)this.Visit(target); if (source is Literal && ((Literal)source).Value == null && ((assignment.Target.Type != null && assignment.Target.Type.IsValueType) || (assignment.Target.Type is TypeParameter) || (assignment.Target.Type is ClassParameter))) { // initobj encoding. return assignment; } assignment.Source = simplify(source, true); return assignment; case NodeType.MemberBinding: case NodeType.Indexer: assignment.Target = (Expression)this.Visit(target); assignment.Source = simplify(source, true); return assignment; case NodeType.Local: case NodeType.Parameter: // target is a Variable; we can be more relaxed on the right side // Note: VS has a strange indentation for switch inside a switch ... switch(source.NodeType) { // (source is MethodCall) || case NodeType.Call : case NodeType.Calli : case NodeType.Callvirt : case NodeType.Jmp : case NodeType.MethodCall : // (source is ArrayConstruct) || case NodeType.ConstructArray: // (source is AddressDereference) || case NodeType.AddressDereference: // (source is MemberBinding) || case NodeType.MemberBinding: // (source is Indexer) case NodeType.Indexer: assignment.Source = (Expression)this.Visit(source); break; case NodeType.Literal: break; // (source is Construct) case NodeType.Construct: default: assignment.Source = simplify(source, true); break; } return assignment; default: throw new ApplicationException("Strange CCI format " + CodePrinter.StatementToString(assignment)); } }
// After they have been duplicated for each "leave" instruction, the "finally" // handlers are transformed into catch handlers that rethrow their exceptions. // public void ConvertFinallyHandlerIntoCatchHandler () { foreach (ExceptionHandler eh in this.allExceptionHandlers) { if (eh.HandlerType == NodeType.Finally || eh.HandlerType == NodeType.FaultHandler) { // transform the finally / fault handler into a catch handler ... eh.HandlerType = NodeType.Catch; // ... that catches all exceptions ... (cont'd at alpha) // (btw: in MSIL, one can throw any object, including non-Exceptions) eh.FilterType = Cci.SystemTypes.Object; // variable to store the caught exception (we can't leave it on the stack because the // code of the original finally handler must start with an empty stack). Variable exceptionVariable = new Local(new Identifier(FINALLYVARPREFIX + (finally_var_count++)), eh.FilterType); // the new catch handler must start with FINALLYVARPREFIX<n> := EPOP ... Block firstBlock = eh.HandlerStartBlock; StatementList stats = firstBlock.Statements; StatementList newBlockStatements = new StatementList(); AssignmentStatement exceptionAssignment = new AssignmentStatement(exceptionVariable, new Expression(NodeType.Pop)); if (stats.Count > 0) { exceptionAssignment.SourceContext = stats[0].SourceContext; exceptionAssignment.Source.SourceContext = stats[0].SourceContext; } newBlockStatements.Add(exceptionAssignment); for(int i = 0; i < stats.Count; i++) { newBlockStatements.Add(stats[i]); } firstBlock.Statements = newBlockStatements; // (alpha) ... and rethrows the exception. // replace the last instruction of eh with a throw exceptionVariable Block lastBlock = (Block) this.lastHandledBlock[eh]; Statement lastStatement = lastBlock.Statements[lastBlock.Statements.Count - 1]; if (lastStatement is EndFinally) { // replace the endfinally with a rethrow; this is OK because (re)throw flushes the stack too. Statement throwStatement; { #if EXPLICIT_THROW_OF_CAPTURED_VARIABLE_RATHER_THAN_RETHROW_IN_FINALLY_EXPANDED_CATCH if (false) // for now { throwStatement = new Throw(exceptionVariable); } else #endif throwStatement = new Throw(null); throwStatement.NodeType = NodeType.Rethrow; } throwStatement.SourceContext = lastBlock.Statements[lastBlock.Statements.Count - 1].SourceContext; lastBlock.Statements[lastBlock.Statements.Count - 1] = throwStatement; } else { Debug.Assert(lastStatement is Throw, "finally/fault not terminated in endfinally/endfault or throw! " + CodePrinter.StatementToString(lastBlock.Statements[lastBlock.Statements.Count - 1])); } } } }
private static bool IsCoalescableAssignment(AssignmentStatement aStmt) { if (aStmt == null) return true; if (aStmt.Source == null || aStmt.Target == null) return false; if (aStmt.Source is MethodCall) return false; if ((ZingNodeType)aStmt.Source.NodeType == ZingNodeType.Choose) return false; return true; }
public override Statement VisitAssignmentStatement(AssignmentStatement assignment) { if (assignment == null) return null; BasicBlock block = AddBlock(new BasicBlock(assignment, CurrentContinuation)); CurrentContinuation = block; return assignment; }
public override Statement VisitAssignmentStatement(AssignmentStatement assignment) { if (assignment == null) return null; return base.VisitAssignmentStatement((AssignmentStatement)assignment.Clone()); }
/// <summary> /// Have to special case assignment of "this" param into other local or closure this-field when we have call-site wrappers /// for constrained virtcalls. In this case, we have to insert a box. /// </summary> public override Statement VisitAssignmentStatement(AssignmentStatement assignment) { if (assignment == null) return null; var result = base.VisitAssignmentStatement(assignment); assignment = result as AssignmentStatement; if (assignment != null && assignment.Target != null && assignment.Target.Type is Interface) { if (assignment.Source != null & assignment.Source.Type is Reference) { var refType = (Reference) assignment.Source.Type; if (refType.ElementType is ITypeParameter) { // found a type mismatch assignment.Source = new BinaryExpression( new AddressDereference(assignment.Source, refType.ElementType), new Literal(refType.ElementType), NodeType.Box); } } } return result; }
private void AddContinueWithMethodToReturnBlock(Block returnBlock, Local taskBasedResult) { Contract.Requires(returnBlock != null); Contract.Requires(taskBasedResult != null); var taskType = taskBasedResult.Type; // To find appropriate ContinueWith method task type should be unwrapped var taskTemplate = HelperMethods.Unspecialize(taskType); var continueWithMethodLocal = GetContinueWithMethod(closureClass, taskTemplate, taskType); // TODO: not sure that this is possible situation when continueWith method is null. // Maybe Contract.Assert(continueWithMethod != null) should be used instead! if (continueWithMethodLocal != null) { // We need to create delegate instance that should be passed to ContinueWith method var funcType = continueWithMethodLocal.Parameters[0].Type; var funcCtor = funcType.GetConstructor(SystemTypes.Object, SystemTypes.IntPtr); Contract.Assume(funcCtor != null); var funcLocal = new Local(funcCtor.DeclaringType); // Creating a method pointer to the AsyncClosure.CheckMethod // In this case we can't use checkMethod field. // Getting CheckMethod from clsoureClassInstance will provide correct (potentially updated) // generic arguments for enclosing type. var checkMethodFromClosureInstance = (Method) closureClassInstance.GetMembersNamed(CheckMethodId)[0]; Contract.Assume(checkMethodFromClosureInstance != null); var ldftn = new UnaryExpression( new MemberBinding(null, checkMethodFromClosureInstance), NodeType.Ldftn, CoreSystemTypes.IntPtr); // Creating delegate that would be used as a continuation for original task returnBlock.Statements.Add( new AssignmentStatement(funcLocal, new Construct(new MemberBinding(null, funcCtor), new ExpressionList(closureLocal, ldftn)))); // Wrapping continuation into TaskExtensions.Unwrap method // (this helps to preserve original exception and original result of the task, // but allows to throw postconditions violations). // Generating: result.ContinueWith(closure.CheckPost); var taskContinuationOption = new Literal(TaskContinuationOptions.ExecuteSynchronously); var continueWithCall = new MethodCall( new MemberBinding(taskBasedResult, continueWithMethodLocal), new ExpressionList(funcLocal, taskContinuationOption)); // Generating: TaskExtensions.Unwrap(result.ContinueWith(...)) var unwrapMethod = GetUnwrapMethod(checkMethodTaskType); var unwrapCall = new MethodCall( new MemberBinding(null, unwrapMethod), new ExpressionList(continueWithCall)); // Generating: result = Unwrap(...); var resultAssignment = new AssignmentStatement(taskBasedResult, unwrapCall); returnBlock.Statements.Add(resultAssignment); } }
public override void VisitAssignmentStatement(AssignmentStatement assignment) { Expression source = assignment.Source; Construct sourceConstruct = source as Construct; if (sourceConstruct != null) { if (sourceConstruct.Type != null && sourceConstruct.Type.Name.Name.StartsWith(this.closureTag)) { if (sourceConstruct.Type.Template != null) { TypeNode template = sourceConstruct.Type.Template; while (template.Template != null) { template = template.Template; } this.closureClass = (Class) template; } else { this.closureClass = (Class) sourceConstruct.Type; } return; } } if (IAsyncStateMachineType == null) { return; } var mb = assignment.Target as MemberBinding; if (mb != null) { var addrOf = mb.TargetObject as UnaryExpression; if (addrOf != null && addrOf.NodeType == NodeType.AddressOf) { var loc = addrOf.Operand as Local; if (loc != null) { var cand = loc.Type; if (HelperMethods.IsCompilerGenerated(cand) && cand.IsAssignableTo(IAsyncStateMachineType)) { this.closureClass = HelperMethods.Unspecialize(cand); } } } } }
public AssignmentExpression(AssignmentStatement assignment) : base(NodeType.AssignmentExpression) { this.AssignmentStatement = assignment; }
private void GenerateMethodReturn(Block block, AssignmentStatement assignmentStatement, MethodCall call) { ZMethod method = (ZMethod)((MemberBinding)call.Callee).BoundMember; // Eventually, this will be checked by an earlier phase. Debug.Assert(method.Parameters.Count == call.Operands.Count); // process output parameters and the return value; for (int i = 0, n = call.Operands.Count; i < n; i++) { Parameter param = method.Parameters[i]; if ((param.Flags & ParameterFlags.Out) != 0 && call.Operands[i] != null && method.Parameters[i] != null) { Statement assignOutParam = Templates.GetStatementTemplate("FetchOutputParameter"); Replacer.Replace(assignOutParam, "_dest", this.VisitExpression(((UnaryExpression)call.Operands[i]).Operand)); Replacer.Replace(assignOutParam, "_paramName", new Identifier("_Lfc_" + method.Parameters[i].Name.Name)); Replacer.Replace(assignOutParam, "_Callee", method.Name); Replacer.Replace(assignOutParam, "_CalleeClass", method.DeclaringType.Name); block.Statements.Add(assignOutParam); } } if (assignmentStatement != null) { Statement assignReturnValue = Templates.GetStatementTemplate("FetchReturnValue"); Replacer.Replace(assignReturnValue, "_dest", this.VisitExpression(assignmentStatement.Target)); Replacer.Replace(assignReturnValue, "_CalleeClass", method.DeclaringType.Name); Replacer.Replace(assignReturnValue, "_Callee", method.Name); block.Statements.Add(assignReturnValue); } Statement stmt = Templates.GetStatementTemplate("InvalidateLastFunctionCompleted"); block.Statements.Add(stmt); }
private Expression ParseAssignmentExpression(Expression operand1, TokenSet followers){ Debug.Assert(Parser.InfixOperators[this.currentToken]); Debug.Assert(this.currentToken != Token.Conditional); switch (this.currentToken){ case Token.AddAssign: case Token.Assign: case Token.BitwiseAndAssign: case Token.BitwiseOrAssign: case Token.BitwiseXorAssign: case Token.DivideAssign: case Token.LeftShiftAssign: case Token.MultiplyAssign: case Token.RemainderAssign: case Token.RightShiftAssign: case Token.SubtractAssign: Token assignmentOperator = this.currentToken; this.GetNextToken(); Expression operand2 = this.ParseExpression(followers); if (operand1 == null || operand2 == null) return null; AssignmentStatement statement = new AssignmentStatement(operand1, operand2, Parser.ConvertToBinaryNodeType(assignmentOperator)); statement.SourceContext = operand1.SourceContext; statement.SourceContext.EndPos = operand2.SourceContext.EndPos; Expression expression = new AssignmentExpression(statement); expression.SourceContext = statement.SourceContext; return expression; default: operand1 = this.ParseBinaryExpression(operand1, followers|Token.Conditional); if (operand1 != null && this.currentToken == Token.Conditional) return this.ParseConditional(operand1, followers); return operand1; } }
private bool ParseStatement(Block/*!*/ block) { //parse instructions and put in expression tree until an assignment, void call, branch target, or branch is encountered StatementList statementList = block.Statements; Expression expr = null; Statement statement = null; bool transferStatement = false; int startingAddress = 0; #if !FxCop SourceContext sourceContext = new SourceContext(); sourceContext.StartPos = this.counter; #endif #if !ROTOR if (this.method.contextForOffset != null){ object sctx = this.method.contextForOffset[this.counter+1]; if (sctx != null) sourceContext = (SourceContext)sctx; } #endif while (true){ bool isStatement = false; startingAddress = this.counter+1; //Add one so that it is never zero (the latter means no entry to the TrivialHashtable) #if FxCop || ILOFFSETS this.ilOffset = this.counter; this.opCode = this.GetOpCode(); #else OpCode opCode = this.GetOpCode(); #endif #if FxCop if (this.handlerMap.TryGetValue(this.ilOffset, out expr)){ expr.sourceContext = sourceContext; expr.ILOffset = this.ilOffset; this.operandStack.Push(expr); } #endif switch (opCode){ case OpCode.Nop: statement = new Statement(NodeType.Nop); goto done; case OpCode.Break: statement = new Statement(NodeType.DebugBreak); goto done; case OpCode.Ldarg_0: expr = this.Parameters(0); break; case OpCode.Ldarg_1: expr = this.Parameters(1); break; case OpCode.Ldarg_2: expr = this.Parameters(2); break; case OpCode.Ldarg_3: expr = this.Parameters(3); break; case OpCode.Ldloc_0: expr = this.locals[0]; break; case OpCode.Ldloc_1: expr = this.locals[1]; break; case OpCode.Ldloc_2: expr = this.locals[2]; break; case OpCode.Ldloc_3: expr = this.locals[3]; break; case OpCode.Stloc_0: statement = new AssignmentStatement(this.locals[0], PopOperand()); goto done; case OpCode.Stloc_1: statement = new AssignmentStatement(this.locals[1], PopOperand()); goto done; case OpCode.Stloc_2: statement = new AssignmentStatement(this.locals[2], PopOperand()); goto done; case OpCode.Stloc_3: statement = new AssignmentStatement(this.locals[3], PopOperand()); goto done; case OpCode.Ldarg_S: expr = this.Parameters(this.GetByte()); break; case OpCode.Ldarga_S: expr = SetType(new UnaryExpression(this.Parameters(this.GetByte()), NodeType.AddressOf)); break; case OpCode.Starg_S: statement = new AssignmentStatement(this.Parameters(this.GetByte()), PopOperand()); goto done; case OpCode.Ldloc_S: expr = this.locals[this.GetByte()]; break; case OpCode.Ldloca_S: expr = SetType(new UnaryExpression(this.locals[this.GetByte()], NodeType.AddressOf)); break; case OpCode.Stloc_S: statement = new AssignmentStatement(this.locals[this.GetByte()], PopOperand()); goto done; case OpCode.Ldnull: expr = new Literal(null, CoreSystemTypes.Object); break; case OpCode.Ldc_I4_M1: expr = new Literal(-1, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_0: expr = new Literal(0, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_1: expr = new Literal(1, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_2: expr = new Literal(2, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_3: expr = new Literal(3, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_4: expr = new Literal(4, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_5: expr = new Literal(5, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_6: expr = new Literal(6, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_7: expr = new Literal(7, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_8: expr = new Literal(8, CoreSystemTypes.Int32); break; case OpCode.Ldc_I4_S: expr = new Literal((int)this.GetSByte(), CoreSystemTypes.Int32); break; case OpCode.Ldc_I4: expr = new Literal(this.GetInt32(), CoreSystemTypes.Int32); break; case OpCode.Ldc_I8: expr = new Literal(this.GetInt64(), CoreSystemTypes.Int64); break; case OpCode.Ldc_R4: expr = new Literal(this.GetSingle(), CoreSystemTypes.Single); break; case OpCode.Ldc_R8: expr = new Literal(this.GetDouble(), CoreSystemTypes.Double); break; case OpCode.Dup: statement = new ExpressionStatement(new Expression(NodeType.Dup)); goto done; case OpCode.Pop: statement = new ExpressionStatement(new UnaryExpression(PopOperand(), NodeType.Pop)); goto done; case OpCode.Jmp: expr = this.ParseCall(NodeType.Jmp, out isStatement); if (isStatement) goto done; break; case OpCode.Call: expr = this.ParseCall(NodeType.Call, out isStatement); if (isStatement) goto done; break; case OpCode.Calli: expr = this.ParseCalli(out isStatement); if (isStatement) goto done; break; case OpCode.Ret: Expression retVal = BodyParser.TypeIsVoid(this.method.ReturnType) ? null : PopOperand(); statement = new Return(retVal); transferStatement = true; goto done; case OpCode.Br_S: statement = this.ParseBranch(NodeType.Nop, 0, true, false); transferStatement = true; goto done; case OpCode.Brfalse_S: statement = this.ParseBranch(NodeType.LogicalNot, 1, true, false); transferStatement = true; goto done; case OpCode.Brtrue_S: statement = this.ParseBranch(NodeType.Nop, 1, true, false); transferStatement = true; goto done; case OpCode.Beq_S: statement = this.ParseBranch(NodeType.Eq, 2, true, false); transferStatement = true; goto done; case OpCode.Bge_S: statement = this.ParseBranch(NodeType.Ge, 2, true, false); transferStatement = true; goto done; case OpCode.Bgt_S: statement = this.ParseBranch(NodeType.Gt, 2, true, false); transferStatement = true; goto done; case OpCode.Ble_S: statement = this.ParseBranch(NodeType.Le, 2, true, false); transferStatement = true; goto done; case OpCode.Blt_S: statement = this.ParseBranch(NodeType.Lt, 2, true, false); transferStatement = true; goto done; case OpCode.Bne_Un_S: statement = this.ParseBranch(NodeType.Ne, 2, true, true); transferStatement = true; goto done; case OpCode.Bge_Un_S: statement = this.ParseBranch(NodeType.Ge, 2, true, true); transferStatement = true; goto done; case OpCode.Bgt_Un_S: statement = this.ParseBranch(NodeType.Gt, 2, true, true); transferStatement = true; goto done; case OpCode.Ble_Un_S: statement = this.ParseBranch(NodeType.Le, 2, true, true); transferStatement = true; goto done; case OpCode.Blt_Un_S: statement = this.ParseBranch(NodeType.Lt, 2, true, true); transferStatement = true; goto done; case OpCode.Br: statement = this.ParseBranch(NodeType.Nop, 0, false, false); transferStatement = true; goto done; case OpCode.Brfalse: statement = this.ParseBranch(NodeType.LogicalNot, 1, false, false); transferStatement = true; goto done; case OpCode.Brtrue: statement = this.ParseBranch(NodeType.Nop, 1, false, false); transferStatement = true; goto done; case OpCode.Beq: statement = this.ParseBranch(NodeType.Eq, 2, false, false); transferStatement = true; goto done; case OpCode.Bge: statement = this.ParseBranch(NodeType.Ge, 2, false, false); transferStatement = true; goto done; case OpCode.Bgt: statement = this.ParseBranch(NodeType.Gt, 2, false, false); transferStatement = true; goto done; case OpCode.Ble: statement = this.ParseBranch(NodeType.Le, 2, false, false); transferStatement = true; goto done; case OpCode.Blt: statement = this.ParseBranch(NodeType.Lt, 2, false, false); transferStatement = true; goto done; case OpCode.Bne_Un: statement = this.ParseBranch(NodeType.Ne, 2, false, true); transferStatement = true; goto done; case OpCode.Bge_Un: statement = this.ParseBranch(NodeType.Ge, 2, false, true); transferStatement = true; goto done; case OpCode.Bgt_Un: statement = this.ParseBranch(NodeType.Gt, 2, false, true); transferStatement = true; goto done; case OpCode.Ble_Un: statement = this.ParseBranch(NodeType.Le, 2, false, true); transferStatement = true; goto done; case OpCode.Blt_Un: statement = this.ParseBranch(NodeType.Lt, 2, false, true); transferStatement = true; goto done; case OpCode.Switch: statement = this.ParseSwitchInstruction(); transferStatement = true; goto done; case OpCode.Ldind_I1: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int8, this.isVolatile, this.alignment); break; case OpCode.Ldind_U1: expr = new AddressDereference(PopOperand(), CoreSystemTypes.UInt8, this.isVolatile, this.alignment); break; case OpCode.Ldind_I2: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int16, this.isVolatile, this.alignment); break; case OpCode.Ldind_U2: expr = new AddressDereference(PopOperand(), CoreSystemTypes.UInt16, this.isVolatile, this.alignment); break; case OpCode.Ldind_I4: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int32, this.isVolatile, this.alignment); break; case OpCode.Ldind_U4: expr = new AddressDereference(PopOperand(), CoreSystemTypes.UInt32, this.isVolatile, this.alignment); break; case OpCode.Ldind_I8: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int64, this.isVolatile, this.alignment); break; case OpCode.Ldind_I: expr = new AddressDereference(PopOperand(), CoreSystemTypes.IntPtr, this.isVolatile, this.alignment); break; case OpCode.Ldind_R4: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Single, this.isVolatile, this.alignment); break; case OpCode.Ldind_R8: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Double, this.isVolatile, this.alignment); break; case OpCode.Ldind_Ref: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Object, this.isVolatile, this.alignment); break; case OpCode.Stind_Ref: statement = this.ParseStoreIndirect(CoreSystemTypes.Object); goto done; case OpCode.Stind_I1: statement = this.ParseStoreIndirect(CoreSystemTypes.Int8); goto done; case OpCode.Stind_I2: statement = this.ParseStoreIndirect(CoreSystemTypes.Int16); goto done; case OpCode.Stind_I4: statement = this.ParseStoreIndirect(CoreSystemTypes.Int32); goto done; case OpCode.Stind_I8: statement = this.ParseStoreIndirect(CoreSystemTypes.Int64); goto done; case OpCode.Stind_R4: statement = this.ParseStoreIndirect(CoreSystemTypes.Single); goto done; case OpCode.Stind_R8: statement = this.ParseStoreIndirect(CoreSystemTypes.Double); goto done; case OpCode.Add: expr = this.ParseBinaryOperation(NodeType.Add); break; case OpCode.Sub: expr = this.ParseBinaryOperation(NodeType.Sub); break; case OpCode.Mul: expr = this.ParseBinaryOperation(NodeType.Mul); break; case OpCode.Div: expr = this.ParseBinaryOperation(NodeType.Div); break; case OpCode.Div_Un: expr = this.ParseBinaryOperation(NodeType.Div_Un); break; case OpCode.Rem: expr = this.ParseBinaryOperation(NodeType.Rem); break; case OpCode.Rem_Un: expr = this.ParseBinaryOperation(NodeType.Rem_Un); break; case OpCode.And: expr = this.ParseBinaryOperation(NodeType.And); break; case OpCode.Or: expr = this.ParseBinaryOperation(NodeType.Or); break; case OpCode.Xor: expr = this.ParseBinaryOperation(NodeType.Xor); break; case OpCode.Shl: expr = this.ParseBinaryOperation(NodeType.Shl); break; case OpCode.Shr: expr = this.ParseBinaryOperation(NodeType.Shr); break; case OpCode.Shr_Un: expr = this.ParseBinaryOperation(NodeType.Shr_Un); break; case OpCode.Neg: expr = this.ParseUnaryOperation(NodeType.Neg); break; case OpCode.Not: expr = this.ParseUnaryOperation(NodeType.Not); break; case OpCode.Conv_I1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I1, CoreSystemTypes.Int8); break; case OpCode.Conv_I2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I2, CoreSystemTypes.Int16); break; case OpCode.Conv_I4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I4, CoreSystemTypes.Int32); break; case OpCode.Conv_I8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I8, CoreSystemTypes.Int64); break; case OpCode.Conv_R4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_R4, CoreSystemTypes.Single); break; case OpCode.Conv_R8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_R8, CoreSystemTypes.Double); break; case OpCode.Conv_U4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U4, CoreSystemTypes.UInt32); break; case OpCode.Conv_U8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U8, CoreSystemTypes.UInt64); break; case OpCode.Callvirt: expr = this.ParseCall(NodeType.Callvirt, out isStatement); if (isStatement) goto done; break; case OpCode.Cpobj: statement = this.ParseCopyObject(); goto done; case OpCode.Ldobj: expr = new AddressDereference(PopOperand(), (TypeNode)this.GetMemberFromToken(), this.isVolatile, this.alignment); break; case OpCode.Ldstr: expr = new Literal(this.GetStringFromToken(), CoreSystemTypes.String); break; case OpCode.Newobj: expr = this.ParseConstruct(); break; case OpCode.Castclass: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.Castclass); break; case OpCode.Isinst: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.Isinst); break; case OpCode.Conv_R_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_R_Un, CoreSystemTypes.Double); break; case OpCode.Unbox: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.Unbox); break; case OpCode.Throw: statement = new Throw(PopOperand()); transferStatement = true; goto done; case OpCode.Ldfld: expr = new MemberBinding(PopOperand(), this.GetMemberFromToken(), this.isVolatile, this.alignment); break; case OpCode.Ldflda: expr = SetType(new UnaryExpression(new MemberBinding(PopOperand(), this.GetMemberFromToken(), this.isVolatile, this.alignment), NodeType.AddressOf)); break; case OpCode.Stfld: statement = this.ParseStoreField(); goto done; case OpCode.Ldsfld: expr = new MemberBinding(null, this.GetMemberFromToken(), this.isVolatile, this.alignment); break; case OpCode.Ldsflda: expr = SetType(new UnaryExpression(new MemberBinding(null, this.GetMemberFromToken(), this.isVolatile, this.alignment), NodeType.AddressOf)); break; case OpCode.Stsfld: statement = new AssignmentStatement(new MemberBinding(null, this.GetMemberFromToken(), this.isVolatile, this.alignment), PopOperand()); goto done; case OpCode.Stobj: statement = this.ParseStoreIndirect((TypeNode)this.GetMemberFromToken()); goto done; case OpCode.Conv_Ovf_I1_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I1_Un, CoreSystemTypes.Int8); break; case OpCode.Conv_Ovf_I2_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I2_Un, CoreSystemTypes.Int16); break; case OpCode.Conv_Ovf_I4_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I4_Un, CoreSystemTypes.Int32); break; case OpCode.Conv_Ovf_I8_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I8_Un, CoreSystemTypes.Int64); break; case OpCode.Conv_Ovf_U1_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U1_Un, CoreSystemTypes.UInt8); break; case OpCode.Conv_Ovf_U2_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U2_Un, CoreSystemTypes.UInt16); break; case OpCode.Conv_Ovf_U4_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U4_Un, CoreSystemTypes.UInt32); break; case OpCode.Conv_Ovf_U8_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U8_Un, CoreSystemTypes.UInt64); break; case OpCode.Conv_Ovf_I_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I_Un, CoreSystemTypes.IntPtr); break; case OpCode.Conv_Ovf_U_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U_Un, CoreSystemTypes.UIntPtr); break; case OpCode.Box: TypeNode t = (TypeNode)this.GetMemberFromToken(); TypeNode bt = t is EnumNode ? CoreSystemTypes.Enum : CoreSystemTypes.ValueType; expr = new BinaryExpression(PopOperand(), new Literal(t, CoreSystemTypes.Type), NodeType.Box, bt); break; case OpCode.Newarr: expr = this.ParseNewArray(); break; case OpCode.Ldlen: expr = new UnaryExpression(PopOperand(), NodeType.Ldlen, CoreSystemTypes.UIntPtr); break; case OpCode.Ldelema: expr = this.ParseArrayElementLoadAddress(); break; case OpCode.Ldelem_I1: case OpCode.Ldelem_U1: case OpCode.Ldelem_I2: case OpCode.Ldelem_U2: case OpCode.Ldelem_I4: case OpCode.Ldelem_U4: case OpCode.Ldelem_I8: case OpCode.Ldelem_I: case OpCode.Ldelem_R4: case OpCode.Ldelem_R8: case OpCode.Ldelem_Ref: expr = this.ParseArrayElementLoad(opCode, null); break; case OpCode.Stelem_I: case OpCode.Stelem_I1: case OpCode.Stelem_I2: case OpCode.Stelem_I4: case OpCode.Stelem_I8: case OpCode.Stelem_R4: case OpCode.Stelem_R8: case OpCode.Stelem_Ref: statement = this.ParseArrayElementAssignment(opCode); goto done; case OpCode.Ldelem: expr = this.ParseArrayElementLoad(opCode, null); break; case OpCode.Stelem: statement = this.ParseArrayElementAssignment(opCode); goto done; case OpCode.Unbox_Any: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.UnboxAny); break; case OpCode.Conv_Ovf_I1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I1, CoreSystemTypes.Int8); break; case OpCode.Conv_Ovf_U1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U1, CoreSystemTypes.UInt8); break; case OpCode.Conv_Ovf_I2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I2, CoreSystemTypes.Int16); break; case OpCode.Conv_Ovf_U2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U2, CoreSystemTypes.UInt16); break; case OpCode.Conv_Ovf_I4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I4, CoreSystemTypes.Int32); break; case OpCode.Conv_Ovf_U4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U4, CoreSystemTypes.UInt32); break; case OpCode.Conv_Ovf_I8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I8, CoreSystemTypes.Int64); break; case OpCode.Conv_Ovf_U8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U8, CoreSystemTypes.UInt64); break; case OpCode.Refanyval: expr = new BinaryExpression(PopOperand(), new Literal(this.GetMemberFromToken(), CoreSystemTypes.Type), NodeType.Refanyval, CoreSystemTypes.IntPtr); break; case OpCode.Ckfinite: expr = this.ParseUnaryOperation(NodeType.Ckfinite); break; case OpCode.Mkrefany: expr = new BinaryExpression(PopOperand(), new Literal(this.GetMemberFromToken(), CoreSystemTypes.Type), NodeType.Mkrefany, CoreSystemTypes.DynamicallyTypedReference); break; case OpCode.Ldtoken: expr = ParseLoadRuntimeMetadataToken(); break; case OpCode.Conv_U2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U2, CoreSystemTypes.UInt16); break; case OpCode.Conv_U1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U1, CoreSystemTypes.UInt8); break; case OpCode.Conv_I: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I, CoreSystemTypes.IntPtr); break; case OpCode.Conv_Ovf_I: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I, CoreSystemTypes.IntPtr); break; case OpCode.Conv_Ovf_U: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U, CoreSystemTypes.UIntPtr); break; case OpCode.Add_Ovf: expr = this.ParseBinaryOperation(NodeType.Add_Ovf); break; case OpCode.Add_Ovf_Un: expr = this.ParseBinaryOperation(NodeType.Add_Ovf_Un); break; case OpCode.Mul_Ovf: expr = this.ParseBinaryOperation(NodeType.Mul_Ovf); break; case OpCode.Mul_Ovf_Un: expr = this.ParseBinaryOperation(NodeType.Mul_Ovf_Un); break; case OpCode.Sub_Ovf: expr = this.ParseBinaryOperation(NodeType.Sub_Ovf); break; case OpCode.Sub_Ovf_Un: expr = this.ParseBinaryOperation(NodeType.Sub_Ovf_Un); break; case OpCode.Endfinally: statement = new EndFinally(); transferStatement = true; goto done; case OpCode.Leave: statement = this.ParseBranch(NodeType.Nop, 0, false, false, true); transferStatement = true; goto done; case OpCode.Leave_S: statement = this.ParseBranch(NodeType.Nop, 0, true, false, true); transferStatement = true; goto done; case OpCode.Stind_I: statement = this.ParseStoreIndirect(CoreSystemTypes.IntPtr); goto done; case OpCode.Conv_U: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U, CoreSystemTypes.UIntPtr); break; case OpCode.Arglist: expr = new Expression(NodeType.Arglist, CoreSystemTypes.ArgIterator); break; case OpCode.Ceq: expr = this.ParseBinaryComparison(NodeType.Ceq); break; case OpCode.Cgt: expr = this.ParseBinaryComparison(NodeType.Cgt); break; case OpCode.Cgt_Un: expr = this.ParseBinaryComparison(NodeType.Cgt_Un); break; case OpCode.Clt: expr = this.ParseBinaryComparison(NodeType.Clt); break; case OpCode.Clt_Un: expr = this.ParseBinaryComparison(NodeType.Clt_Un); break; case OpCode.Ldftn: expr = new UnaryExpression(new MemberBinding(null, this.GetMemberFromToken()), NodeType.Ldftn, CoreSystemTypes.IntPtr); break; case OpCode.Ldvirtftn: expr = new BinaryExpression(PopOperand(), new MemberBinding(null, this.GetMemberFromToken()), NodeType.Ldvirtftn, CoreSystemTypes.IntPtr); break; case OpCode.Ldarg: expr = this.Parameters((ushort)this.GetInt16()); break; case OpCode.Ldarga: expr = SetType(new UnaryExpression(this.Parameters((ushort)this.GetInt16()), NodeType.AddressOf)); break; case OpCode.Starg: statement = new AssignmentStatement(this.Parameters((ushort)this.GetInt16()), PopOperand()); goto done; case OpCode.Ldloc: expr = this.locals[(ushort)this.GetInt16()]; break; case OpCode.Ldloca: expr = SetType(new UnaryExpression(this.locals[(ushort)this.GetInt16()], NodeType.AddressOf)); break; case OpCode.Stloc: statement = new AssignmentStatement(this.locals[(ushort)this.GetInt16()], PopOperand()); goto done; case OpCode.Localloc: expr = new UnaryExpression(PopOperand(), NodeType.Localloc, CoreSystemTypes.Void); break; case OpCode.Endfilter: statement = new EndFilter(PopOperand()); transferStatement = true; goto done; case OpCode.Unaligned_: this.alignment = this.GetByte(); continue; case OpCode.Volatile_: this.isVolatile = true; continue; case OpCode.Tail_: this.isTailCall = true; continue; case OpCode.Initobj: statement = this.ParseInitObject(); goto done; case OpCode.Constrained_: this.constraint = this.GetMemberFromToken() as TypeNode; continue; case OpCode.Cpblk: expr = this.ParseTernaryOperation(NodeType.Cpblk); goto done; case OpCode.Initblk: expr = this.ParseTernaryOperation(NodeType.Initblk); goto done; case OpCode.Rethrow: statement = new Throw(null); statement.NodeType = NodeType.Rethrow; transferStatement = true; goto done; case OpCode.Sizeof: expr = new UnaryExpression(new Literal(this.GetMemberFromToken(), CoreSystemTypes.Type), NodeType.Sizeof, CoreSystemTypes.Int32); break; case OpCode.Refanytype: expr = new UnaryExpression(PopOperand(), NodeType.Refanytype, CoreSystemTypes.RuntimeTypeHandle); break; case OpCode.Readonly_: this.isReadOnly = true; continue; default: throw new InvalidMetadataException(ExceptionStrings.UnknownOpCode); } if (this.blockMap[this.counter+1] != null){ transferStatement = true; //Falls through to the next basic block, so implicitly a "transfer" statement goto done; } //^ assume expr != null; #if FxCop expr.sourceContext = sourceContext; #endif #if FxCop || ILOFFSETS expr.ILOffset = this.ilOffset; #endif this.operandStack.Push(expr); this.isReadOnly = false; this.isVolatile = false; this.isTailCall = false; this.alignment = -1; } done: for (int i = 0; i <= this.operandStack.top; i++){ Expression e = this.operandStack.elements[i]; //^ assume e != null; Statement s = new ExpressionStatement(e); #if FxCop s.SourceContext = this.sourceContext; #endif #if FxCop || ILOFFSETS s.ILOffset = this.ilOffset; #endif statementList.Add(s); } this.operandStack.top = -1; if (statement == null) { statement = new ExpressionStatement(expr); #if FxCop expr.sourceContext = this.sourceContext; #endif #if FxCop || ILOFFSETS expr.ILOffset = this.ilOffset; #endif } statement.SourceContext = sourceContext; #if FxCop || ILOFFSETS statement.ILOffset = this.ilOffset; #endif #if ILOFFSETS this.lastSourceContext = sourceContext; #endif statementList.Add(statement); if (transferStatement) return true; return this.blockMap[this.counter+1] != null; }
public override void VisitAssignmentStatement(AssignmentStatement assignment) { if (assignment == null) return; Construct cons = assignment.Source as Construct; if (cons == null) goto JustVisit; if (!(cons.Type.IsDelegateType())) goto JustVisit; UnaryExpression ue = cons.Operands[1] as UnaryExpression; if (ue == null) goto JustVisit; MemberBinding mb = ue.Operand as MemberBinding; if (mb == null) goto JustVisit; Method m = mb.BoundMember as Method; if (m.IsStatic) { mb = assignment.Target as MemberBinding; if (mb == null) goto JustVisit; if (mb.TargetObject != null) goto JustVisit; // Record the static cache field used to hold the static closure MembersToDuplicate.Add(mb.BoundMember); goto End; } JustVisit: if (assignment.Source == null) goto JustVisit2; if (assignment.Source.NodeType != NodeType.Pop) goto JustVisit2; mb = assignment.Target as MemberBinding; if (mb == null) goto JustVisit2; if (mb.TargetObject != null) goto JustVisit2; if (mb.BoundMember == null) goto JustVisit2; if (HelperMethods.Unspecialize(mb.BoundMember.DeclaringType) != this.containingType) goto JustVisit2; MembersToDuplicate.Add(mb.BoundMember); JustVisit2: ; End: base.VisitAssignmentStatement(assignment); }
public override Statement VisitAssignmentStatement(AssignmentStatement assignment) { Statement result = base.VisitAssignmentStatement(assignment); return result; }
/// <summary> /// Verifies that assignment statements are pure. /// </summary> /// <param name="assignment">Assignment to inspect.</param> /// <returns><paramref name="assignment"/></returns> public override void VisitAssignmentStatement(AssignmentStatement assignment) { // F: Should it be a Precondition? Contract.Assume(assignment != null); // Skip compiler-generated code. // Since we only visit contract regions, any assignment to state is not allowed. bool targetIsLocal = false; if (assignment.Target is Local) targetIsLocal = true; Indexer idxr = assignment.Target as Indexer; // Roslyn compiler introduced new pattern: in the expression tree there is an assignment // from local variable that holds expression to the array. But unlike old compiler // Roslyn is not introducing local variable for holding an array. // Instead of that it uses "dup" instruction and assignes parameter expression // directly to the stack slot. // This change should be addressed here, because otherwise ccrewrite will fail // with an error. if (idxr != null && (idxr.Object is Local || ExpressionTreeInitialization(assignment))) targetIsLocal = true; // Assignments to locals that are structs show up as address deference AddressDereference addressDereference = assignment.Target as AddressDereference; if (addressDereference != null) { UnaryExpression ue = addressDereference.Address as UnaryExpression; if (ue != null) { // F: no idea why this is != null Contract.Assume(assignment.Target.Type != null); if (ue.Operand is Local && (assignment.Target.Type.IsPrimitive || assignment.Target.Type.IsStructural || assignment.Target.Type.IsTypeArgument || assignment.Target.Type is Struct || assignment.Target.Type is EnumNode)) { targetIsLocal = true; } } } if (!IsAnonymousDelegateConstruction(assignment) && !targetIsLocal) { this.assignmentFound = true; //this.errorHandler(new Error("Detected assignment in a pure region in method '" // + this.currentMethod.FullName + "'.", assignment.SourceContext)); } base.VisitAssignmentStatement(assignment); }
/// <summary> /// Verifies that assignment statements are pure. /// </summary> /// <param name="assignment">Assignment to inspect.</param> /// <returns><paramref name="assignment"/></returns> public override void VisitAssignmentStatement(AssignmentStatement assignment) { // F: Should it be a Precondition? Contract.Assume(assignment != null); // Skip compiler-generated code. // Since we only visit contract regions, any assignment to state is not allowed. bool targetIsLocal = false; if (assignment.Target is Local) targetIsLocal = true; Indexer idxr = assignment.Target as Indexer; if (idxr != null && idxr.Object is Local) targetIsLocal = true; // Assignments to locals that are structs show up as address deference AddressDereference addressDereference = assignment.Target as AddressDereference; if (addressDereference != null) { UnaryExpression ue = addressDereference.Address as UnaryExpression; if (ue != null) { // F: no idea why this is != null Contract.Assume(assignment.Target.Type != null); if (ue.Operand is Local && (assignment.Target.Type.IsPrimitive || assignment.Target.Type is Struct || assignment.Target.Type.IsStructural)) { targetIsLocal = true; } } } if (!IsAnonymousDelegateConstruction(assignment) && !targetIsLocal) { this.assignmentFound = true; //this.errorHandler(new Error("Detected assignment in a pure region in method '" // + this.currentMethod.FullName + "'.", assignment.SourceContext)); } base.VisitAssignmentStatement(assignment); }
public EventingVisitor(Action<AssignmentStatement> visitAssignmentStatement) { VisitedAssignmentStatement += visitAssignmentStatement; } public event Action<AssignmentStatement> VisitedAssignmentStatement; public override Statement VisitAssignmentStatement(AssignmentStatement assignment) { if (VisitedAssignmentStatement != null) VisitedAssignmentStatement(assignment); return base.VisitAssignmentStatement(assignment); }