Example #1
0
        internal override PhpTypeCode EmitGet(CodeGenerator /*!*/ codeGenerator, ConstructedType constructedType,
                                              bool runtimeVisibilityCheck, string fallbackName)
        {
            ILEmitter il = codeGenerator.IL;

            if (HasValue)
            {
                il.LoadLiteral(Value);
                return(PhpTypeCodeEnum.FromObject(Value));
            }
            else
            {
                Debug.Assert(realField != null);

                il.Emit(OpCodes.Ldsfld, DType.MakeConstructed(realField, constructedType));
                return(PhpTypeCodeEnum.FromType(realField.FieldType));
            }
        }
Example #2
0
        /// <summary>
        /// Emits stub for one overridden/implemented/exported CLR overload.
        /// </summary>
        /// <param name="il"></param>
        /// <param name="scriptContextPlace"></param>
        /// <param name="stubParameters">The overload parameters.</param>
        /// <param name="stubTypeParameters">The overload type parameters.</param>
        /// <param name="stubReturnType">The overload return type.</param>
        /// <param name="target">The overriding/implementing/exporting method.</param>
        /// <param name="targetType">The type (perhaps constructed) that declared <paramref name="target"/>.</param>
        public static void EmitMethodStubBody(ILEmitter /*!*/ il, IPlace /*!*/ scriptContextPlace,
                                              ParameterInfo[] /*!*/ stubParameters, Type[] /*!*/ stubTypeParameters,
                                              Type /*!*/ stubReturnType, PhpMethod /*!*/ target, DType /*!*/ targetType)
        {
            bool stub_is_static = il.MethodBase.IsStatic;

            ClrStubBuilder stub_builder =
                new ClrStubBuilder(il, scriptContextPlace, stubParameters.Length, (stub_is_static ? 0 : 1));

            if (stubParameters.Length >= target.Signature.MandatoryParamCount &&
                stubTypeParameters.Length >= target.Signature.MandatoryGenericParamCount &&
                (target.Properties & RoutineProperties.IsArgsAware) == 0)
            {
                // we can directly call the target argful

                if (!stub_is_static)
                {
                    il.Ldarg(FunctionBuilder.ArgThis);
                }
                scriptContextPlace.EmitLoad(il);

                stub_builder.EmitLoadArgfullParameters(stubParameters, stubTypeParameters, target);

                // invoke the target (virtually if it's not static)
                il.Emit(stub_is_static ? OpCodes.Call : OpCodes.Callvirt,
                        DType.MakeConstructed(target.ArgFullInfo, targetType as ConstructedType));
            }
            else
            {
                // we have to take the argless way

                stub_builder.EmitLoadArglessParameters(stubParameters, stubTypeParameters, target);

                // invoke the target's argless
                // TODO: this is not behaving 100% correct, because we're losing virtual dispatch here
                if (stub_is_static)
                {
                    il.Emit(OpCodes.Ldnull);
                }
                else
                {
                    il.Ldarg(FunctionBuilder.ArgThis);
                }

                scriptContextPlace.EmitLoad(il);
                il.Emit(OpCodes.Ldfld, Fields.ScriptContext_Stack);

                il.Emit(OpCodes.Call, DType.MakeConstructed(target.ArgLessInfo, targetType as ConstructedType));
            }

            // do not keep it on stack needlessly
            if (stubReturnType == Types.Void)
            {
                il.Emit(OpCodes.Pop);
            }

            // convert ref/out parameters back to CLR type
            for (int i = 0; i < stubParameters.Length; i++)
            {
                stub_builder.EmitStoreClrParameter(stubParameters[i]);
            }

            if (stubReturnType != Types.Void)
            {
                // convert the return parameter back to CLR type
                stub_builder.EmitConvertReturnValue(
                    stubReturnType,
                    target.Signature.AliasReturn ? PhpTypeCode.PhpReference : PhpTypeCode.Object);
            }

            il.Emit(OpCodes.Ret);
        }