public void EmitAwaitOnCompletedDynamic(EmitContext ec, FieldExpr awaiter) { var critical = Module.PredefinedTypes.ICriticalNotifyCompletion; if (!critical.Define()) { throw new NotImplementedException(); } var temp_critical = new LocalTemporary(critical.TypeSpec); var label_critical = ec.DefineLabel(); var label_end = ec.DefineLabel(); // // Special path for dynamic awaiters // // var awaiter = this.$awaiter as ICriticalNotifyCompletion; // if (awaiter == null) { // var completion = (INotifyCompletion) this.$awaiter; // this.$builder.AwaitOnCompleted (ref completion, ref this); // } else { // this.$builder.AwaitUnsafeOnCompleted (ref awaiter, ref this); // } // awaiter.Emit(ec); ec.Emit(OpCodes.Isinst, critical.TypeSpec); temp_critical.Store(ec); temp_critical.Emit(ec); ec.Emit(OpCodes.Brtrue_S, label_critical); var temp = new LocalTemporary(Module.PredefinedTypes.INotifyCompletion.TypeSpec); awaiter.Emit(ec); ec.Emit(OpCodes.Castclass, temp.Type); temp.Store(ec); EmitOnCompleted(ec, temp, false); temp.Release(ec); ec.Emit(OpCodes.Br_S, label_end); ec.MarkLabel(label_critical); EmitOnCompleted(ec, temp_critical, true); ec.MarkLabel(label_end); temp_critical.Release(ec); }
// // if `dup_args' is true, a copy of the arguments will be left // on the stack. If `dup_args' is true, you can specify `this_arg' // which will be duplicated before any other args. Only EmitCall // should be using this interface. // public void Emit(EmitContext ec, bool dup_args, LocalTemporary this_arg) { LocalTemporary[] temps = null; if (dup_args && Count != 0) { temps = new LocalTemporary [Count]; } if (reordered != null && Count > 1) { foreach (NamedArgument na in reordered) { na.EmitAssign(ec); } } int i = 0; foreach (Argument a in args) { a.Emit(ec); if (dup_args) { ec.ig.Emit(OpCodes.Dup); (temps [i++] = new LocalTemporary(a.Type)).Store(ec); } } if (dup_args) { if (this_arg != null) { this_arg.Emit(ec); } for (i = 0; i < temps.Length; i++) { temps[i].Emit(ec); temps[i].Release(ec); } } }
// // if `dup_args' is true, a copy of the arguments will be left // on the stack. If `dup_args' is true, you can specify `this_arg' // which will be duplicated before any other args. Only EmitCall // should be using this interface. // public void Emit (EmitContext ec, bool dup_args, LocalTemporary this_arg) { LocalTemporary[] temps = null; if (dup_args && Count != 0) temps = new LocalTemporary [Count]; if (reordered != null && Count > 1) { foreach (NamedArgument na in reordered) na.EmitAssign (ec); } int i = 0; foreach (Argument a in args) { a.Emit (ec); if (dup_args) { ec.Emit (OpCodes.Dup); (temps [i++] = new LocalTemporary (a.Type)).Store (ec); } } if (dup_args) { if (this_arg != null) this_arg.Emit (ec); for (i = 0; i < temps.Length; i++) { temps[i].Emit (ec); temps[i].Release (ec); } } }
bool DoEmitTypeParameter (EmitContext ec) { #if GMCS_SOURCE ILGenerator ig = ec.ig; // IMemoryLocation ml; MethodInfo ci = TypeManager.activator_create_instance.MakeGenericMethod ( new Type [] { type }); GenericConstraints gc = TypeManager.GetTypeParameterConstraints (type); if (gc.HasReferenceTypeConstraint || gc.HasClassConstraint) { ig.Emit (OpCodes.Call, ci); return true; } // Allow DoEmit() to be called multiple times. // We need to create a new LocalTemporary each time since // you can't share LocalBuilders among ILGeneators. LocalTemporary temp = new LocalTemporary (type); Label label_activator = ig.DefineLabel (); Label label_end = ig.DefineLabel (); temp.AddressOf (ec, AddressOp.Store); ig.Emit (OpCodes.Initobj, type); temp.Emit (ec); ig.Emit (OpCodes.Box, type); ig.Emit (OpCodes.Brfalse, label_activator); temp.AddressOf (ec, AddressOp.Store); ig.Emit (OpCodes.Initobj, type); temp.Emit (ec); ig.Emit (OpCodes.Br_S, label_end); ig.MarkLabel (label_activator); ig.Emit (OpCodes.Call, ci); ig.MarkLabel (label_end); return true; #else throw new InternalErrorException (); #endif }
public override void Emit (EmitContext ec) { LocalTemporary temp_storage = new LocalTemporary(type); temp_storage.AddressOf(ec, AddressOp.LoadStore); ec.ig.Emit(OpCodes.Initobj, type); temp_storage.Emit(ec); }
/// <summary> /// Emits a list of resolved Arguments that are in the arguments /// ArrayList. /// /// The MethodBase argument might be null if the /// emission of the arguments is known not to contain /// a `params' field (for example in constructors or other routines /// that keep their arguments in this structure) /// /// if `dup_args' is true, a copy of the arguments will be left /// on the stack. If `dup_args' is true, you can specify `this_arg' /// which will be duplicated before any other args. Only EmitCall /// should be using this interface. /// </summary> public static void EmitArguments (EmitContext ec, ArrayList arguments, bool dup_args, LocalTemporary this_arg) { if (arguments == null) return; int top = arguments.Count; LocalTemporary [] temps = null; if (dup_args && top != 0) temps = new LocalTemporary [top]; int argument_index = 0; Argument a; for (int i = 0; i < top; i++) { a = (Argument) arguments [argument_index++]; a.Emit (ec); if (dup_args) { ec.ig.Emit (OpCodes.Dup); (temps [i] = new LocalTemporary (a.Type)).Store (ec); } } if (dup_args) { if (this_arg != null) this_arg.Emit (ec); for (int i = 0; i < top; i ++) { temps [i].Emit (ec); temps [i].Release (ec); } } }
protected override void EmitFinallyBody (EmitContext ec) { Expression instance = parent.enumerator; if (!TypeManager.IsValueType (parent.enumerator_type)) { ILGenerator ig = ec.ig; parent.enumerator.Emit (ec); Label call_dispose = ig.DefineLabel (); if (!implements_idisposable) { ec.ig.Emit (OpCodes.Isinst, TypeManager.idisposable_type); LocalTemporary temp = new LocalTemporary (TypeManager.idisposable_type); temp.Store (ec); temp.Emit (ec); instance = temp; } ig.Emit (OpCodes.Brtrue_S, call_dispose); // using 'endfinally' to empty the evaluation stack ig.Emit (OpCodes.Endfinally); ig.MarkLabel (call_dispose); } Invocation.EmitCall (ec, false, instance, TypeManager.void_dispose_void, null, loc); }