Emit type arguments to builder methods that need it.

Use the inferred type variables to construct a type argument for builder
methods. This is for those instructions where the result types cannot be
computed from the result types.
This commit is contained in:
Jakob Stoklund Olesen
2016-11-10 15:33:16 -08:00
parent 36871d3fb1
commit 59eef69a4f
2 changed files with 22 additions and 4 deletions

View File

@@ -9,7 +9,7 @@ from . import instructions
from .typevar import TypeVar
try:
from typing import Union, Tuple # noqa
from typing import Union, Tuple, Sequence # noqa
except ImportError:
pass
@@ -389,12 +389,18 @@ class Apply(Expr):
args = ', '.join(map(str, self.args))
return '{}({})'.format(self.instname(), args)
def rust_builder(self):
# type: () -> str
def rust_builder(self, defs=None):
# type: (Sequence[Var]) -> str
"""
Return a Rust Builder method call for instantiating this instruction
application.
The `defs` argument should be a list of variables defined by this
instruction. It is used to construct a result type if necessary.
"""
args = ', '.join(map(str, self.args))
# Do we need to pass an explicit type argument?
if self.inst.is_polymorphic and not self.inst.use_typevar_operand:
args = defs[0].rust_type() + ', ' + args
method = self.inst.snake_name()
return '{}({})'.format(method, args)

View File

@@ -10,6 +10,7 @@ the input instruction.
from __future__ import absolute_import
from srcgen import Formatter
from base import legalize
from cdsl.ast import Var
try:
from typing import Sequence # noqa
@@ -72,6 +73,12 @@ def unwrap_inst(iref, node, fmt):
fmt.outdented_line('} else {')
fmt.line('unreachable!("bad instruction format")')
# Get the types of any variables where it is needed.
for i in iform.value_operands:
v = expr.args[i]
if isinstance(v, Var) and v.has_free_typevar():
fmt.line('let typeof_{0} = dfg.value_type({0});'.format(v))
# If the node has multiple results, detach the values.
# Place the secondary values in 'src_{}' locals.
if len(node.defs) > 1:
@@ -91,6 +98,11 @@ def unwrap_inst(iref, node, fmt):
for d in node.defs[1:]:
fmt.line('src_{} = vals.next().unwrap();'.format(d))
fmt.line('assert_eq!(vals.next(), None);')
for d in node.defs[1:]:
if d.has_free_typevar():
fmt.line(
'let typeof_{0} = dfg.value_type(src_{0});'
.format(d))
def wrap_tup(seq):
@@ -128,7 +140,7 @@ def emit_dst_inst(node, fmt):
builder = 'let {} = dfg.ins(pos)'.format(wrap_tup(node.defs))
fixup_first_result = node.defs[0].is_output()
fmt.line('{}.{};'.format(builder, node.expr.rust_builder()))
fmt.line('{}.{};'.format(builder, node.expr.rust_builder(node.defs)))
# If we just replaced an instruction, we need to bump the cursor so
# following instructions are inserted *after* the replaced insruction.