Пример #1
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));
        }
Пример #2
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);
        }
Пример #3
0
 public static void EmitConvert(XamlIlEmitContext context, IXamlIlLineInfo node, IXamlIlType what,
                                IXamlIlType to, Func <bool, IXamlIlEmitter> ld)
 {
     if (what.Equals(to))
     {
         ld(false);
     }
     else if (what == XamlIlPseudoType.Null)
     {
         if (to.IsValueType)
         {
             if (to.GenericTypeDefinition?.Equals(context.Configuration.WellKnownTypes.NullableT) == true)
             {
                 using (var loc = context.GetLocal(to))
                     ld(false)
                     .Pop()
                     .Ldloca(loc.Local)
                     .Emit(OpCodes.Initobj, to)
                     .Ldloc(loc.Local);
             }
             else
             {
                 throw new XamlIlLoadException("Unable to convert {x:Null} to " + to.GetFqn(), node);
             }
         }
         else
         {
             ld(false);
         }
     }
     else if (what.IsValueType && to.IsValueType)
     {
         if (to.IsNullableOf(what))
         {
             ld(false).Emit(OpCodes.Newobj,
                            to.Constructors.First(c =>
                                                  c.Parameters.Count == 1 && c.Parameters[0].Equals(what)));
         }
         else if (what.IsNullableOf(what))
         {
             ld(true)
             .EmitCall(what.FindMethod(m => m.Name == "get_Value"));
         }
         else
         {
             throw new XamlIlLoadException(
                       $"Don't know how to convert value type {what.GetFullName()} to value type {to.GetFullName()}",
                       node);
         }
     }
     else if (!to.IsValueType && what.IsValueType)
     {
         if (!to.IsAssignableFrom(what))
         {
             throw new XamlIlLoadException(
                       $"Don't know how to convert value type {what.GetFullName()} to reference type {to.GetFullName()}",
                       node);
         }
         ld(false).Box(what);
     }
     else if (to.IsValueType && !what.IsValueType)
     {
         if (!(what.Namespace == "System" && what.Name == "Object"))
         {
             throw new XamlIlLoadException(
                       $"Don't know how to convert reference type {what.GetFullName()} to value type {to.GetFullName()}",
                       node);
         }
         ld(false).Unbox_Any(to);
     }
     else
     {
         if (to.IsAssignableFrom(what))
         {
             // Downcast, always safe
             ld(false);
         }
         else if (what.IsInterface || what.IsAssignableFrom(to))
         {
             // Upcast or cast from interface, might throw InvalidCastException
             ld(false).Emit(OpCodes.Castclass, to);
         }
         else
         {
             // Types are completely unrelated, e. g. string to List<int> conversion attempt
             throw new XamlIlLoadException(
                       $"Don't know how to convert reference type {what.GetFullName()} to reference type {to.GetFullName()}",
                       node);
         }
     }
 }
Пример #4
0
        public static IXamlIlMethod GetMethod(this IXamlIlType type, FindMethodMethodSignature signature)
        {
            var found = FindMethod(type, signature);

            if (found == null)
            {
                throw new XamlIlTypeSystemException($"Method with signature {signature} is not found on type {type.GetFqn()}");
            }
            return(found);
        }
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode value, IXamlIlCodeGen codeGen, IXamlIlType expectedType)
        {
            var res          = EmitCore(value, codeGen);
            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 (!expectedType.IsAssignableFrom(returnedType))
                {
                    throw new XamlIlLoadException(
                              $"Emit of node {value} resulted in  {returnedType.GetFqn()} which is not convertible to expected {expectedType.GetFqn()}",
                              value);
                }

                if (returnedType.IsValueType && !expectedType.IsValueType)
                {
                    codeGen.Generator.Emit(OpCodes.Box, returnedType);
                }
            }

            return(res);
        }
Пример #6
0
 public override string ToString() => Type.GetFqn();