private void GenerateSwitchForDiscriminator(ILGenerator gen, GenerateUnionCaseAction action, Label afterSwitchBlock) { // process all switch cases stored ... // generate the following structure: // ldarg.0 // start case-1 test // push first discr constant for switch case considered // beq case1 // ldarg.0 // push next (if present) discr constant for switch case considered // beq case1 // // ldarg.0 // start case-2 test // push first discr constant for switch case considered // beq case2 // ... // br default // case1 : // ... // br end // case2 : // ... // br end // default: // ... Label defaultCaseLabel = gen.DefineLabel(); // make sure to have default case, even if no default is specified in IDL // part1: compare and jump foreach (SwitchCase switchCase in m_switchCases) { if (switchCase.IsDefaultCase()) { // generate the default case at the end, no comparison needed for default case continue; } // generate and assign label to the current case switchCase.AssignIlLabel(gen); for (int j = 0; j < switchCase.DiscriminatorValues.Length; j++) { // generate tests action.GenerateLoadDiscValue(gen); PushDiscriminatorValueToStack(gen, switchCase.DiscriminatorValues[j]); gen.Emit(OpCodes.Beq, switchCase.IlLabelAssigned); } } // if nothing found, jump to default case gen.Emit(OpCodes.Br, defaultCaseLabel); // part2: code for cases (jump-targets) SwitchCase defaultCaseFound = null; foreach (SwitchCase switchCase in m_switchCases) { if (switchCase.IsDefaultCase()) { // make sure to generate the default case at the end, not in between defaultCaseFound = switchCase; continue; } // set position for the case label gen.MarkLabel(switchCase.IlLabelAssigned); // the field to return action.GenerateCaseAction(gen, switchCase, false); gen.Emit(OpCodes.Br, afterSwitchBlock); // jump to exit point } // the default case gen.MarkLabel(defaultCaseLabel); if (defaultCaseFound != null) { // a default case present action.GenerateCaseAction(gen, defaultCaseFound, true); } else { action.GenerateNoDefaultCasePresent(gen); } gen.Emit(OpCodes.Br_S, afterSwitchBlock); // jump to exit point }