Пример #1
0
        /// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/>
        internal void Emit(CodeGenerator /*!*/ codeGenerator)
        {
            // TODO: improve
            codeGenerator.EnterGlobalCodeDeclaration(this.varTable, labels, sourceUnit);

            // custom body prolog emittion:
            PluginHandler.EmitBeforeBody(codeGenerator.IL, statements);

            //
            if (codeGenerator.CompilationUnit.IsTransient)
            {
                codeGenerator.DefineLabels(labels);

                codeGenerator.ChainBuilder.Create();

                foreach (Statement statement in statements)
                {
                    statement.Emit(codeGenerator);
                }

                codeGenerator.ChainBuilder.End();

                // return + appended file emission:
                codeGenerator.EmitRoutineEpilogue(this, true);
            }
#if !SILVERLIGHT
            else if (codeGenerator.CompilationUnit.IsPure)
            {
                codeGenerator.ChainBuilder.Create();

                foreach (Statement statement in statements)
                {
                    // skip empty statements in global code (they emit sequence points, which is undesirable):
                    if (!(statement is EmptyStmt))
                    {
                        statement.Emit(codeGenerator);
                    }
                }

                codeGenerator.ChainBuilder.End();
            }
            else
            {
                ScriptCompilationUnit unit = (ScriptCompilationUnit)codeGenerator.CompilationUnit;

                ILEmitter il = codeGenerator.IL;

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

                codeGenerator.DefineLabels(labels);

                // CALL <self>.<Declare>(context);
                codeGenerator.EmitLoadScriptContext();
                il.Emit(OpCodes.Call, unit.ScriptBuilder.DeclareHelperBuilder);

                // IF (<is main script>) CALL <prepended script>.Main()
                if (prependedInclusion != null)
                {
                    prependedInclusion.Emit(codeGenerator);
                }

                codeGenerator.ChainBuilder.Create();

                foreach (Statement statement in statements)
                {
                    statement.Emit(codeGenerator);
                }

                codeGenerator.ChainBuilder.End();

                // return + appended file emission:
                codeGenerator.EmitRoutineEpilogue(this, false);
            }
#endif
            codeGenerator.LeaveGlobalCodeDeclaration();
        }
Пример #2
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);

            // emit custom body prolog:
            PluginHandler.EmitBeforeBody(phpType.Builder.InstanceFieldInitEmitter, null);


            //
            // <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
                // emit custom body prolog:
                PluginHandler.EmitBeforeBody(cil, null);

                //
                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
            }
        }