11using AsmResolver . PE . DotNet . Cil ;
22using Echo . Memory ;
3+ using Echo . Platforms . AsmResolver . Emulation . Stack ;
34using Echo . Platforms . AsmResolver . Tests . Mock ;
45using Xunit ;
56
@@ -13,44 +14,241 @@ public ConvHandlerTest(MockModuleFixture fixture)
1314 }
1415
1516 [ Theory ]
16- [ InlineData ( 0x7f , CilCode . Conv_I1 , 0x7fL ) ]
17- [ InlineData ( 0x7f , CilCode . Conv_Ovf_I1 , 0x7fL ) ]
18- [ InlineData ( 0x80 , CilCode . Conv_I1 , - 0x80L ) ]
19- [ InlineData ( 0x80 , CilCode . Conv_Ovf_I1 , null ) ]
20- [ InlineData ( 0x80 , CilCode . Conv_I2 , 0x80L ) ]
21- [ InlineData ( 0x7fff , CilCode . Conv_I2 , 0x7fffL ) ]
22- [ InlineData ( 0x8000 , CilCode . Conv_I2 , - 0x8000L ) ]
23- [ InlineData ( 0x8000 , CilCode . Conv_Ovf_I2 , null ) ]
24- [ InlineData ( 0x7fffffff , CilCode . Conv_I4 , 0x7fffffffL ) ]
25- [ InlineData ( 0x80000000 , CilCode . Conv_I4 , - 0x80000000L ) ]
26- [ InlineData ( 0x80000000 , CilCode . Conv_Ovf_I4 , null ) ]
27- public void ConvIToI ( long value , CilCode code , long ? expectedValue )
17+ [ InlineData ( 0x7f , CilCode . Conv_I1 , 0x7f ) ]
18+ [ InlineData ( 0x7f , CilCode . Conv_Ovf_I1 , 0x7f ) ]
19+ [ InlineData ( 0x80 , CilCode . Conv_I1 , - 0x80 ) ]
20+ [ InlineData ( - 1 , CilCode . Conv_I1 , - 1 ) ]
21+ [ InlineData ( 0x1ff , CilCode . Conv_I1 , - 1 ) ]
22+ [ InlineData ( 0x80 , CilCode . Conv_I2 , 0x80 ) ]
23+ [ InlineData ( 0x7fff , CilCode . Conv_I2 , 0x7fff ) ]
24+ [ InlineData ( 0x8000 , CilCode . Conv_I2 , - 0x8000 ) ]
25+ [ InlineData ( 0x1ffff , CilCode . Conv_I2 , - 1 ) ]
26+ [ InlineData ( 0x7fffffff , CilCode . Conv_I4 , 0x7fffffff ) ]
27+ [ InlineData ( 0x80000000L , CilCode . Conv_I4 , - 0x80000000 ) ]
28+ [ InlineData ( 0x1ffffffffL , CilCode . Conv_I4 , - 1 ) ]
29+ [ InlineData ( - 1 , CilCode . Conv_I8 , - 1 ) ]
30+ [ InlineData ( 0 , CilCode . Conv_I8 , 0 ) ]
31+ [ InlineData ( 0x7fffffffL , CilCode . Conv_I8 , 0x7fffffff ) ]
32+ public void ConvIToI ( long value , CilCode code , long expectedValue )
2833 {
2934 var stack = Context . CurrentFrame . EvaluationStack ;
3035
3136 stack . Push ( new BitVector ( value ) , Context . Machine . ContextModule . CorLibTypeFactory . Int64 ) ;
3237
3338 var result = Dispatcher . Dispatch ( Context , new CilInstruction ( code . ToOpCode ( ) ) ) ;
34-
35- Assert . Equal ( expectedValue . HasValue , result . IsSuccess ) ;
36- if ( result . IsSuccess )
37- Assert . Equal ( expectedValue ! . Value , stack . Peek ( ) . Contents . Resize ( 64 , true ) . AsSpan ( ) . I64 ) ;
39+
40+ Assert . True ( result . IsSuccess ) ;
41+ var span = stack . Peek ( ) . Contents . AsSpan ( ) ;
42+ if ( code . ToOpCode ( ) . StackBehaviourPush == CilStackBehaviour . PushI8 )
43+ Assert . Equal ( expectedValue , span . I64 ) ;
44+ else
45+ Assert . Equal ( ( int ) expectedValue , span . I32 ) ;
46+ }
47+
48+ [ Theory ]
49+ [ InlineData ( 0x42 , CilCode . Conv_U1 , 0x42 ) ]
50+ [ InlineData ( 0xff , CilCode . Conv_U1 , 0xff ) ]
51+ [ InlineData ( 0x1ff , CilCode . Conv_U1 , 0xff ) ]
52+ [ InlineData ( - 1 , CilCode . Conv_U1 , 0xff ) ]
53+ [ InlineData ( 0x1234 , CilCode . Conv_U2 , 0x1234 ) ]
54+ [ InlineData ( 0xffff , CilCode . Conv_U2 , 0xffff ) ]
55+ [ InlineData ( 0x1ffff , CilCode . Conv_U2 , 0xffff ) ]
56+ [ InlineData ( - 1 , CilCode . Conv_U2 , 0xffff ) ]
57+ [ InlineData ( 0x12345678 , CilCode . Conv_U4 , 0x12345678 ) ]
58+ [ InlineData ( 0xffffffffL , CilCode . Conv_U4 , unchecked ( ( int ) 0xffffffff ) ) ]
59+ [ InlineData ( 0x1ffffffffL , CilCode . Conv_U4 , unchecked ( ( int ) 0xffffffff ) ) ]
60+ [ InlineData ( - 1 , CilCode . Conv_U4 , unchecked ( ( int ) 0xffffffff ) ) ]
61+ [ InlineData ( 42 , CilCode . Conv_U8 , 42 ) ]
62+ [ InlineData ( 0 , CilCode . Conv_U8 , 0 ) ]
63+ [ InlineData ( - 1 , CilCode . Conv_U8 , - 1 ) ]
64+ public void ConvIToU ( long value , CilCode code , long expectedValue )
65+ {
66+ var stack = Context . CurrentFrame . EvaluationStack ;
67+
68+ stack . Push ( new BitVector ( value ) , Context . Machine . ContextModule . CorLibTypeFactory . Int64 ) ;
69+
70+ var result = Dispatcher . Dispatch ( Context , new CilInstruction ( code . ToOpCode ( ) ) ) ;
71+
72+ Assert . True ( result . IsSuccess ) ;
73+ var span = stack . Peek ( ) . Contents . AsSpan ( ) ;
74+ if ( code . ToOpCode ( ) . StackBehaviourPush == CilStackBehaviour . PushI8 )
75+ Assert . Equal ( expectedValue , span . I64 ) ;
76+ else
77+ Assert . Equal ( ( int ) expectedValue , span . I32 ) ;
78+ }
79+
80+ [ Theory ]
81+ [ InlineData ( 42 , CilCode . Conv_R4 , 42.0f ) ]
82+ [ InlineData ( - 1 , CilCode . Conv_R4 , - 1.0f ) ]
83+ [ InlineData ( 0 , CilCode . Conv_R4 , 0.0f ) ]
84+ [ InlineData ( 0x1_0000_0000L , CilCode . Conv_R4 , 4294967296.0f ) ]
85+ [ InlineData ( ( long ) int . MaxValue , CilCode . Conv_R4 , ( float ) int . MaxValue ) ]
86+ [ InlineData ( ( long ) int . MinValue , CilCode . Conv_R4 , ( float ) int . MinValue ) ]
87+ public void ConvIToR4 ( long value , CilCode code , float expectedValue )
88+ {
89+ var stack = Context . CurrentFrame . EvaluationStack ;
90+
91+ stack . Push ( new BitVector ( value ) , Context . Machine . ContextModule . CorLibTypeFactory . Int64 ) ;
92+
93+ var result = Dispatcher . Dispatch ( Context , new CilInstruction ( code . ToOpCode ( ) ) ) ;
94+
95+ Assert . True ( result . IsSuccess ) ;
96+ Assert . Equal ( expectedValue , stack . Peek ( ) . Contents . AsSpan ( ) . F32 ) ;
97+ }
98+
99+ [ Theory ]
100+ [ InlineData ( 42 , CilCode . Conv_R8 , 42.0d ) ]
101+ [ InlineData ( - 1 , CilCode . Conv_R8 , - 1.0d ) ]
102+ [ InlineData ( 0 , CilCode . Conv_R8 , 0.0d ) ]
103+ [ InlineData ( 0x1_0000_0000L , CilCode . Conv_R8 , 4294967296.0d ) ]
104+ [ InlineData ( ( long ) int . MaxValue , CilCode . Conv_R8 , ( double ) int . MaxValue ) ]
105+ [ InlineData ( ( long ) int . MinValue , CilCode . Conv_R8 , ( double ) int . MinValue ) ]
106+ public void ConvIToR8 ( long value , CilCode code , double expectedValue )
107+ {
108+ var stack = Context . CurrentFrame . EvaluationStack ;
109+
110+ stack . Push ( new BitVector ( value ) , Context . Machine . ContextModule . CorLibTypeFactory . Int64 ) ;
111+
112+ var result = Dispatcher . Dispatch ( Context , new CilInstruction ( code . ToOpCode ( ) ) ) ;
113+
114+ Assert . True ( result . IsSuccess ) ;
115+ Assert . Equal ( expectedValue , stack . Peek ( ) . Contents . AsSpan ( ) . F64 ) ;
116+ }
117+
118+ [ Fact ]
119+ public void ConvUnknownFloatToR4ShouldHaveFloatTypeHint ( )
120+ {
121+ var stack = Context . CurrentFrame . EvaluationStack ;
122+
123+ stack . Push ( new StackSlot ( new BitVector ( 64 , false ) , StackSlotTypeHint . Float ) ) ;
124+
125+ var result = Dispatcher . Dispatch ( Context , new CilInstruction ( CilOpCodes . Conv_R4 ) ) ;
126+
127+ Assert . True ( result . IsSuccess ) ;
128+ Assert . Equal ( StackSlotTypeHint . Float , stack . Peek ( ) . TypeHint ) ;
129+ }
130+
131+ [ Fact ]
132+ public void ConvUnknownFloatToI4ShouldHaveIntegerTypeHint ( )
133+ {
134+ var stack = Context . CurrentFrame . EvaluationStack ;
135+
136+ stack . Push ( new StackSlot ( new BitVector ( 64 , false ) , StackSlotTypeHint . Float ) ) ;
137+
138+ var result = Dispatcher . Dispatch ( Context , new CilInstruction ( CilOpCodes . Conv_I4 ) ) ;
139+
140+ Assert . True ( result . IsSuccess ) ;
141+ Assert . Equal ( StackSlotTypeHint . Integer , stack . Peek ( ) . TypeHint ) ;
142+ }
143+
144+ [ Theory ]
145+ [ InlineData ( 1.0d , CilCode . Conv_I1 , 1 ) ]
146+ [ InlineData ( - 1.0d , CilCode . Conv_I1 , - 1 ) ]
147+ [ InlineData ( 100.9d , CilCode . Conv_I1 , 100 ) ]
148+ [ InlineData ( 1.0d , CilCode . Conv_I2 , 1 ) ]
149+ [ InlineData ( - 1.0d , CilCode . Conv_I2 , - 1 ) ]
150+ [ InlineData ( 1000.9d , CilCode . Conv_I2 , 1000 ) ]
151+ [ InlineData ( 1.0d , CilCode . Conv_I4 , 1 ) ]
152+ [ InlineData ( - 1.0d , CilCode . Conv_I4 , - 1 ) ]
153+ [ InlineData ( 3.7d , CilCode . Conv_I4 , 3 ) ]
154+ [ InlineData ( - 3.7d , CilCode . Conv_I4 , - 3 ) ]
155+ [ InlineData ( 0.0d , CilCode . Conv_I4 , 0 ) ]
156+ [ InlineData ( 0.0d , CilCode . Conv_I8 , 0 ) ]
157+ [ InlineData ( 42.0d , CilCode . Conv_I8 , 42 ) ]
158+ [ InlineData ( - 1.0d , CilCode . Conv_I8 , - 1 ) ]
159+ [ InlineData ( 99999.9d , CilCode . Conv_I8 , 99999 ) ]
160+ public void ConvRToI ( double value , CilCode code , long expectedValue )
161+ {
162+ var stack = Context . CurrentFrame . EvaluationStack ;
163+
164+ stack . Push ( new BitVector ( value ) , Context . Machine . ContextModule . CorLibTypeFactory . Double ) ;
165+
166+ var result = Dispatcher . Dispatch ( Context , new CilInstruction ( code . ToOpCode ( ) ) ) ;
167+
168+ Assert . True ( result . IsSuccess ) ;
169+ var span = stack . Peek ( ) . Contents . AsSpan ( ) ;
170+ if ( code . ToOpCode ( ) . StackBehaviourPush == CilStackBehaviour . PushI8 )
171+ Assert . Equal ( expectedValue , span . I64 ) ;
172+ else
173+ Assert . Equal ( ( int ) expectedValue , span . I32 ) ;
174+ }
175+
176+ [ Theory ]
177+ [ InlineData ( 42.0d , CilCode . Conv_U1 , 42 ) ]
178+ [ InlineData ( 0.0d , CilCode . Conv_U1 , 0 ) ]
179+ [ InlineData ( 200.9d , CilCode . Conv_U1 , 200 ) ]
180+ [ InlineData ( 42.0d , CilCode . Conv_U2 , 42 ) ]
181+ [ InlineData ( 0.0d , CilCode . Conv_U2 , 0 ) ]
182+ [ InlineData ( 50000.9d , CilCode . Conv_U2 , 50000 ) ]
183+ [ InlineData ( 42.0d , CilCode . Conv_U4 , 42 ) ]
184+ [ InlineData ( 3.7d , CilCode . Conv_U4 , 3 ) ]
185+ [ InlineData ( 0.0d , CilCode . Conv_U4 , 0 ) ]
186+ [ InlineData ( 42.0d , CilCode . Conv_U8 , 42 ) ]
187+ [ InlineData ( 0.0d , CilCode . Conv_U8 , 0 ) ]
188+ [ InlineData ( 99999.9d , CilCode . Conv_U8 , 99999 ) ]
189+ public void ConvRToU ( double value , CilCode code , long expectedValue )
190+ {
191+ var stack = Context . CurrentFrame . EvaluationStack ;
192+
193+ stack . Push ( new BitVector ( value ) , Context . Machine . ContextModule . CorLibTypeFactory . Double ) ;
194+
195+ var result = Dispatcher . Dispatch ( Context , new CilInstruction ( code . ToOpCode ( ) ) ) ;
196+
197+ Assert . True ( result . IsSuccess ) ;
198+ var span = stack . Peek ( ) . Contents . AsSpan ( ) ;
199+ if ( code . ToOpCode ( ) . StackBehaviourPush == CilStackBehaviour . PushI8 )
200+ Assert . Equal ( expectedValue , span . I64 ) ;
201+ else
202+ Assert . Equal ( ( int ) expectedValue , span . I32 ) ;
38203 }
39204
40205 [ Theory ]
41- [ InlineData ( 1.0 , CilCode . Conv_I4 , 1L ) ]
42- [ InlineData ( - 1.0 , CilCode . Conv_I4 , - 1L ) ]
43- public void ConvFToI ( double value , CilCode code , long ? expectedValue )
206+ [ InlineData ( 0x80 , CilCode . Conv_Ovf_I1 ) ]
207+ [ InlineData ( - 0x81 , CilCode . Conv_Ovf_I1 ) ]
208+ [ InlineData ( 0x8000 , CilCode . Conv_Ovf_I2 ) ]
209+ [ InlineData ( - 0x8001 , CilCode . Conv_Ovf_I2 ) ]
210+ [ InlineData ( 0x80000000L , CilCode . Conv_Ovf_I4 ) ]
211+ [ InlineData ( 0x100 , CilCode . Conv_Ovf_U1 ) ]
212+ [ InlineData ( - 1 , CilCode . Conv_Ovf_U1 ) ]
213+ [ InlineData ( 0x10000 , CilCode . Conv_Ovf_U2 ) ]
214+ [ InlineData ( - 1 , CilCode . Conv_Ovf_U2 ) ]
215+ [ InlineData ( 0x100000000L , CilCode . Conv_Ovf_U4 ) ]
216+ [ InlineData ( - 1 , CilCode . Conv_Ovf_U4 ) ]
217+ public void ConvIOvfShouldOverflow ( long value , CilCode code )
218+ {
219+ var stack = Context . CurrentFrame . EvaluationStack ;
220+
221+ stack . Push ( new BitVector ( value ) , Context . Machine . ContextModule . CorLibTypeFactory . Int64 ) ;
222+
223+ var result = Dispatcher . Dispatch ( Context , new CilInstruction ( code . ToOpCode ( ) ) ) ;
224+
225+ Assert . False ( result . IsSuccess ) ;
226+ Assert . False ( result . ExceptionObject . IsNull ) ;
227+ Assert . Equal ( result . ExceptionObject . GetObjectType ( ) , Context . Machine . ValueFactory . OverflowExceptionType ) ;
228+ }
229+
230+ [ Theory ]
231+ [ InlineData ( - 1.0d , CilCode . Conv_Ovf_U1 ) ]
232+ [ InlineData ( 256.0d , CilCode . Conv_Ovf_U1 ) ]
233+ [ InlineData ( - 1.0d , CilCode . Conv_Ovf_U2 ) ]
234+ [ InlineData ( 65536.0d , CilCode . Conv_Ovf_U2 ) ]
235+ [ InlineData ( - 1.0d , CilCode . Conv_Ovf_U4 ) ]
236+ [ InlineData ( - 1.0d , CilCode . Conv_Ovf_U8 ) ]
237+ [ InlineData ( 128.0d , CilCode . Conv_Ovf_I1 ) ]
238+ [ InlineData ( - 129.0d , CilCode . Conv_Ovf_I1 ) ]
239+ [ InlineData ( 32768.0d , CilCode . Conv_Ovf_I2 ) ]
240+ [ InlineData ( - 32769.0d , CilCode . Conv_Ovf_I2 ) ]
241+ public void ConvROvfShouldOverflow ( double value , CilCode code )
44242 {
45243 var stack = Context . CurrentFrame . EvaluationStack ;
46244
47245 stack . Push ( new BitVector ( value ) , Context . Machine . ContextModule . CorLibTypeFactory . Double ) ;
48246
49247 var result = Dispatcher . Dispatch ( Context , new CilInstruction ( code . ToOpCode ( ) ) ) ;
50-
51- Assert . Equal ( expectedValue . HasValue , result . IsSuccess ) ;
52- if ( result . IsSuccess )
53- Assert . Equal ( expectedValue ! . Value , stack . Peek ( ) . Contents . Resize ( 64 , true ) . AsSpan ( ) . I64 ) ;
248+
249+ Assert . False ( result . IsSuccess ) ;
250+ Assert . False ( result . ExceptionObject . IsNull ) ;
251+ Assert . Equal ( result . ExceptionObject . GetObjectType ( ) , Context . Machine . ValueFactory . OverflowExceptionType ) ;
54252 }
55253 }
56254}
0 commit comments