Пример #1
0
		public static void EmitAddFrame(ILEmitter/*!*/ il, IPlace/*!*/ scriptContextPlace, int typeArgCount, int argCount,
		  Action<ILEmitter, int> typeArgEmitter, Action<ILEmitter, int>/*!*/ argEmitter)
		{
			Debug.Assert(typeArgCount == 0 || typeArgEmitter != null);

			// type args:
			if (typeArgCount > 0)
			{
				scriptContextPlace.EmitLoad(il);
				il.Emit(OpCodes.Ldfld, Fields.ScriptContext_Stack);

				il.EmitOverloadedArgs(Types.DTypeDesc[0], typeArgCount, Methods.PhpStack.AddTypeFrame.ExplicitOverloads, typeArgEmitter);
			}

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

			il.EmitOverloadedArgs(Types.Object[0], argCount, Methods.PhpStack.AddFrame.ExplicitOverloads, argEmitter);

			il.Emit(OpCodes.Call, Methods.PhpStack.AddFrame.Overload(argCount));

			// AddFrame adds empty type frame by default, so if there are no type parameters, we can skip AddTypeFrame call:
			if (typeArgCount > 0)
				il.Emit(OpCodes.Call, Methods.PhpStack.AddTypeFrame.Overload(typeArgCount));
		}
Пример #2
0
        public static void EmitAddFrame(ILEmitter /*!*/ il, IPlace /*!*/ scriptContextPlace, int typeArgCount, int argCount,
                                        Action <ILEmitter, int> typeArgEmitter, Action <ILEmitter, int> /*!*/ argEmitter)
        {
            Debug.Assert(typeArgCount == 0 || typeArgEmitter != null);

            // type args:
            if (typeArgCount > 0)
            {
                scriptContextPlace.EmitLoad(il);
                il.Emit(OpCodes.Ldfld, Fields.ScriptContext_Stack);

                il.EmitOverloadedArgs(Types.DTypeDesc[0], typeArgCount, Methods.PhpStack.AddTypeFrame.ExplicitOverloads, typeArgEmitter);
            }

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

            il.EmitOverloadedArgs(Types.Object[0], argCount, Methods.PhpStack.AddFrame.ExplicitOverloads, argEmitter);

            il.Emit(OpCodes.Call, Methods.PhpStack.AddFrame.Overload(argCount));

            // AddFrame adds empty type frame by default, so if there are no type parameters, we can skip AddTypeFrame call:
            if (typeArgCount > 0)
            {
                il.Emit(OpCodes.Call, Methods.PhpStack.AddTypeFrame.Overload(typeArgCount));
            }
        }
Пример #3
0
            /// <summary>Loads copied parameter value.</summary>
            public TypeSymbol EmitLoad(CodeGenerator cg)
            {
                if (_isparams)
                {
                    // converts params -> PhpArray
                    Debug.Assert(_place.TypeOpt.IsSZArray());
                    return(cg.ArrayToPhpArray(_place, deepcopy: true));
                }
                else
                {
                    // load parameter & dereference PhpValue
                    TypeSymbol t;
                    if (_place.TypeOpt == cg.CoreTypes.PhpValue)
                    {
                        // p.GetValue() : PhpValue
                        _place.EmitLoadAddress(cg.Builder);
                        t = cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.GetValue);
                    }
                    else
                    {
                        // p
                        t = _place.EmitLoad(cg.Builder);
                    }

                    // make copy of given value
                    return(cg.EmitDeepCopy(t, nullcheck: !_notNull));
                }
            }
Пример #4
0
            public TypeSymbol EmitLoad(CodeGenerator cg)
            {
                if (_isparams)
                {
                    // PhpArray( {varargs[index..] )
                    return(cg.ArrayToPhpArray(_varargsplace, startindex: _index, deepcopy: true));
                }
                else
                {
                    var il = cg.Builder;

                    var lbl_default = new object();
                    var lbl_end     = new object();

                    var element_type = ((ArrayTypeSymbol)_varargsplace.TypeOpt).ElementType;

                    // Template: _index < {vargags}.Length ? {varargs[_index]} : DEFAULT

                    // _index < {varargs}.Length
                    il.EmitIntConstant(_index);
                    _varargsplace.EmitLoad(il);
                    cg.EmitArrayLength();
                    il.EmitBranch(ILOpCode.Bge, lbl_default);

                    // LOAD varargs[index]
                    _varargsplace.EmitLoad(il);
                    il.EmitIntConstant(_index);
                    il.EmitOpCode(ILOpCode.Ldelem);
                    cg.EmitSymbolToken(element_type, null);
                    cg.EmitConvertToPhpValue(cg.EmitDeepCopy(element_type, nullcheck: false), 0);
                    il.EmitBranch(ILOpCode.Br, lbl_end);

                    // DEFAULT
                    il.MarkLabel(lbl_default);

                    if (_p.Initializer != null)
                    {
                        using (var tmpcg = new CodeGenerator(cg, _p.Routine))
                        {
                            tmpcg.EmitConvertToPhpValue(_p.Initializer);
                        }
                    }
                    else
                    {
                        cg.Emit_PhpValue_Null();
                    }

                    //
                    il.MarkLabel(lbl_end);

                    //
                    return(cg.CoreTypes.PhpValue);
                }
            }
Пример #5
0
 /// <summary>Loads copied parameter value.</summary>
 public TypeSymbol EmitLoad(CodeGenerator cg)
 {
     if (_isparams)
     {
         // converts params -> PhpArray
         Debug.Assert(_place.TypeOpt.IsSZArray());
         return(cg.ArrayToPhpArray(_place, deepcopy: true));
     }
     else
     {
         // make copy of given value
         return(cg.EmitDeepCopy(_place.EmitLoad(cg.Builder), nullcheck: !_notNull));
     }
 }
Пример #6
0
        public TypeSymbol EmitLoad(ILBuilder il)
        {
            _operand.EmitLoad(il);

            il.EmitOpCode(ILOpCode.Call, _operator.GetCallStackBehavior());
            il.EmitToken(_operator, null, DiagnosticBag.GetInstance());

            return(Type);
        }
Пример #7
0
 public static void EmitArgFullPostCall(ILEmitter /*!*/ il, IPlace /*!*/ stack, LocalBuilder locArgsCount)
 {
     // args-aware:
     if (locArgsCount != null)
     {
         // CALL stack.RemoveArgsAwareFrame(count);
         stack.EmitLoad(il);
         il.Ldloc(locArgsCount);
         il.Emit(OpCodes.Call, Methods.PhpStack.RemoveArgsAwareFrame);
     }
 }
Пример #8
0
		public static void EmitArgFullPostCall(ILEmitter/*!*/ il, IPlace/*!*/ stack, LocalBuilder locArgsCount)
		{
			// args-aware:
			if (locArgsCount != null)
			{
				// CALL stack.RemoveArgsAwareFrame(count);
				stack.EmitLoad(il);
				il.Ldloc(locArgsCount);
				il.Emit(OpCodes.Call, Methods.PhpStack.RemoveArgsAwareFrame);
			}
		}
Пример #9
0
        //public static MethodCallPlace/*!*/ MakePeekValuePlace(IPlace/*!*/ stack, IPlace/*!*/ index)
        //{
        //  Debug.Assert(stack != null && index != null);
        //  return new MethodCallPlace(Methods.PhpStack.PeekValue, false, stack, index);
        //}

        //public static MethodCallPlace/*!*/ MakeValuePeekUncheckedPlace(IPlace/*!*/ stack, IPlace/*!*/ index)
        //{
        //  Debug.Assert(stack != null && index != null);
        //  return new MethodCallPlace(Methods.PhpStack.PeekValueUnchecked, false, stack, index);
        //}

        //public static MethodCallPlace/*!*/ MakeReferencePeekPlace(IPlace/*!*/ stack, IPlace/*!*/ index)
        //{
        //  Debug.Assert(stack != null && index != null);
        //  return new MethodCallPlace(Methods.PhpStack.PeekReference, false, stack, index);
        //}

        //public static MethodCallPlace/*!*/ MakeReferencePeekUncheckedPlace(IPlace/*!*/ stack, IPlace/*!*/ index)
        //{
        //  Debug.Assert(stack != null && index != null);
        //  return new MethodCallPlace(Methods.PhpStack.PeekReferenceUnchecked, false, stack, index);
        //}


        public static object EmitValuePeek(ILEmitter /*!*/ il, IPlace /*!*/ stack, IPlace /*!*/ index)
        {
            Debug.Assert(il != null && stack != null && index != null);

            // CALL stack.PeekValue(<index+1>);
            stack.EmitLoad(il);
            index.EmitLoad(il);
            il.Emit(OpCodes.Call, Methods.PhpStack.PeekValue);

            return(typeof(object));
        }
Пример #10
0
        public static object EmitReferencePeekUnchecked(ILEmitter /*!*/ il, IPlace /*!*/ stack, IPlace /*!*/ index)
        {
            Debug.Assert(il != null && stack != null && index != null);

            // LOAD stack.PeekReferenceUnchecked(<index+1>);
            stack.EmitLoad(il);
            index.EmitLoad(il);
            il.Emit(OpCodes.Call, Methods.PhpStack.PeekReferenceUnchecked);

            return(typeof(PhpReference));
        }
Пример #11
0
        public TypeSymbol EmitLoad(ILBuilder il)
        {
            //if (_property.Getter == null)
            //    throw new InvalidOperationException();

            var stack  = +1;
            var getter = _property.GetMethod;

            if (_holder != null)
            {
                Debug.Assert(!getter.IsStatic);
                _holder.EmitLoad(il);   // {holder}
                stack -= 1;
            }

            il.EmitOpCode(getter.IsVirtual ? ILOpCode.Callvirt : ILOpCode.Call, stack);
            il.EmitToken(getter, null, DiagnosticBag.GetInstance());

            //
            return(getter.ReturnType);
        }
Пример #12
0
		public static void EmitArgFullPreCall(ILEmitter/*!*/ il, IPlace/*!*/ stack, bool argsAware,
		  int formalParamCount, int formalTypeParamCount, out LocalBuilder locArgsCount)
		{
			if (argsAware)
			{
				locArgsCount = il.DeclareLocal(typeof(int));

				// locArgsCount = stack.MakeArgsAware(<formal tpye param count | formal param count>);
				stack.EmitLoad(il);
				il.LdcI4((formalTypeParamCount << 16) | formalParamCount);
				il.Emit(OpCodes.Call, Methods.PhpStack.MakeArgsAware);
				il.Stloc(locArgsCount);
			}
			else
			{
				locArgsCount = null;

				// CALL stack.RemoveFrame();
				stack.EmitLoad(il);
				il.Emit(OpCodes.Call, Methods.PhpStack.RemoveFrame);
			}
		}
Пример #13
0
        public static void EmitArgFullPreCall(ILEmitter /*!*/ il, IPlace /*!*/ stack, bool argsAware,
                                              int formalParamCount, int formalTypeParamCount, out LocalBuilder locArgsCount)
        {
            if (argsAware)
            {
                locArgsCount = il.DeclareLocal(typeof(int));

                // locArgsCount = stack.MakeArgsAware(<formal tpye param count | formal param count>);
                stack.EmitLoad(il);
                il.LdcI4((formalTypeParamCount << 16) | formalParamCount);
                il.Emit(OpCodes.Call, Methods.PhpStack.MakeArgsAware);
                il.Stloc(locArgsCount);
            }
            else
            {
                locArgsCount = null;

                // CALL stack.RemoveFrame();
                stack.EmitLoad(il);
                il.Emit(OpCodes.Call, Methods.PhpStack.RemoveFrame);
            }
        }
Пример #14
0
        override protected void EmitHolder(ILBuilder il)
        {
            Debug.Assert(_field.IsStatic == (_holder == null));

            if (_holder != null)
            {
                if (_holder.Type != null && _holder.Type.IsValueType)
                {
                    Debug.Assert(_holder.HasAddress);
                    _holder.EmitLoadAddress(il);
                }
                else
                {
                    _holder.EmitLoad(il);
                }
            }
        }
Пример #15
0
		internal override PhpTypeCode EmitGet(CodeGenerator/*!*/ codeGenerator, IPlace instance, bool wantRef,
			ConstructedType constructedType, bool runtimeVisibilityCheck)
		{
			Debug.Assert(IsStatic == (instance == null));

			ILEmitter il = codeGenerator.IL;

			if (IsStatic)
			{
				if (runtimeVisibilityCheck)
				{
					// let the operator to check the visibility:
					return codeGenerator.EmitGetStaticPropertyOperator(DeclaringType, this.FullName, null, wantRef);
				}
				il.Emit(OpCodes.Ldsfld, fieldInfo);
			}
			else
			{
				instance.EmitLoad(il);
				il.Emit(OpCodes.Ldfld, fieldInfo);
			}

			PhpTypeCode result = ClrOverloadBuilder.EmitConvertToPhp(il, fieldInfo.FieldType/*, codeGenerator.ScriptContextPlace*/);

			codeGenerator.EmitReferenceDereference(ref result, wantRef);
			return result;
		}
Пример #16
0
		internal override AssignmentCallback EmitSet(CodeGenerator/*!*/ codeGenerator, IPlace instance, bool isRef,
			ConstructedType constructedType, bool runtimeVisibilityCheck)
		{
			Debug.Assert(IsStatic == (instance == null));

			//Debug.Assert(hasSetter, "TODO");
            if (!hasSetter)
            {
                throw new CompilerException(
                    new ErrorInfo(
                           0,
                           "readonly_property_written",
                           ErrorSeverity.Error),
                    new string[]{DeclaringType.FullName, this.Name.Value}
                    );
            }

            //
            
			if (IsStatic)
			{
				// check the visibility at runtime by the operator:
				if (runtimeVisibilityCheck)
					return codeGenerator.EmitSetStaticPropertyOperator(DeclaringType, this.FullName, null, isRef);
			}
			else
			{
				// load target instance:
				instance.EmitLoad(codeGenerator.IL);
			}

			return delegate(CodeGenerator codeGen, PhpTypeCode stackTypeCode)
			{
				MethodInfo setter = this.Setter;

				// TODO: can we get different PhpTypeCode?
				ILEmitter il = codeGen.IL;
				PropertyDesc.EmitSetConversion(il, stackTypeCode, setter.GetParameters()[0].ParameterType);

				il.Emit(setter.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, setter);
			};
		}
Пример #17
0
		/// <summary>
		/// Emits call to specified overload.
		/// </summary>
		/// <param name="method">The overload implementor.</param>
		/// <param name="ps">Formal parameters of the <paramref name="method"/>.</param>
		/// <param name="phpParamCount">The number of PHP arguments of the overload.</param>
        /// <param name="scriptContext">A place where current script context should be loaded from.</param>
		/// <param name="rtVariables">A place where run-time variables table should be loaded from.</param>
		/// <param name="namingContext">A place where the naming can be load from.</param>
        /// <param name="classContext">A place where the class context can be load from.</param>
		/// <param name="optArgs">A place where the number of optional arguments should be loaded from.</param>
		/// <param name="selfRef">A place where reference to 'self' ($this) can be loaded from.</param>
        /// <param name="ignoringReturnValue">True if the return value of the function call is not used then.</param>
		/// <returns>A type of value stored on the top of the evaluation stack. In case of value type, it is NOT boxed.</returns>
		public Type EmitOverloadCall(
			MethodInfo method,
			ParameterInfo[] ps,
			int phpParamCount,
            IPlace scriptContext,
			IPlace rtVariables,
			IPlace namingContext,
            IPlace classContext,
			IPlace optArgs,
			IPlace selfRef,
            bool ignoringReturnValue)
		{
			pushedArgsCount = 0;

            Label overloadCallEndLabel = il.DefineLabel();
            Type/*!*/return_type = method.ReturnType;

            // the routine used to skip the method call in case of invalid parameter cast
            overloadCallSkipEmitter = (ile) =>
                {
                    if (return_type != Types.Void)
                    {
                        // emit the value; because the method call was skipped, value must be loaded here
                        if (return_type.IsValueType)
                            ile.LoadLiteral(Activator.CreateInstance(return_type), false);    // value is not boxed
                        else
                            ile.Emit(OpCodes.Ldnull);
                    }

                    // goto the end label
                    il.Emit(OpCodes.Br, overloadCallEndLabel);
                };

            if (scriptContext != null)
            {
                // LOAD(<context>);
                scriptContext.EmitLoad(il);
                pushedArgsCount++;
            }

			if (selfRef != null)
			{
				// LOAD(<this>);
				selfRef.EmitLoad(il);
				pushedArgsCount++;
			}

			if (rtVariables != null)
			{
				// LOAD(<defined variables>);
				rtVariables.EmitLoad(il);
				pushedArgsCount++;
			}

			if (namingContext != null)
			{
				// LOAD(<naming context>);
				namingContext.EmitLoad(il);
				pushedArgsCount++;
			}

            if (classContext != null)
            {
                // LOAD(<class_context>)
                classContext.EmitLoad(il);
                pushedArgsCount++;
            }

			// loads mandatory arguments:
			for (int i = 0; i < phpParamCount; i++)
			{
				EmitMandatoryArgumentLoad(i, ps[pushedArgsCount]);
				pushedArgsCount++;
			}

			// loads optional arguments:
			if (optArgs != null)
			{
				loadOptParams(this, phpParamCount, ps[ps.Length - 1], optArgs);
				pushedArgsCount++;
			}

			Debug.Assert(pushedArgsCount == ps.Length);

			// all class library functions are args-unaware => remove frame if using stack:
			if (stack != null)
			{
				stack.EmitLoad(il);
				il.Emit(OpCodes.Call, Methods.PhpStack.RemoveFrame);
			}

			// CALL STATIC <overload>(items on STACK);
			il.Emit(OpCodes.Call, method);

            // the result value is on the top of the evaluation stack

			//IPlace return_value = null;

			// stores return value an tmp. variable:
            //if (method.ReturnType != Types.Void)
            //{
            //    LocalBuilder loc = il.DeclareLocal(method.ReturnType);
            //    return_value = new Place(loc);

            //    // stores the result of a call to local:
            //    il.Stloc(loc);
            //}

			// updates arguments passed by reference:
			EmitReferencesLoad();

            // An argument loader can jump here if method call should be skipped.
			// In such a case return_value local will have default value (since locals are initialized).
			il.MarkLabel(overloadCallEndLabel);

            // [CastToFalse] or [PhpDeepCopy]
            if (!ignoringReturnValue)
            {
                // converts return value (deep copy, cast to false):
                EmitReturnValueConversion(method, ref return_type);
            }
            
            // free the skip emitter, to not be used incidentally again
            overloadCallSkipEmitter = null;

            return return_type;
		}
Пример #18
0
        /// <summary>
        /// Emits call to specified overload.
        /// </summary>
        /// <param name="method">The overload implementor.</param>
        /// <param name="ps">Formal parameters of the <paramref name="method"/>.</param>
        /// <param name="phpParamCount">The number of PHP arguments of the overload.</param>
        /// <param name="scriptContext">A place where current script context should be loaded from.</param>
        /// <param name="rtVariables">A place where run-time variables table should be loaded from.</param>
        /// <param name="namingContext">A place where the naming can be load from.</param>
        /// <param name="classContext">A place where the class context can be load from.</param>
        /// <param name="optArgs">A place where the number of optional arguments should be loaded from.</param>
        /// <param name="selfRef">A place where reference to 'self' ($this) can be loaded from.</param>
        /// <param name="ignoringReturnValue">True if the return value of the function call is not used then.</param>
        /// <returns>A type of value stored on the top of the evaluation stack. In case of value type, it is NOT boxed.</returns>
        public Type EmitOverloadCall(
            MethodInfo method,
            ParameterInfo[] ps,
            int phpParamCount,
            IPlace scriptContext,
            IPlace rtVariables,
            IPlace namingContext,
            IPlace classContext,
            IPlace optArgs,
            IPlace selfRef,
            bool ignoringReturnValue)
        {
            pushedArgsCount = 0;

            Label      overloadCallEndLabel = il.DefineLabel();
            Type /*!*/ return_type          = method.ReturnType;

            // the routine used to skip the method call in case of invalid parameter cast
            overloadCallSkipEmitter = (ile) =>
            {
                if (return_type != Types.Void)
                {
                    // emit the value; because the method call was skipped, value must be loaded here
                    if (return_type.IsValueType)
                    {
                        ile.LoadLiteral(Activator.CreateInstance(return_type), false);        // value is not boxed
                    }
                    else
                    {
                        ile.Emit(OpCodes.Ldnull);
                    }
                }

                // goto the end label
                il.Emit(OpCodes.Br, overloadCallEndLabel);
            };

            if (scriptContext != null)
            {
                // LOAD(<context>);
                scriptContext.EmitLoad(il);
                pushedArgsCount++;
            }

            if (selfRef != null)
            {
                // LOAD(<this>);
                selfRef.EmitLoad(il);
                pushedArgsCount++;
            }

            if (rtVariables != null)
            {
                // LOAD(<defined variables>);
                rtVariables.EmitLoad(il);
                pushedArgsCount++;
            }

            if (namingContext != null)
            {
                // LOAD(<naming context>);
                namingContext.EmitLoad(il);
                pushedArgsCount++;
            }

            if (classContext != null)
            {
                // LOAD(<class_context>)
                classContext.EmitLoad(il);
                pushedArgsCount++;
            }

            // loads mandatory arguments:
            for (int i = 0; i < phpParamCount; i++)
            {
                EmitMandatoryArgumentLoad(i, ps[pushedArgsCount]);
                pushedArgsCount++;
            }

            // loads optional arguments:
            if (optArgs != null)
            {
                loadOptParams(this, phpParamCount, ps[ps.Length - 1], optArgs);
                pushedArgsCount++;
            }

            Debug.Assert(pushedArgsCount == ps.Length);

            // all class library functions are args-unaware => remove frame if using stack:
            if (stack != null)
            {
                stack.EmitLoad(il);
                il.Emit(OpCodes.Call, Methods.PhpStack.RemoveFrame);
            }

            // CALL STATIC <overload>(items on STACK);
            il.Emit(OpCodes.Call, method);

            // the result value is on the top of the evaluation stack

            //IPlace return_value = null;

            // stores return value an tmp. variable:
            //if (method.ReturnType != Types.Void)
            //{
            //    LocalBuilder loc = il.DeclareLocal(method.ReturnType);
            //    return_value = new Place(loc);

            //    // stores the result of a call to local:
            //    il.Stloc(loc);
            //}

            // updates arguments passed by reference:
            EmitReferencesLoad();

            // An argument loader can jump here if method call should be skipped.
            // In such a case return_value local will have default value (since locals are initialized).
            il.MarkLabel(overloadCallEndLabel);

            // [CastToFalse] or [PhpDeepCopy]
            if (!ignoringReturnValue)
            {
                // converts return value (deep copy, cast to false):
                EmitReturnValueConversion(method, ref return_type);
            }

            // free the skip emitter, to not be used incidentally again
            overloadCallSkipEmitter = null;

            return(return_type);
        }
Пример #19
0
		//public static MethodCallPlace/*!*/ MakePeekValuePlace(IPlace/*!*/ stack, IPlace/*!*/ index)
		//{
		//  Debug.Assert(stack != null && index != null);
		//  return new MethodCallPlace(Methods.PhpStack.PeekValue, false, stack, index);
		//}

		//public static MethodCallPlace/*!*/ MakeValuePeekUncheckedPlace(IPlace/*!*/ stack, IPlace/*!*/ index)
		//{
		//  Debug.Assert(stack != null && index != null);
		//  return new MethodCallPlace(Methods.PhpStack.PeekValueUnchecked, false, stack, index);
		//}

		//public static MethodCallPlace/*!*/ MakeReferencePeekPlace(IPlace/*!*/ stack, IPlace/*!*/ index)
		//{
		//  Debug.Assert(stack != null && index != null);
		//  return new MethodCallPlace(Methods.PhpStack.PeekReference, false, stack, index);
		//}

		//public static MethodCallPlace/*!*/ MakeReferencePeekUncheckedPlace(IPlace/*!*/ stack, IPlace/*!*/ index)
		//{
		//  Debug.Assert(stack != null && index != null);
		//  return new MethodCallPlace(Methods.PhpStack.PeekReferenceUnchecked, false, stack, index);
		//}


		public static object EmitValuePeek(ILEmitter/*!*/ il, IPlace/*!*/ stack, IPlace/*!*/ index)
		{
			Debug.Assert(il != null && stack != null && index != null);

			// CALL stack.PeekValue(<index+1>);
			stack.EmitLoad(il);
			index.EmitLoad(il);
			il.Emit(OpCodes.Call, Methods.PhpStack.PeekValue);

			return typeof(object);
		}
Пример #20
0
		/// <summary>
		/// Emits load of an array where all optional arguments are stored.
		/// Each optional argument is peeked from the PHP stack and converted before stored to the array.
		/// The resulting array is pushed on evaluation stack so it can be later passed as an argument to a method.
		/// </summary>
		/// <param name="builder">The builder.</param>
		/// <param name="start">The index of the first argument to be loaded.</param>
		/// <param name="param">The last parameter of the overload (should be an array).</param>
		/// <param name="optArgCount">The place where the number of optional arguments is stored.</param>
		/// <remarks>Assumes that the non-negative number of optional arguments has been stored to 
		/// <paramref name="optArgCount"/> place.</remarks>
		public static void EmitPeekAllArguments(OverloadsBuilder/*!*/ builder, int start, ParameterInfo param, IPlace optArgCount)
		{
			Debug.Assert(start >= 0 && optArgCount != null && param != null);

			ILEmitter il = builder.IL;
			Type elem_type = param.ParameterType.GetElementType();
			Type array_type = Type.GetType(elem_type.FullName + "[]", true);
			Type actual_type;

			// declares aux. variables:
			LocalBuilder loc_array = il.DeclareLocal(array_type);
			LocalBuilder loc_i = il.DeclareLocal(typeof(int));
			LocalBuilder loc_elem = il.DeclareLocal(elem_type);

			// creates an array for the arguments 
			// array = new <elem_type>[opt_arg_count]:
			optArgCount.EmitLoad(il);
			il.Emit(OpCodes.Newarr, elem_type);
			il.Stloc(loc_array);

			Label for_end_label = il.DefineLabel();
			Label condition_label = il.DefineLabel();

			// i = 0;
			il.Emit(OpCodes.Ldc_I4_0);
			il.Stloc(loc_i);

			// FOR (i = 0; i < opt_arg_count; i++)
			if (true)
			{
				il.MarkLabel(condition_label);

				// condition (i < opt_arg_count):
				il.Ldloc(loc_i);
				optArgCount.EmitLoad(il);
				il.Emit(OpCodes.Bge, for_end_label);

				// LOAD stack, i + start+1>:
				builder.Stack.EmitLoad(il);
				il.Ldloc(loc_i);
				il.LdcI4(start + 1);
				il.Emit(OpCodes.Add);

				if (elem_type == typeof(PhpReference))
				{
					// CALL stack.PeekReferenceUnchecked(STACK);
					il.Emit(OpCodes.Call, Methods.PhpStack.PeekReferenceUnchecked);
					actual_type = typeof(PhpReference);
				}
				else
				{
					// CALL stack.PeekValueUnchecked(STACK);
					il.Emit(OpCodes.Call, Methods.PhpStack.PeekValueUnchecked);
					actual_type = typeof(object);
				}

				// emits a conversion stuff (loads result into "elem" local variable):
				builder.EmitArgumentConversion(elem_type, actual_type, false, param);
				il.Stloc(loc_elem);

				// array[i] = elem;
				il.Ldloc(loc_array);
				il.Ldloc(loc_i);
				il.Ldloc(loc_elem);
				il.Stelem(elem_type);

				// i = i + 1;
				il.Ldloc(loc_i);
				il.Emit(OpCodes.Ldc_I4_1);
				il.Emit(OpCodes.Add);
				il.Stloc(loc_i);

				// GOTO condition;
				il.Emit(OpCodes.Br, condition_label);
			}
			// END FOR

			il.MarkLabel(for_end_label);

			// loads array to stack - consumed by the method call:
			il.Ldloc(loc_array);
		}
Пример #21
0
		private void EmitLoadAccessorDelegate(ILEmitter/*!*/ il, ConstructorInfo/*!*/ delegateCtor,
			IPlace instance, bool dynamicStub, MethodInfo accessor)
		{
			if (accessor != null)
			{
				if (instance != null) instance.EmitLoad(il); else il.Emit(OpCodes.Ldnull);
				if (!dynamicStub && accessor.IsVirtual)
				{
					instance.EmitLoad(il);
					il.Emit(OpCodes.Ldvirtftn, accessor);
				}
				else il.Emit(OpCodes.Ldftn, accessor);

				il.Emit(OpCodes.Newobj, delegateCtor);
			}
			else il.Emit(OpCodes.Ldnull);
		}
Пример #22
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);
		}
Пример #23
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);
        }
Пример #24
0
        /// <summary>
        /// Create and call <see cref="CallSite"/> for getting property.
        /// </summary>
        /// <param name="cg"><see cref="CodeGenerator"/>.</param>
        /// <param name="wantRef">Wheter <see cref="PhpReference"/> is expected as the result.</param>
        /// <param name="targetExpr">The expression representing the target (object).</param>
        /// <param name="targetObjectPlace">The place representing the target (<see cref="DObject"/>) iff <paramref name="targetExpr"/> is not provided.</param>
        /// <param name="targetPlace">The place representing the target (object) iff <paramref name="targetExpr"/> and <paramref name="targetObjectPlace"/> are not provided.</param>
        /// <param name="targetType">Type of target iff we are getting property statically.</param>
        /// <param name="fieldName">The name of the field. Can be null if the name is not known at compile time (indirect).</param>
        /// <param name="fieldNameExpr">The expression used to get field name in run time (iff <paramref name="fieldName"/> is <c>null</c>.</param>
        /// <param name="issetSemantics">Wheter we are only checking if the property exists. If true, no warnings are thrown during run time.</param>
        /// <returns>Type code of the value that is pushed onto the top of the evaluation stack.</returns>
        public PhpTypeCode EmitGetProperty(
            PHP.Core.CodeGenerator /*!*/ cg, bool wantRef,
            Expression targetExpr, IPlace targetObjectPlace, IPlace targetPlace, DType targetType,
            string fieldName, Expression fieldNameExpr,
            bool issetSemantics)
        {
            Debug.Assert(fieldName != null ^ fieldNameExpr != null);
            Debug.Assert(targetExpr != null || targetObjectPlace != null || targetPlace != null || targetType != null);

            //
            bool staticCall          = (targetExpr == null && targetObjectPlace == null && targetPlace == null); // we are going to access static property
            bool fieldNameIsKnown    = (fieldName != null);
            bool classContextIsKnown = (this.classContextPlace != null);

            //
            // binder flags:
            //
            Type returnType = wantRef ? Types.PhpReference[0] : Types.Object[0];

            //
            // define the call site:
            //

            //
            List <Type> additionalArgs = new List <Type>();

            if (!classContextIsKnown)
            {
                additionalArgs.Add(Types.DTypeDesc[0]);
            }
            if (!fieldNameIsKnown)
            {
                additionalArgs.Add(Types.String[0]);
            }

            var delegateTypeArgs = GetPropertyDelegateTypeArgs(
                staticCall ? Types.DTypeDesc[0] : ((targetObjectPlace != null) ? Types.DObject[0] : Types.Object[0]),   // DTypeDesc of static field's declaring type || DObject if field called on DObject known at compile time || otherwise object
                additionalArgs.ToArray(),
                returnType);

            var delegateType = /*System.Linq.Expressions.Expression.*/ delegateBuilder.GetDelegateType(delegateTypeArgs, callSitesCount);    // (J) do not create dynamic delegates in dynamic modules, so they can be referenced from non-transient assemblies

            //
            var field = DefineCallSite(cg.IL, string.Format("get{0}_{1}", wantRef ? "ref" : string.Empty, fieldName ?? "$"), delegateType, (il) =>
            {
                // <LOAD> Binder.{GetProperty|GetStaticProperty}( fieldName, classContext, issetSemantics, <returnType> )
                if (fieldName != null)
                {
                    il.Emit(OpCodes.Ldstr, fieldName);
                }
                else
                {
                    il.Emit(OpCodes.Ldnull);
                }
                if (this.classContextPlace != null)
                {
                    this.classContextPlace.EmitLoad(il);
                }
                else
                {
                    il.Emit(OpCodes.Ldsfld, Fields.UnknownTypeDesc.Singleton);
                }
                il.LoadBool(issetSemantics);

                il.Emit(OpCodes.Ldtoken, returnType);
                il.Emit(OpCodes.Call, Methods.GetTypeFromHandle);

                il.Emit(OpCodes.Call, staticCall ? Methods.Binder.StaticGetProperty : Methods.Binder.GetProperty);
            });

            //
            // call the CallSite:
            //

            // <field>.Target( <field>, <targetExpr|targetType>, (classContext)?, <methodNameExpr>? ):

            cg.IL.Emit(OpCodes.Ldsfld, field);
            cg.IL.Emit(OpCodes.Ldfld, field.FieldType.GetField("Target"));
            cg.IL.Emit(OpCodes.Ldsfld, field);
            if (staticCall)
            {
                targetType.EmitLoadTypeDesc(cg, ResolveTypeFlags.UseAutoload | ResolveTypeFlags.ThrowErrors);
            }
            else if (targetExpr != null)
            {
                cg.ChainBuilder.Lengthen();         // for hop over ->
                cg.EmitBoxing(targetExpr.Emit(cg)); // prepare for operator invocation
            }
            else if (targetObjectPlace != null)
            {
                targetObjectPlace.EmitLoad(cg.IL);
            }
            else if (targetPlace != null)
            {
                targetPlace.EmitLoad(cg.IL);
            }
            else
            {
                Debug.Fail();
            }
            if (!classContextIsKnown)
            {
                cg.EmitLoadClassContext();
            }
            if (!fieldNameIsKnown)
            {
                cg.EmitName(fieldName /*null*/, fieldNameExpr, true, PhpTypeCode.String);
            }

            cg.MarkTransientSequencePoint();
            cg.IL.Emit(OpCodes.Callvirt, delegateType.GetMethod("Invoke"));

            cg.MarkTransientSequencePoint();

            //
            return(PhpTypeCodeEnum.FromType(returnType));
        }
Пример #25
0
        /// <summary>
        /// Create and call <see cref="CallSite"/> for getting property.
        /// </summary>
        /// <param name="cg"><see cref="CodeGenerator"/>.</param>
        /// <param name="wantRef">Wheter <see cref="PhpReference"/> is expected as the result.</param>
        /// <param name="targetExpr">The expression representing the target (object).</param>
        /// <param name="targetObjectPlace">The place representing the target (<see cref="DObject"/>) iff <paramref name="targetExpr"/> is not provided.</param>
        /// <param name="targetPlace">The place representing the target (object) iff <paramref name="targetExpr"/> and <paramref name="targetObjectPlace"/> are not provided.</param>
        /// <param name="targetType">Type of target iff we are getting property statically.</param>
        /// <param name="fieldName">The name of the field. Can be null if the name is not known at compile time (indirect).</param>
        /// <param name="fieldNameExpr">The expression used to get field name in run time (iff <paramref name="fieldName"/> is <c>null</c>.</param>
        /// <param name="issetSemantics">Wheter we are only checking if the property exists. If true, no warnings are thrown during run time.</param>
        /// <returns>Type code of the value that is pushed onto the top of the evaluation stack.</returns>
        public PhpTypeCode EmitGetProperty(
            PHP.Core.CodeGenerator/*!*/cg, bool wantRef,
            Expression targetExpr, IPlace targetObjectPlace, IPlace targetPlace, DType targetType,
            string fieldName, Expression fieldNameExpr,
            bool issetSemantics)
        {
            Debug.Assert(fieldName != null ^ fieldNameExpr != null);
            Debug.Assert(targetExpr != null || targetObjectPlace != null || targetPlace != null || targetType != null);
            
            //
            bool staticCall = (targetExpr == null && targetObjectPlace == null && targetPlace == null); // we are going to access static property
            bool fieldNameIsKnown = (fieldName != null);
            bool classContextIsKnown = (this.classContextPlace != null);

            //
            // binder flags:
            //
            Type returnType = wantRef ? Types.PhpReference[0] : Types.Object[0];
            
            //
            // define the call site:
            //

            //
            List<Type> additionalArgs = new List<Type>();
            if (!classContextIsKnown) additionalArgs.Add(Types.DTypeDesc[0]);
            if (!fieldNameIsKnown) additionalArgs.Add(Types.String[0]);

            var delegateTypeArgs = GetPropertyDelegateTypeArgs(
                staticCall ? Types.DTypeDesc[0] : ((targetObjectPlace != null) ? Types.DObject[0] : Types.Object[0]),   // DTypeDesc of static field's declaring type || DObject if field called on DObject known at compile time || otherwise object
                additionalArgs.ToArray(),
                returnType);

            var delegateType = /*System.Linq.Expressions.Expression.*/delegateBuilder.GetDelegateType(delegateTypeArgs, callSitesCount);    // (J) do not create dynamic delegates in dynamic modules, so they can be referenced from non-transient assemblies

            //
            var field = DefineCallSite(cg.IL, string.Format("get{0}_{1}", wantRef ? "ref" : string.Empty, fieldName ?? "$"), delegateType, (il) =>
            {
                // <LOAD> Binder.{GetProperty|GetStaticProperty}( fieldName, classContext, issetSemantics, <returnType> )
                if (fieldName != null) il.Emit(OpCodes.Ldstr, fieldName); else il.Emit(OpCodes.Ldnull);
                if (this.classContextPlace != null) this.classContextPlace.EmitLoad(il); else il.Emit(OpCodes.Ldsfld, Fields.UnknownTypeDesc.Singleton);
                il.LoadBool(issetSemantics);

                il.Emit(OpCodes.Ldtoken, returnType);
                il.Emit(OpCodes.Call, Methods.GetTypeFromHandle);

                il.Emit(OpCodes.Call, staticCall ? Methods.Binder.StaticGetProperty : Methods.Binder.GetProperty);
            });

            //
            // call the CallSite:
            //

            // <field>.Target( <field>, <targetExpr|targetType>, (classContext)?, <methodNameExpr>? ):

            cg.IL.Emit(OpCodes.Ldsfld, field);
            cg.IL.Emit(OpCodes.Ldfld, field.FieldType.GetField("Target"));
            cg.IL.Emit(OpCodes.Ldsfld, field);
            if (staticCall) targetType.EmitLoadTypeDesc(cg, ResolveTypeFlags.UseAutoload | ResolveTypeFlags.ThrowErrors);
            else if (targetExpr != null)
            {
                cg.ChainBuilder.Lengthen(); // for hop over ->
                cg.EmitBoxing(targetExpr.Emit(cg)); // prepare for operator invocation
            }
            else if (targetObjectPlace != null) targetObjectPlace.EmitLoad(cg.IL);
            else if (targetPlace != null) targetPlace.EmitLoad(cg.IL);
            else Debug.Fail();
            if (!classContextIsKnown) cg.EmitLoadClassContext();
            if (!fieldNameIsKnown) cg.EmitName(fieldName/*null*/, fieldNameExpr, true, PhpTypeCode.String);

            cg.MarkTransientSequencePoint();
            cg.IL.Emit(OpCodes.Callvirt, delegateType.GetMethod("Invoke"));

            cg.MarkTransientSequencePoint();
            
            //
            return PhpTypeCodeEnum.FromType(returnType);
        }
Пример #26
0
        /// <summary>
        /// Emit load <paramref name="instance"/> in top of the evaluation stack. Unwraps the value if &lt;proxy&gt; is used instead of <c>this</c>.
        /// </summary>
        /// <param name="codeGenerator"></param>
        /// <param name="instance"></param>
        private static void EmitLoadInstanceUnwrapped(CodeGenerator/*!*/ codeGenerator, IPlace instance)
        {
            if (instance != null)
            {
                // just detect DirectVarUse holding $this in context of Type with <proxy> property:
                var targetExpression = ExpressionPlace.GetExpression(instance);

                // pass RealObject instead of DObject when using <proxy>:   // J: ASP.NET code behind fix // ArgLesses expect RealObject too
                if (targetExpression != null &&
                    codeGenerator.LocationStack.InMethodDecl && codeGenerator.LocationStack.PeekMethodDecl().Type.ProxyFieldInfo != null &&    // current type has "<proxy>" property
                    targetExpression is DirectVarUse && ((DirectVarUse)targetExpression).VarName.IsThisVariableName && ((DirectVarUse)targetExpression).IsMemberOf == null)   // we are accessing "this"
                    instance = IndexedPlace.ThisArg;    // "this" instead of "this.<proxy>"

                //
                instance.EmitLoad(codeGenerator.IL);
            }
        }
Пример #27
0
		internal override AssignmentCallback EmitSet(CodeGenerator/*!*/ codeGenerator, IPlace instance, bool isRef,
			ConstructedType constructedType, bool runtimeVisibilityCheck)
		{
			Debug.Assert(IsStatic == (instance == null));

			if (IsStatic)
			{
				// check the visibility at runtime by the operator:
				if (runtimeVisibilityCheck)
					return codeGenerator.EmitSetStaticPropertyOperator(DeclaringType, this.FullName, null, isRef);
			}
			else
			{
				// load target instance:
				instance.EmitLoad(codeGenerator.IL);
			}

			return delegate(CodeGenerator codeGen, PhpTypeCode stackTypeCode)
			{
				// TODO: can we get different PhpTypeCode?
				ILEmitter il = codeGen.IL;
				PropertyDesc.EmitSetConversion(il, stackTypeCode, fieldInfo.FieldType);

				il.Emit(IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fieldInfo);
			};
		}
Пример #28
0
 public override ITypeSymbol EmitLoadTypeInfo(CodeGenerator cg, bool throwOnError = false)
 {
     return(_place
            .EmitLoad(cg.Builder)
            .Expect(cg.CoreTypes.PhpTypeInfo));
 }
Пример #29
0
		internal void EmitGetEventObject(ILEmitter/*!*/ il, IPlace/*!*/ contextPlace, IPlace instance, bool dynamicStub)
		{
			// [ ClrEventObject<handlerType>.Wrap(<SC>, <event name>, <addMethod>, <removeMethod>) ]

			contextPlace.EmitLoad(il);
			il.Emit(OpCodes.Ldstr, FullName);

			ConstructorInfo hook_ctor = typeof(Library.EventClass<>.HookDelegate).MakeGenericType(HandlerType).
				GetConstructor(Types.DelegateCtorArgs);

			// create delegates to the add and remove methods
			EmitLoadAccessorDelegate(il, hook_ctor, instance, dynamicStub, AddMethod);
			EmitLoadAccessorDelegate(il, hook_ctor, instance, dynamicStub, RemoveMethod);

			MethodInfo wrap_method = typeof(Library.EventClass<>).MakeGenericType(HandlerType).GetMethod("Wrap");
			il.Emit(OpCodes.Call, wrap_method);
		}
Пример #30
0
        /// <summary>
        /// Emits <c>place != null</c> expression.
        /// </summary>
        public void EmitNotNull(IPlace place)
        {
            Debug.Assert(place != null);
            Debug.Assert(place.TypeOpt.IsReferenceType);

            // {place} != null : boolean
            place.EmitLoad(_il);
            _il.EmitNullConstant();
            _il.EmitOpCode(ILOpCode.Cgt_un);
        }
Пример #31
0
        private ArrayList refReferences = new ArrayList(3);           // GENERICS: <LocalBuilder>

        #endregion

        #region Call Switch Emitter

        /// <summary>
        /// Emits calls to specified overloads and a switch statement which calls appropriate overload
        /// according to the current value of <see cref="PhpStack.ArgCount"/> field of the current stack.
        /// </summary>
        /// <param name="thisRef">Reference to self.</param>
        /// <param name="script_context">Current script context.</param>
        /// <param name="rtVariables">
        /// Place where a run-time variables table can be loaded from.
        /// </param>
        /// <param name="namingContext">Naming context load-from place.</param>
        /// <param name="classContext">Class context load.</param>
        /// <param name="overloads">The overload list.</param>
        /// <remarks>
        /// Example: given overloads (2,5,7,9+), i.e. there are four overloads having 2, 5, 7 and 9 PHP parameters,
        /// respectively, and the last overload is marked as vararg,
        /// the method emits the following code:
        /// <code>
        /// switch(ArgCount - 2)                  // 2 = minimum { arg count of overload }
        /// {
        ///   case 0: return call #2;             // call to the 2nd overload with appropriate arg. and return value handling
        ///   case 1: goto case error;
        ///   case 2: goto case error;
        ///   case 3: return call #5;
        ///   case 4: goto case error;
        ///   case 5: return call #7;
        ///   case 6: goto case error;
        ///
        /// #if vararg
        ///   case 7: goto default;
        ///   default: return call #vararg (9 mandatory args,optional args);break;
        /// #elif
        ///   case 7: return call #9;
        ///   default: goto case error;
        /// #endif
        ///
        ///   case error: PhpException.InvalidArgumentCount(null, functionName); break;
        /// }
        /// </code>
        /// </remarks>
        public void EmitCallSwitch(IPlace /*!*/ thisRef, IPlace /*!*/ script_context, IPlace /*!*/ rtVariables, IPlace /*!*/ namingContext, IPlace /*!*/ classContext, List <PhpLibraryFunction.Overload> /*!!*/ overloads)
        {
            Debug.AssertAllNonNull(overloads);

            int last = overloads.Count - 1;
            int min  = overloads[0].ParamCount;
            int max  = overloads[last].ParamCount;

            var flags = overloads[last].Flags;

            // if function is not supported, just throw the warning:
            if ((flags & PhpLibraryFunction.OverloadFlags.NotSupported) != 0)
            {
                // stack.RemoveFrame();
                if (stack != null)
                {
                    stack.EmitLoad(il);
                    il.Emit(OpCodes.Call, Methods.PhpStack.RemoveFrame);
                }

                // PhpException.FunctionNotSupported( <FullName> );
                il.Emit(OpCodes.Ldstr, FunctionName.Value);
                il.Emit(OpCodes.Call, Methods.PhpException.FunctionNotSupported_String);
                if (debug)
                {
                    il.Emit(OpCodes.Nop);
                }

                // load methods default value
                il.EmitBoxing(OverloadsBuilder.EmitLoadDefault(il, overloads[last].Method));
                return;
            }

            bool is_vararg = (flags & PhpLibraryFunction.OverloadFlags.IsVararg) != 0;

            if ((flags & PhpLibraryFunction.OverloadFlags.NeedsScriptContext) == 0)
            {
                script_context = null;
            }

            if ((flags & PhpLibraryFunction.OverloadFlags.NeedsThisReference) == 0)
            {
                thisRef = null;
            }

            if ((flags & PhpLibraryFunction.OverloadFlags.NeedsVariables) == 0)
            {
                rtVariables = null;
            }

            if ((flags & PhpLibraryFunction.OverloadFlags.NeedsNamingContext) == 0)
            {
                namingContext = null;
            }

            if ((flags & (PhpLibraryFunction.OverloadFlags.NeedsClassContext | PhpLibraryFunction.OverloadFlags.NeedsLateStaticBind)) == 0)
            {
                classContext = null;
            }

            Label end_label   = il.DefineLabel();
            Label error_label = il.DefineLabel();

            Label[]    cases = new Label[max - min + 1];
            MethodInfo method;

            // fills cases with "goto case error":
            for (int i = 0; i < cases.Length; i++)
            {
                cases[i] = error_label;
            }

            // define labels for valid cases:
            for (int i = 0; i < overloads.Count; i++)
            {
                int count = overloads[i].ParamCount;
                cases[count - min] = il.DefineLabel();
            }

            // LOAD(stack.ArgCount - min);
            stack.EmitLoad(il);
            il.Emit(OpCodes.Ldfld, Fields.PhpStack_ArgCount);
            il.LdcI4(min);
            il.Emit(OpCodes.Sub);

            // SWITCH(tmp)
            il.Emit(OpCodes.Switch, cases);

            // CASE >=N or <0 (underflows);
            // if the last overload is vararg:
            if (is_vararg)
            {
                LocalBuilder opt_arg_count_local = il.DeclareLocal(typeof(int));

                // CASE N:
                il.MarkLabel(cases[cases.Length - 1]);

                // opt_arg_count = stack.ArgCount - max;
                stack.EmitLoad(il);
                il.Emit(OpCodes.Ldfld, Fields.PhpStack_ArgCount);
                il.LdcI4(max);
                il.Emit(OpCodes.Sub);
                il.Stloc(opt_arg_count_local);

                // IF(tmp<0) GOTO CASE error;
                il.Ldloc(opt_arg_count_local);
                il.Emit(OpCodes.Ldc_I4_0);
                il.Emit(OpCodes.Blt, error_label);

                // emits argument loading, stack frame removal, method call, return value conversion:
                method = overloads[last].Method;
                Type return_type = EmitOverloadCall(method, overloads[last].RealParameters, max, script_context,
                                                    rtVariables, namingContext, classContext, new Place(opt_arg_count_local), thisRef, false);

                // loads boxed return value:
                if (return_type != Types.Void)
                {
                    //il.LoadBoxed(return_value);
                    if (return_type.IsValueType)
                    {
                        il.Emit(OpCodes.Box, return_type);
                    }
                }
                else
                {
                    il.Emit(OpCodes.Ldnull);
                }

                // RETURN;
                il.Emit(OpCodes.Ret);                  //bug in Reflector: il.Emit(OpCodes.Br,end_label);
            }
            else
            {
                // GOTO CASE error;
                il.Emit(OpCodes.Br, error_label);
            }

            // emits all valid cases which are not vararg:
            int j = 0;

            for (int i = min; i <= max - (is_vararg ? 1 : 0); i++)
            {
                if (overloads[j].ParamCount == i)
                {
                    // CASE <i>;
                    il.MarkLabel(cases[i - min]);

                    // emits argument loading, stack frame removal, method call, return value conversion:
                    method = overloads[j].Method;
                    Type return_type = EmitOverloadCall(method, overloads[j].RealParameters, i, script_context, rtVariables, namingContext, classContext, null, thisRef, false);

                    // loads boxed return value:
                    if (return_type != Types.Void)
                    {
                        //il.LoadBoxed(return_value);
                        if (return_type.IsValueType)
                        {
                            il.Emit(OpCodes.Box, return_type);
                        }
                    }
                    else
                    {
                        il.Emit(OpCodes.Ldnull);
                    }

                    // RETURN;
                    il.Emit(OpCodes.Ret);                      //bug in Reflector: il.Emit(OpCodes.Br,end_label);

                    j++;
                }
            }
            Debug.Assert(j + (is_vararg ? 1 : 0) == overloads.Count);

            // ERROR:
            il.MarkLabel(error_label);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Ldstr, this.functionName.ToString());
            il.Emit(OpCodes.Call, Methods.PhpException.InvalidArgumentCount);
            if (debug)
            {
                il.Emit(OpCodes.Nop);
            }

            // RETURN null:
            il.Emit(OpCodes.Ldnull);
            il.MarkLabel(end_label);
        }
Пример #32
0
        internal override PhpTypeCode EmitGet(CodeGenerator/*!*/ codeGenerator, IPlace instance, bool wantRef,
            ConstructedType constructedType, bool runtimeVisibilityCheck)
        {
            Debug.Assert(IsStatic == (instance == null));

            ILEmitter il = codeGenerator.IL;
            var getter = RealProperty.GetGetMethod();

            if (getter == null)
                throw new MissingMethodException(string.Format("'{0}.get_{1}' not implemented!", RealProperty.DeclaringType.Name, RealProperty.Name));

            // <this>.
            if (!IsStatic)
                instance.EmitLoad(il);

            // getter()
            il.Emit(OpCodes.Call, getter);
            
            // handle references
            if (wantRef)
            {
                // make reference
                if (Types.PhpReference[0].IsAssignableFrom(getter.ReturnType))
                {
                    EmitIsAliased(il);
                }
                else
                {
                    throw new NotImplementedException();
                }
                //
                return PhpTypeCode.PhpReference;
            }
            else
            {
                // dereference
                if (Types.PhpReference[0].IsAssignableFrom(getter.ReturnType))
                {
                    EmitIsAliased(il);
                    il.Emit(OpCodes.Ldfld, Fields.PhpReference_Value);
                }
                else
                {
                    il.EmitBoxing(PhpTypeCodeEnum.FromType(getter.ReturnType));
                }
                //
                return PhpTypeCode.Object;
            }
        }
Пример #33
0
		public static object EmitReferencePeekUnchecked(ILEmitter/*!*/ il, IPlace/*!*/ stack, IPlace/*!*/ index)
		{
			Debug.Assert(il != null && stack != null && index != null);

			// LOAD stack.PeekReferenceUnchecked(<index+1>);
			stack.EmitLoad(il);
			index.EmitLoad(il);
			il.Emit(OpCodes.Call, Methods.PhpStack.PeekReferenceUnchecked);

			return typeof(PhpReference);
		}
Пример #34
0
        internal override AssignmentCallback EmitSet(CodeGenerator/*!*/ codeGenerator, IPlace instance, bool isRef,
            ConstructedType constructedType, bool runtimeVisibilityCheck)
        {
            ILEmitter il = codeGenerator.IL;
            var setter = RealProperty.GetSetMethod();

            if (setter == null)
                throw new MissingMethodException(string.Format("'{0}.set_{1}' not implemented!", RealProperty.DeclaringType.Name, RealProperty.Name));

            // <this>.
            if (!IsStatic)
                instance.EmitLoad(il);

            // setter()
            return delegate(CodeGenerator codeGen, PhpTypeCode stackTypeCode)
            {
                var parameters = setter.GetParameters();

                if (isRef && parameters[0].ParameterType != Types.PhpReference[0])
                {
                    // .setter(<stack>.Value)
                    codeGen.IL.Emit(OpCodes.Ldfld, Fields.PhpReference_Value);
                    codeGen.IL.Emit(OpCodes.Call, setter);
                }
                else if (!isRef && parameters[0].ParameterType == Types.PhpReference[0])
                {
                    // .getter().Value = <stack>
                    codeGen.IL.Emit(OpCodes.Call, RealProperty.GetGetMethod());
                    codeGen.IL.Emit(OpCodes.Stfld, Fields.PhpReference_Value);
                }
                else
                {
                    // .setter(<stack>)
                    codeGen.IL.Emit(OpCodes.Call, setter);
                }
            };
        }
Пример #35
0
        /// <summary>
        /// Emits load of an array where all optional arguments are stored.
        /// Each optional argument is peeked from the PHP stack and converted before stored to the array.
        /// The resulting array is pushed on evaluation stack so it can be later passed as an argument to a method.
        /// </summary>
        /// <param name="builder">The builder.</param>
        /// <param name="start">The index of the first argument to be loaded.</param>
        /// <param name="param">The last parameter of the overload (should be an array).</param>
        /// <param name="optArgCount">The place where the number of optional arguments is stored.</param>
        /// <remarks>Assumes that the non-negative number of optional arguments has been stored to
        /// <paramref name="optArgCount"/> place.</remarks>
        public static void EmitPeekAllArguments(OverloadsBuilder /*!*/ builder, int start, ParameterInfo param, IPlace optArgCount)
        {
            Debug.Assert(start >= 0 && optArgCount != null && param != null);

            ILEmitter il         = builder.IL;
            Type      elem_type  = param.ParameterType.GetElementType();
            Type      array_type = Type.GetType(elem_type.FullName + "[]", true);
            Type      actual_type;

            // declares aux. variables:
            LocalBuilder loc_array = il.DeclareLocal(array_type);
            LocalBuilder loc_i     = il.DeclareLocal(typeof(int));
            LocalBuilder loc_elem  = il.DeclareLocal(elem_type);

            // creates an array for the arguments
            // array = new <elem_type>[opt_arg_count]:
            optArgCount.EmitLoad(il);
            il.Emit(OpCodes.Newarr, elem_type);
            il.Stloc(loc_array);

            Label for_end_label   = il.DefineLabel();
            Label condition_label = il.DefineLabel();

            // i = 0;
            il.Emit(OpCodes.Ldc_I4_0);
            il.Stloc(loc_i);

            // FOR (i = 0; i < opt_arg_count; i++)
            if (true)
            {
                il.MarkLabel(condition_label);

                // condition (i < opt_arg_count):
                il.Ldloc(loc_i);
                optArgCount.EmitLoad(il);
                il.Emit(OpCodes.Bge, for_end_label);

                // LOAD stack, i + start+1>:
                builder.Stack.EmitLoad(il);
                il.Ldloc(loc_i);
                il.LdcI4(start + 1);
                il.Emit(OpCodes.Add);

                if (elem_type == typeof(PhpReference))
                {
                    // CALL stack.PeekReferenceUnchecked(STACK);
                    il.Emit(OpCodes.Call, Methods.PhpStack.PeekReferenceUnchecked);
                    actual_type = typeof(PhpReference);
                }
                else
                {
                    // CALL stack.PeekValueUnchecked(STACK);
                    il.Emit(OpCodes.Call, Methods.PhpStack.PeekValueUnchecked);
                    actual_type = typeof(object);
                }

                // emits a conversion stuff (loads result into "elem" local variable):
                builder.EmitArgumentConversion(elem_type, actual_type, false, param);
                il.Stloc(loc_elem);

                // array[i] = elem;
                il.Ldloc(loc_array);
                il.Ldloc(loc_i);
                il.Ldloc(loc_elem);
                il.Stelem(elem_type);

                // i = i + 1;
                il.Ldloc(loc_i);
                il.Emit(OpCodes.Ldc_I4_1);
                il.Emit(OpCodes.Add);
                il.Stloc(loc_i);

                // GOTO condition;
                il.Emit(OpCodes.Br, condition_label);
            }
            // END FOR

            il.MarkLabel(for_end_label);

            // loads array to stack - consumed by the method call:
            il.Ldloc(loc_array);
        }
Пример #36
0
		internal override PhpTypeCode EmitGet(CodeGenerator/*!*/ codeGenerator, IPlace instance, bool wantRef,
			ConstructedType constructedType, bool runtimeVisibilityCheck)
		{
			Debug.Assert(IsStatic == (instance == null));
			Debug.Assert(hasGetter, "TODO");

			ILEmitter il = codeGenerator.IL;

			if (IsStatic)
			{
				if (runtimeVisibilityCheck)
				{
					// let the operator to check the visibility:
					return codeGenerator.EmitGetStaticPropertyOperator(DeclaringType, this.FullName, null, wantRef);
				}
			}
			else
			{
				instance.EmitLoad(il);
			}

			MethodInfo getter = this.Getter;

			il.Emit(getter.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, getter);

			PhpTypeCode result = ClrOverloadBuilder.EmitConvertToPhp(il, getter.ReturnType/*, codeGenerator.ScriptContextPlace*/);

			codeGenerator.EmitReferenceDereference(ref result, wantRef);
			return result;
		}
Пример #37
0
		/// <summary>
		/// Emits call to <see cref="ScriptContext.DeclareFunction"/>.
		/// </summary>
		internal static void EmitDeclareFunction(ILEmitter/*!*/il, IPlace/*!*/scriptContextPlace, PhpFunction/*!*/ function)
        {
            Label lbl_fieldinitialized = il.DefineLabel();

            // private static PhpRoutine <routine>'function = null;
            var attrs = FieldAttributes.Static | FieldAttributes.Private;
            var field = il.TypeBuilder.DefineField(string.Format("<routine>'{0}", function.FullName), typeof(PhpRoutineDesc), attrs);

            // if (<field> == null)
            il.Emit(OpCodes.Ldsfld, field);
            il.Emit(OpCodes.Brtrue, lbl_fieldinitialized);
            {
                // <field> = new PhpRoutineDesc(<attributes>, new RoutineDelegate(null, <delegate>))

                // LOAD <attributes>;
                il.LdcI4((int)function.MemberDesc.MemberAttributes);

                // new RoutineDelegate(null, <delegate>, true)
                il.Emit(OpCodes.Ldnull);
                il.Emit(OpCodes.Ldftn, function.ArgLessInfo);
                il.Emit(OpCodes.Newobj, Constructors.RoutineDelegate);
                il.LoadBool(true);

                // new PhpRoutineDesc:
                il.Emit(OpCodes.Newobj, Constructors.PhpRoutineDesc_Attr_Delegate_Bool);

                // <field> = <STACK>
                il.Emit(OpCodes.Stsfld, field);

                // new PurePhpFunction(<field>, fullName, argfull);   // writes desc.Member
                il.Emit(OpCodes.Ldsfld, field);
                il.Emit(OpCodes.Ldstr, function.FullName);
                CodeGenerator.EmitLoadMethodInfo(il, function.ArgFullInfo/*, AssemblyBuilder.DelegateBuilder*/);
                il.Emit(OpCodes.Newobj, Constructors.PurePhpFunction);
                il.Emit(OpCodes.Pop);
                
            }
            il.MarkLabel(lbl_fieldinitialized);

            // CALL ScriptContent.DeclareFunction(<field>, <name>);
            scriptContextPlace.EmitLoad(il);
            
            // LOAD <field>
            il.Emit(OpCodes.Ldsfld, field);            

            // LOAD <fullName>
            il.Emit(OpCodes.Ldstr, function.FullName);

            //
            il.Emit(OpCodes.Call, Methods.ScriptContext.DeclareFunction);
        }
Пример #38
0
 public TypeSymbol EmitLoad(ILBuilder il) => _place.EmitLoad(il);
Пример #39
0
		private PhpTypeCode EmitGetInternal(CodeGenerator/*!*/ codeGenerator, IPlace instance, bool wantRef,
			ConstructedType constructedType, bool runtimeVisibilityCheck, bool setAliasedFlag)
		{
			ILEmitter il = codeGenerator.IL;

			if (IsStatic)
			{
				if (runtimeVisibilityCheck || UpgradesVisibility)
				{
					// let the operator to check the visibility:
					return codeGenerator.EmitGetStaticPropertyOperator(DeclaringType, this.FullName, null, wantRef);
				}

				if (!IsAppStatic) Implementor.EmitThreadStaticInit(codeGenerator, constructedType);

				// retrieve field value
				il.Emit(OpCodes.Ldsfld, DType.MakeConstructed(RealField, constructedType));
				if (wantRef)
				{
					if (setAliasedFlag)
					{
						// set IsAliased to true
						il.Emit(OpCodes.Dup);
						il.Emit(OpCodes.Ldc_I4_1);
						il.EmitCall(OpCodes.Callvirt, Properties.PhpReference_IsAliased.GetSetMethod(), null);
					}

					return PhpTypeCode.PhpReference;
				}
				else
				{
					il.Emit(OpCodes.Ldfld, Fields.PhpReference_Value);

					return PhpTypeCode.Object;
				}
			}
			else
			{
				// LOAD Operators.GetObjectFieldDirect[Ref](this,this.<field>,<name>,<type desc>,[<quiet>]);
				codeGenerator.EmitLoadSelf();
				instance.EmitLoad(il);
				il.Emit(OpCodes.Ldfld, DType.MakeConstructed(RealField, constructedType));
				il.Emit(OpCodes.Ldstr, Name.ToString());
				codeGenerator.EmitLoadClassContext();

				if (wantRef)
				{
					il.Emit(OpCodes.Call, Methods.Operators.GetObjectFieldDirectRef);

					return PhpTypeCode.PhpReference;
				}
				else
				{
					il.LoadBool(codeGenerator.ChainBuilder.QuietRead);
					il.Emit(OpCodes.Call, Methods.Operators.GetObjectFieldDirect);

					return PhpTypeCode.Object;
				}
			}
		}
Пример #40
0
		internal override AssignmentCallback EmitSet(CodeGenerator/*!*/ codeGenerator, IPlace instance, bool isRef,
			ConstructedType constructedType, bool runtimeVisibilityCheck)
		{
			Debug.Assert(IsStatic == (instance == null));

			AdjustConstructedType(ref constructedType);

			if (IsStatic)
			{
				// check the visibility at runtime by the operator:
				if (runtimeVisibilityCheck || UpgradesVisibility)
					return codeGenerator.EmitSetStaticPropertyOperator(DeclaringType, this.FullName, null, isRef);

				if (isRef)
				{
					if (!IsAppStatic) Implementor.EmitThreadStaticInit(codeGenerator, constructedType);

					// just write the PhpReference to the field upon assignment
					return delegate(CodeGenerator codeGen, PhpTypeCode stackTypeCode)
					{
						codeGen.IL.Emit(OpCodes.Stsfld, DType.MakeConstructed(RealField, constructedType));
					};
				}
				else
				{
					// read the PhpReference stored in the field
					EmitGetInternal(codeGenerator, null, true, constructedType, false, false);

					// finish the assignment by writing to its Value field
					return delegate(CodeGenerator codeGen, PhpTypeCode stackTypeCode)
					{
						codeGen.IL.Emit(OpCodes.Stfld, Fields.PhpReference_Value);
					};
				}
			}
			else
			{
				// direct access is possible, however, we have to be prepared for actually calling
				// the operator if the field proves to have been unset

				return delegate(CodeGenerator codeGen, PhpTypeCode stackTypeCode)
				{
					ILEmitter il = codeGen.IL;

					codeGen.EmitLoadSelf();
					instance.EmitLoad(il);
					il.Emit(isRef ? OpCodes.Ldflda : OpCodes.Ldfld, DType.MakeConstructed(RealField, constructedType));
					il.Emit(OpCodes.Ldstr, Name.ToString());
					codeGen.EmitLoadClassContext();

					if (isRef)
					{
						// CALL Operators.SetObjectFieldDirectRef(STACK,<target>,ref <field>,<field name>,<type desc>)
						il.Emit(OpCodes.Call, Methods.Operators.SetObjectFieldDirectRef);
					}
					else
					{
						// CALL Operators.SetObjectFieldDirect(STACK,<target>,<field>,<field name>,<type desc>)
						il.Emit(OpCodes.Call, Methods.Operators.SetObjectFieldDirect);
					}
				};
			}
		}
Пример #41
0
        /// <summary>
        /// Emit LOAD <paramref name="instance"/>.
        /// </summary>ILEmiter
        /// <param name="il"><see cref="ILEmitter"/> object instance.</param>
        /// <param name="instance">The place where to load the instance from.</param>
        /// <param name="declaringType">The type of resulting instance.</param>
        /// <remarks>Instance of value types are wrapped in <see cref="ClrValue&lt;T&gt;"/> object instance.</remarks>
        internal static void EmitLoadInstance(ILEmitter/*!*/il, IPlace/*!*/instance, Type/*!*/declaringType)
        {
            Debug.Assert(il != null && instance != null && declaringType != null, "ClrOverloadBuilder.EmitLoadInstance() null argument!");

            // LOAD <instance>
            instance.EmitLoad(il);

            if (declaringType.IsValueType)
            {
                var clrValueType = ClrObject.valueTypesCache.Get(declaringType).Item1;
                Debug.Assert(clrValueType != null, "Specific ClrValue<T> not found!");

                // CAST (ClrValue<T>)
                il.Emit(OpCodes.Castclass, clrValueType);

                // LOAD .realValue
                var realValueField = clrValueType.GetField("realValue");
                Debug.Assert(realValueField != null, "ClrValue<T>.realValue field not found!");
                il.Emit(OpCodes.Ldflda, clrValueType.GetField("realValue"));
            }
            else
            {
                // CAST (T)
                il.Emit(OpCodes.Castclass, declaringType);
            }
        }
Пример #42
0
		internal override void EmitUnset(CodeGenerator/*!*/ codeGenerator, IPlace/*!*/ instance,
			ConstructedType constructedType, bool runtimeVisibilityCheck)
		{
			ILEmitter il = codeGenerator.IL;

			if (IsStatic)
			{
				// emit error (whether or not the property is visible):
				il.Emit(OpCodes.Ldstr, DeclaringType.FullName);
				il.Emit(OpCodes.Ldstr, this.FullName);
				codeGenerator.EmitPhpException(Methods.PhpException.StaticPropertyUnset);
				return;
			}

			// replace the field with a new PhpSmartReference with IsSet false
			instance.EmitLoad(il);
			il.Emit(OpCodes.Newobj, Constructors.PhpSmartReference.Void);
			il.Emit(OpCodes.Dup);
			
			il.LoadBool(false);
			il.Emit(OpCodes.Callvirt, Properties.PhpReference_IsSet.GetSetMethod());

			il.Emit(OpCodes.Stfld, DType.MakeConstructed(RealField, constructedType));
		}
Пример #43
0
		/// <summary>
		/// Loads a value from a specified place on the evaluation stack and boxes it if it is of a value type.
		/// </summary>
		/// <param name="place">The place where to load a value from.</param>
		public void LoadBoxed(IPlace/*!*/ place)
		{
			Type type = place.PlaceType;

			place.EmitLoad(this);
			if (type.IsValueType)
				il.Emit(OpCodes.Box, type);
		}
Пример #44
0
        internal TypeSymbol EmitGetProperty(IPlace holder, PropertySymbol prop)
        {
            Debug.Assert(prop.IsStatic || holder != null);
            Debug.Assert(prop.GetMethod != null);
            Debug.Assert(prop.GetMethod.ParameterCount == 0);

            var getter = prop.GetMethod;

            if (holder != null && !getter.IsStatic)
            {
                Debug.Assert(holder.TypeOpt != null);
                if (holder.TypeOpt.IsValueType)
                {
                    holder.EmitLoadAddress(_il);
                }
                else
                {
                    holder.EmitLoad(_il);
                }
            }

            return EmitCall(getter.IsVirtual ? ILOpCode.Callvirt : ILOpCode.Call, getter);
        }