/// <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); }
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; }
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); }
/// <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; }
/// <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); }
/// <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; }
/// <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; }
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); }