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            
        }        
예제 #2
0
        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
        }