コード例 #1
0
        public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            var type   = TargetType.GetClrType();
            var member = ResolveMember(type);

            if (member is IXamlIlProperty prop)
            {
                codeGen.Emit(OpCodes.Call, prop.Getter);
                return(XamlIlNodeEmitResult.Type(0, prop.Getter.ReturnType));
            }
            else if (member is IXamlIlField field)
            {
                if (field.IsLiteral)
                {
                    TypeSystemHelpers.EmitFieldLiteral(field, codeGen);
                }
                else
                {
                    codeGen.Emit(OpCodes.Ldsfld, field);
                }
                return(XamlIlNodeEmitResult.Type(0, field.FieldType));
            }
            else
            {
                throw new XamlIlLoadException(
                          $"Unable to resolve {Member} as static field, property, constant or enum value", this);
            }
        }
コード例 #2
0
        public static void EmitFieldLiteral(IXamlIlField field, IXamlIlEmitter codeGen)
        {
            var ftype = field.FieldType.IsEnum ? field.FieldType.GetEnumUnderlyingType() : field.FieldType;

            if (ftype.Name == "UInt64" || ftype.Name == "Int64")
            {
                codeGen.Emit(OpCodes.Ldc_I8,
                             TypeSystemHelpers.ConvertLiteralToLong(field.GetLiteralValue()));
            }
            else if (ftype.Name == "Double")
            {
                codeGen.Emit(OpCodes.Ldc_R8, (double)field.GetLiteralValue());
            }
            else if (ftype.Name == "Single")
            {
                codeGen.Emit(OpCodes.Ldc_R4, (float)field.GetLiteralValue());
            }
            else if (ftype.Name == "String")
            {
                codeGen.Emit(OpCodes.Ldstr, (string)field.GetLiteralValue());
            }
            else
            {
                codeGen.Emit(OpCodes.Ldc_I4,
                             TypeSystemHelpers.ConvertLiteralToInt(field.GetLiteralValue()));
            }
        }
コード例 #3
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"));
                }
            }


            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));
        }
コード例 #4
0
ファイル: TypeSystem.cs プロジェクト: zawodskoj/XamlIl
 public static IXamlIlEmitter DebugHatch(this IXamlIlEmitter emitter, string message)
 {
     #if DEBUG
     var debug = emitter.TypeSystem.GetType("XamlIl.XamlIlDebugHatch").FindMethod(m => m.Name == "Debug");
     emitter.Emit(OpCodes.Ldstr, message);
     emitter.Emit(OpCodes.Call, debug);
     #endif
     return(emitter);
 }
コード例 #5
0
ファイル: TypeSystem.cs プロジェクト: cm4ker/XamlIl
 public static IXamlIlEmitter EmitCall(this IXamlIlEmitter emitter, IXamlIlMethod method, bool swallowResult = false)
 {
     emitter.Emit(method.IsStatic ? OpCodes.Call : OpCodes.Callvirt, method);
     if (swallowResult && !(method.ReturnType.Namespace == "System" && method.ReturnType.Name == "Void"))
     {
         emitter.Emit(OpCodes.Pop);
     }
     return(emitter);
 }
コード例 #6
0
ファイル: XamlIlCompiler.cs プロジェクト: cm4ker/XamlIl
        /// <summary>
        /// void Populate(IServiceProvider sp, T target);
        /// </summary>

        void CompilePopulate(IXamlIlAstManipulationNode manipulation, Func <string, IXamlIlType, IXamlIlTypeBuilder> createSubType, IXamlIlEmitter codeGen, XamlIlContext context)
        {
            var emitContext = InitCodeGen(createSubType, codeGen, context, true);

            codeGen
            .Emit(OpCodes.Ldloc, emitContext.ContextLocal)
            .Emit(OpCodes.Ldarg_1)
            .Emit(OpCodes.Stfld, context.RootObjectField)
            .Emit(OpCodes.Ldarg_1);
            emitContext.Emit(manipulation, codeGen, null);
            codeGen.Emit(OpCodes.Ret);
        }
コード例 #7
0
ファイル: NewObjectEmitter.cs プロジェクト: cm4ker/XamlIl
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlAstNewClrObjectNode n))
            {
                return(null);
            }

            var type = n.Type.GetClrType();
            var ctor = n.Constructor ?? type.FindConstructor();

            if (ctor == null)
            {
                throw new XamlIlLoadException("Unable to find default constructor and no non-default one is specified",
                                              n);
            }

            for (var c = 0; c < n.Arguments.Count; c++)
            {
                context.Emit(n.Arguments[c], codeGen, ctor.Parameters[c]);
            }

            var gen = codeGen
                      .Emit(OpCodes.Newobj, ctor);


            return(XamlIlNodeEmitResult.Type(0, type));
        }
コード例 #8
0
 public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
 {
     // Discard the stack value we are "supposed" to manipulate
     codeGen.Emit(OpCodes.Pop);
     context.Emit(Imperative, codeGen, null);
     return(XamlIlNodeEmitResult.Void(1));
 }
コード例 #9
0
        /// <summary>
        /// void Populate(IServiceProvider sp, T target);
        /// </summary>

        void CompilePopulate(IFileSource fileSource, IXamlIlAstManipulationNode manipulation, Func <string, IXamlIlType, IXamlIlTypeBuilder> createSubType, IXamlIlEmitter codeGen, XamlIlContext context)
        {
            // Uncomment to inspect generated IL in debugger
            //codeGen = new RecordingIlEmitter(codeGen);
            var emitContext = InitCodeGen(fileSource, createSubType, codeGen, context, true);

            codeGen
            .Emit(OpCodes.Ldloc, emitContext.ContextLocal)
            .Emit(OpCodes.Ldarg_1)
            .Emit(OpCodes.Stfld, context.RootObjectField)
            .Emit(OpCodes.Ldloc, emitContext.ContextLocal)
            .Emit(OpCodes.Ldarg_1)
            .Emit(OpCodes.Stfld, context.IntermediateRootObjectField)
            .Emit(OpCodes.Ldarg_1);
            emitContext.Emit(manipulation, codeGen, null);
            codeGen.Emit(OpCodes.Ret);
        }
コード例 #10
0
ファイル: CompilerHelpers.cs プロジェクト: OmniUI/XamlIl2
        public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            var rv = context.Emit(Value, codeGen, Local.Type);

            codeGen.Emit(OpCodes.Dup);
            context.StLocal(Local, codeGen);
            return(XamlIlNodeEmitResult.Type(0, rv.ReturnType));
        }
コード例 #11
0
        public void StLocal(XamlIlAstCompilerLocalNode node, IXamlIlEmitter codeGen)
        {
            if (!_locals.TryGetValue(node, out var local))
            {
                _locals[node] = local = codeGen.DefineLocal(node.Type);
            }

            codeGen.Emit(OpCodes.Stloc, local);
        }
コード例 #12
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlPropertyAssignmentNode an))
                return null;
            var callOp = an.Property.Setter.IsStatic ? OpCodes.Call : OpCodes.Callvirt;
            context.Emit(an.Value, codeGen, an.Property.Setter.Parameters.Last());
            codeGen.Emit(callOp, an.Property.Setter);

            return XamlIlNodeEmitResult.Void(1);
        }
コード例 #13
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter ilgen)
        {
            if (!(node is XamlIlMarkupExtensionNode me))
            {
                return(null);
            }
            XamlIlNeedsParentStackCache.Verify(context, node);

            var prop = context.ParentNodes().OfType <XamlIlPropertyAssignmentNode>().FirstOrDefault();

            var needProvideValueTarget = me.ProvideValue.Parameters.Count != 0 &&
                                         context.RuntimeContext.PropertyTargetObject != null &&
                                         prop != null;

            void EmitPropertyDescriptor()
            {
                if (context.Configuration.TypeMappings.ProvideValueTargetPropertyEmitter
                    ?.Invoke(context, ilgen, prop.Property) == true)
                {
                    return;
                }
                ilgen.Ldstr(prop.Property.Name);
            }

            context.Emit(me.Value, ilgen, me.Value.Type.GetClrType());

            if (me.ProvideValue.Parameters.Count > 0)
            {
                ilgen
                .Emit(OpCodes.Ldloc, context.ContextLocal);
            }

            if (needProvideValueTarget)
            {
                ilgen
                .Ldloc(context.ContextLocal);
                EmitPropertyDescriptor();
                ilgen
                .Stfld(context.RuntimeContext.PropertyTargetProperty);
            }

            ilgen.EmitCall(me.ProvideValue);

            if (needProvideValueTarget)
            {
                ilgen
                .Ldloc(context.ContextLocal)
                .Ldnull()
                .Stfld(context.RuntimeContext.PropertyTargetProperty);
            }



            return(XamlIlNodeEmitResult.Type(0, me.ProvideValue.ReturnType));
        }
コード例 #14
0
 public void LdLocal(XamlIlAstCompilerLocalNode node, IXamlIlEmitter codeGen)
 {
     if (_locals.TryGetValue(node, out var local))
     {
         codeGen.Emit(OpCodes.Ldloc, local);
     }
     else
     {
         throw new XamlIlLoadException("Attempt to read uninitialized local variable", node);
     }
 }
コード例 #15
0
        XamlIlEmitContext InitCodeGen(
            IFileSource file,
            Func <string, IXamlIlType, IXamlIlTypeBuilder> createSubType,
            IXamlIlEmitter codeGen, XamlIlContext context, bool needContextLocal)
        {
            IXamlIlLocal contextLocal = null;

            if (needContextLocal)
            {
                contextLocal = codeGen.DefineLocal(context.ContextType);
                // Pass IService provider as the first argument to context factory
                codeGen
                .Emit(OpCodes.Ldarg_0);
                context.Factory(codeGen);
                codeGen.Emit(OpCodes.Stloc, contextLocal);
            }

            var emitContext = new XamlIlEmitContext(codeGen, _configuration, context, contextLocal, createSubType, file, Emitters);

            return(emitContext);
        }
コード例 #16
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlPropertyValueManipulationNode pvm))
            {
                return(null);
            }
            codeGen.Emit(pvm.Property.Getter.IsStatic ? OpCodes.Call : OpCodes.Callvirt,
                         pvm.Property.Getter);
            context.Emit(pvm.Manipulation, codeGen, null);

            return(XamlIlNodeEmitResult.Void(1));
        }
コード例 #17
0
ファイル: TextNodeEmitter.cs プロジェクト: cm4ker/XamlIl
 public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
 {
     if (!(node is XamlIlAstTextNode text))
     {
         return(null);
     }
     if (!text.Type.GetClrType().Equals(context.Configuration.WellKnownTypes.String))
     {
         throw new XamlIlLoadException("Text node type wasn't resolved to well-known System.String", node);
     }
     codeGen.Emit(OpCodes.Ldstr, text.Text);
     return(XamlIlNodeEmitResult.Type(0, text.Type.GetClrType()));
 }
コード例 #18
0
 public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
 {
     if (Constant is string)
     {
         codeGen.Emit(OpCodes.Ldstr, (string)Constant);
     }
     else if (Constant is long || Constant is ulong)
     {
         codeGen.Emit(OpCodes.Ldc_I8, TypeSystemHelpers.ConvertLiteralToLong(Constant));
     }
     else if (Constant is float f)
     {
         codeGen.Emit(OpCodes.Ldc_R4, f);
     }
     else if (Constant is double d)
     {
         codeGen.Emit(OpCodes.Ldc_R8, d);
     }
     else
     {
         codeGen.Emit(OpCodes.Ldc_I4, TypeSystemHelpers.ConvertLiteralToInt(Constant));
     }
     return(XamlIlNodeEmitResult.Type(0, Type.GetClrType()));
 }
コード例 #19
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlManipulationGroupNode group))
            {
                return(null);
            }
            if (group.Children.Count == 0)
            {
                codeGen.Emit(OpCodes.Pop);
            }
            else
            {
                for (var c = 0; c < group.Children.Count; c++)
                {
                    if (c != group.Children.Count - 1)
                    {
                        codeGen.Emit(OpCodes.Dup);
                    }
                    context.Emit(group.Children[c], codeGen, null);
                }
            }

            return(XamlIlNodeEmitResult.Void(1));
        }
コード例 #20
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlValueWithManipulationNode vwm))
            {
                return(null);
            }
            var created = context.Emit(vwm.Value, codeGen, vwm.Type.GetClrType());

            if (vwm.Manipulation != null &&
                !(vwm.Manipulation is XamlIlManipulationGroupNode grp && grp.Children.Count == 0))
            {
                codeGen.Emit(OpCodes.Dup);
                context.Emit(vwm.Manipulation, codeGen, null);
            }
            return(XamlIlNodeEmitResult.Type(0, created.ReturnType));
        }
コード例 #21
0
        public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            var type   = Value.GetClrType();
            var method = _systemType.Methods.FirstOrDefault(m =>
                                                            m.Name == "GetTypeFromHandle" && m.Parameters.Count == 1 &&
                                                            m.Parameters[0].Name == "RuntimeTypeHandle");

            if (method == null)
            {
                throw new XamlIlTypeSystemException(
                          $"Unable to find GetTypeFromHandle(RuntimeTypeHandle) on {_systemType.GetFqn()}");
            }
            codeGen
            .Emit(OpCodes.Ldtoken, type)
            .Emit(OpCodes.Call, method);
            return(XamlIlNodeEmitResult.Type(0, _systemType));
        }
コード例 #22
0
ファイル: XamlIlCompiler.cs プロジェクト: cm4ker/XamlIl
        void CompileBuild(IXamlIlAstValueNode rootInstance, Func <string, IXamlIlType, IXamlIlTypeBuilder> createSubType,
                          IXamlIlEmitter codeGen, XamlIlContext context, IXamlIlMethod compiledPopulate)
        {
            var needContextLocal = !(rootInstance is XamlIlAstNewClrObjectNode newObj && newObj.Arguments.Count == 0);
            var emitContext      = InitCodeGen(createSubType, codeGen, context, needContextLocal);


            var rv = codeGen.DefineLocal(rootInstance.Type.GetClrType());

            emitContext.Emit(rootInstance, codeGen, rootInstance.Type.GetClrType());
            codeGen
            .Emit(OpCodes.Stloc, rv)
            .Emit(OpCodes.Ldarg_0)
            .Emit(OpCodes.Ldloc, rv)
            .Emit(OpCodes.Call, compiledPopulate)
            .Emit(OpCodes.Ldloc, rv)
            .Emit(OpCodes.Ret);
        }
コード例 #23
0
ファイル: XamlIlCompiler.cs プロジェクト: cm4ker/XamlIl
        /// <summary>
        ///         /// T Build(IServiceProvider sp);
        /// </summary>


        XamlIlEmitContext InitCodeGen(Func <string, IXamlIlType, IXamlIlTypeBuilder> createSubType,
                                      IXamlIlEmitter codeGen, XamlIlContext context, bool needContextLocal)
        {
            IXamlIlLocal contextLocal = null;

            if (needContextLocal)
            {
                contextLocal = codeGen.DefineLocal(context.ContextType);
                codeGen
                .Emit(OpCodes.Ldarg_0)
                .Emit(OpCodes.Newobj, context.Constructor)
                .Emit(OpCodes.Stloc, contextLocal);
            }

            var emitContext = new XamlIlEmitContext(codeGen, _configuration, context, contextLocal, createSubType, Emitters);

            return(emitContext);
        }
コード例 #24
0
 public static IXamlIlEmitter Ldtoken(this IXamlIlEmitter emitter, IXamlIlMethod method)
 => emitter.Emit(OpCodes.Ldtoken, method);
コード例 #25
0
 public static IXamlIlEmitter Ldtoken(this IXamlIlEmitter emitter, IXamlIlType type)
 => emitter.Emit(OpCodes.Ldtoken, type);
コード例 #26
0
 public static IXamlIlEmitter Pop(this IXamlIlEmitter emitter)
 => emitter.Emit(OpCodes.Pop);
コード例 #27
0
 public static IXamlIlEmitter Dup(this IXamlIlEmitter emitter)
 => emitter.Emit(OpCodes.Dup);
コード例 #28
0
 public static IXamlIlEmitter Ret(this IXamlIlEmitter emitter)
 => emitter.Emit(OpCodes.Ret);
コード例 #29
0
 public static IXamlIlEmitter Brtrue(this IXamlIlEmitter emitter, IXamlIlLabel label)
 => emitter.Emit(OpCodes.Brtrue, label);
コード例 #30
0
 public static IXamlIlEmitter Bgt(this IXamlIlEmitter emitter, IXamlIlLabel label)
 => emitter.Emit(OpCodes.Bgt, label);