Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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);
            }
        }
Ejemplo n.º 3
0
        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);
        }