public override void Emit(EmitContext ec) { if (Value) ec.Emit (OpCodes.Ldc_I4_1); else ec.Emit (OpCodes.Ldc_I4_0); }
public override void Emit (EmitContext ec) { // // Emits null pointer // ec.Emit (OpCodes.Ldc_I4_0); ec.Emit (OpCodes.Conv_U); }
protected override void DoEmit(EmitContext ec) { if (statement != null) { statement.EmitStatement (ec); if (unwind_protect) ec.Emit (OpCodes.Leave, ec.CreateReturnLabel ()); else { ec.Emit (OpCodes.Ret); } return; } base.DoEmit (ec); }
public override void Emit(EmitContext ec) { if (statement != null) { statement.EmitStatement (ec); ec.Emit (OpCodes.Ret); return; } base.Emit (ec); }
public override void Emit (EmitContext ec) { ec.EmitNull (); // Only to make verifier happy if (type.IsGenericParameter) ec.Emit (OpCodes.Unbox_Any, type); }
void EmitMoveNext(EmitContext ec) { move_next_ok = ec.DefineLabel(); move_next_error = ec.DefineLabel(); if (resume_points == null) { EmitMoveNext_NoResumePoints(ec, block); return; } current_pc = ec.GetTemporaryLocal(ec.BuiltinTypes.UInt); ec.Emit(OpCodes.Ldarg_0); 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.Emit(OpCodes.Ldarg_0); 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.Emit(OpCodes.Ldc_I4_0); ec.Emit(OpCodes.Stloc, skip_finally); } SymbolWriter.StartIteratorDispatcher(ec); ec.Emit(OpCodes.Ldloc, current_pc); ec.Emit(OpCodes.Switch, labels); ec.Emit(OpCodes.Br, move_next_error); SymbolWriter.EndIteratorDispatcher(ec); ec.MarkLabel(labels[0]); SymbolWriter.StartIteratorBody(ec); block.Emit(ec); SymbolWriter.EndIteratorBody(ec); SymbolWriter.StartIteratorDispatcher(ec); ec.Emit(OpCodes.Ldarg_0); 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); } SymbolWriter.EndIteratorDispatcher(ec); }
public override void Emit (EmitContext ec) { // // It can be null for struct initializers or System.Object // if (base_ctor == null) { if (type == ec.BuiltinTypes.Object) return; ec.Emit (OpCodes.Ldarg_0); ec.Emit (OpCodes.Initobj, type); return; } var call = new CallEmitter (); call.InstanceExpression = new CompilerGeneratedThis (type, loc); call.EmitPredefined (ec, base_ctor, argument_list, false); }
public override void Emit (EmitContext ec) { MethodSpec m; int [] words = decimal.GetBits (Value); int power = (words [3] >> 16) & 0xff; if (power == 0) { if (Value <= int.MaxValue && Value >= int.MinValue) { m = ec.Module.PredefinedMembers.DecimalCtorInt.Resolve (loc); if (m == null) { return; } ec.EmitInt ((int) Value); ec.Emit (OpCodes.Newobj, m); return; } if (Value <= long.MaxValue && Value >= long.MinValue) { m = ec.Module.PredefinedMembers.DecimalCtorLong.Resolve (loc); if (m == null) { return; } ec.EmitLong ((long) Value); ec.Emit (OpCodes.Newobj, m); return; } } ec.EmitInt (words [0]); ec.EmitInt (words [1]); ec.EmitInt (words [2]); // sign ec.EmitInt (words [3] >> 31); // power ec.EmitInt (power); m = ec.Module.PredefinedMembers.DecimalCtor.Resolve (loc); if (m != null) { ec.Emit (OpCodes.Newobj, m); } }
public override void Emit (EmitContext ec) { if (Value == null) { ec.Emit (OpCodes.Ldnull); return; } // // Use string.Empty for both literals and constants even if // it's not allowed at language level // if (Value.Length == 0 && RootContext.Optimize && ec.CurrentType != TypeManager.string_type) { if (TypeManager.string_empty == null) TypeManager.string_empty = TypeManager.GetPredefinedField (TypeManager.string_type, "Empty", loc, TypeManager.string_type); if (TypeManager.string_empty != null) { ec.Emit (OpCodes.Ldsfld, TypeManager.string_empty); return; } } ec.Emit (OpCodes.Ldstr, Value); }
internal void EmitValueChangedCallback (EmitContext ec, string name, TypeSpec type, Location loc) { if (listener_id == null) listener_id = ListenerProxy.Register (ModificationListener); if (listener_proxy_value == null) listener_proxy_value = typeof (ListenerProxy).GetMethod ("ValueChanged"); #if STATIC throw new NotSupportedException (); #else // object value, int row, int col, string name, int listenerId if (type.IsStructOrEnum) ec.Emit (OpCodes.Box, type); ec.EmitInt (loc.Row); ec.EmitInt (loc.Column); ec.Emit (OpCodes.Ldstr, name); ec.EmitInt (listener_id.Value); ec.Emit (OpCodes.Call, listener_proxy_value); #endif }
public override void Emit (EmitContext ec) { if (builder == null) throw new InternalErrorException ("Emit without Store, or after Release"); ec.Emit (OpCodes.Ldloc, builder); }
public void AddressOf (EmitContext ec, AddressOp mode) { if (builder == null) builder = ec.GetTemporaryLocal (type); if (builder.LocalType.IsByRef) { // // if is_address, than this is just the address anyways, // so we just return this. // ec.Emit (OpCodes.Ldloc, builder); } else { ec.Emit (OpCodes.Ldloca, builder); } }
// // Called back from Yield // public void MarkYield(EmitContext ec, Expression expr, int resume_pc, bool unwind_protect, Label resume_point) { // Store the new current ec.Emit (OpCodes.Ldarg_0); expr.Emit (ec); ec.Emit (OpCodes.Stfld, IteratorHost.CurrentField.Spec); // store resume program-counter ec.Emit (OpCodes.Ldarg_0); ec.EmitInt (resume_pc); ec.Emit (OpCodes.Stfld, IteratorHost.PC.Spec); // mark finally blocks as disabled if (unwind_protect && skip_finally != null) { ec.EmitInt (1); ec.Emit (OpCodes.Stloc, skip_finally); } // Return ok ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_ok); ec.MarkLabel (resume_point); }
void EmitMoveNext_NoResumePoints(EmitContext ec, Block original_block) { ec.Emit (OpCodes.Ldarg_0); ec.Emit (OpCodes.Ldfld, IteratorHost.PC.Spec); ec.Emit (OpCodes.Ldarg_0); ec.EmitInt ((int) State.After); ec.Emit (OpCodes.Stfld, IteratorHost.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); SymbolWriter.StartIteratorBody (ec); original_block.Emit (ec); SymbolWriter.EndIteratorBody (ec); ec.MarkLabel (move_next_error); ec.Emit (OpCodes.Ldc_I4_0); ec.Emit (OpCodes.Ret); }
public void EmitLeave(EmitContext ec, bool unwind_protect) { // Return ok ec.Emit(unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_ok); }
public void EmitDispose(EmitContext ec) { if (resume_points == null) { return; } Label end = ec.DefineLabel(); Label[] labels = null; for (int i = 0; i < resume_points.Count; ++i) { ResumableStatement s = resume_points[i]; Label ret = s.PrepareForDispose(ec, end); if (ret.Equals(end) && labels == null) { continue; } if (labels == null) { labels = new Label[resume_points.Count + 1]; for (int j = 0; j <= i; ++j) { labels[j] = end; } } labels[i + 1] = ret; } if (labels != null) { current_pc = ec.GetTemporaryLocal(ec.BuiltinTypes.UInt); ec.EmitThis(); ec.Emit(OpCodes.Ldfld, storey.PC.Spec); ec.Emit(OpCodes.Stloc, current_pc); } ec.EmitThis(); ec.EmitInt(1); ec.Emit(OpCodes.Stfld, ((IteratorStorey)storey).DisposingField.Spec); ec.EmitThis(); ec.EmitInt((int)IteratorStorey.State.After); ec.Emit(OpCodes.Stfld, storey.PC.Spec); if (labels != null) { //SymbolWriter.StartIteratorDispatcher (ec.ig); ec.Emit(OpCodes.Ldloc, current_pc); ec.Emit(OpCodes.Switch, labels); //SymbolWriter.EndIteratorDispatcher (ec.ig); foreach (ResumableStatement s in resume_points) { s.EmitForDispose(ec, current_pc, end, true); } } ec.MarkLabel(end); }
public void EmitYieldBreak(EmitContext ec, bool unwind_protect) { ec.Emit(unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_error); }
public void EmitInitializer(EmitContext ec) { // // Some predefined types are missing // if (builder == null) { return; } var instance = (TemporaryVariableReference)Instance; var builder_field = builder.Spec; if (MemberName.Arity > 0) { builder_field = MemberCache.GetMember(instance.Type, builder_field); } // // Inflated factory method when task is of generic type // if (builder_factory.DeclaringType.IsGeneric) { var task_return_type = return_type.TypeArguments; var bt = builder_factory.DeclaringType.MakeGenericType(Module, task_return_type); builder_factory = MemberCache.GetMember(bt, builder_factory); builder_start = MemberCache.GetMember(bt, builder_start); } // // stateMachine.$builder = AsyncTaskMethodBuilder<{task-type}>.Create(); // instance.AddressOf(ec, AddressOp.Store); ec.Emit(OpCodes.Call, builder_factory); ec.Emit(OpCodes.Stfld, builder_field); // // stateMachine.$builder.Start<{storey-type}>(ref stateMachine); // instance.AddressOf(ec, AddressOp.Store); ec.Emit(OpCodes.Ldflda, builder_field); if (Task != null) { ec.Emit(OpCodes.Dup); } instance.AddressOf(ec, AddressOp.Store); ec.Emit(OpCodes.Call, builder_start.MakeGenericMethod(Module, instance.Type)); // // Emits return stateMachine.$builder.Task; // if (Task != null) { var task_get = Task.Get; if (MemberName.Arity > 0) { task_get = MemberCache.GetMember(builder_field.MemberType, task_get); } var pe_task = new PropertyExpr(Task, Location) { InstanceExpression = EmptyExpression.Null, // Comes from the dup above Getter = task_get }; pe_task.Emit(ec); } }
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); } }
internal void EmitMoveNext(EmitContext ec, Block original_block) { move_next_ok = ec.DefineLabel (); move_next_error = ec.DefineLabel (); if (resume_points == null) { EmitMoveNext_NoResumePoints (ec, original_block); return; } current_pc = ec.GetTemporaryLocal (TypeManager.uint32_type); ec.Emit (OpCodes.Ldarg_0); ec.Emit (OpCodes.Ldfld, IteratorHost.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.Emit (OpCodes.Ldarg_0); ec.EmitInt ((int) State.After); ec.Emit (OpCodes.Stfld, IteratorHost.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 (TypeManager.bool_type); ec.Emit (OpCodes.Ldc_I4_0); ec.Emit (OpCodes.Stloc, skip_finally); } SymbolWriter.StartIteratorDispatcher (ec); ec.Emit (OpCodes.Ldloc, current_pc); ec.Emit (OpCodes.Switch, labels); ec.Emit (OpCodes.Br, move_next_error); SymbolWriter.EndIteratorDispatcher (ec); ec.MarkLabel (labels [0]); SymbolWriter.StartIteratorBody (ec); original_block.Emit (ec); SymbolWriter.EndIteratorBody (ec); SymbolWriter.StartIteratorDispatcher (ec); ec.Emit (OpCodes.Ldarg_0); ec.EmitInt ((int) State.After); ec.Emit (OpCodes.Stfld, IteratorHost.PC.Spec); ec.MarkLabel (move_next_error); ec.EmitInt (0); ec.Emit (OpCodes.Ret); ec.MarkLabel (move_next_ok); ec.Emit (OpCodes.Ldc_I4_1); ec.Emit (OpCodes.Ret); SymbolWriter.EndIteratorDispatcher (ec); }
public override void Emit (EmitContext ec) { Label l_initialized = ec.DefineLabel (); if (mg_cache != null) { ec.Emit (OpCodes.Ldsfld, mg_cache.Spec); ec.Emit (OpCodes.Brtrue_S, l_initialized); } base.Emit (ec); if (mg_cache != null) { ec.Emit (OpCodes.Stsfld, mg_cache.Spec); ec.MarkLabel (l_initialized); ec.Emit (OpCodes.Ldsfld, mg_cache.Spec); } }
protected override void DoEmit(EmitContext ec) { Label label_init = ec.DefineLabel (); ec.Emit (OpCodes.Ldarg_0); ec.Emit (OpCodes.Ldflda, host.PC.Spec); ec.EmitInt ((int) Iterator.State.Start); ec.EmitInt ((int) Iterator.State.Uninitialized); ec.Emit (OpCodes.Call, TypeManager.int_interlocked_compare_exchange); ec.EmitInt ((int) Iterator.State.Uninitialized); ec.Emit (OpCodes.Bne_Un_S, label_init); ec.Emit (OpCodes.Ldarg_0); ec.Emit (OpCodes.Ret); ec.MarkLabel (label_init); new_storey.Emit (ec); ec.Emit (OpCodes.Ret); }
public void EmitPredefined (EmitContext ec, MethodSpec method, Arguments Arguments, bool statement = false, 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 { call_op = IsVirtualCallRequired (InstanceExpression, method) ? OpCodes.Callvirt : OpCodes.Call; if (HasAwaitArguments) { instance_copy = InstanceExpression.EmitToField (ec); var ie = new InstanceEmitter (instance_copy, IsAddressCall (instance_copy, call_op, method.DeclaringType)); if (Arguments == null) { ie.EmitLoad (ec, true); } } else if (!InstanceExpressionOnStack) { var ie = new InstanceEmitter (InstanceExpression, IsAddressCall (InstanceExpression, call_op, method.DeclaringType)); ie.Emit (ec, ConditionalAccess); if (DuplicateArguments) { ec.Emit (OpCodes.Dup); if (Arguments != null && Arguments.Count != 0) { lt = new LocalTemporary (ie.GetStackType (ec)); lt.Store (ec); instance_copy = lt; } } } } if (Arguments != null && !InstanceExpressionOnStack) { EmittedArguments = Arguments.Emit (ec, DuplicateArguments, HasAwaitArguments); if (EmittedArguments != null) { if (instance_copy != null) { var ie = new InstanceEmitter (instance_copy, IsAddressCall (instance_copy, call_op, method.DeclaringType)); ie.Emit (ec, ConditionalAccess); if (lt != null) lt.Release (ec); } EmittedArguments.Emit (ec); } } if (call_op == OpCodes.Callvirt && (InstanceExpression.Type.IsGenericParameter || InstanceExpression.Type.IsStructOrEnum)) { 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 // ec.MarkCallEntry (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); } else { // // 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); } // // Pop the return value if there is one and stack should be empty // if (statement && method.ReturnType.Kind != MemberKind.Void) ec.Emit (OpCodes.Pop); }
public void Store (EmitContext ec) { if (builder == null) builder = ec.GetTemporaryLocal (type); ec.Emit (OpCodes.Stloc, builder); }
public void Emit (EmitContext ec, bool conditionalAccess) { Label NullOperatorLabel; Nullable.Unwrap unwrap; if (conditionalAccess && Expression.IsNeverNull (instance)) conditionalAccess = false; if (conditionalAccess) { NullOperatorLabel = ec.DefineLabel (); unwrap = instance as Nullable.Unwrap; } else { NullOperatorLabel = new Label (); unwrap = null; } IMemoryLocation instance_address = null; bool conditional_access_dup = false; if (unwrap != null) { unwrap.Store (ec); unwrap.EmitCheck (ec); ec.Emit (OpCodes.Brtrue_S, NullOperatorLabel); } else { if (conditionalAccess && addressRequired) { // // Don't allocate temp variable when instance load is cheap and load and load-address // operate on same memory // instance_address = instance as VariableReference; if (instance_address == null) instance_address = instance as LocalTemporary; if (instance_address == null) { EmitLoad (ec, false); ec.Emit (OpCodes.Dup); ec.EmitLoadFromPtr (instance.Type); conditional_access_dup = true; } else { instance.Emit (ec); } } else { EmitLoad (ec, !conditionalAccess); if (conditionalAccess) { conditional_access_dup = !IsInexpensiveLoad (); if (conditional_access_dup) ec.Emit (OpCodes.Dup); } } if (conditionalAccess) { if (instance.Type.Kind == MemberKind.TypeParameter) ec.Emit (OpCodes.Box, instance.Type); ec.Emit (OpCodes.Brtrue_S, NullOperatorLabel); if (conditional_access_dup) ec.Emit (OpCodes.Pop); } } if (conditionalAccess) { if (!ec.ConditionalAccess.Statement) { if (ec.ConditionalAccess.Type.IsNullableType) Nullable.LiftedNull.Create (ec.ConditionalAccess.Type, Location.Null).Emit (ec); else ec.EmitNull (); } ec.Emit (OpCodes.Br, ec.ConditionalAccess.EndLabel); ec.MarkLabel (NullOperatorLabel); if (instance_address != null) { instance_address.AddressOf (ec, AddressOp.Load); } else if (unwrap != null) { unwrap.Emit (ec); var tmp = ec.GetTemporaryLocal (unwrap.Type); ec.Emit (OpCodes.Stloc, tmp); ec.Emit (OpCodes.Ldloca, tmp); ec.FreeTemporaryLocal (tmp, unwrap.Type); } else if (!conditional_access_dup) { instance.Emit (ec); } } }
public override void Emit (EmitContext ec) { int [] words = decimal.GetBits (Value); int power = (words [3] >> 16) & 0xff; if (power == 0) { if (Value <= int.MaxValue && Value >= int.MinValue) { if (TypeManager.void_decimal_ctor_int_arg == null) { TypeManager.void_decimal_ctor_int_arg = TypeManager.GetPredefinedConstructor ( TypeManager.decimal_type, loc, TypeManager.int32_type); if (TypeManager.void_decimal_ctor_int_arg == null) return; } ec.EmitInt ((int) Value); ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg); return; } if (Value <= long.MaxValue && Value >= long.MinValue) { if (TypeManager.void_decimal_ctor_long_arg == null) { TypeManager.void_decimal_ctor_long_arg = TypeManager.GetPredefinedConstructor ( TypeManager.decimal_type, loc, TypeManager.int64_type); if (TypeManager.void_decimal_ctor_long_arg == null) return; } ec.EmitLong ((long) Value); ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_long_arg); return; } } ec.EmitInt (words [0]); ec.EmitInt (words [1]); ec.EmitInt (words [2]); // sign ec.EmitInt (words [3] >> 31); // power ec.EmitInt (power); if (TypeManager.void_decimal_ctor_five_args == null) { TypeManager.void_decimal_ctor_five_args = TypeManager.GetPredefinedConstructor ( TypeManager.decimal_type, loc, TypeManager.int32_type, TypeManager.int32_type, TypeManager.int32_type, TypeManager.bool_type, TypeManager.byte_type); if (TypeManager.void_decimal_ctor_five_args == null) return; } ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args); }
public void EmitLoad (EmitContext ec, bool boxInstance) { var instance_type = instance.Type; // // Push the instance expression // if (addressRequired) { // // If the expression implements IMemoryLocation, then // we can optimize and use AddressOf on the // return. // // If not we have to use some temporary storage for // it. var iml = instance as IMemoryLocation; if (iml != null) { iml.AddressOf (ec, AddressOp.Load); } else { LocalTemporary temp = new LocalTemporary (instance_type); instance.Emit (ec); temp.Store (ec); temp.AddressOf (ec, AddressOp.Load); } return; } instance.Emit (ec); // Only to make verifier happy if (boxInstance && RequiresBoxing ()) { ec.Emit (OpCodes.Box, instance_type); } }
public override void Emit (EmitContext ec) { ec.Emit (OpCodes.Ldnull); // Only to make verifier happy if (TypeManager.IsGenericParameter (type)) ec.Emit (OpCodes.Unbox_Any, type); }
// // 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); } } }
/// <summary> /// C# allows this kind of scenarios: /// interface I { void M (); } /// class X { public void M (); } /// class Y : X, I { } /// /// For that case, we create an explicit implementation function /// I.M in Y. /// </summary> void DefineProxy (TypeSpec iface, MethodSpec base_method, MethodSpec iface_method) { // TODO: Handle nested iface names string proxy_name; var ns = iface.MemberDefinition.Namespace; if (string.IsNullOrEmpty (ns)) proxy_name = iface.MemberDefinition.Name + "." + iface_method.Name; else proxy_name = ns + "." + iface.MemberDefinition.Name + "." + iface_method.Name; var param = iface_method.Parameters; MethodBuilder proxy = container.TypeBuilder.DefineMethod ( proxy_name, MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.CheckAccessOnOverride | MethodAttributes.Virtual | MethodAttributes.Final, CallingConventions.Standard | CallingConventions.HasThis, base_method.ReturnType.GetMetaInfo (), param.GetMetaInfo ()); if (iface_method.IsGeneric) { var gnames = iface_method.GenericDefinition.TypeParameters.Select (l => l.Name).ToArray (); proxy.DefineGenericParameters (gnames); } for (int i = 0; i < param.Count; i++) { string name = param.FixedParameters [i].Name; ParameterAttributes attr = ParametersCompiled.GetParameterAttribute (param.FixedParameters [i].ModFlags); proxy.DefineParameter (i + 1, attr, name); } int top = param.Count; var ec = new EmitContext (new ProxyMethodContext (container), proxy.GetILGenerator (), null); ec.EmitThis (); // TODO: GetAllParametersArguments for (int i = 0; i < top; i++) ec.EmitArgumentLoad (i); ec.Emit (OpCodes.Call, base_method); ec.Emit (OpCodes.Ret); container.TypeBuilder.DefineMethodOverride (proxy, (MethodInfo) iface_method.GetMetaInfo ()); }
public override void Emit(EmitContext ec) { // // Load Iterator storey instance // method.Storey.Instance.Emit (ec); // // Initialize iterator PC when it's unitialized // if (IsEnumerable) { ec.Emit (OpCodes.Dup); ec.EmitInt ((int)State.Uninitialized); var field = IteratorHost.PC.Spec; if (Storey.MemberName.IsGeneric) { field = MemberCache.GetMember (Storey.Instance.Type, field); } ec.Emit (OpCodes.Stfld, field); } }
public override void Emit (EmitContext ec) { ec.Emit (OpCodes.Ldc_R8, Value); }
public void EmitDispose(EmitContext ec) { Label end = ec.DefineLabel (); Label [] labels = null; int n_resume_points = resume_points == null ? 0 : resume_points.Count; for (int i = 0; i < n_resume_points; ++i) { ResumableStatement s = (ResumableStatement) resume_points [i]; Label ret = s.PrepareForDispose (ec, end); if (ret.Equals (end) && labels == null) continue; if (labels == null) { labels = new Label [resume_points.Count + 1]; for (int j = 0; j <= i; ++j) labels [j] = end; } labels [i+1] = ret; } if (labels != null) { current_pc = ec.GetTemporaryLocal (TypeManager.uint32_type); ec.Emit (OpCodes.Ldarg_0); ec.Emit (OpCodes.Ldfld, IteratorHost.PC.Spec); ec.Emit (OpCodes.Stloc, current_pc); } ec.Emit (OpCodes.Ldarg_0); ec.EmitInt ((int) State.After); ec.Emit (OpCodes.Stfld, IteratorHost.PC.Spec); if (labels != null) { //SymbolWriter.StartIteratorDispatcher (ec.ig); ec.Emit (OpCodes.Ldloc, current_pc); ec.Emit (OpCodes.Switch, labels); //SymbolWriter.EndIteratorDispatcher (ec.ig); foreach (ResumableStatement s in resume_points) s.EmitForDispose (ec, this, end, true); } ec.MarkLabel (end); }
public override void Emit (EmitContext ec) { if (Value == null) { ec.EmitNull (); return; } // // Use string.Empty for both literals and constants even if // it's not allowed at language level // if (Value.Length == 0 && ec.Module.Compiler.Settings.Optimize) { var string_type = ec.BuiltinTypes.String; if (ec.CurrentType != string_type) { var m = ec.Module.PredefinedMembers.StringEmpty.Get (); if (m != null) { ec.Emit (OpCodes.Ldsfld, m); return; } } } ec.Emit (OpCodes.Ldstr, Value); }
public void EmitYieldBreak(EmitContext ec, bool unwind_protect) { ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_error); }
public override void Emit (EmitContext ec) { // // Use same anonymous method implementation for scenarios where same // code is used from multiple blocks, e.g. field initializers // if (method == null) { // // Delay an anonymous method definition to avoid emitting unused code // for unreachable blocks or expression trees // method = DoCreateMethodHost (ec); method.Define (); } bool is_static = (method.ModFlags & Modifiers.STATIC) != 0; if (is_static && am_cache == null) { // // Creates a field cache to store delegate instance if it's not generic // if (!method.MemberName.IsGeneric) { var parent = method.Parent.PartialContainer; int id = parent.AnonymousMethodsCounter++; var cache_type = storey != null && storey.Mutator != null ? storey.Mutator.Mutate (type) : type; am_cache = new Field (parent, new TypeExpression (cache_type, loc), Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, new MemberName (CompilerGeneratedContainer.MakeName (null, "f", "am$cache", id), loc), null); am_cache.Define (); parent.AddField (am_cache); } else { // TODO: Implement caching of generated generic static methods // // Idea: // // Some extra class is needed to capture variable generic type // arguments. Maybe we could re-use anonymous types, with a unique // anonymous method id, but they are quite heavy. // // Consider : "() => typeof(T);" // // We need something like // static class Wrap<Tn, Tm, DelegateType> { // public static DelegateType cache; // } // // We then specialize local variable to capture all generic parameters // and delegate type, e.g. "Wrap<Ta, Tb, DelegateTypeInst> cache;" // } } Label l_initialized = ec.DefineLabel (); if (am_cache != null) { ec.Emit (OpCodes.Ldsfld, am_cache.Spec); ec.Emit (OpCodes.Brtrue_S, l_initialized); } // // Load method delegate implementation // if (is_static) { ec.EmitNull (); } else if (storey != null) { Expression e = storey.GetStoreyInstanceExpression (ec).Resolve (new ResolveContext (ec.MemberContext)); if (e != null) { e.Emit (ec); } } else { ec.EmitThis (); // // Special case for value type storey where this is not lifted but // droped off to parent class // for (var b = Block.Parent; b != null; b = b.Parent) { if (b.ParametersBlock.StateMachine != null) { ec.Emit (OpCodes.Ldfld, b.ParametersBlock.StateMachine.HoistedThis.Field.Spec); break; } } } var delegate_method = method.Spec; if (storey != null && storey.MemberName.IsGeneric) { TypeSpec t = storey.Instance.Type; // // Mutate anonymous method instance type if we are in nested // hoisted generic anonymous method storey // if (ec.IsAnonymousStoreyMutateRequired) { t = storey.Mutator.Mutate (t); } ec.Emit (OpCodes.Ldftn, TypeBuilder.GetMethod (t.GetMetaInfo (), (MethodInfo) delegate_method.GetMetaInfo ())); } else { if (delegate_method.IsGeneric) delegate_method = delegate_method.MakeGenericMethod (ec.MemberContext, method.TypeParameters); ec.Emit (OpCodes.Ldftn, delegate_method); } var constructor_method = Delegate.GetConstructor (type); ec.Emit (OpCodes.Newobj, constructor_method); if (am_cache != null) { ec.Emit (OpCodes.Stsfld, am_cache.Spec); ec.MarkLabel (l_initialized); ec.Emit (OpCodes.Ldsfld, am_cache.Spec); } }
public void EmitPredefined(EmitContext ec, MethodSpec method, Arguments Arguments) { 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); } // // 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); }