public static void SmallSnippet(int a, double b) { if (b < (a + 15)) { var s = ((b / a).ToString() + "str").ToString(); checked { var x = a + 10; switch (x) { case 2: var y = (UInt32)4 + (UInt32)x; Log.WriteLine(String.Empty + x + y); break; case 4: a = 15; var arr = new Type[1]; arr[0] = typeof(Single); break; case 7: Object abox = a; b = (Int32)(UInt32)abox + 5; var c = (UInt32)b < 2; break; default: var z = typeof(Type); Log.WriteLine(z.ToString() + sizeof(Double)); throw new NotSupportedException(); } } } else { DateTime dt1; dt1 = DateTime.Now; var dt = new DateTime(1987, 8, 5); var arr = new[] { dt, new DateTime(dt1.Year, dt1.Month, dt1.Day) }; (arr.Length == new List <Int32>().Count).AssertTrue(); Func <int, int> foo = i => dt.Day + i + arr[15].Month; (foo(arr.Length) != 5.0d).AssertTrue(); arr[4] = dt; var dts = new List <DateTime>(); var ss = dts[0].ToString(); IILOp iilop = null; (iilop is ILOp && new [] { "hello", "world" }[0] == "hello").AssertFalse(); } }
public static ILGenerator clone(this ILGenerator il, IILOp op) { // todo #1. also take into account that we need to update stacksize // todo #2. what is RecordTokenFixup()? // load some internals var methodBuilder = il.Get("m_methodBuilder").AssertCast<MethodBuilder>(); var typeBuilder = methodBuilder.Get("m_containingType").AssertCast<TypeBuilder>(); var ilModule = typeBuilder.Get("m_module").AssertCast<ModuleBuilder>(); // if op has some prefixes, clone them first op.Prefixes.ForEach(prefix => il.clone(prefix)); // hello, Shlemiel the Painter... var operand = op.BytesOfOperand.ToArray(); // fixup metadata tokens // 1. if op doesn't have a module specified, we just crash // 2. if op references a module builder, we verify that ilgen references it too // since as of .NET 3.5 you cannot resolve a token in module builder // 3. if op has a regular module, we proceed to fixup var opModule = op.Get("Module").AssertCast<Module>(); opModule.AssertNotNull(); if (opModule is ModuleBuilder) { (opModule == ilModule).AssertTrue(); } else { int newToken; // prepare to process ldtokens var ldc = op as Ldc; var ldc_value = ldc == null ? null : ldc.Value; var ldc_member = null as MemberInfo; if (ldc_value != null) { if (ldc_value is RuntimeTypeHandle) { var rth = (RuntimeTypeHandle)ldc_value; ldc_member = Type.GetTypeFromHandle(rth); } else if (ldc_value is RuntimeMethodHandle) { var rmh = (RuntimeMethodHandle)ldc_value; ldc_member = MethodBase.GetMethodFromHandle(rmh); } else if (ldc_value is RuntimeFieldHandle) { var rfh = (RuntimeFieldHandle)ldc_value; ldc_member = FieldInfo.GetFieldFromHandle(rfh); } } // process special case - ldtoken var operandType = op.OpSpec.OperandType; if (operandType == OperandType.InlineTok) { ldc_member.AssertNotNull(); if (ldc_member is Type) { operandType = OperandType.InlineType; } else if (ldc_member is MethodBase) { operandType = OperandType.InlineMethod; } else if (ldc_member is FieldInfo) { operandType = OperandType.InlineField; } else { throw AssertionHelper.Fail(); } } // process all other cases switch (operandType) { case OperandType.InlineType: var type = (ldc_member ?? op.GetOrDefault("Type") ?? op.GetOrDefault("Resolved")).AssertCast<Type>(); if (op.OpSpec.OpCode == OpCodes.Newarr) type = type.GetElementType(); newToken = ilModule.GetTypeToken(type).Token; operand = BitConverter.GetBytes(newToken); break; case OperandType.InlineField: var field = (ldc_member ?? op.GetOrDefault("Field") ?? op.GetOrDefault("Resolved")).AssertCast<FieldInfo>(); newToken = ilModule.GetFieldToken(field).Token; operand = BitConverter.GetBytes(newToken); break; case OperandType.InlineMethod: // note 1. Module::GetMethodToken won't work here // since it returns index of an entry in the MemberRef metadata table (0x0a) // closed generic methods are stored a separate metadata table (MethodSpec, 0x2b) var method = (ldc_member ?? op.GetOrDefault("Method") ?? op.GetOrDefault("Ctor") ?? op.GetOrDefault("Resolved")).AssertCast<MethodBase>(); var getMethodToken = typeof(ILGenerator).GetMethod("GetMethodToken", BF.PrivateInstance); newToken = (int)getMethodToken.Invoke(il, new Object[] { method, null, false }); operand = BitConverter.GetBytes(newToken); break; case OperandType.InlineString: var @string = (op.GetOrDefault("Value") ?? op.GetOrDefault("Resolved")).AssertCast<String>(); newToken = ilModule.GetStringConstant(@string).Token; operand = BitConverter.GetBytes(newToken); break; case OperandType.InlineSig: // todo. implement this throw AssertionHelper.Fail(); case OperandType.InlineBrTarget: case OperandType.InlineI: case OperandType.InlineI8: case OperandType.InlineNone: #pragma warning disable 612, 618 case OperandType.InlinePhi: #pragma warning restore 612, 618 case OperandType.InlineR: case OperandType.InlineSwitch: case OperandType.InlineVar: case OperandType.ShortInlineBrTarget: case OperandType.ShortInlineI: case OperandType.ShortInlineR: case OperandType.ShortInlineVar: // do nothing - operand ain't needs a fixup break; default: throw AssertionHelper.Fail(); } } // write the op to the output stream return il.raw(op.OpSpec.OpCode, operand); }
public static ILGenerator EmitClone(this ILGenerator il, IILOp op) { return il.clone(op); }
public void DoRewrite() { _status.InProgress.AssertTrue(); using (_status) { Func<byte[]> m_ILStream = () => _il.Get("m_ILStream").AssertCast<byte[]>(); var typeBuilder = _dest.Get("m_containingType").AssertCast<TypeBuilder>(); var module = typeBuilder.Get("m_module").AssertCast<ModuleBuilder>(); Func<int> get_length = () => _il.Get("m_length").AssertCast<int>(); Action<int> set_length = v => _il.Set("m_length", v); // Stage 1: Write rewritten ops according to _logic // So far we don't care about branches being fix't up var rawIl_BeforeStage1 = _src.ParseBody().RawIL; TraceRawIl(rawIl_BeforeStage1, 0); foreach (var op in _body) { _curr = op; _logic(op, this); } // Stage 2: Replace short branches with regular ones // since fixups (see below) might overflow the 1-byte offset storage _rewrittenIL = m_ILStream().Take(get_length()).ToArray(); TraceRawIl(_rewrittenIL, 1); set_length(0); var fixupUpdates = new List<Action>(); var branchExpansionPoints = new Dictionary<int, int>(); foreach (var rop in _rewrittenIL.ParseRawIL(module)) { var rop1 = rop; if (rop1 is Branch) { var br = rop1.AssertCast<Branch>(); if (rop1.OpSpec.OperandType == OperandType.ShortInlineBrTarget) { // rewrite short branch to normal form var opcode_sig = rop1.OpSpec.OpCode.Value + 0x0d; var allOpcodes = typeof(OpCodes).GetFields(BF.PublicStatic).Select(f => f.GetValue(null).AssertCast<OpCode>()); var opcode = allOpcodes.Single(oc => oc.Value == opcode_sig); _il.raw(opcode, BitConverter.GetBytes(br.RelativeTargetOffset)); // update fixup of the next operation // fixup = translate from original offsets to after-stage-2 ones var preImage = _off2op[RewrittenToNearestOrig(rop1.Offset)]; if (preImage.Next != null) fixupUpdates.Add(() => _fixups[preImage.Next] += 3); // update the map that memorizes BEPs in after-stage-1 coordinates fixupUpdates.Add(() => branchExpansionPoints[rop1.Offset] = 3); // also be careful to fixup _offsetsModeChangeLog => lazily! // fixup = translate from after-stage-1 to after-stage-2 coordinates foreach (var entry in _offsetsModeChangeLog) { (rop1.Offset < entry.Offset && entry.Offset < rop1.OffsetOfNextOp).AssertFalse(); var entry1 = entry; var fixup = rop1.Offset >= entry1.Offset ? 0 : 3; fixupUpdates.Add(() => entry1.Offset += fixup); } } else { _il.clone(rop1); } } else { _il.clone(rop1); } } // we defer updates so that they won't f**k up _fixups in process fixupUpdates.RunEach(); // Stage 3: Fixup branches since their offsets are most likely invalid now // todo. also fixup switches and protected regions // // note. this works as follows: // 1) if an instruction was emitted during OffsetsMode.Original, // i.e. (if EnterXXXMode wasn't called) during Clone // it needs a fixup and uses the main fixup log, i.e. _fixups. // 2) if an instruction was emitted during OffsetsMode.Rewritten, // i.e. (if EnterXXXMode wasn't called) during Clone // it ain't need a fixup due to rewriting, // but does need a fixup to compensate for short branches expansion (see above) // and thusly uses the branchExpansionFixups log _rewrittenIL = m_ILStream().Take(get_length()).ToArray(); TraceRawIl(_rewrittenIL, 2); foreach (var rop in _rewrittenIL.ParseRawIL(module)) { // note #1. // we can't use Target here since offsets are most likely broken at the moment // at best it'll return null, and at worst it'll crash // note #2. // we can't use AbsoluteTargetOffset either since it positions at after-stage-2 IL // but not to before-stage-1 IL (i.e. original) // note #3. // neither we can use RewrittenToOrig(rop.Offset) // since, even if we're at OffsetsMode.Original, the rop might've been issued during r/w if (rop is Branch) { var br = rop.AssertCast<Branch>(); var pivot = br.OffsetOfNextOp; Action<int> rewriteRelOffset = newRelOffset => { var addrOfOperand = rop.OffsetOfOperand; var fixedUp = BitConverter.GetBytes(newRelOffset); fixedUp.ForEach((b, i) => m_ILStream()[i + addrOfOperand] = b); }; var mode = GetOffsetsMode(br.Offset); // see section #1 of the above comment if (mode == OffsetsMode.Original) { // note. important: original offsets mode here // doesn't mean that the op processed has a corresponding preimage (see also n0te #3 above) // it only means that the relative offset works in original mode // step 1. find out orig_relOffset (note: trick here!) var r_r_relOffset = br.RelativeTargetOffset; var nearestOrig = _off2op[RewrittenToNearestOrig(br.Offset)]; var r_off2op = _rewrittenIL.ParseRawIL(module).ToDictionary(op => op.Offset, op => op); var r_nearestOrig = r_off2op[OrigToRewritten(nearestOrig.Offset)]; var orig_relOffset = r_r_relOffset + (br.Offset - r_nearestOrig.Offset); // step 2. restore the op that orig_relOffset references var orig_pivot = nearestOrig.OffsetOfNextOp; var orig_absOffset = orig_pivot + orig_relOffset; // step 3. find out the r_pivot (note: trick here!) var r_pivot = br.OffsetOfNextOp; // step 4. calculate the r_relOffset var r_absOffset = OrigToRewritten(orig_absOffset); var r_relOffset = r_absOffset - r_pivot; rewriteRelOffset(r_relOffset); } // see section #2 of the above comment else if (mode == OffsetsMode.Rewritten) { // we can't use relOffset here // because the "where" condition will become really complex // since we need to take into account both negative and positive rels var absOffset = br.AbsoluteTargetOffset; branchExpansionPoints .Where(kvp => kvp.Key < br.AbsoluteTargetOffset) .ForEach(kvp => absOffset += kvp.Value); rewriteRelOffset(absOffset - pivot); } else { throw AssertionHelper.Fail(); } } else if (rop is Switch) { throw AssertionHelper.Fail(); } else { // do nothing - this op ain't eligible for fixup } } // Finalizing the operations // fill in the RewrittenOps _rewrittenIL = m_ILStream().Take(get_length()).ToArray(); TraceRawIl(_rewrittenIL, 3); var opsAfterRewriting = _rewrittenIL.ParseRawIL(module).ToDictionary(op => op.Offset, op => op); foreach (var rop in _rewrittenOps.Keys.ToArray()) { var startOffset = OrigToRewritten(rop.Offset); var endOffset = rop.Next == null ? int.MaxValue : OrigToRewritten(rop.Next.Offset); var imageOps = opsAfterRewriting .Where(kvp2 => startOffset <= kvp2.Key && kvp2.Key < endOffset) .Select(kvp2 => kvp2.Value); _rewrittenOps[rop] = imageOps.ToReadOnly(); } } }
public static ILGenerator clone(this ILGenerator il, IILOp op) { // todo #1. also take into account that we need to update stacksize // todo #2. what is RecordTokenFixup()? // load some internals var methodBuilder = il.Get("m_methodBuilder").AssertCast <MethodBuilder>(); var typeBuilder = methodBuilder.Get("m_containingType").AssertCast <TypeBuilder>(); var ilModule = typeBuilder.Get("m_module").AssertCast <ModuleBuilder>(); // if op has some prefixes, clone them first op.Prefixes.ForEach(prefix => il.clone(prefix)); // hello, Shlemiel the Painter... var operand = op.BytesOfOperand.ToArray(); // fixup metadata tokens // 1. if op doesn't have a module specified, we just crash // 2. if op references a module builder, we verify that ilgen references it too // since as of .NET 3.5 you cannot resolve a token in module builder // 3. if op has a regular module, we proceed to fixup var opModule = op.Get("Module").AssertCast <Module>(); opModule.AssertNotNull(); if (opModule is ModuleBuilder) { (opModule == ilModule).AssertTrue(); } else { int newToken; // prepare to process ldtokens var ldc = op as Ldc; var ldc_value = ldc == null ? null : ldc.Value; var ldc_member = null as MemberInfo; if (ldc_value != null) { if (ldc_value is RuntimeTypeHandle) { var rth = (RuntimeTypeHandle)ldc_value; ldc_member = Type.GetTypeFromHandle(rth); } else if (ldc_value is RuntimeMethodHandle) { var rmh = (RuntimeMethodHandle)ldc_value; ldc_member = MethodBase.GetMethodFromHandle(rmh); } else if (ldc_value is RuntimeFieldHandle) { var rfh = (RuntimeFieldHandle)ldc_value; ldc_member = FieldInfo.GetFieldFromHandle(rfh); } } // process special case - ldtoken var operandType = op.OpSpec.OperandType; if (operandType == OperandType.InlineTok) { ldc_member.AssertNotNull(); if (ldc_member is Type) { operandType = OperandType.InlineType; } else if (ldc_member is MethodBase) { operandType = OperandType.InlineMethod; } else if (ldc_member is FieldInfo) { operandType = OperandType.InlineField; } else { throw AssertionHelper.Fail(); } } // process all other cases switch (operandType) { case OperandType.InlineType: var type = (ldc_member ?? op.GetOrDefault("Type") ?? op.GetOrDefault("Resolved")).AssertCast <Type>(); if (op.OpSpec.OpCode == OpCodes.Newarr) { type = type.GetElementType(); } newToken = ilModule.GetTypeToken(type).Token; operand = BitConverter.GetBytes(newToken); break; case OperandType.InlineField: var field = (ldc_member ?? op.GetOrDefault("Field") ?? op.GetOrDefault("Resolved")).AssertCast <FieldInfo>(); newToken = ilModule.GetFieldToken(field).Token; operand = BitConverter.GetBytes(newToken); break; case OperandType.InlineMethod: // note 1. Module::GetMethodToken won't work here // since it returns index of an entry in the MemberRef metadata table (0x0a) // closed generic methods are stored a separate metadata table (MethodSpec, 0x2b) var method = (ldc_member ?? op.GetOrDefault("Method") ?? op.GetOrDefault("Ctor") ?? op.GetOrDefault("Resolved")).AssertCast <MethodBase>(); var getMethodToken = typeof(ILGenerator).GetMethod("GetMethodToken", BF.PrivateInstance); newToken = (int)getMethodToken.Invoke(il, new Object[] { method, null, false }); operand = BitConverter.GetBytes(newToken); break; case OperandType.InlineString: var @string = (op.GetOrDefault("Value") ?? op.GetOrDefault("Resolved")).AssertCast <String>(); newToken = ilModule.GetStringConstant(@string).Token; operand = BitConverter.GetBytes(newToken); break; case OperandType.InlineSig: // todo. implement this throw AssertionHelper.Fail(); case OperandType.InlineBrTarget: case OperandType.InlineI: case OperandType.InlineI8: case OperandType.InlineNone: #pragma warning disable 612, 618 case OperandType.InlinePhi: #pragma warning restore 612, 618 case OperandType.InlineR: case OperandType.InlineSwitch: case OperandType.InlineVar: case OperandType.ShortInlineBrTarget: case OperandType.ShortInlineI: case OperandType.ShortInlineR: case OperandType.ShortInlineVar: // do nothing - operand ain't needs a fixup break; default: throw AssertionHelper.Fail(); } } // write the op to the output stream return(il.raw(op.OpSpec.OpCode, operand)); }
public static ILGenerator EmitClone(this ILGenerator il, IILOp op) { return(il.clone(op)); }
// dispatch logic private void Dispatch(IILOp op) { switch (op.OpType) { case IILOpType.Nop: Process(op.AssertCast<Nop>()); break; case IILOpType.Break: Process(op.AssertCast<CilBreak>()); break; case IILOpType.Ldarg: Process(op.AssertCast<Ldarg>()); break; case IILOpType.Ldloc: Process(op.AssertCast<Ldloc>()); break; case IILOpType.Stloc: Process(op.AssertCast<Stloc>()); break; case IILOpType.Ldarga: Process(op.AssertCast<Ldarga>()); break; case IILOpType.Starg: Process(op.AssertCast<Starg>()); break; case IILOpType.Ldloca: Process(op.AssertCast<Ldloca>()); break; case IILOpType.Ldc: Process(op.AssertCast<Ldc>()); break; case IILOpType.Dup: Process(op.AssertCast<Dup>()); break; case IILOpType.Pop: Process(op.AssertCast<Pop>()); break; case IILOpType.Call: Process(op.AssertCast<Call>()); break; case IILOpType.Ldind: Process(op.AssertCast<Ldind>()); break; case IILOpType.Stind: Process(op.AssertCast<Stind>()); break; case IILOpType.Operator: Process(op.AssertCast<CilOperator>()); break; case IILOpType.Cast: Process(op.AssertCast<Cast>()); break; case IILOpType.New: Process(op.AssertCast<New>()); break; case IILOpType.Initobj: Process(op.AssertCast<Initobj>()); break; case IILOpType.Ldfld: Process(op.AssertCast<Ldfld>()); break; case IILOpType.Ldflda: Process(op.AssertCast<Ldflda>()); break; case IILOpType.Stfld: Process(op.AssertCast<Stfld>()); break; case IILOpType.Ldlen: Process(op.AssertCast<Ldlen>()); break; case IILOpType.Ldelema: Process(op.AssertCast<Ldelema>()); break; case IILOpType.Ldelem: Process(op.AssertCast<Ldelem>()); break; case IILOpType.Stelem: Process(op.AssertCast<Stelem>()); break; case IILOpType.Ldftn: Process(op.AssertCast<Ldftn>()); break; case IILOpType.Isinst: Process(op.AssertCast<Isinst>()); break; case IILOpType.Sizeof: Process(op.AssertCast<CilSizeOf>()); break; case IILOpType.Throw: Process(op.AssertCast<CilThrow>()); break; case IILOpType.Rethrow: Process(op.AssertCast<CilRethrow>()); break; case IILOpType.Localloc: throw AssertionHelper.Fail(); case IILOpType.Arglist: throw AssertionHelper.Fail(); case IILOpType.Mkrefany: throw AssertionHelper.Fail(); case IILOpType.Refanyval: throw AssertionHelper.Fail(); case IILOpType.Refanytype: throw AssertionHelper.Fail(); case IILOpType.Initblk: throw AssertionHelper.Fail(); case IILOpType.Cpblk: throw AssertionHelper.Fail(); case IILOpType.Cpobj: throw AssertionHelper.Fail(); case IILOpType.Jmp: throw AssertionHelper.Fail(); case IILOpType.Ckfinite: throw AssertionHelper.Fail(); default: throw AssertionHelper.Fail(); } }
private Node _mapOp(IILOp op) { return _map.AssertSingle(kvp => ReferenceEquals(kvp.Value, op)).Key; }
public void DoRewrite() { _status.InProgress.AssertTrue(); using (_status) { Func <byte[]> m_ILStream = () => _il.Get("m_ILStream").AssertCast <byte[]>(); var typeBuilder = _dest.Get("m_containingType").AssertCast <TypeBuilder>(); var module = typeBuilder.Get("m_module").AssertCast <ModuleBuilder>(); Func <int> get_length = () => _il.Get("m_length").AssertCast <int>(); Action <int> set_length = v => _il.Set("m_length", v); // Stage 1: Write rewritten ops according to _logic // So far we don't care about branches being fix't up var rawIl_BeforeStage1 = _src.ParseBody().RawIL; TraceRawIl(rawIl_BeforeStage1, 0); foreach (var op in _body) { _curr = op; _logic(op, this); } // Stage 2: Replace short branches with regular ones // since fixups (see below) might overflow the 1-byte offset storage _rewrittenIL = m_ILStream().Take(get_length()).ToArray(); TraceRawIl(_rewrittenIL, 1); set_length(0); var fixupUpdates = new List <Action>(); var branchExpansionPoints = new Dictionary <int, int>(); foreach (var rop in _rewrittenIL.ParseRawIL(module)) { var rop1 = rop; if (rop1 is Branch) { var br = rop1.AssertCast <Branch>(); if (rop1.OpSpec.OperandType == OperandType.ShortInlineBrTarget) { // rewrite short branch to normal form var opcode_sig = rop1.OpSpec.OpCode.Value + 0x0d; var allOpcodes = typeof(OpCodes).GetFields(BF.PublicStatic).Select(f => f.GetValue(null).AssertCast <OpCode>()); var opcode = allOpcodes.Single(oc => oc.Value == opcode_sig); _il.raw(opcode, BitConverter.GetBytes(br.RelativeTargetOffset)); // update fixup of the next operation // fixup = translate from original offsets to after-stage-2 ones var preImage = _off2op[RewrittenToNearestOrig(rop1.Offset)]; if (preImage.Next != null) { fixupUpdates.Add(() => _fixups[preImage.Next] += 3); } // update the map that memorizes BEPs in after-stage-1 coordinates fixupUpdates.Add(() => branchExpansionPoints[rop1.Offset] = 3); // also be careful to fixup _offsetsModeChangeLog => lazily! // fixup = translate from after-stage-1 to after-stage-2 coordinates foreach (var entry in _offsetsModeChangeLog) { (rop1.Offset < entry.Offset && entry.Offset < rop1.OffsetOfNextOp).AssertFalse(); var entry1 = entry; var fixup = rop1.Offset >= entry1.Offset ? 0 : 3; fixupUpdates.Add(() => entry1.Offset += fixup); } } else { _il.clone(rop1); } } else { _il.clone(rop1); } } // we defer updates so that they won't f**k up _fixups in process fixupUpdates.RunEach(); // Stage 3: Fixup branches since their offsets are most likely invalid now // todo. also fixup switches and protected regions // // note. this works as follows: // 1) if an instruction was emitted during OffsetsMode.Original, // i.e. (if EnterXXXMode wasn't called) during Clone // it needs a fixup and uses the main fixup log, i.e. _fixups. // 2) if an instruction was emitted during OffsetsMode.Rewritten, // i.e. (if EnterXXXMode wasn't called) during Clone // it ain't need a fixup due to rewriting, // but does need a fixup to compensate for short branches expansion (see above) // and thusly uses the branchExpansionFixups log _rewrittenIL = m_ILStream().Take(get_length()).ToArray(); TraceRawIl(_rewrittenIL, 2); foreach (var rop in _rewrittenIL.ParseRawIL(module)) { // note #1. // we can't use Target here since offsets are most likely broken at the moment // at best it'll return null, and at worst it'll crash // note #2. // we can't use AbsoluteTargetOffset either since it positions at after-stage-2 IL // but not to before-stage-1 IL (i.e. original) // note #3. // neither we can use RewrittenToOrig(rop.Offset) // since, even if we're at OffsetsMode.Original, the rop might've been issued during r/w if (rop is Branch) { var br = rop.AssertCast <Branch>(); var pivot = br.OffsetOfNextOp; Action <int> rewriteRelOffset = newRelOffset => { var addrOfOperand = rop.OffsetOfOperand; var fixedUp = BitConverter.GetBytes(newRelOffset); fixedUp.ForEach((b, i) => m_ILStream()[i + addrOfOperand] = b); }; var mode = GetOffsetsMode(br.Offset); // see section #1 of the above comment if (mode == OffsetsMode.Original) { // note. important: original offsets mode here // doesn't mean that the op processed has a corresponding preimage (see also n0te #3 above) // it only means that the relative offset works in original mode // step 1. find out orig_relOffset (note: trick here!) var r_r_relOffset = br.RelativeTargetOffset; var nearestOrig = _off2op[RewrittenToNearestOrig(br.Offset)]; var r_off2op = _rewrittenIL.ParseRawIL(module).ToDictionary(op => op.Offset, op => op); var r_nearestOrig = r_off2op[OrigToRewritten(nearestOrig.Offset)]; var orig_relOffset = r_r_relOffset + (br.Offset - r_nearestOrig.Offset); // step 2. restore the op that orig_relOffset references var orig_pivot = nearestOrig.OffsetOfNextOp; var orig_absOffset = orig_pivot + orig_relOffset; // step 3. find out the r_pivot (note: trick here!) var r_pivot = br.OffsetOfNextOp; // step 4. calculate the r_relOffset var r_absOffset = OrigToRewritten(orig_absOffset); var r_relOffset = r_absOffset - r_pivot; rewriteRelOffset(r_relOffset); } // see section #2 of the above comment else if (mode == OffsetsMode.Rewritten) { // we can't use relOffset here // because the "where" condition will become really complex // since we need to take into account both negative and positive rels var absOffset = br.AbsoluteTargetOffset; branchExpansionPoints .Where(kvp => kvp.Key < br.AbsoluteTargetOffset) .ForEach(kvp => absOffset += kvp.Value); rewriteRelOffset(absOffset - pivot); } else { throw AssertionHelper.Fail(); } } else if (rop is Switch) { throw AssertionHelper.Fail(); } else { // do nothing - this op ain't eligible for fixup } } // Finalizing the operations // fill in the RewrittenOps _rewrittenIL = m_ILStream().Take(get_length()).ToArray(); TraceRawIl(_rewrittenIL, 3); var opsAfterRewriting = _rewrittenIL.ParseRawIL(module).ToDictionary(op => op.Offset, op => op); foreach (var rop in _rewrittenOps.Keys.ToArray()) { var startOffset = OrigToRewritten(rop.Offset); var endOffset = rop.Next == null ? int.MaxValue : OrigToRewritten(rop.Next.Offset); var imageOps = opsAfterRewriting .Where(kvp2 => startOffset <= kvp2.Key && kvp2.Key < endOffset) .Select(kvp2 => kvp2.Value); _rewrittenOps[rop] = imageOps.ToReadOnly(); } } }
private Node _mapOp(IILOp op) { return(_map.AssertSingle(kvp => ReferenceEquals(kvp.Value, op)).Key); }
public bool Equals(IILOp other) { return(Equals(other as ILOp)); }