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(); }
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); }