Exemplo n.º 1
0
        /// <summary>
        /// Emits expression and converts it to required type.
        /// </summary>
        public void EmitConvert(BoundExpression expr, TypeSymbol to, ConversionKind conversion = ConversionKind.Implicit, bool notNull = false)
        {
            Debug.Assert(expr != null);
            Debug.Assert(to != null);

            // pop effectively
            if (to.IsVoid())
            {
                expr.Access = BoundAccess.None;

                if (!expr.IsConstant())
                {
                    // POP LOAD <expr>
                    EmitPop(Emit(expr));
                }

                return;
            }

            // bind target expression type
            expr.Access = expr.Access.WithRead(to);

            if (!expr.Access.IsReadRef)
            {
                // constants
                if (expr.ConstantValue.HasValue && to != null)
                {
                    // TODO: ConversionKind.Strict ?
                    EmitConvert(EmitLoadConstant(expr.ConstantValue.Value, to, notNull), 0, to);
                    return;
                }

                // loads value from place most effectively without runtime type checking
                var place = PlaceOrNull(expr);
                if (place != null && place.Type != to)
                {
                    var type = TryEmitVariableSpecialize(place, expr.TypeRefMask);
                    if (type != null)
                    {
                        EmitConvert(type, 0, to);
                        return;
                    }
                }

                // avoiding of load of full value
                if (place != null && place.HasAddress && place.Type != null && place.Type.IsValueType)
                {
                    var conv = DeclaringCompilation.Conversions.ClassifyConversion(place.Type, to, conversion);
                    if (conv.Exists && conv.IsUserDefined && !conv.MethodSymbol.IsStatic)
                    {
                        // (ADDR expr).Method()
                        this.EmitImplicitConversion(EmitCall(ILOpCode.Call, (MethodSymbol)conv.MethodSymbol, expr, ImmutableArray <BoundArgument> .Empty), to, @checked: true);
                        return;
                    }
                }
            }

            //
            EmitConvert(expr.Emit(this), expr.TypeRefMask, to, conversion);
        }
Exemplo n.º 2
0
            bool TryConstructRuntimeChainElement(BoundExpression expr, out RuntimeChainElement runtimeChainElement)
            {
                Debug.Assert(expr != null);

                runtimeChainElement = null;

                if (expr.IsConstant())
                {
                    return(false);
                }

                // 1/ $$->{field}
                // should be a not resolved field reference (dynamic), otherwise it's unnecessary
                if (expr is BoundFieldRef fieldref &&
                    fieldref.IsInstanceField &&
                    ((Microsoft.CodeAnalysis.Operations.IFieldReferenceOperation)fieldref).Field == null)
                {
                    runtimeChainElement = new RuntimeChainElement(_cg.CoreTypes.RuntimeChain_Property_T, fieldref.Instance)
                    {
                        Fields = new List <KeyValuePair <string, BoundOperation> >(1)
                        {
                            new KeyValuePair <string, BoundOperation>("Name", fieldref.FieldName),
                        }
                    };
                }

                // 2/ $$[Key], $$[]
                if (expr is BoundArrayItemEx arritem)
                {
                    if (arritem.Index != null)
                    {
                        runtimeChainElement = new RuntimeChainElement(_cg.CoreTypes.RuntimeChain_ArrayItem_T, arritem.Array)
                        {
                            Fields = new List <KeyValuePair <string, BoundOperation> >(1)
                            {
                                new KeyValuePair <string, BoundOperation>("Key", arritem.Index),
                            }
                        };
                    }
                    else
                    {
                        runtimeChainElement = new RuntimeChainElement(_cg.CoreTypes.RuntimeChain_ArrayNewItem_T, arritem.Array)
                        {
                        };
                    }
                }

                // TODO: 3/ StaticProperty, ClassConstant

                //
                return(runtimeChainElement != null);
            }