コード例 #1
0
ファイル: CheckingIlEmitter.cs プロジェクト: OmniUI/XamlIl2
        public IXamlIlLabel DefineLabel()
        {
            var label = _inner.DefineLabel();

            _unmarkedLabels.Add(label, null);//, Environment.StackTrace);
            return(label);
        }
コード例 #2
0
            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));
            }
コード例 #3
0
            public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
            {
                var next       = codeGen.DefineLabel();
                var scopeField = context.RuntimeContext.ContextType.Fields.First(f =>
                                                                                 f.Name == AvaloniaXamlIlLanguage.ContextNameScopeFieldName);

                using (var local = codeGen.LocalsPool.GetLocal(_types.StyledElement))
                {
                    codeGen
                    .Isinst(_types.StyledElement)
                    .Dup()
                    .Stloc(local.Local)
                    .Brfalse(next)
                    .Ldloc(local.Local)
                    .Ldloc(context.ContextLocal)
                    .Ldfld(scopeField)
                    .EmitCall(_types.NameScopeSetNameScope, true)
                    .MarkLabel(next)
                    .Ldloc(context.ContextLocal)
                    .Ldfld(scopeField)
                    .EmitCall(_types.INameScopeComplete, true);
                }

                return(XamlIlNodeEmitResult.Void(1));
            }
コード例 #4
0
        public IXamlIlLabel DefineLabel()
        {
            var label = _inner.DefineLabel();

            _labels[label] = new LabelInfo();
            return(label);
        }
コード例 #5
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlPropertyAssignmentNode an))
            {
                return(null);
            }

            var setters = ValidateAndGetSetters(an);

            for (var c = 0; c < an.Values.Count - 1; c++)
            {
                context.Emit(an.Values[c], codeGen, an.Values[c].Type.GetClrType());
            }

            var value = an.Values.Last();

            var isValueType = value.Type.GetClrType().IsValueType;

            // If there is only one available setter or if value is a value type, always use the first one
            if (setters.Count == 1 || isValueType)
            {
                var setter = an.PossibleSetters.First();
                context.Emit(value, codeGen, setter.Parameters.Last());
                setter.Emit(codeGen);
            }
            else
            {
                var          checkedTypes = new List <IXamlIlType>();
                IXamlIlLabel exit         = codeGen.DefineLabel();
                IXamlIlLabel next         = null;
                var          hadJumps     = false;
                context.Emit(value, codeGen, value.Type.GetClrType());

                foreach (var setter in setters)
                {
                    var type = setter.Parameters.Last();

                    // We have already checked this type or its base type
                    if (checkedTypes.Any(ch => ch.IsAssignableFrom(type)))
                    {
                        continue;
                    }

                    if (next != null)
                    {
                        codeGen.MarkLabel(next);
                        next = null;
                    }

                    IXamlIlLabel Next() => next ?? (next = codeGen.DefineLabel());

                    var checkNext = false;
                    if (setter.BinderParameters.AllowRuntimeNull)
                    {
                        checkedTypes.Add(type);
                    }
                    else
                    {
                        // Check for null; Also don't add this type to the list of checked ones because of the null check
                        codeGen
                        .Dup()
                        .Brfalse(Next());
                        checkNext = true;
                    }

                    // Only do dynamic checks if we know that type is not assignable by downcast
                    if (!type.IsAssignableFrom(value.Type.GetClrType()))
                    {
                        codeGen
                        .Dup()
                        .Isinst(type)
                        .Brfalse(Next());
                        checkNext = true;
                    }

                    if (checkNext)
                    {
                        hadJumps = true;
                    }

                    TypeSystemHelpers.EmitConvert(context, codeGen, value, value.Type.GetClrType(), type);
                    setter.Emit(codeGen);
                    if (hadJumps)
                    {
                        codeGen.Br(exit);
                    }

                    if (!checkNext)
                    {
                        break;
                    }
                }

                if (next != null)
                {
                    codeGen.MarkLabel(next);

                    if (setters.Any(x => !x.BinderParameters.AllowRuntimeNull))
                    {
                        next = codeGen.DefineLabel();
                        codeGen
                        .Dup()
                        .Brtrue(next)
                        .Newobj(context.Configuration.TypeSystem.GetType("System.NullReferenceException")
                                .FindConstructor())
                        .Throw();
                        codeGen.MarkLabel(next);
                    }

                    codeGen
                    .Newobj(context.Configuration.TypeSystem.GetType("System.InvalidCastException")
                            .FindConstructor())
                    .Throw();
                }

                codeGen.MarkLabel(exit);
            }

            return(XamlIlNodeEmitResult.Void(1));
        }