protected internal virtual void TraverseOperator(Operator op) { op.Unsupported(); }
protected internal override Node TransformOperator(Operator op) { return Dispatch(op); }
protected internal override void TraverseOperator(Operator op) { Dispatch(op); }
protected internal override void TraverseOperator(Operator op) { op.Args.ForEach(Traverse); // todo. also support nullables and lifted versions of operators op.Args.Any(arg => Types[arg].IsNullable()).AssertFalse(); var impArgs = op.Args; var anyBool = impArgs.Any(arg => Types[arg] == typeof(bool)); if (anyBool) { Types.Add(op, typeof(bool)); return; } var opt = op.OperatorType; if (opt.IsAssign() || opt == OperatorType.Coalesce || opt == OperatorType.LeftShift || opt == OperatorType.RightShift) { Types.Add(op, Types[op.Args.First()]); } else if (opt == OperatorType.AndAlso || opt == OperatorType.OrElse || opt == OperatorType.Not || opt == OperatorType.GreaterThan || opt == OperatorType.GreaterThanOrEqual || opt == OperatorType.Equal || opt == OperatorType.NotEqual || opt == OperatorType.LessThan || opt == OperatorType.LessThanOrEqual) { Types.Add(op, typeof(bool)); } else { if (op.IsUnary()) { var t_target = Types[op.Unary().Target]; if (t_target == null) Types.Add(op, null); else { (t_target.IsInteger() || t_target.IsFloatingPoint()).AssertTrue(); Types.Add(op, t_target); } } else if (op.IsBinary()) { var t_lhs = Types[op.Binary().Lhs]; var t_rhs = Types[op.Binary().Rhs]; if (t_lhs == null || t_rhs == null) Types.Add(op, null); else { if (t_lhs.IsInteger() && t_rhs.IsInteger()) { Func<Type, int> bitness = t => t == typeof(sbyte) || t == typeof(byte) ? 8 : t == typeof(short) || t == typeof(ushort) ? 16 : t == typeof(int) || t == typeof(uint) ? 32 : t == typeof(long) || t == typeof(ulong) ? 64 : ((Func<int>)(() => { throw AssertionHelper.Fail(); }))(); Func<Type, bool> signed = t => t == typeof(sbyte) || t == typeof(short) || t == typeof(int) || t == typeof(long) ? true : t == typeof(byte) || t == typeof(ushort) || t == typeof(uint) || t == typeof(ulong) ? false : ((Func<bool>)(() => { throw AssertionHelper.Fail(); }))(); Func<int, bool, Type> mk_int = (n_bits, is_signed) => { if (n_bits == 8) return is_signed ? typeof(sbyte) : typeof(byte); if (n_bits == 16) return is_signed ? typeof(short) : typeof(ushort); if (n_bits == 32) return is_signed ? typeof(int) : typeof(uint); if (n_bits == 64) return is_signed ? typeof(long) : typeof(ulong); throw AssertionHelper.Fail(); }; // todo. the rules below are specific to C# Func<Type, Type, bool> has_cast_to = (wb, t) => wb == t || bitness(wb) < bitness(t); Func<Type, Type, bool> args_match = (t1, t2) => has_cast_to(t_lhs, t1) && has_cast_to(t_rhs, t2); Type t_result = null; if (args_match(typeof(int), typeof(int))) t_result = typeof(int); else if (args_match(typeof(uint), typeof(uint))) t_result = typeof(uint); else if (args_match(typeof(long), typeof(long))) t_result = typeof(long); else if (args_match(typeof(ulong), typeof(ulong))) t_result = typeof(ulong); else t_result.AssertNotNull(); Types.Add(op, t_result); } else { (t_lhs.IsFloatingPoint() && t_rhs.IsFloatingPoint()).AssertTrue(); if (t_lhs == typeof(double) || t_rhs == typeof(double)) Types.Add(op, typeof(double)); else if (t_lhs == typeof(float) || t_rhs == typeof(float)) Types.Add(op, typeof(float)); else throw AssertionHelper.Fail(); } } } else { throw AssertionHelper.Fail(); } } }
protected override void TraverseOperator(Operator op) { var lhs = op.Args.FirstOrDefault(); var rhs = op.Args.SecondOrDefault(); var targ = op.Args.FirstOrDefault(); var opt = op.OperatorType; if (opt.IsAssign()) { // todo. implement this with the use of SafeExpandOpAssign var equiv = op.UnsafeExpandOpAssign(); Traverse(equiv); } else if (opt == OperatorType.AndAlso) { var equiv = new Conditional(lhs, rhs, new Const(false)); Traverse(equiv); } else if (opt == OperatorType.OrElse) { var equiv = new Conditional(lhs, new Const(true), rhs); Traverse(equiv); } else { op.Args.ForEach(Traverse); switch (opt) { case OperatorType.Add: il.add(); break; case OperatorType.And: il.and(); break; case OperatorType.Divide: il.div(); break; case OperatorType.Equal: il.ceq(); break; case OperatorType.GreaterThan: il.cgt(); break; case OperatorType.GreaterThanOrEqual: il.cge(); break; case OperatorType.LeftShift: il.shl(); break; case OperatorType.LessThan: il.clt(); break; case OperatorType.LessThanOrEqual: il.cle(); break; case OperatorType.Modulo: il.rem(); break; case OperatorType.Multiply: il.mul(); break; case OperatorType.Negate: il.neg(); break; case OperatorType.Not: var is_bool = targ.Type() == typeof(bool); if (is_bool) il.ldc_i4(0).ceq(); else il.not(); break; case OperatorType.NotEqual: il.cne(); break; case OperatorType.Or: il.or(); break; case OperatorType.RightShift: il.shr(); break; case OperatorType.Subtract: il.sub(); break; case OperatorType.Xor: il.xor(); break; default: throw AssertionHelper.Fail(); } } }
protected override void TraverseOperator(Operator op) { var lhs = op.Args.FirstOrDefault(); var rhs = op.Args.SecondOrDefault(); var targ = op.Args.FirstOrDefault(); var opt = op.OperatorType; if (opt.IsAssign()) { var equiv = op.UnsafeExpandOpAssign(); _ptx.ld(equiv); } else if (opt == OperatorType.AndAlso) { var equiv = new Conditional(lhs, rhs, new Const(false)); _ptx.ld(equiv); } else if (opt == OperatorType.OrElse) { var equiv = new Conditional(lhs, new Const(true), rhs); _ptx.ld(equiv); } else { op.Args.ForEach(arg => _ptx.ld(arg)); switch (opt) { case OperatorType.Add: _ptx.op("add"); break; case OperatorType.And: _ptx.op("and"); break; case OperatorType.Divide: _ptx.op("div"); break; case OperatorType.Equal: _ptx.op("setp.eq"); break; case OperatorType.GreaterThan: _ptx.op("setp.gt"); break; case OperatorType.GreaterThanOrEqual: _ptx.op("setp.ge"); break; case OperatorType.LeftShift: _ptx.op("shl"); break; case OperatorType.LessThan: _ptx.op("setp.lt"); break; case OperatorType.LessThanOrEqual: _ptx.op("setp.le"); break; case OperatorType.Modulo: _ptx.op("rem"); break; case OperatorType.Multiply: var t = _ptx.peek_expr().Type; _ptx.op(t.is_int() ? "mul.lo" : "mul"); break; case OperatorType.Negate: _ptx.op("neg"); break; case OperatorType.Not: _ptx.ld("not"); break; case OperatorType.NotEqual: _ptx.op("setp.ne"); break; case OperatorType.Or: _ptx.op("or"); break; case OperatorType.RightShift: _ptx.op("shr"); break; case OperatorType.Subtract: _ptx.op("sub"); break; case OperatorType.Xor: _ptx.op("xor"); break; default: throw AssertionHelper.Fail(); } } }
protected internal override void TraverseOperator(Operator op) { var opt = op.OperatorType; if (op.IsUnary()) { if (!opt.ToString().StartsWith("Post")) _writer.Write(opt.ToCSharpSymbol()); Traverse(op.Args.First()); if (opt.ToString().StartsWith("Post")) _writer.Write(opt.ToCSharpSymbol()); } else if (op.IsBinary()) { Traverse(op.Args.First()); _writer.Write(" " + opt.ToCSharpSymbol() + " "); Traverse(op.Args.Second()); } else { op.Unsupported(); } }
protected internal virtual Node TransformOperator(Operator op) { return op.AcceptTransformer(this, true); }