private void ClrCompare(QilNodeType relOp, XmlTypeCode code) {
OpCode opcode;
Label lblTrue;
switch (this.iterCurr.CurrentBranchingContext) {
case BranchingContext.OnFalse:
// Reverse the comparison operator
// Use Bxx_Un OpCodes to handle NaN case for double and single types
if (code == XmlTypeCode.Double || code == XmlTypeCode.Float) {
switch (relOp) {
case QilNodeType.Gt: opcode = OpCodes.Ble_Un; break;
case QilNodeType.Ge: opcode = OpCodes.Blt_Un; break;
case QilNodeType.Lt: opcode = OpCodes.Bge_Un; break;
case QilNodeType.Le: opcode = OpCodes.Bgt_Un; break;
case QilNodeType.Eq: opcode = OpCodes.Bne_Un; break;
case QilNodeType.Ne: opcode = OpCodes.Beq; break;
default: Debug.Assert(false); opcode = OpCodes.Nop; break;
}
}
else {
switch (relOp)
{
case QilNodeType.Gt: opcode = OpCodes.Ble; break;
case QilNodeType.Ge: opcode = OpCodes.Blt; break;
case QilNodeType.Lt: opcode = OpCodes.Bge; break;
case QilNodeType.Le: opcode = OpCodes.Bgt; break;
case QilNodeType.Eq: opcode = OpCodes.Bne_Un; break;
case QilNodeType.Ne: opcode = OpCodes.Beq; break;
default: Debug.Assert(false); opcode = OpCodes.Nop; break;
}
}
this.helper.Emit(opcode, this.iterCurr.LabelBranch);
this.iterCurr.Storage = StorageDescriptor.None();
break;
case BranchingContext.OnTrue:
switch (relOp) {
case QilNodeType.Gt: opcode = OpCodes.Bgt; break;
case QilNodeType.Ge: opcode = OpCodes.Bge; break;
case QilNodeType.Lt: opcode = OpCodes.Blt; break;
case QilNodeType.Le: opcode = OpCodes.Ble; break;
case QilNodeType.Eq: opcode = OpCodes.Beq; break;
case QilNodeType.Ne: opcode = OpCodes.Bne_Un; break;
default: Debug.Assert(false); opcode = OpCodes.Nop; break;
}
this.helper.Emit(opcode, this.iterCurr.LabelBranch);
this.iterCurr.Storage = StorageDescriptor.None();
break;
default:
Debug.Assert(this.iterCurr.CurrentBranchingContext == BranchingContext.None);
switch (relOp) {
case QilNodeType.Gt: this.helper.Emit(OpCodes.Cgt); break;
case QilNodeType.Lt: this.helper.Emit(OpCodes.Clt); break;
case QilNodeType.Eq: this.helper.Emit(OpCodes.Ceq); break;
default:
switch (relOp) {
case QilNodeType.Ge: opcode = OpCodes.Bge_S; break;
case QilNodeType.Le: opcode = OpCodes.Ble_S; break;
case QilNodeType.Ne: opcode = OpCodes.Bne_Un_S; break;
default: Debug.Assert(false); opcode = OpCodes.Nop; break;
}
// Push "true" if comparison succeeds, "false" otherwise
lblTrue = this.helper.DefineLabel();
this.helper.Emit(opcode, lblTrue);
this.helper.ConvBranchToBool(lblTrue, true);
break;
}
this.iterCurr.Storage = StorageDescriptor.Stack(typeof(bool), false);
break;
}
}