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 (); }
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)))); }
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; }
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; }
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)))); }
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; }