Exemplo n.º 1
0
        public override BoundNode VisitSwitchDispatch(BoundSwitchDispatch node)
        {
            BoundSpillSequenceBuilder builder = null;
            var expression = VisitExpression(ref builder, node.Expression);

            return(UpdateStatement(builder, node.Update(expression, node.Cases, node.DefaultLabel, node.EqualityMethod)));
        }
Exemplo n.º 2
0
        public override BoundNode VisitSwitchDispatch(BoundSwitchDispatch node)
        {
            AddGoto(node.DefaultLabel);
            foreach ((_, LabelSymbol label) in node.Cases)
            {
                AddGoto(label);
            }

            return(base.VisitSwitchDispatch(node));
        }
            private bool GenerateSwitchDispatch(BoundDecisionDagNode node, HashSet <BoundDecisionDagNode> loweredNodes)
            {
                Debug.Assert(!loweredNodes.Contains(node));

                // We only generate a switch dispatch if we have two or more value tests in a row
                if (!(node is BoundTestDecisionDagNode firstTestNode &&
                      firstTestNode.Test is BoundDagValueTest firstTest &&
                      firstTestNode.WhenFalse is BoundTestDecisionDagNode whenFalse &&
                      whenFalse.Test is BoundDagValueTest secondTest &&
                      !loweredNodes.Contains(whenFalse) &&
                      !this._dagNodeLabels.ContainsKey(whenFalse) &&
                      firstTest.Input == secondTest.Input &&
                      firstTest.Input.Type.IsValidV6SwitchGoverningType()))
                {
                    // https://github.com/dotnet/roslyn/issues/12509 Could optimize float, double, decimal value switches. For now use if-then-else
                    return(false);
                }

                // Gather up the (value, label) pairs, starting with the first one
                var cases = ArrayBuilder <(ConstantValue value, LabelSymbol label)> .GetInstance();

                cases.Add((value: firstTest.Value, label: GetDagNodeLabel(firstTestNode.WhenTrue)));

                BoundTestDecisionDagNode previous = firstTestNode;

                while (previous.WhenFalse is BoundTestDecisionDagNode p &&
                       p.Test is BoundDagValueTest vd &&
                       vd.Input == firstTest.Input &&
                       !this._dagNodeLabels.ContainsKey(p) &&
                       !loweredNodes.Contains(p))
                {
                    cases.Add((value: vd.Value, label: GetDagNodeLabel(p.WhenTrue)));
                    loweredNodes.Add(p);
                    previous = p;
                }

                // If we are emitting a hash table based string switch,
                // we need to generate a helper method for computing
                // string hash value in <PrivateImplementationDetails> class.

                MethodSymbol?stringEquality = null;

                if (firstTest.Input.Type.SpecialType == SpecialType.System_String)
                {
                    EnsureStringHashFunction(cases.Count, node.Syntax);
                    stringEquality = _localRewriter.UnsafeGetSpecialTypeMethod(node.Syntax, SpecialMember.System_String__op_Equality);
                }

                LabelSymbol defaultLabel = GetDagNodeLabel(previous.WhenFalse);
                var         dispatch     = new BoundSwitchDispatch(
                    node.Syntax, _tempAllocator.GetTemp(firstTest.Input), cases.ToImmutableAndFree(), defaultLabel, stringEquality);

                _loweredDecisionDag.Add(dispatch);
                return(true);
            }
Exemplo n.º 4
0
        public override BoundNode VisitSwitchDispatch(BoundSwitchDispatch node)
        {
            VisitRvalue(node.Expression);
            var state = this.State.Clone();

            PendingBranches.Add(new PendingBranch(node, state, node.DefaultLabel));
            foreach ((_, LabelSymbol label) in node.Cases)
            {
                PendingBranches.Add(new PendingBranch(node, state, label));
            }

            SetUnreachable();
            return(null);
        }