File: Semantics\CompileTimeCalculations.vb
Web Access
Project: src\src\Compilers\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.vbproj (Microsoft.CodeAnalysis.VisualBasic)
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
' See the LICENSE file in the project root for more information.
 
Option Strict On
Option Explicit On
Option Infer On
 
Imports System.Runtime.CompilerServices
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
 
Namespace Microsoft.CodeAnalysis.VisualBasic
 
    Friend Module CompileTimeCalculations
 
        Friend Function UncheckedCLng(v As ULong) As Long
            Return CType(v, Long)
        End Function
 
        Friend Function UncheckedCLng(v As Double) As Long
            Return CType(v, Long)
        End Function
 
        Friend Function UncheckedCULng(v As Long) As ULong
            Return CType(v, ULong)
        End Function
 
        Friend Function UncheckedCULng(v As Integer) As ULong
            Return CType(v, ULong)
        End Function
 
        Friend Function UncheckedCULng(v As Double) As ULong
            Return CType(v, ULong)
        End Function
 
        Friend Function UncheckedCInt(v As ULong) As Integer
            Return CType(v, Integer)
        End Function
 
        Friend Function UncheckedCInt(v As Long) As Integer
            Return CType(v, Integer)
        End Function
 
        Friend Function UncheckedCUInt(v As ULong) As UInteger
            Return CType(v, UInteger)
        End Function
 
        Friend Function UncheckedCUInt(v As Long) As UInteger
            Return CType(v, UInteger)
        End Function
 
        Friend Function UncheckedCUInt(v As Integer) As UInteger
            Return CType(v, UInteger)
        End Function
 
        Friend Function UncheckedCShort(v As ULong) As Short
            Return CType(v, Short)
        End Function
 
        Friend Function UncheckedCShort(v As Long) As Short
            Return CType(v, Short)
        End Function
 
        Friend Function UncheckedCShort(v As Integer) As Short
            Return CType(v, Short)
        End Function
 
        Friend Function UncheckedCShort(v As UShort) As Short
            Return CType(v, Short)
        End Function
 
        Friend Function UncheckedCInt(v As UInteger) As Integer
            Return CType(v, Integer)
        End Function
 
        Friend Function UncheckedCShort(v As UInteger) As Short
            Return CType(v, Short)
        End Function
 
        Friend Function UncheckedCUShort(v As Short) As UShort
            Return CType(v, UShort)
        End Function
 
        Friend Function UncheckedCUShort(v As Integer) As UShort
            Return CType(v, UShort)
        End Function
 
        Friend Function UncheckedCUShort(v As Long) As UShort
            Return CType(v, UShort)
        End Function
 
        Friend Function UncheckedCByte(v As SByte) As Byte
            Return CType(v, Byte)
        End Function
 
        Friend Function UncheckedCByte(v As Integer) As Byte
            Return CType(v, Byte)
        End Function
 
        Friend Function UncheckedCByte(v As Long) As Byte
            Return CType(v, Byte)
        End Function
 
        Friend Function UncheckedCByte(v As UShort) As Byte
            Return CType(v, Byte)
        End Function
 
        Friend Function UncheckedCSByte(v As Byte) As SByte
            Return CType(v, SByte)
        End Function
 
        Friend Function UncheckedCSByte(v As Integer) As SByte
            Return CType(v, SByte)
        End Function
 
        Friend Function UncheckedCSByte(v As Long) As SByte
            Return CType(v, SByte)
        End Function
 
        Friend Function UncheckedMul(x As Integer, y As Integer) As Integer
            Return x * y
        End Function
 
        Friend Function UncheckedMul(x As Long, y As Long) As Long
            Return x * y
        End Function
 
        Friend Function UncheckedIntegralDiv(x As Long, y As Long) As Long
            If y = -1 Then
                Return UncheckedNegate(x)
            End If
 
            Return x \ y
        End Function
 
        Private Function UncheckedAdd(x As Long, y As Long) As Long
            Return x + y
        End Function
 
        Private Function UncheckedNegate(x As Long) As Long
            Return -x
        End Function
 
        Friend Function GetConstantValueAsInt64(ByRef value As ConstantValue) As Long
            Select Case (value.Discriminator)
                Case ConstantValueTypeDiscriminator.SByte : Return value.SByteValue
                Case ConstantValueTypeDiscriminator.Byte : Return value.ByteValue
                Case ConstantValueTypeDiscriminator.Int16 : Return value.Int16Value
                Case ConstantValueTypeDiscriminator.UInt16 : Return value.UInt16Value
                Case ConstantValueTypeDiscriminator.Int32 : Return value.Int32Value
                Case ConstantValueTypeDiscriminator.UInt32 : Return value.UInt32Value
                Case ConstantValueTypeDiscriminator.Int64 : Return value.Int64Value
                Case ConstantValueTypeDiscriminator.UInt64 : Return UncheckedCLng(value.UInt64Value)
                Case ConstantValueTypeDiscriminator.Char : Return AscW(value.CharValue)
                Case ConstantValueTypeDiscriminator.Boolean : Return If(value.BooleanValue, 1, 0)
                Case ConstantValueTypeDiscriminator.DateTime : Return value.DateTimeValue.Ticks
                Case Else : Throw ExceptionUtilities.UnexpectedValue(value.Discriminator)
            End Select
        End Function
 
        Friend Function GetConstantValue(type As ConstantValueTypeDiscriminator, value As Long) As ConstantValue
            Dim result As ConstantValue
 
            Select Case (type)
                Case ConstantValueTypeDiscriminator.SByte : result = ConstantValue.Create(UncheckedCSByte(value))
                Case ConstantValueTypeDiscriminator.Byte : result = ConstantValue.Create(UncheckedCByte(value))
                Case ConstantValueTypeDiscriminator.Int16 : result = ConstantValue.Create(UncheckedCShort(value))
                Case ConstantValueTypeDiscriminator.UInt16 : result = ConstantValue.Create(UncheckedCUShort(value))
                Case ConstantValueTypeDiscriminator.Int32 : result = ConstantValue.Create(UncheckedCInt(value))
                Case ConstantValueTypeDiscriminator.UInt32 : result = ConstantValue.Create(UncheckedCUInt(value))
                Case ConstantValueTypeDiscriminator.Int64 : result = ConstantValue.Create(value)
                Case ConstantValueTypeDiscriminator.UInt64 : result = ConstantValue.Create(UncheckedCULng(value))
                Case ConstantValueTypeDiscriminator.Char : result = ConstantValue.Create(ChrW(UncheckedCInt(value)))
                Case ConstantValueTypeDiscriminator.Boolean : result = ConstantValue.Create(If(value = 0, False, True))
                Case ConstantValueTypeDiscriminator.DateTime : result = ConstantValue.Create(New DateTime(value))
                Case Else : Throw ExceptionUtilities.UnexpectedValue(type)
            End Select
 
            Debug.Assert(result.Discriminator = type)
 
            Return result
        End Function
 
        Friend Function NarrowIntegralResult(
            sourceValue As Long,
            sourceType As ConstantValueTypeDiscriminator,
            resultType As ConstantValueTypeDiscriminator,
            ByRef overflow As Boolean
        ) As Long
            Dim resultValue As Long = 0
 
            Select Case (resultType)
 
                Case ConstantValueTypeDiscriminator.Boolean
                    resultValue = If(sourceValue = 0, 0, 1)
                    Return resultValue
 
                Case ConstantValueTypeDiscriminator.SByte
                    resultValue = UncheckedCSByte(sourceValue)
 
                Case ConstantValueTypeDiscriminator.Byte
                    resultValue = UncheckedCByte(sourceValue)
 
                Case ConstantValueTypeDiscriminator.Int16
                    resultValue = UncheckedCShort(sourceValue)
 
                Case ConstantValueTypeDiscriminator.UInt16
                    resultValue = UncheckedCUShort(sourceValue)
 
                Case ConstantValueTypeDiscriminator.Int32
                    resultValue = UncheckedCInt(sourceValue)
 
                Case ConstantValueTypeDiscriminator.UInt32
                    resultValue = UncheckedCUInt(sourceValue)
 
                Case ConstantValueTypeDiscriminator.Int64
                    resultValue = sourceValue
 
                Case ConstantValueTypeDiscriminator.UInt64
                    resultValue = sourceValue 'UncheckedCLng(UncheckedCULng(SourceValue))
 
                Case ConstantValueTypeDiscriminator.Char
                    resultValue = UncheckedCUShort(sourceValue)
                    ' // ?? overflow?
 
                Case Else
                    Throw ExceptionUtilities.UnexpectedValue(resultType)
            End Select
 
            If Not ConstantValue.IsBooleanType(sourceType) AndAlso
                 (ConstantValue.IsUnsignedIntegralType(sourceType) Xor ConstantValue.IsUnsignedIntegralType(resultType)) Then
                ' // If source is a signed type and is a negative value or
                ' // target is a signed type and results in a negative
                ' // value, indicate overflow.
                If Not ConstantValue.IsUnsignedIntegralType(sourceType) Then
                    If sourceValue < 0 Then
                        overflow = True
                    End If
                Else
                    Debug.Assert(Not ConstantValue.IsUnsignedIntegralType(resultType), "Expected signed Target type!!!")
 
                    If resultValue < 0 Then
                        overflow = True
                    End If
                End If
            End If
 
            If resultValue <> sourceValue Then
                overflow = True
            End If
 
            Return resultValue
        End Function
 
        Friend Function NarrowIntegralResult(
            sourceValue As Long,
            sourceType As SpecialType,
            resultType As SpecialType,
            ByRef overflow As Boolean
        ) As Long
            Return NarrowIntegralResult(sourceValue,
                                        sourceType.ToConstantValueDiscriminator(),
                                        resultType.ToConstantValueDiscriminator(),
                                        overflow)
        End Function
 
        ''' <summary>
        ''' Narrow a quadword result to a specific integral type, setting Overflow true
        ''' if the result value cannot be represented in the result type.
        ''' </summary>
        Friend Function NarrowIntegralResult(
                        sourceValue As Long,
                        sourceType As TypeSymbol,
                        resultType As TypeSymbol,
                        ByRef overflow As Boolean) As Long
 
            Debug.Assert(sourceType.IsIntegralType() OrElse sourceType.IsBooleanType() OrElse sourceType.IsCharType(),
                        "Unexpected source type passed in to conversion function!!!")
 
            Return NarrowIntegralResult(sourceValue,
                                        sourceType.GetConstantValueTypeDiscriminator(),
                                        resultType.GetConstantValueTypeDiscriminator(),
                                        overflow)
        End Function
 
        Friend Function ConvertIntegralValue(
            sourceValue As Long,
            sourceType As ConstantValueTypeDiscriminator,
            targetType As ConstantValueTypeDiscriminator,
            ByRef integerOverflow As Boolean
        ) As ConstantValue
 
            Debug.Assert(ConstantValue.IsIntegralType(sourceType) OrElse ConstantValue.IsBooleanType(sourceType) OrElse ConstantValue.IsCharType(sourceType),
                "Unexpected source type passed in to conversion function!!!")
 
            If ConstantValue.IsIntegralType(targetType) OrElse ConstantValue.IsBooleanType(targetType) OrElse ConstantValue.IsCharType(targetType) Then
                Return GetConstantValue(targetType, NarrowIntegralResult(sourceValue, sourceType, targetType, integerOverflow))
            End If
 
            If ConstantValue.IsStringType(targetType) Then
                'This is correct only if the input type is Char.
                If ConstantValue.IsCharType(sourceType) Then
                    Return ConstantValue.Create(New String(ChrW(UncheckedCInt(sourceValue)), 1))
                End If
            End If
 
            If ConstantValue.IsFloatingType(targetType) Then
                Return ConvertFloatingValue(
                            If(ConstantValue.IsUnsignedIntegralType(sourceType), CType(UncheckedCULng(sourceValue), Double), CType(sourceValue, Double)),
                            targetType,
                            integerOverflow)
            End If
 
            If ConstantValue.IsDecimalType(targetType) Then
 
                Dim resultValue As Decimal
 
                Dim sign As Boolean
 
                If Not ConstantValue.IsUnsignedIntegralType(sourceType) AndAlso sourceValue < 0 Then
                    ' // Negative numbers need converted to positive and set the negative sign bit
                    sign = True
                    sourceValue = -sourceValue
                Else
                    sign = False
                End If
 
                Dim lo32 As Integer = UncheckedCInt(sourceValue And &HFFFFFFFF)
                ' // We include the sign bit here because we negated a negative above, so the
                ' // only number that still has the sign bit set is the maximum negative number
                ' // (which has no positive counterpart)
                Dim mid32 As Integer = UncheckedCInt((sourceValue And &HFFFFFFFF00000000) >> 32)
                Dim hi32 As Integer = 0
                Dim scale As Byte = 0
 
                resultValue = New Decimal(lo32, mid32, hi32, sign, scale)
 
                Return ConvertDecimalValue(resultValue, targetType, integerOverflow)
            End If
 
            Throw ExceptionUtilities.Unreachable()
        End Function
 
        Friend Function ConvertFloatingValue(
            sourceValue As Double,
                        targetType As ConstantValueTypeDiscriminator,
            ByRef integerOverflow As Boolean
        ) As ConstantValue
 
            Dim overflow As Boolean = False
 
            If (ConstantValue.IsBooleanType(targetType)) Then
 
                Return ConvertIntegralValue(If(sourceValue = 0.0, 0, 1),
                                            ConstantValueTypeDiscriminator.Int64,
                                            targetType,
                                            integerOverflow)
            End If
 
            If ConstantValue.IsIntegralType(targetType) OrElse ConstantValue.IsCharType(targetType) Then
 
                overflow = DetectFloatingToIntegralOverflow(sourceValue, ConstantValue.IsUnsignedIntegralType(targetType))
 
                If Not overflow Then
                    Dim integralValue As Long
                    Dim temporary As Double
                    Dim floor As Double
                    Dim sourceIntegralType As ConstantValueTypeDiscriminator
 
                    ' // VB has different rounding behavior than C by default. Ensure we
                    ' // are using the right type of rounding
 
                    temporary = sourceValue + 0.5
 
                    ' // We had a number that was equally close to 2 integers.
                    ' // We need to return the even one.
                    floor = Math.Floor(temporary)
 
                    '[AlekseyT]: Using Math.IEEERemainder as a replacement for fmod.
                    If floor <> temporary OrElse Math.IEEERemainder(temporary, 2.0) = 0 Then
                        integralValue = If(IsUnsignedLongType(targetType), ConvertFloatingToUI64(floor), UncheckedCLng(floor))
                    Else
                        integralValue = If(IsUnsignedLongType(targetType), ConvertFloatingToUI64(floor - 1.0), UncheckedCLng(floor - 1.0))
                    End If
 
                    If sourceValue < 0 Then
                        sourceIntegralType = ConstantValueTypeDiscriminator.Int64
                    Else
                        sourceIntegralType = ConstantValueTypeDiscriminator.UInt64
                    End If
 
                    Return ConvertIntegralValue(integralValue,
                                                sourceIntegralType,
                                                targetType,
                                                integerOverflow)
                End If
            End If
 
            If ConstantValue.IsFloatingType(targetType) Then
                Dim resultValue As Double = NarrowFloatingResult(sourceValue, targetType, overflow)
 
                ' // We have decided to ignore overflows in compile-time evaluation
                ' // of floating expressions.
 
                If targetType = ConstantValueTypeDiscriminator.Single Then
                    Return ConstantValue.Create(CType(resultValue, Single))
                End If
 
                Debug.Assert(targetType = ConstantValueTypeDiscriminator.Double)
                Return ConstantValue.Create(resultValue)
            End If
 
            If ConstantValue.IsDecimalType(targetType) Then
                Dim resultValue As Decimal
 
                Try
                    resultValue = Convert.ToDecimal(sourceValue)
                Catch ex As OverflowException
                    overflow = True
                End Try
 
                If Not overflow Then
                    Return ConvertDecimalValue(resultValue, targetType, integerOverflow)
                End If
            End If
 
            If overflow Then
                Return ConstantValue.Bad
            End If
 
            Throw ExceptionUtilities.Unreachable()
        End Function
 
        Friend Function ConvertDecimalValue(
            sourceValue As Decimal,
            targetType As ConstantValueTypeDiscriminator,
            ByRef integerOverflow As Boolean
        ) As ConstantValue
 
            Dim overflow As Boolean = False
 
            If ConstantValue.IsIntegralType(targetType) OrElse ConstantValue.IsCharType(targetType) Then
                Dim isNegative As Boolean
                Dim scale As Byte
                Dim low, mid, high As UInteger
                sourceValue.GetBits(isNegative, scale, low, mid, high)
 
                If scale = 0 Then
                    Dim resultValue As Long
 
                    ' Easy case: no scale factor.
                    overflow = high <> 0
 
                    If Not overflow Then
                        resultValue = (CLng(mid) << 32) Or low
 
                        Dim sourceIntegralType As ConstantValueTypeDiscriminator = Nothing
 
                        If isNegative Then
                            ' The source value is negative, so we need to negate the result value.
                            ' If the result type is unsigned, or the result value is already
                            ' large enough that it consumes the sign bit, then we have overflowed.
                            If ConstantValue.IsUnsignedIntegralType(targetType) OrElse
                               UncheckedCULng(resultValue) > &H8000000000000000UL Then
                                overflow = True
                            Else
                                resultValue = UncheckedNegate(resultValue)
                                sourceIntegralType = ConstantValueTypeDiscriminator.Int64
                            End If
                        Else
                            sourceIntegralType = ConstantValueTypeDiscriminator.UInt64
                        End If
 
                        If Not overflow Then
                            Return ConvertIntegralValue(resultValue,
                                                        sourceIntegralType,
                                                        targetType,
                                                        integerOverflow)
                        End If
                    End If
 
                Else
                    Dim resultValue As Double
 
                    ' // No overflow possible
                    resultValue = Decimal.ToDouble(sourceValue)
 
                    Return ConvertFloatingValue(resultValue,
                                                targetType,
                                                integerOverflow)
                End If
            End If
 
            If ConstantValue.IsFloatingType(targetType) OrElse ConstantValue.IsBooleanType(targetType) Then
                Dim resultValue As Double
 
                ' // No overflow possible
                resultValue = Decimal.ToDouble(sourceValue)
 
                Return ConvertFloatingValue(resultValue,
                                            targetType,
                                            integerOverflow)
            End If
 
            If ConstantValue.IsDecimalType(targetType) Then
                Return ConstantValue.Create(sourceValue)
            End If
 
            If overflow Then
                Return ConstantValue.Bad
            End If
 
            Throw ExceptionUtilities.Unreachable()
        End Function
 
        Friend Function NarrowFloatingResult(
            value As Double,
            resultType As ConstantValueTypeDiscriminator,
            ByRef overflow As Boolean
        ) As Double
 
            If Double.IsNaN(value) Then
                overflow = True
            End If
 
            Select Case (resultType)
 
                Case ConstantValueTypeDiscriminator.Double
                    Return value
 
                Case ConstantValueTypeDiscriminator.Single
 
                    If value > Single.MaxValue OrElse value < Single.MinValue Then
                        overflow = True
                    End If
 
                    Return CType(value, Single)
 
                Case Else
                    Throw ExceptionUtilities.UnexpectedValue(resultType)
            End Select
 
            Return value
        End Function
 
        Friend Function NarrowFloatingResult(
                value As Double,
                resultType As SpecialType,
                ByRef overflow As Boolean
            ) As Double
 
            If Double.IsNaN(value) Then
                overflow = True
            End If
 
            Select Case resultType
                Case SpecialType.System_Double
                    Return value
 
                Case SpecialType.System_Single
                    If value > Single.MaxValue OrElse value < Single.MinValue Then
                        overflow = True
                    End If
 
                    Return CType(value, Single)
 
                Case Else
                    Throw ExceptionUtilities.UnexpectedValue(resultType)
            End Select
 
            Return value
        End Function
 
        Private Function DetectFloatingToIntegralOverflow(
            sourceValue As Double,
            isUnsigned As Boolean
        ) As Boolean
 
            If isUnsigned Then
                ' // this code is shared by fjitdef.h
                If sourceValue < &HF000000000000000UL Then
                    If sourceValue > -1 Then
                        Return False
                    End If
                Else
                    Dim temporary As Double = (sourceValue - &HF000000000000000UL)
 
                    If temporary < &H7000000000000000L AndAlso UncheckedCLng(temporary) < &H1000000000000000L Then
                        Return False
                    End If
                End If
            Else
                ' // this code is shared by fjitdef.h
                If sourceValue < -&H7000000000000000L Then
                    Dim temporary As Double = sourceValue - (-&H7000000000000000L)
 
                    If temporary > -&H7000000000000000L AndAlso UncheckedCLng(temporary) > -&H1000000000000001L Then
                        Return False
                    End If
                Else
                    If sourceValue > &H7000000000000000L Then
                        Dim temporary As Double = (sourceValue - &H7000000000000000L)
 
                        If temporary < &H7000000000000000L AndAlso UncheckedCLng(temporary) < &H1000000000000000L Then
                            Return False
                        End If
                    Else
                        Return False
                    End If
                End If
            End If
 
            Return True
        End Function
 
        Private Function ConvertFloatingToUI64(sourceValue As Double) As Long
            ' // Conversion from double to uint64 is annoyingly implemented by the
            ' // VC++ compiler as (uint64)(int64)(double)val, so we have to do it by hand.
 
            Dim result As Long
 
            ' // code below stolen from jit...
            Dim two63 As Double = 2147483648.0 * 4294967296.0
 
            If sourceValue < two63 Then
                result = UncheckedCLng(sourceValue)
            Else
                result = UncheckedAdd(UncheckedCLng(sourceValue - two63), &H8000000000000000)
            End If
 
            Return result
        End Function
 
        Private Function IsUnsignedLongType(type As ConstantValueTypeDiscriminator) As Boolean
            Return type = ConstantValueTypeDiscriminator.UInt64
        End Function
 
        Friend Function TypeAllowsCompileTimeConversions(type As ConstantValueTypeDiscriminator) As Boolean
            Return TypeAllowsCompileTimeOperations(type)
        End Function
 
        Friend Function TypeAllowsCompileTimeOperations(type As ConstantValueTypeDiscriminator) As Boolean
            Select Case (type)
                Case ConstantValueTypeDiscriminator.Boolean,
                     ConstantValueTypeDiscriminator.SByte,
                     ConstantValueTypeDiscriminator.Byte,
                     ConstantValueTypeDiscriminator.Int16,
                     ConstantValueTypeDiscriminator.UInt16,
                     ConstantValueTypeDiscriminator.Int32,
                     ConstantValueTypeDiscriminator.UInt32,
                     ConstantValueTypeDiscriminator.Int64,
                     ConstantValueTypeDiscriminator.UInt64,
                     ConstantValueTypeDiscriminator.Char,
                     ConstantValueTypeDiscriminator.Decimal,
                     ConstantValueTypeDiscriminator.Double,
                     ConstantValueTypeDiscriminator.Single,
                     ConstantValueTypeDiscriminator.DateTime,
                     ConstantValueTypeDiscriminator.String
 
                    Return True
 
                Case Else
                    Return False
            End Select
 
        End Function
 
        Friend Function AdjustConstantValueFromMetadata(value As ConstantValue, targetType As TypeSymbol, isByRefParamValue As Boolean) As ConstantValue
            ' See MetaImport::DecodeValue in Dev10 compiler.
 
            If targetType Is Nothing OrElse targetType.IsErrorType() Then
                Return value
            End If
 
            Select Case value.Discriminator
 
                Case ConstantValueTypeDiscriminator.Int32
 
                    ' Adding the test for Object here is necessary in order to
                    ' make something like "Optional Byref X As Object = 5" work.
                    If targetType.IsIntrinsicType() OrElse
                       targetType.IsEnumType() OrElse
                       targetType.IsObjectType() OrElse
                       (targetType.IsNullableType() AndAlso targetType.GetNullableUnderlyingType().IsIntrinsicType()) Then
                        'No change
                        Exit Select
                    End If
 
                    If isByRefParamValue OrElse
                        (Not targetType.IsTypeParameter() AndAlso
                         Not targetType.IsArrayType() AndAlso
                         targetType.IsReferenceType()) Then
 
                        ' // REVIEW: are there other byref types besides Integer and enums
                        ' //         that might need to be handled here?
                        ' // ByRef Integer, and ByRef Enum (that is stored as I4)
                        ' // are pointer types, but optional values are not pointers
 
                        ' // COM+ encodes pointer constants as I4's
                        ' // CONSIDER LATER AnthonyL 8/21/00: Does this t_ref workaround move to I8 on a 64-bit machine?
 
                        ' // MattGe: Back out part of 604868 to address build lab issue #4093
                        ' // Probably just need to #ifdef this differently for 64bit, but
                        ' // will let Cameron decide.
                        ' //Value.Integral = (__int32)*(WIN64_UNALIGNED void **)pvValue;
 
                        If value.Int32Value = 0 Then
                            value = ConstantValue.Nothing
                        Else
                            value = ConstantValue.Bad
                        End If
                    End If
 
                Case ConstantValueTypeDiscriminator.Int64
 
                    If targetType.IsDateTimeType() Then
                        value = ConstantValue.Create(New DateTime(value.Int64Value))
                    End If
            End Select
 
            Return value
        End Function
 
        Friend Function Multiply(
            leftValue As Long,
            rightValue As Long,
            sourceType As SpecialType,
            resultType As SpecialType,
            ByRef integerOverflow As Boolean
        ) As Long
            Return Multiply(leftValue, rightValue,
                            sourceType.ToConstantValueDiscriminator(),
                            resultType.ToConstantValueDiscriminator(),
                            integerOverflow)
        End Function
 
        Friend Function Multiply(
            leftValue As Long,
            rightValue As Long,
            sourceType As ConstantValueTypeDiscriminator,
            resultType As ConstantValueTypeDiscriminator,
            ByRef integerOverflow As Boolean
        ) As Long
 
            Dim ResultValue = NarrowIntegralResult(
                                    UncheckedMul(leftValue, rightValue),
                                    sourceType,
                                    resultType,
                                    integerOverflow)
 
            If ConstantValue.IsUnsignedIntegralType(resultType) Then
                If rightValue <> 0 AndAlso
                     UncheckedCULng(ResultValue) / UncheckedCULng(rightValue) <> UncheckedCULng(leftValue) Then
 
                    integerOverflow = True
                End If
            Else
                If (leftValue > 0 AndAlso rightValue > 0 AndAlso ResultValue <= 0) OrElse
                    (leftValue < 0 AndAlso rightValue < 0 AndAlso ResultValue <= 0) OrElse
                    (leftValue > 0 AndAlso rightValue < 0 AndAlso ResultValue >= 0) OrElse
                    (leftValue < 0 AndAlso rightValue > 0 AndAlso ResultValue >= 0) OrElse
                    (rightValue <> 0 AndAlso ResultValue / rightValue <> leftValue) Then
 
                    integerOverflow = True
                End If
            End If
 
            Return ResultValue
        End Function
    End Module
 
End Namespace