/// <summary> /// Emits 'for' statement on current IL stream. /// </summary> /// <param name="il">IL generator to be emitted to.</param> /// <param name="count">'count' local variable which is <see cref="Int32"/> type and holds maximum loop count.</param> /// <param name="bodyEmitter">Delegate to emit for statement body.</param> public static void EmitFor( TracingILGenerator il, LocalBuilder count, Action<TracingILGenerator, LocalBuilder> bodyEmitter ) { Contract.Requires( il != null ); Contract.Requires( count != null ); Contract.Requires( bodyEmitter != null ); var i = il.DeclareLocal( typeof( int ), "i" ); il.EmitLdc_I4_0(); il.EmitAnyStloc( i ); var forCond = il.DefineLabel( "FOR_COND" ); il.EmitBr( forCond ); var body = il.DefineLabel( "BODY" ); il.MarkLabel( body ); bodyEmitter( il, i ); // increment il.EmitAnyLdloc( i ); il.EmitLdc_I4_1(); il.EmitAdd(); il.EmitAnyStloc( i ); // cond il.MarkLabel( forCond ); il.EmitAnyLdloc( i ); il.EmitAnyLdloc( count ); il.EmitBlt( body ); }
/// <summary> /// Emits 'foreach' statement on the IL stream. /// </summary> /// <param name="il">IL generator to be emitted to.</param> /// <param name="traits"><see cref="CollectionTraits"/> which contains traits of the iterating collection.</param> /// <param name="collection">'collection' argument index.</param> /// <param name="bodyEmitter">Delegate to emit body statement.</param> public static void EmitForEach( TracingILGenerator il, CollectionTraits traits, LocalBuilder collection, Action<TracingILGenerator, Action> bodyEmitter ) { Contract.Requires( il != null ); Contract.Requires( collection != null ); Contract.Requires( bodyEmitter != null ); var enumerator = il.DeclareLocal( traits.GetEnumeratorMethod.ReturnType, "enumerator" ); // gets enumerator if ( collection.LocalType.IsValueType ) { il.EmitAnyLdloca( collection ); } else { il.EmitAnyLdloc( collection ); } il.EmitAnyCall( traits.GetEnumeratorMethod ); il.EmitAnyStloc( enumerator ); if ( typeof( IDisposable ).IsAssignableFrom( traits.GetEnumeratorMethod.ReturnType ) ) { il.BeginExceptionBlock(); } var startLoop = il.DefineLabel( "START_LOOP" ); il.MarkLabel( startLoop ); var endLoop = il.DefineLabel( "END_LOOP" ); var enumeratorType = traits.GetEnumeratorMethod.ReturnType; MethodInfo moveNextMethod = enumeratorType.GetMethod( "MoveNext", Type.EmptyTypes ); PropertyInfo currentProperty = traits.GetEnumeratorMethod.ReturnType.GetProperty( "Current" ); if ( moveNextMethod == null ) { moveNextMethod = Metadata._IEnumerator.MoveNext; } if ( currentProperty == null ) { if ( enumeratorType == typeof( IDictionaryEnumerator ) ) { currentProperty = Metadata._IDictionaryEnumerator.Current; } else if ( enumeratorType.IsInterface ) { if ( enumeratorType.IsGenericType && enumeratorType.GetGenericTypeDefinition() == typeof( IEnumerator<> ) ) { currentProperty = typeof( IEnumerator<> ).MakeGenericType( traits.ElementType ).GetProperty( "Current" ); } else { currentProperty = Metadata._IEnumerator.Current; } } } Contract.Assert( currentProperty != null, enumeratorType.ToString() ); // iterates if ( traits.GetEnumeratorMethod.ReturnType.IsValueType ) { il.EmitAnyLdloca( enumerator ); } else { il.EmitAnyLdloc( enumerator ); } il.EmitAnyCall( moveNextMethod ); il.EmitBrfalse( endLoop ); bodyEmitter( il, () => { if ( traits.GetEnumeratorMethod.ReturnType.IsValueType ) { il.EmitAnyLdloca( enumerator ); } else { il.EmitAnyLdloc( enumerator ); } il.EmitGetProperty( currentProperty ); } ); il.EmitBr( startLoop ); il.MarkLabel( endLoop ); // Dispose if ( typeof( IDisposable ).IsAssignableFrom( traits.GetEnumeratorMethod.ReturnType ) ) { il.BeginFinallyBlock(); if ( traits.GetEnumeratorMethod.ReturnType.IsValueType ) { var disposeMethod = traits.GetEnumeratorMethod.ReturnType.GetMethod( "Dispose" ); if ( disposeMethod != null && disposeMethod.GetParameters().Length == 0 && disposeMethod.ReturnType == typeof( void ) ) { il.EmitAnyLdloca( enumerator ); il.EmitAnyCall( disposeMethod ); } else { il.EmitAnyLdloc( enumerator ); il.EmitBox( traits.GetEnumeratorMethod.ReturnType ); il.EmitAnyCall( Metadata._IDisposable.Dispose ); } } else { il.EmitAnyLdloc( enumerator ); il.EmitAnyCall( Metadata._IDisposable.Dispose ); } il.EndExceptionBlock(); } }
private static void EmitNilImplicationForPrimitive( TracingILGenerator il, SerializingMember member, LocalBuilder value, Label endOfDeserialization ) { var endIf = il.DefineLabel( "END_IF_NULL" ); EmitCompareNull( il, value, endIf ); switch ( member.Contract.NilImplication ) { case NilImplication.MemberDefault: { /* * if( value == null ) * { * // Skip current. * goto END_OF_DESERIALIZATION; * } */ il.EmitBr( endOfDeserialization ); break; } case NilImplication.Null: { // Throw exception for non-nullable value type. // Nop for nullables. if ( member.Member.GetMemberValueType().GetIsValueType() && Nullable.GetUnderlyingType( member.Member.GetMemberValueType() ) == null ) { /* * if( value == null ) * { * throw SerializationEceptions.NewValueTypeCannotBeNull( "...", typeof( MEMBER ), typeof( TYPE ) ); * } */ il.EmitLdstr( member.Contract.Name ); il.EmitLdtoken( member.Member.GetMemberValueType() ); il.EmitAnyCall( Metadata._Type.GetTypeFromHandle ); il.EmitLdtoken( member.Member.DeclaringType ); il.EmitAnyCall( Metadata._Type.GetTypeFromHandle ); il.EmitAnyCall( SerializationExceptions.NewValueTypeCannotBeNull3Method ); il.EmitThrow(); } break; } case NilImplication.Prohibit: { /* * if( value == null ) * { * throw SerializationEceptions.NewProhibitNullException( "..." ); * } */ il.EmitLdstr( member.Contract.Name ); il.EmitAnyCall( SerializationExceptions.NewNullIsProhibitedMethod ); il.EmitThrow(); break; } } il.MarkLabel( endIf ); }
private void DoConditionalInstruction( TracingILGenerator il, Action onThen, Action onElse ) { if ( this._elseExpression != null ) { var @else = il.DefineLabel( "ELSE" ); var endIf = il.DefineLabel( "END_IF" ); this._condition.Branch( il, @else ); onThen(); if ( !this._thenExpression.IsTerminating ) { il.EmitBr( endIf ); } il.MarkLabel( @else ); onElse(); il.MarkLabel( endIf ); } else { var endIf = il.DefineLabel( "END_IF" ); this._condition.Branch( il, endIf ); onThen(); il.MarkLabel( endIf ); } }