Example #1
0
                public void Emit(IXamlIlEmitter emitter)
                {
                    var so     = _parent._config.WellKnownTypes.Object;
                    var method = _parent._avaloniaObject
                                 .FindMethod(m => m.IsPublic && !m.IsStatic && m.Name == "SetValue"
                                             &&
                                             m.Parameters.Count == 3 &&
                                             m.Parameters[0].Equals(_parent._avaloniaPropertyType) &&
                                             m.Parameters[1].Equals(so) &&
                                             m.Parameters[2].IsEnum
                                             );

                    if (method == null)
                    {
                        throw new XamlIlTypeSystemException(
                                  "Unable to find SetValue(AvaloniaProperty, object, BindingPriority) on AvaloniaObject");
                    }
                    using (var loc = emitter.LocalsPool.GetLocal(_parent.PropertyType))
                        emitter
                        .Stloc(loc.Local)
                        .Ldsfld(_parent._field)
                        .Ldloc(loc.Local);

                    if (_parent.PropertyType.IsValueType)
                    {
                        emitter.Box(_parent.PropertyType);
                    }
                    emitter
                    .Ldc_I4(0)
                    .EmitCall(method);
                }
            public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
            {
                var exts           = context.Configuration.TypeSystem.GetType("Avalonia.Controls.NameScopeExtensions");
                var findNameScope  = exts.FindMethod(m => m.Name == "FindNameScope");
                var registerMethod = findNameScope.ReturnType.FindMethod(m => m.Name == "Register");

                using (var targetLoc = context.GetLocal(context.Configuration.WellKnownTypes.Object))
                    using (var nameScopeLoc = context.GetLocal(findNameScope.ReturnType))
                    {
                        var exit = codeGen.DefineLabel();
                        codeGen
                        // var target = {pop}
                        .Stloc(targetLoc.Local)
                        // var scope = target.FindNameScope()
                        .Ldloc(targetLoc.Local)
                        .Castclass(findNameScope.Parameters[0])
                        .EmitCall(findNameScope)
                        .Stloc(nameScopeLoc.Local)
                        // if({scope} != null) goto call;
                        .Ldloc(nameScopeLoc.Local)
                        .Brfalse(exit)
                        .Ldloc(nameScopeLoc.Local);
                        context.Emit(Value, codeGen, Value.Type.GetClrType());
                        codeGen
                        .Ldloc(targetLoc.Local)
                        .EmitCall(registerMethod)
                        .MarkLabel(exit);
                    }
                return(XamlIlNodeEmitResult.Void(1));
            }
Example #3
0
File: Clr.cs Project: cm4ker/XamlIl
        public void Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen, bool swallowResult)
        {
            int firstCast = -1;

            for (var c = ParametersWithThis.Count - 1; c >= 0; c--)
            {
                if (!_method.ParametersWithThis[c].Equals(ParametersWithThis[c]))
                {
                    firstCast = c;
                }
            }

            if (firstCast != -1)
            {
                var locals = new Stack <XamlIlEmitContext.PooledLocal>();
                for (var c = ParametersWithThis.Count - 1; c >= firstCast; c--)
                {
                    codeGen.Castclass(ParametersWithThis[c]);
                    if (c > firstCast)
                    {
                        var l = context.GetLocal(ParametersWithThis[c]);
                        codeGen.Stloc(l.Local);
                        locals.Push(l);
                    }
                }

                while (locals.Count != 0)
                {
                    using (var l = locals.Pop())
                        codeGen.Ldloc(l.Local);
                }
            }

            _method.Emit(context, codeGen, swallowResult);
        }
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlObjectInitializationNode init))
            {
                return(null);
            }
            var supportInitType    = context.Configuration.TypeMappings.SupportInitialize;
            var supportsInitialize = supportInitType != null &&
                                     context.Configuration.TypeMappings.SupportInitialize
                                     .IsAssignableFrom(init.Type);

            if (supportsInitialize)
            {
                codeGen
                // We need a copy for/EndInit
                .Emit(OpCodes.Dup);
                if (!init.SkipBeginInit)
                {
                    codeGen
                    .Emit(OpCodes.Dup)
                    .EmitCall(supportInitType.FindMethod(m => m.Name == "BeginInit"));
                }
            }


            var addToParentStack = context.RuntimeContext.ParentListField != null &&
                                   !init.Type.IsValueType &&
                                   context.GetOrCreateItem <XamlIlNeedsParentStackCache>().NeedsParentStack(node);

            if (addToParentStack)
            {
                using (var local = context.GetLocal(init.Type))
                    codeGen
                    .Stloc(local.Local)
                    .Ldloc(context.ContextLocal)
                    .Ldloc(local.Local)
                    .EmitCall(context.RuntimeContext.PushParentMethod)
                    .Ldloc(local.Local);
            }

            context.Emit(init.Manipulation, codeGen, null);

            if (addToParentStack)
            {
                codeGen
                .Ldloc(context.ContextLocal)
                .EmitCall(context.RuntimeContext.PopParentMethod, true);
            }

            if (supportsInitialize)
            {
                codeGen
                .EmitCall(supportInitType.FindMethod(m => m.Name == "EndInit"));
            }


            return(XamlIlNodeEmitResult.Void(1));
        }
Example #5
0
 public override void Emit(IXamlIlEmitter emitter)
 {
     using (var bloc = emitter.LocalsPool.GetLocal(Types.IBinding))
         emitter
         .Stloc(bloc.Local)
         .Ldsfld(AvaloniaProperty)
         .Ldloc(bloc.Local)
         // TODO: provide anchor?
         .Ldnull();
     emitter.EmitCall(Types.AvaloniaObjectBindMethod, true);
 }
            public void Emit(IXamlIlEmitter emitter)
            {
                var locals = new Stack <XamlIlLocalsPool.PooledLocal>();

                // Save all "setter" parameters
                for (var c = Parameters.Count - 1; c >= 0; c--)
                {
                    var loc = emitter.LocalsPool.GetLocal(Parameters[c]);
                    locals.Push(loc);
                    emitter.Stloc(loc.Local);
                }

                emitter.EmitCall(_getter);
                while (locals.Count > 0)
                {
                    using (var loc = locals.Pop())
                        emitter.Ldloc(loc.Local);
                }
                emitter.EmitCall(_adder, true);
            }
Example #7
0
        public static void EmitConvert(XamlIlEmitContext context, IXamlIlEmitter ilgen, IXamlIlLineInfo node,
                                       IXamlIlType what,
                                       IXamlIlType to)
        {
            XamlIlLocalsPool.PooledLocal local = null;

            EmitConvert(context, node, what, to, lda =>
            {
                if (!lda)
                {
                    return(ilgen);
                }
                local = ilgen.LocalsPool.GetLocal(what);
                ilgen
                .Stloc(local.Local)
                .Ldloca(local.Local);
                return(ilgen);
            });
            local?.Dispose();
        }
Example #8
0
        public void EmitCall(IXamlIlEmitter codeGen)
        {
            int firstCast = -1;

            for (var c = Parameters.Count - 1; c >= 0; c--)
            {
                if (!_baseParametersWithThis[c].Equals(Parameters[c]))
                {
                    firstCast = c;
                }
            }

            if (firstCast != -1)
            {
                var locals = new Stack <XamlIlLocalsPool.PooledLocal>();
                for (var c = Parameters.Count - 1; c >= firstCast; c--)
                {
                    codeGen.Castclass(_baseParametersWithThis[c]);
                    if (c > firstCast)
                    {
                        var l = codeGen.LocalsPool.GetLocal(_baseParametersWithThis[c]);
                        codeGen.Stloc(l.Local);
                        locals.Push(l);
                    }
                }

                while (locals.Count != 0)
                {
                    using (var l = locals.Pop())
                    {
                        codeGen.Ldloc(l.Local);
                        l.Dispose();
                    }
                }
            }

            codeGen.EmitCall(_method);
        }
Example #9
0
        public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            var scopeField = context.RuntimeContext.ContextType.Fields.First(f =>
                                                                             f.Name == AvaloniaXamlIlLanguage.ContextNameScopeFieldName);

            using (var targetLoc = context.GetLocal(context.Configuration.WellKnownTypes.Object))
            {
                codeGen
                // var target = {pop}
                .Stloc(targetLoc.Local)
                // _context.NameScope.Register(Name, target)
                .Ldloc(context.ContextLocal)
                .Ldfld(scopeField);

                context.Emit(Name, codeGen, Name.Type.GetClrType());

                codeGen
                .Ldloc(targetLoc.Local)
                .EmitCall(_types.INameScopeRegister, true);
            }

            return(XamlIlNodeEmitResult.Void(1));
        }
Example #10
0
        private XamlIlNodeEmitResult EmitCore(IXamlIlAstNode value, IXamlIlEmitter codeGen, IXamlIlType expectedType)
        {
            CheckingIlEmitter parent         = null;
            CheckingIlEmitter checkedEmitter = null;

            if (EnableIlVerification)
            {
                parent = codeGen as CheckingIlEmitter;

                parent?.Pause();
                checkedEmitter = new CheckingIlEmitter(codeGen);
            }
#if XAMLIL_DEBUG
            var res = EmitNode(value, checkedEmitter);
#else
            XamlIlNodeEmitResult res;
            try
            {
                res = EmitNode(value, checkedEmitter ?? codeGen);
            }
            catch (Exception e) when(!(e is XmlException))
            {
                throw new XamlIlLoadException(
                          "Internal compiler error while emitting node " + value + ":\n" + e, value);
            }
#endif
            if (EnableIlVerification)
            {
                var expectedBalance = res.ProducedItems - res.ConsumedItems;
                var checkResult     =
                    checkedEmitter.Check(res.ProducedItems - res.ConsumedItems, false);
                if (checkResult != null)
                {
                    throw new XamlIlLoadException($"Error during IL verification: {checkResult}\n{checkedEmitter}\n",
                                                  value);
                }
                parent?.Resume();
                parent?.ExplicitStack(expectedBalance);
            }

            var returnedType = res.ReturnType;

            if (returnedType != null || expectedType != null)
            {
                if (returnedType != null && expectedType == null)
                {
                    throw new XamlIlLoadException(
                              $"Emit of node {value} resulted in {returnedType.GetFqn()} while caller expected void", value);
                }

                if (expectedType != null && returnedType == null)
                {
                    throw new XamlIlLoadException(
                              $"Emit of node {value} resulted in void while caller expected {expectedType.GetFqn()}", value);
                }

                if (!returnedType.Equals(expectedType))
                {
                    XamlIlLocalsPool.PooledLocal local = null;
                    // ReSharper disable once ExpressionIsAlwaysNull
                    // Value is assigned inside the closure in certain conditions

                    TypeSystemHelpers.EmitConvert(this, value, returnedType, expectedType, ldaddr =>
                    {
                        if (ldaddr && returnedType.IsValueType)
                        {
                            // We need to store the value to a temporary variable, since *address*
                            // is required (probably for  method call on the value type)
                            local = GetLocal(returnedType);
                            codeGen
                            .Stloc(local.Local)
                            .Ldloca(local.Local);
                        }
                        // Otherwise do nothing, value is already at the top of the stack
                        return(codeGen);
                    });
                    local?.Dispose();
                }
            }


            return(res);
        }
Example #11
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlObjectInitializationNode init))
            {
                return(null);
            }
            var supportInitType    = context.Configuration.TypeMappings.SupportInitialize;
            var supportsInitialize = supportInitType != null &&
                                     context.Configuration.TypeMappings.SupportInitialize
                                     .IsAssignableFrom(init.Type);

            if (supportsInitialize)
            {
                codeGen
                // We need a copy for/EndInit
                .Emit(OpCodes.Dup);
                if (!init.SkipBeginInit)
                {
                    codeGen
                    .Emit(OpCodes.Dup)
                    .EmitCall(supportInitType.FindMethod(m => m.Name == "BeginInit"));
                }
            }

            IXamlIlType objectListType   = null;
            var         addToParentStack = context.RuntimeContext.ParentListField != null &&
                                           !init.Type.IsValueType &&
                                           context.GetOrCreateItem <XamlIlNeedsParentStackCache>().NeedsParentStack(node);

            if (addToParentStack)
            {
                objectListType = context.Configuration.TypeSystem.GetType("System.Collections.Generic.List`1")
                                 .MakeGenericType(new[] { context.Configuration.WellKnownTypes.Object });

                using (var local = context.GetLocal(init.Type))
                    codeGen
                    .Stloc(local.Local)
                    .Ldloc(context.ContextLocal).Ldfld(context.RuntimeContext.ParentListField)
                    .Ldloc(local.Local)
                    .EmitCall(objectListType.FindMethod("Add", context.Configuration.WellKnownTypes.Void,
                                                        false, context.Configuration.WellKnownTypes.Object))
                    .Ldloc(local.Local);
            }

            context.Emit(init.Manipulation, codeGen, null);

            if (addToParentStack)
            {
                codeGen
                .Ldloc(context.ContextLocal).Ldfld(context.RuntimeContext.ParentListField)
                .Ldloc(context.ContextLocal).Ldfld(context.RuntimeContext.ParentListField)
                .EmitCall(objectListType.FindMethod(m => m.Name == "get_Count"))
                .Ldc_I4(1).Emit(OpCodes.Sub)
                .EmitCall(objectListType.FindMethod(m => m.Name == "RemoveAt"));
            }

            if (supportsInitialize)
            {
                codeGen
                .EmitCall(supportInitType.FindMethod(m => m.Name == "EndInit"));
            }


            return(XamlIlNodeEmitResult.Void(1));
        }