Beispiel #1
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 #2
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 #3
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);
		}
Beispiel #4
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);
        }