protected override QilNode VisitOr(QilBinary ndOr) {
Label lblTemp = new Label();
// Visit left branch
switch (this.iterCurr.CurrentBranchingContext) {
case BranchingContext.OnFalse:
// If left condition evaluates to true, jump to new label that will be fixed
// just beyond the second condition
lblTemp = this.helper.DefineLabel();
NestedVisitWithBranch(ndOr.Left, BranchingContext.OnTrue, lblTemp);
break;
case BranchingContext.OnTrue:
// If left condition evaluates to true, branch to true label
NestedVisitWithBranch(ndOr.Left, BranchingContext.OnTrue, this.iterCurr.LabelBranch);
break;
default:
// If left condition evalutes to true, jump to code that pushes "true"
Debug.Assert(this.iterCurr.CurrentBranchingContext == BranchingContext.None);
lblTemp = this.helper.DefineLabel();
NestedVisitWithBranch(ndOr.Left, BranchingContext.OnTrue, lblTemp);
break;
}
// Visit right branch
switch (this.iterCurr.CurrentBranchingContext) {
case BranchingContext.OnFalse:
// If right condition evaluates to false, branch to false label
NestedVisitWithBranch(ndOr.Right, BranchingContext.OnFalse, this.iterCurr.LabelBranch);
break;
case BranchingContext.OnTrue:
// If right condition evaluates to true, branch to true label
NestedVisitWithBranch(ndOr.Right, BranchingContext.OnTrue, this.iterCurr.LabelBranch);
break;
default:
// If right condition evalutes to true, jump to code that pushes "true".
// Otherwise, if both conditions evaluate to false, fall through code path
// will push "false".
NestedVisitWithBranch(ndOr.Right, BranchingContext.OnTrue, lblTemp);
break;
}
switch (this.iterCurr.CurrentBranchingContext) {
case BranchingContext.OnFalse:
// Anchor true label
this.helper.MarkLabel(lblTemp);
goto case BranchingContext.OnTrue;
case BranchingContext.OnTrue:
this.iterCurr.Storage = StorageDescriptor.None();
break;
case BranchingContext.None:
// Convert branch targets into push of true/false
this.helper.ConvBranchToBool(lblTemp, true);
this.iterCurr.Storage = StorageDescriptor.Stack(typeof(bool), false);
break;
}
return ndOr;
}