Inheritance: Statement, IExpressionStatement
 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);
 }
Example #3
0
 /// <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;
 }
Example #4
0
 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;
 }
Example #5
0
 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;
 }
Example #8
0
    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);
    }
Example #9
0
    /// <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;
    }
Example #10
0
 /// <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;
 }
Example #11
0
 /// <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;
 }
Example #12
0
 /// <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;
 }
Example #13
0
 /// <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;
 }
Example #14
0
 /// <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
   }
 }
Example #15
0
 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);
      }
    }
Example #18
0
        /// <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;
 }
Example #24
0
    /// <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;
    }
Example #25
0
        /// <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;
            }
              }
        }
Example #26
0
 /// <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);
 }
Example #27
0
 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);
     }
       }
 }
Example #28
0
 /// <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;
 }
Example #29
0
 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;
 }
Example #30
0
 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;
 }