1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System.Dynamic.Utils;
6 
7 namespace System.Linq.Expressions.Interpreter
8 {
9     internal abstract class LeftShiftInstruction : Instruction
10     {
11         private static Instruction s_SByte, s_Int16, s_Int32, s_Int64, s_Byte, s_UInt16, s_UInt32, s_UInt64;
12 
13         public override int ConsumedStack => 2;
14         public override int ProducedStack => 1;
15         public override string InstructionName => "LeftShift";
16 
LeftShiftInstruction()17         private LeftShiftInstruction() { }
18 
19         private sealed class LeftShiftSByte : LeftShiftInstruction
20         {
Run(InterpretedFrame frame)21             public override int Run(InterpretedFrame frame)
22             {
23                 object shift = frame.Pop();
24                 object value = frame.Pop();
25                 if (value == null || shift == null)
26                 {
27                     frame.Push(null);
28                 }
29                 else
30                 {
31                     frame.Push(unchecked((sbyte)((sbyte)value << (int)shift)));
32                 }
33                 return 1;
34             }
35         }
36 
37         private sealed class LeftShiftInt16 : LeftShiftInstruction
38         {
Run(InterpretedFrame frame)39             public override int Run(InterpretedFrame frame)
40             {
41                 object shift = frame.Pop();
42                 object value = frame.Pop();
43                 if (value == null || shift == null)
44                 {
45                     frame.Push(null);
46                 }
47                 else
48                 {
49                     frame.Push(unchecked((short)((short)value << (int)shift)));
50                 }
51                 return 1;
52             }
53         }
54 
55         private sealed class LeftShiftInt32 : LeftShiftInstruction
56         {
Run(InterpretedFrame frame)57             public override int Run(InterpretedFrame frame)
58             {
59                 object shift = frame.Pop();
60                 object value = frame.Pop();
61                 if (value == null || shift == null)
62                 {
63                     frame.Push(null);
64                 }
65                 else
66                 {
67                     frame.Push((int)value << (int)shift);
68                 }
69                 return 1;
70             }
71         }
72 
73         private sealed class LeftShiftInt64 : LeftShiftInstruction
74         {
Run(InterpretedFrame frame)75             public override int Run(InterpretedFrame frame)
76             {
77                 object shift = frame.Pop();
78                 object value = frame.Pop();
79                 if (value == null || shift == null)
80                 {
81                     frame.Push(null);
82                 }
83                 else
84                 {
85                     frame.Push((long)value << (int)shift);
86                 }
87                 return 1;
88             }
89         }
90 
91         private sealed class LeftShiftByte : LeftShiftInstruction
92         {
Run(InterpretedFrame frame)93             public override int Run(InterpretedFrame frame)
94             {
95                 object shift = frame.Pop();
96                 object value = frame.Pop();
97                 if (value == null || shift == null)
98                 {
99                     frame.Push(null);
100                 }
101                 else
102                 {
103                     frame.Push(unchecked((byte)((byte)value << (int)shift)));
104                 }
105                 return 1;
106             }
107         }
108 
109         private sealed class LeftShiftUInt16 : LeftShiftInstruction
110         {
Run(InterpretedFrame frame)111             public override int Run(InterpretedFrame frame)
112             {
113                 object shift = frame.Pop();
114                 object value = frame.Pop();
115                 if (value == null || shift == null)
116                 {
117                     frame.Push(null);
118                 }
119                 else
120                 {
121                     frame.Push(unchecked((ushort)((ushort)value << (int)shift)));
122                 }
123                 return 1;
124             }
125         }
126 
127         private sealed class LeftShiftUInt32 : LeftShiftInstruction
128         {
Run(InterpretedFrame frame)129             public override int Run(InterpretedFrame frame)
130             {
131                 object shift = frame.Pop();
132                 object value = frame.Pop();
133                 if (value == null || shift == null)
134                 {
135                     frame.Push(null);
136                 }
137                 else
138                 {
139                     frame.Push((uint)value << (int)shift);
140                 }
141                 return 1;
142             }
143         }
144 
145         private sealed class LeftShiftUInt64 : LeftShiftInstruction
146         {
Run(InterpretedFrame frame)147             public override int Run(InterpretedFrame frame)
148             {
149                 object shift = frame.Pop();
150                 object value = frame.Pop();
151                 if (value == null || shift == null)
152                 {
153                     frame.Push(null);
154                 }
155                 else
156                 {
157                     frame.Push((ulong)value << (int)shift);
158                 }
159                 return 1;
160             }
161         }
162 
163         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
Create(Type type)164         public static Instruction Create(Type type)
165         {
166             switch (type.GetNonNullableType().GetTypeCode())
167             {
168                 case TypeCode.SByte: return s_SByte ?? (s_SByte = new LeftShiftSByte());
169                 case TypeCode.Int16: return s_Int16 ?? (s_Int16 = new LeftShiftInt16());
170                 case TypeCode.Int32: return s_Int32 ?? (s_Int32 = new LeftShiftInt32());
171                 case TypeCode.Int64: return s_Int64 ?? (s_Int64 = new LeftShiftInt64());
172                 case TypeCode.Byte: return s_Byte ?? (s_Byte = new LeftShiftByte());
173                 case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new LeftShiftUInt16());
174                 case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new LeftShiftUInt32());
175                 case TypeCode.UInt64: return s_UInt64 ?? (s_UInt64 = new LeftShiftUInt64());
176                 default:
177                     throw ContractUtils.Unreachable;
178             }
179         }
180     }
181 }
182