public BlockContext (IMemberContext mc, ExplicitBlock block, TypeSpec returnType) : base (mc) { if (returnType == null) throw new ArgumentNullException ("returnType"); this.return_type = returnType; // TODO: check for null value CurrentBlock = block; }
void FabricateBodyStatement () { // // Delegate obj1 = backing_field // do { // Delegate obj2 = obj1; // obj1 = Interlocked.CompareExchange (ref backing_field, Delegate.Combine|Remove(obj2, value), obj1); // } while ((object)obj1 != (object)obj2) // var field_info = ((EventField) method).backing_field; FieldExpr f_expr = new FieldExpr (field_info, Location); if (!IsStatic) f_expr.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location); var obj1 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location); var obj2 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location); block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (obj1, Location), f_expr))); var cond = new BooleanExpression (new Binary (Binary.Operator.Inequality, new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj1, Location), Location), new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj2, Location), Location))); var body = new ExplicitBlock (block, Location, Location); block.AddStatement (new Do (body, cond, Location, Location)); body.AddStatement (new StatementExpression ( new SimpleAssign (new LocalVariableReference (obj2, Location), new LocalVariableReference (obj1, Location)))); var args_oper = new Arguments (2); args_oper.Add (new Argument (new LocalVariableReference (obj2, Location))); args_oper.Add (new Argument (block.GetParameterReference (0, Location))); var op_method = GetOperation (Location); var args = new Arguments (3); args.Add (new Argument (f_expr, Argument.AType.Ref)); args.Add (new Argument (new Cast ( new TypeExpression (field_info.MemberType, Location), new Invocation (MethodGroupExpr.CreatePredefined (op_method, op_method.DeclaringType, Location), args_oper), Location))); args.Add (new Argument (new LocalVariableReference (obj1, Location))); var cas = Module.PredefinedMembers.InterlockedCompareExchange_T.Resolve (Location); if (cas == null) return; body.AddStatement (new StatementExpression (new SimpleAssign ( new LocalVariableReference (obj1, Location), new Invocation (MethodGroupExpr.CreatePredefined (cas, cas.DeclaringType, Location), args)))); }
public FieldInitializerContext (IMemberContext mc, BlockContext constructorContext) : base (mc, null, constructorContext.ReturnType) { flags |= Options.FieldInitializerScope | Options.ConstructorScope; this.ctor_block = constructorContext.CurrentBlock.Explicit; }
public FieldInitializerContext (IMemberContext mc, ResolveContext constructorContext) : base (mc, Options.FieldInitializerScope | Options.ConstructorScope) { this.ctor_block = constructorContext.CurrentBlock.Explicit; }
public Switch (Expression e, ExplicitBlock block, List<SwitchSection> sects, Location l) { Expr = e; this.block = block; Sections = sects; loc = l; }
// // Useful when TopLevel block is downgraded to normal block // public Block (ToplevelBlock parent, ToplevelBlock source) : this (parent, source.flags, source.StartLocation, source.EndLocation) { statements = source.statements; children = source.children; labels = source.labels; variables = source.variables; constants = source.constants; switch_block = source.switch_block; }
// // Creates a link between hoisted variable block and the anonymous method storey // // An anonymous method can reference variables from any outer block, but they are // hoisted in their own ExplicitBlock. When more than one block is referenced we // need to create another link between those variable storeys // public void AddReferenceFromChildrenBlock (ExplicitBlock block) { if (children_references == null) children_references = new List<ExplicitBlock> (); if (!children_references.Contains (block)) children_references.Add (block); }
public override void Emit() { var base_type = Parent.PartialContainer.BaseType; if (base_type != null && Block != null) { var base_dtor = MemberCache.FindMember (base_type, new MemberFilter (MetadataName, 0, MemberKind.Destructor, null, null), BindingRestriction.InstanceOnly) as MethodSpec; if (base_dtor == null) throw new NotImplementedException (); MethodGroupExpr method_expr = MethodGroupExpr.CreatePredefined (base_dtor, base_type, Location); method_expr.InstanceExpression = new BaseThis (base_type, Location); var try_block = new ExplicitBlock (block, block.StartLocation, block.EndLocation) { IsCompilerGenerated = true }; var finaly_block = new ExplicitBlock (block, Location, Location) { IsCompilerGenerated = true }; // // 0-size arguments to avoid CS0250 error // TODO: Should use AddScopeStatement or something else which emits correct // debugger scope // finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0)), Location.Null)); var tf = new TryFinally (try_block, finaly_block, Location); block.WrapIntoDestructor (tf, try_block); } base.Emit (); }
Method GenerateNumberMatcher () { var loc = Location; var parameters = ParametersCompiled.CreateFullyResolved ( new [] { new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, loc), "obj", 0, null, loc), new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, loc), "value", 0, null, loc), new Parameter (new TypeExpression (Compiler.BuiltinTypes.Bool, loc), "enumType", 0, null, loc), }, new [] { Compiler.BuiltinTypes.Object, Compiler.BuiltinTypes.Object, Compiler.BuiltinTypes.Bool }); var m = new Method (this, new TypeExpression (Compiler.BuiltinTypes.Bool, loc), Modifiers.PUBLIC | Modifiers.STATIC | Modifiers.DEBUGGER_HIDDEN, new MemberName ("NumberMatcher", loc), parameters, null); parameters [0].Resolve (m, 0); parameters [1].Resolve (m, 1); parameters [2].Resolve (m, 2); ToplevelBlock top_block = new ToplevelBlock (Compiler, parameters, loc); m.Block = top_block; // // if (enumType) // return Equals (obj, value); // var equals_args = new Arguments (2); equals_args.Add (new Argument (top_block.GetParameterReference (0, loc))); equals_args.Add (new Argument (top_block.GetParameterReference (1, loc))); var if_type = new If ( top_block.GetParameterReference (2, loc), new Return (new Invocation (new SimpleName ("Equals", loc), equals_args), loc), loc); top_block.AddStatement (if_type); // // if (obj is Enum || obj == null) // return false; // var if_enum = new If ( new Binary (Binary.Operator.LogicalOr, new Is (top_block.GetParameterReference (0, loc), new TypeExpression (Compiler.BuiltinTypes.Enum, loc), loc), new Binary (Binary.Operator.Equality, top_block.GetParameterReference (0, loc), new NullLiteral (loc))), new Return (new BoolLiteral (Compiler.BuiltinTypes, false, loc), loc), loc); top_block.AddStatement (if_enum); var system_convert = new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "Convert", loc); var expl_block = new ExplicitBlock (top_block, loc, loc); // // var converted = System.Convert.ChangeType (obj, System.Convert.GetTypeCode (value)); // var lv_converted = LocalVariable.CreateCompilerGenerated (Compiler.BuiltinTypes.Object, top_block, loc); var arguments_gettypecode = new Arguments (1); arguments_gettypecode.Add (new Argument (top_block.GetParameterReference (1, loc))); var gettypecode = new Invocation (new MemberAccess (system_convert, "GetTypeCode", loc), arguments_gettypecode); var arguments_changetype = new Arguments (1); arguments_changetype.Add (new Argument (top_block.GetParameterReference (0, loc))); arguments_changetype.Add (new Argument (gettypecode)); var changetype = new Invocation (new MemberAccess (system_convert, "ChangeType", loc), arguments_changetype); expl_block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (lv_converted, loc), changetype, loc))); // // return converted.Equals (value) // var equals_arguments = new Arguments (1); equals_arguments.Add (new Argument (top_block.GetParameterReference (1, loc))); var equals_invocation = new Invocation (new MemberAccess (new LocalVariableReference (lv_converted, loc), "Equals"), equals_arguments); expl_block.AddStatement (new Return (equals_invocation, loc)); var catch_block = new ExplicitBlock (top_block, loc, loc); catch_block.AddStatement (new Return (new BoolLiteral (Compiler.BuiltinTypes, false, loc), loc)); top_block.AddStatement (new TryCatch (expl_block, new List<Catch> () { new Catch (catch_block, loc) }, loc, false)); m.Define (); m.PrepareEmit (); AddMember (m); return m; }
public Block CreateSwitchBlock (Location start) { // FIXME: should this be implicit? Block new_block = new ExplicitBlock (this, start, start); new_block.switch_block = this; return new_block; }
public Block (Block parent, Flags flags, Location start, Location end) { if (parent != null) { parent.AddChild (this); // the appropriate constructors will fixup these fields Toplevel = parent.Toplevel; Explicit = parent.Explicit; } this.Parent = parent; this.flags = flags; this.StartLocation = start; this.EndLocation = end; this.loc = start; this_id = id++; statements = new List<Statement> (4); }
protected override bool CheckBase() { // Don't check base, the destructor has special syntax var base_type = Parent.PartialContainer.BaseType; if (base_type == null) return true; if (Block != null) { MethodGroupExpr method_expr = Expression.MethodLookup (Parent.Module.Compiler, Parent.Definition, base_type, MemberKind.Destructor, MetadataName, 0, Location); if (method_expr == null) throw new NotImplementedException (); method_expr.IsBase = true; method_expr.InstanceExpression = new CompilerGeneratedThis (Parent.Definition, Location); ToplevelBlock new_block = new ToplevelBlock (Compiler, Block.StartLocation); new_block.EndLocation = Block.EndLocation; Block finaly_block = new ExplicitBlock (new_block, Location, Location); Block try_block = new Block (new_block, block); // // 0-size arguments to avoid CS0250 error // TODO: Should use AddScopeStatement or something else which emits correct // debugger scope // finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0)))); new_block.AddStatement (new TryFinally (try_block, finaly_block, Location)); block = new_block; } return true; }
// // Initializes all hoisted variables // public void EmitStoreyInstantiation (EmitContext ec, ExplicitBlock block) { // There can be only one instance variable for each storey type if (Instance != null) throw new InternalErrorException (); SymbolWriter.OpenCompilerGeneratedBlock (ec); // // Create an instance of a storey // var storey_type_expr = CreateStoreyTypeExpression (ec); ResolveContext rc = new ResolveContext (ec.MemberContext); rc.CurrentBlock = block; Expression e = new New (storey_type_expr, null, Location).Resolve (rc); e.Emit (ec); Instance = new LocalTemporary (storey_type_expr.Type); Instance.Store (ec); EmitHoistedFieldsInitialization (rc, ec); SymbolWriter.DefineScopeVariable (ID, Instance.Builder); SymbolWriter.CloseCompilerGeneratedBlock (ec); }
void FabricateBodyStatement() { var cas = TypeManager.gen_interlocked_compare_exchange; if (cas == null) { var t = Module.PredefinedTypes.Interlocked.Resolve (Location); if (t == null) return; var p = new ParametersImported ( new[] { new ParameterData (null, Parameter.Modifier.REF), new ParameterData (null, Parameter.Modifier.NONE), new ParameterData (null, Parameter.Modifier.NONE) }, new[] { new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null), new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null), new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null), }, false); var filter = new MemberFilter ("CompareExchange", 1, MemberKind.Method, p, null); cas = TypeManager.gen_interlocked_compare_exchange = TypeManager.GetPredefinedMethod (t, filter, Location); } // // Delegate obj1 = backing_field // do { // Delegate obj2 = obj1; // obj1 = Interlocked.CompareExchange (ref backing_field, Delegate.Combine|Remove(obj2, value), obj1); // } while (obj1 != obj2) // var field_info = ((EventField) method).backing_field; FieldExpr f_expr = new FieldExpr (field_info, Location); if (!IsStatic) f_expr.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location); var obj1 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location); var obj2 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location); block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (obj1, Location), f_expr))); var cond = new BooleanExpression (new Binary (Binary.Operator.Inequality, new LocalVariableReference (obj1, Location), new LocalVariableReference (obj2, Location), Location)); var body = new ExplicitBlock (block, Location, Location); block.AddStatement (new Do (body, cond, Location)); body.AddStatement (new StatementExpression ( new SimpleAssign (new LocalVariableReference (obj2, Location), new LocalVariableReference (obj1, Location)))); var args_oper = new Arguments (2); args_oper.Add (new Argument (new LocalVariableReference (obj2, Location))); args_oper.Add (new Argument (block.GetParameterReference (0, Location))); var args = new Arguments (3); args.Add (new Argument (f_expr, Argument.AType.Ref)); args.Add (new Argument (new Cast ( new TypeExpression (field_info.MemberType, Location), new Invocation (MethodGroupExpr.CreatePredefined (Operation, Operation.DeclaringType, Location), args_oper), Location))); args.Add (new Argument (new LocalVariableReference (obj1, Location))); body.AddStatement (new StatementExpression (new SimpleAssign ( new LocalVariableReference (obj1, Location), new Invocation (MethodGroupExpr.CreatePredefined (cas, cas.DeclaringType, Location), args)))); }
public ExplicitBlock CreateSwitchBlock (Location start) { // FIXME: Only explicit block should be created var new_block = new ExplicitBlock (this, start, start); new_block.switch_block = Explicit; return new_block; }
public BlockContext (ResolveContext rc, ExplicitBlock block, TypeSpec returnType) : this (rc.MemberContext, block, returnType) { if (rc.IsUnsafe) flags |= ResolveContext.Options.UnsafeScope; if (rc.HasSet (ResolveContext.Options.CheckedScope)) flags |= ResolveContext.Options.CheckedScope; if (rc.IsInProbingMode) flags |= ResolveContext.Options.ProbingMode; if (rc.HasSet (ResolveContext.Options.FieldInitializerScope)) flags |= ResolveContext.Options.FieldInitializerScope; if (rc.HasSet (ResolveContext.Options.ExpressionTreeConversion)) flags |= ResolveContext.Options.ExpressionTreeConversion; if (rc.HasSet (ResolveContext.Options.BaseInitializer)) flags |= ResolveContext.Options.BaseInitializer; }
public BlockContext (ResolveContext rc, ExplicitBlock block, TypeSpec returnType) : this (rc.MemberContext, block, returnType) { if (rc.IsUnsafe) flags |= ResolveContext.Options.UnsafeScope; if (rc.HasSet (ResolveContext.Options.CheckedScope)) flags |= ResolveContext.Options.CheckedScope; }
public Block (Block parent, Flags flags, Location start, Location end) { if (parent != null) { // the appropriate constructors will fixup these fields ParametersBlock = parent.ParametersBlock; Explicit = parent.Explicit; } this.Parent = parent; this.flags = flags; this.StartLocation = start; this.EndLocation = end; this.loc = start; statements = new List<Statement> (4); this.original = this; }
public AnonymousMethodStorey (ExplicitBlock block, TypeDefinition parent, MemberBase host, TypeParameters tparams, string name, MemberKind kind) : base (parent, MakeMemberName (host, name, parent.Module.CounterAnonymousContainers, tparams, block.StartLocation), tparams, 0, kind) { OriginalSourceBlock = block; ID = parent.Module.CounterAnonymousContainers++; }
public void WrapIntoDestructor (TryFinally tf, ExplicitBlock tryBlock) { tryBlock.statements = statements; statements = new List<Statement> (1); statements.Add (tf); }
// // Initializes all hoisted variables // public void EmitStoreyInstantiation (EmitContext ec, ExplicitBlock block) { // There can be only one instance variable for each storey type if (Instance != null) throw new InternalErrorException (); // // Create an instance of this storey // ResolveContext rc = new ResolveContext (ec.MemberContext); rc.CurrentBlock = block; var storey_type_expr = CreateStoreyTypeExpression (ec); var source = new New (storey_type_expr, null, Location).Resolve (rc); // // When the current context is async (or iterator) lift local storey // instantiation to the currect storey // if (ec.CurrentAnonymousMethod is StateMachineInitializer && (block.HasYield || block.HasAwait)) { // // Unfortunately, normal capture mechanism could not be used because we are // too late in the pipeline and standart assign cannot be used either due to // recursive nature of GetStoreyInstanceExpression // var field = ec.CurrentAnonymousMethod.Storey.AddCompilerGeneratedField ( LocalVariable.GetCompilerGeneratedName (block), storey_type_expr, true); field.Define (); field.Emit (); var fexpr = new FieldExpr (field, Location); fexpr.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location); fexpr.EmitAssign (ec, source, false, false); Instance = fexpr; } else { var local = TemporaryVariableReference.Create (source.Type, block, Location); if (source.Type.IsStruct) { local.LocalInfo.CreateBuilder (ec); } else { local.EmitAssign (ec, source); } Instance = local; } EmitHoistedFieldsInitialization (rc, ec); // TODO: Implement properly //SymbolWriter.DefineScopeVariable (ID, Instance.Builder); }
protected override bool CheckBase () { flags |= MethodAttributes.Virtual; if (!base.CheckBase ()) return false; if (Parent.PartialContainer.BaseCache == null) return true; Type base_type = Parent.PartialContainer.BaseCache.Container.Type; if (base_type != null && Block != null) { MethodGroupExpr method_expr = Expression.MethodLookup (Parent.Module.Compiler, Parent.TypeBuilder, base_type, MetadataName, Location); if (method_expr == null) throw new NotImplementedException (); method_expr.IsBase = true; method_expr.InstanceExpression = new CompilerGeneratedThis (Parent.TypeBuilder, Location); ToplevelBlock new_block = new ToplevelBlock (Compiler, Block.StartLocation); new_block.EndLocation = Block.EndLocation; Block finaly_block = new ExplicitBlock (new_block, Location, Location); Block try_block = new Block (new_block, block); // // 0-size arguments to avoid CS0250 error // TODO: Should use AddScopeStatement or something else which emits correct // debugger scope // finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0)))); new_block.AddStatement (new TryFinally (try_block, finaly_block, Location)); block = new_block; } return true; }