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