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);
            }
        }
            private void GenerateCode(FieldInfo field, ILGenerator gen, CodeFlow cf)
            {
                var stackDescriptor = cf.LastDescriptor();

                if (stackDescriptor == null)
                {
                    CodeFlow.LoadTarget(gen);
                    stackDescriptor = Spring.TypeDescriptor.OBJECT;
                }

                if (!field.IsStatic)
                {
                    // Instance
                    if (field.DeclaringType.IsValueType)
                    {
                        if (stackDescriptor != null && stackDescriptor.IsBoxed)
                        {
                            gen.Emit(OpCodes.Unbox_Any, field.DeclaringType);
                        }
                    }
                    else
                    {
                        if (stackDescriptor == null || field.DeclaringType != stackDescriptor.Value)
                        {
                            gen.Emit(OpCodes.Castclass, field.DeclaringType);
                        }
                    }

                    gen.Emit(OpCodes.Ldfld, field);
                }
                else
                {
                    // Static
                    if (stackDescriptor != null)
                    {
                        // A static field/method call will not consume what is on the stack,
                        // it needs to be popped off.
                        gen.Emit(OpCodes.Pop);
                    }

                    if (field.IsLiteral)
                    {
                        EmitLiteralFieldCode(gen, field);
                    }
                    else
                    {
                        gen.Emit(OpCodes.Ldsfld, field);
                    }
                }
            }
            private void GenerateCode(MethodInfo method, ILGenerator gen, CodeFlow cf)
            {
                var stackDescriptor = cf.LastDescriptor();

                if (stackDescriptor == null)
                {
                    CodeFlow.LoadTarget(gen);
                    stackDescriptor = Spring.TypeDescriptor.OBJECT;
                }

                if (!method.IsStatic)
                {
                    // Instance
                    if (method.DeclaringType.IsValueType)
                    {
                        if (stackDescriptor != null && stackDescriptor.IsBoxed)
                        {
                            gen.Emit(OpCodes.Unbox_Any, method.DeclaringType);
                        }

                        var vtLocal = gen.DeclareLocal(method.DeclaringType);
                        gen.Emit(OpCodes.Stloc, vtLocal);
                        gen.Emit(OpCodes.Ldloca, vtLocal);
                        gen.Emit(OpCodes.Call, method);
                    }
                    else
                    {
                        if (stackDescriptor == null || method.DeclaringType != stackDescriptor.Value)
                        {
                            gen.Emit(OpCodes.Castclass, method.DeclaringType);
                        }

                        gen.Emit(OpCodes.Callvirt, method);
                    }
                }
                else
                {
                    // Static
                    if (stackDescriptor != null)
                    {
                        // A static field/method call will not consume what is on the stack,
                        // it needs to be popped off.
                        gen.Emit(OpCodes.Pop);
                    }

                    gen.Emit(OpCodes.Call, method);
                }
            }
Exemple #4
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);
        }
        public void GenerateCode(string propertyName, ILGenerator gen, CodeFlow cf)
        {
            var descriptor = cf.LastDescriptor();

            if (descriptor == null || descriptor.Value != typeof(IDictionary))
            {
                if (descriptor == null)
                {
                    CodeFlow.LoadTarget(gen);
                }

                gen.Emit(OpCodes.Castclass, typeof(IDictionary));
            }

            gen.Emit(OpCodes.Ldstr, propertyName);
            gen.Emit(OpCodes.Callvirt, _getItem);
        }
Exemple #6
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);
        }