Esempio n. 1
0
        /// <summary>
        /// Process the child nodes of a SwitchNode, and generate 'case's for them.
        /// </summary>
        private void ProcessSwitchChildren(int depth, SwitchNode node)
        {
            for (int i = 0; i < node.Expression.NumValues; i++)
            {
                // skip over child references in the outer loop.  once we get to a real
                // child node, we'll scan for ChildReferenceNodes.
                if (!(node[i] is ChildReferenceNode))
                {
                    // search for child references and generate fall thru cases
                    for (int j = i + 1; j < node.Expression.NumValues; j++)
                    {
                        if (node[j] is ChildReferenceNode &&
                            ((ChildReferenceNode)node[j]).Index == i)
                        {
                            EmitIndented(depth, $"case 0x{j:x}: ");
                            EmitComment("fall thru");
                        }
                    }

                    // emit case label
                    EmitIndented(depth, $"case 0x{i:x}:");

                    // emit children, followed by 'break'
                    ProcessNode(node[i], depth + 1);

                    if (!(node[i] is Rule) || !spec.Config.NoBreakAfterRule)
                    {
                        EmitIndented(depth + 1, "break;");
                    }
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Process a SwitchNode and generate equivalent C code.
        /// </summary>
        private void ProcessSwitch(SwitchNode node, int depth)
        {
            if (node.Expression is Bitfield)
            {
                var bf = (Bitfield)node.Expression;
                EmitIndented(depth, $"switch ({GenerateBitfield(bf)}) {{");
            }
            else
            {
                Debug.Assert(node.Expression is BitfieldSet);
                var bfSet = (BitfieldSet)node.Expression;
                EmitIndented(depth, $"switch ({GenerateBitfieldSet(bfSet)}) {{");
            }

            ProcessSwitchChildren(depth, node);

            EmitIndented(depth, "}");
        }
Esempio n. 3
0
        /// <summary>
        /// Build a decoder subtree for the given switch case.
        /// </summary>
        /// <param name="node">The enclosing switch node.</param>
        /// <param name="value">Value of case (eg., case 0x0 has value 0).</param>
        /// <returns>Decoder subtree.</returns>
        private Node BuildSwitchCase(SwitchNode node, int value)
        {
            Debug.Assert(value >= 0 && value < node.Expression.NumValues);

            if (spec.Config.Verbose)
            {
                Console.WriteLine("Switch case {0}", value);
            }

            // generate a derived RuleSet for this switch case
            var cond = new Condition(spec,
                                     node.Expression.GetBitsForValue(value),
                                     new TristateBitArray(spec.NumFlags));

            RuleSet derivedSet = ruleSet.Derive(cond);

            // generate a corresponding TreeBuilder and update its totals for
            // switch bits & nesting depth
            var builder = new TreeBuilder(spec, derivedSet, this);

            builder.totalSwitchBits += node.Expression.NumBits;
            builder.switchNestingDepth++;

            // use it to build tree for case label
            Node child = builder.Build();

            // search previously-generated switch cases for functionally identical subtrees
            for (int previousValue = 0; previousValue < value; previousValue++)
            {
                if (node[previousValue].Equals(child))
                {
                    if (spec.Config.Verbose)
                    {
                        Console.WriteLine("Pruning child {0} => {1}", value, previousValue);
                    }

                    // replace generated subtree with a reference to the (identical) subtree
                    child = new ChildReferenceNode(spec, previousValue);
                    break;
                }
            }

            return(child);
        }
Esempio n. 4
0
        /// <summary>
        /// Actually build the switch node, given the supplied expression.
        /// </summary>
        /// <param name="expression">Either a bitfield or a bitfield set.</param>
        /// <returns>Bitfield node object.</returns>
        private SwitchNode BuildSwitch(SwitchableNode expression)
        {
            if (spec.Config.Verbose)
            {
                Console.WriteLine("Building switch node for {0}.", expression.ToString());
            }

            var node = new SwitchNode(spec, expression);

            // iterate through every possible value of 'expression'
            for (int value = 0; value < expression.NumValues; value++)
            {
                // store child in switch node's table
                node[value] = BuildSwitchCase(node, value);
            }

            if (spec.Config.Verbose)
            {
                Console.WriteLine("Switch completed.");
            }

            return(node);
        }