Example #1
0
        protected static void GenerateCodeForArgument(ILGenerator gen, CodeFlow cf, SpelNode argument, TypeDescriptor paramDesc)
        {
            cf.EnterCompilationScope();
            argument.GenerateCode(gen, cf);
            var lastDesc = cf.LastDescriptor();

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

            var valueTypeOnStack = CodeFlow.IsValueType(lastDesc);

            // Check if need to box it for the method reference?
            if (valueTypeOnStack && paramDesc.IsReferenceType)
            {
                CodeFlow.InsertBoxIfNecessary(gen, lastDesc);
            }
            else if (paramDesc.IsValueType && !paramDesc.IsBoxed && !valueTypeOnStack)
            {
                gen.Emit(OpCodes.Unbox_Any, paramDesc.Value);
            }
            else
            {
                // This would be unnecessary in the case of subtyping (e.g. method takes Number but Integer passed in)
                CodeFlow.InsertCastClass(gen, paramDesc);
            }

            cf.ExitCompilationScope();
        }
Example #2
0
        private void GenerateInstanceMethodCode(ILGenerator gen, CodeFlow cf, MethodInfo targetMethod, Type targetType)
        {
            var stackDescriptor = cf.LastDescriptor();

            if (stackDescriptor == null)
            {
                // Nothing on the stack but something is needed
                CodeFlow.LoadTarget(gen);
                stackDescriptor = TypeDescriptor.OBJECT;
            }

            Label?skipIfNullTarget = null;

            if (_nullSafe)
            {
                skipIfNullTarget = GenerateNullCheckCode(gen);
            }

            if (targetType.IsValueType)
            {
                if (stackDescriptor.IsBoxed || stackDescriptor.IsReferenceType)
                {
                    gen.Emit(OpCodes.Unbox_Any, targetType);
                }

                var local = gen.DeclareLocal(targetType);
                gen.Emit(OpCodes.Stloc, local);
                gen.Emit(OpCodes.Ldloca, local);
            }
            else
            {
                if (stackDescriptor.Value != targetType)
                {
                    CodeFlow.InsertCastClass(gen, new TypeDescriptor(targetType));
                }
            }

            GenerateCodeForArguments(gen, cf, targetMethod, _children);
            if (targetType.IsValueType)
            {
                gen.Emit(OpCodes.Call, targetMethod);
            }
            else
            {
                gen.Emit(OpCodes.Callvirt, targetMethod);
            }

            if (_originalPrimitiveExitTypeDescriptor != null)
            {
                // The output of the accessor will be a primitive but from the block above it might be null,
                // so to have a 'common stack' element at skipIfNull target we need to box the primitive
                CodeFlow.InsertBoxIfNecessary(gen, _originalPrimitiveExitTypeDescriptor);
            }

            if (skipIfNullTarget.HasValue)
            {
                gen.MarkLabel(skipIfNullTarget.Value);
            }
        }
Example #3
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);
        }
Example #4
0
        private Label GenerateNullCheckCode(ILGenerator gen)
        {
            var skipIfNullTarget = gen.DefineLabel();
            var continueTarget   = gen.DefineLabel();

            gen.Emit(OpCodes.Dup);
            gen.Emit(OpCodes.Ldnull);
            gen.Emit(OpCodes.Cgt_Un);
            gen.Emit(OpCodes.Brtrue, continueTarget);

            // cast null on stack to result type
            CodeFlow.InsertCastClass(gen, _exitTypeDescriptor);
            gen.Emit(OpCodes.Br, skipIfNullTarget);
            gen.MarkLabel(continueTarget);
            return(skipIfNullTarget);
        }