public override void EmitStatement(EmitContext ec) { if (resolved == null) { return; } // // Emit sequence symbol info even if we are in compiler generated // block to allow debugging field initializers when constructor is // compiler generated // if (ec.HasSet(BuilderContext.Options.OmitDebugInfo) && ec.HasMethodSymbolBuilder) { using (ec.With(BuilderContext.Options.OmitDebugInfo, false)) { ec.Mark(loc); } } if (resolved != this) { resolved.EmitStatement(ec); } else { base.EmitStatement(ec); } }
void EmitMoveNext_NoResumePoints(EmitContext ec) { ec.EmitThis(); ec.Emit(OpCodes.Ldfld, storey.PC.Spec); ec.EmitThis(); ec.EmitInt((int)IteratorStorey.State.After); ec.Emit(OpCodes.Stfld, storey.PC.Spec); // We only care if the PC is zero (start executing) or non-zero (don't do anything) ec.Emit(OpCodes.Brtrue, move_next_error); iterator_body_end = ec.DefineLabel(); if (ec.EmitAccurateDebugInfo && ec.Mark(Block.Original.StartLocation)) { ec.Emit(OpCodes.Nop); } block.Emit(ec); ec.MarkLabel(iterator_body_end); EmitMoveNextEpilogue(ec); ec.MarkLabel(move_next_error); if (ReturnType.Kind != MemberKind.Void) { ec.EmitInt(0); ec.Emit(OpCodes.Ret); } }
public override void Emit (EmitContext ec) { // It can be null for static initializers if (base_ctor == null) return; ec.Mark (loc); Invocation.EmitCall (ec, new CompilerGeneratedThis (type, loc), base_ctor, argument_list, loc); }
public override void EmitStatement (EmitContext ec) { if (resolved == null) return; // // Emit sequence symbol info even if we are in compiler generated // block to allow debugging field initializers when constructor is // compiler generated // if (ec.HasSet (BuilderContext.Options.OmitDebugInfo) && ec.HasMethodSymbolBuilder) { using (ec.With (BuilderContext.Options.OmitDebugInfo, false)) { ec.Mark (loc); } } if (resolved != this) resolved.EmitStatement (ec); else base.EmitStatement (ec); }
protected override void DoEmit (EmitContext ec) { if (empty) { expr.EmitSideEffect (ec); return; } Label old_begin = ec.LoopBegin; Label old_end = ec.LoopEnd; ec.LoopBegin = ec.DefineLabel (); ec.LoopEnd = ec.DefineLabel (); // // Inform whether we are infinite or not // if (expr is Constant){ // expr is 'true', since the 'empty' case above handles the 'false' case ec.MarkLabel (ec.LoopBegin); expr.EmitSideEffect (ec); Statement.Emit (ec); ec.Emit (OpCodes.Br, ec.LoopBegin); // // Inform that we are infinite (ie, `we return'), only // if we do not `break' inside the code. // ec.MarkLabel (ec.LoopEnd); } else { Label while_loop = ec.DefineLabel (); ec.Emit (OpCodes.Br, ec.LoopBegin); ec.MarkLabel (while_loop); Statement.Emit (ec); ec.MarkLabel (ec.LoopBegin); ec.Mark (loc); expr.EmitBranchable (ec, while_loop, true); ec.MarkLabel (ec.LoopEnd); } ec.LoopBegin = old_begin; ec.LoopEnd = old_end; }
public virtual void Emit (EmitContext ec) { ec.Mark (loc); DoEmit (ec); }
public override void Emit (EmitContext ec) { if (scope_initializers != null) EmitScopeInitializers (ec); ec.Mark (StartLocation); DoEmit (ec); if (SymbolWriter.HasSymbolWriter) EmitSymbolInfo (ec); }
public override void Emit (EmitContext ec) { if (Report.Errors > 0) return; #if PRODUCTION try { #endif if (ec.HasReturnLabel) ec.ReturnLabel = ec.DefineLabel (); base.Emit (ec); ec.Mark (EndLocation); if (ec.HasReturnLabel) ec.MarkLabel (ec.ReturnLabel); if (ec.return_value != null) { ec.Emit (OpCodes.Ldloc, ec.return_value); ec.Emit (OpCodes.Ret); } else { // // If `HasReturnLabel' is set, then we already emitted a // jump to the end of the method, so we must emit a `ret' // there. // // Unfortunately, System.Reflection.Emit automatically emits // a leave to the end of a finally block. This is a problem // if no code is following the try/finally block since we may // jump to a point after the end of the method. // As a workaround, we're always creating a return label in // this case. // if (ec.HasReturnLabel || !unreachable) { if (ec.ReturnType != TypeManager.void_type) ec.Emit (OpCodes.Ldloc, ec.TemporaryReturn ()); ec.Emit (OpCodes.Ret); } } #if PRODUCTION } catch (Exception e){ Console.WriteLine ("Exception caught by the compiler while emitting:"); Console.WriteLine (" Block that caused the problem begin at: " + block.loc); Console.WriteLine (e.GetType ().FullName + ": " + e.Message); throw; } #endif }
public override void Emit(EmitContext ec) { // It can be null for static initializers if (base_constructor_group == null) return; ec.Mark (loc); base_constructor_group.EmitCall (ec, argument_list); }
void EmitMoveNext(EmitContext ec) { move_next_ok = ec.DefineLabel(); move_next_error = ec.DefineLabel(); if (resume_points == null) { EmitMoveNext_NoResumePoints(ec); return; } current_pc = ec.GetTemporaryLocal(ec.BuiltinTypes.UInt); ec.EmitThis(); ec.Emit(OpCodes.Ldfld, storey.PC.Spec); ec.Emit(OpCodes.Stloc, current_pc); // We're actually in state 'running', but this is as good a PC value as any if there's an abnormal exit ec.EmitThis(); ec.EmitInt((int)IteratorStorey.State.After); ec.Emit(OpCodes.Stfld, storey.PC.Spec); Label[] labels = new Label[1 + resume_points.Count]; labels[0] = ec.DefineLabel(); bool need_skip_finally = false; for (int i = 0; i < resume_points.Count; ++i) { ResumableStatement s = resume_points[i]; need_skip_finally |= s is ExceptionStatement; labels[i + 1] = s.PrepareForEmit(ec); } if (need_skip_finally) { skip_finally = ec.GetTemporaryLocal(ec.BuiltinTypes.Bool); ec.EmitInt(0); ec.Emit(OpCodes.Stloc, skip_finally); } var async_init = this as AsyncInitializer; if (async_init != null) { ec.BeginExceptionBlock(); } ec.Emit(OpCodes.Ldloc, current_pc); ec.Emit(OpCodes.Switch, labels); ec.Emit(async_init != null ? OpCodes.Leave : OpCodes.Br, move_next_error); ec.MarkLabel(labels[0]); BodyEnd = ec.DefineLabel(); block.EmitEmbedded(ec); ec.MarkLabel(BodyEnd); if (async_init != null) { async_init.EmitCatchBlock(ec); } ec.Mark(Block.Original.EndLocation); ec.EmitThis(); ec.EmitInt((int)IteratorStorey.State.After); ec.Emit(OpCodes.Stfld, storey.PC.Spec); EmitMoveNextEpilogue(ec); ec.MarkLabel(move_next_error); if (ReturnType.Kind != MemberKind.Void) { ec.EmitInt(0); ec.Emit(OpCodes.Ret); } ec.MarkLabel(move_next_ok); if (ReturnType.Kind != MemberKind.Void) { ec.EmitInt(1); ec.Emit(OpCodes.Ret); } }
public override void Emit (EmitContext ec) { // It can be null for static initializers if (base_ctor == null) return; ec.Mark (loc); var call = new CallEmitter (); call.InstanceExpression = new CompilerGeneratedThis (type, loc); call.EmitPredefined (ec, base_ctor, argument_list); }
void EmitMoveNext(EmitContext ec) { move_next_ok = ec.DefineLabel(); move_next_error = ec.DefineLabel(); if (resume_points == null) { EmitMoveNext_NoResumePoints(ec); return; } current_pc = ec.GetTemporaryLocal(ec.BuiltinTypes.UInt); ec.EmitThis(); ec.Emit(OpCodes.Ldfld, storey.PC.Spec); ec.Emit(OpCodes.Stloc, current_pc); // We're actually in state 'running', but this is as good a PC value as any if there's an abnormal exit ec.EmitThis(); ec.EmitInt((int)IteratorStorey.State.After); ec.Emit(OpCodes.Stfld, storey.PC.Spec); Label[] labels = new Label[1 + resume_points.Count]; labels[0] = ec.DefineLabel(); bool need_skip_finally = false; for (int i = 0; i < resume_points.Count; ++i) { ResumableStatement s = resume_points[i]; need_skip_finally |= s is ExceptionStatement; labels[i + 1] = s.PrepareForEmit(ec); } if (need_skip_finally) { skip_finally = ec.GetTemporaryLocal(ec.BuiltinTypes.Bool); ec.EmitInt(0); ec.Emit(OpCodes.Stloc, skip_finally); } var async_init = this as AsyncInitializer; if (async_init != null) { ec.BeginExceptionBlock(); } ec.Emit(OpCodes.Ldloc, current_pc); ec.Emit(OpCodes.Switch, labels); ec.Emit(async_init != null ? OpCodes.Leave : OpCodes.Br, move_next_error); ec.MarkLabel(labels[0]); iterator_body_end = ec.DefineLabel(); if (ec.EmitAccurateDebugInfo && ec.Mark(Block.Original.StartLocation)) { ec.Emit(OpCodes.Nop); } block.Emit(ec); ec.MarkLabel(iterator_body_end); if (async_init != null) { var catch_value = LocalVariable.CreateCompilerGenerated(ec.Module.Compiler.BuiltinTypes.Exception, block, Location); ec.BeginCatchBlock(catch_value.Type); catch_value.EmitAssign(ec); ec.EmitThis(); ec.EmitInt((int)IteratorStorey.State.After); ec.Emit(OpCodes.Stfld, storey.PC.Spec); ((AsyncTaskStorey)async_init.Storey).EmitSetException(ec, new LocalVariableReference(catch_value, Location)); ec.Emit(OpCodes.Leave, move_next_ok); ec.EndExceptionBlock(); } ec.Mark(Block.Original.EndLocation); ec.EmitThis(); ec.EmitInt((int)IteratorStorey.State.After); ec.Emit(OpCodes.Stfld, storey.PC.Spec); EmitMoveNextEpilogue(ec); ec.MarkLabel(move_next_error); if (ReturnType.Kind != MemberKind.Void) { ec.EmitInt(0); ec.Emit(OpCodes.Ret); } ec.MarkLabel(move_next_ok); if (ReturnType.Kind != MemberKind.Void) { ec.EmitInt(1); ec.Emit(OpCodes.Ret); } }
public void EmitPredefined (EmitContext ec, MethodSpec method, Arguments Arguments, Location? loc = null) { Expression instance_copy = null; if (!HasAwaitArguments && ec.HasSet (BuilderContext.Options.AsyncBody)) { HasAwaitArguments = Arguments != null && Arguments.ContainsEmitWithAwait (); if (HasAwaitArguments && InstanceExpressionOnStack) { throw new NotSupportedException (); } } OpCode call_op; LocalTemporary lt = null; if (method.IsStatic) { call_op = OpCodes.Call; } else { if (IsVirtualCallRequired (InstanceExpression, method)) { call_op = OpCodes.Callvirt; } else { call_op = OpCodes.Call; } if (HasAwaitArguments) { instance_copy = InstanceExpression.EmitToField (ec); if (Arguments == null) EmitCallInstance (ec, instance_copy, method.DeclaringType, call_op); } else if (!InstanceExpressionOnStack) { var instance_on_stack_type = EmitCallInstance (ec, InstanceExpression, method.DeclaringType, call_op); if (DuplicateArguments) { ec.Emit (OpCodes.Dup); if (Arguments != null && Arguments.Count != 0) { lt = new LocalTemporary (instance_on_stack_type); lt.Store (ec); instance_copy = lt; } } } } if (Arguments != null && !InstanceExpressionOnStack) { EmittedArguments = Arguments.Emit (ec, DuplicateArguments, HasAwaitArguments); if (EmittedArguments != null) { if (instance_copy != null) { EmitCallInstance (ec, instance_copy, method.DeclaringType, call_op); if (lt != null) lt.Release (ec); } EmittedArguments.Emit (ec); } } if (call_op == OpCodes.Callvirt && (InstanceExpression.Type.IsGenericParameter || InstanceExpression.Type.IsStruct)) { ec.Emit (OpCodes.Constrained, InstanceExpression.Type); } if (loc != null) { // // Emit explicit sequence point for expressions like Foo.Bar () to help debugger to // break at right place when LHS expression can be stepped-into // // TODO: The list is probably not comprehensive, need to do more testing // if (InstanceExpression is PropertyExpr || InstanceExpression is Invocation || InstanceExpression is IndexerExpr || InstanceExpression is New || InstanceExpression is DelegateInvocation) ec.Mark (loc.Value); } // // Set instance expression to actual result expression. When it contains await it can be // picked up by caller // InstanceExpression = instance_copy; if (method.Parameters.HasArglist) { var varargs_types = GetVarargsTypes (method, Arguments); ec.Emit (call_op, method, varargs_types); return; } // // If you have: // this.DoFoo (); // and DoFoo is not virtual, you can omit the callvirt, // because you don't need the null checking behavior. // ec.Emit (call_op, method); }
public void EmitPredefined(EmitContext ec, MethodSpec method, Arguments Arguments, Location?loc = null) { Expression instance_copy = null; if (!HasAwaitArguments && ec.HasSet(BuilderContext.Options.AsyncBody)) { HasAwaitArguments = Arguments != null && Arguments.ContainsEmitWithAwait(); if (HasAwaitArguments && InstanceExpressionOnStack) { throw new NotSupportedException(); } } OpCode call_op; LocalTemporary lt = null; if (method.IsStatic) { call_op = OpCodes.Call; } else { if (IsVirtualCallRequired(InstanceExpression, method)) { call_op = OpCodes.Callvirt; } else { call_op = OpCodes.Call; } if (HasAwaitArguments) { instance_copy = InstanceExpression.EmitToField(ec); if (Arguments == null) { EmitCallInstance(ec, instance_copy, method.DeclaringType, call_op); } } else if (!InstanceExpressionOnStack) { var instance_on_stack_type = EmitCallInstance(ec, InstanceExpression, method.DeclaringType, call_op); if (DuplicateArguments) { ec.Emit(OpCodes.Dup); if (Arguments != null && Arguments.Count != 0) { lt = new LocalTemporary(instance_on_stack_type); lt.Store(ec); instance_copy = lt; } } } } if (Arguments != null && !InstanceExpressionOnStack) { EmittedArguments = Arguments.Emit(ec, DuplicateArguments, HasAwaitArguments); if (EmittedArguments != null) { if (instance_copy != null) { EmitCallInstance(ec, instance_copy, method.DeclaringType, call_op); if (lt != null) { lt.Release(ec); } } EmittedArguments.Emit(ec); } } if (call_op == OpCodes.Callvirt && (InstanceExpression.Type.IsGenericParameter || InstanceExpression.Type.IsStruct)) { ec.Emit(OpCodes.Constrained, InstanceExpression.Type); } if (loc != null) { // // Emit explicit sequence point for expressions like Foo.Bar () to help debugger to // break at right place when LHS expression can be stepped-into // // TODO: The list is probably not comprehensive, need to do more testing // if (InstanceExpression is PropertyExpr || InstanceExpression is Invocation || InstanceExpression is IndexerExpr || InstanceExpression is New || InstanceExpression is DelegateInvocation) { ec.Mark(loc.Value); } } // // Set instance expression to actual result expression. When it contains await it can be // picked up by caller // InstanceExpression = instance_copy; if (method.Parameters.HasArglist) { var varargs_types = GetVarargsTypes(method, Arguments); ec.Emit(call_op, method, varargs_types); return; } // // If you have: // this.DoFoo (); // and DoFoo is not virtual, you can omit the callvirt, // because you don't need the null checking behavior. // ec.Emit(call_op, method); }
public void Emit (EmitContext ec) { if (parent_constructor != null){ ec.Mark (loc, false); if (ec.IsStatic) Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc); else Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc); } }
public override void Emit (EmitContext ec) { base.Emit (ec); ec.Mark (EndLocation); }
public override void Emit (EmitContext ec) { Block prev_block = ec.CurrentBlock; ec.CurrentBlock = this; if (scope_initializers != null) { SymbolWriter.OpenCompilerGeneratedBlock (ec.ig); using (ec.Set (EmitContext.Flags.OmitDebuggingInfo)) { foreach (Statement s in scope_initializers) s.Emit (ec); } SymbolWriter.CloseCompilerGeneratedBlock (ec.ig); } ec.Mark (StartLocation); DoEmit (ec); if (SymbolWriter.HasSymbolWriter) EmitSymbolInfo (ec); ec.CurrentBlock = prev_block; }