public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound) { throw new NotImplementedException (); }
public override void EmitStatement (EmitContext ec) { EmitCall (ec, binder_expr, arguments, true); }
// // Emits a list of resolved Arguments // public void Emit (EmitContext ec) { Emit (ec, false, false); }
/// <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, 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 void EmitAssign (EmitContext ec) { ec.EmitArgumentStore (idx); }
public void EmitToVariable (EmitContext ec) { var type = Expr.Type; if (IsByRef) { var ml = (IMemoryLocation) Expr; ml.AddressOf (ec, AddressOp.LoadStore); type = ReferenceContainer.MakeType (ec.Module, type); } else { Expr.Emit (ec); } variable = new LocalTemporary (type); variable.Store (ec); Expr = variable; }
public void EmitPrologue(EmitContext ec) { awaiter = ((AsyncTaskStorey)machine_initializer.Storey).AddAwaiter(expr.Type, loc); var fe_awaiter = new FieldExpr(awaiter, loc); fe_awaiter.InstanceExpression = new CompilerGeneratedThis(ec.CurrentType, loc); // // awaiter = expr.GetAwaiter (); // using (ec.With(BuilderContext.Options.OmitDebugInfo, true)) { fe_awaiter.EmitAssign(ec, expr, false, false); } Label skip_continuation = ec.DefineLabel(); Expression completed_expr; if (IsDynamic) { var rc = new ResolveContext(ec.MemberContext); Arguments dargs = new Arguments(1); dargs.Add(new Argument(fe_awaiter)); completed_expr = new DynamicMemberBinder("IsCompleted", dargs, loc).Resolve(rc); dargs = new Arguments(1); dargs.Add(new Argument(completed_expr)); completed_expr = new DynamicConversion(ec.Module.Compiler.BuiltinTypes.Bool, 0, dargs, loc).Resolve(rc); } else { var pe = PropertyExpr.CreatePredefined(awaiter_definition.IsCompleted, loc); pe.InstanceExpression = fe_awaiter; completed_expr = pe; } completed_expr.EmitBranchable(ec, skip_continuation, true); base.DoEmit(ec); // // The stack has to be empty before calling await continuation. We handle this // by lifting values which would be left on stack into class fields. The process // is quite complicated and quite hard to test because any expression can possibly // leave a value on the stack. // // Following assert fails when some of expression called before is missing EmitToField // or parent expression fails to find await in children expressions // ec.AssertEmptyStack(); var storey = (AsyncTaskStorey)machine_initializer.Storey; if (IsDynamic) { storey.EmitAwaitOnCompletedDynamic(ec, fe_awaiter); } else { storey.EmitAwaitOnCompleted(ec, fe_awaiter); } // Return ok machine_initializer.EmitLeave(ec, unwind_protect); ec.MarkLabel(resume_point); ec.MarkLabel(skip_continuation); }
public void Emit (EmitContext ec, bool leave_copy) { throw new NotImplementedException (); }
public override Expression EmitToField(EmitContext ec) { return(this); }
protected override void DoEmit(EmitContext ec) { GetResultExpression(ec).Emit(ec); }
public override void EmitStatement(EmitContext ec) { stmt.EmitStatement(ec); }
public void EmitAssign(EmitContext ec, FieldExpr field) { stmt.EmitPrologue(ec); field.InstanceExpression.Emit(ec); stmt.Emit(ec); }
public override Expression EmitToField(EmitContext ec) { stmt.EmitPrologue(ec); return(stmt.GetResultExpression(ec)); }
public override void Emit (EmitContext ec) { var rc = new ResolveContext (ec.MemberContext); var expr = new Conditional (new BooleanExpression (condition), invoke, assign, loc).Resolve (rc); expr.Emit (ec); }
public override void Emit(EmitContext ec) { throw new NotImplementedException(); }
public override void EmitStatement (EmitContext ec) { flags |= CSharpBinderFlags.ResultDiscarded; base.EmitStatement (ec); }
protected override void EmitMoveNextEpilogue(EmitContext ec) { var storey = (AsyncTaskStorey)Storey; storey.EmitSetResult(ec); }
public void AddressOf (EmitContext ec, AddressOp mode) { throw new NotImplementedException (); }
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 IExpressionCleanup.EmitCleanup(EmitContext ec) { EmitAssign(ec, new NullConstant(type, loc), false, false); }
protected override void DoEmit (EmitContext ec) { }
public override Arguments Emit (EmitContext ec, bool dup_args, bool prepareAwait) { foreach (var a in ordered) { if (prepareAwait) a.EmitToField (ec, false); else a.EmitToVariable (ec); } return base.Emit (ec, dup_args, prepareAwait); }
public override void Emit (EmitContext ec) { }
// // if `dup_args' is true or any of arguments contains await. // A copy of all arguments will be returned to the caller // public virtual Arguments Emit (EmitContext ec, bool dup_args, bool prepareAwait) { List<Argument> dups; if ((dup_args && Count != 0) || prepareAwait) dups = new List<Argument> (Count); else dups = null; LocalTemporary lt; foreach (Argument a in args) { if (prepareAwait) { dups.Add (a.EmitToField (ec, true)); continue; } a.Emit (ec); if (!dup_args) { continue; } if (a.Expr.IsSideEffectFree) { // // No need to create a temporary variable for side effect free expressions. I assume // all side-effect free expressions are cheap, this has to be tweaked when we become // more aggressive on detection // dups.Add (a); } else { ec.Emit (OpCodes.Dup); // TODO: Release local temporary on next Emit // Need to add a flag to argument to indicate this lt = new LocalTemporary (a.Type); lt.Store (ec); dups.Add (new Argument (lt, a.ArgType)); } } if (dups != null) return new Arguments (dups); return null; }
// public override void EmitJs (JsEmitContext jec) // { // } protected override void DoEmit (EmitContext ec) { throw new NotSupportedException (); }
public override void Emit (EmitContext ec) { throw new NotImplementedException (); }
protected override void DoEmit (EmitContext ec) { if (!expr.IsSideEffectFree) { expr.EmitSideEffect (ec); } }
public override void Emit (EmitContext ec) { EmitCall (ec, binder_expr, arguments, false); }
public override void EmitStatement (EmitContext ec) { throw new System.NotImplementedException (); }
protected void EmitCall (EmitContext ec, Expression binder, Arguments arguments, bool isStatement) { // // This method generates all internal infrastructure for a dynamic call. The // reason why it's quite complicated is the mixture of dynamic and anonymous // methods. Dynamic itself requires a temporary class (ContainerX) and anonymous // methods can generate temporary storey as well (AnonStorey). Handling MVAR // type parameters rewrite is non-trivial in such case as there are various // combinations possible therefore the mutator is not straightforward. Secondly // we need to keep both MVAR(possibly VAR for anon storey) and type VAR to emit // correct Site field type and its access from EmitContext. // int dyn_args_count = arguments == null ? 0 : arguments.Count; int default_args = isStatement ? 1 : 2; var module = ec.Module; bool has_ref_out_argument = false; var targs = new TypeExpression[dyn_args_count + default_args]; targs[0] = new TypeExpression (module.PredefinedTypes.CallSite.TypeSpec, loc); TypeExpression[] targs_for_instance = null; TypeParameterMutator mutator; var site_container = ec.CreateDynamicSite (); if (context_mvars != null) { TypeParameters tparam; TypeContainer sc = site_container; do { tparam = sc.CurrentTypeParameters; sc = sc.Parent; } while (tparam == null); mutator = new TypeParameterMutator (context_mvars, tparam); if (!ec.IsAnonymousStoreyMutateRequired) { targs_for_instance = new TypeExpression[targs.Length]; targs_for_instance[0] = targs[0]; } } else { mutator = null; } for (int i = 0; i < dyn_args_count; ++i) { Argument a = arguments[i]; if (a.ArgType == Argument.AType.Out || a.ArgType == Argument.AType.Ref) has_ref_out_argument = true; var t = a.Type; // Convert any internal type like dynamic or null to object if (t.Kind == MemberKind.InternalCompilerType) t = ec.BuiltinTypes.Object; if (targs_for_instance != null) targs_for_instance[i + 1] = new TypeExpression (t, loc); if (mutator != null) t = t.Mutate (mutator); targs[i + 1] = new TypeExpression (t, loc); } TypeExpr del_type = null; TypeExpr del_type_instance_access = null; if (!has_ref_out_argument) { string d_name = isStatement ? "Action" : "Func"; TypeExpr te = null; Namespace type_ns = module.GlobalRootNamespace.GetNamespace ("System", true); if (type_ns != null) { te = type_ns.LookupType (module, d_name, dyn_args_count + default_args, LookupMode.Normal, loc); } if (te != null) { if (!isStatement) { var t = type; if (t.Kind == MemberKind.InternalCompilerType) t = ec.BuiltinTypes.Object; if (targs_for_instance != null) targs_for_instance[targs_for_instance.Length - 1] = new TypeExpression (t, loc); if (mutator != null) t = t.Mutate (mutator); targs[targs.Length - 1] = new TypeExpression (t, loc); } del_type = new GenericTypeExpr (te.Type, new TypeArguments (targs), loc); if (targs_for_instance != null) del_type_instance_access = new GenericTypeExpr (te.Type, new TypeArguments (targs_for_instance), loc); else del_type_instance_access = del_type; } } // // Create custom delegate when no appropriate predefined delegate has been found // Delegate d; if (del_type == null) { TypeSpec rt = isStatement ? ec.BuiltinTypes.Void : type; Parameter[] p = new Parameter[dyn_args_count + 1]; p[0] = new Parameter (targs[0], "p0", Parameter.Modifier.NONE, null, loc); var site = ec.CreateDynamicSite (); int index = site.Containers == null ? 0 : site.Containers.Count; if (mutator != null) rt = mutator.Mutate (rt); for (int i = 1; i < dyn_args_count + 1; ++i) { p[i] = new Parameter (targs[i], "p" + i.ToString ("X"), arguments[i - 1].Modifier, null, loc); } d = new Delegate (site, new TypeExpression (rt, loc), Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED, new MemberName ("Container" + index.ToString ("X")), new ParametersCompiled (p), null); d.CreateContainer (); d.DefineContainer (); d.Define (); site.AddTypeContainer (d); del_type = new TypeExpression (d.CurrentType, loc); if (targs_for_instance != null) { del_type_instance_access = null; } else { del_type_instance_access = del_type; } } else { d = null; } var site_type_decl = new GenericTypeExpr (module.PredefinedTypes.CallSiteGeneric.TypeSpec, new TypeArguments (del_type), loc); var field = site_container.CreateCallSiteField (site_type_decl, loc); if (field == null) return; if (del_type_instance_access == null) { var dt = d.CurrentType.DeclaringType.MakeGenericType (module, context_mvars.Types); del_type_instance_access = new TypeExpression (MemberCache.GetMember (dt, d.CurrentType), loc); } var instanceAccessExprType = new GenericTypeExpr (module.PredefinedTypes.CallSiteGeneric.TypeSpec, new TypeArguments (del_type_instance_access), loc); if (instanceAccessExprType.ResolveAsType (ec.MemberContext) == null) return; bool inflate_using_mvar = context_mvars != null && ec.IsAnonymousStoreyMutateRequired; TypeSpec gt; if (inflate_using_mvar || context_mvars == null) { gt = site_container.CurrentType; } else { gt = site_container.CurrentType.MakeGenericType (module, context_mvars.Types); } // When site container already exists the inflated version has to be // updated manually to contain newly created field if (gt is InflatedTypeSpec && site_container.AnonymousMethodsCounter > 1) { var tparams = gt.MemberDefinition.TypeParametersCount > 0 ? gt.MemberDefinition.TypeParameters : TypeParameterSpec.EmptyTypes; var inflator = new TypeParameterInflator (module, gt, tparams, gt.TypeArguments); gt.MemberCache.AddMember (field.InflateMember (inflator)); } FieldExpr site_field_expr = new FieldExpr (MemberCache.GetMember (gt, field), loc); BlockContext bc = new BlockContext (ec.MemberContext, null, ec.BuiltinTypes.Void); Arguments args = new Arguments (1); args.Add (new Argument (binder)); StatementExpression s = new StatementExpression (new SimpleAssign (site_field_expr, new Invocation (new MemberAccess (instanceAccessExprType, "Create"), args))); using (ec.With (BuilderContext.Options.OmitDebugInfo, true)) { if (s.Resolve (bc)) { Statement init = new If (new Binary (Binary.Operator.Equality, site_field_expr, new NullLiteral (loc)), s, loc); init.Emit (ec); } args = new Arguments (1 + dyn_args_count); args.Add (new Argument (site_field_expr)); if (arguments != null) { int arg_pos = 1; foreach (Argument a in arguments) { if (a is NamedArgument) { // Name is not valid in this context args.Add (new Argument (a.Expr, a.ArgType)); } else { args.Add (a); } if (inflate_using_mvar && a.Type != targs[arg_pos].Type) a.Expr.Type = targs[arg_pos].Type; ++arg_pos; } } Expression target = new DelegateInvocation (new MemberAccess (site_field_expr, "Target", loc).Resolve (bc), args, loc).Resolve (bc); if (target != null) target.Emit (ec); } }
public override void Emit (EmitContext ec) { throw new NotSupportedException (); }
public override void EmitStatement (EmitContext ec) { var stmt = new If (condition, new StatementExpression (invoke), new StatementExpression (assign), loc); using (ec.With (BuilderContext.Options.OmitDebugInfo, true)) { stmt.Emit (ec); } }
public override void Emit (EmitContext ec) { throw new InternalErrorException ("Missing Resolve call"); }
public override void EmitStatement (EmitContext ec) { // It's null for ResolveLValue used without assignment if (binder_expr == null) EmitCall (ec, setter, Arguments, true); else base.EmitStatement (ec); }
public virtual void Emit (EmitContext ec) { if (!IsByRef) { Expr.Emit (ec); return; } AddressOp mode = AddressOp.Store; if (ArgType == AType.Ref) mode |= AddressOp.Load; IMemoryLocation ml = (IMemoryLocation) Expr; ml.AddressOf (ec, mode); }
public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound) { EmitCall (ec, setter, setter_args, !leave_copy); }
public Argument EmitToField (EmitContext ec, bool cloneResult) { var res = Expr.EmitToField (ec); if (cloneResult && res != Expr) return new Argument (res, ArgType); Expr = res; return this; }
public void Emit (EmitContext ec) { ec.EmitArgumentLoad (idx); }
public override void Emit (EmitContext ec) { // TODO: Should guard against multiple emits base.Emit (ec); // Release temporary variable when used if (variable != null) variable.Release (ec); }
public void EmitAddressOf (EmitContext ec) { if ((ModFlags & Modifier.RefOutMask) != 0) { ec.EmitArgumentLoad (idx); } else { ec.EmitArgumentAddress (idx); } }
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); }