public LinqBuilder(CodeGenerator/*!*/ cg) { this.cg = cg; IPlace this_place = new IndexedPlace(PlaceHolder.Argument, 0); this.rtVariablesPlace = new Place(this_place, Fields.LinqContext_variables); this.scriptContextPlace = new Place(this_place, Fields.LinqContext_context); this.classContextPlace = new Place(this_place, Fields.LinqContext_typeHandle); this.selfPlace = new Place(this_place, Fields.LinqContext_outerType); }
public LinqBuilder(CodeGenerator /*!*/ cg) { this.cg = cg; IPlace this_place = new IndexedPlace(PlaceHolder.Argument, 0); this.rtVariablesPlace = new Place(this_place, Fields.LinqContext_variables); this.scriptContextPlace = new Place(this_place, Fields.LinqContext_context); this.classContextPlace = new Place(this_place, Fields.LinqContext_typeHandle); this.selfPlace = new Place(this_place, Fields.LinqContext_outerType); }
internal void EmitHelpers() { CompilationUnit unit = this.CompilationUnit; ILEmitter il = new ILEmitter(DeclareHelperBuilder); IndexedPlace script_context_place = new IndexedPlace(PlaceHolder.Argument, 0); foreach (PhpFunction function in unit.GetDeclaredFunctions()) { if (function.IsDefinite) { CodeGenerator.EmitDeclareFunction(il, script_context_place, function); } } foreach (PhpType type in unit.GetDeclaredTypes()) { if (type.IsDefinite) { // CALL <context>.DeclareType(<type desc>, <name>); type.EmitAutoDeclareOnScriptContext(il, script_context_place); } else if (!type.IsComplete) { if (type.IncompleteClassDeclareMethodInfo != null) { // check whether base class is known at this point of execution, // if so, declare this incomplete class immediately. As PHP does. type.EmitDeclareIncompleteOnScriptContext(il, script_context_place); } } } foreach (GlobalConstant constant in unit.GetDeclaredConstants()) { if (constant.IsDefinite) { var field = constant.RealField; Debug.Assert(field != null); Debug.Assert(field.IsStatic); // CALL <context>.DeclareConstant(<name>, <value>); script_context_place.EmitLoad(il); il.Emit(OpCodes.Ldstr, constant.FullName); il.LoadLiteralBox(constant.Value); //il.Emit(OpCodes.Ldsfld, field); // const field cannot be referenced in IL il.Emit(OpCodes.Call, Methods.ScriptContext.DeclareConstant); } } il.Emit(OpCodes.Ret); }
/// <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(); }
/// <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(); } }
protected virtual SetterDelegate/*!*/ GenerateSetterStub() { if (Member is ClrEvent) return new SetterDelegate(EventSetter); #if SILVERLIGHT DynamicMethod stub = new DynamicMethod("<^SetterStub>", Types.Void, Types.Object_Object); /*DynamicMethod stub = new DynamicMethod("<^SetterStub>", PhpFunctionUtils.DynamicStubAttributes, CallingConventions.Standard, Types.Void, Types.Object_Object, this.declaringType.RealType, true);*/ #else DynamicMethod stub = new DynamicMethod("<^SetterStub>", PhpFunctionUtils.DynamicStubAttributes, CallingConventions.Standard, Types.Void, Types.Object_Object, this.declaringType.RealType, true); #endif #if DEBUG_DYNAMIC_STUBS // Debugging - save the generated stub to TEMP AssemblyName name = new AssemblyName("SetterStub_" + Property.FullName.ToString().Replace(':', '_')); AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Save, "C:\\Temp"); ModuleBuilder mb = ab.DefineDynamicModule(name.Name, name.Name + ".dll"); TypeBuilder tb = mb.DefineType("Stub"); MethodBuilder meb = tb.DefineMethod(DeclaringType.ToString() + "::" + Property.FullName, MethodAttributes.PrivateScope | MethodAttributes.Static, Types.Void, Types.Object_Object); ILEmitter il_dbg = new ILEmitter(meb); IndexedPlace instance2 = new IndexedPlace(PlaceHolder.Argument, 0); IndexedPlace stack = new IndexedPlace(PlaceHolder.Argument, 1); ClrProperty clr_property_dbg = Member as ClrProperty; if (clr_property_dbg != null && clr_property_dbg.HasSetter) { if (!clr_property_dbg.Setter.IsStatic) { il_dbg.Emit(OpCodes.Ldarg_0); if (declaringType.RealType.IsValueType) il_dbg.Emit(OpCodes.Unbox, declaringType.RealType); #if EMIT_VERIFIABLE_STUBS else il_dbg.Emit(OpCodes.Castclass, declaringType.RealType); #endif } il_dbg.Emit(OpCodes.Ldarg_1); EmitSetConversion(il_dbg, PhpTypeCode.Object, clr_property_dbg.Setter.GetParameters()[0].ParameterType); il_dbg.Emit(OpCodes.Call, clr_property_dbg.Setter); } il_dbg.Emit(OpCodes.Ret); tb.CreateType(); ab.Save("SetterStub_" + Property.FullName.ToString().Replace(':', '_') + ".dll"); #endif ILEmitter il = new ILEmitter(stub); ClrProperty clr_property = Member as ClrProperty; Type arg_type; if (clr_property != null) { // return error-throwing setter if the property is read-only if (!clr_property.HasSetter) return new SetterDelegate(MissingSetter); if (!clr_property.Setter.IsStatic) { ClrOverloadBuilder.EmitLoadInstance(il, IndexedPlace.ThisArg, declaringType.RealType); // il.Emit(OpCodes.Ldarg_0); // if (declaringType.RealType.IsValueType) // il.Emit(OpCodes.Unbox, declaringType.RealType); //#if EMIT_VERIFIABLE_STUBS // else // il.Emit(OpCodes.Castclass, declaringType.RealType); //#endif } il.Emit(OpCodes.Ldarg_1); arg_type = clr_property.Setter.GetParameters()[0].ParameterType; EmitSetConversion(il, PhpTypeCode.Object, arg_type); il.Emit(OpCodes.Call, clr_property.Setter); } else { ClrField clr_field = ClrField; // return error-throwing setter if the field is initonly if (clr_field.FieldInfo.IsInitOnly) return new SetterDelegate(MissingSetter); if (!clr_field.FieldInfo.IsStatic) { ClrOverloadBuilder.EmitLoadInstance(il, IndexedPlace.ThisArg, declaringType.RealType); //il.Emit(OpCodes.Ldarg_0); ////il.Emit(OpCodes.Castclass, this.declaringType.RealType); //if (declaringType.RealType.IsValueType) il.Emit(OpCodes.Unbox, declaringType.RealType); } il.Emit(OpCodes.Ldarg_1); arg_type = clr_field.FieldInfo.FieldType; EmitSetConversion(il, PhpTypeCode.Object, arg_type); il.Emit((clr_field.FieldInfo.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld), clr_field.FieldInfo); } il.Emit(OpCodes.Ret); return (SetterDelegate)stub.CreateDelegate(typeof(SetterDelegate)); }
/// <summary> /// Called when a <see cref="PHP.Core.AST.FieldDecl"/> AST node is visited during the emit phase. /// </summary> public void InitializeField(PhpField/*!*/ field, AST.Expression initVal) { ILEmitter cil; IPlace sc_place; if (field.IsStatic) { // (J) even overiding static field is created again in derivating type // there is no initialization taking place if the implementing CLI field does not live in current class //if (field.Overrides != null) return; if (field.IsAppStatic) { // app-static field initialization is emitted into the static ctor cil = field.DeclaringPhpType.Builder.StaticCtorEmitter; sc_place = new LazyLoadSCPlace(); } else { // thread-static field initialization is emitted into the __InitializeStaticFields method cil = new ILEmitter(field.DeclaringPhpType.StaticFieldInitMethodBuilder); sc_place = new IndexedPlace(PlaceHolder.Argument, ScriptBuilder.ArgContext); } } else { if (initVal == null && field.Implementor != field.DeclaringType) return; // instance field initialization is emitted into the <InitializeInstanceFields> method cil = field.DeclaringPhpType.Builder.InstanceFieldInitEmitter; sc_place = new IndexedPlace(PlaceHolder.Argument, FunctionBuilder.ArgContextInstance); cil.Ldarg(FunctionBuilder.ArgThis); } if (initVal != null) { // emit the expression evaluating code ILEmitter old_il = il; IPlace old_sc_place = ScriptContextPlace; try { // set il and SC-emitter appropriately il = cil; ScriptContextPlace = sc_place; EmitBoxing(initVal.Emit(this)); } finally { // restore the saved il and SC-emitter il = old_il; ScriptContextPlace = old_sc_place; } cil.Emit(OpCodes.Newobj, Constructors.PhpSmartReference.Object); } else cil.Emit(OpCodes.Newobj, Constructors.PhpSmartReference.Void); // store it in the field Debug.Assert(field.IsStatic == field.RealField.IsStatic); cil.Emit(field.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, field.RealField); }
protected override RoutineDelegate GenerateArglessStub() { ClrMethod clr_method = ClrMethod; Debug.Assert(clr_method != null, "CLR method should be fully reflected"); #if DEBUG_METHOD_STUBS AssemblyName name = new AssemblyName("MethodStub_" + clr_method.ToString().Replace(':','_')); AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Save, "C:\\Temp"); ModuleBuilder mb = ab.DefineDynamicModule(name.Name, name.Name + ".dll"); TypeBuilder tb = mb.DefineType(clr_method.Name.ToString()); MethodBuilder mmb = tb.DefineMethod("<^MethodStub>", PhpFunctionUtils.DynamicStubAttributes, CallingConventions.Standard, Types.Object[0], Types.Object_PhpStack); ILEmitter tmpil = new ILEmitter(mmb); IndexedPlace tmpinstance = new IndexedPlace(PlaceHolder.Argument, 0); IndexedPlace tmpstack = new IndexedPlace(PlaceHolder.Argument, 1); clr_method.EmitArglessStub(tmpil, tmpstack, tmpinstance); tb.CreateType(); ab.Save(name.Name + ".dll"); #endif #if SILVERLIGHT DynamicMethod stub = new DynamicMethod("<^>." + clr_method.Name.Value, Types.Object[0], Types.Object_PhpStack); #else DynamicMethod stub = new DynamicMethod("<^>." + clr_method.Name.Value, PhpFunctionUtils.DynamicStubAttributes, CallingConventions.Standard, Types.Object[0], Types.Object_PhpStack, this.declaringType.RealType, true); #endif ILEmitter il = new ILEmitter(stub); IndexedPlace instance = new IndexedPlace(PlaceHolder.Argument, 0); IndexedPlace stack = new IndexedPlace(PlaceHolder.Argument, 1); clr_method.EmitArglessStub(il, stack, instance); // TODO: is it possible to drop the member? // the compiler may get activated: // member = null; this.arglessStubMethod = stub; return (RoutineDelegate)stub.CreateDelegate(typeof(RoutineDelegate)); }
private static string CreateDynamicWrapperInternal(Type /*!*/ attr, Assembly /*!*/ assembly, string directory, string filename) #endif { string assembly_base_name; AssemblyBuilder assembly_builder; ModuleBuilder module_builder; TypeBuilder type_builder; MethodBuilder method_builder; IndexedPlace stack_place = new IndexedPlace(PlaceHolder.Argument, 1); // TODO: if function requires this reference, we need to pass it somehow IPlace self_ref = LiteralPlace.Null; IPlace script_context = new Place(stack_place, Fields.PhpStack_Context); IPlace rt_variables = new Place(stack_place, Fields.PhpStack_Variables); IPlace naming_context = new Place(stack_place, Fields.PhpStack_NamingContext); IPlace class_context = new Place(null, Fields.UnknownTypeDesc.Singleton); #if !SILVERLIGHT if (directory == null) { directory = Configuration.GetPathsNoLoad().DynamicWrappers; } Directory.CreateDirectory(directory); #endif Dictionary <string, List <PhpLibraryFunction.Overload> > functions = GetLibraryFunctions(attr, assembly); OverloadsBuilder overloads_builder = new OverloadsBuilder( false, stack_place, new OverloadsBuilder.ParameterLoader(PhpStackBuilder.EmitValuePeekUnchecked), new OverloadsBuilder.ParameterLoader(PhpStackBuilder.EmitReferencePeekUnchecked), new OverloadsBuilder.ParametersLoader(PhpStackBuilder.EmitPeekAllArguments)); #if SILVERLIGHT int commaIdx = assembly.FullName.IndexOf(','); assembly_base_name = commaIdx == -1 ? assembly.FullName : assembly.FullName.Substring(0, commaIdx); #else // securitycritical assembly_base_name = assembly.GetName().Name; #endif // appends assembly name with the suffix: AssemblyName name = new AssemblyName(); #if !SILVERLIGHT name.Version = assembly.GetName().Version; #endif name.Name = assembly_base_name + PhpLibraryModule.DynamicAssemblySuffix; #if SILVERLIGHT // defines assembly with storage in the dynamic code path: assembly_builder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run); // defines a module: module_builder = assembly_builder.DefineDynamicModule(PhpLibraryModule.DynamicWrapperModuleName); #else // defines assembly with storage in the dynamic code path: assembly_builder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Save, directory); // defines a module: module_builder = assembly_builder.DefineDynamicModule(PhpLibraryModule.DynamicWrapperModuleName, filename); #endif // defines type which will contain all mathods: type_builder = module_builder.DefineType(Namespaces.LibraryStubs + Type.Delimiter + assembly_base_name, DynamicTypeAttributes); try { foreach (KeyValuePair <string, List <PhpLibraryFunction.Overload> > function in functions) { // defines method: method_builder = type_builder.DefineMethod(function.Key, MethodAttributes.Public | MethodAttributes.Static, Types.Object[0], Types.Object_PhpStack); ILEmitter il = new ILEmitter(method_builder); overloads_builder.IL = il; overloads_builder.Aux = stack_place; overloads_builder.FunctionName = new Name(function.Key); // if run-time variables are needed by the overload sets a place where they are stored up: overloads_builder.EmitCallSwitch(self_ref, script_context, rt_variables, naming_context, class_context, function.Value); // RETURN: il.Emit(OpCodes.Ret); } } catch (Exception e) { Debug.WriteLine("A", e.ToString()); } type_builder.CreateType(); #if SILVERLIGHT return(assembly_builder); #else assembly_builder.Save(filename); return(Path.Combine(directory, filename)); #endif }
internal override PhpTypeCode EmitCall(CodeGenerator/*!*/ codeGenerator, string fallbackQualifiedName, CallSignature callSignature, IPlace instance, bool runtimeVisibilityCheck, int overloadIndex, DType type, Position position, AccessType access, bool callVirt) { #if DEBUG_DYNAMIC_STUBS MethodBuilder mb = codeGenerator.IL.TypeBuilder.DefineMethod(DeclaringType.FullName + "::" + FullName, MethodAttributes.PrivateScope | MethodAttributes.Static, typeof(object), Types.Object_PhpStack); ILEmitter il = new ILEmitter(mb); IndexedPlace instance2 = new IndexedPlace(PlaceHolder.Argument, 0); IndexedPlace stack = new IndexedPlace(PlaceHolder.Argument, 1); EmitArglessStub(il, stack, instance2); #endif Debug.Assert(instance == null || instance is ExpressionPlace || instance == IndexedPlace.ThisArg); Debug.Assert(fallbackQualifiedName == null); return codeGenerator.EmitRoutineOperatorCall(DeclaringType, ExpressionPlace.GetExpression(instance), this.FullName, null, null, callSignature, access); }
internal override PhpTypeCode EmitCall(CodeGenerator/*!*/ codeGenerator, string fallbackQualifiedName, CallSignature callSignature, IPlace instance, bool runtimeVisibilityCheck, int overloadIndex, DType type, Position position, AccessType access, bool callVirt) { Overload overload = overloads[overloadIndex]; Statistics.AST.AddLibraryFunctionCall(FullName, overload.ParamCount); if ((overload.Flags & OverloadFlags.NotSupported) != 0) { codeGenerator.IL.Emit(OpCodes.Ldstr, FullName); codeGenerator.IL.Emit(OpCodes.Call, Methods.PhpException.FunctionNotSupported_String); if (codeGenerator.Context.Config.Compiler.Debug) codeGenerator.IL.Emit(OpCodes.Nop); return OverloadsBuilder.EmitLoadDefault(codeGenerator.IL, overload.Method); } //IPlace return_value; IPlace script_context = null; IPlace opt_arg_count = null; IPlace self_ref = null; IPlace rt_variables = null; IPlace naming_context = null; IPlace class_context = null; // // captures eval info: if ((options & FunctionImplOptions.CaptureEvalInfo) != 0) { codeGenerator.EmitEvalInfoCapture(position.FirstLine, position.FirstColumn, false); } // current ScriptContext: if ((overload.Flags & OverloadFlags.NeedsScriptContext) != 0) { script_context = codeGenerator.ScriptContextPlace; } // number of optional arguments passed to a function (empty or a literal place): if ((overload.Flags & OverloadFlags.IsVararg) != 0) { opt_arg_count = new IndexedPlace(PlaceHolder.None, callSignature.Parameters.Count - overload.ParamCount); } // this reference? if ((options & FunctionImplOptions.NeedsThisReference) != 0) { self_ref = codeGenerator.SelfPlace; } // run-time variables table: if ((options & FunctionImplOptions.NeedsVariables) != 0) { rt_variables = codeGenerator.RTVariablesTablePlace; } // naming context if ((options & FunctionImplOptions.NeedsNamingContext) != 0) { naming_context = (codeGenerator.SourceUnit.NamingContextFieldBuilder != null) ? (IPlace)new Place(null, codeGenerator.SourceUnit.NamingContextFieldBuilder) : (IPlace)LiteralPlace.Null; } // call context if ((options & FunctionImplOptions.NeedsClassContext) != 0) { class_context = codeGenerator.TypeContextPlace; } OverloadsBuilder.ParameterLoader param_loader = new OverloadsBuilder.ParameterLoader(callSignature.EmitLibraryLoadArgument); OverloadsBuilder.ParametersLoader opt_param_loader = new OverloadsBuilder.ParametersLoader(callSignature.EmitLibraryLoadOptArguments); OverloadsBuilder builder = new OverloadsBuilder( codeGenerator.Context.Config.Compiler.Debug, null, // PHP stack is not used param_loader, // value parameter loader param_loader, // reference parameter loader opt_param_loader); // optional parameter array loader // setups builder: builder.Aux = codeGenerator; builder.IL = codeGenerator.IL; builder.FunctionName = name; // emits overload call: Type/*!*/return_type = builder.EmitOverloadCall(overload.Method, overload.RealParameters, overload.ParamCount, script_context, rt_variables, naming_context, class_context, opt_arg_count, self_ref, access == AccessType.None); //if (return_value != null) //{ // // loads value on the stack: // return_value.EmitLoad(codeGenerator.IL); // return PhpTypeCodeEnum.FromType(return_value.PlaceType); //} if (return_type != Types.Void) { return PhpTypeCodeEnum.FromType(return_type); } else { if (codeGenerator.Context.Config.Compiler.Debug) { codeGenerator.IL.Emit(OpCodes.Nop); } return PhpTypeCode.Void; } }
private static string CreateDynamicWrapperInternal(Type/*!*/ attr, Assembly/*!*/ assembly, string directory, string filename) #endif { string assembly_base_name; AssemblyBuilder assembly_builder; ModuleBuilder module_builder; TypeBuilder type_builder; MethodBuilder method_builder; IndexedPlace stack_place = new IndexedPlace(PlaceHolder.Argument, 1); // TODO: if function requires this reference, we need to pass it somehow IPlace self_ref = LiteralPlace.Null; IPlace script_context = new Place(stack_place, Fields.PhpStack_Context); IPlace rt_variables = new Place(stack_place, Fields.PhpStack_Variables); IPlace naming_context = new Place(stack_place, Fields.PhpStack_NamingContext); IPlace class_context = new Place(null, Fields.UnknownTypeDesc.Singleton); #if !SILVERLIGHT if (directory == null) directory = Configuration.GetPathsNoLoad().DynamicWrappers; Directory.CreateDirectory(directory); #endif Dictionary<string, List<PhpLibraryFunction.Overload>> functions = GetLibraryFunctions(attr, assembly); OverloadsBuilder overloads_builder = new OverloadsBuilder( false, stack_place, new OverloadsBuilder.ParameterLoader(PhpStackBuilder.EmitValuePeekUnchecked), new OverloadsBuilder.ParameterLoader(PhpStackBuilder.EmitReferencePeekUnchecked), new OverloadsBuilder.ParametersLoader(PhpStackBuilder.EmitPeekAllArguments)); #if SILVERLIGHT int commaIdx = assembly.FullName.IndexOf(','); assembly_base_name = commaIdx == -1 ? assembly.FullName : assembly.FullName.Substring(0, commaIdx); #else // securitycritical assembly_base_name = assembly.GetName().Name; #endif // appends assembly name with the suffix: AssemblyName name = new AssemblyName(); #if !SILVERLIGHT name.Version = assembly.GetName().Version; #endif name.Name = assembly_base_name + PhpLibraryModule.DynamicAssemblySuffix; #if SILVERLIGHT // defines assembly with storage in the dynamic code path: assembly_builder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run); // defines a module: module_builder = assembly_builder.DefineDynamicModule(PhpLibraryModule.DynamicWrapperModuleName); #else // defines assembly with storage in the dynamic code path: assembly_builder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Save, directory); // defines a module: module_builder = assembly_builder.DefineDynamicModule(PhpLibraryModule.DynamicWrapperModuleName, filename); #endif // defines type which will contain all mathods: type_builder = module_builder.DefineType(Namespaces.LibraryStubs + Type.Delimiter + assembly_base_name, DynamicTypeAttributes); try { foreach (KeyValuePair<string, List<PhpLibraryFunction.Overload>> function in functions) { // defines method: method_builder = type_builder.DefineMethod(function.Key, MethodAttributes.Public | MethodAttributes.Static, Types.Object[0], Types.Object_PhpStack); ILEmitter il = new ILEmitter(method_builder); overloads_builder.IL = il; overloads_builder.Aux = stack_place; overloads_builder.FunctionName = new Name(function.Key); // if run-time variables are needed by the overload sets a place where they are stored up: overloads_builder.EmitCallSwitch(self_ref, script_context, rt_variables, naming_context, class_context, function.Value); // RETURN: il.Emit(OpCodes.Ret); } } catch (Exception e) { Debug.WriteLine("A", e.ToString()); } type_builder.CreateType(); #if SILVERLIGHT return assembly_builder; #else assembly_builder.Save(filename); return Path.Combine(directory, filename); #endif }