void EmitEpilogue(IILEmitter emitter, InjectedFeature feature, NetfuserEvent.CilBodyBuilding me, IReadOnlyList <Tuple <Instruction, Var> > returns) { var target = me.Target; var rt = returns.RandomElementOrDefault(Rng); if (rt == null) { if (target.HasReturnType && (feature.Output.Flags & VarFlags.Ret) == 0) { Utils.RandomConst(emitter, target.ReturnType, Rng); } emitter.Emit(OpCodes.Ret); } else { if (target.HasReturnType) { if ((feature.Output.Flags & VarFlags.Ret) == 0) { Utils.RandomConst(emitter, target.ReturnType, Rng); } rt.Item2.Store(emitter); } emitter.Emit(OpCodes.Br, rt.Item1); } }
public void EmitChecker(IRng rng, IILEmitter emitter, Instruction falseTarget) { Local local = null; try { var zti = IsZeroTolerant() ? rng.NextInt32(0, 2) : -1; if (zti >= 0 || (_upper.HasValue && _lower.HasValue)) { local = emitter.RequestTempLocal(ElementType.ToType()); emitter.Stloc(local); } var upperFirst = rng.NextBoolean(); if (zti == 0) { EmitNz(); } Emit(emitter, ref local, upperFirst, rng.NextBoolean(), falseTarget); if (zti == 1) { EmitNz(); } Emit(emitter, ref local, !upperFirst, rng.NextBoolean(), falseTarget); if (zti == 2) { EmitNz(); } } finally { if (local != null) { emitter.TempLocals.Release(local); } } void EmitNz() { emitter.Ldloc(local); if (rng.NextBoolean()) { emitter.Emit(OpCodes.Brfalse, falseTarget); } else { emitter.Emit(OpCodes.Ldc_I4_0); emitter.NumericConversion(ElementType.I4, ElementType, false); emitter.Emit(OpCodes.Beq, falseTarget); } } }
public static IILEmitter Emit(this IILEmitter emitter, params OpCode[] codes) { foreach (var code in codes) { emitter.Emit(Instruction.Create(code)); } return(emitter); }
public static IILEmitter Emit(this IILEmitter emitter, IEnumerable <Instruction> instructions) { foreach (var i in instructions) { emitter.Emit(i.Clone()); } return(emitter); }
public void EmitChecker(IILEmitter emitter, IRng rng, Instruction normalFlowTarget) { var fv = Flag.Field; emitter.Emit(OpCodes.Ldarg_0); emitter.Emit(OpCodes.Ldfld, emitter.Importer.Import(fv)); if (Constraints != null) { emitter.NumericConversion(fv.FieldType.ElementType, Constraints.ElementType, false); Constraints.EmitChecker(rng, emitter, normalFlowTarget); } else { var(signed, bytes) = IntConstraints.GetProps(Flag.Field.FieldType.ElementType); emitter.Const(Value.Value, bytes, signed); emitter.Emit(OpCodes.Bne_Un, normalFlowTarget); } }
public override void Store(IILEmitter emitter, Action pushValue = null) { if (pushValue == null) { using (emitter.UseTempLocal(Type, out var local)) { emitter.Stloc(local); emitter.Emit(OpCodes.Ldarg_0); emitter.Ldloc(local); } } else { emitter.Emit(OpCodes.Ldarg_0); pushValue.Invoke(); } Stfld(emitter); }
public override void Store(IILEmitter emitter, Action pushValue = null) { pushValue?.Invoke(); if (Parameter.IsReturnTypeParameter) { emitter.Emit(OpCodes.Ret); } else { emitter.Starg(Parameter); } }
public static void EmitLoadArg(IILEmitter il, int index) { switch (index) { case 0: il.Emit(OpCodes.Ldarg_0); return; case 1: il.Emit(OpCodes.Ldarg_1); return; case 2: il.Emit(OpCodes.Ldarg_2); return; case 3: il.Emit(OpCodes.Ldarg_3); return; case { } n when n < 256: il.Emit(OpCodes.Ldarg_S, (byte)index); return; default: il.Emit(OpCodes.Ldarg, (short)index); return; } }
public override void Emit(IMemberEmitter member, ILGenerator gen) { ArgumentsUtil.EmitLoadOwnerAndReference(reference, gen); var notNull = gen.DefineLabel(); gen.Emit(OpCodes.Brtrue_S, notNull); ifNull.Emit(member, gen); gen.MarkLabel(notNull); if (ifNotNull != null) // yeah, I know that reads funny :) { ifNotNull.Emit(member, gen); } }
bool Emit(IILEmitter emitter, ref Local local, bool upper, bool invert, Instruction falseTarget) { var ic = upper ? _upper : _lower; if (!ic.HasValue) { return(false); } var c = Base.Lang.Ints.Const(ic.Value.Value, Bytes, Signed); var compiler = new ExprCompiler(emitter); if (invert) { if (local == null) { local = emitter.RequestTempLocal(c.Type); emitter.Stloc(local); } compiler.Compile(c); emitter.Ldloc(local); var op = DnextFactory.CondBranch(upper, !ic.Value.Inclusive, Signed); emitter.Emit(op, falseTarget); } else { if (local != null) { emitter.Ldloc(local); } compiler.Compile(c); var op = DnextFactory.CondBranch(!upper, !ic.Value.Inclusive, Signed); emitter.Emit(op, falseTarget); } return(true); }
/// <summary> /// Emits call to the method that contains de-mangler (injected as an <see cref="InjectedFeature"/>). /// This is to replace instruction(s) that load original constant in the IL /// </summary> /// <param name="emitter">IL emitter</param> /// <param name="rng">Pseudo-random number generator</param> /// <param name="instance">instance of the class where the method with injected de-mangler is located</param> /// <param name="mangled">mangled value</param> public void EmitCall(IILEmitter emitter, IRng rng, Local instance, object mangled) { var pi = Input is Var.Arg a ? a.Parameter : null; if (pi == null) { emitter.Ldloc(instance); Codec.LoadValue(emitter, mangled, true); Codec.EmitConversion(emitter, mangled.GetType(), Input.Type.ElementType.ToType()); ((Var.Fld)Input).Stfld(emitter); } var method = Method.Method; emitter.Ldloc(instance); foreach (var pd in method.Parameters) { if (pd.IsNormalMethodParameter) { if (pi == pd) { Codec.LoadValue(emitter, mangled, true); Codec.EmitConversion(emitter, mangled.GetType(), pd.Type.ElementType.ToType()); } else { Utils.RandomConst(emitter, pd.Type, rng); } } } emitter.Callvirt(emitter.Importer.Import(method)); if (method.HasReturnType) { if ((Output.Flags & VarFlags.Ret) == 0) { emitter.Emit(OpCodes.Pop); } } if (Output is Var.Fld f) { emitter.Ldloc(instance); f.Ldfld(emitter); } }
public void EmitNew(IILEmitter emitter, IRng rng, Local instance) { var ctor = Flag.Type.Ctors.RandomElementOrDefault(rng); if (ctor == null || (Flag.Ctor != null && rng.NextBoolean())) { foreach (var pd in Flag.Ctor.Parameters) { if (pd.IsNormalMethodParameter) { if (pd == Flag.FlagParameter) { EmitFlagValue(emitter, rng); } else { Utils.RandomConst(emitter, pd.Type, rng); } } } emitter.Newobj(emitter.Importer.Import(Flag.Ctor)); emitter.Stloc(instance); } else { foreach (var pd in ctor.Parameters) { if (pd.IsNormalMethodParameter) { Utils.RandomConst(emitter, pd.Type, rng); } } emitter.Newobj(emitter.Importer.Import(ctor)); emitter.Stloc(instance); emitter.Ldloc(instance); EmitFlagValue(emitter, rng); emitter.Emit(OpCodes.Stfld, emitter.Importer.Import(Flag.Field)); } }
public void ConvertTo(IILEmitter emitter, ElementType to) { switch (to) { case ElementType.I1: emitter.Emit(OpCodes.Conv_I1); break; case ElementType.I2: emitter.Emit(OpCodes.Conv_I2); break; case ElementType.I4: emitter.Emit(OpCodes.Conv_I4); break; case ElementType.I8: emitter.Emit(OpCodes.Conv_I8); break; case ElementType.U1: emitter.Emit(OpCodes.Conv_U1); break; case ElementType.U2: emitter.Emit(OpCodes.Conv_U2); break; case ElementType.U4: emitter.Emit(OpCodes.Conv_U4); break; case ElementType.U8: emitter.Emit(OpCodes.Conv_U8); break; } }
public static IILEmitter Emit(this IILEmitter emitter, OpCode code, ITypeDefOrRef type) => emitter.Emit(Instruction.Create(code, type));
public static IILEmitter Switch(this IILEmitter emitter, IList <Instruction> targets) => emitter.Emit(Instruction.Create(OpCodes.Switch, targets));
public static IILEmitter Emit(this IILEmitter emitter, OpCode code, Instruction target) => emitter.Emit(Instruction.Create(code, target));
public static IILEmitter Emit(this IILEmitter emitter, OpCode code, string v) => emitter.Emit(Instruction.Create(code, v));
public static IILEmitter Emit(this IILEmitter emitter, OpCode code, Local l) => emitter.Emit(Instruction.Create(code, l));
public static IILEmitter Emit(this IILEmitter emitter, OpCode code, Parameter p) => emitter.Emit(Instruction.Create(code, p));
public static IILEmitter Emit(this IILEmitter emitter, OpCode code, MethodSig ms) => emitter.Emit(Instruction.Create(code, ms));
public static IILEmitter Emit(this IILEmitter emitter, OpCode code, ITokenOperand to) => emitter.Emit(Instruction.Create(code, to));
public static IILEmitter Emit(this IILEmitter emitter, OpCode code, IField f) => emitter.Emit(Instruction.Create(code, f));
public static void RandomConst(IILEmitter il, TypeSig t, IRng rng) { switch (t.ElementType) { case ElementType.I1: il.Const(rng.NextInt8()); break; case ElementType.I2: il.Const(rng.NextInt16()); break; case ElementType.I4: il.Const(rng.NextInt32()); break; case ElementType.I8: il.Const(rng.NextInt64()); break; case ElementType.U1: il.Const(rng.NextUInt8()); break; case ElementType.U2: il.Const(rng.NextUInt16()); break; case ElementType.U4: il.Const(rng.NextUInt32()); break; case ElementType.U8: il.Const(rng.NextUInt64()); break; case ElementType.R4: il.Const(rng.NextFloat()); break; case ElementType.R8: il.Const(rng.NextDouble()); break; case ElementType.Char: il.Const((char)rng.NextUInt16()); break; case ElementType.Boolean: il.Const(rng.NextBoolean()); break; default: if (t.IsValueType) { var it = il.Importer.Import(t); using (il.UseTempLocal(it, out var l)) { il.Ldloca(l); il.Initobj(new TypeSpecUser(it)); il.Ldloc(l); } } else { il.Emit(OpCodes.Ldnull); } break; } }
private void EmitCastToType(Type typeFrom, Type typeTo) { if (!typeFrom.IsValueType && typeTo.IsValueType) { _ilg.Emit(OpCodes.Unbox_Any, _ilg.Importer.Import(typeTo)); return; } if (typeFrom.IsValueType && !typeTo.IsValueType) { _ilg.Emit(OpCodes.Box, _ilg.Importer.Import(typeFrom)); if (typeTo != typeof(object)) { _ilg.Emit(OpCodes.Castclass, _ilg.Importer.Import(typeTo)); return; } return; } if (!typeFrom.IsValueType && !typeTo.IsValueType) { _ilg.Emit(OpCodes.Castclass, _ilg.Importer.Import(typeTo)); return; } throw new NotSupportedException($"{typeFrom} => {typeTo}"); }
public override void Load(IILEmitter emitter) { emitter.Emit(OpCodes.Ldarg_0); Ldfld(emitter); }
public static IILEmitter Emit(this IILEmitter emitter, OpCode code, MemberRef mr) => emitter.Emit(Instruction.Create(code, mr));
public void Ldfld(IILEmitter emitter) { emitter.Emit(Instruction.Create(OpCodes.Ldfld, _resolver?.Invoke(Field) ?? Field)); }