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; } } }
/// <summary> /// Emit call of the instance/static method. This defines the call site and call it using given parameters. /// </summary> /// <param name="cg">Current code <see cref="CodeGenerator"/>.</param> /// <param name="returnType">Return type of the method call determined by current access of the method call.</param> /// <param name="targetExpr">The method call instance expression (the target) if it is an instance method call.</param> /// <param name="targetType">The target type if it is a static method call.</param> /// <param name="methodFullName">If known at compile time, the method name. Otherwise <c>null</c>.</param> /// <param name="methodNameExpr">If the <paramref name="methodFullName"/> is null, this will be the expression giving the method name in run time.</param> /// <param name="callSignature">The call signature of the method call.</param> /// <returns>The resulting value type code. This value will be pushed onto the evaluation stack.</returns> public PhpTypeCode EmitMethodCall( PHP.Core.CodeGenerator /*!*/ cg, Type returnType, Expression /*!*/ targetExpr, DType /*!*/ targetType, string methodFullName, Expression methodNameExpr, CallSignature callSignature) { Debug.Assert(methodFullName != null ^ methodNameExpr != null); // bool staticCall = (targetExpr == null); // we are going to emit static method call //bool methodNameIsKnown = (methodFullName != null); //bool classContextIsKnown = (this.classContextPlace != null); // // define the call site: // var delegateType = /*System.Linq.Expressions.Expression.*/ delegateBuilder.GetDelegateType( MethodCallDelegateTypeArgs( callSignature, staticCall ? Types.DObject[0] : Types.Object[0], MethodCallDelegateAdditionalArguments(staticCall, methodFullName != null, this.classContextPlace != null), returnType), 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("call_{0}", methodFullName ?? "$"), delegateType, (il) => { // <LOAD> Binder.{MethodCall|StaticMethodCall}( methodFullName, genericParamsCount, paramsCount, classContext, <returnType> ) if (methodFullName != null) { il.Emit(OpCodes.Ldstr, methodFullName); } else { il.Emit(OpCodes.Ldnull); } il.LdcI4(callSignature.GenericParams.Count); il.LdcI4(callSignature.Parameters.Count); if (this.classContextPlace != null) { this.classContextPlace.EmitLoad(il); } else { il.Emit(OpCodes.Ldsfld, Fields.UnknownTypeDesc.Singleton); } il.Emit(OpCodes.Ldtoken, returnType); il.Emit(OpCodes.Call, Methods.GetTypeFromHandle); il.Emit(OpCodes.Call, staticCall ? Methods.Binder.StaticMethodCall : Methods.Binder.MethodCall); }); // // call the CallSite: // // <field>.Target( <field>, <targetExpr|self>, <scriptContext>, <callSignature.EmitLoadOnEvalStack>, <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) { cg.EmitLoadSelf(); } else { EmitMethodTargetExpr(cg, targetExpr); } cg.EmitLoadScriptContext(); EmitMethodCallParameters(cg, callSignature); if (staticCall) { targetType.EmitLoadTypeDesc(cg, ResolveTypeFlags.UseAutoload | ResolveTypeFlags.ThrowErrors); } if (/*!classContextIsKnown*/ this.classContextPlace == null) { cg.EmitLoadClassContext(); } if (/*!methodNameIsKnown*/ methodFullName == null) { cg.EmitName(methodFullName /*null*/, methodNameExpr, true); } cg.MarkTransientSequencePoint(); cg.IL.Emit(OpCodes.Callvirt, delegateType.GetMethod("Invoke")); cg.MarkTransientSequencePoint(); // return(PhpTypeCodeEnum.FromType(returnType)); }