public FieldAssignmentReplacementBuilder(FieldReference field, IMetadataHost host, ExpressionStatement assignment, ReplacementRegistry registry) { this.field = field; this.host = host; this.assignment = assignment; this.registry = registry; }
public override void TraverseChildren(IMethodDefinition method) { this.methodTraversed = method; if (method.IsConstructor && PhoneTypeHelper.isPhoneApplicationClass(typeTraversed, host)) { navigationCallers.Add(method); string mainPageUri = PhoneCodeHelper.instance().PhonePlugin.getMainPageXAML(); SourceMethodBody sourceBody = method.Body as SourceMethodBody; if (sourceBody != null) { BlockStatement bodyBlock = sourceBody.Block as BlockStatement; if (bodyBlock != null) { Assignment uriInitAssign = new Assignment() { Source = new CompileTimeConstant() { Type = host.PlatformType.SystemString, Value = UriHelper.getURIBase(mainPageUri), }, Type = host.PlatformType.SystemString, Target = new TargetExpression() { Type = host.PlatformType.SystemString, // TODO unify code for current uri fieldreference Definition = new FieldReference() { ContainingType = PhoneCodeHelper.instance().getMainAppTypeReference(), IsStatic=true, Type=host.PlatformType.SystemString, Name=host.NameTable.GetNameFor(PhoneCodeHelper.IL_CURRENT_NAVIGATION_URI_VARIABLE), InternFactory= host.InternFactory, }, }, }; Statement uriInitStmt= new ExpressionStatement() { Expression= uriInitAssign, }; bodyBlock.Statements.Insert(0, uriInitStmt); } } } base.TraverseChildren(method); }
/// <summary> /// Converts the assume statement into a call to Contract.Assume /// </summary> public override IStatement Rewrite(IAssumeStatement assumeStatement) { var methodCall = new MethodCall() { Arguments = new List<IExpression> { assumeStatement.Condition, }, IsStaticCall = true, MethodToCall = this.contractProvider.ContractMethods.Assume, Type = systemVoid, Locations = new List<ILocation>(assumeStatement.Locations), }; ExpressionStatement es = new ExpressionStatement() { Expression = methodCall }; return es; }
private Statement ParseArraySet(IOperation currentOperation) { ExpressionStatement result = new ExpressionStatement(); Assignment assignment = new Assignment(); result.Expression = assignment; assignment.Source = this.PopOperandStack(); TargetExpression targetExpression = new TargetExpression(); assignment.Target = targetExpression; ArrayIndexer indexer = this.ParseArrayIndexer(currentOperation); targetExpression.Definition = indexer; targetExpression.Instance = indexer.IndexedObject; return result; }
private Statement ParsePop() { ExpressionStatement result = new ExpressionStatement(); result.Expression = this.PopOperandStack(); return result; }
delegate void Action(); //not defined in CLR v2. /// <summary> /// Saves the current closure fields. Allocates a new closure and updates the fields. Then calls the given delegate and /// restores the earlier state. /// </summary> private void AllocateClosureFor(object scope, List<IStatement> statements, Action rewriteScope) { Contract.Assume(!this.isInsideAnonymousMethod); var savedCurrentClosure = this.currentClosureClass; var savedCurrentClosureSelfInstance = this.currentClosureSelfInstance; var savedCurrentClosureInstance = this.currentClosureInstance; var savedCurrentClosureObject = this.currentClosureObject; var savedCurrentClosureLocal = this.currentClosureLocal; this.CreateClosureClass(); IFieldReference outerClosure = null; if (savedCurrentClosureLocal != null) { this.CreateClosureField(this.currentClosureSelfInstance, savedCurrentClosureSelfInstance, savedCurrentClosureInstance, savedCurrentClosureLocal.Name.Value); outerClosure = this.fieldReferencesForUseInsideThisMethod[this.currentClosureSelfInstance]; } var closureLocal = new LocalDefinition() { Type = this.currentClosureInstance, Name = this.host.NameTable.GetNameFor("CS$<>__locals"+this.closureClasses.Count) }; this.currentClosureObject = new BoundExpression() { Definition = closureLocal, Type = this.currentClosureInstance }; this.currentClosureLocal = closureLocal; if (this.closureLocalInstances == null) this.closureLocalInstances = new List<IExpression>(); this.closureLocalInstances.Add(this.currentClosureObject); rewriteScope(); Statement createClosure = new ExpressionStatement() { Expression = new Assignment() { Target = new TargetExpression() { Definition = closureLocal, Type = closureLocal.Type }, Source = new CreateObjectInstance() { MethodToCall = this.GetReferenceToDefaultConstructor(this.currentClosureInstance), Type = currentClosureSelfInstance, } } }; ILabeledStatement labeledStatement = null; for (int i = 0, n = statements.Count; i < n; i++) { labeledStatement = statements[i] as ILabeledStatement; if (labeledStatement != null) { createClosure = new LabeledStatement() { Label = labeledStatement.Label, Statement = createClosure }; createClosure.Locations.AddRange(labeledStatement.Locations); statements[i] = labeledStatement.Statement; break; } else if (statements[i] is IEmptyStatement) { continue; } else { var declSt = statements[i] as ILocalDeclarationStatement; if (declSt != null && declSt.InitialValue == null) continue; break; } } statements.Insert(0, createClosure); if (outerClosure != null) { statements.Insert(1, new ExpressionStatement() { Expression = new Assignment() { Target = new TargetExpression() { Instance = new BoundExpression() { Definition = closureLocal, Type = closureLocal.Type }, Definition = outerClosure, Type = closureLocal.Type }, Source = new BoundExpression() { Definition = savedCurrentClosureLocal, Type = savedCurrentClosureLocal.Type }, Type = closureLocal.Type, } }); } this.currentClosureClass = savedCurrentClosure; this.currentClosureSelfInstance = savedCurrentClosureSelfInstance; this.currentClosureInstance = savedCurrentClosureInstance; this.currentClosureObject = savedCurrentClosureObject; this.currentClosureLocal = savedCurrentClosureLocal; }
private Statement ParseArraySet(IOperation currentOperation) { Contract.Requires(currentOperation != null); ExpressionStatement result = new ExpressionStatement(); Assignment assignment = new Assignment(); result.Expression = assignment; assignment.Source = this.PopOperandStack(); TargetExpression targetExpression = new TargetExpression(); assignment.Target = targetExpression; Contract.Assume(currentOperation.Value is IArrayTypeReference); ArrayIndexer indexer = this.ParseArrayIndexer(currentOperation, ((IArrayTypeReference)currentOperation.Value).ElementType); targetExpression.Definition = indexer; targetExpression.Instance = indexer.IndexedObject; targetExpression.Type = indexer.Type; assignment.Source = TypeInferencer.Convert(assignment.Source, indexer.Type); assignment.Type = indexer.Type; return result; }
public override IStatement Rewrite(ILocalDeclarationStatement localDeclarationStatement) { if (this.iteratorLocalCount != null) { uint count = 0; this.iteratorLocalCount.TryGetValue(this.currentBlockStatement, out count); this.iteratorLocalCount[this.currentBlockStatement] = ++count; } BoundField/*?*/ boundField; if (this.fieldForCapturedLocalOrParameter.TryGetValue(localDeclarationStatement.LocalVariable, out boundField)) { if (localDeclarationStatement.InitialValue != null && !localDeclarationStatement.InitialValue.Equals(Dummy.Expression)) { ExpressionStatement assignToLocal = new ExpressionStatement() { Expression = new Assignment() { Source = localDeclarationStatement.InitialValue, Target = new TargetExpression() { Definition = localDeclarationStatement.LocalVariable, Instance = null, Type = localDeclarationStatement.LocalVariable.Type }, Type = localDeclarationStatement.LocalVariable.Type }, Locations = IteratorHelper.EnumerableIsEmpty(localDeclarationStatement.Locations) ? null : new List<ILocation>(localDeclarationStatement.Locations) }; base.RewriteChildren(assignToLocal); return assignToLocal; } } return base.Rewrite(localDeclarationStatement); }
/// <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 the constuctor of the iterator class. The pseudo-code is: /// /// Ctor(int state) { /// object.Ctor(); /// this.state = state; /// this.threadid = Thread.CurrentThread.ManagedThreadId; /// } /// </summary> private void CreateIteratorClosureConstructor(IteratorClosureInformation iteratorClosure) { MethodDefinition constructor = new MethodDefinition() { InternFactory = this.host.InternFactory, Parameters = new List<IParameterDefinition>(1), }; // Parameter ParameterDefinition stateParameter = new ParameterDefinition() { ContainingSignature = constructor, Index = 0, Name = this.host.NameTable.GetNameFor("state"), Type = this.host.PlatformType.SystemInt32 }; constructor.Parameters.Add(stateParameter); // Statements MethodCall baseConstructorCall = new MethodCall() { ThisArgument = new ThisReference(), MethodToCall = this.ObjectCtor, Type = this.host.PlatformType.SystemVoid }; ExpressionStatement baseConstructorCallStatement = new ExpressionStatement() { Expression = baseConstructorCall }; List<IStatement> statements = new List<IStatement>(); ExpressionStatement thisDotStateEqState = new ExpressionStatement() { Expression = new Assignment() { Source = new BoundExpression() { Definition = stateParameter, Instance = null, Type = this.host.PlatformType.SystemInt32 }, Target = new TargetExpression() { Instance = new ThisReference(), Type = this.host.PlatformType.SystemInt32, Definition = iteratorClosure.StateFieldReference }, Type = this.host.PlatformType.SystemInt32 } }; ExpressionStatement thisThreadIdEqCurrentThreadId = new ExpressionStatement() { Expression = new Assignment() { Source = new MethodCall() { MethodToCall = this.ThreadDotManagedThreadId.Getter, ThisArgument = this.ThreadDotCurrentThread, Type = this.host.PlatformType.SystemInt32 }, Target = new TargetExpression() { Instance = new ThisReference(), Type = this.host.PlatformType.SystemInt32, Definition = iteratorClosure.InitThreadIdFieldReference }, Type = this.host.PlatformType.SystemInt32 } }; statements.Add(baseConstructorCallStatement); statements.Add(thisDotStateEqState); statements.Add(thisThreadIdEqCurrentThreadId); BlockStatement block = new BlockStatement() { Statements = statements }; SourceMethodBody body = new SourceMethodBody(this.host, this.sourceLocationProvider); body.LocalsAreZeroed = true; body.IsNormalized = true; body.Block = block; constructor.Body = body; body.MethodDefinition = constructor; // Metadata of the constructor constructor.CallingConvention = CallingConvention.HasThis; constructor.ContainingTypeDefinition = iteratorClosure.ClosureDefinition; constructor.IsCil = true; constructor.IsHiddenBySignature = true; constructor.IsRuntimeSpecial = true; constructor.IsSpecialName = true; constructor.Name = this.host.NameTable.Ctor; constructor.Type = this.host.PlatformType.SystemVoid; constructor.Visibility = TypeMemberVisibility.Public; iteratorClosure.Constructor = constructor; }
/// <summary> /// Create the new body of the iterator method. /// </summary> /// <remarks> /// Pseudo code: /// iteratorClosureLocal = new Closure(0); /// iteratorClosureLocal.field = parameter; // for each parameter including this. /// return iteratorClosureLocal; /// </remarks> private BlockStatement CreateNewIteratorMethodBody(IteratorClosureInformation iteratorClosure) { BlockStatement result = new BlockStatement(); // iteratorClosureLocal = new IteratorClosure(0); LocalDefinition localDefinition = new LocalDefinition() { Name = this.host.NameTable.GetNameFor("iteratorClosureLocal"), Type = GetClosureTypeReferenceFromIterator(iteratorClosure), }; CreateObjectInstance createObjectInstance = new CreateObjectInstance() { MethodToCall = GetMethodReference(iteratorClosure, iteratorClosure.Constructor), Type = localDefinition.Type }; // the start state depends on whether the iterator is an IEnumerable or an IEnumerator. For the former, // it must be created in state -2. Then it is the GetEnumerator method that puts it into its // "start" state, i.e., state 0. var startState = this.isEnumerable ? -2 : 0; createObjectInstance.Arguments.Add(new CompileTimeConstant() { Value = startState, Type = this.host.PlatformType.SystemInt32 }); LocalDeclarationStatement localDeclarationStatement = new LocalDeclarationStatement() { InitialValue = createObjectInstance, LocalVariable = localDefinition }; result.Statements.Add(localDeclarationStatement); // Generate assignments to closure instance's fields for each of the parameters captured by the closure. foreach (object capturedLocalOrParameter in FieldForCapturedLocalOrParameter.Keys) { BoundField boundField = FieldForCapturedLocalOrParameter[capturedLocalOrParameter]; Assignment assignment; ITypeReference localOrParameterType = GetLocalOrParameterType(capturedLocalOrParameter); if (capturedLocalOrParameter is ILocalDefinition) continue; if (capturedLocalOrParameter is IThisReference) { var thisR = new ThisReference(); IExpression thisValue = thisR; if (!this.method.ContainingTypeDefinition.IsClass) { thisValue = new AddressDereference() { Address = thisR, Type = this.method.ContainingTypeDefinition.IsGeneric ? (ITypeReference)this.method.ContainingTypeDefinition.InstanceType : (ITypeReference)this.method.ContainingTypeDefinition }; } assignment = new Assignment { Source = thisValue, Type = this.method.ContainingType, Target = new TargetExpression() { Definition = GetFieldReference(iteratorClosure, boundField.Field), Type = this.method.ContainingType, Instance = new BoundExpression() { Type = localDefinition.Type, Instance = null, Definition = localDefinition, IsVolatile = false } }, }; } else { assignment = new Assignment { Source = new BoundExpression() { Definition = capturedLocalOrParameter, Instance = null, IsVolatile = false, Type = localOrParameterType }, Type = localOrParameterType, Target = new TargetExpression() { Definition = GetFieldReference(iteratorClosure, boundField.Field), Type = localOrParameterType, Instance = new BoundExpression() { Type = localDefinition.Type, Instance = null, Definition = localDefinition, IsVolatile = false } }, }; } ExpressionStatement expressionStatement = new ExpressionStatement() { Expression = assignment }; result.Statements.Add(expressionStatement); } // Generate: return iteratorClosureLocal; result.Statements.Add(new ReturnStatement() { Expression = new BoundExpression() { Definition = localDeclarationStatement.LocalVariable, Instance = null, Type = localDeclarationStatement.LocalVariable.Type } }); return result; }
/// <summary> /// Replace a yield break with: /// { /// this.state = -2; /// return; /// } /// </summary> /// <param name="yieldBreakStatement"></param> /// <returns></returns> public override IStatement Rewrite(IYieldBreakStatement yieldBreakStatement) { BlockStatement blockStatement = new BlockStatement(); ExpressionStatement thisDotStateEqMinus2 = new ExpressionStatement() { Expression = new Assignment() { Source = new CompileTimeConstant() { Value = -2, Type = this.host.PlatformType.SystemInt32 }, Target = new TargetExpression() { Definition = iteratorClosure.StateFieldReference, Type = this.host.PlatformType.SystemInt32, Instance = new ThisReference() }, Type = this.host.PlatformType.SystemInt32, } }; blockStatement.Statements.Add(thisDotStateEqMinus2); ReturnStatement returnFalse = new ReturnStatement() { Expression = new CompileTimeConstant() { Value = false, Type = this.host.PlatformType.SystemBoolean } }; blockStatement.Statements.Add(returnFalse); return blockStatement; }
/// <summary> /// Replace a (yield return exp)with a new block of the form: /// { /// Fresh_Label:; /// this.current = exp; /// state = Fresh_state; /// return true; /// } /// and associate the newly generated Fresh_state with its entry point: Fresh_label. /// </summary> public override IStatement Rewrite(IYieldReturnStatement yieldReturnStatement) { BlockStatement blockStatement = new BlockStatement(); int state = this.stateNumber++; ExpressionStatement thisDotStateEqState = new ExpressionStatement() { Expression = new Assignment() { Source = new CompileTimeConstant() { Value = state, Type = this.host.PlatformType.SystemInt32 }, Target = new TargetExpression() { Definition = this.iteratorClosure.StateFieldReference, Instance = new ThisReference(), Type = this.host.PlatformType.SystemInt32 }, Type = this.host.PlatformType.SystemInt32, }, Locations = IteratorHelper.EnumerableIsEmpty(yieldReturnStatement.Locations) ? null : new List<ILocation>(yieldReturnStatement.Locations) }; blockStatement.Statements.Add(thisDotStateEqState); ExpressionStatement thisDotCurrentEqReturnExp = new ExpressionStatement() { Expression = new Assignment() { Source = yieldReturnStatement.Expression, Target = new TargetExpression() { Definition = this.iteratorClosure.CurrentFieldReference, Instance = new ThisReference(), Type = this.iteratorClosure.CurrentFieldReference.Type }, Type = this.iteratorClosure.CurrentFieldReference.Type } }; blockStatement.Statements.Add(thisDotCurrentEqReturnExp); ReturnStatement returnTrue = new ReturnStatement() { Expression = new CompileTimeConstant() { Value = true, Type = this.host.PlatformType.SystemBoolean } }; blockStatement.Statements.Add(returnTrue); LabeledStatement labeledStatement = new LabeledStatement() { Label = this.host.NameTable.GetNameFor("Label"+state), Statement = new EmptyStatement() }; blockStatement.Statements.Add(labeledStatement); this.stateEntries.Add(state, labeledStatement); return blockStatement; }
/// <summary> /// If the <paramref name="typeDefinition"/> has a type contract, generate a /// contract invariant method and add it to the Methods of the <paramref name="typeDefinition"/>. /// </summary> private void VisitTypeDefinition(ITypeDefinition typeDefinition) { ITypeContract typeContract = this.contractProvider.GetTypeContractFor(typeDefinition); if (typeContract != null) { #region Define the method List<IStatement> statements = new List<IStatement>(); var methodBody = new SourceMethodBody(this.host) { LocalsAreZeroed = true, Block = new BlockStatement() { Statements = statements } }; List<ICustomAttribute> attributes = new List<ICustomAttribute>(); MethodDefinition m = new MethodDefinition() { Attributes = attributes, Body = methodBody, CallingConvention = CallingConvention.HasThis, ContainingTypeDefinition = typeDefinition, InternFactory = this.host.InternFactory, IsStatic = false, Name = this.host.NameTable.GetNameFor("$InvariantMethod$"), Type = systemVoid, Visibility = TypeMemberVisibility.Private, }; methodBody.MethodDefinition = m; #region Add calls to Contract.Invariant foreach (var inv in typeContract.Invariants) { var methodCall = new MethodCall() { Arguments = new List<IExpression> { inv.Condition, }, IsStaticCall = true, MethodToCall = this.contractProvider.ContractMethods.Invariant, Type = systemVoid, Locations = new List<ILocation>(inv.Locations), }; ExpressionStatement es = new ExpressionStatement() { Expression = methodCall }; statements.Add(es); } statements.Add(new ReturnStatement()); #endregion #region Add [ContractInvariantMethod] var contractInvariantMethodType = new Immutable.NamespaceTypeReference( this.host, this.host.PlatformType.SystemDiagnosticsContractsContract.ContainingUnitNamespace, this.host.NameTable.GetNameFor("ContractInvariantMethodAttribute"), 0, false, false, true, PrimitiveTypeCode.NotPrimitive ); var contractInvariantMethodCtor = new Microsoft.Cci.MutableCodeModel.MethodReference() { CallingConvention = CallingConvention.HasThis, ContainingType = contractInvariantMethodType, GenericParameterCount = 0, InternFactory = this.host.InternFactory, Name = host.NameTable.Ctor, Type = host.PlatformType.SystemVoid, }; var contractInvariantMethodAttribute = new CustomAttribute(); contractInvariantMethodAttribute.Constructor = contractInvariantMethodCtor; attributes.Add(contractInvariantMethodAttribute); #endregion var namedTypeDefinition = (NamedTypeDefinition)typeDefinition; var newMethods = new List<IMethodDefinition>(namedTypeDefinition.Methods == null ? 1 : namedTypeDefinition.Methods.Count() + 1); if (namedTypeDefinition.Methods != null) { foreach (var meth in namedTypeDefinition.Methods) { if (!ContractHelper.IsInvariantMethod(this.host, meth)) newMethods.Add(meth); } } namedTypeDefinition.Methods = newMethods; namedTypeDefinition.Methods.Add(m); #endregion Define the method } }
public override IStatement Rewrite(IPushStatement pushStatement) { var depth = this.locals.Count; var t = pushStatement.ValueToPush.Type; var local = this.GetOrCreateLocal(depth, t); this.locals.Push(local); var assignment = new Assignment() { Source = pushStatement.ValueToPush, Target = new TargetExpression(){ Definition = local, Instance = null, Type = t, }, Type = t, }; if (this.inThenBranch) { if (this.thenBranchPushes != null && (t.TypeCode == PrimitiveTypeCode.Int32 || t.TypeCode == PrimitiveTypeCode.Boolean)) { this.thenBranchPushes.Add(depth, assignment); } } else if (this.inElseBranch) { if (this.thenBranchPushes != null) { if (t.TypeCode == PrimitiveTypeCode.Int32) { Contract.Assume(this.thenBranchPushes.ContainsKey(depth)); var a = this.thenBranchPushes[depth]; if (a.Type.TypeCode == PrimitiveTypeCode.Boolean) { // then this should be a push of a boolean, not an int Contract.Assume(pushStatement.ValueToPush is ICompileTimeConstant); var ctc = (ICompileTimeConstant) pushStatement.ValueToPush; var boolLocal = a.Target.Definition as ILocalDefinition; assignment.Target = new TargetExpression() { Definition = boolLocal, Instance = null, Type = this.systemBool, }; assignment.Source = new CompileTimeConstant() { Type = this.systemBool, Value = ((int)ctc.Value) == 0 ? false : true, }; this.locals.Pop(); this.locals.Push(boolLocal); } } else if (t.TypeCode == PrimitiveTypeCode.Boolean) { Contract.Assume(this.thenBranchPushes.ContainsKey(depth)); var a = this.thenBranchPushes[depth]; if (a.Type.TypeCode == PrimitiveTypeCode.Int32) { // then this should have been a push of a boolean, not an int Contract.Assume(a.Source is ICompileTimeConstant); var ctc = (ICompileTimeConstant)a.Source; var boolLocal = a.Target.Definition as ILocalDefinition; Contract.Assume(boolLocal != null); a.Target = new TargetExpression() { Definition = boolLocal, Instance = null, Type = this.systemBool, }; a.Source = new CompileTimeConstant() { Type = this.systemBool, Value = ((int)ctc.Value) == 0 ? false : true, }; } } } } var expressionStatment = new ExpressionStatement() { Expression = assignment, }; return expressionStatment; }
/* private void translateAnonymousControlsForPage(ITypeDefinition typeDef) { if (PhoneCodeHelper.instance().PhonePlugin != null && typeDef.isPhoneApplicationPageClass(sink.host)) { IEnumerable<ControlInfoStructure> pageCtrls= PhoneCodeHelper.instance().PhonePlugin.getControlsForPage(typeDef.ToString()); foreach (ControlInfoStructure ctrlInfo in pageCtrls) { if (ctrlInfo.Name.Contains(PhoneControlsPlugin.BOOGIE_DUMMY_CONTROL) || ctrlInfo.Name == Dummy.Name.Value) { string anonymousControlName = ctrlInfo.Name; IFieldDefinition fieldDef = new FieldDefinition() { ContainingTypeDefinition = typeDef, Name = sink.host.NameTable.GetNameFor(anonymousControlName), InternFactory = sink.host.InternFactory, Visibility = TypeMemberVisibility.Public, Type = sink.host.PlatformType.SystemObject, IsStatic = false, }; (typeDef as Microsoft.Cci.MutableCodeModel.NamespaceTypeDefinition).Fields.Add(fieldDef); //sink.FindOrCreateFieldVariable(fieldDef); } } } } */ private void CreateDefaultStructConstructor(ITypeDefinition typeDefinition) { Contract.Requires(typeDefinition.IsStruct); var proc = this.sink.FindOrCreateProcedureForDefaultStructCtor(typeDefinition); this.sink.BeginMethod(typeDefinition); var stmtTranslator = this.Factory.MakeStatementTraverser(this.sink, this.PdbReader, false); var stmts = new List<IStatement>(); foreach (var f in typeDefinition.Fields) { if (f.IsStatic) continue; var s = new ExpressionStatement() { Expression = new Assignment() { Source = new DefaultValue() { DefaultValueType = f.Type, Type = f.Type, }, Target = new TargetExpression() { Definition = f, Instance = new ThisReference() { Type = typeDefinition, }, Type = f.Type, }, Type = f.Type, }, }; stmts.Add(s); } stmtTranslator.Traverse(stmts); var translatedStatements = stmtTranslator.StmtBuilder.Collect(Bpl.Token.NoToken); var lit = Bpl.Expr.Literal(1); lit.Type = Bpl.Type.Int; var args = new List<object> { lit }; var attrib = new Bpl.QKeyValue(typeDefinition.Token(), "inline", args, null); // TODO: Need to have it be {:inine 1} (and not just {:inline})? List<Bpl.Variable> vars = new List<Bpl.Variable>(); foreach (Bpl.Variable v in this.sink.LocalVarMap.Values) { vars.Add(v); } List<Bpl.Variable> vseq = new List<Bpl.Variable>(vars.ToArray()); Bpl.Implementation impl = new Bpl.Implementation(Bpl.Token.NoToken, proc.Name, new List<Bpl.TypeVariable>(), proc.InParams, proc.OutParams, vseq, translatedStatements, attrib, new Bpl.Errors() ); impl.Proc = (Bpl.Procedure) proc; // TODO: get rid of cast this.sink.TranslatedProgram.AddTopLevelDeclaration(impl); }
private void injectNavigationUpdateCode(IBlockStatement block, IEnumerable<Tuple<IStatement,StaticURIMode, string>> staticStmts, IEnumerable<IStatement> nonStaticStmts) { // TODO Here there is the STRONG assumption that a given method will only navigate at most once per method call // TODO (or at most will re-navigate to the same page). Quick "page flipping" on the same method // TODO would not be captured correctly Microsoft.Cci.MutableCodeModel.BlockStatement mutableBlock = block as Microsoft.Cci.MutableCodeModel.BlockStatement; foreach (IStatement stmt in nonStaticStmts) { int ndx = mutableBlock.Statements.ToList().IndexOf(stmt); if (ndx == -1) { // can't be throw new IndexOutOfRangeException("Statement must exist in original block"); } Assignment currentURIAssign = new Assignment() { Source = new CompileTimeConstant() { Type = host.PlatformType.SystemString, Value = PhoneCodeHelper.BOOGIE_DO_HAVOC_CURRENTURI, }, Type = host.PlatformType.SystemString, Target = new TargetExpression() { Type = host.PlatformType.SystemString, // TODO unify code for current uri fieldreference Definition = new FieldReference() { ContainingType = PhoneCodeHelper.instance().getMainAppTypeReference(), IsStatic= true, Type = host.PlatformType.SystemString, Name = host.NameTable.GetNameFor(PhoneCodeHelper.IL_CURRENT_NAVIGATION_URI_VARIABLE), InternFactory=host.InternFactory, }, }, }; Statement uriInitStmt = new ExpressionStatement() { Expression = currentURIAssign, }; mutableBlock.Statements.Insert(ndx + 1, uriInitStmt); } foreach (Tuple<IStatement, StaticURIMode, string> entry in staticStmts) { int ndx= mutableBlock.Statements.ToList().IndexOf(entry.Item1); if (ndx == -1) { // can't be throw new IndexOutOfRangeException("Statement must exist in original block"); } Assignment currentURIAssign = new Assignment() { Source = new CompileTimeConstant() { Type = host.PlatformType.SystemString, Value = UriHelper.getURIBase(entry.Item3).ToLower(), }, Type = host.PlatformType.SystemString, Target = new TargetExpression() { Type = host.PlatformType.SystemString, // TODO unify code for current uri fieldreference Definition = new FieldReference() { ContainingType = PhoneCodeHelper.instance().getMainAppTypeReference(), IsStatic= true, Type = host.PlatformType.SystemString, Name = host.NameTable.GetNameFor(PhoneCodeHelper.IL_CURRENT_NAVIGATION_URI_VARIABLE), InternFactory=host.InternFactory, }, }, }; Statement uriInitStmt = new ExpressionStatement() { Expression = currentURIAssign, }; mutableBlock.Statements.Insert(ndx+1, uriInitStmt); } }
/// <summary /> public override IStatement Rewrite(IForEachStatement forEachStatement) { ILocalDefinition foreachLocal; var key = forEachStatement.Collection.Type.InternedKey; ITypeReference enumeratorType; IMethodReference getEnumerator; IMethodReference getCurrent; var gtir = forEachStatement.Collection.Type as IGenericTypeInstanceReference; if (gtir != null) { var typeArguments = gtir.GenericArguments; ITypeReference genericEnumeratorType = new Immutable.GenericTypeInstanceReference(this.host.PlatformType.SystemCollectionsGenericIEnumerator, typeArguments, this.host.InternFactory); ITypeReference genericEnumerableType = new Immutable.GenericTypeInstanceReference(this.host.PlatformType.SystemCollectionsGenericIEnumerable, typeArguments, this.host.InternFactory); enumeratorType = genericEnumeratorType; getEnumerator = new SpecializedMethodReference() { CallingConvention = CallingConvention.HasThis, ContainingType = genericEnumerableType, InternFactory = this.host.InternFactory, Name = this.host.NameTable.GetNameFor("GetEnumerator"), Parameters = new List<IParameterTypeInformation>(), Type = genericEnumeratorType, UnspecializedVersion = new MethodReference() { CallingConvention = CallingConvention.HasThis, ContainingType = this.host.PlatformType.SystemCollectionsGenericIEnumerable, InternFactory = this.host.InternFactory, Name = this.host.NameTable.GetNameFor("GetEnumerator"), Parameters = new List<IParameterTypeInformation>(), Type = this.host.PlatformType.SystemCollectionsGenericIEnumerator, }, }; var getEnumerator2 = (IMethodReference) IteratorHelper.First(genericEnumerableType.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("GetEnumerator"), false)); getEnumerator = getEnumerator2; getCurrent = (IMethodReference) IteratorHelper.First(genericEnumeratorType.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("get_Current"), false)); } else { enumeratorType = this.host.PlatformType.SystemCollectionsIEnumerator; getEnumerator = new MethodReference() { CallingConvention = CallingConvention.HasThis, ContainingType = enumeratorType, InternFactory = this.host.InternFactory, Name = this.host.NameTable.GetNameFor("GetEnumerator"), Parameters = new List<IParameterTypeInformation>(), Type = this.host.PlatformType.SystemCollectionsIEnumerable, }; getCurrent = new MethodReference() { CallingConvention = CallingConvention.HasThis, ContainingType = enumeratorType, InternFactory = this.host.InternFactory, Name = this.host.NameTable.GetNameFor("get_Current"), Parameters = new List<IParameterTypeInformation>(), Type = this.host.PlatformType.SystemObject, }; } var initializer = new MethodCall() { Arguments = new List<IExpression>(), IsStaticCall = false, IsVirtualCall = true, MethodToCall = getEnumerator, ThisArgument = forEachStatement.Collection, Type = enumeratorType, }; IStatement initialization; if (!this.foreachLocals.TryGetValue(key, out foreachLocal)) { foreachLocal = new LocalDefinition() { Type = enumeratorType, Name = this.host.NameTable.GetNameFor("CS$5$" + this.foreachLocals.Count) }; this.foreachLocals.Add(key, foreachLocal); initialization = new LocalDeclarationStatement() { InitialValue = initializer, LocalVariable = foreachLocal, }; } else { initialization = new ExpressionStatement() { Expression = new Assignment() { Source = initializer, Target = new TargetExpression() { Definition = foreachLocal, Instance = null, Type = foreachLocal.Type, }, Type = foreachLocal.Type, }, }; } var newStmts = new List<IStatement>(); newStmts.Add(new ExpressionStatement(){ Expression = new Assignment(){ Source = new MethodCall(){ Arguments = new List<IExpression>(), IsStaticCall = false, IsVirtualCall = true, MethodToCall = getCurrent, ThisArgument = new BoundExpression(){ Definition = foreachLocal, Instance = null, }, Type = forEachStatement.Variable.Type, }, Target = new TargetExpression(){ Definition = forEachStatement.Variable, Instance = null, }, Type = forEachStatement.Variable.Type, }, }); newStmts.Add(forEachStatement.Body); var newBody = new BlockStatement(){ Statements = newStmts,}; var result = new BlockStatement() { Statements = new List<IStatement>(){ initialization, new TryCatchFinallyStatement(){ TryBody = new BlockStatement() { Statements = new List<IStatement>(){ new WhileDoStatement(){ Body = newBody, Condition = new MethodCall(){ Arguments = new List<IExpression>(), IsStaticCall = false, IsVirtualCall = true, MethodToCall = moveNext, ThisArgument = new BoundExpression(){ Definition = foreachLocal, Instance = null, }, Type = this.host.PlatformType.SystemBoolean, }, }, }, }, FinallyBody = new BlockStatement() { Statements = new List<IStatement>(){ new ConditionalStatement(){ Condition = new Equality(){ LeftOperand = new BoundExpression(){ Definition = foreachLocal, Instance = null, Type = foreachLocal.Type, }, RightOperand = new CompileTimeConstant(){ Type = foreachLocal.Type, Value = null, }, Type = this.host.PlatformType.SystemBoolean, }, FalseBranch = new EmptyStatement(), TrueBranch = new ExpressionStatement(){ Expression = new MethodCall(){ Arguments = new List<IExpression>(), IsStaticCall = false, IsVirtualCall = true, MethodToCall = this.disposeMethod, ThisArgument = new BoundExpression(){ Definition = foreachLocal, Instance = null, }, Type = this.host.PlatformType.SystemVoid, }, }, }, }, }, }, }, }; return result; }
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()); }
public override IStatement Visit(ExpressionStatement expressionStatement) { var assignment = expressionStatement.Expression as IAssignment; if (assignment == null) return base.Visit(expressionStatement); // need to look for method calls var lambda = assignment.Source as AnonymousDelegate; if (lambda == null) return base.Visit(expressionStatement); // but otherwise, we know no sub-expression of this assignment are interesting for this visitor // so don't do the base call. var fieldReference = assignment.Target.Definition as IFieldReference; if (fieldReference != null) { if (this.cachedDelegateFieldsOrLocals.ContainsKey(fieldReference.Name.Value)) return CodeDummy.Block; else return expressionStatement; } var localDefinition = assignment.Target.Definition as ILocalDefinition; if (localDefinition == null) return expressionStatement; if (this.cachedDelegateFieldsOrLocals.ContainsKey(localDefinition.Name.Value)) return CodeDummy.Block; else return expressionStatement; }
private void ParseInstruction(Instruction instruction, List<IStatement> statements) { Contract.Requires(instruction != null); Contract.Requires(statements != null); Statement/*?*/ statement = null; Expression/*?*/ expression = null; ITypeReference/*?*/ elementType = null; IOperation currentOperation = instruction.Operation; OperationCode currentOpcode = currentOperation.OperationCode; if (this.host.PreserveILLocations) { if (this.lastLocation == null) this.lastLocation = currentOperation.Location; } else if (this.sourceLocationProvider != null) { if (this.lastSourceLocation == null) { foreach (var sourceLocation in this.sourceLocationProvider.GetPrimarySourceLocationsFor(currentOperation.Location)) { Contract.Assume(sourceLocation != null); if (sourceLocation.StartLine != 0x00feefee) { this.lastSourceLocation = sourceLocation; break; } } } } if (this.synchronizatonPointLocationFor != null) { uint currentOffset = currentOperation.Offset; var syncPointLocation = this.synchronizatonPointLocationFor[currentOffset]; if (syncPointLocation != null) { if (syncPointLocation.SynchronizationPoint.ContinuationOffset == currentOffset) this.lastContinuationLocation = new ContinuationLocation(syncPointLocation); else this.lastSynchronizationLocation = syncPointLocation; } } switch (currentOpcode) { case OperationCode.Add: case OperationCode.Add_Ovf: case OperationCode.Add_Ovf_Un: case OperationCode.And: case OperationCode.Ceq: case OperationCode.Cgt: case OperationCode.Cgt_Un: case OperationCode.Clt: case OperationCode.Clt_Un: case OperationCode.Div: case OperationCode.Div_Un: case OperationCode.Mul: case OperationCode.Mul_Ovf: case OperationCode.Mul_Ovf_Un: case OperationCode.Or: case OperationCode.Rem: case OperationCode.Rem_Un: case OperationCode.Shl: case OperationCode.Shr: case OperationCode.Shr_Un: case OperationCode.Sub: case OperationCode.Sub_Ovf: case OperationCode.Sub_Ovf_Un: case OperationCode.Xor: expression = this.ParseBinaryOperation(currentOpcode); break; case OperationCode.Arglist: expression = new RuntimeArgumentHandleExpression(); break; case OperationCode.Array_Addr: elementType = ((IArrayTypeReference)currentOperation.Value).ElementType; expression = this.ParseArrayElementAddres(currentOperation, elementType); break; case OperationCode.Ldelema: elementType = (ITypeReference)currentOperation.Value; expression = this.ParseArrayElementAddres(currentOperation, elementType, treatArrayAsSingleDimensioned: true); break; case OperationCode.Array_Create: case OperationCode.Array_Create_WithLowerBound: case OperationCode.Newarr: expression = this.ParseArrayCreate(currentOperation); break; case OperationCode.Array_Get: elementType = ((IArrayTypeReference)currentOperation.Value).ElementType; expression = this.ParseArrayIndexer(currentOperation, elementType??this.platformType.SystemObject, treatArrayAsSingleDimensioned: false); break; case OperationCode.Ldelem: elementType = (ITypeReference)currentOperation.Value; goto case OperationCode.Ldelem_Ref; case OperationCode.Ldelem_I: elementType = this.platformType.SystemIntPtr; goto case OperationCode.Ldelem_Ref; case OperationCode.Ldelem_I1: elementType = this.platformType.SystemInt8; goto case OperationCode.Ldelem_Ref; case OperationCode.Ldelem_I2: elementType = this.platformType.SystemInt16; goto case OperationCode.Ldelem_Ref; case OperationCode.Ldelem_I4: elementType = this.platformType.SystemInt32; goto case OperationCode.Ldelem_Ref; case OperationCode.Ldelem_I8: elementType = this.platformType.SystemInt64; goto case OperationCode.Ldelem_Ref; case OperationCode.Ldelem_R4: elementType = this.platformType.SystemFloat32; goto case OperationCode.Ldelem_Ref; case OperationCode.Ldelem_R8: elementType = this.platformType.SystemFloat64; goto case OperationCode.Ldelem_Ref; case OperationCode.Ldelem_U1: elementType = this.platformType.SystemUInt8; goto case OperationCode.Ldelem_Ref; case OperationCode.Ldelem_U2: elementType = this.platformType.SystemUInt16; goto case OperationCode.Ldelem_Ref; case OperationCode.Ldelem_U4: elementType = this.platformType.SystemUInt32; goto case OperationCode.Ldelem_Ref; case OperationCode.Ldelem_Ref: expression = this.ParseArrayIndexer(currentOperation, elementType??this.platformType.SystemObject, treatArrayAsSingleDimensioned: true); break; case OperationCode.Array_Set: statement = this.ParseArraySet(currentOperation); break; case OperationCode.Beq: case OperationCode.Beq_S: case OperationCode.Bge: case OperationCode.Bge_S: case OperationCode.Bge_Un: case OperationCode.Bge_Un_S: case OperationCode.Bgt: case OperationCode.Bgt_S: case OperationCode.Bgt_Un: case OperationCode.Bgt_Un_S: case OperationCode.Ble: case OperationCode.Ble_S: case OperationCode.Ble_Un: case OperationCode.Ble_Un_S: case OperationCode.Blt: case OperationCode.Blt_S: case OperationCode.Blt_Un: case OperationCode.Blt_Un_S: case OperationCode.Bne_Un: case OperationCode.Bne_Un_S: statement = this.ParseBinaryConditionalBranch(currentOperation); break; case OperationCode.Box: expression = this.ParseConversion(currentOperation); break; case OperationCode.Br: case OperationCode.Br_S: case OperationCode.Leave: case OperationCode.Leave_S: statement = this.ParseUnconditionalBranch(currentOperation); break; case OperationCode.Break: statement = new DebuggerBreakStatement(); break; case OperationCode.Brfalse: case OperationCode.Brfalse_S: case OperationCode.Brtrue: case OperationCode.Brtrue_S: statement = this.ParseUnaryConditionalBranch(currentOperation); break; case OperationCode.Call: case OperationCode.Callvirt: MethodCall call = this.ParseCall(currentOperation); if (call.MethodToCall.Type.TypeCode == PrimitiveTypeCode.Void) { call.Locations.Add(currentOperation.Location); // turning it into a statement prevents the location from being attached to the expresssion ExpressionStatement es = new ExpressionStatement(); es.Expression = call; statement = es; } else expression = call; break; case OperationCode.Calli: expression = this.ParsePointerCall(currentOperation); break; case OperationCode.Castclass: case OperationCode.Conv_I: case OperationCode.Conv_I1: case OperationCode.Conv_I2: case OperationCode.Conv_I4: case OperationCode.Conv_I8: case OperationCode.Conv_Ovf_I: case OperationCode.Conv_Ovf_I_Un: case OperationCode.Conv_Ovf_I1: case OperationCode.Conv_Ovf_I1_Un: case OperationCode.Conv_Ovf_I2: case OperationCode.Conv_Ovf_I2_Un: case OperationCode.Conv_Ovf_I4: case OperationCode.Conv_Ovf_I4_Un: case OperationCode.Conv_Ovf_I8: case OperationCode.Conv_Ovf_I8_Un: case OperationCode.Conv_Ovf_U: case OperationCode.Conv_Ovf_U_Un: case OperationCode.Conv_Ovf_U1: case OperationCode.Conv_Ovf_U1_Un: case OperationCode.Conv_Ovf_U2: case OperationCode.Conv_Ovf_U2_Un: case OperationCode.Conv_Ovf_U4: case OperationCode.Conv_Ovf_U4_Un: case OperationCode.Conv_Ovf_U8: case OperationCode.Conv_Ovf_U8_Un: case OperationCode.Conv_R_Un: case OperationCode.Conv_R4: case OperationCode.Conv_R8: case OperationCode.Conv_U: case OperationCode.Conv_U1: case OperationCode.Conv_U2: case OperationCode.Conv_U4: case OperationCode.Conv_U8: case OperationCode.Unbox: case OperationCode.Unbox_Any: expression = this.ParseConversion(currentOperation); break; case OperationCode.Ckfinite: var operand = this.PopOperandStack(); var chkfinite = new MutableCodeModel.MethodReference() { CallingConvention = Cci.CallingConvention.FastCall, ContainingType = host.PlatformType.SystemFloat64, Name = this.host.NameTable.GetNameFor("__ckfinite__"), Type = host.PlatformType.SystemFloat64, InternFactory = host.InternFactory, }; expression = new MethodCall() { Arguments = new List<IExpression>(1) { operand }, IsStaticCall = true, Type = operand.Type, MethodToCall = chkfinite }; break; case OperationCode.Constrained_: //This prefix is redundant and is not represented in the code model. break; case OperationCode.Cpblk: var copyMemory = new CopyMemoryStatement(); copyMemory.NumberOfBytesToCopy = this.PopOperandStack(); copyMemory.SourceAddress = this.PopOperandStack(); copyMemory.TargetAddress = this.PopOperandStack(); statement = copyMemory; break; case OperationCode.Cpobj: expression = this.ParseCopyObject(); break; case OperationCode.Dup: expression = this.ParseDup(instruction.Type); break; case OperationCode.Endfilter: statement = this.ParseEndfilter(); break; case OperationCode.Endfinally: statement = new EndFinally(); break; case OperationCode.Initblk: var fillMemory = new FillMemoryStatement(); fillMemory.NumberOfBytesToFill = this.PopOperandStack(); fillMemory.FillValue = this.PopOperandStack(); fillMemory.TargetAddress = this.PopOperandStack(); statement = fillMemory; break; case OperationCode.Initobj: statement = this.ParseInitObject(currentOperation); break; case OperationCode.Isinst: expression = this.ParseCastIfPossible(currentOperation); break; case OperationCode.Jmp: var methodToCall = (IMethodReference)currentOperation.Value; expression = new MethodCall() { IsJumpCall = true, MethodToCall = methodToCall, Type = methodToCall.Type }; break; case OperationCode.Ldarg: case OperationCode.Ldarg_0: case OperationCode.Ldarg_1: case OperationCode.Ldarg_2: case OperationCode.Ldarg_3: case OperationCode.Ldarg_S: case OperationCode.Ldloc: case OperationCode.Ldloc_0: case OperationCode.Ldloc_1: case OperationCode.Ldloc_2: case OperationCode.Ldloc_3: case OperationCode.Ldloc_S: case OperationCode.Ldfld: case OperationCode.Ldsfld: expression = this.ParseBoundExpression(instruction); break; case OperationCode.Ldarga: case OperationCode.Ldarga_S: case OperationCode.Ldflda: case OperationCode.Ldsflda: case OperationCode.Ldloca: case OperationCode.Ldloca_S: case OperationCode.Ldftn: case OperationCode.Ldvirtftn: expression = this.ParseAddressOf(instruction); break; case OperationCode.Ldc_I4: case OperationCode.Ldc_I4_0: case OperationCode.Ldc_I4_1: case OperationCode.Ldc_I4_2: case OperationCode.Ldc_I4_3: case OperationCode.Ldc_I4_4: case OperationCode.Ldc_I4_5: case OperationCode.Ldc_I4_6: case OperationCode.Ldc_I4_7: case OperationCode.Ldc_I4_8: case OperationCode.Ldc_I4_M1: case OperationCode.Ldc_I4_S: case OperationCode.Ldc_I8: case OperationCode.Ldc_R4: case OperationCode.Ldc_R8: case OperationCode.Ldnull: case OperationCode.Ldstr: expression = this.ParseCompileTimeConstant(currentOperation); break; case OperationCode.Ldind_I: case OperationCode.Ldind_I1: case OperationCode.Ldind_I2: case OperationCode.Ldind_I4: case OperationCode.Ldind_I8: case OperationCode.Ldind_R4: case OperationCode.Ldind_R8: case OperationCode.Ldind_Ref: case OperationCode.Ldind_U1: case OperationCode.Ldind_U2: case OperationCode.Ldind_U4: case OperationCode.Ldobj: expression = this.ParseAddressDereference(currentOperation); break; case OperationCode.Ldlen: expression = this.ParseVectorLength(); break; case OperationCode.Ldtoken: expression = ParseToken(currentOperation); break; case OperationCode.Localloc: expression = this.ParseStackArrayCreate(); break; case OperationCode.Mkrefany: expression = this.ParseMakeTypedReference(currentOperation); break; case OperationCode.Neg: expression = this.ParseUnaryOperation(new UnaryNegation()); break; case OperationCode.Not: expression = this.ParseUnaryOperation(new OnesComplement()); break; case OperationCode.Newobj: expression = this.ParseCreateObjectInstance(currentOperation); break; case OperationCode.No_: Contract.Assume(false); //if code out there actually uses this, I need to know sooner rather than later. //TODO: need object model support break; case OperationCode.Nop: statement = new EmptyStatement(); break; case OperationCode.Pop: statement = this.ParsePop(); break; case OperationCode.Readonly_: this.sawReadonly = true; break; case OperationCode.Refanytype: expression = this.ParseGetTypeOfTypedReference(); break; case OperationCode.Refanyval: expression = this.ParseGetValueOfTypedReference(currentOperation); break; case OperationCode.Ret: statement = this.ParseReturn(); break; case OperationCode.Rethrow: statement = new RethrowStatement(); break; case OperationCode.Sizeof: expression = ParseSizeOf(currentOperation); break; case OperationCode.Starg: case OperationCode.Starg_S: case OperationCode.Stelem: case OperationCode.Stelem_I: case OperationCode.Stelem_I1: case OperationCode.Stelem_I2: case OperationCode.Stelem_I4: case OperationCode.Stelem_I8: case OperationCode.Stelem_R4: case OperationCode.Stelem_R8: case OperationCode.Stelem_Ref: case OperationCode.Stfld: case OperationCode.Stind_I: case OperationCode.Stind_I1: case OperationCode.Stind_I2: case OperationCode.Stind_I4: case OperationCode.Stind_I8: case OperationCode.Stind_R4: case OperationCode.Stind_R8: case OperationCode.Stind_Ref: case OperationCode.Stloc: case OperationCode.Stloc_0: case OperationCode.Stloc_1: case OperationCode.Stloc_2: case OperationCode.Stloc_3: case OperationCode.Stloc_S: case OperationCode.Stobj: case OperationCode.Stsfld: statement = this.ParseAssignment(currentOperation); break; case OperationCode.Switch: statement = this.ParseSwitchInstruction(currentOperation); break; case OperationCode.Tail_: this.sawTailCall = true; break; case OperationCode.Throw: statement = this.ParseThrow(); break; case OperationCode.Unaligned_: Contract.Assume(currentOperation.Value is byte); var alignment = (byte)currentOperation.Value; Contract.Assume(alignment == 1 || alignment == 2 || alignment == 4); this.alignment = alignment; break; case OperationCode.Volatile_: this.sawVolatile = true; break; } if (expression != null) { if (expression.Type is Dummy) expression.Type = instruction.Type; Contract.Assume(!(expression.Type is Dummy)); if (expression.Type.TypeCode != PrimitiveTypeCode.Void) { if (this.host.PreserveILLocations) { expression.Locations.Add(currentOperation.Location); } this.operandStack.Push(expression); } } else if (statement != null) { this.TurnOperandStackIntoPushStatements(statements); statements.Add(statement); if (this.host.PreserveILLocations) { if (this.lastLocation != null) { statement.Locations.Add(this.lastLocation); this.lastLocation = null; } } else if (this.lastSourceLocation != null) { statement.Locations.Add(this.lastSourceLocation); this.lastSourceLocation = null; } if (this.lastSynchronizationLocation != null) { statement.Locations.Add(this.lastSynchronizationLocation); this.lastSynchronizationLocation = null; } else if (this.lastContinuationLocation != null) { statement.Locations.Add(this.lastContinuationLocation); this.lastContinuationLocation = null; } } }
private IEnumerable<IStatement> getCodeForSettingEnabledness(ControlInfoStructure controlInfo) { IList<IStatement> code = new List<IStatement>(); BoundExpression boundControl = makeBoundControlFromControlInfo(controlInfo); MethodCall setEnablednessCall = new MethodCall() { IsStaticCall = false, IsVirtualCall = true, IsTailCall = false, Type = ((Microsoft.Cci.Immutable.PlatformType) host.PlatformType).SystemVoid, MethodToCall = isEnabledSetter, ThisArgument = boundControl, }; setEnablednessCall.Arguments.Add(controlInfo.IsEnabled ? trueConstant : falseConstant); ExpressionStatement callStmt = new ExpressionStatement() { Expression = setEnablednessCall, }; code.Add(callStmt); return code; }
private Statement ParseAssignment(IOperation currentOperation) { Contract.Requires(currentOperation != null); TargetExpression target = new TargetExpression(); ITypeReference/*?*/ elementType = null; if (this.alignment > 0) { Contract.Assume(this.alignment == 1 || this.alignment == 2 || this.alignment == 4); target.Alignment = this.alignment; } target.IsVolatile = this.sawVolatile; Assignment assignment = new Assignment(); assignment.Target = target; assignment.Source = this.PopOperandStack(); ExpressionStatement result = new ExpressionStatement(); result.Expression = assignment; switch (currentOperation.OperationCode) { case OperationCode.Starg: case OperationCode.Starg_S: { var definition = currentOperation.Value; if (definition == null) { target.Definition = new ThisReference(); var typeForThis = (INamedTypeDefinition)this.MethodDefinition.ContainingTypeDefinition; if (typeForThis.IsValueType) target.Type = Immutable.ManagedPointerType.GetManagedPointerType(Microsoft.Cci.MutableCodeModel.NamedTypeDefinition.SelfInstance(typeForThis, this.host.InternFactory), this.host.InternFactory); else target.Type = NamedTypeDefinition.SelfInstance(typeForThis, this.host.InternFactory); } else { var par = definition as IParameterDefinition; Contract.Assume(par != null); target.Definition = definition; target.Type = par.Type; } break; } case OperationCode.Stfld: target.Instance = this.PopOperandStack(); goto case OperationCode.Stsfld; case OperationCode.Stsfld: Contract.Assume(currentOperation.Value is IFieldReference); var field = (IFieldReference)currentOperation.Value; target.Definition = field; target.Type = field.Type; break; case OperationCode.Stelem: elementType = (ITypeReference)currentOperation.Value; goto case OperationCode.Stelem_Ref; case OperationCode.Stelem_I: elementType = this.platformType.SystemIntPtr; goto case OperationCode.Stelem_Ref; case OperationCode.Stelem_I1: elementType = this.platformType.SystemInt8; goto case OperationCode.Stelem_Ref; case OperationCode.Stelem_I2: elementType = this.platformType.SystemInt16; goto case OperationCode.Stelem_Ref; case OperationCode.Stelem_I4: elementType = this.platformType.SystemInt32; goto case OperationCode.Stelem_Ref; case OperationCode.Stelem_I8: elementType = this.platformType.SystemInt64; goto case OperationCode.Stelem_Ref; case OperationCode.Stelem_R4: elementType = this.platformType.SystemFloat32; goto case OperationCode.Stelem_Ref; case OperationCode.Stelem_R8: elementType = this.platformType.SystemFloat64; goto case OperationCode.Stelem_Ref; case OperationCode.Stelem_Ref: ArrayIndexer indexer = this.ParseArrayIndexer(currentOperation, elementType??this.platformType.SystemObject, treatArrayAsSingleDimensioned: true); target.Definition = indexer; target.Instance = indexer.IndexedObject; target.Type = indexer.Type; break; case OperationCode.Stind_I: elementType = this.platformType.SystemIntPtr; goto case OperationCode.Stind_Ref; case OperationCode.Stind_I1: elementType = this.platformType.SystemInt8; goto case OperationCode.Stind_Ref; case OperationCode.Stind_I2: elementType = this.platformType.SystemInt16; goto case OperationCode.Stind_Ref; case OperationCode.Stind_I4: elementType = this.platformType.SystemInt32; goto case OperationCode.Stind_Ref; case OperationCode.Stind_I8: elementType = this.platformType.SystemInt64; goto case OperationCode.Stind_Ref; case OperationCode.Stind_R4: elementType = this.platformType.SystemFloat32; goto case OperationCode.Stind_Ref; case OperationCode.Stind_R8: elementType = this.platformType.SystemFloat64; goto case OperationCode.Stind_Ref; case OperationCode.Stobj: elementType = (ITypeReference)currentOperation.Value; goto case OperationCode.Stind_Ref; case OperationCode.Stind_Ref: AddressDereference addressDereference = new AddressDereference(); addressDereference.Address = this.PopOperandStack(); addressDereference.Alignment = this.alignment; addressDereference.IsVolatile = this.sawVolatile; target.Definition = addressDereference; var pointerType = addressDereference.Address.Type as IPointerTypeReference; if (pointerType != null) addressDereference.Type = pointerType.TargetType; else { var managedPointerType = addressDereference.Address.Type as IManagedPointerTypeReference; if (managedPointerType != null) addressDereference.Type = managedPointerType.TargetType; else { //The pointer itself is untyped, so the instruction must have specified the element type addressDereference.Type = elementType??this.platformType.SystemObject; } } target.Type = addressDereference.Type; break; case OperationCode.Stloc: case OperationCode.Stloc_0: case OperationCode.Stloc_1: case OperationCode.Stloc_2: case OperationCode.Stloc_3: case OperationCode.Stloc_S: Contract.Assume(currentOperation.Value is ILocalDefinition); var local = this.GetLocalWithSourceName((ILocalDefinition)currentOperation.Value); target.Definition = local; this.numberOfAssignmentsToLocal[local] = this.numberOfAssignmentsToLocal.ContainsKey(local) ? this.numberOfAssignmentsToLocal[local] + 1 : 1; target.Type = local.Type; break; default: { var definition = currentOperation.Value; Contract.Assume(definition is ILocalDefinition || definition is IParameterDefinition || definition is IFieldReference || definition is IArrayIndexer || definition is IAddressDereference || definition is IPropertyDefinition); target.Definition = definition; break; } } assignment.Source = TypeInferencer.Convert(assignment.Source, target.Type); //mainly to convert (u)ints to bools, chars and pointers. assignment.Type = target.Type; Contract.Assume(assignment.Target.Type.TypeCode != PrimitiveTypeCode.Boolean || assignment.Source.Type.TypeCode == PrimitiveTypeCode.Boolean || IsByRef(assignment.Target.Definition)); this.alignment = 0; this.sawVolatile = false; return result; }
/// <summary> /// For a string field, s, the source expression e.s += "" /// turns into a specific pattern. /// That pattern here looks like: /// i: push e /// i+1: push dup.s /// i+2: (!= dup (default_value string)) ? goto L2 : empty /// i+3: L1 /// i+4: pop /// i+5: push "" /// i+6: L2 /// i+7: pop.s = pop /// </summary> private bool ReplacePlusAssignForStringPattern(BlockStatement b) { Contract.Requires(b != null); bool replacedPattern = false; var statements = b.Statements; for (int i = 0; i < statements.Count - 7; i++) { var push1 = statements[i] as PushStatement; if (push1 == null) continue; var push2 = statements[i + 1] as PushStatement; if (push2 == null) continue; var boundExpression = push2.ValueToPush as IBoundExpression; if (boundExpression == null) continue; var dupValue = boundExpression.Instance as IDupValue; if (dupValue == null) continue; var field = boundExpression.Definition as IFieldReference; if (field == null) continue; var conditionalStatement = statements[i + 2] as IConditionalStatement; if (conditionalStatement == null) continue; var notEquality = conditionalStatement.Condition as INotEquality; if (notEquality == null) continue; var gotoStatement = conditionalStatement.TrueBranch as IGotoStatement; if (gotoStatement == null) continue; var branchTarget = gotoStatement.TargetStatement; var emptyStatement = conditionalStatement.FalseBranch as IEmptyStatement; if (emptyStatement == null) continue; var labeledStatement = statements[i + 3] as ILabeledStatement; if (labeledStatement == null) continue; var popStatement = statements[i + 4] as IExpressionStatement; if (popStatement == null) continue; if (!(popStatement.Expression is IPopValue)) continue; var pushEmptyString = statements[i + 5] as IPushStatement; if (pushEmptyString == null) continue; var emptyString = pushEmptyString.ValueToPush as ICompileTimeConstant; if (emptyString == null) continue; if (emptyString.Type.TypeCode != PrimitiveTypeCode.String) continue; if ((string)emptyString.Value != "") continue; labeledStatement = statements[i + 6] as ILabeledStatement; if (labeledStatement == null) continue; if (labeledStatement.Label != branchTarget.Label) continue; var assignStatement = statements[i + 7] as IExpressionStatement; if (assignStatement == null) continue; var assignment = assignStatement.Expression as IAssignment; if (assignment == null) continue; if (!(assignment.Source is IPopValue)) continue; if (!(assignment.Target.Instance is IPopValue)) continue; // REVIEW: should the definition of the target be checked to be the same as "field"? If so, how? var plusEqual = new Addition() { LeftOperand = new TargetExpression() { Definition = assignment.Target.Definition, Instance = push1.ValueToPush, }, RightOperand = emptyString, ResultIsUnmodifiedLeftOperand = false, Type = assignment.Type, }; statements[i] = new ExpressionStatement() { Expression = plusEqual, Locations = new List<ILocation>(push1.Locations), }; statements.RemoveRange(i + 1, 7); replacedPattern = true; } return replacedPattern; }
/// <summary> /// Parse instructions and put them into an expression tree until an assignment, void call, branch target, or branch is encountered. /// Returns true if the parsed statement is last of the current basic block. This happens when the next statement is a branch /// target, or if the parsed statement could transfers control to anything but the following statement. /// </summary> private void ParseInstruction(BasicBlock currentBlock) { Statement/*?*/ statement = null; Expression/*?*/ expression = null; IOperation currentOperation = this.operationEnumerator.Current; OperationCode currentOpcode = currentOperation.OperationCode; if (this.host.PreserveILLocations) { if (this.lastLocation == null) this.lastLocation = currentOperation.Location; } else { if (this.sourceLocationProvider != null && this.lastSourceLocation == null) { foreach (var sourceLocation in this.sourceLocationProvider.GetPrimarySourceLocationsFor(currentOperation.Location)) { if (sourceLocation.StartLine != 0x00feefee) { this.lastSourceLocation = sourceLocation; break; } } } } switch (currentOpcode) { case OperationCode.Add: case OperationCode.Add_Ovf: case OperationCode.Add_Ovf_Un: case OperationCode.And: case OperationCode.Ceq: case OperationCode.Cgt: case OperationCode.Cgt_Un: case OperationCode.Clt: case OperationCode.Clt_Un: case OperationCode.Div: case OperationCode.Div_Un: case OperationCode.Mul: case OperationCode.Mul_Ovf: case OperationCode.Mul_Ovf_Un: case OperationCode.Or: case OperationCode.Rem: case OperationCode.Rem_Un: case OperationCode.Shl: case OperationCode.Shr: case OperationCode.Shr_Un: case OperationCode.Sub: case OperationCode.Sub_Ovf: case OperationCode.Sub_Ovf_Un: case OperationCode.Xor: expression = this.ParseBinaryOperation(currentOpcode); break; case OperationCode.Arglist: expression = new RuntimeArgumentHandleExpression(); break; case OperationCode.Array_Addr: case OperationCode.Ldelema: expression = this.ParseArrayElementAddres(currentOperation); break; case OperationCode.Array_Create: case OperationCode.Array_Create_WithLowerBound: case OperationCode.Newarr: expression = this.ParseArrayCreate(currentOperation); break; case OperationCode.Array_Get: case OperationCode.Ldelem: case OperationCode.Ldelem_I: case OperationCode.Ldelem_I1: case OperationCode.Ldelem_I2: case OperationCode.Ldelem_I4: case OperationCode.Ldelem_I8: case OperationCode.Ldelem_R4: case OperationCode.Ldelem_R8: case OperationCode.Ldelem_Ref: case OperationCode.Ldelem_U1: case OperationCode.Ldelem_U2: case OperationCode.Ldelem_U4: expression = this.ParseArrayIndexer(currentOperation); break; case OperationCode.Array_Set: statement = this.ParseArraySet(currentOperation); break; case OperationCode.Beq: case OperationCode.Beq_S: case OperationCode.Bge: case OperationCode.Bge_S: case OperationCode.Bge_Un: case OperationCode.Bge_Un_S: case OperationCode.Bgt: case OperationCode.Bgt_S: case OperationCode.Bgt_Un: case OperationCode.Bgt_Un_S: case OperationCode.Ble: case OperationCode.Ble_S: case OperationCode.Ble_Un: case OperationCode.Ble_Un_S: case OperationCode.Blt: case OperationCode.Blt_S: case OperationCode.Blt_Un: case OperationCode.Blt_Un_S: case OperationCode.Bne_Un: case OperationCode.Bne_Un_S: statement = this.ParseBinaryConditionalBranch(currentOperation); break; case OperationCode.Box: expression = this.ParseConversion(currentOperation); break; case OperationCode.Br: case OperationCode.Br_S: case OperationCode.Leave: case OperationCode.Leave_S: statement = this.ParseUnconditionalBranch(currentOperation); break; case OperationCode.Break: statement = new DebuggerBreakStatement(); break; case OperationCode.Brfalse: case OperationCode.Brfalse_S: case OperationCode.Brtrue: case OperationCode.Brtrue_S: statement = this.ParseUnaryConditionalBranch(currentOperation); break; case OperationCode.Call: case OperationCode.Callvirt: MethodCall call = this.ParseCall(currentOperation); if (call.MethodToCall.Type.TypeCode == PrimitiveTypeCode.Void) { call.Locations.Add(currentOperation.Location); // turning it into a statement prevents the location from being attached to the expresssion ExpressionStatement es = new ExpressionStatement(); es.Expression = call; statement = es; } else expression = call; break; case OperationCode.Calli: expression = this.ParsePointerCall(currentOperation); break; case OperationCode.Castclass: case OperationCode.Conv_I: case OperationCode.Conv_I1: case OperationCode.Conv_I2: case OperationCode.Conv_I4: case OperationCode.Conv_I8: case OperationCode.Conv_Ovf_I: case OperationCode.Conv_Ovf_I_Un: case OperationCode.Conv_Ovf_I1: case OperationCode.Conv_Ovf_I1_Un: case OperationCode.Conv_Ovf_I2: case OperationCode.Conv_Ovf_I2_Un: case OperationCode.Conv_Ovf_I4: case OperationCode.Conv_Ovf_I4_Un: case OperationCode.Conv_Ovf_I8: case OperationCode.Conv_Ovf_I8_Un: case OperationCode.Conv_Ovf_U: case OperationCode.Conv_Ovf_U_Un: case OperationCode.Conv_Ovf_U1: case OperationCode.Conv_Ovf_U1_Un: case OperationCode.Conv_Ovf_U2: case OperationCode.Conv_Ovf_U2_Un: case OperationCode.Conv_Ovf_U4: case OperationCode.Conv_Ovf_U4_Un: case OperationCode.Conv_Ovf_U8: case OperationCode.Conv_Ovf_U8_Un: case OperationCode.Conv_R_Un: case OperationCode.Conv_R4: case OperationCode.Conv_R8: case OperationCode.Conv_U: case OperationCode.Conv_U1: case OperationCode.Conv_U2: case OperationCode.Conv_U4: case OperationCode.Conv_U8: case OperationCode.Unbox: case OperationCode.Unbox_Any: expression = this.ParseConversion(currentOperation); break; case OperationCode.Ckfinite: this.PopOperandStack(); Debug.Assert(false); //if code out there actually uses this, I need to know sooner rather than later. //TODO: need a code model statement for this instruction. break; case OperationCode.Constrained_: //This prefix is redundant and is not represented in the code model. break; case OperationCode.Cpblk: var copyMemory = new CopyMemoryStatement(); copyMemory.NumberOfBytesToCopy = this.PopOperandStack(); copyMemory.SourceAddress = this.PopOperandStack(); copyMemory.TargetAddress = this.PopOperandStack(); statement = copyMemory; break; case OperationCode.Cpobj: expression = this.ParseCopyObject(); break; case OperationCode.Dup: statement = this.ParseDup(); break; case OperationCode.Endfilter: statement = this.ParseEndfilter(); break; case OperationCode.Endfinally: statement = new EndFinally(); break; case OperationCode.Initblk: var fillMemory = new FillMemoryStatement(); fillMemory.NumberOfBytesToFill = this.PopOperandStack(); fillMemory.FillValue = this.PopOperandStack(); fillMemory.TargetAddress = this.PopOperandStack(); statement = fillMemory; break; case OperationCode.Initobj: statement = this.ParseInitObject(currentOperation); break; case OperationCode.Isinst: expression = this.ParseCastIfPossible(currentOperation); break; case OperationCode.Jmp: Debug.Assert(false); //if code out there actually uses this, I need to know sooner rather than later. //TODO: need a code model statement for this instruction. break; case OperationCode.Ldarg: case OperationCode.Ldarg_0: case OperationCode.Ldarg_1: case OperationCode.Ldarg_2: case OperationCode.Ldarg_3: case OperationCode.Ldarg_S: case OperationCode.Ldloc: case OperationCode.Ldloc_0: case OperationCode.Ldloc_1: case OperationCode.Ldloc_2: case OperationCode.Ldloc_3: case OperationCode.Ldloc_S: case OperationCode.Ldfld: case OperationCode.Ldsfld: expression = this.ParseBoundExpression(currentOperation); break; case OperationCode.Ldarga: case OperationCode.Ldarga_S: case OperationCode.Ldflda: case OperationCode.Ldsflda: case OperationCode.Ldloca: case OperationCode.Ldloca_S: case OperationCode.Ldftn: case OperationCode.Ldvirtftn: expression = this.ParseAddressOf(currentOperation); break; case OperationCode.Ldc_I4: case OperationCode.Ldc_I4_0: case OperationCode.Ldc_I4_1: case OperationCode.Ldc_I4_2: case OperationCode.Ldc_I4_3: case OperationCode.Ldc_I4_4: case OperationCode.Ldc_I4_5: case OperationCode.Ldc_I4_6: case OperationCode.Ldc_I4_7: case OperationCode.Ldc_I4_8: case OperationCode.Ldc_I4_M1: case OperationCode.Ldc_I4_S: case OperationCode.Ldc_I8: case OperationCode.Ldc_R4: case OperationCode.Ldc_R8: case OperationCode.Ldnull: case OperationCode.Ldstr: expression = this.ParseCompileTimeConstant(currentOperation); break; case OperationCode.Ldind_I: case OperationCode.Ldind_I1: case OperationCode.Ldind_I2: case OperationCode.Ldind_I4: case OperationCode.Ldind_I8: case OperationCode.Ldind_R4: case OperationCode.Ldind_R8: case OperationCode.Ldind_Ref: case OperationCode.Ldind_U1: case OperationCode.Ldind_U2: case OperationCode.Ldind_U4: case OperationCode.Ldobj: expression = this.ParseAddressDereference(currentOperation); break; case OperationCode.Ldlen: expression = this.ParseVectorLength(); break; case OperationCode.Ldtoken: expression = ParseToken(currentOperation); break; case OperationCode.Localloc: expression = this.ParseStackArrayCreate(); break; case OperationCode.Mkrefany: expression = this.ParseMakeTypedReference(currentOperation); break; case OperationCode.Neg: expression = this.ParseUnaryOperation(new UnaryNegation()); break; case OperationCode.Not: expression = this.ParseUnaryOperation(new OnesComplement()); break; case OperationCode.Newobj: expression = this.ParseCreateObjectInstance(currentOperation); break; case OperationCode.No_: Debug.Assert(false); //if code out there actually uses this, I need to know sooner rather than later. //TODO: need object model support break; case OperationCode.Nop: statement = new EmptyStatement(); break; case OperationCode.Pop: statement = this.ParsePop(); break; case OperationCode.Readonly_: this.sawReadonly = true; break; case OperationCode.Refanytype: expression = this.ParseGetTypeOfTypedReference(); break; case OperationCode.Refanyval: expression = this.ParseGetValueOfTypedReference(currentOperation); break; case OperationCode.Ret: statement = this.ParseReturn(); break; case OperationCode.Rethrow: statement = new RethrowStatement(); break; case OperationCode.Sizeof: expression = ParseSizeOf(currentOperation); break; case OperationCode.Starg: case OperationCode.Starg_S: case OperationCode.Stelem: case OperationCode.Stelem_I: case OperationCode.Stelem_I1: case OperationCode.Stelem_I2: case OperationCode.Stelem_I4: case OperationCode.Stelem_I8: case OperationCode.Stelem_R4: case OperationCode.Stelem_R8: case OperationCode.Stelem_Ref: case OperationCode.Stfld: case OperationCode.Stind_I: case OperationCode.Stind_I1: case OperationCode.Stind_I2: case OperationCode.Stind_I4: case OperationCode.Stind_I8: case OperationCode.Stind_R4: case OperationCode.Stind_R8: case OperationCode.Stind_Ref: case OperationCode.Stloc: case OperationCode.Stloc_0: case OperationCode.Stloc_1: case OperationCode.Stloc_2: case OperationCode.Stloc_3: case OperationCode.Stloc_S: case OperationCode.Stobj: case OperationCode.Stsfld: statement = this.ParseAssignment(currentOperation); break; case OperationCode.Switch: statement = this.ParseSwitchInstruction(currentOperation); break; case OperationCode.Tail_: this.sawTailCall = true; break; case OperationCode.Throw: statement = this.ParseThrow(); break; case OperationCode.Unaligned_: this.alignment = (byte)currentOperation.Value; break; case OperationCode.Volatile_: this.sawVolatile = true; break; } if (expression != null) { if (this.host.PreserveILLocations) { expression.Locations.Add(currentOperation.Location); } this.operandStack.Push(expression); } else if (statement != null) { this.TurnOperandStackIntoPushStatements(currentBlock); currentBlock.Statements.Add(statement); if (this.host.PreserveILLocations) { if (this.lastLocation != null) { statement.Locations.Add(this.lastLocation); this.lastLocation = null; } } else if (this.lastSourceLocation != null) { statement.Locations.Add(this.lastSourceLocation); this.lastSourceLocation = null; } } }
/// <summary> /// Visits the specified expression statement. /// </summary> /// <param name="expressionStatement">The expression statement.</param> public override void Visit(IExpressionStatement expressionStatement) { ExpressionStatement mutableExpressionStatement = new ExpressionStatement(expressionStatement); this.resultStatement = this.myCodeCopier.DeepCopy(mutableExpressionStatement); }
private void TurnOperandStackIntoPushStatements(BasicBlock currentBlock) { int insertPoint = currentBlock.Statements.Count; while (this.operandStack.Count > 0) { Expression operand = this.PopOperandStack(); MethodCall/*?*/ call = operand as MethodCall; if (call != null && call.MethodToCall.Type.TypeCode == PrimitiveTypeCode.Void) { ExpressionStatement expressionStatement = new ExpressionStatement(); expressionStatement.Expression = operand; currentBlock.Statements.Insert(insertPoint, expressionStatement); } else { PushStatement push = new PushStatement(); push.ValueToPush = operand; currentBlock.Statements.Insert(insertPoint, push); } } }
/// <summary> /// Visits the specified expression statement. /// </summary> /// <param name="expressionStatement">The expression statement.</param> /// <returns></returns> protected virtual IStatement DeepCopy(ExpressionStatement expressionStatement) { expressionStatement.Expression = Substitute(expressionStatement.Expression); return expressionStatement; }
private Statement ParseAssignment(IOperation currentOperation) { TargetExpression target = new TargetExpression(); ITypeReference/*?*/ elementType = null; target.Alignment = this.alignment; target.Definition = currentOperation.Value; target.IsVolatile = this.sawVolatile; Assignment assignment = new Assignment(); assignment.Target = target; assignment.Source = this.PopOperandStack(); ExpressionStatement result = new ExpressionStatement(); result.Expression = assignment; switch (currentOperation.OperationCode) { case OperationCode.Stfld: target.Instance = this.PopOperandStack(); break; case OperationCode.Stelem: case OperationCode.Stelem_I: case OperationCode.Stelem_I1: case OperationCode.Stelem_I2: case OperationCode.Stelem_I4: case OperationCode.Stelem_I8: case OperationCode.Stelem_R4: case OperationCode.Stelem_R8: case OperationCode.Stelem_Ref: ArrayIndexer indexer = this.ParseArrayIndexer(currentOperation); target.Definition = indexer; target.Instance = indexer.IndexedObject; break; case OperationCode.Stind_I: elementType = this.platformType.SystemIntPtr; goto case OperationCode.Stind_Ref; case OperationCode.Stind_I1: elementType = this.platformType.SystemInt8; goto case OperationCode.Stind_Ref; case OperationCode.Stind_I2: elementType = this.platformType.SystemInt16; goto case OperationCode.Stind_Ref; case OperationCode.Stind_I4: elementType = this.platformType.SystemInt32; goto case OperationCode.Stind_Ref; case OperationCode.Stind_I8: elementType = this.platformType.SystemInt64; goto case OperationCode.Stind_Ref; case OperationCode.Stind_R4: elementType = this.platformType.SystemFloat32; goto case OperationCode.Stind_Ref; case OperationCode.Stind_R8: elementType = this.platformType.SystemFloat64; goto case OperationCode.Stind_Ref; case OperationCode.Stind_Ref: case OperationCode.Stobj: AddressDereference addressDereference = new AddressDereference(); addressDereference.Address = this.PopOperandStack(); addressDereference.Alignment = this.alignment; addressDereference.IsVolatile = this.sawVolatile; //capture the element type. The pointer might be untyped, in which case the instruction is the only point where the element type is known. if (elementType != null) addressDereference.Type = elementType; //else: The type inferencer will fill in the type once the pointer type is known. target.Definition = addressDereference; break; case OperationCode.Stloc: case OperationCode.Stloc_0: case OperationCode.Stloc_1: case OperationCode.Stloc_2: case OperationCode.Stloc_3: case OperationCode.Stloc_S: var local = this.GetLocalWithSourceName((ILocalDefinition)target.Definition); target.Definition = local; this.numberOfAssignments[local] = this.numberOfAssignments.ContainsKey(local) ? this.numberOfAssignments[local] + 1 : 1; break; } this.alignment = 0; this.sawVolatile = false; return result; }
public override void RewriteChildren(MethodDefinition methodDefinition) { IMethodContract methodContract = this.contractProvider.GetMethodContractFor(methodDefinition); if (methodContract == null) return; ISourceMethodBody sourceMethodBody = methodDefinition.Body as ISourceMethodBody; if (sourceMethodBody == null) return; List<IStatement> contractStatements = new List<IStatement>(); foreach (var precondition in methodContract.Preconditions) { var methodCall = new MethodCall() { Arguments = new List<IExpression> { precondition.Condition, }, IsStaticCall = true, MethodToCall = this.contractProvider.ContractMethods.Requires, Type = systemVoid, Locations = new List<ILocation>(precondition.Locations), }; ExpressionStatement es = new ExpressionStatement() { Expression = methodCall }; contractStatements.Add(es); } foreach (var postcondition in methodContract.Postconditions) { var methodCall = new MethodCall() { Arguments = new List<IExpression> { this.Rewrite(postcondition.Condition), }, IsStaticCall = true, MethodToCall = this.contractProvider.ContractMethods.Ensures, Type = systemVoid, Locations = new List<ILocation>(postcondition.Locations), }; ExpressionStatement es = new ExpressionStatement() { Expression = methodCall }; contractStatements.Add(es); } List<IStatement> existingStatements = new List<IStatement>(sourceMethodBody.Block.Statements); existingStatements = this.Rewrite(existingStatements); // keep the call to the base constructor at the top if (methodDefinition.IsConstructor && existingStatements.Count > 0) { contractStatements.Insert(0, existingStatements[0]); existingStatements.RemoveAt(0); } contractStatements.AddRange(existingStatements); // replaces assert/assume var newSourceMethodBody = new SourceMethodBody(this.host, this.sourceLocationProvider) { Block = new BlockStatement() { Statements = contractStatements, }, IsNormalized = false, LocalsAreZeroed = sourceMethodBody.LocalsAreZeroed, MethodDefinition = methodDefinition, }; methodDefinition.Body = newSourceMethodBody; return; }