You've already forked linux-packaging-mono
Imported Upstream version 5.8.0.22
Former-commit-id: df344e34b07851d296efb3e6604c8db42b6f7aa3
This commit is contained in:
parent
5f4a27cc8a
commit
7d05485754
@@ -155,7 +155,7 @@
|
||||
</Type>
|
||||
</Namespace>
|
||||
<Namespace Name="System.Collections.Generic">
|
||||
<Type Name="IEnumerable<>" Dynamic="Required">
|
||||
<Type Name="IEnumerable<>">
|
||||
<Method Name="GetEnumerator" Dynamic="Required"/>
|
||||
</Type>
|
||||
<Type Name="IEnumerator<>">
|
||||
|
||||
@@ -904,7 +904,6 @@ namespace System.Linq.Expressions.Compiler
|
||||
Label labEnd;
|
||||
LocalBuilder locFrom = locals.GetLocal(typeFrom);
|
||||
il.Emit(OpCodes.Stloc, locFrom);
|
||||
LocalBuilder locTo = locals.GetLocal(typeTo);
|
||||
// test for null
|
||||
il.Emit(OpCodes.Ldloca, locFrom);
|
||||
il.EmitHasValue(typeFrom);
|
||||
@@ -919,16 +918,16 @@ namespace System.Linq.Expressions.Compiler
|
||||
// construct result type
|
||||
ConstructorInfo ci = typeTo.GetConstructor(new Type[] { nnTypeTo });
|
||||
il.Emit(OpCodes.Newobj, ci);
|
||||
il.Emit(OpCodes.Stloc, locTo);
|
||||
labEnd = il.DefineLabel();
|
||||
il.Emit(OpCodes.Br_S, labEnd);
|
||||
// if null then create a default one
|
||||
il.MarkLabel(labIfNull);
|
||||
LocalBuilder locTo = locals.GetLocal(typeTo);
|
||||
il.Emit(OpCodes.Ldloca, locTo);
|
||||
il.Emit(OpCodes.Initobj, typeTo);
|
||||
il.MarkLabel(labEnd);
|
||||
il.Emit(OpCodes.Ldloc, locTo);
|
||||
locals.FreeLocal(locTo);
|
||||
il.MarkLabel(labEnd);
|
||||
}
|
||||
|
||||
|
||||
@@ -936,14 +935,10 @@ namespace System.Linq.Expressions.Compiler
|
||||
{
|
||||
Debug.Assert(!typeFrom.IsNullableType());
|
||||
Debug.Assert(typeTo.IsNullableType());
|
||||
LocalBuilder locTo = locals.GetLocal(typeTo);
|
||||
Type nnTypeTo = typeTo.GetNonNullableType();
|
||||
il.EmitConvertToType(typeFrom, nnTypeTo, isChecked, locals);
|
||||
ConstructorInfo ci = typeTo.GetConstructor(new Type[] { nnTypeTo });
|
||||
il.Emit(OpCodes.Newobj, ci);
|
||||
il.Emit(OpCodes.Stloc, locTo);
|
||||
il.Emit(OpCodes.Ldloc, locTo);
|
||||
locals.FreeLocal(locTo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -150,43 +150,33 @@ namespace System.Linq.Expressions.Compiler
|
||||
{
|
||||
Debug.Assert(!leftType.IsNullableType());
|
||||
Debug.Assert(!rightType.IsNullableType());
|
||||
|
||||
if (op == ExpressionType.Equal || op == ExpressionType.NotEqual)
|
||||
{
|
||||
EmitUnliftedEquality(op, leftType);
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Assert(leftType.IsPrimitive);
|
||||
Debug.Assert(leftType.IsPrimitive || (op == ExpressionType.Equal || op == ExpressionType.NotEqual) && (!leftType.IsValueType || leftType.IsEnum));
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case ExpressionType.NotEqual:
|
||||
if (leftType.GetTypeCode() == TypeCode.Boolean)
|
||||
{
|
||||
goto case ExpressionType.ExclusiveOr;
|
||||
}
|
||||
|
||||
_ilg.Emit(OpCodes.Ceq);
|
||||
_ilg.Emit(OpCodes.Ldc_I4_0);
|
||||
goto case ExpressionType.Equal;
|
||||
case ExpressionType.Equal:
|
||||
_ilg.Emit(OpCodes.Ceq);
|
||||
return;
|
||||
case ExpressionType.Add:
|
||||
_ilg.Emit(OpCodes.Add);
|
||||
break;
|
||||
case ExpressionType.AddChecked:
|
||||
if (leftType.IsFloatingPoint())
|
||||
{
|
||||
_ilg.Emit(OpCodes.Add);
|
||||
}
|
||||
else if (leftType.IsUnsigned())
|
||||
{
|
||||
_ilg.Emit(OpCodes.Add_Ovf_Un);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ilg.Emit(OpCodes.Add_Ovf);
|
||||
}
|
||||
_ilg.Emit(leftType.IsFloatingPoint() ? OpCodes.Add : (leftType.IsUnsigned() ? OpCodes.Add_Ovf_Un : OpCodes.Add_Ovf));
|
||||
break;
|
||||
case ExpressionType.Subtract:
|
||||
_ilg.Emit(OpCodes.Sub);
|
||||
break;
|
||||
case ExpressionType.SubtractChecked:
|
||||
if (leftType.IsFloatingPoint())
|
||||
{
|
||||
_ilg.Emit(OpCodes.Sub);
|
||||
}
|
||||
else if (leftType.IsUnsigned())
|
||||
if (leftType.IsUnsigned())
|
||||
{
|
||||
_ilg.Emit(OpCodes.Sub_Ovf_Un);
|
||||
// Guaranteed to fit within result type: no conversion
|
||||
@@ -194,25 +184,14 @@ namespace System.Linq.Expressions.Compiler
|
||||
}
|
||||
else
|
||||
{
|
||||
_ilg.Emit(OpCodes.Sub_Ovf);
|
||||
_ilg.Emit(leftType.IsFloatingPoint() ? OpCodes.Sub : OpCodes.Sub_Ovf);
|
||||
}
|
||||
break;
|
||||
case ExpressionType.Multiply:
|
||||
_ilg.Emit(OpCodes.Mul);
|
||||
break;
|
||||
case ExpressionType.MultiplyChecked:
|
||||
if (leftType.IsFloatingPoint())
|
||||
{
|
||||
_ilg.Emit(OpCodes.Mul);
|
||||
}
|
||||
else if (leftType.IsUnsigned())
|
||||
{
|
||||
_ilg.Emit(OpCodes.Mul_Ovf_Un);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ilg.Emit(OpCodes.Mul_Ovf);
|
||||
}
|
||||
_ilg.Emit(leftType.IsFloatingPoint() ? OpCodes.Mul : (leftType.IsUnsigned() ? OpCodes.Mul_Ovf_Un : OpCodes.Mul_Ovf));
|
||||
break;
|
||||
case ExpressionType.Divide:
|
||||
_ilg.Emit(leftType.IsUnsigned() ? OpCodes.Div_Un : OpCodes.Div);
|
||||
@@ -306,19 +285,6 @@ namespace System.Linq.Expressions.Compiler
|
||||
}
|
||||
}
|
||||
|
||||
private void EmitUnliftedEquality(ExpressionType op, Type type)
|
||||
{
|
||||
Debug.Assert(op == ExpressionType.Equal || op == ExpressionType.NotEqual);
|
||||
Debug.Assert(type.IsPrimitive || !type.IsValueType || type.IsEnum);
|
||||
_ilg.Emit(OpCodes.Ceq);
|
||||
if (op == ExpressionType.NotEqual)
|
||||
{
|
||||
_ilg.Emit(OpCodes.Ldc_I4_0);
|
||||
_ilg.Emit(OpCodes.Ceq);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
|
||||
private void EmitLiftedBinaryOp(ExpressionType op, Type leftType, Type rightType, Type resultType, bool liftedToNull)
|
||||
{
|
||||
|
||||
@@ -146,17 +146,20 @@ namespace System.Linq.Expressions.Compiler
|
||||
// emit call to invoke
|
||||
_ilg.Emit(OpCodes.Callvirt, b.Conversion.Type.GetInvokeMethod());
|
||||
}
|
||||
else if (!TypeUtils.AreEquivalent(b.Type, nnLeftType))
|
||||
else if (TypeUtils.AreEquivalent(b.Type, b.Left.Type))
|
||||
{
|
||||
_ilg.Emit(OpCodes.Ldloca, loc);
|
||||
_ilg.EmitGetValueOrDefault(b.Left.Type);
|
||||
_ilg.EmitConvertToType(nnLeftType, b.Type, isChecked: true, locals: this);
|
||||
_ilg.Emit(OpCodes.Ldloc, loc);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ilg.Emit(OpCodes.Ldloca, loc);
|
||||
_ilg.EmitGetValueOrDefault(b.Left.Type);
|
||||
if (!TypeUtils.AreEquivalent(b.Type, nnLeftType))
|
||||
{
|
||||
_ilg.EmitConvertToType(nnLeftType, b.Type, isChecked: true, locals: this);
|
||||
}
|
||||
}
|
||||
|
||||
FreeLocal(loc);
|
||||
|
||||
_ilg.Emit(OpCodes.Br, labEnd);
|
||||
@@ -273,6 +276,8 @@ namespace System.Linq.Expressions.Compiler
|
||||
|
||||
private void EmitMethodAndAlso(BinaryExpression b, CompilationFlags flags)
|
||||
{
|
||||
Debug.Assert(b.Method.IsStatic);
|
||||
|
||||
Label labEnd = _ilg.DefineLabel();
|
||||
EmitExpression(b.Left);
|
||||
_ilg.Emit(OpCodes.Dup);
|
||||
@@ -281,25 +286,13 @@ namespace System.Linq.Expressions.Compiler
|
||||
_ilg.Emit(OpCodes.Call, opFalse);
|
||||
_ilg.Emit(OpCodes.Brtrue, labEnd);
|
||||
|
||||
//store the value of the left value before emitting b.Right to empty the evaluation stack
|
||||
LocalBuilder locLeft = GetLocal(b.Left.Type);
|
||||
_ilg.Emit(OpCodes.Stloc, locLeft);
|
||||
|
||||
EmitExpression(b.Right);
|
||||
//store the right value to local
|
||||
LocalBuilder locRight = GetLocal(b.Right.Type);
|
||||
_ilg.Emit(OpCodes.Stloc, locRight);
|
||||
|
||||
Debug.Assert(b.Method.IsStatic);
|
||||
_ilg.Emit(OpCodes.Ldloc, locLeft);
|
||||
_ilg.Emit(OpCodes.Ldloc, locRight);
|
||||
if ((flags & CompilationFlags.EmitAsTailCallMask) == CompilationFlags.EmitAsTail)
|
||||
{
|
||||
_ilg.Emit(OpCodes.Tailcall);
|
||||
}
|
||||
|
||||
_ilg.Emit(OpCodes.Call, b.Method);
|
||||
FreeLocal(locLeft);
|
||||
FreeLocal(locRight);
|
||||
_ilg.MarkLabel(labEnd);
|
||||
}
|
||||
|
||||
@@ -319,18 +312,21 @@ namespace System.Linq.Expressions.Compiler
|
||||
{
|
||||
BinaryExpression b = (BinaryExpression)expr;
|
||||
|
||||
if (b.Method != null && !b.IsLiftedLogical)
|
||||
if (b.Method != null)
|
||||
{
|
||||
EmitMethodAndAlso(b, flags);
|
||||
if (b.IsLiftedLogical)
|
||||
{
|
||||
EmitExpression(b.ReduceUserdefinedLifted());
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitMethodAndAlso(b, flags);
|
||||
}
|
||||
}
|
||||
else if (b.Left.Type == typeof(bool?))
|
||||
{
|
||||
EmitLiftedAndAlso(b);
|
||||
}
|
||||
else if (b.IsLiftedLogical)
|
||||
{
|
||||
EmitExpression(b.ReduceUserdefinedLifted());
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitUnliftedAndAlso(b);
|
||||
@@ -386,33 +382,23 @@ namespace System.Linq.Expressions.Compiler
|
||||
|
||||
private void EmitMethodOrElse(BinaryExpression b, CompilationFlags flags)
|
||||
{
|
||||
Debug.Assert(b.Method.IsStatic);
|
||||
|
||||
Label labEnd = _ilg.DefineLabel();
|
||||
EmitExpression(b.Left);
|
||||
_ilg.Emit(OpCodes.Dup);
|
||||
MethodInfo opTrue = TypeUtils.GetBooleanOperator(b.Method.DeclaringType, "op_True");
|
||||
Debug.Assert(opTrue != null, "factory should check that the method exists");
|
||||
|
||||
_ilg.Emit(OpCodes.Call, opTrue);
|
||||
_ilg.Emit(OpCodes.Brtrue, labEnd);
|
||||
|
||||
//store the value of the left value before emitting b.Right to empty the evaluation stack
|
||||
LocalBuilder locLeft = GetLocal(b.Left.Type);
|
||||
_ilg.Emit(OpCodes.Stloc, locLeft);
|
||||
|
||||
EmitExpression(b.Right);
|
||||
//store the right value to local
|
||||
LocalBuilder locRight = GetLocal(b.Right.Type);
|
||||
_ilg.Emit(OpCodes.Stloc, locRight);
|
||||
|
||||
Debug.Assert(b.Method.IsStatic);
|
||||
_ilg.Emit(OpCodes.Ldloc, locLeft);
|
||||
_ilg.Emit(OpCodes.Ldloc, locRight);
|
||||
if ((flags & CompilationFlags.EmitAsTailCallMask) == CompilationFlags.EmitAsTail)
|
||||
{
|
||||
_ilg.Emit(OpCodes.Tailcall);
|
||||
}
|
||||
|
||||
_ilg.Emit(OpCodes.Call, b.Method);
|
||||
FreeLocal(locLeft);
|
||||
FreeLocal(locRight);
|
||||
_ilg.MarkLabel(labEnd);
|
||||
}
|
||||
|
||||
@@ -420,18 +406,21 @@ namespace System.Linq.Expressions.Compiler
|
||||
{
|
||||
BinaryExpression b = (BinaryExpression)expr;
|
||||
|
||||
if (b.Method != null && !b.IsLiftedLogical)
|
||||
if (b.Method != null)
|
||||
{
|
||||
EmitMethodOrElse(b, flags);
|
||||
if (b.IsLiftedLogical)
|
||||
{
|
||||
EmitExpression(b.ReduceUserdefinedLifted());
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitMethodOrElse(b, flags);
|
||||
}
|
||||
}
|
||||
else if (b.Left.Type == typeof(bool?))
|
||||
{
|
||||
EmitLiftedOrElse(b);
|
||||
}
|
||||
else if (b.IsLiftedLogical)
|
||||
{
|
||||
EmitExpression(b.ReduceUserdefinedLifted());
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitUnliftedOrElse(b);
|
||||
@@ -468,36 +457,36 @@ namespace System.Linq.Expressions.Compiler
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
|
||||
private void EmitExpressionAndBranch(bool branchValue, Expression node, Label label)
|
||||
{
|
||||
Debug.Assert(node.Type == typeof(bool));
|
||||
CompilationFlags startEmitted = EmitExpressionStart(node);
|
||||
try
|
||||
switch (node.NodeType)
|
||||
{
|
||||
if (node.Type == typeof(bool))
|
||||
{
|
||||
switch (node.NodeType)
|
||||
{
|
||||
case ExpressionType.Not:
|
||||
EmitBranchNot(branchValue, (UnaryExpression)node, label);
|
||||
return;
|
||||
case ExpressionType.AndAlso:
|
||||
case ExpressionType.OrElse:
|
||||
EmitBranchLogical(branchValue, (BinaryExpression)node, label);
|
||||
return;
|
||||
case ExpressionType.Block:
|
||||
EmitBranchBlock(branchValue, (BlockExpression)node, label);
|
||||
return;
|
||||
case ExpressionType.Equal:
|
||||
case ExpressionType.NotEqual:
|
||||
EmitBranchComparison(branchValue, (BinaryExpression)node, label);
|
||||
return;
|
||||
}
|
||||
}
|
||||
EmitExpression(node, CompilationFlags.EmitAsNoTail | CompilationFlags.EmitNoExpressionStart);
|
||||
EmitBranchOp(branchValue, label);
|
||||
}
|
||||
finally
|
||||
{
|
||||
EmitExpressionEnd(startEmitted);
|
||||
case ExpressionType.Not:
|
||||
EmitBranchNot(branchValue, (UnaryExpression)node, label);
|
||||
break;
|
||||
|
||||
case ExpressionType.AndAlso:
|
||||
case ExpressionType.OrElse:
|
||||
EmitBranchLogical(branchValue, (BinaryExpression)node, label);
|
||||
break;
|
||||
|
||||
case ExpressionType.Block:
|
||||
EmitBranchBlock(branchValue, (BlockExpression)node, label);
|
||||
break;
|
||||
|
||||
case ExpressionType.Equal:
|
||||
case ExpressionType.NotEqual:
|
||||
EmitBranchComparison(branchValue, (BinaryExpression)node, label);
|
||||
break;
|
||||
|
||||
default:
|
||||
EmitExpression(node, CompilationFlags.EmitAsNoTail | CompilationFlags.EmitNoExpressionStart);
|
||||
EmitBranchOp(branchValue, label);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
EmitExpressionEnd(startEmitted);
|
||||
}
|
||||
|
||||
private void EmitBranchOp(bool branch, Label label)
|
||||
@@ -513,6 +502,7 @@ namespace System.Linq.Expressions.Compiler
|
||||
EmitBranchOp(branch, label);
|
||||
return;
|
||||
}
|
||||
|
||||
EmitExpressionAndBranch(!branch, node.Operand, label);
|
||||
}
|
||||
|
||||
|
||||
@@ -72,14 +72,44 @@ namespace System.Linq.Expressions.Compiler
|
||||
}
|
||||
else if (node.NodeType == ExpressionType.NegateChecked && node.Operand.Type.IsInteger())
|
||||
{
|
||||
EmitExpression(node.Operand);
|
||||
LocalBuilder loc = GetLocal(node.Operand.Type);
|
||||
_ilg.Emit(OpCodes.Stloc, loc);
|
||||
_ilg.EmitPrimitive(0);
|
||||
_ilg.EmitConvertToType(typeof(int), node.Operand.Type, isChecked: false, locals: this);
|
||||
_ilg.Emit(OpCodes.Ldloc, loc);
|
||||
FreeLocal(loc);
|
||||
EmitBinaryOperator(ExpressionType.SubtractChecked, node.Operand.Type, node.Operand.Type, node.Type, liftedToNull: false);
|
||||
Type type = node.Type;
|
||||
Debug.Assert(type == node.Operand.Type);
|
||||
if (type.IsNullableType())
|
||||
{
|
||||
Label nullOrZero = _ilg.DefineLabel();
|
||||
Label end = _ilg.DefineLabel();
|
||||
EmitExpression(node.Operand);
|
||||
LocalBuilder loc = GetLocal(type);
|
||||
|
||||
// check for null or zero
|
||||
_ilg.Emit(OpCodes.Stloc, loc);
|
||||
_ilg.Emit(OpCodes.Ldloca, loc);
|
||||
_ilg.EmitGetValueOrDefault(type);
|
||||
_ilg.Emit(OpCodes.Brfalse_S, nullOrZero);
|
||||
|
||||
// calculate 0 - operand
|
||||
Type nnType = type.GetNonNullableType();
|
||||
_ilg.EmitDefault(nnType, locals: null); // locals won't be used.
|
||||
_ilg.Emit(OpCodes.Ldloca, loc);
|
||||
_ilg.EmitGetValueOrDefault(type);
|
||||
EmitBinaryOperator(ExpressionType.SubtractChecked, nnType, nnType, nnType, liftedToNull: false);
|
||||
|
||||
// construct result
|
||||
_ilg.Emit(OpCodes.Newobj, type.GetConstructor(new Type[] { nnType }));
|
||||
_ilg.Emit(OpCodes.Br_S, end);
|
||||
|
||||
// if null then push back on stack
|
||||
_ilg.MarkLabel(nullOrZero);
|
||||
_ilg.Emit(OpCodes.Ldloc, loc);
|
||||
FreeLocal(loc);
|
||||
_ilg.MarkLabel(end);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ilg.EmitDefault(type, locals: null); // locals won't be used.
|
||||
EmitExpression(node.Operand);
|
||||
EmitBinaryOperator(ExpressionType.SubtractChecked, type, type, type, liftedToNull: false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -47,12 +47,10 @@ namespace System.Linq.Expressions.Interpreter
|
||||
public override int Run(InterpretedFrame frame)
|
||||
{
|
||||
int length = ConvertHelper.ToInt32NoNull(frame.Pop());
|
||||
if (length < 0)
|
||||
{
|
||||
// to make behavior aligned with array creation emitted by C# compiler
|
||||
throw new OverflowException();
|
||||
}
|
||||
frame.Push(Array.CreateInstance(_elementType, length));
|
||||
// To make behavior aligned with array creation emitted by C# compiler if length is less than
|
||||
// zero we try to use it to create an array, which will throw an OverflowException with the
|
||||
// correct localized error message.
|
||||
frame.Push(length < 0 ? new int[length] : Array.CreateInstance(_elementType, length));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace System.Linq.Expressions.Interpreter
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
|
||||
[ThreadStatic]
|
||||
public static InterpretedFrame CurrentFrame;
|
||||
private static InterpretedFrame s_currentFrame;
|
||||
|
||||
internal readonly Interpreter Interpreter;
|
||||
internal InterpretedFrame _parent;
|
||||
@@ -177,14 +177,14 @@ namespace System.Linq.Expressions.Interpreter
|
||||
|
||||
internal InterpretedFrame Enter()
|
||||
{
|
||||
InterpretedFrame currentFrame = CurrentFrame;
|
||||
CurrentFrame = this;
|
||||
InterpretedFrame currentFrame = s_currentFrame;
|
||||
s_currentFrame = this;
|
||||
return _parent = currentFrame;
|
||||
}
|
||||
|
||||
internal void Leave(InterpretedFrame prevFrame)
|
||||
{
|
||||
CurrentFrame = prevFrame;
|
||||
s_currentFrame = prevFrame;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace System.Linq.Expressions.Interpreter
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.Push(unchecked(-(float)obj));
|
||||
frame.Push(-(float)obj);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -96,7 +96,7 @@ namespace System.Linq.Expressions.Interpreter
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.Push(unchecked(-(double)obj));
|
||||
frame.Push(-(double)obj);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -120,7 +120,7 @@ namespace System.Linq.Expressions.Interpreter
|
||||
|
||||
internal abstract class NegateCheckedInstruction : Instruction
|
||||
{
|
||||
private static Instruction s_Int16, s_Int32, s_Int64, s_Single, s_Double;
|
||||
private static Instruction s_Int16, s_Int32, s_Int64;
|
||||
|
||||
public override int ConsumedStack => 1;
|
||||
public override int ProducedStack => 1;
|
||||
@@ -179,40 +179,6 @@ namespace System.Linq.Expressions.Interpreter
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class NegateCheckedSingle : NegateCheckedInstruction
|
||||
{
|
||||
public override int Run(InterpretedFrame frame)
|
||||
{
|
||||
object obj = frame.Pop();
|
||||
if (obj == null)
|
||||
{
|
||||
frame.Push(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.Push(checked(-(float)obj));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class NegateCheckedDouble : NegateCheckedInstruction
|
||||
{
|
||||
public override int Run(InterpretedFrame frame)
|
||||
{
|
||||
object obj = frame.Pop();
|
||||
if (obj == null)
|
||||
{
|
||||
frame.Push(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.Push(checked(-(double)obj));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static Instruction Create(Type type)
|
||||
{
|
||||
Debug.Assert(!type.IsEnum);
|
||||
@@ -221,10 +187,8 @@ namespace System.Linq.Expressions.Interpreter
|
||||
case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new NegateCheckedInt16());
|
||||
case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new NegateCheckedInt32());
|
||||
case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new NegateCheckedInt64());
|
||||
case TypeCode.Single: return s_Single ?? (s_Single = new NegateCheckedSingle());
|
||||
case TypeCode.Double: return s_Double ?? (s_Double = new NegateCheckedDouble());
|
||||
default:
|
||||
throw ContractUtils.Unreachable;
|
||||
return NegateInstruction.Create(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace System.Linq.Expressions.Interpreter
|
||||
{
|
||||
// Perf: EqualityComparer<T> but is 3/2 to 2 times slower.
|
||||
private static Instruction s_reference, s_Boolean, s_SByte, s_Int16, s_Char, s_Int32, s_Int64, s_Byte, s_UInt16, s_UInt32, s_UInt64, s_Single, s_Double;
|
||||
private static Instruction s_BooleanLiftedToNull, s_SByteLiftedToNull, s_Int16LiftedToNull, s_CharLiftedToNull, s_Int32LiftedToNull, s_Int64LiftedToNull, s_ByteLiftedToNull, s_UInt16LiftedToNull, s_UInt32LiftedToNull, s_UInt64LiftedToNull, s_SingleLiftedToNull, s_DoubleLiftedToNull;
|
||||
private static Instruction s_SByteLiftedToNull, s_Int16LiftedToNull, s_CharLiftedToNull, s_Int32LiftedToNull, s_Int64LiftedToNull, s_ByteLiftedToNull, s_UInt16LiftedToNull, s_UInt32LiftedToNull, s_UInt64LiftedToNull, s_SingleLiftedToNull, s_DoubleLiftedToNull;
|
||||
|
||||
public override int ConsumedStack => 2;
|
||||
public override int ProducedStack => 1;
|
||||
@@ -292,24 +292,6 @@ namespace System.Linq.Expressions.Interpreter
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class NotEqualBooleanLiftedToNull : NotEqualInstruction
|
||||
{
|
||||
public override int Run(InterpretedFrame frame)
|
||||
{
|
||||
object right = frame.Pop();
|
||||
object left = frame.Pop();
|
||||
if (left == null || right == null)
|
||||
{
|
||||
frame.Push(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.Push((bool)left != (bool)right);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class NotEqualSByteLiftedToNull : NotEqualInstruction
|
||||
{
|
||||
public override int Run(InterpretedFrame frame)
|
||||
@@ -515,7 +497,7 @@ namespace System.Linq.Expressions.Interpreter
|
||||
{
|
||||
switch (type.GetNonNullableType().GetTypeCode())
|
||||
{
|
||||
case TypeCode.Boolean: return s_BooleanLiftedToNull ?? (s_BooleanLiftedToNull = new NotEqualBooleanLiftedToNull());
|
||||
case TypeCode.Boolean: return ExclusiveOrInstruction.Create(type);
|
||||
case TypeCode.SByte: return s_SByteLiftedToNull ?? (s_SByteLiftedToNull = new NotEqualSByteLiftedToNull());
|
||||
case TypeCode.Int16: return s_Int16LiftedToNull ?? (s_Int16LiftedToNull = new NotEqualInt16LiftedToNull());
|
||||
case TypeCode.Char: return s_CharLiftedToNull ?? (s_CharLiftedToNull = new NotEqualCharLiftedToNull());
|
||||
|
||||
@@ -93,6 +93,26 @@ namespace System.Linq.Expressions
|
||||
|
||||
// Null paramName as there are two paths here with different parameter names at the API
|
||||
TypeUtils.ValidateType(decType, null);
|
||||
|
||||
#if __MonoCS__
|
||||
if (member is PropertyInfo pi)
|
||||
{
|
||||
if (!pi.CanWrite)
|
||||
{
|
||||
throw Error.PropertyDoesNotHaveSetter(pi, nameof(member));
|
||||
}
|
||||
|
||||
memberType = pi.PropertyType;
|
||||
}
|
||||
else if (member is FieldInfo fi)
|
||||
{
|
||||
memberType = fi.FieldType;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Error.ArgumentMustBeFieldInfoOrPropertyInfo(nameof(member));
|
||||
}
|
||||
#else
|
||||
switch (member)
|
||||
{
|
||||
case PropertyInfo pi:
|
||||
@@ -111,6 +131,7 @@ namespace System.Linq.Expressions
|
||||
default:
|
||||
throw Error.ArgumentMustBeFieldInfoOrPropertyInfo(nameof(member));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +127,26 @@ namespace System.Linq.Expressions
|
||||
|
||||
// Null paramName as there are several paths here with different parameter names at the API
|
||||
TypeUtils.ValidateType(decType, null, allowByRef: true, allowPointer: true);
|
||||
|
||||
#if __MonoCS__
|
||||
if (member is PropertyInfo pi)
|
||||
{
|
||||
if (!pi.CanRead)
|
||||
{
|
||||
throw Error.PropertyDoesNotHaveGetter(pi, nameof(member));
|
||||
}
|
||||
|
||||
memberType = pi.PropertyType;
|
||||
}
|
||||
else if (member is FieldInfo fi)
|
||||
{
|
||||
memberType = fi.FieldType;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Error.ArgumentMustBeFieldInfoOrPropertyInfo(nameof(member));
|
||||
}
|
||||
#else
|
||||
switch (member)
|
||||
{
|
||||
case PropertyInfo pi:
|
||||
@@ -145,6 +165,7 @@ namespace System.Linq.Expressions
|
||||
default:
|
||||
throw Error.ArgumentMustBeFieldInfoOrPropertyInfo(nameof(member));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void ValidateMemberInitArgs(Type type, ReadOnlyCollection<MemberBinding> bindings)
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace System.Linq.Expressions.Tests
|
||||
{
|
||||
ConstantExpression instance = Expression.Constant(new int[2,3]);
|
||||
ConstantExpression index = Expression.Constant(2);
|
||||
Assert.Throws<ArgumentException>(() => Expression.ArrayAccess(instance, index));
|
||||
AssertExtensions.Throws<ArgumentException>(null, () => Expression.ArrayAccess(instance, index));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -1 +1 @@
|
||||
484a44b822cf81dea641f5fdd78dc6323912be5c
|
||||
389b6d47b316f20c52847e6c98776e95d6654046
|
||||
@@ -1616,7 +1616,7 @@ namespace System.Linq.Expressions.Tests
|
||||
public static void UnreadableArray()
|
||||
{
|
||||
Expression array = Expression.Property(null, typeof(Unreadable<int[]>), nameof(Unreadable<int>.WriteOnly));
|
||||
Assert.Throws<ArgumentException>(() => Expression.ArrayLength(array));
|
||||
AssertExtensions.Throws<ArgumentException>("array", () => Expression.ArrayLength(array));
|
||||
}
|
||||
|
||||
private static IEnumerable<object[]> TestArrays()
|
||||
|
||||
@@ -285,5 +285,50 @@ namespace System.Linq.Expressions.Tests
|
||||
NewArrayExpression newArrayExpression = Expression.NewArrayBounds(typeof(string), bound0, bound1);
|
||||
AssertExtensions.Throws<ArgumentNullException>("expressions", () => newArrayExpression.Update(null));
|
||||
}
|
||||
|
||||
[Theory, ClassData(typeof(CompilationTypes))]
|
||||
public static void SingleNegativeBoundErrorMessage(bool useInterpreter)
|
||||
{
|
||||
string localizedMessage = null;
|
||||
try
|
||||
{
|
||||
int[] dummy = new int["".Length - 2];
|
||||
}
|
||||
catch (OverflowException oe)
|
||||
{
|
||||
localizedMessage = oe.Message;
|
||||
}
|
||||
|
||||
Expression<Func<int[]>> lambda =
|
||||
Expression.Lambda<Func<int[]>>(Expression.NewArrayBounds(typeof(int), Expression.Constant(-2)));
|
||||
var func = lambda.Compile(useInterpreter);
|
||||
OverflowException ex = Assert.Throws<OverflowException>(() => func());
|
||||
|
||||
if (!PlatformDetection.IsNetNative) // Exceptions do not always have messages
|
||||
Assert.Equal(localizedMessage, ex.Message);
|
||||
}
|
||||
|
||||
[Theory, ClassData(typeof(CompilationTypes))]
|
||||
public static void MultipleNegativeBoundErrorMessage(bool useInterpreter)
|
||||
{
|
||||
string localizedMessage = null;
|
||||
try
|
||||
{
|
||||
int[,,] dummy = new int[1, 1, "".Length - 2];
|
||||
}
|
||||
catch (OverflowException oe)
|
||||
{
|
||||
localizedMessage = oe.Message;
|
||||
}
|
||||
|
||||
Expression<Func<int[,,]>> lambda = Expression.Lambda<Func<int[,,]>>(
|
||||
Expression.NewArrayBounds(
|
||||
typeof(int), Expression.Constant(0), Expression.Constant(0), Expression.Constant(-2)));
|
||||
var func = lambda.Compile(useInterpreter);
|
||||
OverflowException ex = Assert.Throws<OverflowException>(() => func());
|
||||
|
||||
if (!PlatformDetection.IsNetNative) // Exceptions do not always have messages
|
||||
Assert.Equal(localizedMessage, ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1645,7 +1645,7 @@ namespace System.Linq.Expressions.Tests
|
||||
[Fact]
|
||||
public static void VoidType()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => Expression.NewArrayInit(typeof(void)));
|
||||
AssertExtensions.Throws<ArgumentException>("type", () => Expression.NewArrayInit(typeof(void)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -1665,7 +1665,7 @@ namespace System.Linq.Expressions.Tests
|
||||
[Fact]
|
||||
public static void ByRefType()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => Expression.NewArrayInit(typeof(int).MakeByRefType()));
|
||||
AssertExtensions.Throws<ArgumentException>("type", () => Expression.NewArrayInit(typeof(int).MakeByRefType()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -1677,14 +1677,14 @@ namespace System.Linq.Expressions.Tests
|
||||
[Fact]
|
||||
public static void GenericType()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => Expression.NewArrayInit(typeof(List<>)));
|
||||
AssertExtensions.Throws<ArgumentException>("type", () => Expression.NewArrayInit(typeof(List<>)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void TypeContainsGenericParameters()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => Expression.NewArrayInit(typeof(List<>.Enumerator)));
|
||||
Assert.Throws<ArgumentException>(() => Expression.NewArrayInit(typeof(List<>).MakeGenericType(typeof(List<>))));
|
||||
AssertExtensions.Throws<ArgumentException>("type", () => Expression.NewArrayInit(typeof(List<>.Enumerator)));
|
||||
AssertExtensions.Throws<ArgumentException>("type", () => Expression.NewArrayInit(typeof(List<>).MakeGenericType(typeof(List<>))));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -494,5 +494,36 @@ namespace System.Linq.Expressions.Tests
|
||||
)).Compile(useInterpreter);
|
||||
Assert.Equal(1, func());
|
||||
}
|
||||
|
||||
#if FEATURE_COMPILE
|
||||
[Fact]
|
||||
public static void VerifyIL_NullableIntCoalesceToNullableInt()
|
||||
{
|
||||
ParameterExpression x = Expression.Parameter(typeof(int?));
|
||||
ParameterExpression y = Expression.Parameter(typeof(int?));
|
||||
Expression<Func<int?, int?, int?>> f =
|
||||
Expression.Lambda<Func<int?, int?, int?>>(Expression.Coalesce(x, y), x, y);
|
||||
|
||||
f.VerifyIL(
|
||||
@".method valuetype [System.Private.CoreLib]System.Nullable`1<int32> ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure,valuetype [System.Private.CoreLib]System.Nullable`1<int32>,valuetype [System.Private.CoreLib]System.Nullable`1<int32>)
|
||||
{
|
||||
.maxstack 2
|
||||
.locals init (
|
||||
[0] valuetype [System.Private.CoreLib]System.Nullable`1<int32>
|
||||
)
|
||||
|
||||
IL_0000: ldarg.1
|
||||
IL_0001: stloc.0
|
||||
IL_0002: ldloca.s V_0
|
||||
IL_0004: call instance bool valuetype [System.Private.CoreLib]System.Nullable`1<int32>::get_HasValue()
|
||||
IL_0009: brfalse IL_0014
|
||||
IL_000e: ldloc.0
|
||||
IL_000f: br IL_0015
|
||||
IL_0014: ldarg.2
|
||||
IL_0015: ret
|
||||
}");
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -785,14 +785,14 @@ namespace System.Linq.Expressions.Tests
|
||||
public static void AndAlsoGlobalMethod()
|
||||
{
|
||||
MethodInfo method = GlobalMethod(typeof(int), new[] { typeof(int), typeof(int) });
|
||||
Assert.Throws<ArgumentException>(() => Expression.AndAlso(Expression.Constant(1), Expression.Constant(2), method));
|
||||
AssertExtensions.Throws<ArgumentException>(null, () => Expression.AndAlso(Expression.Constant(1), Expression.Constant(2), method));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void OrElseGlobalMethod()
|
||||
{
|
||||
MethodInfo method = GlobalMethod(typeof(int), new [] { typeof(int), typeof(int) });
|
||||
Assert.Throws<ArgumentException>(() => Expression.OrElse(Expression.Constant(1), Expression.Constant(2), method));
|
||||
AssertExtensions.Throws<ArgumentException>(null, () => Expression.OrElse(Expression.Constant(1), Expression.Constant(2), method));
|
||||
}
|
||||
|
||||
private static TypeBuilder GetTypeBuilder()
|
||||
|
||||
@@ -376,7 +376,7 @@ namespace System.Linq.Expressions.Tests
|
||||
Assert.Throws<ArgumentNullException>(() => children.CopyTo(null, 0));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => children.CopyTo(copyToTest, -1));
|
||||
Assert.All(copyToTest, Assert.Null); // assert partial copy didn't happen before exception
|
||||
Assert.Throws<ArgumentException>(() => children.CopyTo(copyToTest, 2));
|
||||
AssertExtensions.Throws<ArgumentException>(parCount >= 2 && parCount <= 5 ? null : "destinationArray", () => children.CopyTo(copyToTest, 2));
|
||||
Assert.All(copyToTest, Assert.Null);
|
||||
children.CopyTo(copyToTest, 1);
|
||||
Assert.Equal(copyToTest, exps.Prepend(null));
|
||||
|
||||
@@ -169,6 +169,41 @@ namespace System.Linq.Expressions.Tests
|
||||
Assert.Equal(expected, func());
|
||||
}
|
||||
|
||||
[Theory, PerCompilationType(nameof(ConditionalValues))]
|
||||
public void InvertedConditionalSelectsCorrectExpression(bool test, object ifTrue, object ifFalse, object expected, bool useInterpreter)
|
||||
{
|
||||
Func<object> func = Expression.Lambda<Func<object>>(
|
||||
Expression.Convert(
|
||||
Expression.Condition(
|
||||
Expression.Not(Expression.Constant(test)),
|
||||
Expression.Constant(ifFalse),
|
||||
Expression.Constant(ifTrue)
|
||||
),
|
||||
typeof(object)
|
||||
)
|
||||
).Compile(useInterpreter);
|
||||
|
||||
Assert.Equal(expected, func());
|
||||
}
|
||||
|
||||
|
||||
[Theory, PerCompilationType(nameof(ConditionalValues))]
|
||||
public void ConditionalWithMethodSelectsCorrectExpression(bool test, object ifTrue, object ifFalse, object expected, bool useInterpreter)
|
||||
{
|
||||
Func<object> func = Expression.Lambda<Func<object>>(
|
||||
Expression.Convert(
|
||||
Expression.Condition(
|
||||
Expression.Not(Expression.Constant(test), GetType().GetMethod(nameof(NotNot))),
|
||||
Expression.Constant(ifTrue),
|
||||
Expression.Constant(ifFalse)
|
||||
),
|
||||
typeof(object)
|
||||
)
|
||||
).Compile(useInterpreter);
|
||||
|
||||
Assert.Equal(expected, func());
|
||||
}
|
||||
|
||||
[Theory, PerCompilationType(nameof(ConditionalValuesWithTypes))]
|
||||
public void ConditionalSelectsCorrectExpressionWithType(bool test, object ifTrue, object ifFalse, object expected, Type type, bool useInterpreter)
|
||||
{
|
||||
@@ -187,7 +222,7 @@ namespace System.Linq.Expressions.Tests
|
||||
[Fact]
|
||||
public void ByRefType()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => Expression.Condition(
|
||||
AssertExtensions.Throws<ArgumentException>(null, () => Expression.Condition(
|
||||
Expression.Constant(true),
|
||||
Expression.Constant(null),
|
||||
Expression.Constant(null),
|
||||
@@ -197,7 +232,7 @@ namespace System.Linq.Expressions.Tests
|
||||
[Fact]
|
||||
public void PointerType()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => Expression.Condition(
|
||||
AssertExtensions.Throws<ArgumentException>(null, () => Expression.Condition(
|
||||
Expression.Constant(true),
|
||||
Expression.Constant(null),
|
||||
Expression.Constant(null),
|
||||
@@ -207,7 +242,7 @@ namespace System.Linq.Expressions.Tests
|
||||
[Fact]
|
||||
public void GenericType()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => Expression.Condition(
|
||||
AssertExtensions.Throws<ArgumentException>(null, () => Expression.Condition(
|
||||
Expression.Constant(true),
|
||||
Expression.Constant(null),
|
||||
Expression.Constant(null),
|
||||
@@ -217,12 +252,12 @@ namespace System.Linq.Expressions.Tests
|
||||
[Fact]
|
||||
public void TypeContainsGenericParameters()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => Expression.Condition(
|
||||
AssertExtensions.Throws<ArgumentException>(null, () => Expression.Condition(
|
||||
Expression.Constant(true),
|
||||
Expression.Constant(null),
|
||||
Expression.Constant(null),
|
||||
typeof(List<>.Enumerator)));
|
||||
Assert.Throws<ArgumentException>(() => Expression.Condition(
|
||||
AssertExtensions.Throws<ArgumentException>(null, () => Expression.Condition(
|
||||
Expression.Constant(true),
|
||||
Expression.Constant(null),
|
||||
Expression.Constant(null),
|
||||
@@ -270,5 +305,7 @@ namespace System.Linq.Expressions.Tests
|
||||
private class Visitor : ExpressionVisitor
|
||||
{
|
||||
}
|
||||
|
||||
public static bool NotNot(bool value) => value;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user