17ec681f3Smrg# Copyright © 2021 Intel Corporation
27ec681f3Smrg#
37ec681f3Smrg# Permission is hereby granted, free of charge, to any person obtaining a
47ec681f3Smrg# copy of this software and associated documentation files (the
57ec681f3Smrg# "Software"), to deal in the Software without restriction, including
67ec681f3Smrg# without limitation the rights to use, copy, modify, merge, publish,
77ec681f3Smrg# distribute, sub license, and/or sell copies of the Software, and to
87ec681f3Smrg# permit persons to whom the Software is furnished to do so, subject to
97ec681f3Smrg# the following conditions:
107ec681f3Smrg#
117ec681f3Smrg# The above copyright notice and this permission notice (including the
127ec681f3Smrg# next paragraph) shall be included in all copies or substantial portions
137ec681f3Smrg# of the Software.
147ec681f3Smrg#
157ec681f3Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
167ec681f3Smrg# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
177ec681f3Smrg# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
187ec681f3Smrg# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
197ec681f3Smrg# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
207ec681f3Smrg# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
217ec681f3Smrg# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
227ec681f3Smrg
237ec681f3Smrgimport docutils.nodes
247ec681f3Smrgimport mako.template
257ec681f3Smrgimport os
267ec681f3Smrgimport sphinx
277ec681f3Smrgfrom sphinx.directives import SphinxDirective
287ec681f3Smrgfrom sphinx.domains import Domain
297ec681f3Smrgfrom sphinx.util.nodes import make_refnode
307ec681f3Smrgimport sys
317ec681f3Smrgimport textwrap
327ec681f3Smrg
337ec681f3SmrgTHIS_DIR = os.path.dirname(os.path.abspath(__file__))
347ec681f3SmrgMESA_DIR = os.path.join(THIS_DIR, '..', '..')
357ec681f3SmrgNIR_PATH = os.path.join(MESA_DIR, 'src', 'compiler', 'nir')
367ec681f3Smrgsys.path.append(NIR_PATH)
377ec681f3Smrg
387ec681f3Smrgimport nir_opcodes
397ec681f3Smrg
407ec681f3SmrgOP_DESC_TEMPLATE = mako.template.Template("""
417ec681f3Smrg<%
427ec681f3Smrgdef src_decl_list(num_srcs):
437ec681f3Smrg   return ', '.join('nir_ssa_def *src' + str(i) for i in range(num_srcs))
447ec681f3Smrg
457ec681f3Smrgdef to_yn(b):
467ec681f3Smrg    return 'Y' if b else 'N'
477ec681f3Smrg%>
487ec681f3Smrg
497ec681f3Smrg**Properties:**
507ec681f3Smrg
517ec681f3Smrg.. list-table::
527ec681f3Smrg   :header-rows: 1
537ec681f3Smrg
547ec681f3Smrg   * - Per-component
557ec681f3Smrg     - Associative
567ec681f3Smrg     - 2-src commutative
577ec681f3Smrg   * - ${to_yn(op.output_size == 0)}
587ec681f3Smrg     - ${to_yn('associative' in op.algebraic_properties)}
597ec681f3Smrg     - ${to_yn('2src_commutative' in op.algebraic_properties)}
607ec681f3Smrg
617ec681f3Smrg**Constant-folding:**
627ec681f3Smrg
637ec681f3Smrg.. code-block:: c
647ec681f3Smrg
657ec681f3Smrg${textwrap.indent(op.const_expr, '    ')}
667ec681f3Smrg
677ec681f3Smrg**Builder function:**
687ec681f3Smrg
697ec681f3Smrg.. c:function:: nir_ssa_def *nir_${op.name}(nir_builder *, ${src_decl_list(op.num_inputs)})
707ec681f3Smrg""")
717ec681f3Smrg
727ec681f3Smrgdef parse_rst(state, parent, rst):
737ec681f3Smrg    vl = docutils.statemachine.ViewList(rst.splitlines())
747ec681f3Smrg    state.nested_parse(vl, 0, parent)
757ec681f3Smrg
767ec681f3Smrgdef nir_alu_type_name(t, s):
777ec681f3Smrg    if s:
787ec681f3Smrg        return '{}[{}]'.format(t, s)
797ec681f3Smrg    else:
807ec681f3Smrg        return '{}[N]'.format(t)
817ec681f3Smrg
827ec681f3Smrgdef build_alu_op_desc(state, env, op):
837ec681f3Smrg    desc = sphinx.addnodes.desc(domain='nir', objtype='aluop')
847ec681f3Smrg
857ec681f3Smrg    # Add the signature
867ec681f3Smrg    sig = sphinx.addnodes.desc_signature()
877ec681f3Smrg    desc.append(sig)
887ec681f3Smrg    sig += sphinx.addnodes.desc_name(op.name, op.name)
897ec681f3Smrg
907ec681f3Smrg    params = sphinx.addnodes.desc_parameterlist()
917ec681f3Smrg    for i, t, s in zip(range(100), op.input_types, op.input_sizes):
927ec681f3Smrg        params += docutils.nodes.Text(nir_alu_type_name(t, s) + ' ')
937ec681f3Smrg        params += sphinx.addnodes.desc_parameter('', 'src' + str(i))
947ec681f3Smrg    sig += params
957ec681f3Smrg
967ec681f3Smrg    sig += sphinx.addnodes.desc_returns('',
977ec681f3Smrg        nir_alu_type_name(op.output_type, op.output_size))
987ec681f3Smrg
997ec681f3Smrg    nir_domain = env.get_domain('nir')
1007ec681f3Smrg    sig['ids'].append(nir_domain.add_alu_op_ref(op))
1017ec681f3Smrg
1027ec681f3Smrg    # Build the description
1037ec681f3Smrg    content = sphinx.addnodes.desc_content()
1047ec681f3Smrg    desc.append(content)
1057ec681f3Smrg    parse_rst(state, content, OP_DESC_TEMPLATE.render(op=op, textwrap=textwrap))
1067ec681f3Smrg
1077ec681f3Smrg    return desc
1087ec681f3Smrg
1097ec681f3Smrgclass NIRALUOpcodesDirective(SphinxDirective):
1107ec681f3Smrg    def run(self):
1117ec681f3Smrg        return [build_alu_op_desc(self.state, self.env, op)
1127ec681f3Smrg                for op in nir_opcodes.opcodes.values()]
1137ec681f3Smrg
1147ec681f3Smrgclass NIRDomain(Domain):
1157ec681f3Smrg    """A new NIR directive
1167ec681f3Smrg
1177ec681f3Smrg    To list all NIR ALU opcodes with their descriptions:
1187ec681f3Smrg    ```rst
1197ec681f3Smrg    .. nir:alu-opcodes::
1207ec681f3Smrg    ```
1217ec681f3Smrg
1227ec681f3Smrg    To reference a NIR opcode, ``:nir:alu-op:`fadd```
1237ec681f3Smrg    """
1247ec681f3Smrg    name = 'nir'
1257ec681f3Smrg    roles = {
1267ec681f3Smrg        'alu-op' : sphinx.roles.XRefRole(),
1277ec681f3Smrg    }
1287ec681f3Smrg    directives = {
1297ec681f3Smrg        'alu-opcodes' : NIRALUOpcodesDirective,
1307ec681f3Smrg    }
1317ec681f3Smrg    initial_data = {
1327ec681f3Smrg        'alu-op-refs': [],
1337ec681f3Smrg    }
1347ec681f3Smrg
1357ec681f3Smrg    def add_alu_op_ref(self, op):
1367ec681f3Smrg        """Add reference to an ALU op."""
1377ec681f3Smrg        self.data['alu-op-refs'].append((op.name, self.env.docname))
1387ec681f3Smrg        return 'nir-alu-op-' + op.name
1397ec681f3Smrg
1407ec681f3Smrg    def resolve_xref(self, env, fromdocname, builder, typ, target, node,
1417ec681f3Smrg                     contnode):
1427ec681f3Smrg        for opname, todocname in self.data['alu-op-refs']:
1437ec681f3Smrg            if target == opname:
1447ec681f3Smrg                targ = 'nir-alu-op-' + opname
1457ec681f3Smrg                return make_refnode(builder, fromdocname, todocname, targ,
1467ec681f3Smrg                                    contnode, targ)
1477ec681f3Smrg
1487ec681f3Smrg        return None
1497ec681f3Smrg
1507ec681f3Smrgdef setup(app):
1517ec681f3Smrg    app.add_domain(NIRDomain)
152