static Expression GenerateExpression(RandomGenerator random, Expression current, int currentDepth, int targetDepth) { if (currentDepth == targetDepth || (currentDepth > targetDepth / 3 && random.NextInt32(100) > 85)) return current; switch ((ExpressionOps)random.NextInt32(6)) { case ExpressionOps.Add: return GenerateExpression(random, current, currentDepth + 1, targetDepth) + GenerateExpression(random, (LiteralExpression)random.NextUInt32(), currentDepth + 1, targetDepth); case ExpressionOps.Sub: return GenerateExpression(random, current, currentDepth + 1, targetDepth) - GenerateExpression(random, (LiteralExpression)random.NextUInt32(), currentDepth + 1, targetDepth); case ExpressionOps.Mul: return GenerateExpression(random, current, currentDepth + 1, targetDepth) * (LiteralExpression)(random.NextUInt32() | 1); case ExpressionOps.Xor: return GenerateExpression(random, current, currentDepth + 1, targetDepth) ^ GenerateExpression(random, (LiteralExpression)random.NextUInt32(), currentDepth + 1, targetDepth); case ExpressionOps.Not: return ~GenerateExpression(random, current, currentDepth + 1, targetDepth); case ExpressionOps.Neg: return -GenerateExpression(random, current, currentDepth + 1, targetDepth); } throw new UnreachableException(); }
static Expression ProcessExpression(Expression exp) { if (exp is BinOpExpression) { var binOp = (BinOpExpression)exp; var binOpRight = binOp.Right as BinOpExpression; // a + (b + c) => (a + b) + c if (binOpRight != null && binOpRight.Operation == binOp.Operation && (binOp.Operation == BinOps.Add || binOp.Operation == BinOps.Mul || binOp.Operation == BinOps.Or || binOp.Operation == BinOps.And || binOp.Operation == BinOps.Xor)) { binOp.Left = new BinOpExpression { Left = binOp.Left, Operation = binOp.Operation, Right = binOpRight.Left }; binOp.Right = binOpRight.Right; } binOp.Left = ProcessExpression(binOp.Left); binOp.Right = ProcessExpression(binOp.Right); if (binOp.Right is LiteralExpression && ((LiteralExpression)binOp.Right).Value == 0 && binOp.Operation == BinOps.Add) // x + 0 => x return binOp.Left; } else if (exp is ArrayIndexExpression) { ((ArrayIndexExpression)exp).Array = ProcessExpression(((ArrayIndexExpression)exp).Array); } else if (exp is UnaryOpExpression) { ((UnaryOpExpression)exp).Value = ProcessExpression(((UnaryOpExpression)exp).Value); } return exp; }
public static void GeneratePair(RandomGenerator random, Expression var, Expression result, int depth, out Expression expression, out Expression inverse) { expression = GenerateExpression(random, var, 0, depth); SwapOperands(random, expression); var hasVar = new Dictionary<Expression, bool>(); HasVariable(expression, hasVar); inverse = GenerateInverse(expression, result, hasVar); }
void Compile(RPContext ctx, CilBody body, out Func<int, int> expCompiled, out Expression inverse) { var var = new Variable("{VAR}"); var result = new Variable("{RESULT}"); Expression expression; ctx.DynCipher.GenerateExpressionPair( ctx.Random, new VariableExpression { Variable = var }, new VariableExpression { Variable = result }, ctx.Depth, out expression, out inverse); expCompiled = new DMCodeGen(typeof(int), new[] { Tuple.Create("{VAR}", typeof(int)) }) .GenerateCIL(expression) .Compile<Func<int, int>>(); }
static IEnumerable<Variable> GetVariableUsage(Expression exp) { if (exp is VariableExpression) yield return ((VariableExpression)exp).Variable; else if (exp is ArrayIndexExpression) { foreach (Variable i in GetVariableUsage(((ArrayIndexExpression)exp).Array)) yield return i; } else if (exp is BinOpExpression) { foreach (Variable i in GetVariableUsage(((BinOpExpression)exp).Left) .Concat(GetVariableUsage(((BinOpExpression)exp).Right))) yield return i; } else if (exp is UnaryOpExpression) { foreach (Variable i in GetVariableUsage(((UnaryOpExpression)exp).Value)) yield return i; } }
static void SwapOperands(RandomGenerator random, Expression exp) { if (exp is BinOpExpression) { var binExp = (BinOpExpression)exp; if (random.NextBoolean()) { Expression tmp = binExp.Left; binExp.Left = binExp.Right; binExp.Right = tmp; } SwapOperands(random, binExp.Left); SwapOperands(random, binExp.Right); } else if (exp is UnaryOpExpression) SwapOperands(random, ((UnaryOpExpression)exp).Value); else if (exp is LiteralExpression || exp is VariableExpression) return; else throw new UnreachableException(); }
public x86Register? GenerateX86(Expression expression, Func<Variable, x86Register, IEnumerable<x86Instruction>> loadArg) { instrs = new List<x86Instruction>(); usedRegs = new bool[8]; MaxUsedRegister = -1; // CRITICAL registers! usedRegs[(int)x86Register.EBP] = true; usedRegs[(int)x86Register.ESP] = true; try { return ((x86RegisterOperand)Emit(expression, loadArg)).Register; } catch (Exception ex) { if (ex.Message == "Register overflowed.") return null; throw; } }
private static Expression ProcessExpression(Expression exp) { if (exp is BinOpExpression) { var binOp = (BinOpExpression)exp; if (binOp.Operation == BinOps.Mul && binOp.Right is LiteralExpression) { // Decompose multiplication into shifts, e.g. x * 3 => x << 1 + x uint literal = ((LiteralExpression)binOp.Right).Value; if (literal == 0) return (LiteralExpression)0; if (literal == 1) return binOp.Left; uint bits = NumberOfSetBits(literal); if (bits <= 2) { var sum = new List<Expression>(); int n = 0; while (literal != 0) { if ((literal & 1) != 0) { if (n == 0) sum.Add(binOp.Left); else sum.Add(binOp.Left << n); } literal >>= 1; n++; } BinOpExpression x = sum.OfType<BinOpExpression>().First(); foreach (Expression i in sum.Except(new[] { x })) x += i; return x; } } else { binOp.Left = ProcessExpression(binOp.Left); binOp.Right = ProcessExpression(binOp.Right); } } else if (exp is ArrayIndexExpression) { ((ArrayIndexExpression)exp).Array = ProcessExpression(((ArrayIndexExpression)exp).Array); } else if (exp is UnaryOpExpression) { ((UnaryOpExpression)exp).Value = ProcessExpression(((UnaryOpExpression)exp).Value); } return exp; }
static bool HasVariable(Expression exp, Dictionary<Expression, bool> hasVar) { bool ret; if (!hasVar.TryGetValue(exp, out ret)) { if (exp is VariableExpression) ret = true; else if (exp is LiteralExpression) ret = false; else if (exp is BinOpExpression) { var binExp = (BinOpExpression)exp; ret = HasVariable(binExp.Left, hasVar) || HasVariable(binExp.Right, hasVar); } else if (exp is UnaryOpExpression) { ret = HasVariable(((UnaryOpExpression)exp).Value, hasVar); } else throw new UnreachableException(); hasVar[exp] = ret; } return ret; }
static Expression ReplaceVar(Expression exp, Variable buff) { if (exp is VariableExpression) { if (((VariableExpression)exp).Variable.Name[0] != 'v') return exp; return new ArrayIndexExpression { Array = new VariableExpression { Variable = buff }, Index = (int)(exp as VariableExpression).Variable.Tag }; } if (exp is ArrayIndexExpression) { ((ArrayIndexExpression)exp).Array = ReplaceVar(((ArrayIndexExpression)exp).Array, buff); } else if (exp is BinOpExpression) { ((BinOpExpression)exp).Left = ReplaceVar(((BinOpExpression)exp).Left, buff); ((BinOpExpression)exp).Right = ReplaceVar(((BinOpExpression)exp).Right, buff); } else if (exp is UnaryOpExpression) { ((UnaryOpExpression)exp).Value = ReplaceVar(((UnaryOpExpression)exp).Value, buff); } return exp; }
void EmitStore(Expression exp, Expression value) { if (exp is ArrayIndexExpression) { var arrIndex = (ArrayIndexExpression)exp; EmitLoad(arrIndex.Array); Emit(Instruction.CreateLdcI4(arrIndex.Index)); EmitLoad(value); Emit(Instruction.Create(OpCodes.Stelem_I4)); } else if (exp is VariableExpression) { var var = (VariableExpression)exp; EmitLoad(value); StoreVar(var.Variable); } else throw new NotSupportedException(); }
static Expression GenerateInverse(Expression exp, Expression var, Dictionary<Expression, bool> hasVar) { Expression result = var; while (!(exp is VariableExpression)) { Debug.Assert(hasVar[exp]); if (exp is UnaryOpExpression) { var unaryOp = (UnaryOpExpression)exp; result = new UnaryOpExpression { Operation = unaryOp.Operation, Value = result }; exp = unaryOp.Value; } else if (exp is BinOpExpression) { var binOp = (BinOpExpression)exp; bool leftHasVar = hasVar[binOp.Left]; Expression varExp = leftHasVar ? binOp.Left : binOp.Right; Expression constExp = leftHasVar ? binOp.Right : binOp.Left; if (binOp.Operation == BinOps.Add) result = new BinOpExpression { Operation = BinOps.Sub, Left = result, Right = constExp }; else if (binOp.Operation == BinOps.Sub) { if (leftHasVar) { // v - k = r => v = r + k result = new BinOpExpression { Operation = BinOps.Add, Left = result, Right = constExp }; } else { // k - v = r => v = k - r result = new BinOpExpression { Operation = BinOps.Sub, Left = constExp, Right = result }; } } else if (binOp.Operation == BinOps.Mul) { Debug.Assert(constExp is LiteralExpression); uint val = ((LiteralExpression)constExp).Value; val = MathsUtils.modInv(val); result = new BinOpExpression { Operation = BinOps.Mul, Left = result, Right = (LiteralExpression)val }; } else if (binOp.Operation == BinOps.Xor) result = new BinOpExpression { Operation = BinOps.Xor, Left = result, Right = constExp }; exp = varExp; } } return result; }
public void GenerateExpressionPair(RandomGenerator random, Expression var, Expression result, int depth, out Expression expression, out Expression inverse) { ExpressionGenerator.GeneratePair(random, var, result, depth, out expression, out inverse); }
private static IEnumerable<Variable> GetVariableDefinition(Expression exp) { if (exp is VariableExpression) yield return ((VariableExpression)exp).Variable; }
public void GenerateCIL(Expression expression) { EmitLoad(expression); }
void EmitLoad(Expression exp) { if (exp is ArrayIndexExpression) { var arrIndex = (ArrayIndexExpression)exp; EmitLoad(arrIndex.Array); Emit(Instruction.CreateLdcI4(arrIndex.Index)); Emit(Instruction.Create(OpCodes.Ldelem_U4)); } else if (exp is BinOpExpression) { var binOp = (BinOpExpression)exp; EmitLoad(binOp.Left); EmitLoad(binOp.Right); OpCode op; switch (binOp.Operation) { case BinOps.Add: op = OpCodes.Add; break; case BinOps.Sub: op = OpCodes.Sub; break; case BinOps.Div: op = OpCodes.Div; break; case BinOps.Mul: op = OpCodes.Mul; break; case BinOps.Or: op = OpCodes.Or; break; case BinOps.And: op = OpCodes.And; break; case BinOps.Xor: op = OpCodes.Xor; break; case BinOps.Lsh: op = OpCodes.Shl; break; case BinOps.Rsh: op = OpCodes.Shr_Un; break; default: throw new NotSupportedException(); } Emit(Instruction.Create(op)); } else if (exp is UnaryOpExpression) { var unaryOp = (UnaryOpExpression)exp; EmitLoad(unaryOp.Value); OpCode op; switch (unaryOp.Operation) { case UnaryOps.Not: op = OpCodes.Not; break; case UnaryOps.Negate: op = OpCodes.Neg; break; default: throw new NotSupportedException(); } Emit(Instruction.Create(op)); } else if (exp is LiteralExpression) { var literal = (LiteralExpression)exp; Emit(Instruction.CreateLdcI4((int)literal.Value)); } else if (exp is VariableExpression) { var var = (VariableExpression)exp; LoadVar(var.Variable); } else throw new NotSupportedException(); }
private Ix86Operand Emit(Expression exp, Func<Variable, x86Register, IEnumerable<x86Instruction>> loadArg) { if (exp is BinOpExpression) { var binOp = (BinOpExpression)exp; x86Register reg; switch (binOp.Operation) { case BinOps.Add: reg = Normalize(x86Instruction.Create(x86OpCode.ADD, Emit(binOp.Left, loadArg), Emit(binOp.Right, loadArg))); break; case BinOps.Sub: reg = Normalize(x86Instruction.Create(x86OpCode.SUB, Emit(binOp.Left, loadArg), Emit(binOp.Right, loadArg))); break; case BinOps.Mul: reg = Normalize(x86Instruction.Create(x86OpCode.IMUL, Emit(binOp.Left, loadArg), Emit(binOp.Right, loadArg))); break; case BinOps.Xor: reg = Normalize(x86Instruction.Create(x86OpCode.XOR, Emit(binOp.Left, loadArg), Emit(binOp.Right, loadArg))); break; default: throw new NotSupportedException(); } TakeRegister(reg); return new x86RegisterOperand(reg); } if (exp is UnaryOpExpression) { var unaryOp = (UnaryOpExpression)exp; x86Register reg; switch (unaryOp.Operation) { case UnaryOps.Negate: reg = Normalize(x86Instruction.Create(x86OpCode.NEG, Emit(unaryOp.Value, loadArg))); break; case UnaryOps.Not: reg = Normalize(x86Instruction.Create(x86OpCode.NOT, Emit(unaryOp.Value, loadArg))); break; default: throw new NotSupportedException(); } TakeRegister(reg); return new x86RegisterOperand(reg); } if (exp is LiteralExpression) return new x86ImmediateOperand((int)((LiteralExpression)exp).Value); if (exp is VariableExpression) { x86Register reg = GetFreeRegister(); TakeRegister(reg); instrs.AddRange(loadArg(((VariableExpression)exp).Variable, reg)); return new x86RegisterOperand(reg); } throw new NotSupportedException(); }