Assign a type variable to all VALUE operands.

A few operands have a fixed type assigned. Create a singleton type
variable for these exceptions. Most instructions are polymorphic, so
this is a little overhead.

Eliminate the Operand.typ field and replace it with an Operand.typevar
field which is always a TypeVar, but which only exists in VALUE
operands.
This commit is contained in:
Jakob Stoklund Olesen
2016-11-08 14:41:13 -08:00
parent 9327d567b4
commit 45fd134d3e
6 changed files with 93 additions and 39 deletions

View File

@@ -5,10 +5,14 @@ from __future__ import absolute_import
import srcgen
import constant_hash
from unique_table import UniqueTable, UniqueSeqTable
from cdsl.operands import ImmediateKind
import cdsl.types
import cdsl.operands
from cdsl.formats import InstructionFormat
from cdsl.instructions import Instruction # noqa
from cdsl.operands import Operand # noqa
from cdsl.typevar import TypeVar # noqa
def gen_formats(fmt):
# type: (srcgen.Formatter) -> None
@@ -302,6 +306,7 @@ def gen_opcodes(groups, fmt):
def get_constraint(op, ctrl_typevar, type_sets):
# type: (Operand, TypeVar, UniqueTable) -> str
"""
Get the value type constraint for an SSA value operand, where
`ctrl_typevar` is the controlling type variable.
@@ -312,22 +317,22 @@ def get_constraint(op, ctrl_typevar, type_sets):
- `Free(idx)` where `idx` is an index into `type_sets`.
- `Same`, `Lane`, `AsBool` for controlling typevar-derived constraints.
"""
assert op.kind is cdsl.operands.VALUE
t = op.typ
assert op.is_value()
tv = op.typevar
# A concrete value type.
if isinstance(t, cdsl.types.ValueType):
return 'Concrete({})'.format(t.rust_name())
if tv.singleton_type:
return 'Concrete({})'.format(tv.singleton_type.rust_name())
if t.free_typevar() is not ctrl_typevar:
assert not t.is_derived
return 'Free({})'.format(type_sets.add(t.type_set))
if tv.free_typevar() is not ctrl_typevar:
assert not tv.is_derived
return 'Free({})'.format(type_sets.add(tv.type_set))
if t.is_derived:
assert t.base is ctrl_typevar, "Not derived directly from ctrl_typevar"
return t.derived_func
if tv.is_derived:
assert tv.base is ctrl_typevar, "Not derived from ctrl_typevar"
return tv.derived_func
assert t is ctrl_typevar
assert tv is ctrl_typevar
return 'Same'
@@ -486,6 +491,7 @@ def gen_member_inits(iform, fmt):
def gen_inst_builder(inst, fmt):
# type: (Instruction, srcgen.Formatter) -> None
"""
Emit a method for generating the instruction `inst`.
@@ -502,10 +508,10 @@ def gen_inst_builder(inst, fmt):
if inst.is_polymorphic and not inst.use_typevar_operand:
args.append('{}: Type'.format(inst.ctrl_typevar.name))
tmpl_types = list()
into_args = list()
tmpl_types = list() # type: List[str]
into_args = list() # type: List[str]
for op in inst.ins:
if isinstance(op.kind, cdsl.operands.ImmediateKind):
if isinstance(op.kind, ImmediateKind):
t = 'T{}{}'.format(1 + len(tmpl_types), op.kind.name)
tmpl_types.append('{}: Into<{}>'.format(t, op.kind.rust_type))
into_args.append(op.name)
@@ -553,7 +559,7 @@ def gen_inst_builder(inst, fmt):
# The format constructor will resolve the result types from the
# type var.
args.append('ctrl_typevar')
elif inst.outs[inst.value_results[0]].typ == inst.ctrl_typevar:
elif inst.outs[inst.value_results[0]].typevar == inst.ctrl_typevar:
# The format constructor expects a simple result type.
# No type transformation needed from the controlling type
# variable.
@@ -567,13 +573,12 @@ def gen_inst_builder(inst, fmt):
else:
# This non-polymorphic instruction has a fixed result type.
args.append(
'types::' +
inst.outs[inst.value_results[0]].typ.name.upper())
inst.outs[inst.value_results[0]]
.typevar.singleton_type.rust_name())
args.extend(op.name for op in inst.ins)
args = ', '.join(args)
# Call to the format constructor,
fcall = 'self.{}({})'.format(inst.format.name, args)
fcall = 'self.{}({})'.format(inst.format.name, ', '.join(args))
if len(inst.value_results) == 0:
fmt.line(fcall + '.0')