public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            if (_cachedReadAccessor is not ICompilablePropertyAccessor accessorToUse)
            {
                throw new InvalidOperationException("Property accessor is not compilable: " + _cachedReadAccessor);
            }

            Label?skipIfNullLabel = null;

            if (_nullSafe)
            {
                skipIfNullLabel = gen.DefineLabel();
                gen.Emit(OpCodes.Dup);
                gen.Emit(OpCodes.Ldnull);
                gen.Emit(OpCodes.Cgt_Un);
                gen.Emit(OpCodes.Brfalse, skipIfNullLabel.Value);
            }

            accessorToUse.GenerateCode(_name, gen, cf);
            cf.PushDescriptor(_exitTypeDescriptor);
            if (_originalPrimitiveExitTypeDescriptor != null)
            {
                // The output of the accessor is a primitive but from the block above it might be null,
                // so to have a common stack element type at skipIfNull target it is necessary
                // to box the primitive
                CodeFlow.InsertBoxIfNecessary(gen, _originalPrimitiveExitTypeDescriptor);
            }

            if (skipIfNullLabel.HasValue)
            {
                gen.MarkLabel(skipIfNullLabel.Value);
            }
        }
示例#2
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            if (_exitTypeDescriptor == TypeDescriptor.STRING)
            {
                gen.Emit(OpCodes.Newobj, _sbConstructor);
                Walk(gen, cf, LeftOperand);
                Walk(gen, cf, RightOperand);
                gen.Emit(OpCodes.Callvirt, _toString);
            }
            else
            {
                _children[0].GenerateCode(gen, cf);
                var leftDesc = _children[0].ExitDescriptor;
                var exitDesc = _exitTypeDescriptor;
                if (exitDesc == null)
                {
                    throw new InvalidOperationException("No exit type descriptor");
                }

                CodeFlow.InsertNumericUnboxOrPrimitiveTypeCoercion(gen, leftDesc, exitDesc);
                if (_children.Length > 1)
                {
                    cf.EnterCompilationScope();
                    _children[1].GenerateCode(gen, cf);
                    var rightDesc = _children[1].ExitDescriptor;
                    cf.ExitCompilationScope();
                    CodeFlow.InsertNumericUnboxOrPrimitiveTypeCoercion(gen, rightDesc, exitDesc);
                    gen.Emit(OpCodes.Add);
                }
            }

            cf.PushDescriptor(_exitTypeDescriptor);
        }
示例#3
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            // pseudo: if (leftOperandValue) { result=true; } else { result=rightOperandValue; }
            var elseTarget  = gen.DefineLabel();
            var endIfTarget = gen.DefineLabel();
            var result      = gen.DeclareLocal(typeof(bool));

            cf.EnterCompilationScope();
            LeftOperand.GenerateCode(gen, cf);
            cf.UnboxBooleanIfNecessary(gen);
            cf.ExitCompilationScope();
            gen.Emit(OpCodes.Brfalse, elseTarget);
            gen.Emit(OpCodes.Ldc_I4_1);
            gen.Emit(OpCodes.Stloc, result);
            gen.Emit(OpCodes.Br, endIfTarget);
            gen.MarkLabel(elseTarget);
            cf.EnterCompilationScope();
            RightOperand.GenerateCode(gen, cf);
            cf.UnboxBooleanIfNecessary(gen);
            cf.ExitCompilationScope();
            gen.Emit(OpCodes.Stloc, result);
            gen.MarkLabel(endIfTarget);
            gen.Emit(OpCodes.Ldloc, result);
            cf.PushDescriptor(_exitTypeDescriptor);
        }
示例#4
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            CodeFlow.LoadEvaluationContext(gen);
            var leftDesc  = LeftOperand.ExitDescriptor;
            var rightDesc = RightOperand.ExitDescriptor;
            var leftPrim  = CodeFlow.IsValueType(leftDesc);
            var rightPrim = CodeFlow.IsValueType(rightDesc);

            cf.EnterCompilationScope();
            LeftOperand.GenerateCode(gen, cf);
            cf.ExitCompilationScope();
            if (leftPrim)
            {
                CodeFlow.InsertBoxIfNecessary(gen, leftDesc);
            }

            cf.EnterCompilationScope();
            RightOperand.GenerateCode(gen, cf);
            cf.ExitCompilationScope();
            if (rightPrim)
            {
                CodeFlow.InsertBoxIfNecessary(gen, rightDesc);
            }

            gen.Emit(OpCodes.Call, _equalityCheck);
            cf.PushDescriptor(TypeDescriptor.Z);
        }
示例#5
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            LeftOperand.GenerateCode(gen, cf);
            var leftDesc = LeftOperand.ExitDescriptor;
            var exitDesc = _exitTypeDescriptor;

            if (exitDesc == null)
            {
                throw new InvalidOperationException("No exit type descriptor");
            }

            CodeFlow.InsertNumericUnboxOrPrimitiveTypeCoercion(gen, leftDesc, exitDesc);
            if (_children.Length > 1)
            {
                cf.EnterCompilationScope();
                RightOperand.GenerateCode(gen, cf);
                var rightDesc = RightOperand.ExitDescriptor;
                cf.ExitCompilationScope();
                CodeFlow.InsertNumericUnboxOrPrimitiveTypeCoercion(gen, rightDesc, exitDesc);
                gen.Emit(OpCodes.Sub);
            }
            else
            {
                gen.Emit(OpCodes.Neg);
            }

            cf.PushDescriptor(_exitTypeDescriptor);
        }
示例#6
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            foreach (var child in _children)
            {
                child.GenerateCode(gen, cf);
            }

            cf.PushDescriptor(_exitTypeDescriptor);
        }
示例#7
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            var constantFieldName = "inlineList$" + cf.NextFieldId();

            cf.RegisterNewField(constantFieldName, new List <object>());
            cf.RegisterNewInitGenerator((initGenerator, cflow) => { GenerateInitCode(constantFieldName, initGenerator, cflow); });

            GenerateLoadListCode(gen, constantFieldName);
            cf.PushDescriptor(new TypeDescriptor(typeof(IList)));
        }
示例#8
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            if (_type == null)
            {
                throw new InvalidOperationException("No type available");
            }

            gen.Emit(OpCodes.Ldtoken, _type);
            gen.Emit(OpCodes.Call, _getTypeFromHandle);
            cf.PushDescriptor(_exitTypeDescriptor);
        }
示例#9
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            // May reach here without it computed if all elements are literals
            ComputeExitTypeDescriptor();

            cf.EnterCompilationScope();
            _children[0].GenerateCode(gen, cf);
            var lastDesc = cf.LastDescriptor() ?? throw new InvalidOperationException("No last descriptor");

            if (!CodeFlow.IsValueType(lastDesc))
            {
                gen.Emit(OpCodes.Unbox_Any, typeof(bool));
            }

            cf.ExitCompilationScope();

            var elseTarget    = gen.DefineLabel();
            var endOfIfTarget = gen.DefineLabel();

            gen.Emit(OpCodes.Brfalse, elseTarget);
            cf.EnterCompilationScope();
            _children[1].GenerateCode(gen, cf);
            if (!CodeFlow.IsValueType(_exitTypeDescriptor))
            {
                lastDesc = cf.LastDescriptor();
                if (lastDesc == null)
                {
                    throw new InvalidOperationException("No last descriptor");
                }

                CodeFlow.InsertBoxIfNecessary(gen, lastDesc);
            }

            cf.ExitCompilationScope();
            gen.Emit(OpCodes.Br, endOfIfTarget);

            gen.MarkLabel(elseTarget);
            cf.EnterCompilationScope();
            _children[2].GenerateCode(gen, cf);
            if (!CodeFlow.IsValueType(_exitTypeDescriptor))
            {
                lastDesc = cf.LastDescriptor();
                if (lastDesc == null)
                {
                    throw new InvalidOperationException("No last descriptor");
                }

                CodeFlow.InsertBoxIfNecessary(gen, lastDesc);
            }

            cf.ExitCompilationScope();
            gen.MarkLabel(endOfIfTarget);
            cf.PushDescriptor(_exitTypeDescriptor);
        }
示例#10
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            var method = _method;

            if (method == null)
            {
                throw new InvalidOperationException("No method handle");
            }

            GenerateCodeForArguments(gen, cf, method, _children);
            gen.Emit(OpCodes.Call, method);
            cf.PushDescriptor(_exitTypeDescriptor);
        }
示例#11
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            var method = GetTargetMethodAndType(out var classType);

            if (method.IsStatic)
            {
                GenerateStaticMethodCode(gen, cf, method);
            }
            else
            {
                GenerateInstanceMethodCode(gen, cf, method, classType);
            }

            cf.PushDescriptor(_exitTypeDescriptor);
        }
示例#12
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            if (_name.Equals(ROOT))
            {
                CodeFlow.LoadTarget(gen);
            }
            else
            {
                gen.Emit(OpCodes.Ldarg_2);
                gen.Emit(OpCodes.Ldstr, _name);
                gen.Emit(OpCodes.Callvirt, GetLookUpVariableMethod());
            }

            CodeFlow.InsertCastClass(gen, _exitTypeDescriptor);
            cf.PushDescriptor(_exitTypeDescriptor);
        }
示例#13
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            var result = gen.DeclareLocal(typeof(bool));

            if (_value.Equals(BooleanTypedValue.TRUE))
            {
                gen.Emit(OpCodes.Ldc_I4_1);
            }
            else
            {
                gen.Emit(OpCodes.Ldc_I4_0);
            }

            gen.Emit(OpCodes.Stloc, result);
            gen.Emit(OpCodes.Ldloc, result);
            cf.PushDescriptor(_exitTypeDescriptor);
        }
示例#14
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            LeftOperand.GenerateCode(gen, cf);
            CodeFlow.InsertBoxIfNecessary(gen, cf.LastDescriptor());
            if (_type == null)
            {
                throw new InvalidOperationException("No type available");
            }

            var convert = gen.DeclareLocal(typeof(bool));

            gen.Emit(OpCodes.Isinst, _type);
            gen.Emit(OpCodes.Ldnull);
            gen.Emit(OpCodes.Cgt_Un);
            gen.Emit(OpCodes.Stloc, convert);
            gen.Emit(OpCodes.Ldloc, convert);

            cf.PushDescriptor(_exitTypeDescriptor);
        }
示例#15
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            var executor = (ReflectiveConstructorExecutor)_cachedExecutor;

            if (executor == null)
            {
                throw new InvalidOperationException("No cached executor");
            }

            var constructor = executor.Constructor;

            // children[0] is the type of the constructor, don't want to include that in argument processing
            var arguments = new SpelNode[_children.Length - 1];

            Array.Copy(_children, 1, arguments, 0, _children.Length - 1);
            GenerateCodeForArguments(gen, cf, constructor, arguments);
            gen.Emit(OpCodes.Newobj, constructor);
            cf.PushDescriptor(_exitTypeDescriptor);
        }
示例#16
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            var elseTarget  = gen.DefineLabel();
            var endIfTarget = gen.DefineLabel();
            var result      = gen.DeclareLocal(typeof(bool));

            var child = _children[0];

            child.GenerateCode(gen, cf);
            cf.UnboxBooleanIfNecessary(gen);
            gen.Emit(OpCodes.Brtrue, elseTarget);
            gen.Emit(OpCodes.Ldc_I4_1);
            gen.Emit(OpCodes.Stloc, result);
            gen.Emit(OpCodes.Br, endIfTarget);
            gen.MarkLabel(elseTarget);
            gen.Emit(OpCodes.Ldc_I4_0);
            gen.Emit(OpCodes.Stloc, result);
            gen.MarkLabel(endIfTarget);
            gen.Emit(OpCodes.Ldloc, result);
            cf.PushDescriptor(_exitTypeDescriptor);
        }
示例#17
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            var intVal = _value.Value;

            if (intVal == null)
            {
                throw new InvalidOperationException("No int value");
            }

            var intValue = (int)intVal;

            if (intValue == -1)
            {
                // Not sure we can get here because -1 is OpMinus
                gen.Emit(OpCodes.Ldc_I4_M1);
            }
            else
            {
                gen.Emit(OpCodes.Ldc_I4, intValue);
            }

            cf.PushDescriptor(_exitTypeDescriptor);
        }
示例#18
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            CodeFlow.LoadEvaluationContext(gen);
            var leftDesc  = LeftOperand.ExitDescriptor;
            var rightDesc = RightOperand.ExitDescriptor;
            var leftPrim  = CodeFlow.IsValueType(leftDesc);
            var rightPrim = CodeFlow.IsValueType(rightDesc);

            cf.EnterCompilationScope();
            LeftOperand.GenerateCode(gen, cf);
            cf.ExitCompilationScope();
            if (leftPrim)
            {
                CodeFlow.InsertBoxIfNecessary(gen, leftDesc);
            }

            cf.EnterCompilationScope();
            RightOperand.GenerateCode(gen, cf);
            cf.ExitCompilationScope();
            if (rightPrim)
            {
                CodeFlow.InsertBoxIfNecessary(gen, rightDesc);
            }

            // returns bool
            gen.Emit(OpCodes.Call, _equalityCheck);

            // Invert the boolean
            var result = gen.DeclareLocal(typeof(bool));

            gen.Emit(OpCodes.Ldc_I4_0);
            gen.Emit(OpCodes.Ceq);
            gen.Emit(OpCodes.Stloc, result);
            gen.Emit(OpCodes.Ldloc, result);

            cf.PushDescriptor(TypeDescriptor.Z);
        }
示例#19
0
 public override void GenerateCode(ILGenerator gen, CodeFlow cf)
 {
     gen.Emit(OpCodes.Ldc_R4, (float)_value.Value);
     cf.PushDescriptor(_exitTypeDescriptor);
 }
示例#20
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            // exit type descriptor can be null if both components are literal expressions
            ComputeExitTypeDescriptor();
            cf.EnterCompilationScope();

            _children[0].GenerateCode(gen, cf);
            var lastDesc = cf.LastDescriptor();

            if (lastDesc == null)
            {
                throw new InvalidOperationException("No last descriptor");
            }

            // if primitive result, boxed will be on stack
            CodeFlow.InsertBoxIfNecessary(gen, lastDesc);
            cf.ExitCompilationScope();

            var ifResult        = gen.DeclareLocal(typeof(bool));
            var finalResult     = gen.DeclareLocal(_exitTypeDescriptor.Value);
            var loadFinalResult = gen.DefineLabel();

            // Save off child1 result
            var child1Result = gen.DeclareLocal(typeof(object));

            gen.Emit(OpCodes.Stloc, child1Result);

            var child1IsNull = gen.DefineLabel();

            gen.Emit(OpCodes.Ldloc, child1Result);

            // br if child1 null
            gen.Emit(OpCodes.Brfalse, child1IsNull);

            // Check for empty string
            gen.Emit(OpCodes.Ldstr, string.Empty);
            gen.Emit(OpCodes.Ldloc, child1Result);
            gen.Emit(OpCodes.Callvirt, _equalsMethod);
            gen.Emit(OpCodes.Ldc_I4_0);
            gen.Emit(OpCodes.Ceq);

            // save empty string result
            gen.Emit(OpCodes.Stloc, ifResult);
            var loadCheckIfResults = gen.DefineLabel();

            gen.Emit(OpCodes.Br, loadCheckIfResults);

            // Child1 null, load false for if result
            gen.MarkLabel(child1IsNull);
            gen.Emit(OpCodes.Ldc_I4_0);
            gen.Emit(OpCodes.Stloc, ifResult);

            // Fall thru to check if results;
            // Mark Check if Results
            gen.MarkLabel(loadCheckIfResults);

            // Load if results;
            gen.Emit(OpCodes.Ldloc, ifResult);
            var callChild2 = gen.DefineLabel();

            // If faild, call child2 for results
            gen.Emit(OpCodes.Brfalse, callChild2);

            // Final result is child 1, save final
            gen.Emit(OpCodes.Ldloc, child1Result);
            gen.Emit(OpCodes.Stloc, finalResult);
            gen.Emit(OpCodes.Br, loadFinalResult);

            gen.MarkLabel(callChild2);
            cf.EnterCompilationScope();
            _children[1].GenerateCode(gen, cf);

            if (!CodeFlow.IsValueType(_exitTypeDescriptor))
            {
                lastDesc = cf.LastDescriptor();
                if (lastDesc == null)
                {
                    throw new InvalidOperationException("No last descriptor");
                }

                if (lastDesc == TypeDescriptor.V)
                {
                    gen.Emit(OpCodes.Ldnull);
                }
                else
                {
                    CodeFlow.InsertBoxIfNecessary(gen, lastDesc);
                }
            }

            cf.ExitCompilationScope();
            gen.Emit(OpCodes.Stloc, finalResult);

            // Load final result on stack
            gen.MarkLabel(loadFinalResult);
            gen.Emit(OpCodes.Ldloc, finalResult);
            cf.PushDescriptor(_exitTypeDescriptor);
        }
示例#21
0
        public override void GenerateCode(ILGenerator gen, CodeFlow cf)
        {
            var descriptor = cf.LastDescriptor();

            if (descriptor == null)
            {
                CodeFlow.LoadTarget(gen);
            }

            if (_indexedType == IndexedType.ARRAY)
            {
                var arrayType = _exitTypeDescriptor.Value.MakeArrayType();
                gen.Emit(OpCodes.Castclass, arrayType);
                var child = _children[0];
                cf.EnterCompilationScope();
                child.GenerateCode(gen, cf);
                cf.ExitCompilationScope();
                gen.Emit(GetLdElemInsn(_exitTypeDescriptor.Value));
            }
            else if (_indexedType == IndexedType.LIST)
            {
                gen.Emit(OpCodes.Castclass, typeof(IList));
                cf.EnterCompilationScope();
                _children[0].GenerateCode(gen, cf);
                cf.ExitCompilationScope();
                gen.Emit(OpCodes.Callvirt, _listGetItemMethod);
            }
            else if (_indexedType == IndexedType.MAP)
            {
                gen.Emit(OpCodes.Castclass, typeof(IDictionary));

                // Special case when the key is an unquoted string literal that will be parsed as
                // a property/field reference
                if (_children[0] is PropertyOrFieldReference reference)
                {
                    var mapKeyName = reference.Name;
                    gen.Emit(OpCodes.Ldstr, mapKeyName);
                }
                else
                {
                    cf.EnterCompilationScope();
                    _children[0].GenerateCode(gen, cf);
                    cf.ExitCompilationScope();
                }

                gen.Emit(OpCodes.Callvirt, _dictionaryGetItemMethod);
            }
            else if (_indexedType == IndexedType.OBJECT)
            {
                if (_cachedReadAccessor is not ReflectivePropertyAccessor.OptimalPropertyAccessor accessor)
                {
                    throw new InvalidOperationException("No cached read accessor");
                }

                bool isStatic;
                var  method = accessor.Member as MethodInfo;
                var  field  = accessor.Member as FieldInfo;

                if (method != null)
                {
                    isStatic = method.IsStatic;
                }
                else
                {
                    isStatic = field.IsStatic;
                }

                var targetType = accessor.Member.DeclaringType;
                if (!isStatic && (descriptor == null || targetType != descriptor.Value))
                {
                    gen.Emit(OpCodes.Castclass, targetType);
                }

                if (method != null)
                {
                    if (isStatic)
                    {
                        gen.Emit(OpCodes.Call, method);
                    }
                    else
                    {
                        gen.Emit(OpCodes.Callvirt, method);
                    }
                }
                else
                {
                    if (isStatic)
                    {
                        gen.Emit(OpCodes.Ldsfld, field);
                    }
                    else
                    {
                        gen.Emit(OpCodes.Ldfld, field);
                    }
                }
            }

            cf.PushDescriptor(_exitTypeDescriptor);
        }
示例#22
0
        protected void GenerateComparisonCode(ILGenerator gen, CodeFlow cf, OpCode brToElseInstruction)
        {
            var left      = LeftOperand;
            var right     = RightOperand;
            var leftDesc  = left.ExitDescriptor;
            var rightDesc = right.ExitDescriptor;

            var elseTarget    = gen.DefineLabel();
            var endOfIfTarget = gen.DefineLabel();

            var unboxLeft  = !CodeFlow.IsValueType(leftDesc);
            var unboxRight = !CodeFlow.IsValueType(rightDesc);

            cf.EnterCompilationScope();
            left.GenerateCode(gen, cf);
            cf.ExitCompilationScope();
            if (CodeFlow.IsValueType(leftDesc))
            {
                gen.Emit(OpCodes.Box, leftDesc.Value);
                unboxLeft = true;
            }

            cf.EnterCompilationScope();
            right.GenerateCode(gen, cf);
            cf.ExitCompilationScope();
            if (CodeFlow.IsValueType(rightDesc))
            {
                gen.Emit(OpCodes.Box, rightDesc.Value);
                unboxRight = true;
            }

            var leftLocal  = gen.DeclareLocal(typeof(object));
            var rightLocal = gen.DeclareLocal(typeof(object));

            gen.Emit(OpCodes.Stloc, rightLocal);
            gen.Emit(OpCodes.Stloc, leftLocal);

            gen.Emit(OpCodes.Ldloc, leftLocal);
            gen.Emit(OpCodes.Ldloc, rightLocal);

            // This code block checks whether the left or right operand is null and handles
            // those cases before letting the original code (that only handled actual numbers) run
            var rightIsNonNullTarget = gen.DefineLabel();

            // stack: left/right
            gen.Emit(OpCodes.Brtrue, rightIsNonNullTarget);

            // stack: left
            // here: RIGHT==null LEFT==unknown
            var leftNotNullRightIsNullTarget = gen.DefineLabel();

            gen.Emit(OpCodes.Brtrue, leftNotNullRightIsNullTarget);

            // stack: empty
            // here: RIGHT==null LEFT==null
            // load 0 or 1 depending on comparison instruction
            if (brToElseInstruction == OpCodes.Bge || brToElseInstruction == OpCodes.Ble)
            {
                gen.Emit(OpCodes.Ldc_I4_0);
            }
            else if (brToElseInstruction == OpCodes.Bgt || brToElseInstruction == OpCodes.Blt)
            {
                gen.Emit(OpCodes.Ldc_I4_1);
            }
            else
            {
                throw new InvalidOperationException("Unsupported: " + brToElseInstruction);
            }

            gen.Emit(OpCodes.Br, endOfIfTarget);
            gen.MarkLabel(leftNotNullRightIsNullTarget);

            // stack: empty
            // RIGHT==null LEFT!=null
            // load 0 or 1 depending on comparison instruction
            if (brToElseInstruction == OpCodes.Bge || brToElseInstruction == OpCodes.Bgt)
            {
                gen.Emit(OpCodes.Ldc_I4_0);
            }
            else if (brToElseInstruction == OpCodes.Ble || brToElseInstruction == OpCodes.Blt)
            {
                gen.Emit(OpCodes.Ldc_I4_1);
            }
            else
            {
                throw new InvalidOperationException("Unsupported: " + brToElseInstruction);
            }

            gen.Emit(OpCodes.Br, endOfIfTarget);
            gen.MarkLabel(rightIsNonNullTarget);

            // stack: left
            // here: RIGHT!=null LEFT==unknown
            var neitherRightNorLeftAreNullTarget = gen.DefineLabel();

            gen.Emit(OpCodes.Brtrue, neitherRightNorLeftAreNullTarget);

            // stack: empty
            // here: RIGHT!=null LEFT==null
            if (brToElseInstruction == OpCodes.Bge || brToElseInstruction == OpCodes.Bgt)
            {
                gen.Emit(OpCodes.Ldc_I4_1);
            }
            else if (brToElseInstruction == OpCodes.Ble || brToElseInstruction == OpCodes.Blt)
            {
                gen.Emit(OpCodes.Ldc_I4_0);
            }
            else
            {
                throw new InvalidOperationException("Unsupported: " + brToElseInstruction);
            }

            gen.Emit(OpCodes.Br, endOfIfTarget);
            gen.MarkLabel(neitherRightNorLeftAreNullTarget);

            // stack: empty
            // neither were null so unbox and proceed with numeric comparison
            gen.Emit(OpCodes.Ldloc, leftLocal);
            if (unboxLeft)
            {
                gen.Emit(OpCodes.Unbox_Any, leftDesc.Value);
            }

            // stack: left
            gen.Emit(OpCodes.Ldloc, rightLocal);
            if (unboxRight)
            {
                gen.Emit(OpCodes.Unbox_Any, rightDesc.Value);
            }

            // stack: left, right
            // Br instruction
            gen.Emit(brToElseInstruction, elseTarget);

            // Stack: Empty
            gen.Emit(OpCodes.Ldc_I4_1);
            gen.Emit(OpCodes.Br, endOfIfTarget);
            gen.MarkLabel(elseTarget);

            // Stack: Empty
            gen.Emit(OpCodes.Ldc_I4_0);
            gen.MarkLabel(endOfIfTarget);

            // Stack: result on stack, convert to bool
            var result = gen.DeclareLocal(typeof(bool));

            gen.Emit(OpCodes.Stloc, result);
            gen.Emit(OpCodes.Ldloc, result);
            cf.PushDescriptor(TypeDescriptor.Z);
        }
示例#23
0
 public override void GenerateCode(ILGenerator gen, CodeFlow cf)
 {
     gen.Emit(OpCodes.Ldnull);
     cf.PushDescriptor(_exitTypeDescriptor);
 }