private void VisitAssignment(ITargetExpression target, IExpression source, SourceTraverser sourceTraverser,
      bool treatAsStatement, bool pushTargetRValue, bool resultIsInitialTargetRValue) {
      Contract.Requires(target != null);
      Contract.Requires(source != null);
      Contract.Requires(sourceTraverser != null);
      Contract.Requires(!resultIsInitialTargetRValue || pushTargetRValue);
      Contract.Requires(!pushTargetRValue || source is IBinaryOperation);

      var tok = source.Token();
      var typ = source.Type;
      var structCopy = TranslationHelper.IsStruct(typ) && !(source is IDefaultValue);
      // then a struct value of type S is being assigned: "lhs := s"
      // model this as the statement "call lhs := S..#copy_ctor(s)" that does the bit-wise copying
      Bpl.DeclWithFormals proc = null;
      if (structCopy) {
        proc = this.sink.FindOrCreateProcedureForStructCopy(typ);
      }

      object container = target.Definition;

      Top:

      ILocalDefinition/*?*/ local = container as ILocalDefinition;
      if (local != null) {
        if (source is IDefaultValue && !local.Type.ResolvedType.IsReferenceType) {
        //  this.LoadAddressOf(local, null);
        //  this.generator.Emit(OperationCode.Initobj, local.Type);
        //  if (!treatAsStatement) this.LoadLocal(local);
        } else {
          Bpl.IdentifierExpr temp = null;
          var bplLocal = Bpl.Expr.Ident(this.sink.FindOrCreateLocalVariable(local));
          if (pushTargetRValue) {
            this.TranslatedExpressions.Push(bplLocal);
            if (!treatAsStatement && resultIsInitialTargetRValue) {
              var loc = this.sink.CreateFreshLocal(source.Type);
              temp = Bpl.Expr.Ident(loc);
              var e3 = this.TranslatedExpressions.Pop();
              var cmd3 = Bpl.Cmd.SimpleAssign(tok, temp, e3);
              this.StmtTraverser.StmtBuilder.Add(cmd3);
              this.TranslatedExpressions.Push(temp);
            }
          }
          sourceTraverser(source);
          var e = this.TranslatedExpressions.Pop();
          if (temp != null) this.TranslatedExpressions.Push(temp);

          Bpl.Cmd cmd;
          if (structCopy) {
            cmd = new Bpl.CallCmd(tok, proc.Name, new List<Bpl.Expr> { e, }, new List<Bpl.IdentifierExpr> { bplLocal, });
          } else {
            cmd = Bpl.Cmd.SimpleAssign(tok, bplLocal, e);
          }
          StmtTraverser.StmtBuilder.Add(cmd);

          if (!treatAsStatement && !resultIsInitialTargetRValue) {
            this.TranslatedExpressions.Push(bplLocal);
          }
        }
        return;
      }
      IParameterDefinition/*?*/ parameter = container as IParameterDefinition;
      if (parameter != null) {
        if (source is IDefaultValue && !parameter.Type.ResolvedType.IsReferenceType) {
          //this.LoadAddressOf(parameter, null);
          //this.generator.Emit(OperationCode.Initobj, parameter.Type);
          //if (!treatAsStatement) this.LoadParameter(parameter);
        } else {
          Bpl.IdentifierExpr temp = null;
          if (pushTargetRValue) {
            this.LoadParameter(parameter);
            if (!treatAsStatement && resultIsInitialTargetRValue) {
              var loc = this.sink.CreateFreshLocal(source.Type);
              temp = Bpl.Expr.Ident(loc);
              var e3 = this.TranslatedExpressions.Pop();
              var cmd3 = Bpl.Cmd.SimpleAssign(tok, temp, e3);
              this.StmtTraverser.StmtBuilder.Add(cmd3);
              this.TranslatedExpressions.Push(temp);
            }
          }
          sourceTraverser(source);
          var e = this.TranslatedExpressions.Pop();
          if (temp != null) this.TranslatedExpressions.Push(temp);
          var bplParam = Bpl.Expr.Ident(this.sink.FindParameterVariable(parameter, this.contractContext));

          Bpl.Cmd cmd;
          if (structCopy) {
            cmd = new Bpl.CallCmd(tok, proc.Name, new List<Bpl.Expr> { e, bplParam, }, new List<Bpl.IdentifierExpr>());
          } else {
            cmd = Bpl.Cmd.SimpleAssign(tok, bplParam, e);
          }
          StmtTraverser.StmtBuilder.Add(cmd);

          if (!treatAsStatement && !resultIsInitialTargetRValue) {
            this.LoadParameter(parameter);
          }
        }
        return;
      }
      IFieldReference/*?*/ field = container as IFieldReference;
      if (field != null) {

        var f = Bpl.Expr.Ident(this.sink.FindOrCreateFieldVariable(field));
        var boogieTypeOfField = sink.CciTypeToBoogie(field.Type);

        if (source is IDefaultValue && !field.Type.ResolvedType.IsReferenceType) {
          //this.LoadAddressOf(field, target.Instance);
          //if (!treatAsStatement) {
          //  this.generator.Emit(OperationCode.Dup);
          //  this.StackSize++;
          //}
          //this.generator.Emit(OperationCode.Initobj, field.Type);
          //if (!treatAsStatement)
          //  this.generator.Emit(OperationCode.Ldobj, field.Type);
          //else
          //  this.StackSize--;
        } else {
          Bpl.Expr x = null;
          Bpl.IdentifierExpr temp = null;
          if (pushTargetRValue) {
            if (target.Instance != null) {
              this.Traverse(target.Instance);
              x = this.TranslatedExpressions.Pop();
              AssertOrAssumeNonNull(tok, x);
              var e2 = this.sink.Heap.ReadHeap(x, f, TranslationHelper.IsStruct(field.ContainingType) ? AccessType.Struct : AccessType.Heap, boogieTypeOfField);
              this.TranslatedExpressions.Push(e2);
            } else {
              TranslatedExpressions.Push(f);
            }
            
            if (!treatAsStatement && resultIsInitialTargetRValue) {
              var loc = this.sink.CreateFreshLocal(source.Type);
              temp = Bpl.Expr.Ident(loc);
              var e3 = this.TranslatedExpressions.Pop();
              var cmd = Bpl.Cmd.SimpleAssign(tok, temp, e3);
              this.StmtTraverser.StmtBuilder.Add(cmd);
              this.TranslatedExpressions.Push(temp);
            }
          }
          sourceTraverser(source);
          if (!treatAsStatement && !resultIsInitialTargetRValue) {
            var loc = this.sink.CreateFreshLocal(source.Type);
            temp = Bpl.Expr.Ident(loc);
            var e3 = this.TranslatedExpressions.Pop();
            var cmd = Bpl.Cmd.SimpleAssign(tok, temp, e3);
            this.StmtTraverser.StmtBuilder.Add(cmd);
            this.TranslatedExpressions.Push(temp);
          }

          var e = this.TranslatedExpressions.Pop();
          if (temp != null) this.TranslatedExpressions.Push(temp);

          if (target.Instance == null) {
            // static fields are not kept in the heap
            StmtTraverser.StmtBuilder.Add(Bpl.Cmd.SimpleAssign(tok, f, e));
          } else {
            this.sink.Heap.WriteHeap(tok, x, f, e,
              field.ResolvedField.ContainingType.ResolvedType.IsStruct ? AccessType.Struct : AccessType.Heap,
              boogieTypeOfField, StmtTraverser.StmtBuilder);
          }

        }
        return;
      }

      VisitArrayIndexer:

      IArrayIndexer/*?*/ arrayIndexer = container as IArrayIndexer;
      if (arrayIndexer != null) {
        Contract.Assume(arrayIndexer.Indices.Count() == 1); // BUG: deal with multi-dimensional arrays
        if (source is IDefaultValue && !arrayIndexer.Type.ResolvedType.IsReferenceType) {
        //  this.LoadAddressOf(arrayIndexer, target.Instance);
        //  if (!treatAsStatement) {
        //    this.generator.Emit(OperationCode.Dup);
        //    this.StackSize++;
        //  }
        //  this.generator.Emit(OperationCode.Initobj, arrayIndexer.Type);
        //  if (!treatAsStatement)
        //    this.generator.Emit(OperationCode.Ldobj, arrayIndexer.Type);
        //  else
        //    this.StackSize--;
        } else {
          Bpl.IdentifierExpr/*?*/ temp = null;
          this.Traverse(arrayIndexer.IndexedObject);
          var arrayExpr = this.TranslatedExpressions.Peek();
          this.Traverse(arrayIndexer.Indices);
          var indexExpr = this.TranslatedExpressions.Peek();
          if (pushTargetRValue) {
            AssertOrAssumeNonNull(tok, arrayExpr);
            var e2 = this.sink.Heap.ReadHeap(arrayExpr, indexExpr, AccessType.Array, this.sink.CciTypeToBoogie(arrayIndexer.Type));
            this.TranslatedExpressions.Push(e2);

            if (!treatAsStatement && resultIsInitialTargetRValue) {
                var loc = this.sink.CreateFreshLocal(source.Type);
                temp = Bpl.Expr.Ident(loc);
                var e3 = this.TranslatedExpressions.Pop();
                var cmd = Bpl.Cmd.SimpleAssign(tok, temp, e3);
                this.StmtTraverser.StmtBuilder.Add(cmd);
                this.TranslatedExpressions.Push(temp);
            }
          }
          sourceTraverser(source);

          var e = this.TranslatedExpressions.Pop();
          var indices_prime = this.TranslatedExpressions.Pop();
          var x = this.TranslatedExpressions.Pop();
          sink.Heap.WriteHeap(Bpl.Token.NoToken, x, indices_prime, e, AccessType.Array, sink.CciTypeToBoogie(arrayIndexer.Type), StmtTraverser.StmtBuilder);

          if (!treatAsStatement && !resultIsInitialTargetRValue) {
            AssertOrAssumeNonNull(tok, arrayExpr);
            var e2 = this.sink.Heap.ReadHeap(arrayExpr, indexExpr, AccessType.Array, this.sink.CciTypeToBoogie(arrayIndexer.Type));
            this.TranslatedExpressions.Push(e2);
          } else {
            if (temp != null) this.TranslatedExpressions.Push(temp);
          }
        }
        return;
      }
      IAddressDereference/*?*/ addressDereference = container as IAddressDereference;
      if (addressDereference != null) {
        var addrOf = addressDereference.Address as IAddressOf;
        if (addrOf != null) {
          var arrayIndexer2 = addrOf.Expression.Definition as IArrayIndexer;
          if (arrayIndexer2 != null) {
            container = arrayIndexer2;
            goto VisitArrayIndexer;
          }
        }
        var be = addressDereference.Address as IBoundExpression;
        if (be != null) {
          container = be.Definition;
          goto Top;
        }
        this.Traverse(addressDereference.Address);
        if (source is IDefaultValue && !addressDereference.Type.ResolvedType.IsReferenceType) {
          //if (!treatAsStatement) {
          //  this.generator.Emit(OperationCode.Dup);
          //  this.StackSize++;
          //}
          //this.generator.Emit(OperationCode.Initobj, addressDereference.Type);
          //if (!treatAsStatement)
          //  this.generator.Emit(OperationCode.Ldobj, addressDereference.Type);
          //else
          //  this.StackSize--;
        } else if (source is IAddressDereference) {
          //if (!treatAsStatement) {
          //  this.generator.Emit(OperationCode.Dup);
          //  this.StackSize++;
          //}
          //this.Traverse(((IAddressDereference)source).Address);
          //this.generator.Emit(OperationCode.Cpobj, addressDereference.Type);
          //this.StackSize -= 2;
          //if (!treatAsStatement)
          //  this.generator.Emit(OperationCode.Ldobj, addressDereference.Type);
        } else {
          Bpl.IdentifierExpr/*?*/ temp = null;
          if (pushTargetRValue) {
            this.TranslatedExpressions.Push(this.TranslatedExpressions.Peek());
            if (!treatAsStatement && resultIsInitialTargetRValue) {
              this.TranslatedExpressions.Push(this.TranslatedExpressions.Peek());
              var loc = this.sink.CreateFreshLocal(source.Type);
              temp = Bpl.Expr.Ident(loc);
              var e3 = this.TranslatedExpressions.Pop();
              var cmd = Bpl.Cmd.SimpleAssign(tok, temp, e3);
              this.StmtTraverser.StmtBuilder.Add(cmd);
              this.TranslatedExpressions.Push(temp);
            }
          }
          sourceTraverser(source);
          if (!treatAsStatement && !resultIsInitialTargetRValue) {
            this.TranslatedExpressions.Push(this.TranslatedExpressions.Peek());
            var loc = this.sink.CreateFreshLocal(source.Type);
            temp = Bpl.Expr.Ident(loc);
            var e3 = this.TranslatedExpressions.Pop();
            var cmd = Bpl.Cmd.SimpleAssign(tok, temp, e3);
            this.StmtTraverser.StmtBuilder.Add(cmd);
            this.TranslatedExpressions.Push(temp);
          }
          //this.VisitAssignmentTo(addressDereference);
          if (temp != null) this.TranslatedExpressions.Push(temp);
        }
        return;
      }
      IPropertyDefinition/*?*/ propertyDefinition = container as IPropertyDefinition;
      if (propertyDefinition != null) {
        Contract.Assume(propertyDefinition.Getter != null && propertyDefinition.Setter != null);
        if (!propertyDefinition.IsStatic) {
          this.Traverse(target.Instance);
        }
        Bpl.IdentifierExpr temp = null;
        var token = Bpl.Token.NoToken;
        if (pushTargetRValue) {

          List<Bpl.Expr> inexpr;
          List<Bpl.IdentifierExpr> outvars;
          Bpl.IdentifierExpr thisExpr;
          Dictionary<Bpl.IdentifierExpr, Tuple<Bpl.IdentifierExpr, bool>> toBoxed;
          var proc2 = TranslateArgumentsAndReturnProcedure(token, propertyDefinition.Getter, propertyDefinition.Getter.ResolvedMethod, target.Instance, Enumerable<IExpression>.Empty, out inexpr, out outvars, out thisExpr, out toBoxed);

          EmitLineDirective(token);

          this.StmtTraverser.StmtBuilder.Add(new Bpl.CallCmd(token, proc2.Name, inexpr, outvars));

          if (!treatAsStatement && resultIsInitialTargetRValue) {
            //var 
            //this.generator.Emit(OperationCode.Dup);
            //this.StackSize++;
            //temp = new TemporaryVariable(source.Type, this.method);
            //this.VisitAssignmentTo(temp);
          }
        }
        sourceTraverser(source);
        if (!treatAsStatement && !resultIsInitialTargetRValue) {
          var e3 = this.TranslatedExpressions.Pop();
          var loc = this.sink.CreateFreshLocal(source.Type);
          temp = Bpl.Expr.Ident(loc);
          var cmd = Bpl.Cmd.SimpleAssign(tok, temp, e3);
          this.StmtTraverser.StmtBuilder.Add(cmd);
          this.TranslatedExpressions.Push(temp);
        }

        var setterArgs = new List<Bpl.Expr>();
        var setterArg = this.TranslatedExpressions.Pop();
        if (!propertyDefinition.IsStatic)
          setterArgs.Add(this.TranslatedExpressions.Pop());
        setterArgs.Add(setterArg);

        var setterProc = this.sink.FindOrCreateProcedure(propertyDefinition.Setter.ResolvedMethod);
        EmitLineDirective(token);
        this.StmtTraverser.StmtBuilder.Add(new Bpl.CallCmd(token, setterProc.Decl.Name, setterArgs, new List<Bpl.IdentifierExpr>()));

        if (temp != null) this.TranslatedExpressions.Push(temp);
        return;
      }
      Contract.Assume(false);
    }
Example #2
0
    private void VisitAssignment(ITargetExpression target, IExpression source, SourceTraverser sourceTraverser,
      bool treatAsStatement, bool pushTargetRValue, bool resultIsInitialTargetRValue) {
      Contract.Requires(target != null);
      Contract.Requires(source != null);
      Contract.Requires(sourceTraverser != null);
      Contract.Requires(!resultIsInitialTargetRValue || pushTargetRValue);
      Contract.Requires(!pushTargetRValue || source is IBinaryOperation);

      object container = target.Definition;
      ILocalDefinition/*?*/ local = container as ILocalDefinition;
      if (local != null) {
        if (source is IDefaultValue && !local.Type.ResolvedType.IsReferenceType) {
          this.LoadAddressOf(local, null);
          this.generator.Emit(OperationCode.Initobj, local.Type);
          this.StackSize--;
          if (!treatAsStatement) this.LoadLocal(local);
        } else {
          if (pushTargetRValue) {
            this.LoadLocal(local);
            if (!treatAsStatement && resultIsInitialTargetRValue) {
              this.generator.Emit(OperationCode.Dup);
              this.StackSize++;
            }
          }
          sourceTraverser(source);
          if (!treatAsStatement && !resultIsInitialTargetRValue) {
            this.generator.Emit(OperationCode.Dup);
            this.StackSize++;
          }
          this.VisitAssignmentTo(local);
        }
        return;
      }
      IParameterDefinition/*?*/ parameter = container as IParameterDefinition;
      if (parameter != null) {
        if (source is IDefaultValue && !parameter.Type.ResolvedType.IsReferenceType) {
          this.LoadAddressOf(parameter, null);
          this.generator.Emit(OperationCode.Initobj, parameter.Type);
          this.StackSize--;
          if (!treatAsStatement) this.LoadParameter(parameter);
        } else {
          if (pushTargetRValue) {
            this.LoadParameter(parameter);
            if (!treatAsStatement && resultIsInitialTargetRValue) {
              this.generator.Emit(OperationCode.Dup);
              this.StackSize++;
            }
          }
          sourceTraverser(source);
          if (!treatAsStatement && !resultIsInitialTargetRValue) {
            this.generator.Emit(OperationCode.Dup);
            this.StackSize++;
          }
          ushort parIndex = GetParameterIndex(parameter);
          if (parIndex <= byte.MaxValue) this.generator.Emit(OperationCode.Starg_S, parameter);
          else this.generator.Emit(OperationCode.Starg, parameter);
          this.StackSize--;
        }
        return;
      }
      IFieldReference/*?*/ field = container as IFieldReference;
      if (field != null) {
        if (source is IDefaultValue && !field.Type.ResolvedType.IsReferenceType) {
          this.LoadAddressOf(field, target.Instance);
          if (!treatAsStatement) {
            this.generator.Emit(OperationCode.Dup);
            this.StackSize++;
          }
          this.generator.Emit(OperationCode.Initobj, field.Type);
          if (!treatAsStatement)
            this.generator.Emit(OperationCode.Ldobj, field.Type);
          else
            this.StackSize--;
        } else {
          ILocalDefinition/*?*/ temp = null;
          if (target.Instance != null) {
            this.Traverse(target.Instance);
            if (pushTargetRValue) {
              this.generator.Emit(OperationCode.Dup);
              this.StackSize++;
            }
          }
          if (pushTargetRValue) {
            if (target.Instance != null)
              this.generator.Emit(OperationCode.Ldfld, field);
            else {
              this.generator.Emit(OperationCode.Ldsfld, field);
              this.StackSize++;
            }
            if (!treatAsStatement && resultIsInitialTargetRValue) {
              this.generator.Emit(OperationCode.Dup);
              this.StackSize++;
              temp = new TemporaryVariable(source.Type, this.method);
              this.VisitAssignmentTo(temp);
            }
          }
          
          sourceTraverser(source);
          if (!treatAsStatement && !resultIsInitialTargetRValue) {
            this.generator.Emit(OperationCode.Dup);
            this.StackSize++;
            temp = new TemporaryVariable(source.Type, this.method);
            this.VisitAssignmentTo(temp);
          }
          if (target.IsUnaligned)
            this.generator.Emit(OperationCode.Unaligned_, target.Alignment);
          if (target.IsVolatile)
            this.generator.Emit(OperationCode.Volatile_);
          if (target.Instance == null) {
            this.generator.Emit(OperationCode.Stsfld, field);
            this.StackSize--;
          } else {
            this.generator.Emit(OperationCode.Stfld, field);
            this.StackSize-=2;
          }
          if (temp != null) this.LoadLocal(temp);
        }
        return;
      }
      IArrayIndexer/*?*/ arrayIndexer = container as IArrayIndexer;
      if (arrayIndexer != null) {
        if (source is IDefaultValue && !arrayIndexer.Type.ResolvedType.IsReferenceType) {
          this.LoadAddressOf(arrayIndexer, target.Instance);
          if (!treatAsStatement) {
            this.generator.Emit(OperationCode.Dup);
            this.StackSize++;
          }
          this.generator.Emit(OperationCode.Initobj, arrayIndexer.Type);
          if (!treatAsStatement)
            this.generator.Emit(OperationCode.Ldobj, arrayIndexer.Type);
          else
            this.StackSize--;
        } else {
          ILocalDefinition/*?*/ temp = null;
          IArrayTypeReference arrayType = (IArrayTypeReference)target.Instance.Type;
          this.Traverse(target.Instance);
          this.Traverse(arrayIndexer.Indices);
          if (pushTargetRValue) {
            if (arrayType.IsVector)
              this.generator.Emit(OperationCode.Ldelema);
            else
              this.generator.Emit(OperationCode.Array_Addr, arrayType);
            this.generator.Emit(OperationCode.Dup); this.StackSize++;
            this.LoadIndirect(arrayType.ElementType);
            if (!treatAsStatement && resultIsInitialTargetRValue) {
              this.generator.Emit(OperationCode.Dup);
              this.StackSize++;
              temp = new TemporaryVariable(source.Type, this.method);
              this.VisitAssignmentTo(temp);
            }
          }
          sourceTraverser(source);
          if (!treatAsStatement && !resultIsInitialTargetRValue) {
            this.generator.Emit(OperationCode.Dup);
            this.StackSize++;
            temp = new TemporaryVariable(source.Type, this.method);
            this.VisitAssignmentTo(temp);
          }
          if (pushTargetRValue) {
            this.StoreIndirect(arrayType.ElementType);
          } else {
            if (arrayType.IsVector)
              this.StoreVectorElement(arrayType.ElementType);
            else {
              this.generator.Emit(OperationCode.Array_Set, arrayType);
              this.StackSize-=(ushort)(IteratorHelper.EnumerableCount(arrayIndexer.Indices)+2);
            }
          }
          if (temp != null) this.LoadLocal(temp);
        }
        return;
      }
      IAddressDereference/*?*/ addressDereference = container as IAddressDereference;
      if (addressDereference != null) {
        this.Traverse(addressDereference.Address);
        if (source is IDefaultValue && !addressDereference.Type.ResolvedType.IsReferenceType) {
          if (!treatAsStatement) {
            this.generator.Emit(OperationCode.Dup);
            this.StackSize++;
          }
          this.generator.Emit(OperationCode.Initobj, addressDereference.Type);
          if (!treatAsStatement)
            this.generator.Emit(OperationCode.Ldobj, addressDereference.Type);
          else
            this.StackSize--;
        } else if (source is IAddressDereference) {
          if (!treatAsStatement) {
            this.generator.Emit(OperationCode.Dup);
            this.StackSize++;
          }
          this.Traverse(((IAddressDereference)source).Address);
          this.generator.Emit(OperationCode.Cpobj, addressDereference.Type);
          this.StackSize-=2;
          if (!treatAsStatement)
            this.generator.Emit(OperationCode.Ldobj, addressDereference.Type);
        } else {
          ILocalDefinition/*?*/ temp = null;
          if (pushTargetRValue) {
            this.generator.Emit(OperationCode.Dup);
            this.StackSize++;
            if (addressDereference.IsUnaligned)
              this.generator.Emit(OperationCode.Unaligned_, addressDereference.Alignment);
            if (addressDereference.IsVolatile)
              this.generator.Emit(OperationCode.Volatile_);
            this.LoadIndirect(addressDereference.Type);
            if (!treatAsStatement && resultIsInitialTargetRValue) {
              this.generator.Emit(OperationCode.Dup);
              this.StackSize++;
              temp = new TemporaryVariable(source.Type, this.method);
              this.VisitAssignmentTo(temp);
            }
          }
          sourceTraverser(source);
          if (!treatAsStatement && !resultIsInitialTargetRValue) {
            this.generator.Emit(OperationCode.Dup);
            this.StackSize++;
            temp = new TemporaryVariable(source.Type, this.method);
            this.VisitAssignmentTo(temp);
          }
          this.VisitAssignmentTo(addressDereference);
          if (temp != null) this.LoadLocal(temp);
        }
        return;
      }
      IPropertyDefinition/*?*/ propertyDefinition = container as IPropertyDefinition;
      if (propertyDefinition != null) {
        Contract.Assume(propertyDefinition.Getter != null && propertyDefinition.Setter != null);
        if (!propertyDefinition.IsStatic) {
          this.Traverse(target.Instance);
        }
        ILocalDefinition temp = null;
        if (pushTargetRValue) {
          if (!propertyDefinition.IsStatic) {
            this.generator.Emit(OperationCode.Dup);
            this.StackSize++;
            this.generator.Emit(target.GetterIsVirtual ? OperationCode.Callvirt : OperationCode.Call, propertyDefinition.Getter);
          } else {
            this.generator.Emit(OperationCode.Call, propertyDefinition.Getter);
            this.StackSize++;
          }
          if (!treatAsStatement && resultIsInitialTargetRValue) {
            this.generator.Emit(OperationCode.Dup);
            this.StackSize++;
            temp = new TemporaryVariable(source.Type, this.method);
            this.VisitAssignmentTo(temp);
          }
        }
        sourceTraverser(source);
        if (!treatAsStatement && !resultIsInitialTargetRValue) {
          this.generator.Emit(OperationCode.Dup);
          this.StackSize++;
          temp = new TemporaryVariable(propertyDefinition.Type, this.method);
          this.VisitAssignmentTo(temp);
        }
        if (!propertyDefinition.IsStatic) {
          this.generator.Emit(target.SetterIsVirtual ? OperationCode.Callvirt : OperationCode.Call, propertyDefinition.Setter);
          this.StackSize -= 2;
        } else {
          this.generator.Emit(OperationCode.Call, propertyDefinition.Setter);
          this.StackSize--;
        }
        if (temp != null) this.LoadLocal(temp);
        return;
      }
      Contract.Assume(false);
    }