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