/// <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(); }
/// <summary> /// Emits init field helpers (<c>__lastContext</c> field, <c><InitializeInstanceFields></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 } }