Esempio n. 1
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();
        }
Esempio n. 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);
        }