Beispiel #1
0
        private void EmitLoadArgfullParameters(ParameterInfo[] /*!*/ stubParameters,
                                               Type[] /*!*/ stubTypeParameters, PhpMethod /*!*/ target)
        {
            for (int i = 0; i < target.Signature.GenericParamCount; i++)
            {
                if (i < stubTypeParameters.Length)
                {
                    il.Emit(OpCodes.Ldtoken, stubTypeParameters[i]);
                    il.Emit(OpCodes.Call, Methods.DTypeDesc_Create);
                }
                else
                {
                    // optional type parameter, whose value is not supplied
                    il.Emit(OpCodes.Ldsfld, Fields.Arg_DefaultType);
                }
            }

            for (int i = 0; i < target.Signature.ParamCount; i++)
            {
                if (i < stubParameters.Length)
                {
                    EmitLoadClrParameter(
                        stubParameters[i],
                        target.Signature.IsAlias(i) ? PhpTypeCode.PhpReference : PhpTypeCode.Object);
                }
                else
                {
                    // optional parameter, whose value is not supplied
                    il.Emit(OpCodes.Ldsfld, Fields.Arg_Default);
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Defines CLR-friendly constructors based on a PHP &quot;constructor&quot; method.
        /// </summary>
        public static void DefineExportedConstructors(PhpType /*!*/ phpType)
        {
            phpType.Builder.ClrConstructorStubs = new List <StubInfo>();
            PhpMethod ctor = phpType.GetConstructor() as PhpMethod;

            if (ctor == null)
            {
                // the class defines (nor inherits) no constructor -> create a parameter-less CLR constructor
                ConstructorBuilder ctor_builder =
                    phpType.RealTypeBuilder.DefineConstructor(
                        DefaultConstructorAttributes,
                        CallingConventions.Standard,
                        Type.EmptyTypes);

                phpType.ClrConstructorInfos = new ConstructorInfo[] { ctor_builder };

                phpType.Builder.ClrConstructorStubs.Add(
                    new StubInfo(ctor_builder, new ParameterInfo[0], StubInfo.EmptyGenericParameters, null));
            }
            else if (!ctor.IsAbstract)
            {
                Debug.Assert(!ctor.IsStatic && ctor.Signature.GenericParamCount == 0);

                if (ctor.Builder == null)
                {
                    // contructor not defined in this class
                    phpType.ClrConstructorInfos = new ConstructorInfo[0];
                    return;
                }

                // infer constructor visibility
                List <ConstructorInfo> ctor_infos = new List <ConstructorInfo>();

                MethodAttributes attr = Reflection.Enums.ToMethodAttributes(ctor.RoutineDesc.MemberAttributes);

                foreach (StubInfo info in ClrStubBuilder.DefineMethodExportStubs(
                             ctor,
                             attr,
                             true,
                             delegate(string[] genericParamNames, object[] parameterTypes, object returnType)
                {
                    // accept all overloads
                    return(true);
                }))
                {
                    phpType.Builder.ClrConstructorStubs.Add(info);

                    // infos are returned in ascending order w.r.t. parameter count
                    ctor_infos.Add(info.ConstructorBuilder);
                }

                phpType.ClrConstructorInfos = ctor_infos.ToArray();
            }
        }
Beispiel #3
0
        private static void EmitExportedConstructors(PhpType /*!*/ phpType)
        {
            PhpMethod ctor = phpType.GetConstructor() as PhpMethod;

            foreach (StubInfo info in phpType.Builder.ClrConstructorStubs)
            {
                EmitExportedConstructor(
                    phpType,
                    info.ConstructorBuilder,
                    ctor,
                    info.Parameters);
            }
        }
Beispiel #4
0
 private void EmitLoadArglessParameters(ParameterInfo[] /*!*/ stubParameters,
                                        Type[] /*!*/ stubTypeParameters, PhpMethod /*!*/ target)
 {
     PhpStackBuilder.EmitAddFrame(il, scriptContextPlace, stubTypeParameters.Length, stubParameters.Length,
                                  delegate(ILEmitter eil, int i)
     {
         il.Emit(OpCodes.Ldtoken, stubTypeParameters[i]);
         il.Emit(OpCodes.Call, Methods.DTypeDesc_Create);
     },
                                  delegate(ILEmitter eil, int i)
     {
         EmitLoadClrParameter(stubParameters[i], PhpTypeCode.Unknown);
     });
 }
Beispiel #5
0
        private static void EmitExportedConstructor(PhpType /*!*/ phpType, ConstructorBuilder /*!*/ ctorStubBuilder,
                                                    PhpMethod phpCtor, ParameterInfo[] /*!*/ parameters)
        {
            // set parameter names and attributes
            if (phpCtor != null)
            {
                ClrStubBuilder.DefineStubParameters(
                    ctorStubBuilder,
                    phpCtor.Builder.Signature.FormalParams,
                    parameters);
            }

            // emit ctor body
            ILEmitter cil = new ILEmitter(ctorStubBuilder);

            // [ this(ScriptContext.CurrentContext ]
            cil.Ldarg(FunctionBuilder.ArgThis);
            cil.EmitCall(OpCodes.Call, Methods.ScriptContext.GetCurrentContext, null);

            LocalBuilder sc_local = cil.DeclareLocal(Types.ScriptContext[0]);

            cil.Stloc(sc_local);
            cil.Ldloc(sc_local);

            cil.LdcI4(1);
            cil.Emit(OpCodes.Call, phpType.ShortConstructorInfo);

            if (phpCtor != null)
            {
                // invoke the PHP ctor method
                ClrStubBuilder.EmitMethodStubBody(
                    cil,
                    new Place(sc_local),
                    parameters,
                    new GenericTypeParameterBuilder[0],
                    Types.Void,
                    phpCtor,
                    phpCtor.DeclaringType);
            }
            else
            {
                cil.Emit(OpCodes.Ret);
            }
        }
Beispiel #6
0
        /// <summary>
        /// Add at runtime a method to a type
        /// </summary>
        /// <param name="typedesc">Type to modify</param>
        /// <param name="attributes">New method attributes</param>
        /// <param name="func_name">Method name</param>
        /// <param name="callback">Method body</param>
        /// <remarks>Used by PDO_SQLITE</remarks>
        public void AddMethodToType(DTypeDesc typedesc, PhpMemberAttributes attributes, string func_name, Func <object, PhpStack, object> callback)
        {
            Debug.Assert(typedesc != null);

            var name        = new Name(func_name);
            var method_desc = new PhpRoutineDesc(typedesc, attributes);

            if (!typedesc.Methods.ContainsKey(name))
            {
                typedesc.Methods.Add(name, method_desc);

                // assign member:
                if (method_desc.Member == null)
                {
                    Func <ScriptContext, object> dummyArgFullCallback = DummyArgFull;
                    PhpMethod method = new PhpMethod(name, (PhpRoutineDesc)method_desc, dummyArgFullCallback.Method, (callback != null) ? callback.Method : null);
                    method.WriteUp(PhpRoutineSignature.FromArgfullInfo(method, dummyArgFullCallback.Method));
                    method_desc.Member = method;
                }
            }
        }
Beispiel #7
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);
        }