private void EmitTypeBinaryExpression(Expression expr) { TypeBinaryExpression node = (TypeBinaryExpression)expr; if (node.NodeType == ExpressionType.TypeEqual) { EmitExpression(node.ReduceTypeEqual()); return; } Type type = node.Expression.Type; // Try to determine the result statically AnalyzeTypeIsResult result = ConstantCheck.AnalyzeTypeIs(node); if (result == AnalyzeTypeIsResult.KnownTrue || result == AnalyzeTypeIsResult.KnownFalse) { // Result is known statically, so just emit the expression for // its side effects and return the result EmitExpressionAsVoid(node.Expression); _ilg.EmitBoolean(result == AnalyzeTypeIsResult.KnownTrue); return; } if (result == AnalyzeTypeIsResult.KnownAssignable) { // We know the type can be assigned, but still need to check // for null at runtime if (type.IsNullableType()) { EmitAddress(node.Expression, type); _ilg.EmitHasValue(type); return; } Debug.Assert(!type.GetTypeInfo().IsValueType); EmitExpression(node.Expression); _ilg.Emit(OpCodes.Ldnull); _ilg.Emit(OpCodes.Ceq); _ilg.Emit(OpCodes.Ldc_I4_0); _ilg.Emit(OpCodes.Ceq); return; } Debug.Assert(result == AnalyzeTypeIsResult.Unknown); // Emit a full runtime "isinst" check EmitExpression(node.Expression); if (type.GetTypeInfo().IsValueType) { _ilg.Emit(OpCodes.Box, type); } _ilg.Emit(OpCodes.Isinst, node.TypeOperand); _ilg.Emit(OpCodes.Ldnull); _ilg.Emit(OpCodes.Cgt_Un); }
private void EmitTypeBinaryExpression(Expression expr) { var node = (TypeBinaryExpression)expr; if (node.NodeType == ExpressionType.TypeEqual) { EmitExpression(node.ReduceTypeEqual()); return; } var type = node.Expression.Type; // Try to determine the result statically var result = ConstantCheck.AnalyzeTypeIs(node); switch (result) { case AnalyzeTypeIsResult.KnownTrue: case AnalyzeTypeIsResult.KnownFalse: // Result is known statically, so just emit the expression for // its side effects and return the result EmitExpressionAsVoid(node.Expression); IL.EmitPrimitive(result == AnalyzeTypeIsResult.KnownTrue); return; case AnalyzeTypeIsResult.KnownAssignable when type.IsNullable(): EmitAddress(node.Expression, type); IL.EmitHasValue(type); return; case AnalyzeTypeIsResult.KnownAssignable: Debug.Assert(!type.IsValueType); EmitExpression(node.Expression); IL.Emit(OpCodes.Ldnull); IL.Emit(OpCodes.Cgt_Un); return; default: break; } Debug.Assert(result == AnalyzeTypeIsResult.Unknown); // Emit a full runtime "isinst" check EmitExpression(node.Expression); if (type.IsValueType) { IL.Emit(OpCodes.Box, type); } IL.Emit(OpCodes.Isinst, node.TypeOperand); IL.Emit(OpCodes.Ldnull); IL.Emit(OpCodes.Cgt_Un); }