예제 #1
0
 /// <summary>
 /// Checks the data structure for consistency.
 /// </summary>
 public void SanityCheck()
 {
     foreach (var xil3i in Instructions)
     {
         switch (xil3i.Command.Name)
         {
         case InstructionCodes.StoreVar:
         {
             var local = xil3i.StaticOperand as Variable;
             if (local != null)
             {
                 Debug.Assert(Locals.Contains(local));
             }
         }
         break;
         }
     }
 }
예제 #2
0
        public void CompileExpression(Expression e, bool pop = false, bool addressMode = false, Condition cond = null)
        {
            switch (e.ExpressionType)
            {
            case ExpressionType.NoOp:
                break;

            case ExpressionType.AddressOf:
                CompileExpression((e as AddressOf).Operand, pop, true);
                break;

            case ExpressionType.Constant:
            {
                if (cond != null && !cond.Handled)
                {
                    if ((bool)e.ConstantValue)
                    {
                        cond.CanSkipFalse = true;

                        if (cond.Sequence != ConditionSequence.TrueFollows)
                        {
                            Branch(Opcodes.Br, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()));
                        }
                    }
                    else
                    {
                        cond.CanSkipTrue = true;

                        if (cond.Sequence != ConditionSequence.FalseFollows)
                        {
                            Branch(Opcodes.Br, cond.FalseLabel ?? (cond.FalseLabel = NewLabel()));
                        }
                    }

                    cond.Handled = true;
                }
                else if (!pop)
                {
                    if (e.ConstantValue != null)
                    {
                        Emit(Opcodes.Constant, e.ConstantValue);
                    }
                    else if (!e.ReturnType.IsReferenceType || e.ReturnType.IsGenericType)
                    {
                        Emit(Opcodes.DefaultInit, e.ReturnType);
                    }
                    else
                    {
                        Emit(Opcodes.Null);
                    }

                    if (addressMode)
                    {
                        CreateIndirection(e.ReturnType);
                    }
                }
            }
            break;

            case ExpressionType.Default:
            {
                if (cond != null && !cond.Handled)
                {
                    Branch(Opcodes.Br, cond.FalseLabel);
                    cond.Handled = true;
                }
                else if (!pop)
                {
                    Emit(Opcodes.DefaultInit, e.ReturnType);

                    if (addressMode)
                    {
                        CreateIndirection(e.ReturnType);
                    }
                }
            }
            break;

            case ExpressionType.TypeOf:
            {
                if (!pop)
                {
                    Emit(Opcodes.TypeOf, (e as TypeOf).Type);
                }
            }
            break;

            case ExpressionType.This:
            {
                if (pop)
                {
                    return;
                }
                Emit(Opcodes.This);

                if (!addressMode && Function.DeclaringType.IsValueType)
                {
                    Emit(Opcodes.LoadObj, Function.DeclaringType);
                }
            }
            break;

            case ExpressionType.Base:
            {
                if (pop)
                {
                    return;
                }
                Emit(Opcodes.This);

                if (!Function.DeclaringType.IsValueType)
                {
                    return;
                }

                Emit(Opcodes.LoadObj, Function.DeclaringType);
                Emit(Opcodes.Box, Function.DeclaringType);
            }
            break;

            case ExpressionType.SequenceOp:
            {
                var s = e as SequenceOp;
                CompileExpression(s.Left, !s.Left.ReturnType.IsVoid);
                CompileExpression(s.Right, pop, addressMode);
            }
            break;

            case ExpressionType.IsOp:
            {
                var s = e as IsOp;
                CompileExpression(s.Operand, pop);

                if (pop)
                {
                    break;
                }
                if (s.Operand.ReturnType.IsGenericParameter)
                {
                    Emit(Opcodes.Box, s.Operand.ReturnType);
                }

                Emit(Opcodes.AsClass, s.TestType);
                Emit(Opcodes.Null);
                Emit(Opcodes.Neq);

                if (addressMode)
                {
                    CreateIndirection(s.ReturnType);
                }
            }
            break;

            case ExpressionType.AsOp:
            {
                var s = e as AsOp;
                CompileExpression(s.Operand, pop);

                if (pop)
                {
                    break;
                }
                if (s.Operand.ReturnType.IsGenericParameter)
                {
                    Emit(Opcodes.Box, s.Operand.ReturnType);
                }

                Emit(Opcodes.AsClass, s.ReturnType);

                if (s.ReturnType.IsGenericParameter)
                {
                    Emit(Opcodes.UnboxAny, s.ReturnType);
                }
                if (addressMode)
                {
                    CreateIndirection(s.ReturnType);
                }
            }
            break;

            case ExpressionType.LoadLocal:
            {
                var s = e as LoadLocal;
                if (pop)
                {
                    break;
                }

                Emit(addressMode
                                ? Opcodes.LoadLocalAddress
                                : Opcodes.LoadLocal,
                     s.Variable);
            }
            break;

            case ExpressionType.LoadField:
            {
                var s = e as LoadField;

                if (s.Object != null)
                {
                    CompileExpression(s.Object, false, addressMode && s.Object is This);

                    if (pop)
                    {
                        Pop();
                    }
                    else
                    {
                        Emit(addressMode
                                        ? Opcodes.LoadFieldAddress
                                        : Opcodes.LoadField,
                             s.Field);
                    }
                }
                else
                {
                    if (!pop)
                    {
                        Emit(addressMode
                                        ? Opcodes.LoadStaticFieldAddress
                                        : Opcodes.LoadStaticfield,
                             s.Field);
                    }
                }
            }
            break;

            case ExpressionType.LoadElement:
            {
                var s = e as LoadElement;
                CompileExpression(s.Array, pop);
                CompileExpression(s.Index, pop);

                if (pop)
                {
                    return;
                }

                Emit(addressMode
                                ? Opcodes.LoadArrayElementAddress
                                : Opcodes.LoadArrayElement,
                     s.Array.ReturnType.ElementType);
            }
            break;

            case ExpressionType.LoadArgument:
            {
                if (pop)
                {
                    return;
                }
                var s        = e as LoadArgument;
                var paramRef = s.Parameter.IsReference;

                if (paramRef)
                {
                    if (addressMode)
                    {
                        Emit(Opcodes.LoadArg, s.Index);
                    }
                    else
                    {
                        Emit(Opcodes.LoadArg, s.Index);
                        Emit(Opcodes.LoadObj, s.Parameter.Type);
                    }
                }
                else
                {
                    Emit(addressMode
                                    ? Opcodes.LoadArgAddress
                                    : Opcodes.LoadArg,
                         s.Index);
                }
            }
            break;

            case ExpressionType.StoreLocal:
            {
                var s = e as StoreLocal;

                // TODO: This is a workaround for bug in sub ctor calls, remove this later
                if (!Locals.Contains(s.Variable))
                {
                    Locals.Add(s.Variable);
                }

                CompileExpression(s.Value);
                if (!pop)
                {
                    Emit(Opcodes.Dup);
                }
                Emit(Opcodes.StoreLocal, s.Variable);
            }
            break;

            case ExpressionType.StoreArgument:
            {
                var s = e as StoreArgument;

                if (s.Parameter.IsReference)
                {
                    Emit(Opcodes.LoadArg, s.Index);         // Loads the pointer from a out/ref argument
                    CompileExpression(s.Value);
                    var temp = StoreTemp(s.Value.ReturnType, pop);
                    Emit(Opcodes.StoreObj, s.Value.ReturnType);
                    LoadTemp(temp);
                }
                else
                {
                    CompileExpression(s.Value);
                    var temp = StoreTemp(s.Value.ReturnType, pop);
                    Emit(Opcodes.StoreArg, s.Index);
                    LoadTemp(temp);
                }

                if (!pop && addressMode)
                {
                    CreateIndirection(s.ReturnType);
                }
            }
            break;

            case ExpressionType.StoreField:
            {
                var s = e as StoreField;

                if (s.Object != null)
                {
                    CompileObject(s.Object, s.Field);
                    CompileExpression(s.Value);

                    var temp = StoreTemp(s.Value.ReturnType, pop);
                    Emit(Opcodes.StoreField, s.Field);
                    LoadTemp(temp);
                }
                else
                {
                    CompileExpression(s.Value);

                    var temp = StoreTemp(s.Value.ReturnType, pop);
                    Emit(Opcodes.StoreStaticField, s.Field);
                    LoadTemp(temp);
                }

                if (!pop & addressMode)
                {
                    CreateIndirection(s.ReturnType);
                }
            }
            break;

            case ExpressionType.StoreThis:
            {
                var s = e as StoreThis;

                Emit(Opcodes.This);

                if (!pop & addressMode)
                {
                    Emit(Opcodes.Dup);
                }

                CompileExpression(s.Value);
                Emit(Opcodes.StoreObj, s.Value.ReturnType);
            }
            break;

            case ExpressionType.StoreElement:
            {
                var s = e as StoreElement;

                CompileExpression(s.Array);
                CompileExpression(s.Index);
                CompileExpression(s.Value);

                var temp = StoreTemp(s.Value.ReturnType, pop);
                Emit(Opcodes.StoreArrayElement, s.Value.ReturnType);
                LoadTemp(temp);

                if (!pop & addressMode)
                {
                    CreateIndirection(s.ReturnType);
                }
            }
            break;

            case ExpressionType.SetProperty:
            {
                var s = e as SetProperty;
                CompileObject(s.Object, s.Property);

                foreach (var arg in s.Arguments)
                {
                    CompileExpression(arg);
                }

                CompileExpression(s.Value);

                var temp = StoreTemp(s.Value.ReturnType, pop);

                Call(s.Object, s.Property.SetMethod);

                LoadTemp(temp);

                if (!pop & addressMode)
                {
                    CreateIndirection(s.ReturnType);
                }
            }
            break;

            case ExpressionType.GetProperty:
            {
                var s = e as GetProperty;
                CompileObject(s.Object, s.Property);

                foreach (var arg in s.Arguments)
                {
                    CompileExpression(arg);
                }

                if (s.Property.DeclaringType.IsArray && s.Property.Parameters.Length == 0 && s.Property.UnoName == "Length")
                {
                    Emit(Opcodes.LoadArrayLength);
                }
                else
                {
                    Call(s.Object, s.Property.GetMethod);
                }

                if (pop)
                {
                    Pop();
                }
                else if (addressMode)
                {
                    CreateIndirection(s.ReturnType);
                }
            }
            break;

            case ExpressionType.AddListener:
            {
                var s = e as AddListener;
                CompileObject(s.Object, s.Event);
                CompileExpression(s.Listener);
                Call(s.Object, s.Event.AddMethod);
            }
            break;

            case ExpressionType.RemoveListener:
            {
                var s = e as RemoveListener;
                CompileObject(s.Object, s.Event);
                CompileExpression(s.Listener);
                Call(s.Object, s.Event.RemoveMethod);
            }
            break;

            case ExpressionType.ReferenceOp:
            {
                var s = e as ReferenceOp;

                CompileExpression(s.Left);

                if (s.Left.ReturnType.IsGenericParameter)
                {
                    Emit(Opcodes.Box, s.Left.ReturnType);
                }

                CompileExpression(s.Right);

                if (s.Right.ReturnType.IsGenericParameter)
                {
                    Emit(Opcodes.Box, s.Right.ReturnType);
                }

                if (cond != null && !cond.Handled)
                {
                    if (s.EqualityType == EqualityType.NotEqual)
                    {
                        Branch(Opcodes.BrNeq, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()));
                        Branch(Opcodes.Br, cond.FalseLabel ?? (cond.FalseLabel = NewLabel()));
                    }
                    else
                    {
                        Branch(Opcodes.BrEq, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()));
                        Branch(Opcodes.Br, cond.FalseLabel ?? (cond.FalseLabel = NewLabel()));
                    }

                    cond.Handled = true;
                    return;
                }

                Emit(s.EqualityType == EqualityType.NotEqual
                                ? Opcodes.Neq
                                : Opcodes.Eq);

                if (pop)
                {
                    Pop();
                }
                else if (addressMode)
                {
                    CreateIndirection(e.ReturnType);
                }
            }
            break;

            case ExpressionType.BranchOp:
            {
                var s = e as BranchOp;

                if (s.BranchType == BranchType.And)
                {
                    if (cond != null && !cond.Handled)
                    {
                        var brtrue = NewLabel();
                        CompileCondition(s.Left, ConditionSequence.TrueFollows, brtrue, cond.FalseLabel ?? (cond.FalseLabel = NewLabel()));

                        MarkLabel(brtrue);
                        CompileCondition(s.Right, ConditionSequence.NoneFollows, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()), cond.FalseLabel ?? (cond.FalseLabel = NewLabel()));

                        cond.Handled = true;
                    }
                    else
                    {
                        var c = CompileCondition(s.Left, ConditionSequence.TrueFollows);

                        var brafter = NewLabel();

                        MarkLabel(c.TrueLabel);
                        CompileExpression(s.Right);
                        Branch(Opcodes.Br, brafter);

                        MarkLabel(c.FalseLabel);
                        Emit(Opcodes.Constant, false);

                        MarkLabel(brafter);
                    }
                }
                else
                {
                    if (cond != null && !cond.Handled)
                    {
                        var brfalse = NewLabel();
                        CompileCondition(s.Left, ConditionSequence.FalseFollows, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()), brfalse);

                        MarkLabel(brfalse);
                        CompileCondition(s.Right, ConditionSequence.NoneFollows, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()), cond.FalseLabel ?? (cond.FalseLabel = NewLabel()));

                        cond.Handled = true;
                    }
                    else
                    {
                        var c = CompileCondition(s.Left, ConditionSequence.TrueFollows);

                        var brafter = NewLabel();

                        MarkLabel(c.TrueLabel);
                        Emit(Opcodes.Constant, true);
                        Branch(Opcodes.Br, brafter);

                        MarkLabel(c.FalseLabel);
                        CompileExpression(s.Right);

                        MarkLabel(brafter);
                    }
                }
            }
            break;

            case ExpressionType.ConditionalOp:
            {
                var s       = e as ConditionalOp;
                var brtrue  = NewLabel();
                var brfalse = NewLabel();
                var brafter = NewLabel();
                var cc      = CompileCondition(s.Condition, ConditionSequence.TrueFollows, brtrue, brfalse);

                if (!cc.CanSkipTrue)
                {
                    MarkLabel(brtrue);
                    CompileExpression(s.True, pop, addressMode);
                    Branch(Opcodes.Br, brafter);
                }

                if (!cc.CanSkipFalse)
                {
                    MarkLabel(brfalse);
                    CompileExpression(s.False, pop, addressMode);
                }

                MarkLabel(brafter);
            }
            break;

            case ExpressionType.NullOp:
            {
                var s       = e as NullOp;
                var brnull  = NewLabel();
                var brafter = NewLabel();

                CompileExpression(s.Left);
                Emit(Opcodes.Dup);

                if (s.Left.ReturnType.IsGenericParameter)
                {
                    Emit(Opcodes.Box, s.Left.ReturnType);
                }

                Branch(Opcodes.BrNotNull, brafter);

                MarkLabel(brnull);
                Emit(Opcodes.Pop);
                CompileExpression(s.Right);

                MarkLabel(brafter);

                if (pop)
                {
                    Pop();
                }
            }
            break;

            case ExpressionType.CallCast:
            {
                var s = e as CallCast;
                CompileExpression(s.Operand);

                // TODO: Many casts are NOOP - i.e. byte -> char, char -> int
                switch (s.Operand.ReturnType.BuiltinType)
                {
                case BuiltinType.Char:
                case BuiltinType.Byte:
                case BuiltinType.SByte:
                case BuiltinType.UShort:
                case BuiltinType.Short:
                case BuiltinType.UInt:
                case BuiltinType.Int:
                case BuiltinType.ULong:
                case BuiltinType.Long:
                case BuiltinType.Float:
                case BuiltinType.Double:
                    switch (s.ReturnType.BuiltinType)
                    {
                    case BuiltinType.Char: Emit(Opcodes.ConvChar); break;

                    case BuiltinType.Byte: Emit(Opcodes.ConvByte); break;

                    case BuiltinType.SByte: Emit(Opcodes.ConvSByte); break;

                    case BuiltinType.UShort: Emit(Opcodes.ConvUShort); break;

                    case BuiltinType.Short: Emit(Opcodes.ConvShort); break;

                    case BuiltinType.UInt: Emit(Opcodes.ConvUInt); break;

                    case BuiltinType.Int: Emit(Opcodes.ConvInt); break;

                    case BuiltinType.ULong: Emit(Opcodes.ConvULong); break;

                    case BuiltinType.Long: Emit(s.Operand.ReturnType.IsUnsignedType ? Opcodes.ConvULong : Opcodes.ConvLong); break;

                    case BuiltinType.Float: Emit(Opcodes.ConvFloat); break;

                    case BuiltinType.Double: Emit(Opcodes.ConvDouble); break;

                    default: Call(null, s.Cast); break;
                    }

                    break;

                default:
                    Call(null, s.Cast);
                    break;
                }

                if (pop)
                {
                    Pop();
                }
                else if (addressMode)
                {
                    CreateIndirection(s.ReturnType);
                }
            }
            break;

            case ExpressionType.CallConstructor:
            {
                var s = e as CallConstructor;

                Emit(Opcodes.This);

                for (int i = 0; i < s.Arguments.Length; i++)
                {
                    CompileExpression(s.Arguments[i]);
                }

                Call(null, s.Constructor);
            }
            break;

            case ExpressionType.CallMethod:
            {
                var s = e as CallMethod;
                CompileObject(s.Object, s.Method);

                for (int i = 0; i < s.Arguments.Length; i++)
                {
                    CompileExpression(s.Arguments[i]);
                }

                Call(s.Object, s.Method);

                if (!s.ReturnType.IsVoid)
                {
                    if (pop)
                    {
                        Pop();
                    }
                    else if (addressMode)
                    {
                        CreateIndirection(s.ReturnType);
                    }
                }
            }
            break;

            case ExpressionType.CallDelegate:
            {
                var s = e as CallDelegate;
                CompileExpression(s.Object);

                foreach (var arg in s.Arguments)
                {
                    CompileExpression(arg);
                }

                Emit(Opcodes.CallDelegate, s.Object.ReturnType);

                if (!s.ReturnType.IsVoid)
                {
                    if (pop)
                    {
                        Pop();
                    }
                    else if (addressMode)
                    {
                        CreateIndirection(s.ReturnType);
                    }
                }
            }
            break;

            case ExpressionType.CallBinOp:
            {
                CompileBinOp(e as CallBinOp, pop, cond);
                if (addressMode)
                {
                    CreateIndirection(e.ReturnType);
                }
            }
            break;

            case ExpressionType.CallUnOp:
            {
                CompileUnOp(e as CallUnOp, pop);
                if (addressMode)
                {
                    CreateIndirection(e.ReturnType);
                }
            }
            break;

            case ExpressionType.CastOp:
            {
                var s = e as CastOp;
                CompileExpression(s.Operand);

                if (s.ReturnType.IsReferenceType && !s.ReturnType.IsGenericParameter)
                {
                    if (s.Operand.ReturnType.IsValueType || s.Operand.ReturnType.IsGenericParameter)
                    {
                        Emit(Opcodes.Box, s.Operand.ReturnType);
                    }
                    else
                    {
                        Emit(Opcodes.CastClass, s.ReturnType);
                    }

                    if (pop)
                    {
                        Pop();
                    }
                }
                else if (s.Operand.ReturnType.IsReferenceType && !s.Operand.ReturnType.IsGenericParameter)
                {
                    if (s.ReturnType.IsValueType)
                    {
                        Emit(Opcodes.Unbox, s.ReturnType);
                        Emit(Opcodes.LoadObj, s.ReturnType);

                        if (pop)
                        {
                            Pop();
                        }
                        else if (addressMode)
                        {
                            CreateIndirection(e.ReturnType);
                        }
                    }
                    else if (s.ReturnType.IsGenericParameter)
                    {
                        Emit(Opcodes.UnboxAny, s.ReturnType);

                        if (pop)
                        {
                            Pop();
                        }
                        else if (addressMode)
                        {
                            CreateIndirection(e.ReturnType);
                        }
                    }
                    else
                    {
                        Emit(Opcodes.CastClass, s.ReturnType);
                        if (pop)
                        {
                            Pop();
                        }
                    }
                }
                else
                {
                    if (addressMode && !pop)
                    {
                        CreateIndirection(s.ReturnType);
                    }
                }
            }
            break;

            case ExpressionType.NewObject:
            {
                var s = e as NewObject;
                foreach (var arg in s.Arguments)
                {
                    CompileExpression(arg);
                }

                Emit(Opcodes.NewObject, s.Constructor);

                if (pop)
                {
                    Pop();
                }
                else if (s.ReturnType.IsValueType && addressMode)
                {
                    CreateIndirection(e.ReturnType);
                }
            }
            break;

            case ExpressionType.NewDelegate:
            {
                var s = e as NewDelegate;

                if (s.Object != null)
                {
                    CompileExpression(s.Object);
                }
                else
                {
                    Emit(Opcodes.Null);
                }

                if (s.Object == null ||
                    s.Object is Base)
                {
                    Emit(Opcodes.LoadFunction, s.Method);
                }
                else
                {
                    Emit(Opcodes.Dup);
                    Emit(Opcodes.LoadFunctionVirtual, s.Method);
                }

                Emit(Opcodes.NewDelegate, s.ReturnType);
            }
            break;

            case ExpressionType.NewArray:
            {
                var s = e as NewArray;

                if (s.Size != null)
                {
                    CompileExpression(s.Size);
                }
                else
                {
                    Emit(Opcodes.Constant, s.Initializers.Length);
                }

                Emit(Opcodes.NewArray, ((RefArrayType)s.ReturnType).ElementType);

                if (s.Initializers != null)
                {
                    for (int i = 0; i < s.Initializers.Length; i++)
                    {
                        Emit(Opcodes.Dup);
                        Emit(Opcodes.Constant, i);
                        CompileExpression(s.Initializers[i]);
                        Emit(Opcodes.StoreArrayElement, s.Initializers[i].ReturnType);
                    }
                }

                if (pop)
                {
                    Pop();
                }
            }
            break;

            case ExpressionType.FixOp:
                CompileFixOp(e as FixOp, pop, addressMode);
                break;

            case ExpressionType.Swizzle:
            {
                var sw = e as Swizzle;

                CompileExpression(sw.Object);
                var temp = StoreTemp(sw.Object.ReturnType, false);

                foreach (var f in sw.Fields)
                {
                    LoadTemp(temp);
                    Emit(Opcodes.LoadField, f);
                }

                Emit(Opcodes.NewObject, sw.Constructor);

                if (pop)
                {
                    Pop();
                }
                else if (sw.ReturnType.IsValueType && addressMode)
                {
                    CreateIndirection(e.ReturnType);
                }
            }
            break;

            // Shader expression types must be handled to be able to use the bytecode backend for control flow validation of shaders,
            // as well as generating bytecode/assembly shaders
            case ExpressionType.RuntimeConst:
            {
                var s = e as RuntimeConst;
                Emit(Opcodes.GetShaderConst, s.State.RuntimeConstants[s.Index]);
            }
            break;

            case ExpressionType.LoadUniform:
            {
                var s = e as LoadUniform;
                Emit(Opcodes.LoadShaderUniform, s.State.Uniforms[s.Index]);
            }
            break;

            case ExpressionType.LoadPixelSampler:
            {
                var s = e as LoadPixelSampler;
                Emit(Opcodes.LoadShaderPixelSampler, s.State.PixelSamplers[s.Index]);
            }
            break;

            case ExpressionType.LoadVarying:
            {
                var s = e as LoadVarying;
                Emit(Opcodes.LoadShaderVarying, s.State.Varyings[s.Index]);
            }
            break;

            case ExpressionType.LoadVertexAttrib:
            {
                var s = e as LoadVertexAttrib;
                Emit(Opcodes.LoadShaderVarying, s.State.VertexAttributes[s.Index]);
            }
            break;

            case ExpressionType.CallShader:
            {
                var s = e as CallShader;

                for (int i = 0; i < s.Arguments.Length; i++)
                {
                    CompileExpression(s.Arguments[i]);
                }

                Call(null, s.Function);

                if (!s.ReturnType.IsVoid)
                {
                    if (pop)
                    {
                        Pop();
                    }
                    else if (addressMode)
                    {
                        CreateIndirection(s.ReturnType);
                    }
                }
            }
            break;

            case ExpressionType.LoadPtr:
            {
                var s = e as LoadPtr;
                CompileExpression(s.Argument, pop, addressMode, cond);
            }
            break;

            default:
                throw new Exception("<" + e.ExpressionType + "> is not supported in bytecode backend - at " + e.Source);
            }
        }