|
' 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.
Imports System.Reflection.Metadata
Imports Microsoft.CodeAnalysis.CodeGen
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen
Partial Friend Class CodeGenerator
Private Sub EmitUnaryOperatorExpression(expression As BoundUnaryOperator, used As Boolean)
Debug.Assert((expression.OperatorKind And Not UnaryOperatorKind.IntrinsicOpMask) = 0 AndAlso expression.OperatorKind <> 0)
If Not used AndAlso Not OperatorHasSideEffects(expression) Then
EmitExpression(expression.Operand, used:=False)
Return
End If
Select Case expression.OperatorKind
Case UnaryOperatorKind.Minus
' If overflow checking is on, we must subtract from zero because Neg doesn't
' check for overflow.
Dim targetPrimitiveType = expression.Type.PrimitiveTypeCode
Dim useCheckedSubtraction As Boolean = (expression.Checked AndAlso
(targetPrimitiveType = Cci.PrimitiveTypeCode.Int32 OrElse
targetPrimitiveType = Cci.PrimitiveTypeCode.Int64))
If useCheckedSubtraction Then
' Generate the zero const first.
_builder.EmitOpCode(ILOpCode.Ldc_i4_0)
If targetPrimitiveType = Cci.PrimitiveTypeCode.Int64 Then
_builder.EmitOpCode(ILOpCode.Conv_i8)
End If
End If
EmitExpression(expression.Operand, used:=True)
If useCheckedSubtraction Then
_builder.EmitOpCode(ILOpCode.Sub_ovf)
Else
_builder.EmitOpCode(ILOpCode.Neg)
End If
' The result of the math operation has either 4 or 8 byte width.
' For 1 and 2 byte widths, convert the value back to the original type.
DowncastResultOfArithmeticOperation(targetPrimitiveType, expression.Checked)
Case UnaryOperatorKind.Not
If expression.Type.IsBooleanType() Then
' ISSUE: Will this emit 0 for false and 1 for true or can it leave non-zero on the stack without mapping it to 1?
' Dev10 code gen made sure there is either 0 or 1 on the stack after this operation.
EmitCondExpr(expression.Operand, sense:=False)
Else
EmitExpression(expression.Operand, used:=True)
_builder.EmitOpCode(ILOpCode.Not)
' Since the CLR will generate a 4-byte result from the Not operation, we
' need to convert back to ui1 or ui2 because they are unsigned
' CONSIDER cambecc (8-2-2000): no need to generate a Convert for each of n consecutive
' Not operations
Dim targetPrimitiveType = expression.Type.PrimitiveTypeCode
If targetPrimitiveType = Cci.PrimitiveTypeCode.UInt8 OrElse
targetPrimitiveType = Cci.PrimitiveTypeCode.UInt16 Then
_builder.EmitNumericConversion(Cci.PrimitiveTypeCode.UInt32,
targetPrimitiveType, False)
End If
End If
Case UnaryOperatorKind.Plus
EmitExpression(expression.Operand, used:=True)
Case Else
Throw ExceptionUtilities.UnexpectedValue(expression.OperatorKind)
End Select
EmitPopIfUnused(used)
End Sub
Private Shared Function OperatorHasSideEffects(expression As BoundUnaryOperator) As Boolean
If expression.Checked AndAlso
expression.OperatorKind = UnaryOperatorKind.Minus AndAlso
expression.Type.IsIntegralType() Then
Return True
End If
Return False
End Function
Private Sub EmitBinaryOperatorExpression(expression As BoundBinaryOperator, used As Boolean)
Dim operationKind = expression.OperatorKind And BinaryOperatorKind.OpMask
Dim shortCircuit As Boolean = operationKind = BinaryOperatorKind.AndAlso OrElse operationKind = BinaryOperatorKind.OrElse
If Not used AndAlso Not shortCircuit AndAlso Not OperatorHasSideEffects(expression) Then
EmitExpression(expression.Left, False)
EmitExpression(expression.Right, False)
Return
End If
If IsCondOperator(operationKind) Then
EmitBinaryCondOperator(expression, True)
Else
EmitBinaryOperator(expression)
End If
EmitPopIfUnused(used)
End Sub
Private Function IsCondOperator(operationKind As BinaryOperatorKind) As Boolean
Select Case (operationKind And BinaryOperatorKind.OpMask)
Case BinaryOperatorKind.OrElse,
BinaryOperatorKind.AndAlso,
BinaryOperatorKind.Equals,
BinaryOperatorKind.NotEquals,
BinaryOperatorKind.LessThanOrEqual,
BinaryOperatorKind.GreaterThanOrEqual,
BinaryOperatorKind.LessThan,
BinaryOperatorKind.GreaterThan,
BinaryOperatorKind.Is,
BinaryOperatorKind.IsNot
Return True
Case Else
Return False
End Select
End Function
Private Function IsComparisonOperator(operationKind As BinaryOperatorKind) As Boolean
Select Case operationKind And BinaryOperatorKind.OpMask
Case BinaryOperatorKind.Equals,
BinaryOperatorKind.NotEquals,
BinaryOperatorKind.LessThanOrEqual,
BinaryOperatorKind.GreaterThanOrEqual,
BinaryOperatorKind.LessThan,
BinaryOperatorKind.GreaterThan,
BinaryOperatorKind.Is,
BinaryOperatorKind.IsNot
Return True
Case Else
Return False
End Select
End Function
Private Sub EmitBinaryOperator(expression As BoundBinaryOperator)
' Do not blow the stack due to a deep recursion on the left.
Dim child As BoundExpression = expression.Left
If child.Kind <> BoundKind.BinaryOperator OrElse child.ConstantValueOpt IsNot Nothing Then
EmitBinaryOperatorSimple(expression)
Return
End If
Dim binary As BoundBinaryOperator = DirectCast(child, BoundBinaryOperator)
If IsCondOperator(binary.OperatorKind) Then
EmitBinaryOperatorSimple(expression)
Return
End If
Dim stack = ArrayBuilder(Of BoundBinaryOperator).GetInstance()
stack.Push(expression)
Do
stack.Push(binary)
child = binary.Left
If child.Kind <> BoundKind.BinaryOperator OrElse child.ConstantValueOpt IsNot Nothing Then
Exit Do
End If
binary = DirectCast(child, BoundBinaryOperator)
If IsCondOperator(binary.OperatorKind) Then
Exit Do
End If
Loop
EmitExpression(child, True)
Do
binary = stack.Pop()
EmitExpression(binary.Right, True)
Select Case (binary.OperatorKind And BinaryOperatorKind.OpMask)
Case BinaryOperatorKind.And
_builder.EmitOpCode(ILOpCode.And)
Case BinaryOperatorKind.Xor
_builder.EmitOpCode(ILOpCode.Xor)
Case BinaryOperatorKind.Or
_builder.EmitOpCode(ILOpCode.Or)
Case Else
EmitBinaryArithOperatorInstructionAndDowncast(binary)
End Select
Loop While binary IsNot expression
Debug.Assert(stack.Count = 0)
stack.Free()
End Sub
Private Sub EmitBinaryOperatorSimple(expression As BoundBinaryOperator)
Select Case (expression.OperatorKind And BinaryOperatorKind.OpMask)
Case BinaryOperatorKind.And
EmitExpression(expression.Left, True)
EmitExpression(expression.Right, True)
_builder.EmitOpCode(ILOpCode.And)
Case BinaryOperatorKind.Xor
EmitExpression(expression.Left, True)
EmitExpression(expression.Right, True)
_builder.EmitOpCode(ILOpCode.Xor)
Case BinaryOperatorKind.Or
EmitExpression(expression.Left, True)
EmitExpression(expression.Right, True)
_builder.EmitOpCode(ILOpCode.Or)
Case Else
EmitBinaryArithOperator(expression)
End Select
End Sub
Private Function OperatorHasSideEffects(expression As BoundBinaryOperator) As Boolean
Dim type = expression.OperatorKind And BinaryOperatorKind.OpMask
Select Case type
Case BinaryOperatorKind.Divide,
BinaryOperatorKind.Modulo,
BinaryOperatorKind.IntegerDivide
Return True
Case BinaryOperatorKind.Multiply,
BinaryOperatorKind.Add,
BinaryOperatorKind.Subtract
Return expression.Checked AndAlso expression.Type.IsIntegralType()
Case Else
Return False
End Select
End Function
Private Sub EmitBinaryArithOperator(expression As BoundBinaryOperator)
EmitExpression(expression.Left, True)
EmitExpression(expression.Right, True)
EmitBinaryArithOperatorInstructionAndDowncast(expression)
End Sub
Private Sub EmitBinaryArithOperatorInstructionAndDowncast(expression As BoundBinaryOperator)
Dim targetPrimitiveType = expression.Type.PrimitiveTypeCode
Dim opKind = expression.OperatorKind And BinaryOperatorKind.OpMask
Select Case opKind
Case BinaryOperatorKind.Multiply
If expression.Checked AndAlso
(targetPrimitiveType = Cci.PrimitiveTypeCode.Int32 OrElse targetPrimitiveType = Cci.PrimitiveTypeCode.Int64) Then
_builder.EmitOpCode(ILOpCode.Mul_ovf)
ElseIf expression.Checked AndAlso
(targetPrimitiveType = Cci.PrimitiveTypeCode.UInt32 OrElse targetPrimitiveType = Cci.PrimitiveTypeCode.UInt64) Then
_builder.EmitOpCode(ILOpCode.Mul_ovf_un)
Else
_builder.EmitOpCode(ILOpCode.Mul)
End If
Case BinaryOperatorKind.Modulo
If targetPrimitiveType.IsUnsigned() Then
_builder.EmitOpCode(ILOpCode.Rem_un)
Else
_builder.EmitOpCode(ILOpCode.[Rem])
End If
Case BinaryOperatorKind.Add
If expression.Checked AndAlso
(targetPrimitiveType = Cci.PrimitiveTypeCode.Int32 OrElse targetPrimitiveType = Cci.PrimitiveTypeCode.Int64) Then
_builder.EmitOpCode(ILOpCode.Add_ovf)
ElseIf expression.Checked AndAlso
(targetPrimitiveType = Cci.PrimitiveTypeCode.UInt32 OrElse targetPrimitiveType = Cci.PrimitiveTypeCode.UInt64) Then
_builder.EmitOpCode(ILOpCode.Add_ovf_un)
Else
_builder.EmitOpCode(ILOpCode.Add)
End If
Case BinaryOperatorKind.Subtract
If expression.Checked AndAlso
(targetPrimitiveType = Cci.PrimitiveTypeCode.Int32 OrElse targetPrimitiveType = Cci.PrimitiveTypeCode.Int64) Then
_builder.EmitOpCode(ILOpCode.Sub_ovf)
ElseIf expression.Checked AndAlso
(targetPrimitiveType = Cci.PrimitiveTypeCode.UInt32 OrElse targetPrimitiveType = Cci.PrimitiveTypeCode.UInt64) Then
_builder.EmitOpCode(ILOpCode.Sub_ovf_un)
Else
_builder.EmitOpCode(ILOpCode.Sub)
End If
Case BinaryOperatorKind.Divide,
BinaryOperatorKind.IntegerDivide
If targetPrimitiveType.IsUnsigned() Then
_builder.EmitOpCode(ILOpCode.Div_un)
Else
_builder.EmitOpCode(ILOpCode.Div)
End If
Case BinaryOperatorKind.LeftShift
' And the right operand with mask corresponding the left operand type
Debug.Assert(expression.Right.Type.PrimitiveTypeCode = Cci.PrimitiveTypeCode.Int32)
'mask RHS if not a constant or too large
Dim shiftMax = GetShiftSizeMask(expression.Left.Type)
Dim shiftConst = expression.Right.ConstantValueOpt
If shiftConst Is Nothing OrElse shiftConst.UInt32Value > shiftMax Then
_builder.EmitConstantValue(ConstantValue.Create(shiftMax))
_builder.EmitOpCode(ILOpCode.And)
End If
_builder.EmitOpCode(ILOpCode.Shl)
Case BinaryOperatorKind.RightShift
' And the right operand with mask corresponding the left operand type
Debug.Assert(expression.Right.Type.PrimitiveTypeCode = Cci.PrimitiveTypeCode.Int32)
'mask RHS if not a constant or too large
Dim shiftMax = GetShiftSizeMask(expression.Left.Type)
Dim shiftConst = expression.Right.ConstantValueOpt
If shiftConst Is Nothing OrElse shiftConst.UInt32Value > shiftMax Then
_builder.EmitConstantValue(ConstantValue.Create(shiftMax))
_builder.EmitOpCode(ILOpCode.And)
End If
If targetPrimitiveType.IsUnsigned() Then
_builder.EmitOpCode(ILOpCode.Shr_un)
Else
_builder.EmitOpCode(ILOpCode.Shr)
End If
Case Else
' BinaryOperatorKind.Power, BinaryOperatorKind.Like and BinaryOperatorKind.Concatenate should go here.
Throw ExceptionUtilities.UnexpectedValue(opKind)
End Select
' The result of the math operation has either 4 or 8 byte width.
' For 1 and 2 byte widths, convert the value back to the original type.
DowncastResultOfArithmeticOperation(targetPrimitiveType, expression.Checked AndAlso
opKind <> BinaryOperatorKind.LeftShift AndAlso
opKind <> BinaryOperatorKind.RightShift)
End Sub
Private Sub DowncastResultOfArithmeticOperation(
targetPrimitiveType As Cci.PrimitiveTypeCode,
isChecked As Boolean
)
' The result of the math operation has either 4 or 8 byte width.
' For 1 and 2 byte widths, convert the value back to the original type.
If targetPrimitiveType = Cci.PrimitiveTypeCode.Int8 OrElse
targetPrimitiveType = Cci.PrimitiveTypeCode.UInt8 OrElse
targetPrimitiveType = Cci.PrimitiveTypeCode.Int16 OrElse
targetPrimitiveType = Cci.PrimitiveTypeCode.UInt16 Then
_builder.EmitNumericConversion(If(targetPrimitiveType.IsUnsigned(), Cci.PrimitiveTypeCode.UInt32, Cci.PrimitiveTypeCode.Int32),
targetPrimitiveType,
isChecked)
End If
End Sub
Public Shared Function GetShiftSizeMask(leftOperandType As TypeSymbol) As Integer
Return leftOperandType.GetEnumUnderlyingTypeOrSelf.SpecialType.GetShiftSizeMask()
End Function
Private Sub EmitShortCircuitingOperator(condition As BoundBinaryOperator, sense As Boolean, stopSense As Boolean, stopValue As Boolean)
' we generate:
'
' gotoif (a == stopSense) fallThrough
' b == sense
' goto labEnd
' fallThrough:
' stopValue
' labEnd:
' AND OR
' +- ------ -----
' stopSense | !sense sense
' stopValue | 0 1
Dim fallThrough As Object = Nothing
EmitCondBranch(condition.Left, fallThrough, stopSense)
EmitCondExpr(condition.Right, sense)
' if fall-through was not initialized, no-one is going to take that branch
' and we are done with Right on the stack
If fallThrough Is Nothing Then
Return
End If
Dim labEnd = New Object
_builder.EmitBranch(ILOpCode.Br, labEnd)
' if we get to FallThrough we should not have Right on the stack. Adjust for that.
_builder.AdjustStack(-1)
_builder.MarkLabel(fallThrough)
_builder.EmitBoolConstant(stopValue)
_builder.MarkLabel(labEnd)
End Sub
'NOTE: odd positions assume inverted sense
Private Shared ReadOnly s_compOpCodes As ILOpCode() = New ILOpCode() {ILOpCode.Clt, ILOpCode.Cgt, ILOpCode.Cgt, ILOpCode.Clt, ILOpCode.Clt_un, ILOpCode.Cgt_un, ILOpCode.Cgt_un, ILOpCode.Clt_un, ILOpCode.Clt, ILOpCode.Cgt_un, ILOpCode.Cgt, ILOpCode.Clt_un}
'NOTE: The result of this should be a boolean on the stack.
Private Sub EmitBinaryCondOperator(binOp As BoundBinaryOperator, sense As Boolean)
Dim andOrSense As Boolean = sense
Dim opIdx As Integer
Dim opKind = (binOp.OperatorKind And BinaryOperatorKind.OpMask)
Dim operandType = binOp.Left.Type
Debug.Assert(operandType IsNot Nothing OrElse (binOp.Left.IsNothingLiteral() AndAlso (opKind = BinaryOperatorKind.Is OrElse opKind = BinaryOperatorKind.IsNot)))
If operandType IsNot Nothing AndAlso operandType.IsBooleanType() Then
' Since VB True is -1 but is stored as 1 in IL, relational operations on Boolean must
' be reversed to yield the correct results. Note that = and <> do not need reversal.
Select Case opKind
Case BinaryOperatorKind.LessThan
opKind = BinaryOperatorKind.GreaterThan
Case BinaryOperatorKind.LessThanOrEqual
opKind = BinaryOperatorKind.GreaterThanOrEqual
Case BinaryOperatorKind.GreaterThan
opKind = BinaryOperatorKind.LessThan
Case BinaryOperatorKind.GreaterThanOrEqual
opKind = BinaryOperatorKind.LessThanOrEqual
End Select
End If
Select Case opKind
Case BinaryOperatorKind.OrElse
andOrSense = Not andOrSense
GoTo BinaryOperatorKindLogicalAnd
Case BinaryOperatorKind.AndAlso
BinaryOperatorKindLogicalAnd:
Debug.Assert(binOp.Left.Type.SpecialType = SpecialType.System_Boolean)
Debug.Assert(binOp.Right.Type.SpecialType = SpecialType.System_Boolean)
If Not andOrSense Then
EmitShortCircuitingOperator(binOp, sense, sense, True)
Else
EmitShortCircuitingOperator(binOp, sense, Not sense, False)
End If
Return
Case BinaryOperatorKind.IsNot
ValidateReferenceEqualityOperands(binOp)
GoTo BinaryOperatorKindNotEqual
Case BinaryOperatorKind.Is
ValidateReferenceEqualityOperands(binOp)
GoTo BinaryOperatorKindEqual
Case BinaryOperatorKind.NotEquals
BinaryOperatorKindNotEqual:
sense = Not sense
GoTo BinaryOperatorKindEqual
Case BinaryOperatorKind.Equals
BinaryOperatorKindEqual:
Dim constant = binOp.Left.ConstantValueOpt
Dim comparand = binOp.Right
If constant Is Nothing Then
constant = comparand.ConstantValueOpt
comparand = binOp.Left
End If
If constant IsNot Nothing Then
If constant.IsDefaultValue Then
If Not constant.IsFloating Then
If sense Then
EmitIsNullOrZero(comparand, constant)
Else
' obj != null/0 for pointers and integral numerics is emitted as cgt.un
EmitIsNotNullOrZero(comparand, constant)
End If
Return
End If
ElseIf constant.IsBoolean Then
' treat "x = True" ==> "x"
EmitExpression(comparand, True)
EmitIsSense(sense)
Return
End If
End If
EmitBinaryCondOperatorHelper(ILOpCode.Ceq, binOp.Left, binOp.Right, sense)
Return
Case BinaryOperatorKind.Or
Debug.Assert(binOp.Left.Type.SpecialType = SpecialType.System_Boolean)
Debug.Assert(binOp.Right.Type.SpecialType = SpecialType.System_Boolean)
EmitBinaryCondOperatorHelper(ILOpCode.Or, binOp.Left, binOp.Right, sense)
Return
Case BinaryOperatorKind.And
Debug.Assert(binOp.Left.Type.SpecialType = SpecialType.System_Boolean)
Debug.Assert(binOp.Right.Type.SpecialType = SpecialType.System_Boolean)
EmitBinaryCondOperatorHelper(ILOpCode.And, binOp.Left, binOp.Right, sense)
Return
Case BinaryOperatorKind.Xor
Debug.Assert(binOp.Left.Type.SpecialType = SpecialType.System_Boolean)
Debug.Assert(binOp.Right.Type.SpecialType = SpecialType.System_Boolean)
' Xor is equivalent to not equal.
If (sense) Then
EmitBinaryCondOperatorHelper(ILOpCode.Xor, binOp.Left, binOp.Right, True)
Else
EmitBinaryCondOperatorHelper(ILOpCode.Ceq, binOp.Left, binOp.Right, True)
End If
Return
Case BinaryOperatorKind.LessThan
opIdx = 0
Case BinaryOperatorKind.LessThanOrEqual
opIdx = 1
sense = Not sense
Case BinaryOperatorKind.GreaterThan
opIdx = 2
Case BinaryOperatorKind.GreaterThanOrEqual
opIdx = 3
sense = Not sense
Case Else
Throw ExceptionUtilities.UnexpectedValue(opKind)
End Select
If operandType IsNot Nothing Then
If operandType.IsUnsignedIntegralType() Then
opIdx += 4
Else
If operandType.IsFloatingType() Then
opIdx += 8
End If
End If
End If
EmitBinaryCondOperatorHelper(s_compOpCodes(opIdx), binOp.Left, binOp.Right, sense)
Return
End Sub
Private Sub EmitIsNotNullOrZero(comparand As BoundExpression, nullOrZero As ConstantValue)
EmitExpression(comparand, True)
Dim comparandType = comparand.Type
If comparandType.IsReferenceType AndAlso Not IsVerifierReference(comparandType) Then
EmitBox(comparandType, comparand.Syntax)
End If
_builder.EmitConstantValue(nullOrZero)
_builder.EmitOpCode(ILOpCode.Cgt_un)
End Sub
Private Sub EmitIsNullOrZero(comparand As BoundExpression, nullOrZero As ConstantValue)
EmitExpression(comparand, True)
Dim comparandType = comparand.Type
If comparandType.IsReferenceType AndAlso Not IsVerifierReference(comparandType) Then
EmitBox(comparandType, comparand.Syntax)
End If
_builder.EmitConstantValue(nullOrZero)
_builder.EmitOpCode(ILOpCode.Ceq)
End Sub
Private Sub EmitBinaryCondOperatorHelper(opCode As ILOpCode,
left As BoundExpression,
right As BoundExpression,
sense As Boolean)
EmitExpression(left, True)
EmitExpression(right, True)
_builder.EmitOpCode(opCode)
EmitIsSense(sense)
End Sub
' generate a conditional (ie, boolean) expression...
' this will leave a value on the stack which conforms to sense, ie:(condition == sense)
Private Function EmitCondExpr(condition As BoundExpression, sense As Boolean) As ConstResKind
RemoveNegation(condition, sense)
Debug.Assert(condition.Type.SpecialType = SpecialType.System_Boolean)
If _ilEmitStyle = ILEmitStyle.Release AndAlso condition.IsConstant Then
Dim constValue = condition.ConstantValueOpt
Debug.Assert(constValue.IsBoolean)
Dim constant = constValue.BooleanValue
_builder.EmitBoolConstant(constant = sense)
Return (If(constant = sense, ConstResKind.ConstTrue, ConstResKind.ConstFalse))
End If
If condition.Kind = BoundKind.BinaryOperator Then
Dim binOp = DirectCast(condition, BoundBinaryOperator)
EmitBinaryCondOperator(binOp, sense)
Return ConstResKind.NotAConst
End If
EmitExpression(condition, True)
EmitIsSense(sense)
Return ConstResKind.NotAConst
End Function
''' <summary>
''' Emits boolean expression without branching if possible (i.e., no logical operators, only comparisons).
''' Leaves a boolean (int32, 0 or 1) value on the stack which conforms to sense, i.e., <c>condition = sense</c>.
''' </summary>
Private Function TryEmitComparison(condition As BoundExpression, sense As Boolean) As Boolean
RemoveNegation(condition, sense)
Debug.Assert(condition.Type.SpecialType = SpecialType.System_Boolean)
If condition.IsConstant Then
Dim constValue = condition.ConstantValueOpt
Debug.Assert(constValue.IsBoolean)
Dim constant = constValue.BooleanValue
_builder.EmitBoolConstant(constant = sense)
Return True
End If
If condition.Kind = BoundKind.BinaryOperator Then
Dim binOp = DirectCast(condition, BoundBinaryOperator)
' Intentionally don't optimize logical operators, they need branches to short-circuit.
If IsComparisonOperator(binOp.OperatorKind) Then
EmitBinaryCondOperator(binOp, sense)
Return True
End If
ElseIf condition.Kind = BoundKind.TypeOf Then
Dim typeOfExpression = DirectCast(condition, BoundTypeOf)
EmitTypeOfExpression(typeOfExpression, used:=True, optimize:=True)
If typeOfExpression.IsTypeOfIsNotExpression Then
sense = Not sense
End If
' Convert to 1 or 0.
_builder.EmitOpCode(ILOpCode.Ldnull)
_builder.EmitOpCode(If(sense, ILOpCode.Cgt_un, ILOpCode.Ceq))
Return True
Else
EmitExpression(condition, used:=True)
' Convert to 1 or 0 (although `condition` is of type `Boolean`, it can contain any integer).
_builder.EmitOpCode(ILOpCode.Ldc_i4_0)
_builder.EmitOpCode(If(sense, ILOpCode.Cgt_un, ILOpCode.Ceq))
Return True
End If
Return False
End Function
Private Sub RemoveNegation(ByRef condition As BoundExpression, ByRef sense As Boolean)
While condition.Kind = BoundKind.UnaryOperator
Dim unOp = DirectCast(condition, BoundUnaryOperator)
Debug.Assert(unOp.OperatorKind = UnaryOperatorKind.Not AndAlso unOp.Type.IsBooleanType())
condition = unOp.Operand
sense = Not sense
End While
End Sub
' emits IsTrue/IsFalse according to the sense
' IsTrue actually does nothing
Private Sub EmitIsSense(sense As Boolean)
If Not sense Then
_builder.EmitOpCode(ILOpCode.Ldc_i4_0)
_builder.EmitOpCode(ILOpCode.Ceq)
End If
End Sub
End Class
End Namespace
|