public void Build(Type objectType, bool detectCycles, MethodBuilder staticMethodBuilder) { using var il = staticMethodBuilder.CreateILEmitter(); il.DefineLabel(out var exit); var needReferenceComparison = !objectType.ImplementsGenericInterface(typeof(IEnumerable<>)); // collections do reference comparisons anyway if (needReferenceComparison) { if (!objectType.IsValueType) { il.EmitReferenceComparison(LoadArgument(Arg.X), LoadArgument(Arg.Y), Ret(1)); } else if (objectType.IsNullable()) { il.EmitCheckNullablesForValue(LoadArgumentAddress(Arg.X), LoadArgumentAddress(Arg.Y), objectType, exit); } } if (detectCycles) { EmitCycleDetection(il, objectType); } var emitter = _resolver.GetComparisonEmitter(new ArgumentVariable(objectType)); emitter.Emit(il, exit); if (detectCycles) { il.Emit(Remove(Arg.SetX, Arg.X, objectType)) .Emit(Remove(Arg.SetY, Arg.Y, objectType)); } il.Emit(emitter.EmitCheckForResult(exit)) .MarkLabel(exit) .Ret(1); }
public void Build(Type objectType, bool detectCycles, MethodBuilder staticMethodBuilder) { using var il = staticMethodBuilder.CreateILEmitter(); var isCollection = objectType.ImplementsGenericInterface(typeof(IEnumerable <>)); var needNullCheck = !objectType.IsValueType && !isCollection; // collections do null check anyway if (needNullCheck) { il.LoadArgument(Arg.Input) .Brtrue_S(out var next) .Ret(0) .MarkLabel(next); } if (detectCycles) { EmitCycleDetection(il, objectType); } _resolver.GetHasherEmitter(new ArgumentVariable(objectType)).Emit(il); if (detectCycles) { il.Emit(Remove(Arg.CycleSet, Arg.Input, objectType)); } il.Ret(); }