public ILEmitter Emit(ILEmitter il, LocalBuilder hash) { il.Emit(_variable.Load(Arg.Input)) .Stloc(_variable.VariableType, out var enumerable) .DefineLabel(out var end); if (!_variable.VariableType.IsValueType) { il.Brtrue_S(Ldloc(enumerable), out var begin) .Ldc_I4(0) .Br(end) .MarkLabel(begin); } if (_configuration.Get(_variable.OwnerType).IgnoreCollectionOrder) { return(EmitHashAsSortedArray(il, enumerable, hash).MarkLabel(end)); } il.CallMethod(_getEnumeratorMethod, LoadCaller(enumerable)) .Stloc(_enumeratorType, out var enumerator) .DefineLabel(out var loopStart); if (!_enumeratorType.IsValueType) { il.Brtrue_S(Ldloc(enumerator), loopStart) .Ldc_I4(0) .Br(end); } // todo: 1. think how to use try/finally block // the problem now with the inner `return` statements, it has to be `leave` instruction //il.BeginExceptionBlock(); Loop(il, enumerator, loopStart, hash); //il.BeginFinallyBlock(); EmitDisposeEnumerator(il, enumerator); //il.EndExceptionBlock(); return(il.Ldloc(hash).MarkLabel(end)); }
private static void EmitCycleDetection(ILEmitter il, Type objectType) => il.Brtrue_S(TryAdd(Arg.CycleSet, Arg.Input, objectType), out var next) .Emit(GetCount(Arg.CycleSet)) .Stloc(typeof(int), out var count) .Ret(CallMethod(_getHashCodeMethod, LoadCaller(count))) .MarkLabel(next);