private void EmitRangeCheckedBranch(ConstantValue startConstant, ConstantValue endConstant, object targetLabel) { _builder.EmitLoad(_key); // Normalize the key to 0 if needed // Emit: ldc constant // sub if (!startConstant.IsDefaultValue) { _builder.EmitConstantValue(startConstant); _builder.EmitOpCode(ILOpCode.Sub); } if (_keyTypeCode.Is64BitIntegral()) { _builder.EmitLongConstant(endConstant.Int64Value - startConstant.Int64Value); } else { _builder.EmitIntConstant(endConstant.Int32Value - startConstant.Int32Value); } _builder.EmitBranch(ILOpCode.Ble_un, targetLabel, ILOpCode.Bgt_un); }
private void EmitRangeCheckIfNeeded(ConstantValue startConstant, ConstantValue endConstant, object bucketFallThroughLabel) { // switch treats key as an unsigned int. // this ensures that normalization does not introduce [over|under]flows issues with 32bit or shorter keys. // 64bit values, however must be checked before 32bit truncation happens. if (_keyTypeCode.Is64BitIntegral()) { // Dup(normalized); // if ((ulong)(normalized) > (ulong)(endConstant - startConstant)) // { // // not going to use it in the switch // Pop(normalized); // goto bucketFallThroughLabel; // } var inRangeLabel = new object(); _builder.EmitOpCode(ILOpCode.Dup); _builder.EmitLongConstant(endConstant.Int64Value - startConstant.Int64Value); _builder.EmitBranch(ILOpCode.Ble_un, inRangeLabel, ILOpCode.Bgt_un); _builder.EmitOpCode(ILOpCode.Pop); _builder.EmitBranch(ILOpCode.Br, bucketFallThroughLabel); // If we get to inRangeLabel, we should have key on stack, adjust for that. // builder cannot infer this since it has not seen all branches, // but it will verify that our Adjustment is valid when more branches are known. _builder.AdjustStack(+1); _builder.MarkLabel(inRangeLabel); } }
private void EmitRangeCheckedBranch( ConstantValue startConstant, ConstantValue endConstant, object targetLabel ) { _builder.EmitLoad(_key); // Normalize the key to 0 if needed // Emit: ldc constant // sub if (!startConstant.IsDefaultValue) { _builder.EmitConstantValue(startConstant); _builder.EmitOpCode(ILOpCode.Sub); } if (_keyTypeCode.Is64BitIntegral()) { _builder.EmitLongConstant(endConstant.Int64Value - startConstant.Int64Value); } else { int Int32Value(ConstantValue value) { // ConstantValue does not correctly convert byte and ushort values to int. // It sign extends them rather than padding them. We compensate for that here. // See also https://github.com/dotnet/roslyn/issues/18579 switch (value.Discriminator) { case ConstantValueTypeDiscriminator.Byte: return(value.ByteValue); case ConstantValueTypeDiscriminator.UInt16: return(value.UInt16Value); default: return(value.Int32Value); } } _builder.EmitIntConstant(Int32Value(endConstant) - Int32Value(startConstant)); } _builder.EmitBranch(ILOpCode.Ble_un, targetLabel, ILOpCode.Bgt_un); }