From 59eef69a4f55c050b2a0de6f2ba27b45c3fd677d Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 10 Nov 2016 15:33:16 -0800 Subject: [PATCH] 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. --- lib/cretonne/meta/cdsl/ast.py | 12 +++++++++--- lib/cretonne/meta/gen_legalizer.py | 14 +++++++++++++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/cretonne/meta/cdsl/ast.py b/lib/cretonne/meta/cdsl/ast.py index 8db7352333..ddcc702575 100644 --- a/lib/cretonne/meta/cdsl/ast.py +++ b/lib/cretonne/meta/cdsl/ast.py @@ -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) diff --git a/lib/cretonne/meta/gen_legalizer.py b/lib/cretonne/meta/gen_legalizer.py index 409ebb7cf2..983871ac40 100644 --- a/lib/cretonne/meta/gen_legalizer.py +++ b/lib/cretonne/meta/gen_legalizer.py @@ -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.