public static int InsertInstructions(this MethodDefinition method, ILEmitter weakHandler, int insertPoint)
 {
     foreach (var i in weakHandler.Emit())
     {
         method.Body.Instructions.Insert(insertPoint, i);
         ++insertPoint;
     }
     return insertPoint;
 }
Exemplo n.º 2
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));
        }
Exemplo n.º 3
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));
        }
Exemplo n.º 4
0
        /// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
        internal override PhpTypeCode Emit(CodeGenerator codeGenerator)
        {
            Debug.Assert(access == AccessType.Read || access == AccessType.None);
            ILEmitter il = codeGenerator.IL;

            // count integer and string keys:
            int int_count    = 0;
            int string_count = 0;

            DetermineCapacities(out int_count, out string_count);

            // array = new PhpArray(<int_count>, <string_count>);
            il.Emit(OpCodes.Ldc_I4, int_count);
            il.Emit(OpCodes.Ldc_I4, string_count);
            il.Emit(OpCodes.Newobj, Constructors.PhpArray.Int32_Int32);

            if (codeGenerator.Context.Config.Compiler.Debug)
            {
                il.Emit(OpCodes.Nop);
                il.Emit(OpCodes.Nop);
                il.Emit(OpCodes.Nop);
            }

            foreach (Item item in items)
            {
                // CALL array.SetArrayItemRef(z, p);
                // CALL array.SetArrayItem(x, PhpVariable.Copy(y, CopyReason.Assigned));
                // CALL array.SetArrayItem(PhpVariable.Copy(x, CopyReason.Assigned))
                // CALL array.AddToEnd(x)

                il.Emit(OpCodes.Dup);
                PhpTypeCode index_type_code = item.EmitIndex(codeGenerator);
                item.EmitValue(codeGenerator);
                codeGenerator.EmitSetArrayItem(index_type_code, item.Index, item is RefItem, true);
            }

            switch (this.access)
            {
            case AccessType.Read:
                // keep array on the stack
                return(PhpTypeCode.PhpArray);

            case AccessType.None:
                // pop array from the stack
                il.Emit(OpCodes.Pop);
                return(PhpTypeCode.Void);
            }

            Debug.Fail();
            return(PhpTypeCode.Invalid);
        }
Exemplo n.º 5
0
            internal override void Emit(WhileStmt node, CodeGenerator codeGenerator)
            {
                Statistics.AST.AddNode("Loop.While");

                ILEmitter il         = codeGenerator.IL;
                Label     cond_label = il.DefineLabel();
                Label     exit_label = il.DefineLabel();
                Label     stat_label = il.DefineLabel();

                codeGenerator.BranchingStack.BeginLoop(cond_label, exit_label, codeGenerator.ExceptionBlockNestingLevel);

                if (node.LoopType == WhileStmt.Type.While)
                {
                    il.Emit(OpCodes.Br, cond_label);
                }

                // body:
                il.MarkLabel(stat_label);
                node.Body.Emit(codeGenerator);

                // marks a sequence point containing condition:
                codeGenerator.MarkSequencePoint(node.CondExpr);

                // condition:
                il.MarkLabel(cond_label);

                // bounded loop:
                if (node.CondExpr != null)
                {
                    // IF (<(bool) condition>) GOTO stat;
                    codeGenerator.EmitConversion(node.CondExpr, PhpTypeCode.Boolean);
                    il.Emit(OpCodes.Brtrue, stat_label);
                }

                il.MarkLabel(exit_label);
                codeGenerator.BranchingStack.EndLoop();

                il.ForgetLabel(cond_label);
                il.ForgetLabel(exit_label);
                il.ForgetLabel(stat_label);
            }
Exemplo n.º 6
0
        /// <summary>
        /// Emit the PhpType finalizer. The finalizer is emitted only if there is __destruct() function
        /// and there is no finalizer in any base class already. The finalizer calls this.Dispose() which
        /// calls __destruct() function directly.
        /// </summary>
        /// <param name="phpType"></param>
        private static void EmitFinalizer(PhpType /*!*/ phpType)
        {
            // only if __destruct was now defined in some base class, no need to override existing definition on Finalize
            DRoutine     basedestruct;
            DRoutineDesc destruct;

            if ((destruct = phpType.TypeDesc.GetMethod(DObject.SpecialMethodNames.Destruct)) != null && (phpType.Base == null ||
                                                                                                         phpType.Base.GetMethod(DObject.SpecialMethodNames.Destruct, phpType, out basedestruct) == GetMemberResult.NotFound))
            {
                MethodBuilder finalizer_builder = phpType.RealTypeBuilder.DefineMethod("Finalize", MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Family, typeof(void), Type.EmptyTypes);

                ILEmitter dil = new ILEmitter(finalizer_builder);

                // exact Finalize() method pattern follows:

                // try
                dil.BeginExceptionBlock();

                // this.Dispose(false)
                dil.Emit(OpCodes.Ldarg_0);
                dil.Emit(OpCodes.Ldc_I4_0);
                dil.Emit(OpCodes.Callvirt, PHP.Core.Emit.Methods.DObject_Dispose);

                // finally
                dil.BeginFinallyBlock();

                // Object.Finalize()
                dil.Emit(OpCodes.Ldarg_0);
                dil.Emit(OpCodes.Call, PHP.Core.Emit.Methods.Object_Finalize);

                dil.EndExceptionBlock();

                dil.Emit(OpCodes.Ret);
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Define new instance of CallSite&lt;<paramref name="delegateType"/>&gt; and initialize it with specified binder.
        /// </summary>
        /// <param name="bodyEmitter"><see cref="ILEmitter"/> of the body that is using this call site. This method may emit initialization of the call site into this <paramref name="bodyEmitter"/>.</param>
        /// <param name="userFriendlyName">User friendly name used as name for the CallSite field.</param>
        /// <param name="delegateType">CallSite type argument.</param>
        /// <param name="binderInstanceEmitter">Function used to emit initialization of the binder from within the call sites container .cctor.</param>
        /// <returns>The <see cref="FieldInfo"/> containing the instance of the created CallSite.</returns>
        public FieldInfo /*!*/ DefineCallSite(ILEmitter /*!*/ bodyEmitter, string /*!*/ userFriendlyName, Type /*!*/ delegateType, Action <ILEmitter> /*!*/ binderInstanceEmitter)
        {
            Debug.Assert(userFriendlyName != null && delegateType != null && binderInstanceEmitter != null);

            userFriendlyName += ("'" + (callSitesCount++));

            // call site type
            var callSiteType = Types.CallSiteGeneric[0].MakeGenericType(delegateType);

            // define the field:
            // public static readonly CallSite<delegateType> <userFriendlyName>
            var attrs = FieldAttributes.Static | FieldAttributes.InitOnly | ((staticCtorEmitter == null) ? FieldAttributes.Private : FieldAttributes.Assembly);
            var field = this.DefineField(PluginHandler.ConvertCallSiteName(userFriendlyName), callSiteType, attrs);

            if (staticCtorEmitter == null) // => this.classContext != null
            {
                // emit initialization of the call site just in the body of current method (as it is in C#, we need current generic arguments):
                Debug.Assert(this.classContext != null);

                // check if the call site if not null, otherwise initialize it first:

                // if (<field> == null) <InitializeCallSite>;
                Label ifend = bodyEmitter.DefineLabel();
                bodyEmitter.Emit(OpCodes.Ldsfld, field);
                bodyEmitter.Emit(OpCodes.Brtrue, ifend);

                // init the field:
                InitializeCallSite(bodyEmitter, callSiteType, field, binderInstanceEmitter);

                bodyEmitter.MarkLabel(ifend);
            }
            else
            {
                // init the field in .cctor:
                InitializeCallSite(staticCtorEmitter, callSiteType, field, binderInstanceEmitter);
            }

            //
            return(field);
        }
Exemplo n.º 8
0
        internal override void EmitStoreAssign(CodeGenerator codeGenerator)
        {
            ILEmitter il = codeGenerator.IL;

            if (varName.IsThisVariableName)
            {
                // emit error throwing code
                il.Emit(OpCodes.Pop);
                codeGenerator.EmitPhpException(Methods.PhpException.CannotReassignThis);
            }
            else if (codeGenerator.VariableIsAutoGlobal(varName))
            {
                // Check if the variable is auto-global
                codeGenerator.EmitAutoGlobalStoreAssign();
            }
            else if (codeGenerator.OptimizedLocals)
            {
                // Template:
                //		"WRITE($x,value);"
                //		**** // if specified variable is of type PhpReference
                //		ldloc local
                //		**** // Otherwise do nothing

                VariablesTable.Entry entry = codeGenerator.CurrentVariablesTable[varName];

                if (entry.IsPhpReference)
                {
                    il.Emit(OpCodes.Stfld, Fields.PhpReference_Value);
                }
                else
                {
                    entry.Variable.EmitStore(il);
                }
            }
            else
            {
                // CALL Operators.SetVariable(STACK:table,STACK:name,STACK:value);
                il.Emit(OpCodes.Call, Methods.Operators.SetVariable);
            }
        }
Exemplo n.º 9
0
            /// <summary>
            /// Emit lambda function that returns values used for sorting and
            /// call to OrderedSequence.OrderBy method (with current LINQ context as
            /// first and generated lambda as a second parameter)
            /// </summary>
            public override PhpTypeCode Emit(LinqBuilder codeGenerator)
            {
                ILEmitter il = codeGenerator.IL;

                // NEW Func[object,object](<linq context>, <&lambda>);
                codeGenerator.EmitLoadLinqContext();
                il.Emit(OpCodes.Ldftn, codeGenerator.EmitLambda(string.Format("<Comparer_{0}>",
                                                                              codeGenerator.GetNextComparerNum()), valueVar, expression, PhpTypeCode.Object));
                il.Emit(OpCodes.Newobj, LinqExterns.Func2_object_object_ctor);

                // LOAD Select[object,object](<source>, <delegate>);
                if (isThenBy)
                {
                    il.Emit(OpCodes.Call, ordering == Ordering.Descending ? LinqExterns.ThenByDescending : LinqExterns.ThenBy);
                }
                else
                {
                    il.Emit(OpCodes.Call, ordering == Ordering.Descending ? LinqExterns.OrderByDescending : LinqExterns.OrderBy);
                }

                return(base.Emit(codeGenerator));
            }
Exemplo n.º 10
0
        /// <summary>
        /// Emits dynamic inclusion.
        /// </summary>
        private PhpTypeCode EmitDynamicInclusion(CodeGenerator /*!*/ codeGenerator)
        {
            // do not generate dynamic auto inclusions:
            if (InclusionTypesEnum.IsAutoInclusion(inclusionType))
            {
                return(PhpTypeCode.Void);
            }

            ILEmitter il = codeGenerator.IL;

            // CALL context.DynamicInclude(<file name>,<relative includer source path>,variables,self,includer);
            codeGenerator.EmitLoadScriptContext();
            codeGenerator.EmitConversion(fileNameEx, PhpTypeCode.String);
            il.Emit(OpCodes.Ldstr, codeGenerator.SourceUnit.SourceFile.RelativePath.ToString());
            codeGenerator.EmitLoadRTVariablesTable();
            codeGenerator.EmitLoadSelf();
            codeGenerator.EmitLoadClassContext();
            il.LoadLiteral(inclusionType);
            il.Emit(OpCodes.Call, Methods.ScriptContext.DynamicInclude);

            return(PhpTypeCode.Object);
        }
Exemplo n.º 11
0
        /// <summary>
        /// Stores a value on the top of the stack to a specified variable.
        /// </summary>
        internal void StoreLocalAssign(CodeGenerator codeGenerator, VariablesTable.Entry variable, LocalBuilder variableName)
        {
            ILEmitter il = codeGenerator.IL;

            Debug.Assert(variable == null ^ variableName == null);
            LocalBuilder temp;

            if (variable != null)
            {
                if (variable.IsPhpReference)
                {
                    // temp = STACK
                    temp = il.GetTemporaryLocal(Types.Object[0], true);
                    il.Stloc(temp);

                    // <variable>.value = temp;
                    variable.Variable.EmitLoad(il);
                    il.Ldloc(temp);
                    il.Emit(OpCodes.Stfld, Fields.PhpReference_Value);
                }
                else
                {
                    variable.Variable.EmitStore(il);
                }
            }
            else
            {
                // temp = STACK
                temp = il.GetTemporaryLocal(Types.Object[0], true);
                il.Stloc(temp);

                // CALL Operators.SetVariable(<local variables table>,<name>,temp);
                codeGenerator.EmitLoadScriptContext();
                codeGenerator.EmitLoadRTVariablesTable();
                il.Ldloc(variableName);
                il.Ldloc(temp);
                il.Emit(OpCodes.Call, Methods.Operators.SetVariable);
            }
        }
Exemplo n.º 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);
            }
        }
Exemplo n.º 13
0
        /// <summary>
        /// Emits IL instructions that transfer the control to the target label for <B>break</B> statement
        /// having parameter that cannot be evaluated at compile time.
        /// </summary>
        /// <remarks>This function is used to generate code for <B>break v;</B> where <i>v</i> is a variable.</remarks>
        public void EmitBreakRuntime()
        {
            int       i;
            ILEmitter il = codeGenerator.IL;

            Label[] jumpTable = new Label[stack.Count + 1];
            Label   exitLabel = il.DefineLabel();

            Debug.Assert(stack.Count != 0);

            for (i = 0; i <= stack.Count; i++)
            {
                jumpTable[i] = il.DefineLabel();
            }

            // The value according to we switch is already present on the evaluation stack
            LocalBuilder break_level_count = il.DeclareLocal(typeof(Int32));

            il.Emit(OpCodes.Dup);
            il.Stloc(break_level_count);
            il.Emit(OpCodes.Switch, jumpTable);

            // Default case
            il.Ldloc(break_level_count);
            codeGenerator.EmitPhpException(Methods.PhpException.InvalidBreakLevelCount);
            il.Emit(OpCodes.Br, exitLabel);

            il.MarkLabel(jumpTable[0]);
            EmitBranchToExit((StackItem)stack[stack.Count - 1]);

            for (i = 1; i <= stack.Count; i++)
            {
                il.MarkLabel(jumpTable[i]);
                EmitBranchToExit((StackItem)stack[stack.Count - i]);
            }

            il.MarkLabel(exitLabel);
        }
Exemplo n.º 14
0
        /// <summary>
        /// Emits code that loads type descriptors for all generic arguments and a call to
        /// <see cref="Operators.MakeGenericTypeInstantiation"/>.
        /// </summary>
        internal void EmitMakeGenericInstantiation(CodeGenerator /*!*/ codeGenerator, ResolveTypeFlags flags)
        {
            ILEmitter il = codeGenerator.IL;

            il.EmitOverloadedArgs(Types.DTypeDesc[0], genericParams.Count, Methods.Operators.MakeGenericTypeInstantiation.ExplicitOverloads, delegate(ILEmitter eil, int i)
            {
                genericParams[i].EmitLoadTypeDesc(codeGenerator, flags);
            });

            if (genericParams.Count > 0)
            {
                il.Emit(OpCodes.Call, Methods.Operators.MakeGenericTypeInstantiation.Overload(genericParams.Count));
            }
        }
Exemplo n.º 15
0
        public void DefineContextType()
        {
            linqContextBuilder = cg.IL.TypeBuilder.DefineNestedType(ContextTypeName + cg.IL.GetNextUniqueIndex(),
                                                                    TypeAttributes.Class | TypeAttributes.NestedPrivate | TypeAttributes.Sealed,
                                                                    typeof(PHP.Core.LinqContext), null);

            // .ctor:

            ConstructorBuilder ctor = linqContextBuilder.DefineConstructor(MethodAttributes.Assembly,
                                                                           CallingConventions.HasThis, Types.LinqContextArgs);

            ILEmitter il = new ILEmitter(ctor);

            il.Ldarg(0);
            il.Ldarg(1);
            il.Ldarg(2);
            il.Ldarg(3);
            il.Ldarg(4);
            il.Emit(OpCodes.Call, Constructors.LinqContext);
            il.Emit(OpCodes.Ret);

            linqContextCtor = ctor;
        }
Exemplo n.º 16
0
        public void EmitNewLinqContext()
        {
            ILEmitter il = cg.IL;

            linqContextLocal = il.DeclareLocal(linqContextBuilder);

            // linq_context = NEW <linq context>(<this>, <variables>, <script context>, <type desc>)
            cg.SelfPlace.EmitLoad(il);
            cg.RTVariablesTablePlace.EmitLoad(il);
            cg.ScriptContextPlace.EmitLoad(il);
            cg.TypeContextPlace.EmitLoad(il);
            il.Emit(OpCodes.Newobj, linqContextCtor);
            il.Stloc(linqContextLocal);
        }
Exemplo n.º 17
0
            /// <summary>
            /// Emits the catch-block.
            /// </summary>
            /// <param name="node">Instance.</param>
            /// <param name="codeGenerator">A code generator.</param>
            /// <param name="exceptionLocal">A local variable containing an instance of <see cref="Library.SPL.Exception"/>.</param>
            /// <param name="endLabel">A label in IL stream where the processing of the try-catch blocks ends.</param>
            /// <param name="nextCatchLabel">A label in IL stream where the next catch block processing begins.</param>
            public void Emit(CatchItem /*!*/ node, CodeGenerator /*!*/ codeGenerator,
                             LocalBuilder /*!*/ exceptionLocal,
                             Label endLabel, Label nextCatchLabel)
            {
                ILEmitter il = codeGenerator.IL;

                codeGenerator.MarkSequencePoint(node.Variable);

                // IF !InstanceOf(<class name>) GOTO next_catch;
                il.Ldloc(exceptionLocal);
                resolvedType.EmitInstanceOf(codeGenerator, null);
                il.Emit(OpCodes.Brfalse, nextCatchLabel);

                // variable = exception;
                node.Variable.Emit(codeGenerator);
                il.Ldloc(exceptionLocal);
                SimpleVarUseHelper.EmitAssign(node.Variable, codeGenerator);

                node.Statements.Emit(codeGenerator);

                // LEAVE end;
                il.Emit(OpCodes.Leave, endLabel);
            }
Exemplo n.º 18
0
        internal override void EmitStoreRefAssign(CodeGenerator codeGenerator)
        {
            ILEmitter il = codeGenerator.IL;

            if (codeGenerator.OptimizedLocals)
            {
                // For IndirectVarUse emit switch over all variables
                EmitSwitch(codeGenerator, new SwitchMethod(StoreLocalRefAssign));
            }
            else
            {
                // Operators.SetVariable( <FROM EmitStoreRefPrepare> )
                il.Emit(OpCodes.Call, Methods.Operators.SetVariableRef);
            }
        }
Exemplo n.º 19
0
        internal override PhpTypeCode Emit(CodeGenerator /*!*/ codeGenerator)
        {
            ILEmitter il    = codeGenerator.IL;
            int       indir = this.count - 2;

            // cast object to correct tuple type:
            //   Tuple<Tuple<...Tuple<object, object>, .. >, object>, object>
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Castclass, LinqExterns.GetTupleInfo(indir).Type);

            // Find value at specified index (tup.First.First....First/Second);
            int timesFirst = index - ((index == count - 1) ? 1 : 0);

            for (int i = 0; i < timesFirst; i++)
            {
                il.Emit(OpCodes.Call, LinqExterns.GetTupleInfo(indir - i).SecondGetter);
            }

            // The last value is stored in Second, other values are stored in First
            il.Emit(OpCodes.Call, (index == count - 1)?
                    LinqExterns.GetTupleInfo(indir - timesFirst).SecondGetter:
                    LinqExterns.GetTupleInfo(indir - timesFirst).FirstGetter);
            return(PhpTypeCode.Object);
        }
Exemplo n.º 20
0
        internal override void EmitStoreAssign(CodeGenerator codeGenerator)
        {
            ILEmitter il = codeGenerator.IL;

            if (codeGenerator.OptimizedLocals)
            {
                // For IndirectVarUse emit switch over all variables
                EmitSwitch(codeGenerator, new SwitchMethod(StoreLocalAssign));
            }
            else
            {
                // Template:
                //		void Operators.SetVariable(table, "x", PhpVariable.Copy(Operators.getValue(table, "x"), CopyReason.Assigned));
                il.Emit(OpCodes.Call, Methods.Operators.SetVariable);
            }
        }
Exemplo n.º 21
0
        /// <summary>
        /// Emits init field helpers (<c>__lastContext</c> field, <c>&lt;InitializeInstanceFields&gt;</c>
        /// method and <c>__InitializeStaticFields</c> into a class.
        /// </summary>
        internal static void EmitInitFieldHelpers(PhpType phpType)
        {
            //
            // <InitializeInstanceFields>
            //

            // <InitializeInstanceFields> method - will contain instance field initialization
            phpType.Builder.InstanceFieldInit = phpType.RealTypeBuilder.DefineMethod(
                InstanceFieldInitMethodName,
#if SILVERLIGHT
                MethodAttributes.Public | MethodAttributes.HideBySig,
#else
                MethodAttributes.Private | MethodAttributes.HideBySig,
#endif
                CallingConventions.Standard,
                Types.Void,
                Types.ScriptContext);
            phpType.Builder.InstanceFieldInitEmitter = new ILEmitter(phpType.Builder.InstanceFieldInit);

            //
            // <InitializeStaticFields>
            //

            // <InitializeStaticFields> method has already been defined during the analysis phase - will contain (thread)
            // static field initialization
            ILEmitter cil = new ILEmitter(phpType.StaticFieldInitMethodBuilder);

            if (phpType.Builder.HasThreadStaticFields)
            {
                // __lastContext thread-static field - will contain the last SC that inited static fields for this thread
                FieldBuilder last_context = phpType.RealTypeBuilder.DefineField(
                    "<lastScriptContext>",
                    Types.ScriptContext[0],
                    FieldAttributes.Private | FieldAttributes.Static);

                // SILVERLIGHT: Not sure what this does & what would be the right behavior...
#if !SILVERLIGHT
                last_context.SetCustomAttribute(AttributeBuilders.ThreadStatic);
#endif
                //
                Label init_needed_label = cil.DefineLabel();
                // [ if (arg0 == __lastContext) ret ]
                cil.Emit(OpCodes.Ldarg_0);
                cil.Emit(OpCodes.Ldsfld, last_context);
                cil.Emit(OpCodes.Bne_Un_S, init_needed_label);
                cil.Emit(OpCodes.Ret);
                // [ __lastContext = arg0 ]
                cil.MarkLabel(init_needed_label);
                cil.Emit(OpCodes.Ldarg_0);
                cil.Emit(OpCodes.Stsfld, last_context);

                // the rest of the method is created when fields are emitted
            }
        }
Exemplo n.º 22
0
        /// <summary>
        /// Implements a <see cref="ISpecializationCacheArgs"/> interface in order to
        /// make the given <paramref name="typeBuilder"/> compatible with a
        /// <see cref="SpecializationCache{TLoader, TArgs, TDelegate}"/> instance.
        /// </summary>
        /// <param name="typeBuilder">The target type builder to use.</param>
        /// <param name="fields">The source fields used for implementation.</param>
        private static void ImplementSpecializationCacheArgs(
            TypeBuilder typeBuilder,
            FieldInfo[] fields)
        {
            var specializedType = typeof(SpecializedValue <>);
            var getArgMethod    = typeBuilder.DefineMethod(
                nameof(ISpecializationCacheArgs.GetSpecializedArg),
                MethodAttributes.Public | MethodAttributes.Virtual,
                typeof(object),
                new Type[] { typeof(int) });

            var emitter = new ILEmitter(getArgMethod.GetILGenerator());

            // Declare labels and emit jump table
            var labels = new ILLabel[fields.Length];

            for (int i = 0, e = fields.Length; i < e; ++i)
            {
                labels[i] = emitter.DeclareLabel();
            }
            emitter.Emit(OpCodes.Ldarg_1);
            emitter.EmitSwitch(labels);
            for (int i = 0, e = fields.Length; i < e; ++i)
            {
                var field = fields[i];
                emitter.MarkLabel(labels[i]);
                emitter.Emit(OpCodes.Ldarg_0);
                emitter.Emit(OpCodes.Ldfld, field);

                // Wrap in a specialized instance
                var fieldReturnType     = specializedType.MakeGenericType(field.FieldType);
                var instanceConstructor = fieldReturnType.GetConstructor(
                    new Type[]
                {
                    field.FieldType
                });
                emitter.EmitNewObject(instanceConstructor);

                emitter.Emit(OpCodes.Box, fieldReturnType);
                emitter.Emit(OpCodes.Ret);
            }

            // Return dummy argument
            emitter.Emit(OpCodes.Ldnull);
            emitter.Emit(OpCodes.Ret);
            emitter.Finish();

            typeBuilder.AddInterfaceImplementation(typeof(ISpecializationCacheArgs));
        }
Exemplo n.º 23
0
        /// <summary>
        /// Bake the container class if any. Close the call sites builder.
        /// </summary>
        public void Bake()
        {
            if (containerClass != null)
            {
                Debug.Assert(staticCtorEmitter != null);

                // finish static ctor:
                staticCtorEmitter.Emit(OpCodes.Ret);

                // bake the call sites container:
                containerClass.CreateType();

                // avoid of using the builders anymore:
                containerClass    = null;
                staticCtorEmitter = null;
            }
        }
Exemplo n.º 24
0
        internal override PhpTypeCode EmitGet(CodeGenerator /*!*/ codeGenerator, ConstructedType constructedType,
                                              bool runtimeVisibilityCheck, string fallbackName)
        {
            ILEmitter il = codeGenerator.IL;

            if (HasValue)
            {
                il.LoadLiteral(Value);
                return(PhpTypeCodeEnum.FromObject(Value));
            }
            else
            {
                Debug.Assert(realField != null);

                il.Emit(OpCodes.Ldsfld, DType.MakeConstructed(realField, constructedType));
                return(PhpTypeCodeEnum.FromType(realField.FieldType));
            }
        }
Exemplo n.º 25
0
        public ILEmitter Emit(ILEmitter il, LocalBuilder hash)
        {
            var arrayType = _variable.VariableType;

            il.Emit(_variable.Load(Arg.Input)) // load array
            .Stloc(arrayType, out var array)
            .Brtrue_S(Ldloc(array), out var begin)
            .Ldc_I4(0)
            .Br(out var end)
            .MarkLabel(begin);

            if (_configuration.IgnoreCollectionOrder)
            {
                il.EmitArraySorting(_hasCustomComparer, arrayType.GetElementType(), array);
            }

            return(_arrayHashEmitter.Emit(il, arrayType, array, hash).MarkLabel(end));
        }
Exemplo n.º 26
0
        internal override PhpTypeCode Emit(CodeGenerator /*!*/ codeGenerator)
        {
            // emit tuple value
            foreach (OrderingClause clause in OrderingItems)
            {
                clause.Expression.Emit(codeGenerator);
            }
            LastItem.Emit(codeGenerator);

            // emit tuple creation
            ILEmitter il = codeGenerator.IL;

            for (int indirection = 0; indirection < OrderingItems.Count; indirection++)
            {
                il.Emit(OpCodes.Newobj, LinqExterns.GetTupleInfo(indirection).Constructor);
            }
            return(PhpTypeCode.Object);
        }
Exemplo n.º 27
0
        internal override PhpTypeCode EmitIsset(CodeGenerator codeGenerator, bool empty)
        {
            // Template: "isset(x)"     x != null
            //				isset doesn't distinguish between the NULL and uninitialized variable
            //				a reference is dereferenced, i.e. isset tells us whether the referenced variable is set

            Debug.Assert(access == AccessType.Read);
            // Cases 1, 4, 5, 6, 9 never reached
            Debug.Assert(codeGenerator.ChainBuilder.IsMember == false);
            // Case 3 never reached
            Debug.Assert(codeGenerator.ChainBuilder.IsArrayItem == false);

            codeGenerator.ChainBuilder.QuietRead = true;

            // 2,7,8
            if (this.isMemberOf != null)
            {
                // 2: $b->a
                // 8: b[]->a
                codeGenerator.ChainBuilder.Create();
                codeGenerator.ChainBuilder.Begin();
                codeGenerator.ChainBuilder.QuietRead = true;
                EmitReadField(codeGenerator, false);
                codeGenerator.ChainBuilder.End();
                return(PhpTypeCode.Object);
            }
            // 7: $a
            // Check whether this variable is set
            //codeGenerator.EmitVariableIsset(this);
            ILEmitter il = codeGenerator.IL;

            if (varName.IsThisVariableName && codeGenerator.LocationStack.LocationType == LocationTypes.MethodDecl)
            {
                CompilerLocationStack.MethodDeclContext context = codeGenerator.LocationStack.PeekMethodDecl();
                if (!context.Method.IsStatic)
                {
                    // $this is always set in instance methods
                    il.Emit(OpCodes.Ldarg_0);
                    return(PhpTypeCode.Object);
                }
            }
            this.EmitLoad(codeGenerator);
            return(PhpTypeCode.Object);
        }
Exemplo n.º 28
0
            /// <summary>
            /// Emits code that loads type descriptors for all generic arguments and a call to
            /// <see cref="Operators.MakeGenericTypeInstantiation"/>.
            /// </summary>
            internal void EmitMakeGenericInstantiation(TypeRef node, CodeGenerator /*!*/ codeGenerator, ResolveTypeFlags flags)
            {
                if (node.GenericParams == null || node.GenericParams.Count == 0)
                {
                    return;
                }

                ILEmitter il = codeGenerator.IL;

                il.EmitOverloadedArgs(Types.DTypeDesc[0], node.GenericParams.Count, Methods.Operators.MakeGenericTypeInstantiation.ExplicitOverloads, delegate(ILEmitter eil, int i)
                {
                    TypeRefHelper.EmitLoadTypeDesc(node.GenericParams[i], codeGenerator, flags);
                });

                if (node.GenericParams.Count > 0)
                {
                    il.Emit(OpCodes.Call, Methods.Operators.MakeGenericTypeInstantiation.Overload(node.GenericParams.Count));
                }
            }
Exemplo n.º 29
0
        internal override void EmitLoadRef(CodeGenerator codeGenerator)
        {
            ILEmitter il = codeGenerator.IL;

            if (codeGenerator.OptimizedLocals)
            {
                // For IndirectVarUse emit switch over all variables.
                EmitSwitch(codeGenerator, new SwitchMethod(LoadLocalRef));
            }
            else
            {
                // Template:
                //		PhpReference Operators.GetVariableRef(IDictionary table, string name) //returns variable value; variable is of type PhpReference
                codeGenerator.EmitLoadScriptContext();
                codeGenerator.EmitLoadRTVariablesTable();
                EmitName(codeGenerator);
                il.Emit(OpCodes.Call, Methods.Operators.GetVariableRef);
            }
        }
Exemplo n.º 30
0
        /// <summary>
        /// Loads a specified reference local variable.
        /// </summary>
        internal void LoadLocalRef(CodeGenerator codeGenerator, VariablesTable.Entry variable, LocalBuilder variableName)
        {
            ILEmitter il = codeGenerator.IL;

            Debug.Assert(variable == null ^ variableName == null);

            if (variable != null)
            {
                Debug.Assert(variable.IsPhpReference);
                variable.Variable.EmitLoad(il);
            }
            else
            {
                codeGenerator.EmitLoadScriptContext();
                codeGenerator.EmitLoadRTVariablesTable();
                il.Ldloc(variableName);
                il.Emit(OpCodes.Call, Methods.Operators.GetVariableRef);
            }
        }
        public ILEmitter Emit(ILEmitter il, LocalBuilder hash)
        {
            il.Emit(_variable.Load(Arg.Input))
            .Stloc(_variable.VariableType, out var enumerable)
            .DefineLabel(out var end);

            if (!_variable.VariableType.IsValueType)
            {
                il.Brtrue_S(Ldloc(enumerable), out var begin)
                .Ldc_I4(0)
                .Br(end)
                .MarkLabel(begin);
            }

            if (_configuration.Get(_variable.OwnerType).IgnoreCollectionOrder)
            {
                return(EmitHashAsSortedArray(il, enumerable, hash).MarkLabel(end));
            }

            il.CallMethod(_getEnumeratorMethod, LoadCaller(enumerable))
            .Stloc(_enumeratorType, out var enumerator)
            .DefineLabel(out var loopStart);

            if (!_enumeratorType.IsValueType)
            {
                il.Brtrue_S(Ldloc(enumerator), loopStart)
                .Ldc_I4(0)
                .Br(end);
            }

            // todo: 1. think how to use try/finally block
            // the problem now with the inner `return` statements, it has to be `leave` instruction
            //il.BeginExceptionBlock();

            Loop(il, enumerator, loopStart, hash);

            //il.BeginFinallyBlock();
            EmitDisposeEnumerator(il, enumerator);

            //il.EndExceptionBlock();

            return(il.Ldloc(hash).MarkLabel(end));
        }