import docutils.nodes
import mako.template
import os
import sphinx
from sphinx.directives import SphinxDirective
from sphinx.domains import Domain
from sphinx.util.nodes import make_refnode
import sys
import textwrap
THIS_DIR = os.path.dirname(os.path.abspath(__file__))
MESA_DIR = os.path.join(THIS_DIR, '..', '..')
NIR_PATH = os.path.join(MESA_DIR, 'src', 'compiler', 'nir')
sys.path.append(NIR_PATH)
import nir_opcodes
OP_DESC_TEMPLATE = mako.template.Template("""
<%
def src_decl_list(num_srcs):
return ', '.join('nir_ssa_def *src' + str(i) for i in range(num_srcs))
def to_yn(b):
return 'Y' if b else 'N'
%>
**Properties:**
.. list-table::
:header-rows: 1
* - Per-component
- Associative
- 2-src commutative
* - ${to_yn(op.output_size == 0)}
- ${to_yn('associative' in op.algebraic_properties)}
- ${to_yn('2src_commutative' in op.algebraic_properties)}
**Constant-folding:**
.. code-block:: c
${textwrap.indent(op.const_expr, ' ')}
**Builder function:**
.. c:function:: nir_ssa_def *nir_${op.name}(nir_builder *, ${src_decl_list(op.num_inputs)})
""")
def parse_rst(state, parent, rst):
vl = docutils.statemachine.ViewList(rst.splitlines())
state.nested_parse(vl, 0, parent)
def nir_alu_type_name(t, s):
if s:
return '{}[{}]'.format(t, s)
else:
return '{}[N]'.format(t)
def build_alu_op_desc(state, env, op):
desc = sphinx.addnodes.desc(domain='nir', objtype='aluop')
sig = sphinx.addnodes.desc_signature()
desc.append(sig)
sig += sphinx.addnodes.desc_name(op.name, op.name)
params = sphinx.addnodes.desc_parameterlist()
for i, t, s in zip(range(100), op.input_types, op.input_sizes):
params += docutils.nodes.Text(nir_alu_type_name(t, s) + ' ')
params += sphinx.addnodes.desc_parameter('', 'src' + str(i))
sig += params
sig += sphinx.addnodes.desc_returns('',
nir_alu_type_name(op.output_type, op.output_size))
nir_domain = env.get_domain('nir')
sig['ids'].append(nir_domain.add_alu_op_ref(op))
content = sphinx.addnodes.desc_content()
desc.append(content)
parse_rst(state, content, OP_DESC_TEMPLATE.render(op=op, textwrap=textwrap))
return desc
class NIRALUOpcodesDirective(SphinxDirective):
def run(self):
return [build_alu_op_desc(self.state, self.env, op)
for op in nir_opcodes.opcodes.values()]
class NIRDomain(Domain):
"""A new NIR directive
To list all NIR ALU opcodes with their descriptions:
```rst
.. nir:alu-opcodes::
```
To reference a NIR opcode, ``:nir:alu-op:`fadd```
"""
name = 'nir'
roles = {
'alu-op' : sphinx.roles.XRefRole(),
}
directives = {
'alu-opcodes' : NIRALUOpcodesDirective,
}
initial_data = {
'alu-op-refs': [],
}
def add_alu_op_ref(self, op):
"""Add reference to an ALU op."""
self.data['alu-op-refs'].append((op.name, self.env.docname))
return 'nir-alu-op-' + op.name
def resolve_xref(self, env, fromdocname, builder, typ, target, node,
contnode):
for opname, todocname in self.data['alu-op-refs']:
if target == opname:
targ = 'nir-alu-op-' + opname
return make_refnode(builder, fromdocname, todocname, targ,
contnode, targ)
return None
def setup(app):
app.add_domain(NIRDomain)