Example #1
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);
			}
		}
Example #2
0
		/// <summary>
		/// Emits helper declaring all single-declared functions and classes in the script being built.
		/// </summary>
		/// <remarks>
		/// For each function and class emits a call to <see cref="ApplicationContext.DeclareFunction"/> and 
        /// <see cref="ApplicationContext.DeclareType"/>, respectively, which declares it.
		/// The helper is called as the first instruction of Main helper. 
		/// </remarks>		
		private void EmitDeclareHelper()
		{
			PureCompilationUnit unit = this.PureCompilationUnit;
			ILEmitter il = new ILEmitter(declareHelperBuilder);
			IndexedPlace app_context_place = new IndexedPlace(PlaceHolder.Argument, 0);
            TypeBuilder publicsContainer = null;    // container type for public stubs of global declarations (which are inaccessible from other assemblies)

			foreach (PhpFunction function in unit.GetDeclaredFunctions())
			{
				if (function.IsDefinite)
				{
					app_context_place.EmitLoad(il);

					// NEW RoutineDelegate(<static method>);
					il.Emit(OpCodes.Ldnull);
					il.Emit(OpCodes.Ldftn, function.ArgLessInfo);
					il.Emit(OpCodes.Newobj, Constructors.RoutineDelegate);

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

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

                    // LOAD <argfull>
                    if (function.ArgFullInfo != null)
                        CodeGenerator.EmitLoadMethodInfo(
                            il,
                            (function.ArgFullInfo.DeclaringType != null)
                                ? function.ArgFullInfo
                                : EmitPhpFunctionPublicStub(ref publicsContainer, function) // function.ArgFullInfo is real global method not accessible from other assemblies, must be wrapped
                            /*, AssemblyBuilder.DelegateBuilder*/);
                    else
                        il.Emit(OpCodes.Ldnull);
                    
					// CALL <application context>.DeclareFunction(<stub>, <name>, <member attributes>, <argfull>)
					il.Emit(OpCodes.Call, Methods.ApplicationContext.DeclareFunction);
				}
			}

			foreach (PhpType type in unit.GetDeclaredTypes())
			{
				if (type.IsDefinite)
				{
					// CALL <application context>.DeclareType(<type desc>, <name>);
					type.EmitAutoDeclareOnApplicationContext(il, app_context_place);
				}
			}

			foreach (GlobalConstant constant in unit.GetDeclaredConstants())
			{
				if (constant.IsDefinite)
				{
					app_context_place.EmitLoad(il);

					// CALL <application context>.DeclareConstant(<name>, <value>);
					il.Emit(OpCodes.Ldstr, constant.FullName);
                    //il.Emit(OpCodes.Ldsfld, constant.RealField);
                    //if (constant.RealField.FieldType.IsValueType) il.Emit(OpCodes.Box, constant.RealField.FieldType);
                    il.LoadLiteralBox(constant.Value);
					il.Emit(OpCodes.Call, Methods.ApplicationContext.DeclareConstant);
				}
			}

			il.Emit(OpCodes.Ret);

            // complete the publicsContainer type, if created:
            if (publicsContainer != null)
                publicsContainer.CreateType();
		}
Example #3
0
        /// <summary>
        /// Emit <see cref="PhpVariable.Copy"/> if needed. It means <see cref="Expression.Access"/> has to be <see cref="AccessType.Read"/> and <paramref name="returnType"/> has to be copiable.
        /// </summary>
        /// <param name="il">The <see cref="ILEmitter"/>.</param>
        /// <param name="returnType"><see cref="PhpTypeCode"/> of function call return value.</param>
        protected void EmitReturnValueCopy(ILEmitter/*!*/il, PhpTypeCode returnType)
        {
            Debug.Assert(il != null);

            // copy only if we are reading the return value &&
            // only if return type is copiable:
            if (access != AccessType.None &&   // reading, not literals:
                PhpTypeCodeEnum.IsDeeplyCopied(returnType) &&
                returnType != PhpTypeCode.PhpReference) // PhpSmartReference can be an issue if method returns an object field (but this is handled by binders)
            {
                il.LdcI4((int)CopyReason.ReturnedByCopy);
                il.Emit(OpCodes.Call, Methods.PhpVariable.Copy);
            }
        }
Example #4
0
		internal void EmitSetConversion(ILEmitter/*!*/ il, PhpTypeCode sourceTypeCode, Type/*!*/ targetType)
		{
			LocalBuilder strictness = il.GetTemporaryLocal(typeof(PHP.Core.ConvertToClr.ConversionStrictness));
			if (!ClrOverloadBuilder.EmitConvertToClr(il, sourceTypeCode, targetType, strictness))
			{
				Label label_ok = il.DefineLabel();

				il.Ldloc(strictness);
				il.LdcI4((int)PHP.Core.ConvertToClr.ConversionStrictness.Failed);
				il.Emit(OpCodes.Ceq);
				il.Emit(OpCodes.Brfalse, label_ok);

				il.Emit(OpCodes.Ldstr, Property.DeclaringType.FullName);
				il.Emit(OpCodes.Ldstr, Property.FullName);
				il.Emit(OpCodes.Call, Methods.PhpException.PropertyTypeMismatch);

				il.MarkLabel(label_ok, true);
			}
			il.ReturnTemporaryLocal(strictness);
		}
Example #5
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);
        }
Example #6
0
		/// <summary>
		/// Emits code which pops argument from the <see cref="PhpStack"/> and pushes it on the evaluation stack.
		/// </summary>
		private void EmitPeekArgument(ILEmitter/*!*/ il, int index)
		{
			bool optional = index >= signature.MandatoryParamCount;
			int stack_offset = index + 1;

			if (signature.IsAlias(index))
			{
				// LOAD stack.PeekReference[Optional](<stack_offset>, [default_value]);
				arglessStackPlace.EmitLoad(il);                           // stack
				il.LdcI4(stack_offset);                                   // offset on stack

				if (optional)
					il.Emit(OpCodes.Call, Methods.PhpStack.PeekReferenceOptional);
				else
					il.Emit(OpCodes.Call, Methods.PhpStack.PeekReference);
			}
			else
			{
				// LOAD stack.PeekValue[Optional](<stack_offset>);
				arglessStackPlace.EmitLoad(il);                           // stack
				il.LdcI4(stack_offset);                                   // offset on stack

				if (optional)
					il.Emit(OpCodes.Call, Methods.PhpStack.PeekValueOptional);
				else
					il.Emit(OpCodes.Call, Methods.PhpStack.PeekValue);
			}
		}
Example #7
0
        private void EmitPeekPseudoGenericArgument(ILEmitter/*!*/ il, int index)
		{
			bool optional = index >= signature.MandatoryGenericParamCount;
			int stack_offset = index + 1;

			// LOAD stack.PeekType[Optional](<stack_offset>, [default_value]);
			arglessStackPlace.EmitLoad(il);                           // stack
			il.LdcI4(stack_offset);                                   // offset on stack

			if (optional)
				il.Emit(OpCodes.Call, Methods.PhpStack.PeekTypeOptional);
			else
				il.Emit(OpCodes.Call, Methods.PhpStack.PeekType);
		}
Example #8
0
		/// <summary>
		/// Emits code that loads the value from this storage place.
		/// </summary>
		/// <param name="il">The <see cref="ILEmitter"/> to emit the code to.</param>
		public void EmitLoad(ILEmitter il)
		{
			switch (holder)
			{
				case PlaceHolder.Local: il.Ldloc(index); break;
				case PlaceHolder.Argument: il.Ldarg(index); break;
				case PlaceHolder.None: il.LdcI4(index); break;
			}
		}
Example #9
0
        /// <summary>
        /// Emits load of default value assuming given method fails.
        /// </summary>
        /// <param name="il">ILEmitter.</param>
        /// <param name="method">Method which default return value have to be loaded.</param>
        /// <returns></returns>
        public static PhpTypeCode EmitLoadDefault(ILEmitter/*!*/il, MethodInfo/*!*/method)
        {
            if (method.ReturnType == Types.Bool[0] || method.ReturnTypeCustomAttributes.IsDefined(typeof(CastToFalseAttribute), false))
            {
                il.LoadBool(false);
                return PhpTypeCode.Boolean;
            }

            if (method.ReturnType == Types.Int[0])
            {
                il.LdcI4(0);
                return PhpTypeCode.Integer;
            }

            return PhpTypeCode.Void;
        }
Example #10
0
		public static object EmitReferencePeekUnchecked(ILEmitter/*!*/ il, int index, object/*!*/ stackPlace)
		{
			Debug.Assert(il != null && stackPlace != null);

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

			return typeof(PhpReference);
		}
Example #11
0
		public static object EmitValuePeek(ILEmitter/*!*/ il, int index, object/*!*/ stackPlace)
		{
			Debug.Assert(il != null && stackPlace != null);

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

			return typeof(object);
		}