PixelMagic.CodeGenContext.EmitBinary C# (CSharp) Method

EmitBinary() private method

private EmitBinary ( BinOpKind op ) : void
op BinOpKind
return void
        internal void EmitBinary(BinOpKind op)
        {
            //FIXME it might be an issue if arguments are not of type Vector4f
            MethodInfo mi = null;
            switch (op) {
            case BinOpKind.Add:
                mi = typeof (Vector4f).GetMethod ("op_Addition");
                break;
            case BinOpKind.Sub:
                mi = typeof (Vector4f).GetMethod ("op_Subtraction");
                break;
            case BinOpKind.Mul:
                mi = typeof (Vector4f).GetMethod ("op_Multiply");
                break;
            case BinOpKind.Max:
                mi = typeof (VectorOperations).GetMethod ("Max", new Type[] { typeof (Vector4f), typeof (Vector4f)});
                break;
            case BinOpKind.Dp3:
                //This is a very fuck'd up code sequence, figure out how to speed it up
                ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Multiply"));
                ilgen.Emit (OpCodes.Dup);
                ilgen.Emit (OpCodes.Dup);
                //FIXME we could use HorizontalAdd for this step
                EmitShuffle (ShuffleSel.XFromY); //[x,y,z,w] [x,y,z,w] [y,y,z,w]
                ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Addition")); //[x,y,z,w] [x + y,_,_,_]

                EmitShuffle (ShuffleSel.ZFromY); //[x,y,z,w] [_,_,x + y, _]
                ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Addition")); //[_,_, x + y + z, _]
                EmitShuffle (ShuffleSel.ExpandZ); //[dp3, dp3, dp3, dp3]
                break;
            case BinOpKind.Dp4:
                //We should use things like HorizontalAdd  or the new Dp instruction
                ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Multiply"));
                ilgen.Emit (OpCodes.Dup);

                EmitShuffle (ShuffleSel.XFromY | ShuffleSel.ZFromW); //[x,y,z,w] [y,y,w,w]
                ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Addition")); //[x + y,_,z + w,_]
                ilgen.Emit (OpCodes.Dup); //[x + y,_,z + w,_] [x + y,_,z + w,_]

                EmitShuffle (ShuffleSel.XFromZ); //[x + y,_,_,_] [z + w,_,_,_]
                ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Addition")); //[x + y + z + w,_,_,_]
                EmitShuffle (ShuffleSel.ExpandX); //[dp4, dp4, dp4, dp4]
                break;
            case BinOpKind.Min:
                mi = typeof (VectorOperations).GetMethod ("Min", new Type[] { typeof (Vector4f), typeof (Vector4f)});
                break;
            case BinOpKind.Slt:
            case BinOpKind.Sge:
                //XXX hoist the constant out of the loop
                mi = typeof (VectorOperations).GetMethod ("CompareLessThan", new Type[] { typeof (Vector4f), typeof (Vector4f)});
                ilgen.Emit (OpCodes.Ldc_R4, 1f);
                ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetConstructor (new Type [] {typeof (float) }));
                if (op == BinOpKind.Slt)
                    ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_BitwiseAnd"));
                else
                    ilgen.Emit (OpCodes.Call, typeof (VectorOperations).GetMethod ("AndNot", new Type[] { typeof (Vector4f), typeof (Vector4f)}));
                break;
            default:
                throw new Exception ("can't handle binop " + op);
            }
            if (mi != null)
                ilgen.Emit (OpCodes.Call, mi);
        }

Usage Example

Example #1
0
 public override void EmitBody(CodeGenContext ctx)
 {
     ctx.LoadValue (src1);
     ctx.LoadValue (src2);
     ctx.EmitBinary (op);
     ctx.StoreValue (dest);
 }