コード例 #1
0
            internal override void Emit(GlobalStmt node, CodeGenerator codeGenerator)
            {
                Statistics.AST.AddNode("GlobalStmt");

                foreach (SimpleVarUse variable in node.VarList)
                {
                    variable.Emit(codeGenerator);

                    // CALL Operators.GetItemRef(<string variable name>, ref context.AutoGlobals.GLOBALS);
                    SimpleVarUseHelper.EmitName(variable, codeGenerator);
                    codeGenerator.EmitAutoGlobalLoadAddress(new VariableName(VariableName.GlobalsName));
                    codeGenerator.IL.Emit(OpCodes.Call, Methods.Operators.GetItemRef.String);

                    SimpleVarUseHelper.EmitAssign(variable, codeGenerator);
                }
            }
コード例 #2
0
            private void EmitNodeWriteAssign(IndirectVarUse node, CodeGenerator codeGenerator)
            {
                ChainBuilder chain = codeGenerator.ChainBuilder;

                // Note that for cases 1,3,4,5,6,9 EmitAssign is never called!!!

                // 2,7,8
                if (chain.IsMember)
                {
                    // 2,8
                    if (chain.Exists)
                    {
                        // 8: b[]->$a
                        chain.EmitSetObjectField();
                    }
                    else
                    {
                        // 2: $b->a
                        Debug.Assert(node.IsMemberOf is SimpleVarUse || node.IsMemberOf is FunctionCall);
                        if (node.IsMemberOf is FunctionCall)
                        {
                            codeGenerator.ChainBuilder.LoadAddressOfFunctionReturnValue = true;
                        }

                        assignmentCallback(codeGenerator, PhpTypeCode.Object);

                        SimpleVarUse svu = node.IsMemberOf as SimpleVarUse;
                        if (svu != null)
                        {
                            SimpleVarUseHelper.EmitLoadAddress_StoreBack(svu, codeGenerator);
                        }
                        // else do nothing
                    }
                    chain.End();
                }
                else
                {
                    // 7: $a
                    //codeGenerator.EmitVariableStoreAssign(this);
                    this.EmitStoreAssign(node, codeGenerator);
                }
            }
コード例 #3
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);
            }
コード例 #4
0
            public void Emit(StaticVarDecl /*!*/ node, CodeGenerator codeGenerator)
            {
                ILEmitter il = codeGenerator.IL;
                string    id = codeGenerator.GetLocationId();

                if (id == null)
                {
                    // we are in global code -> just assign the iniVal to the variable
                    node.Variable.Emit(codeGenerator);

                    if (node.Initializer != null)
                    {
                        codeGenerator.EmitBoxing(node.Initializer.Emit(codeGenerator));
                        il.Emit(OpCodes.Newobj, Constructors.PhpReference_Object);
                    }
                    else
                    {
                        il.Emit(OpCodes.Newobj, Constructors.PhpReference_Void);
                    }

                    // continue ...
                }
                else
                {
                    // cache the integer index of static local variable to access its value fast from within the array

                    // unique static local variable string ID
                    id = String.Format("{0}${1}${2}", id, node.Variable.VarName, node.Span.Start);

                    // create static field for static local index: private static int <id>;
                    var type = codeGenerator.IL.TypeBuilder;
                    Debug.Assert(type != null, "The method does not have declaring type! (global code in pure mode?)");
                    var field_id = type.DefineField(id, Types.Int[0], System.Reflection.FieldAttributes.Private | System.Reflection.FieldAttributes.Static);

                    // we are in a function or method -> try to retrieve the local value from ScriptContext
                    node.Variable.Emit(codeGenerator);

                    // <context>.GetStaticLocal( <field> )
                    codeGenerator.EmitLoadScriptContext();                           // <context>
                    il.Emit(OpCodes.Ldsfld, field_id);                               // <field>
                    il.Emit(OpCodes.Callvirt, Methods.ScriptContext.GetStaticLocal); // GetStaticLocal
                    il.Emit(OpCodes.Dup);

                    // ?? <context>.AddStaticLocal( <field> != 0 ? <field> : ( <field> = ScriptContext.GetStaticLocalId(<id>) ), <initializer> )
                    if (true)
                    {
                        // if (GetStaticLocal(<field>) == null)
                        Label local_initialized = il.DefineLabel();
                        il.Emit(OpCodes.Brtrue /*not .S, initializer can emit really long code*/, local_initialized);

                        il.Emit(OpCodes.Pop);

                        // <field> != 0 ? <field> : ( <field> = ScriptContext.GetStaticLocalId(<id>) )
                        il.Emit(OpCodes.Ldsfld, field_id);         // <field>

                        if (true)
                        {
                            // if (<field> == 0)
                            Label id_initialized = il.DefineLabel();
                            il.Emit(OpCodes.Brtrue_S, id_initialized);

                            // <field> = GetStaticLocalId( <id> )
                            il.Emit(OpCodes.Ldstr, id);
                            il.Emit(OpCodes.Call, Methods.ScriptContext.GetStaticLocalId);
                            il.Emit(OpCodes.Stsfld, field_id);

                            il.MarkLabel(id_initialized);
                        }

                        // <context>.AddStaticLocal(<field>,<initialize>)
                        codeGenerator.EmitLoadScriptContext();  // <context>
                        il.Emit(OpCodes.Ldsfld, field_id);      // <field>
                        if (node.Initializer != null)
                        {
                            codeGenerator.EmitBoxing(node.Initializer.Emit(codeGenerator));                           // <initializer>
                        }
                        else
                        {
                            il.Emit(OpCodes.Ldnull);
                        }
                        il.Emit(OpCodes.Callvirt, Methods.ScriptContext.AddStaticLocal);    // AddStaticLocal

                        //
                        il.MarkLabel(local_initialized);
                    }

                    // continue ...
                }

                // stores value from top of the stack to the variable:
                SimpleVarUseHelper.EmitAssign(node.Variable, codeGenerator);
            }
コード例 #5
0
            internal override PhpTypeCode EmitAssign(ItemUse node, CodeGenerator codeGenerator)
            {
                var         chain = codeGenerator.ChainBuilder;
                PhpTypeCode result;

                switch (access)
                {
                case AccessType.WriteAndReadRef:
                case AccessType.WriteAndReadUnknown:
                case AccessType.ReadAndWrite:
                case AccessType.ReadAndWriteAndReadRef:
                case AccessType.ReadAndWriteAndReadUnknown:
                case AccessType.Write:
                case AccessType.WriteRef:
                {
                    bool reference = access == AccessType.WriteRef;

                    // Note that some work was done in Emit() !
                    // In cases 3, 4, 5 EmitAssign is not called

                    if (node.IsMemberOf != null ||
                        (node.IsMemberOf == null && (node.Array is DirectStFldUse || node.Array is IndirectStFldUse || node.Array is ItemUse)))
                    {
                        // 2, 6, 7
                        chain.EmitSetArrayItem(indexTypeCode, node.Index, reference);
                        chain.End();
                    }
                    else
                    {
                        // Note: The value which should be stored is already loaded on the evaluation stack.
                        //				Push the destination array and index and call the operator
                        // 1: a_[x]_
                        Debug.Assert(node.Array is SimpleVarUse);
                        chain.IsArrayItem  = true;
                        chain.IsLastMember = true;
                        indexTypeCode      = codeGenerator.EmitArrayKey(chain, node.Index);
                        node.Array.Emit(codeGenerator);
                        chain.EmitSetItem(indexTypeCode, node.Index, reference);

                        // Store the changed variable into table of variables (do nothing in optimalized functions)
                        SimpleVarUseHelper.EmitLoadAddress_StoreBack((SimpleVarUse)node.Array, codeGenerator);
                    }

                    result = PhpTypeCode.Void;
                    break;
                }

                case AccessType.None:
                    // do nothing
                    result = PhpTypeCode.Void;
                    break;

                case AccessType.Read:
                    // do nothing
                    result = PhpTypeCode.Object;
                    break;

                case AccessType.ReadRef:
                    // Do nothing
                    result = PhpTypeCode.PhpReference;
                    break;

                default:
                    Debug.Fail(null);
                    result = PhpTypeCode.Invalid;
                    break;
                }

                return(result);
            }