private (LocalBuilder xDone, LocalBuilder yDone) EmitMoveNext(LocalBuilder xEnumerator, LocalBuilder yEnumerator, ILEmitter il) { // todo: 3. it's possible to use "not done" flag. it will simplify emitted code in _emitCheckIfLoopsAreDone. il.Ceq(CallMethod(_moveNextMethod, LoadCaller(xEnumerator)), Ldc_I4(0), out var xDone) .Ceq(CallMethod(_moveNextMethod, LoadCaller(yEnumerator)), Ldc_I4(0), out var yDone); return(xDone, yDone); }
public ILEmitter EmitCompareArrays( ILEmitter il, Type arrayType, Type ownerType, LocalBuilder xArray, LocalBuilder yArray, Label afterLoop) { // todo: 2. compare array lengths at the beginning il.EmitArrayLength(arrayType, xArray, out var countX) .EmitArrayLength(arrayType, yArray, out var countY) .Ldc_I4(0) .Stloc(typeof(int), out var index) .DefineLabel(out var loopStart) .DefineLabel(out var continueLoop) .MarkLabel(loopStart); using (il.LocalsScope()) { il.Ceq(Ldloc(index), Ldloc(countX), out var isDoneX) .Ceq(Ldloc(index), Ldloc(countY), out var isDoneY); _emitCheckIfLoopsAreDone(il, isDoneX, isDoneY, afterLoop); } using (il.LocalsScope()) { var arrays = new Dictionary <ushort, LocalBuilder>(2) { [Arg.X] = xArray, [Arg.Y] = yArray }; var itemVariable = new ArrayItemVariable(arrayType, ownerType, arrays, index); var itemComparison = _resolver.GetComparisonEmitter(itemVariable); return(il.Emit( itemComparison.Emit(continueLoop), itemComparison.EmitCheckForResult(continueLoop)) .MarkLabel(continueLoop) .Add(Ldloc(index), Ldc_I4(1)) .Stloc(index) .Br(loopStart)); } }
private static void EmitCycleDetection(ILEmitter il, Type objectType) => il.Ceq(Ldc_I4(0), Or(TryAdd(Arg.SetX, Arg.X, objectType), TryAdd(Arg.SetY, Arg.Y, objectType))) .Brfalse_S(out var next)
public ILEmitter Emit(ILEmitter il, Label _) => il.Ceq(_variable.Load(Arg.X), _variable.Load(Arg.Y));