+ //
+ // Otherwise simply use temporary local variable
+ //
+ var field = LocalVariable.CreateCompilerGenerated (action, OriginalSourceBlock, Location);
+ EmitActionLoad (ec);
+ field.EmitAssign (ec);
+ return new LocalVariableReference (field, Location);
+ }
+
+ void EmitActionLoad (EmitContext ec)
+ {
+ ec.EmitThis ();
+ ec.Emit (OpCodes.Ldftn, StateMachineMethod.Spec);
+ ec.Emit (OpCodes.Newobj, (MethodSpec) MemberCache.FindMember (action, MemberFilter.Constructor (null), BindingRestriction.DeclaredOnly));
+ }
+
+ public void EmitSetException (EmitContext ec, LocalVariableReference exceptionVariable)
+ {
+ //
+ // $builder.SetException (Exception)
+ //
+ var mg = MethodGroupExpr.CreatePredefined (set_exception, set_exception.DeclaringType, Location);
+ mg.InstanceExpression = new FieldExpr (Builder, Location) {
+ InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location)
+ };
+
+ Arguments args = new Arguments (1);
+ args.Add (new Argument (exceptionVariable));
+
+ mg.EmitCall (ec, args);
+ }
+
+ public void EmitSetResult (EmitContext ec)
+ {
+ //
+ // $builder.SetResult ();
+ // $builder.SetResult<return-type> (value);
+ //
+ var mg = MethodGroupExpr.CreatePredefined (set_result, set_result.DeclaringType, Location);
+ mg.InstanceExpression = new FieldExpr (Builder, Location) {
+ InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location)
+ };
+
+ Arguments args;
+ if (hoisted_return == null) {
+ args = new Arguments (0);
+ } else {
+ args = new Arguments (1);
+ args.Add (new Argument (new LocalVariableReference (hoisted_return, Location)));
+ }
+
+ mg.EmitCall (ec, args);
+ }
+ }
+
+ class StackField : Field
+ {
+ public StackField (TypeDefinition parent, FullNamedExpression type, Modifiers mod, MemberName name)
+ : base (parent, type, mod, name, null)
+ {
+ }
+
+ public bool CanBeReused { get; set; }
+ }
+
+ class StackFieldExpr : FieldExpr
+ {
+ public StackFieldExpr (Field field)
+ : base (field, Location.Null)
+ {
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ base.Emit (ec);
+
+ var field = (StackField) spec.MemberDefinition;
+ field.CanBeReused = true;