public override ICatchClause Rewrite(ICatchClause catchClause) { _log.Info("Rewriting ITryCatchFinallyStatement: " + catchClause + " Pass: "******".ctor")); expression = new CreateObjectInstance() { MethodToCall = ctor, Type = catchClause.ExceptionContainer.Type }; } return new CatchClause(catchClause) { Body = new BlockStatement() { Statements = new ThrowStatement() { Exception = expression }.InList<IStatement>() } }; }
public override IExpression Rewrite(IThisReference thisReference) { var boundExpression = new BoundExpression(); boundExpression.Instance = thisReference; boundExpression.Definition = iteratorClosure.ThisFieldReference; boundExpression.Type = iteratorClosure.ThisFieldReference.Type; return boundExpression; }
public override void BuildMethod() { AddStatement.DeclareInterceptedType(field.ContainingType.ResolvedType); Context.Log.WriteTrace(" Adding: var interceptedField = interceptedType.GetField('{0}');", field.Name.Value); Context.Block.Statements.Add( Declare.Variable<FieldInfo>("interceptedField").As( Call.VirtualMethod("GetField", typeof (string)).ThatReturns<FieldInfo>().WithArguments( Constant.Of(field.Name.Value)).On("interceptedType")) ); AddStatement.DeclareArgumentsList(); var funcT = SharpMockTypes.Functions[0]; var funcActualT = new GenericTypeInstanceReference(); funcActualT.GenericType = funcT; funcActualT.GenericArguments.Add(field.Type); var accessor = new AnonymousDelegate(); accessor.Type = funcActualT; accessor.ReturnType = field.Type; accessor.CallingConvention = CallingConvention.HasThis; var accessorBody = new BlockStatement(); var returnActualField = new ReturnStatement(); var actualField = new BoundExpression(); actualField.Type = field.Type; actualField.Definition = field; returnActualField.Expression = actualField; accessorBody.Statements.Add(returnActualField); accessor.Body = accessorBody; Context.Block.Statements.Add( Declare.Variable("local_0", funcActualT).As(accessor) ); AddStatement.DeclareRegistryInterceptor(); AddStatement.DeclareInvocation(); AddStatement.SetArgumentsOnInvocation(); AddStatement.SetOriginalCallOnInvocation(); AddStatement.SetTargetOnInvocationToNull(); Context.Block.Statements.Add( Do(Call.PropertySetter<MemberInfo>("OriginalCallInfo").WithArguments("interceptedField").On("invocation")) ); AddStatement.CallShouldInterceptOnInterceptor(); AddStatement.CallInterceptOnInterceptor(); Context.Block.Statements.Add( Declare.Variable("interceptionResult", field.Type).As( ChangeType.Convert(Call.PropertyGetter<object>("Return").On("invocation")).To(field.Type)) ); Context.Block.Statements.Add(Return.Variable(Locals["interceptionResult"])); }
public override void RewriteChildren(BoundExpression boundExpression) { BoundField/*?*/ boundField; if (this.fieldForCapturedLocalOrParameter.TryGetValue(boundExpression.Definition, out boundField)) { boundExpression.Instance = new ThisReference(); boundExpression.Definition = iteratorClosure.GetReferenceOfFieldUsedByPeers(boundField.Field); boundExpression.Type = boundField.Type; return; } base.RewriteChildren(boundExpression); }
public override IExpression Visit(BoundExpression boundExpression) { var fieldReference = boundExpression.Definition as IFieldReference; if (fieldReference != null) { if (this.cachedDelegateFieldsOrLocals.ContainsKey(fieldReference.Name.Value)) return this.cachedDelegateFieldsOrLocals[fieldReference.Name.Value]; else return boundExpression; } var localDefinition = boundExpression.Definition as ILocalDefinition; if (localDefinition != null) { if (this.cachedDelegateFieldsOrLocals.ContainsKey(localDefinition.Name.Value)) return this.cachedDelegateFieldsOrLocals[localDefinition.Name.Value]; else return boundExpression; } return base.Visit(boundExpression); }
public override IExpression Visit(BoundExpression boundExpression) { ILocalDefinition/*?*/ local = boundExpression.Definition as ILocalDefinition; if (local != null) { IExpression substitute = boundExpression; if (this.expressionToSubstituteForCompilerGeneratedSingleAssignmentLocal.TryGetValue(local, out substitute)) { this.sourceMethodBody.numberOfReferences[local]--; return substitute; } } IFieldReference/*?*/ closureField = boundExpression.Definition as IFieldReference; if (closureField != null) { var unspecializedClosureField = UnspecializedMethods.UnspecializedFieldReference(closureField); IBoundExpression/*?*/ binding = null; if (this.capturedBinding.TryGetValue(unspecializedClosureField.InternedKey, out binding)) { IThisReference thisReference = binding.Instance as IThisReference; if (thisReference != null && binding.Definition is Dummy) return thisReference; boundExpression.Definition = binding.Definition; boundExpression.Instance = binding.Instance; return boundExpression; } } IParameterDefinition/*?*/ parameter = boundExpression.Definition as IParameterDefinition; if (parameter != null) { IParameterDefinition parToSubstitute; if (this.parameterMap.TryGetValue(parameter, out parToSubstitute)) { boundExpression.Definition = parToSubstitute; return boundExpression; } } return base.Visit(boundExpression); }
public override IExpression Rewrite(IDupValue dupValue) { var depth = this.locals.Count; var t = dupValue.Type; Contract.Assume(0 < this.locals.Count); var local = this.locals.Peek(); this.locals.Push(local); var be = new BoundExpression() { Definition = local, Instance = null, Type = t, }; return be; }
public override void BuildMethod() { AddStatement.DeclareInterceptedType(field.ContainingType.ResolvedType); Context.Log.WriteTrace(" Adding: var interceptedField = interceptedType.GetField('{0}');", field.Name.Value); Context.Block.Statements.Add( Declare.Variable<FieldInfo>("interceptedField").As( Call.VirtualMethod("GetField", typeof (string)).ThatReturns<FieldInfo>().WithArguments( Constant.Of(field.Name.Value)).On("interceptedType")) ); AddStatement.DeclareArgumentsList(); AddStatement.AddArgumentToList(Params["assignedValue"]); var actionT = SharpMockTypes.Actions[1]; var actionActualT = new GenericTypeInstanceReference(); actionActualT.GenericType = actionT; actionActualT.GenericArguments.Add(field.Type); var assignment = new AnonymousDelegate(); assignment.Type = actionActualT; assignment.ReturnType = Context.Host.PlatformType.SystemVoid; assignment.CallingConvention = CallingConvention.HasThis; var parameterDefinition = new ParameterDefinition(); parameterDefinition.Index = 0; parameterDefinition.Type = field.Type; parameterDefinition.Name = Context.Host.NameTable.GetNameFor("alteredValue"); parameterDefinition.ContainingSignature = assignment; assignment.Parameters.Add(parameterDefinition); var assignmentBody = new BlockStatement(); var assignActualField = new ExpressionStatement(); var actualField = new TargetExpression(); actualField.Type = field.Type; actualField.Definition = field; var value = new BoundExpression(); value.Type = field.Type; value.Definition = parameterDefinition; var assignValueToField = new Assignment(); assignValueToField.Source = value; assignValueToField.Target = actualField; assignValueToField.Type = field.Type; assignActualField.Expression = assignValueToField; actualField.Type = field.Type; actualField.Definition = field; assignmentBody.Statements.Add(assignActualField); assignmentBody.Statements.Add(new ReturnStatement()); assignment.Body = assignmentBody; Context.Block.Statements.Add( Declare.Variable("local_0", actionActualT).As(assignment) ); AddStatement.DeclareRegistryInterceptor(); AddStatement.DeclareInvocation(); AddStatement.SetArgumentsOnInvocation(); AddStatement.SetOriginalCallOnInvocation(); AddStatement.SetTargetOnInvocationToNull(); Context.Block.Statements.Add( Do(Call.PropertySetter<MemberInfo>("OriginalCallInfo").WithArguments("interceptedField").On("invocation")) ); AddStatement.CallShouldInterceptOnInterceptor(); AddStatement.CallInterceptOnInterceptor(); Context.Block.Statements.Add(Return.Void()); }
/// <summary> /// Visits the specified bound expression. /// </summary> /// <param name="boundExpression">The bound expression.</param> /// <returns></returns> protected virtual IExpression DeepCopy(BoundExpression boundExpression) { if (boundExpression.Instance != null) boundExpression.Instance = Substitute(boundExpression.Instance); ILocalDefinition/*?*/ loc = boundExpression.Definition as ILocalDefinition; if (loc != null) boundExpression.Definition = this.GetMutableCopyIfItExists(loc); else { IParameterDefinition/*?*/ par = boundExpression.Definition as IParameterDefinition; if (par != null) boundExpression.Definition = this.GetMutableCopyIfItExists(par); else { IFieldReference/*?*/ field = boundExpression.Definition as IFieldReference; boundExpression.Definition = this.Substitute(field); } } boundExpression.Type = this.Substitute(boundExpression.Type); return boundExpression; }
public override IExpression Rewrite(IPopValue popValue) { var t = popValue.Type; Contract.Assume(0 < this.locals.Count); var local = this.locals.Pop(); if (this.inThenBranch) { var depth = this.locals.Count; if (this.thenBranchPushes != null && this.thenBranchPushes.ContainsKey(depth) && local == this.thenBranchPushes[depth].Target.Definition) this.thenBranchPushes.Remove(depth); } var be = new BoundExpression() { Definition = local, Instance = null, Type = local.Type, }; return be; }
/// <summary> /// Visits the specified bound expression. /// </summary> /// <param name="boundExpression">The bound expression.</param> public override void Visit(IBoundExpression boundExpression) { BoundExpression mutableBoundExpression = boundExpression as BoundExpression; if (alwaysMakeACopy || mutableBoundExpression == null) mutableBoundExpression = new BoundExpression(boundExpression); this.resultExpression = this.myCodeMutator.Visit(mutableBoundExpression); }
/// <summary> /// Visits the specified bound expression. /// </summary> /// <param name="boundExpression">The bound expression.</param> public override void Visit(IBoundExpression boundExpression) { BoundExpression mutableBoundExpression = new BoundExpression(boundExpression); this.resultExpression = this.myCodeCopier.DeepCopy(mutableBoundExpression); }
/// <summary> /// Returns an expression that results in a closure object instance that contains the given field. /// If the expression will be evaluated in the body of this.method, the result is a bound expression /// that references the local that contains the object. Otherwise it is the "this" argument of the /// anonymous delegate method, possibly with a number of field accesses to chase down the outer closure chain. /// </summary> /// <param name="closureField">A reference to a field from the "self instance" of a closure class.</param> private IExpression GetClosureObjectInstanceContaining(IFieldReference closureField) { if (this.isInsideAnonymousMethod) { IExpression result = new ThisReference() { Type = this.currentClosureSelfInstance }; while (result.Type != closureField.ContainingType) { var outerClosureField = this.fieldReferencesForUseInsideAnonymousMethods[result.Type]; result = new BoundExpression() { Instance = result, Definition = outerClosureField, Type = outerClosureField.Type }; } return result; } else { foreach (var instance in this.closureLocalInstances) { if (instance.Type == closureField.ContainingType) return instance; } return this.currentClosureObject; } }
/// <summary> /// Rewrites the children of the given bound expression. /// </summary> public override void RewriteChildren(BoundExpression boundExpression) { IFieldReference closureField; var map = this.isInsideAnonymousMethod ? this.fieldReferencesForUseInsideAnonymousMethods : this.fieldReferencesForUseInsideThisMethod; if (map.TryGetValue(boundExpression.Definition, out closureField)) { boundExpression.Instance = this.GetClosureObjectInstanceContaining(closureField); boundExpression.Definition = closureField; boundExpression.Type = closureField.Type; return; } base.RewriteChildren(boundExpression); }
/// <summary> /// Rewrites the children of the given bound expression. /// </summary> public virtual void RewriteChildren(BoundExpression boundExpression) { this.RewriteChildren((Expression)boundExpression); if (boundExpression.Instance != null) boundExpression.Instance = this.Rewrite(boundExpression.Instance); var local = boundExpression.Definition as ILocalDefinition; if (local != null) boundExpression.Definition = this.RewriteReference(local); else { var parameter = boundExpression.Definition as IParameterDefinition; if (parameter != null) boundExpression.Definition = this.RewriteReference(parameter); else { var fieldReference = (IFieldReference)boundExpression.Definition; boundExpression.Definition = this.Rewrite(fieldReference); } } }
/// <summary> /// If the <paramref name="boundExpression"/> represents a parameter of the target method, /// it is replaced with the equivalent parameter of the source method. /// </summary> /// <param name="boundExpression">The bound expression.</param> public override void RewriteChildren(BoundExpression boundExpression) { var/*?*/ par = boundExpression.Definition as IParameterDefinition; if (par != null && par.ContainingSignature == this.targetMethod) { boundExpression.Definition = this.parameters[par.Index]; if (boundExpression.Instance != null) { boundExpression.Instance = this.Rewrite(boundExpression.Instance); } boundExpression.Type = this.Rewrite(boundExpression.Type); return; } else { base.RewriteChildren(boundExpression); } }
/// <summary> /// Appends the statements afters the calls used to calculate the max of the tmp of all the calls /// </summary> protected void AppendStatementsTmpCopy(IMethodDefinition method, List<StatementTmpCopyInformation> statementsTmpCopy, Dictionary<IStatement, IBlockStatement> statementsContainingBlocks, Dictionary<string, GlobalPolyInfo> globalPolyInfoTmp) { var block = ((BasicBlock)((Microsoft.Cci.ILToCodeModel.SourceMethodBody)method.Body).Block); var methodStatements = block.Statements; var int32Type = _host.PlatformType.SystemInt32; var callNumber = 1; var localsInsertedByType = new Dictionary<ITypeReference, List<LocalDeclarationStatement>>(); foreach (var statementCopyInformation in statementsTmpCopy) { var stmt = statementCopyInformation.AfterStatement; var statements = ((BlockStatement)statementsContainingBlocks[stmt]).Statements; var index = statements.IndexOf(stmt); if (index >= 0) { IExpression initialValue = new BoundExpression() { Type = int32Type, Definition = GetTmpField(statementCopyInformation.CalledMethod, statementCopyInformation.TmpType) }; var localDecl = new LocalDeclarationStatement() { InitialValue = initialValue, LocalVariable = new LocalDefinition() { Type = int32Type, Name = _host.NameTable.GetNameFor("tmp_call_" + callNumber) } }; callNumber++; var tmpType = statementCopyInformation.TmpType; if (!localsInsertedByType.ContainsKey(tmpType)) { localsInsertedByType.Add(tmpType, new List<LocalDeclarationStatement>()); } localsInsertedByType[tmpType].Add(localDecl); if (!statementCopyInformation.InsideLoop) { statements.Insert(index + 1, localDecl); var calledMethodName = statementCopyInformation.CalledMethodReference.ToString(); var contractLocalExpr = TranslateMethodContractToLocalExpression( statementCopyInformation.CalledMethodReference, stmt, _memoryContractsInformation.MethodsTmpContracts[calledMethodName][statementCopyInformation.TmpType], statementCopyInformation.CalledMethodArguments); if (!_currentInstrInfo.GlobalPolyInfoTmp.ContainsKey(tmpType.ToString())) { _currentInstrInfo.GlobalPolyInfoTmp.Add(tmpType.ToString(), new GlobalPolyInfo()); } _currentInstrInfo.GlobalPolyInfoTmp[tmpType.ToString()].MaxCalls.Add(contractLocalExpr); } else { localDecl.InitialValue = new CompileTimeConstant() { Type = int32Type, Value = 0 }; var loopContainingStatements = ((BasicBlock)statementsContainingBlocks[statementCopyInformation.LoopStartAt]).Statements; loopContainingStatements.Insert(0, localDecl); bool doRegularInstrumentation = true; if (!_currentInstrInfo.GlobalPolyInfoTmp.ContainsKey(tmpType.ToString())) { _currentInstrInfo.GlobalPolyInfoTmp.Add(tmpType.ToString(), new GlobalPolyInfo()); } if (statementCopyInformation.LoopInvariants != null) { //invariants available, calculate the max directly and insert the assignment after the loop var calledMethodName = statementCopyInformation.CalledMethodReference.ToString(); if (_memoryContractsInformation.MethodsTmpContracts.ContainsKey(calledMethodName) && _memoryContractsInformation.MethodsTmpContracts[calledMethodName].ContainsKey(statementCopyInformation.TmpType)) { var contractLocalExpr = TranslateMethodContractToLocalExpression( statementCopyInformation.CalledMethodReference, stmt, _memoryContractsInformation.MethodsTmpContracts[calledMethodName][statementCopyInformation.TmpType], statementCopyInformation.CalledMethodArguments); var maxExprPolyCond = PolytopesCalculator.MaxOver(contractLocalExpr, statementCopyInformation.LoopInvariants, GetMethodFreeVars(_currentMethod)); IExpression maxPolyExpr = null; IExpression maxCondExpr = null; if (maxExprPolyCond != null) { maxPolyExpr = ExpressionGenerator.GenerateExpressionFromString(maxExprPolyCond.Poly, _host, _currentMethod); maxCondExpr = ExpressionGenerator.GenerateExpressionFromString(maxExprPolyCond.Cond, _host, _currentMethod); } index = loopContainingStatements.IndexOf(statementCopyInformation.LoopEndAt); if (index >= 0 && maxPolyExpr != null && maxCondExpr != null) { doRegularInstrumentation = false; loopContainingStatements.Insert(index + 1, new ConditionalStatement() { Condition = maxCondExpr, TrueBranch = new ExpressionStatement() { Expression = new Assignment() { Type = int32Type, Source = maxPolyExpr, Target = new TargetExpression() { Type = int32Type, Definition = localDecl.LocalVariable } } }, FalseBranch = new EmptyStatement() }); //store in the global poly info _currentInstrInfo.GlobalPolyInfoTmp[tmpType.ToString()].MaxCallsLoops.Add(maxExprPolyCond); } } } if (doRegularInstrumentation) { //no invariants available or could not calculate max, calculate instrumenting Math.Max calls if (statementCopyInformation.InsideLoop) { _currentInstrInfo.GlobalPolyInfoTmp[tmpType.ToString()].AllContractsRequiredAvailable = false; } index = statements.IndexOf(stmt); //adjust the index, it could have changed because of the previous localDecl insertion statements.Insert(index + 1, new ExpressionStatement() { Expression = new Assignment() { Type = int32Type, Source = BuildMaxCall(new BoundExpression() { Definition = localDecl.LocalVariable, Type = int32Type }, initialValue), Target = new TargetExpression() { Type = int32Type, Definition = localDecl.LocalVariable } } }); } } } } var appendToStatementList = ((BasicBlock)statementsContainingBlocks[_currentStatement]).Statements; foreach (var tmpType in localsInsertedByType.Keys) { bool doRegularInstrumentation = true; var tmpField = GetTmpField(method, tmpType); var globalInfoForTmp = globalPolyInfoTmp[tmpType.ToString()]; //check if we can calculate the max with the polytopes calculator if (globalInfoForTmp.AllContractsRequiredAvailable) { var polys = new List<string>(); var conds = new List<string>(); conds.AddRange(GetMethodRequiresExprs(method)); polys.AddRange(globalInfoForTmp.MaxCalls); foreach (var poly in globalInfoForTmp.MaxCallsLoops) { polys.Add(poly.Poly); conds.Add(poly.Cond); } var max = PolytopesCalculator.MaxPoly(polys, conds, GetMethodFreeVars(method)); if (max != null) { var condExpr = ExpressionGenerator.GenerateExpressionFromString(max.Cond, _host, method); var maxExpr = ExpressionGenerator.GenerateExpressionFromString(max.Poly, _host, method); if (condExpr != null && maxExpr != null) { InsertStatementAtBottom(appendToStatementList, new ConditionalStatement() { Condition = condExpr, TrueBranch = new ExpressionStatement() { Expression = new Assignment() { Type = int32Type, Source = new Addition() { Type = int32Type, LeftOperand = new BoundExpression() { Type = int32Type, Definition = tmpField }, RightOperand = maxExpr }, Target = new TargetExpression() { Type = int32Type, Definition = tmpField } } }, FalseBranch = new EmptyStatement() }); doRegularInstrumentation = false; } } } if (doRegularInstrumentation) { var maxExpr = GetMaxExpressionOverLocals(localsInsertedByType[tmpType]); //add the statement tmpField += Math.Max(...); InsertStatementAtBottom(appendToStatementList, new ExpressionStatement() { Expression = new Assignment() { Type = int32Type, Source = new Addition() { Type = int32Type, LeftOperand = new BoundExpression() { Type = int32Type, Definition = tmpField }, RightOperand = maxExpr }, Target = new TargetExpression() { Type = int32Type, Definition = tmpField } } }); } } }
/// <summary> /// Create the body of the generic version of GetEnumerator for the iterator closure class. /// /// The body's pseudo code. /// { /// if (Thread.CurrentThread.ManagedThreadId == this.l_initialThreadId AND this.state == -2) { /// this.state = 0; /// return this; /// } /// else { /// return a new copy of the iterator instance with state being zero. /// } /// } /// </summary> private BlockStatement GetBodyOfGenericGetEnumerator(IteratorClosureInformation iteratorClosure) { var thisDotState = new BoundExpression() { Definition = iteratorClosure.StateFieldReference, Instance = new ThisReference(), Type = this.host.PlatformType.SystemInt32 }; var thisDotThreadId = new BoundExpression() { Definition = iteratorClosure.InitThreadIdFieldReference, Instance = new ThisReference(), Type = this.host.PlatformType.SystemInt32 }; var currentThreadId = new MethodCall() { MethodToCall = ThreadDotManagedThreadId.Getter, ThisArgument = ThreadDotCurrentThread, Type = this.host.PlatformType.SystemInt32 }; var stateEqMinus2 = new Equality() { LeftOperand = thisDotState, RightOperand = new CompileTimeConstant() { Type = this.host.PlatformType.SystemInt32, Value = -2 }, Type = this.host.PlatformType.SystemBoolean }; var threadIdEqCurrentThreadId = new Equality { LeftOperand = thisDotThreadId, RightOperand = currentThreadId, Type = this.host.PlatformType.SystemBoolean }; var thisDotStateEq0 = new ExpressionStatement() { Expression = new Assignment() { Source = new CompileTimeConstant() { Type = this.host.PlatformType.SystemInt32, Value = 0 }, Target = new TargetExpression() { Definition = iteratorClosure.StateFieldReference, Instance = new ThisReference(), Type = this.host.PlatformType.SystemInt32 }, Type = this.host.PlatformType.SystemInt32 }, }; var returnThis = new BlockStatement(); returnThis.Statements.Add(thisDotStateEq0); returnThis.Statements.Add(new ReturnStatement() { Expression = new ThisReference() }); var returnNew = new BlockStatement(); var args = new List<IExpression>(); args.Add(new CompileTimeConstant() { Value = 0, Type = this.host.PlatformType.SystemInt32 }); var closureInstanceLocalDecl = new LocalDeclarationStatement() { LocalVariable = new LocalDefinition() { Name = this.host.NameTable.GetNameFor("local0"), Type = iteratorClosure.ClosureDefinitionReference }, InitialValue = new CreateObjectInstance() { MethodToCall = iteratorClosure.ConstructorReference, Arguments = args, Type = iteratorClosure.ClosureDefinitionReference } }; var returnNewClosureInstance = new ReturnStatement() { Expression = new BoundExpression() { Instance = null, Type = iteratorClosure.ClosureDefinitionReference, Definition = closureInstanceLocalDecl.LocalVariable } }; returnNew.Statements.Add(closureInstanceLocalDecl); if (!method.IsStatic) { ExpressionStatement assignThisDotThisToNewClosureDotThis = new ExpressionStatement() { Expression = new Assignment() { Source = new BoundExpression() { Definition = iteratorClosure.ThisFieldReference, Instance = new ThisReference(), Type = iteratorClosure.ClosureDefinitionReference }, Type = iteratorClosure.ClosureDefinition, Target = new TargetExpression() { Instance = new BoundExpression() { Instance = null, Definition = closureInstanceLocalDecl.LocalVariable, Type = iteratorClosure.ClosureDefinitionReference }, Definition = iteratorClosure.ThisFieldReference, Type = iteratorClosure.ClosureDefinitionReference } } }; returnNew.Statements.Add(assignThisDotThisToNewClosureDotThis); } returnNew.Statements.Add(returnNewClosureInstance); ConditionalStatement returnThisOrNew = new ConditionalStatement() { Condition = new Conditional() { Condition = stateEqMinus2, ResultIfTrue = threadIdEqCurrentThreadId, ResultIfFalse = new CompileTimeConstant() { Type = this.host.PlatformType.SystemBoolean, Value = false }, Type = this.host.PlatformType.SystemBoolean }, TrueBranch = returnThis, FalseBranch = returnNew }; BlockStatement block = new BlockStatement(); block.Statements.Add(returnThisOrNew); return block; }
/// <summary> /// Create two properties: object Current and T Current as the closure class implements both the /// generic and non-generic version of ienumerator. /// /// Current Implementation generates getters, but not the property. /// </summary> /// <param name="iteratorClosure">Information about the closure created when compiling the current iterator method</param> private void CreateIteratorClosureProperties(IteratorClosureInformation iteratorClosure) { // Non-generic version of the get_Current, which returns the generic version of get_Current. MethodDefinition getterNonGenericCurrent = new MethodDefinition() { Attributes = new List<ICustomAttribute>(1), InternFactory = this.host.InternFactory, Name = this.host.NameTable.GetNameFor("System.Collections.IEnumerator.get_Current") }; CustomAttribute debuggerHiddenAttribute = new CustomAttribute(); debuggerHiddenAttribute.Constructor = this.DebuggerHiddenCtor; getterNonGenericCurrent.Attributes.Add(debuggerHiddenAttribute); getterNonGenericCurrent.CallingConvention |= CallingConvention.HasThis; getterNonGenericCurrent.Visibility |= TypeMemberVisibility.Public; getterNonGenericCurrent.ContainingTypeDefinition = iteratorClosure.ClosureDefinition; getterNonGenericCurrent.Type = this.host.PlatformType.SystemObject; getterNonGenericCurrent.IsSpecialName = true; getterNonGenericCurrent.IsVirtual = true; getterNonGenericCurrent.IsNewSlot = true; getterNonGenericCurrent.IsHiddenBySignature = true; getterNonGenericCurrent.IsSealed = true; iteratorClosure.NonGenericGetCurrent = getterNonGenericCurrent; IMethodReference originalMethod = Dummy.MethodReference; foreach (ITypeMemberReference tref in iteratorClosure.NonGenericIEnumeratorInterface.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("get_Current"), false)) { originalMethod = tref as IMethodReference; if (originalMethod != null) break; } // assert originalMethod != Dummy MethodImplementation getterImplementation = new MethodImplementation() { ContainingType = iteratorClosure.ClosureDefinition, ImplementingMethod = getterNonGenericCurrent, ImplementedMethod = originalMethod }; iteratorClosure.ClosureDefinition.ExplicitImplementationOverrides.Add(getterImplementation); List<IStatement> statements = new List<IStatement>(); IFieldReference currentField = iteratorClosure.CurrentFieldReference; BoundExpression thisDotCurr = new BoundExpression() { Definition = currentField, Instance = new ThisReference(), Locations = iteratorClosure.ClosureDefinition.Locations, Type = currentField.Type }; IExpression returnExpression; if (!iteratorClosure.ElementType.IsValueType && TypeHelper.TypesAreAssignmentCompatible(iteratorClosure.ElementType.ResolvedType, this.host.PlatformType.SystemObject.ResolvedType)) { returnExpression = thisDotCurr; } else { Conversion convertion = new Conversion() { CheckNumericRange = false, Type = this.host.PlatformType.SystemObject, TypeAfterConversion = getterNonGenericCurrent.Type, ValueToConvert = thisDotCurr }; returnExpression = convertion; } ReturnStatement returnCurrent = new ReturnStatement() { Expression = returnExpression, Locations = iteratorClosure.ClosureDefinition.Locations }; statements.Add(returnCurrent); BlockStatement block = new BlockStatement() { Statements = statements }; SourceMethodBody body = new SourceMethodBody(this.host, this.sourceLocationProvider); body.IsNormalized = true; body.LocalsAreZeroed = true; body.Block = block; body.MethodDefinition = getterNonGenericCurrent; getterNonGenericCurrent.Body = body; // Create generic version of get_Current, the body of which is simply returning this.current. MethodDefinition getterGenericCurrent = new MethodDefinition() { Attributes = new List<ICustomAttribute>(1), InternFactory = this.host.InternFactory, Name = this.host.NameTable.GetNameFor("System.Collections.Generic.IEnumerator<" + iteratorClosure.ElementType.ToString() +">.get_Current") }; getterGenericCurrent.Attributes.Add(debuggerHiddenAttribute); getterGenericCurrent.CallingConvention |= CallingConvention.HasThis; getterGenericCurrent.Visibility |= TypeMemberVisibility.Public; getterGenericCurrent.ContainingTypeDefinition = iteratorClosure.ClosureDefinition; getterGenericCurrent.Type = iteratorClosure.ElementType; getterGenericCurrent.IsSpecialName = true; getterGenericCurrent.IsVirtual = true; getterGenericCurrent.IsNewSlot = true; getterGenericCurrent.IsHiddenBySignature = true; getterGenericCurrent.IsSealed = true; iteratorClosure.GenericGetCurrent = getterGenericCurrent; originalMethod = Dummy.MethodReference; foreach (ITypeMemberReference tref in iteratorClosure.GenericIEnumeratorInterface.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("get_Current"), false)) { originalMethod = tref as IMethodReference; if (originalMethod != null) break; } MethodImplementation getterImplementation2 = new MethodImplementation() { ContainingType = iteratorClosure.ClosureDefinition, ImplementingMethod = getterGenericCurrent, ImplementedMethod = originalMethod }; iteratorClosure.ClosureDefinition.ExplicitImplementationOverrides.Add(getterImplementation2); statements = new List<IStatement>(); currentField = iteratorClosure.CurrentFieldReference; BoundExpression thisDotCurrent = new BoundExpression() { Definition = currentField, Instance = new ThisReference(), Locations = iteratorClosure.ClosureDefinition.Locations, Type = currentField.Type }; returnCurrent = new ReturnStatement() { Expression = thisDotCurrent, Locations = iteratorClosure.ClosureDefinition.Locations }; statements.Add(returnCurrent); block = new BlockStatement() { Statements = statements }; body = new SourceMethodBody(this.host, this.sourceLocationProvider); body.LocalsAreZeroed = true; body.Block = block; body.MethodDefinition = getterGenericCurrent; getterGenericCurrent.Body = body; }
private Expression ParseBoundExpression(Instruction instruction) { Contract.Requires(instruction != null); IOperation currentOperation = instruction.Operation; if (currentOperation.Value == null) return new ThisReference(); BoundExpression result = new BoundExpression(); result.Alignment = this.alignment; result.Definition = currentOperation.Value; result.IsVolatile = this.sawVolatile; switch (currentOperation.OperationCode) { case OperationCode.Ldarg: case OperationCode.Ldarg_0: case OperationCode.Ldarg_1: case OperationCode.Ldarg_2: case OperationCode.Ldarg_3: case OperationCode.Ldarg_S: var par = result.Definition as IParameterDefinition; Contract.Assume(par != null); result.Type = par.IsByReference ? new ManagedPointerTypeReference() { TargetType = par.Type, InternFactory = this.host.InternFactory } : par.Type; break; case OperationCode.Ldsfld: var field = result.Definition as IFieldReference; Contract.Assume(field != null); result.Type = field.Type; break; case OperationCode.Ldfld: result.Instance = this.PopOperandStack(); goto case OperationCode.Ldsfld; case OperationCode.Ldloc: case OperationCode.Ldloc_0: case OperationCode.Ldloc_1: case OperationCode.Ldloc_2: case OperationCode.Ldloc_3: case OperationCode.Ldloc_S: if (this.instructionsThatMakeALastUseOfALocalVersion.Contains(instruction)) { this.instructionsThatMakeALastUseOfALocalVersion.Remove(instruction); this.bindingsThatMakeALastUseOfALocalVersion.Add(result); } Contract.Assume(result.Definition is ILocalDefinition); var locDef = (ILocalDefinition)result.Definition; var local = result.Definition = this.GetLocalWithSourceName(locDef); this.numberOfReferencesToLocal[local] = this.numberOfReferencesToLocal.ContainsKey(local) ? this.numberOfReferencesToLocal[local] + 1 : 1; result.Type = locDef.IsReference ? new ManagedPointerTypeReference() { TargetType = locDef.Type, InternFactory = this.host.InternFactory } : locDef.Type; break; } this.alignment = 0; this.sawVolatile = false; return result; }
public static IExpression GenerateExpressionFromString(string strExpr, IMetadataHost host, IMethodDefinition method) { strExpr = Normalize(strExpr); string rpn = GetRPN(strExpr); Stack<IExpression> stVals = new Stack<IExpression>(); RPNEnumerator rpnEnum = new RPNEnumerator(rpn); var int32Type = host.PlatformType.SystemInt32; var boolType = host.PlatformType.SystemBoolean; while (rpnEnum.MoveNext()) { RPNValue rpnVal = (RPNValue)rpnEnum.Current; if (rpnVal.type == RPNValueType.OPERAND) { if (reNum.IsMatch(rpnVal.val)) { stVals.Push(new CompileTimeConstant() { Type = int32Type, Value = int.Parse(rpnVal.val.Replace(':', '-')) }); } else { IExpression expr = null; var exprParts = rpnVal.val.Split('.'); if (exprParts[0] == "this") { expr = new ThisReference() { Type = method.ContainingType.ResolvedType }; } else { foreach (var arg in method.Parameters) { if (arg.Name.Value == exprParts[0]) { expr = new BoundExpression() { Type = arg.Type.ResolvedType, Definition = arg }; break; } } } if (expr != null && exprParts.Length > 1) { for (int i = 1; i < exprParts.Length; i++) { expr = GetExprWithAccesor(expr, exprParts[i], host); } } if (expr == null || expr.Type.ResolvedType != int32Type.ResolvedType) { return null; } stVals.Push(expr); } } else { var v1 = stVals.Pop(); var v2 = stVals.Pop(); if (rpnVal.val == "+") stVals.Push(new Addition() { Type = int32Type, LeftOperand = v2, RightOperand = v1 }); else if (rpnVal.val == "-") stVals.Push(new Subtraction() { Type = int32Type, LeftOperand = v2, RightOperand = v1 }); else if (rpnVal.val == "*") stVals.Push(new Multiplication() { Type = int32Type, LeftOperand = v2, RightOperand = v1 }); else if (rpnVal.val == "/") stVals.Push(new Division() { Type = int32Type, LeftOperand = v2, RightOperand = v1 }); else if (rpnVal.val == "=") stVals.Push(new Equality() { Type = int32Type, LeftOperand = v2, RightOperand = v1 }); else if (rpnVal.val == "&") stVals.Push(new Conditional() { Type = boolType, Condition = v2, ResultIfTrue = v1, ResultIfFalse = new CompileTimeConstant() { Type = int32Type, Value = 0 } }); else if (rpnVal.val == "|") stVals.Push(new Conditional() { Type = boolType, Condition = v2, ResultIfTrue = new CompileTimeConstant() { Type = int32Type, Value = 1 }, ResultIfFalse = v1 }); else if (rpnVal.val == ">") stVals.Push(new GreaterThan() { Type = boolType, LeftOperand = v2, RightOperand = v1 }); else if (rpnVal.val == "<") stVals.Push(new LessThan() { Type = boolType, LeftOperand = v2, RightOperand = v1 }); else if (rpnVal.val == "%") stVals.Push(new GreaterThanOrEqual() { Type = boolType, LeftOperand = v2, RightOperand = v1 }); else if (rpnVal.val == "#") stVals.Push(new LessThanOrEqual() { Type = boolType, LeftOperand = v2, RightOperand = v1 }); else return null; } } if (stVals.Count > 0) { return stVals.Pop(); } return null; }
/// <summary> /// Rewrites the given anonymous delegate expression. /// </summary> public override IExpression Rewrite(IAnonymousDelegate anonymousDelegate) { if (this.isInsideAnonymousMethod) return base.Rewrite(anonymousDelegate); IMethodReference method = this.CreateClosureMethod((AnonymousDelegate)anonymousDelegate); var createDelegate = new CreateDelegateInstance() { MethodToCallViaDelegate = method, Type = anonymousDelegate.Type }; if (!method.IsStatic) { //TODO: if there is reason to believe the delegate will be constructed in a loop, but its closure is constructed before the loop, then cache the delegate in a local //that is in the same scope as the closure instance if (method.ContainingType == this.currentClosureInstance) createDelegate.Instance = this.currentClosureObject; else //non static peer method createDelegate.Instance = new ThisReference() { Type = NamedTypeDefinition.SelfInstance((INamedTypeDefinition)this.method.ContainingTypeDefinition, this.host.InternFactory) }; } else if ((method.CallingConvention & CallingConvention.Generic) == 0) { //cache the delegate in a static field (we can only do this if method is not generic, i.e. when at most one instance will be created). var cache = this.CreateStaticCacheField(anonymousDelegate.Type); var boundField = new BoundExpression() { Definition = cache, Type = cache.Type }; var statements = new List<IStatement>(1); var conditional = new ConditionalStatement() { Condition = new Equality() { LeftOperand = boundField, RightOperand = new CompileTimeConstant() { Value = null, Type = cache.Type }, Type = this.host.PlatformType.SystemBoolean }, TrueBranch = new ExpressionStatement() { Expression = new Assignment() { Target = new TargetExpression() { Definition = cache, Type = cache.Type }, Source = createDelegate, Type = cache.Type } } }; statements.Add(conditional); return new BlockExpression() { BlockStatement = new BlockStatement() { Statements = statements }, Expression = boundField }; } return createDelegate; }
/// <summary> /// The source expression "new C(){ f1 = e1, f2 = e2, ... }" (where the f's can be fields /// or properties) turns into "cgl = new C(); cgl.f1 = e1; cg1.f2 = e2; ...". /// ("cgl" means "compiler-generated local".) /// Turn it into a block expression whose Statements are the statements above (but where /// the first one becomes a local declaration statement), and with an Expression that is /// just the local, cgl', where cgl' is a freshly created local. /// </summary> private bool ReplaceCompilerGeneratedLocalUsedForInitializersPattern(BlockStatement b) { Contract.Requires(b != null); bool replacedPattern = false; var statements = b.Statements; for (int i = 0; i < statements.Count - 1; i++) { var expressionStatement = statements[i] as ExpressionStatement; if (expressionStatement == null) continue; var assignment = expressionStatement.Expression as Assignment; if (assignment == null) continue; var local = assignment.Target.Definition as ILocalDefinition; if (local == null || local is CapturedLocalDefinition) continue; if (this.numberOfAssignmentsToLocal[local] != 1) continue; if (this.sourceLocationProvider != null) { bool isCompilerGenerated; var sourceName = this.sourceLocationProvider.GetSourceNameFor(local, out isCompilerGenerated); if (!isCompilerGenerated) continue; } var createObject = assignment.Source as ICreateObjectInstance; if (createObject == null) continue; if (!this.singleUseExpressionChecker.ExpressionCanBeMovedAndDoesNotReference(assignment.Source, local)) continue; var j = 1; while (i + j < statements.Count - 1 && IsAssignmentToFieldOrProperty(local, statements[i + j])) j++; if (j == 1) continue; if (this.numberOfReferencesToLocal[local] != (uint)j) continue; Contract.Assume(i + j < statements.Count); //i < statements.Count-1 and (j == 1 or the loop above established i+j < statements.Count-1) Contract.Assume(statements[i + j] != null); if (LocalFinder.LocalOccursIn(statements[i+j], local) && this.singleAssignmentReferenceFinder.LocalCanBeReplacedIn(statements[i + j], local)) { var newLocal = new LocalDefinition() { Name = this.host.NameTable.GetNameFor(local.Name.Value + "_prime"), MethodDefinition = local.MethodDefinition, Type = local.Type, }; var lds = new LocalDeclarationStatement() { InitialValue = assignment.Source, LocalVariable = newLocal, }; var stmts = new List<IStatement>(j) { lds, }; var boundExpression = new BoundExpression() { Definition = newLocal, Instance = null, Type = newLocal.Type, }; foreach (var s in statements.GetRange(i + 1, j - 1)) { Contract.Assume(s != null); this.singleAssignmentLocalReplacer.Replace(boundExpression, local, s); stmts.Add(s); } var blockExpression = new BlockExpression() { BlockStatement = new BlockStatement() { Statements = stmts, }, Expression = new BoundExpression() { Definition = newLocal, Instance = null, Type = newLocal.Type, }, Type = newLocal.Type, }; if (this.singleAssignmentLocalReplacer.Replace(blockExpression, local, statements[i + j])) { this.numberOfAssignmentsToLocal[newLocal] = 1; this.numberOfReferencesToLocal[newLocal] = (uint)j; this.numberOfAssignmentsToLocal[local]--; this.numberOfReferencesToLocal[local] = 0; statements.RemoveRange(i, j); replacedPattern = true; } else Contract.Assume(false); // replacement should succeed since the combination of LocalOccursIn and LocalCanBeReplacedIn returned true } } return replacedPattern; }
private Expression ParseBoundExpression(IOperation currentOperation) { if (currentOperation.Value == null) return new ThisReference(); BoundExpression result = new BoundExpression(); result.Alignment = this.alignment; result.Definition = currentOperation.Value; result.IsVolatile = this.sawVolatile; var parameter = result.Definition as IParameterDefinition; if (parameter != null) { result.Type = parameter.Type; if (parameter.IsByReference) result.Type = Immutable.ManagedPointerType.GetManagedPointerType(result.Type, this.host.InternFactory); } else { var local = result.Definition as ILocalDefinition; if (local != null) { result.Definition = this.GetLocalWithSourceName(local); result.Type = local.Type; if (local.IsReference) result.Type = Immutable.ManagedPointerType.GetManagedPointerType(result.Type, this.host.InternFactory); } else { var field = (IFieldReference)result.Definition; result.Type = field.Type; } } switch (currentOperation.OperationCode) { case OperationCode.Ldfld: result.Instance = this.PopOperandStack(); break; case OperationCode.Ldloc: case OperationCode.Ldloc_0: case OperationCode.Ldloc_1: case OperationCode.Ldloc_2: case OperationCode.Ldloc_3: case OperationCode.Ldloc_S: this.numberOfReferences[result.Definition] = this.numberOfReferences.ContainsKey(result.Definition) ? this.numberOfReferences[result.Definition] + 1 : 1; break; } this.alignment = 0; this.sawVolatile = false; return result; }
/// <summary> /// Visits the specified bound expression. /// </summary> /// <param name="boundExpression">The bound expression.</param> /// <returns></returns> public virtual IExpression Visit(BoundExpression boundExpression) { if (boundExpression.Instance != null) boundExpression.Instance = Visit(boundExpression.Instance); ILocalDefinition/*?*/ loc = boundExpression.Definition as ILocalDefinition; if (loc != null) boundExpression.Definition = this.VisitReferenceTo(loc); else { IParameterDefinition/*?*/ par = boundExpression.Definition as IParameterDefinition; if (par != null) boundExpression.Definition = this.VisitReferenceTo(par); else { IFieldReference/*?*/ field = boundExpression.Definition as IFieldReference; boundExpression.Definition = this.Visit(field); } } boundExpression.Type = this.Visit(boundExpression.Type); return boundExpression; }