Наследование: ILocalDefinition
Пример #1
0
 /// <summary>
 /// Generates IL for the specified default value.
 /// </summary>
 /// <param name="defaultValue">The default value.</param>
 public override void TraverseChildren(IDefaultValue defaultValue)
 {
     ILocalDefinition temp = new TemporaryVariable(defaultValue.Type, this.method);
       this.LoadAddressOf(temp, null);
       this.generator.Emit(OperationCode.Initobj, defaultValue.Type);
       this.StackSize--;
       this.LoadLocal(temp);
 }
Пример #2
0
        private void GenerateDownLevelLockStatement(ILockStatement lockStatement)
        {
            var systemThreading = new NestedUnitNamespaceReference(this.host.PlatformType.SystemObject.ContainingUnitNamespace,
            this.host.NameTable.GetNameFor("Threading"));
              var systemThreadingMonitor = new NamespaceTypeReference(this.host, systemThreading, this.host.NameTable.GetNameFor("Monitor"), 0,
            isEnum: false, isValueType: false, typeCode: PrimitiveTypeCode.NotPrimitive);
              var parameters = new IParameterTypeInformation[2];
              var monitorEnter = new MethodReference(this.host, systemThreadingMonitor, CallingConvention.Default, this.host.PlatformType.SystemVoid,
            this.host.NameTable.GetNameFor("Enter"), 0, this.host.PlatformType.SystemObject);
              var monitorExit = new MethodReference(this.host, systemThreadingMonitor, CallingConvention.Default, this.host.PlatformType.SystemVoid,
            this.host.NameTable.GetNameFor("Exit"), 0, this.host.PlatformType.SystemObject);

              this.EmitSequencePoint(lockStatement.Locations);
              var guardObject = new TemporaryVariable(lockStatement.Guard.Type, this.method);
              this.Traverse(lockStatement.Guard);
              this.generator.Emit(OperationCode.Dup); this.StackSize++;
              this.VisitAssignmentTo(guardObject);
              this.generator.Emit(OperationCode.Call, monitorEnter);
              this.StackSize--;
              //try
              var savedCurrentTryCatch = this.currentTryCatch;
              this.currentTryCatch = lockStatement;
              var savedCurrentTryCatchFinallyEnd = this.currentTryCatchFinallyEnd;
              this.currentTryCatchFinallyEnd = new ILGeneratorLabel();
              this.generator.BeginTryBody();
              this.Traverse(lockStatement.Body);
              if (!this.lastStatementWasUnconditionalTransfer)
            this.generator.Emit(OperationCode.Leave, this.currentTryCatchFinallyEnd);
              //finally
              this.generator.BeginFinallyBlock();
              //if (status)
              this.LoadLocal(guardObject);
              this.generator.Emit(OperationCode.Call, monitorExit);
              this.StackSize--;
              //monitor exit
              this.generator.Emit(OperationCode.Endfinally);
              this.generator.EndTryBody();
              this.generator.MarkLabel(this.currentTryCatchFinallyEnd);
              this.currentTryCatchFinallyEnd = savedCurrentTryCatchFinallyEnd;
              this.currentTryCatch = savedCurrentTryCatch;
              this.lastStatementWasUnconditionalTransfer = false;
        }
Пример #3
0
 private void LoadAddressOf(object container, IExpression/*?*/ instance, bool emitReadonlyPrefix)
 {
     this.StackSize++;
       ILocalDefinition/*?*/ local = container as ILocalDefinition;
       if (local != null) {
     ushort localIndex = this.GetLocalIndex(local);
     if (localIndex <= byte.MaxValue) this.generator.Emit(OperationCode.Ldloca_S, local);
     else this.generator.Emit(OperationCode.Ldloca, local);
     return;
       }
       IParameterDefinition/*?*/ parameter = container as IParameterDefinition;
       if (parameter != null) {
     ushort parIndex = GetParameterIndex(parameter);
     if (parIndex <= byte.MaxValue) this.generator.Emit(OperationCode.Ldarga_S, parameter);
     else this.generator.Emit(OperationCode.Ldarga, parameter);
     return;
       }
       IFieldReference/*?*/ field = container as IFieldReference;
       if (field != null) {
     if (instance == null)
       this.generator.Emit(OperationCode.Ldsflda, field);
     else {
       this.Traverse(instance);
       this.generator.Emit(OperationCode.Ldflda, field);
     }
     return;
       }
       IArrayIndexer/*?*/ arrayIndexer = container as IArrayIndexer;
       if (arrayIndexer != null) {
     this.Traverse(arrayIndexer.IndexedObject);
     this.Traverse(arrayIndexer.Indices);
     if (emitReadonlyPrefix)
       this.generator.Emit(OperationCode.Readonly_);
     IArrayTypeReference arrayType = (IArrayTypeReference)arrayIndexer.IndexedObject.Type;
     if (arrayType.IsVector)
       this.generator.Emit(OperationCode.Ldelema, arrayType.ElementType);
     else
       this.generator.Emit(OperationCode.Array_Addr, arrayType);
     return;
       }
       IAddressDereference/*?*/ addressDereference = container as IAddressDereference;
       if (addressDereference != null) {
     this.Traverse(addressDereference.Address);
     return;
       }
       IMethodReference/*?*/ method = container as IMethodReference;
       if (method != null) {
     if (instance != null) {
       this.Traverse(instance);
       this.generator.Emit(OperationCode.Ldvirtftn, method);
     } else
       this.generator.Emit(OperationCode.Ldftn, method);
     return;
       }
       IThisReference/*?*/ thisParameter = container as IThisReference;
       if (thisParameter != null) {
     this.generator.Emit(OperationCode.Ldarg_0);
     return;
       }
       IAddressableExpression/*?*/ addressableExpression = container as IAddressableExpression;
       if (addressableExpression != null) {
     this.LoadAddressOf(addressableExpression.Definition, addressableExpression.Instance);
     return;
       }
       ITargetExpression/*?*/ targetExpression = container as ITargetExpression;
       if (targetExpression != null) {
     this.LoadAddressOf(targetExpression.Definition, targetExpression.Instance);
     return;
       }
       IAddressOf addressOfExpression = container as IAddressOf;
       if (addressOfExpression != null) {
     this.LoadAddressOf(addressOfExpression.Expression, addressOfExpression);
     return;
       }
       IExpression/*?*/ expression = container as IExpression;
       if (expression != null) {
     TemporaryVariable temp = new TemporaryVariable(expression.Type, this.method);
     this.Traverse(expression);
     this.VisitAssignmentTo(temp);
     this.LoadAddressOf(temp, null);
     return;
       }
       Contract.Assume(false);
 }
Пример #4
0
        /// <summary>
        /// Generates IL code for the given for each statement for the special case where the collection is known
        /// to be vector type.
        /// </summary>
        /// <param name="forEachStatement">The foreach statement to visit.</param>
        /// <param name="arrayType">The vector type of the collection.</param>
        public virtual void VisitForeachArrayElement(IForEachStatement forEachStatement, IArrayTypeReference arrayType)
        {
            Contract.Requires(arrayType.IsVector);
              ILGeneratorLabel savedCurrentBreakTarget = this.currentBreakTarget;
              ILGeneratorLabel savedCurrentContinueTarget = this.currentContinueTarget;
              this.currentBreakTarget = new ILGeneratorLabel();
              this.currentContinueTarget = new ILGeneratorLabel();
              if (this.currentTryCatch != null) {
            this.mostNestedTryCatchFor.Add(this.currentBreakTarget, this.currentTryCatch);
            this.mostNestedTryCatchFor.Add(this.currentContinueTarget, this.currentTryCatch);
              }
              ILGeneratorLabel conditionCheck = new ILGeneratorLabel();
              ILGeneratorLabel loopStart = new ILGeneratorLabel();

              this.EmitSequencePoint(forEachStatement.Variable.Locations);
              this.Traverse(forEachStatement.Collection);
              this.generator.Emit(OperationCode.Dup);
              var array = new TemporaryVariable(arrayType, this.method);
              this.VisitAssignmentTo(array);
              var length = new TemporaryVariable(this.host.PlatformType.SystemInt32, this.method);
              this.generator.Emit(OperationCode.Ldlen);
              this.generator.Emit(OperationCode.Conv_I4);
              this.VisitAssignmentTo(length);
              var counter = new TemporaryVariable(this.host.PlatformType.SystemInt32, this.method);
              this.generator.Emit(OperationCode.Ldc_I4_0);
              this.StackSize++;
              this.VisitAssignmentTo(counter);
              this.generator.Emit(OperationCode.Br, conditionCheck);
              this.generator.MarkLabel(loopStart);
              this.LoadLocal(array);
              this.LoadLocal(counter);
              this.LoadVectorElement(arrayType.ElementType);
              this.VisitAssignmentTo(forEachStatement.Variable);
              this.Traverse(forEachStatement.Body);
              this.generator.MarkLabel(this.currentContinueTarget);
              this.LoadLocal(counter);
              this.generator.Emit(OperationCode.Ldc_I4_1);
              this.StackSize++;
              this.generator.Emit(OperationCode.Add);
              this.StackSize--;
              this.VisitAssignmentTo(counter);
              this.generator.MarkLabel(conditionCheck);
              this.EmitSequencePoint(forEachStatement.Collection.Locations);
              this.LoadLocal(counter);
              this.LoadLocal(length);
              this.generator.Emit(OperationCode.Blt, loopStart);
              this.generator.MarkLabel(this.currentBreakTarget);

              this.currentBreakTarget = savedCurrentBreakTarget;
              this.currentContinueTarget = savedCurrentContinueTarget;
        }
Пример #5
0
 /// <summary>
 /// Generates IL for the assignment.
 /// </summary>
 /// <param name="assignment">The assignment.</param>
 /// <param name="treatAsStatement">if set to <c>true</c> [treat as statement].</param>
 public virtual void VisitAssignment(IAssignment assignment, bool treatAsStatement)
 {
     object container = assignment.Target.Definition;
       ILocalDefinition/*?*/ local = container as ILocalDefinition;
       if (local != null) {
     if (assignment.Source is IDefaultValue && !local.Type.ResolvedType.IsReferenceType) {
       this.LoadAddressOf(local, null);
       this.generator.Emit(OperationCode.Initobj, local.Type);
     } else {
       this.Traverse(assignment.Source);
       this.VisitAssignmentTo(local);
     }
     if (!treatAsStatement) this.LoadLocal(local);
     return;
       }
       IParameterDefinition/*?*/ parameter = container as IParameterDefinition;
       if (parameter != null) {
     if (assignment.Source is IDefaultValue && !parameter.Type.ResolvedType.IsReferenceType) {
       this.LoadAddressOf(parameter, null);
       this.generator.Emit(OperationCode.Initobj, parameter.Type);
     } else {
       this.Traverse(assignment.Source);
       ushort parIndex = GetParameterIndex(parameter);
       if (parIndex <= byte.MaxValue) this.generator.Emit(OperationCode.Starg_S, parameter);
       else this.generator.Emit(OperationCode.Starg, parameter);
       this.StackSize--;
     }
     if (!treatAsStatement) this.LoadParameter(parameter);
     return;
       }
       IFieldReference/*?*/ field = container as IFieldReference;
       if (field != null) {
     if (assignment.Source is IDefaultValue && !field.Type.ResolvedType.IsReferenceType) {
       this.LoadAddressOf(field, assignment.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 {
       if (assignment.Target.Instance != null) {
     this.Traverse(assignment.Target.Instance);
     if (!treatAsStatement) {
       this.generator.Emit(OperationCode.Dup);
       this.StackSize++;
     }
       }
       this.Traverse(assignment.Source);
       if (assignment.Target.IsUnaligned)
     this.generator.Emit(OperationCode.Unaligned_, assignment.Target.Alignment);
       if (assignment.Target.IsVolatile)
     this.generator.Emit(OperationCode.Volatile_);
       if (assignment.Target.Instance == null) {
     this.generator.Emit(OperationCode.Stsfld, field);
     this.StackSize--;
       } else {
     this.generator.Emit(OperationCode.Stfld, field);
     this.StackSize-=2;
       }
       if (!treatAsStatement)
     this.LoadField(assignment.Target.IsUnaligned ? assignment.Target.Alignment : (byte)0, assignment.Target.IsVolatile, null, field, assignment.Target.Instance == null);
     }
     return;
       }
       IArrayIndexer/*?*/ arrayIndexer = container as IArrayIndexer;
       if (arrayIndexer != null) {
     if (assignment.Source is IDefaultValue && !arrayIndexer.Type.ResolvedType.IsReferenceType) {
       this.LoadAddressOf(arrayIndexer, assignment.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 {
       this.Traverse(assignment.Target.Instance);
       this.Traverse(arrayIndexer.Indices);
       this.Traverse(assignment.Source);
       ILocalDefinition/*?*/ temp = null;
       if (!treatAsStatement) {
     temp = new TemporaryVariable(assignment.Source.Type, this.method);
     this.VisitAssignmentTo(temp);
     this.LoadLocal(temp);
       }
       IArrayTypeReference arrayType = (IArrayTypeReference)assignment.Target.Instance.Type;
       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 (assignment.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 (assignment.Source is IAddressDereference) {
       if (!treatAsStatement) {
     this.generator.Emit(OperationCode.Dup);
     this.StackSize++;
       }
       this.Traverse(((IAddressDereference)assignment.Source).Address);
       this.generator.Emit(OperationCode.Cpobj, addressDereference.Type);
       this.StackSize-=2;
       if (!treatAsStatement)
     this.generator.Emit(OperationCode.Ldobj, addressDereference.Type);
     } else {
       this.Traverse(assignment.Source);
       ILocalDefinition/*?*/ temp = null;
       if (!treatAsStatement) {
     temp = new TemporaryVariable(assignment.Source.Type, this.method);
     this.VisitAssignmentTo(temp);
     this.LoadLocal(temp);
       }
       this.VisitAssignmentTo(addressDereference);
       if (temp != null) this.LoadLocal(temp);
     }
     return;
       }
       Contract.Assume(false);
 }
Пример #6
0
        /// <summary>
        /// Generates IL for the specified resource use statement.
        /// </summary>
        /// <param name="resourceUseStatement">The resource use statement.</param>
        public override void TraverseChildren(IResourceUseStatement resourceUseStatement)
        {
            this.EmitSequencePoint(resourceUseStatement.Locations);
              var systemIDisposable = new NamespaceTypeReference(this.host, this.host.PlatformType.SystemObject.ContainingUnitNamespace,
            this.host.NameTable.GetNameFor("IDisposable"), 0, isEnum: false, isValueType: false, typeCode: PrimitiveTypeCode.NotPrimitive);
              var dispose = new MethodReference(this.host, systemIDisposable, CallingConvention.Default, this.host.PlatformType.SystemVoid,
            this.host.NameTable.GetNameFor("Dispose"), 0, Enumerable<IParameterTypeInformation>.Empty);

              //Get resource into a local
              ILocalDefinition resourceLocal;
              var localDeclaration = resourceUseStatement.ResourceAcquisitions as ILocalDeclarationStatement;
              if (localDeclaration != null) {
            resourceLocal = localDeclaration.LocalVariable;
            this.Traverse(localDeclaration.InitialValue);
              } else {
            var expressionStatement = (IExpressionStatement)resourceUseStatement.ResourceAcquisitions;
            this.Traverse(expressionStatement.Expression);
            resourceLocal = new TemporaryVariable(systemIDisposable, this.method);
              }
              this.VisitAssignmentTo(resourceLocal);

              //try
              var savedCurrentTryCatch = this.currentTryCatch;
              this.currentTryCatch = resourceUseStatement;
              var savedCurrentTryCatchFinallyEnd = this.currentTryCatchFinallyEnd;
              this.currentTryCatchFinallyEnd = new ILGeneratorLabel();
              this.generator.BeginTryBody();
              this.Traverse(resourceUseStatement.Body);
              if (!this.lastStatementWasUnconditionalTransfer)
            this.generator.Emit(OperationCode.Leave, this.currentTryCatchFinallyEnd);

              //finally
              this.generator.BeginFinallyBlock();
              var endOfFinally = new ILGeneratorLabel();
              if (!resourceLocal.Type.IsValueType) {
            this.generator.Emit(OperationCode.Ldloc, resourceLocal);
            this.generator.Emit(OperationCode.Brfalse_S, endOfFinally);
              }
              this.generator.Emit(OperationCode.Ldloc, resourceLocal);
              this.generator.Emit(OperationCode.Callvirt, dispose);
              this.generator.MarkLabel(endOfFinally);
              this.generator.Emit(OperationCode.Endfinally);
              this.generator.EndTryBody();
              this.generator.MarkLabel(this.currentTryCatchFinallyEnd);
              this.currentTryCatchFinallyEnd = savedCurrentTryCatchFinallyEnd;
              this.currentTryCatch = savedCurrentTryCatch;
              this.lastStatementWasUnconditionalTransfer = false;
        }
Пример #7
0
        /// <summary>
        /// Generates IL for the specified lock statement.
        /// </summary>
        /// <param name="lockStatement">The lock statement.</param>
        public override void TraverseChildren(ILockStatement lockStatement)
        {
            if (this.host.SystemCoreAssemblySymbolicIdentity.Version.Major < 4) {
            this.GenerateDownLevelLockStatement(lockStatement);
            return;
              }
              var systemThreading = new NestedUnitNamespaceReference(this.host.PlatformType.SystemObject.ContainingUnitNamespace,
            this.host.NameTable.GetNameFor("Threading"));
              var systemThreadingMonitor = new NamespaceTypeReference(this.host, systemThreading, this.host.NameTable.GetNameFor("Monitor"), 0,
            isEnum: false, isValueType: false, typeCode: PrimitiveTypeCode.NotPrimitive);
              var parameters = new IParameterTypeInformation[2];
              var monitorEnter = new MethodReference(this.host, systemThreadingMonitor, CallingConvention.Default, this.host.PlatformType.SystemVoid,
            this.host.NameTable.GetNameFor("Enter"), 0, parameters);
              parameters[0] = new SimpleParameterTypeInformation(monitorEnter, 0, this.host.PlatformType.SystemObject);
              parameters[1] = new SimpleParameterTypeInformation(monitorEnter, 1, this.host.PlatformType.SystemBoolean, isByReference: true);
              var monitorExit = new MethodReference(this.host, systemThreadingMonitor, CallingConvention.Default, this.host.PlatformType.SystemVoid,
            this.host.NameTable.GetNameFor("Exit"), 0, this.host.PlatformType.SystemObject);

              this.EmitSequencePoint(lockStatement.Locations);
              var guardObject = new TemporaryVariable(lockStatement.Guard.Type, this.method);
              var lockTaken = new TemporaryVariable(this.host.PlatformType.SystemBoolean, this.method);
              //try
              var savedCurrentTryCatch = this.currentTryCatch;
              this.currentTryCatch = lockStatement;
              var savedCurrentTryCatchFinallyEnd = this.currentTryCatchFinallyEnd;
              this.currentTryCatchFinallyEnd = new ILGeneratorLabel();
              this.generator.BeginTryBody();
              this.Traverse(lockStatement.Guard);
              this.generator.Emit(OperationCode.Dup); this.StackSize++;
              this.VisitAssignmentTo(guardObject);
              this.LoadAddressOf(lockTaken, null);
              this.generator.Emit(OperationCode.Call, monitorEnter);
              this.StackSize-=2;
              this.Traverse(lockStatement.Body);
              if (!this.lastStatementWasUnconditionalTransfer)
            this.generator.Emit(OperationCode.Leave, this.currentTryCatchFinallyEnd);
              //finally
              this.generator.BeginFinallyBlock();
              //if (status)
              var endIf = new ILGeneratorLabel();
              this.LoadLocal(lockTaken);
              this.generator.Emit(OperationCode.Brfalse_S, endIf);
              this.StackSize--;
              this.LoadLocal(guardObject);
              this.generator.Emit(OperationCode.Call, monitorExit);
              this.StackSize--;
              this.generator.MarkLabel(endIf);
              //monitor exit
              this.generator.Emit(OperationCode.Endfinally);
              this.generator.EndTryBody();
              this.generator.MarkLabel(this.currentTryCatchFinallyEnd);
              this.currentTryCatchFinallyEnd = savedCurrentTryCatchFinallyEnd;
              this.currentTryCatch = savedCurrentTryCatch;
              this.lastStatementWasUnconditionalTransfer = false;
        }
Пример #8
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);
    }