Browse Source

Verify that type variables have been fully bound.

The shift instructions have two type variables since the shift amount can be a
differently sized integer. Fix the RISC-V shift encodings to reflect this, and
allow i64 registers to be shifted by an i32 amount.
pull/3/head
Jakob Stoklund Olesen 8 years ago
parent
commit
24c97ce6e5
  1. 37
      meta/cretonne/__init__.py
  2. 14
      meta/target/riscv/encodings.py

37
meta/cretonne/__init__.py

@ -666,6 +666,17 @@ class Instruction(object):
"""
return self.bind(ValueType.by_name(name))
def fully_bound(self):
"""
Verify that all typevars have been bound, and return a
`(inst, typevars)` pair.
This version in `Instruction` itself allows non-polymorphic
instructions to duck-type as `BoundInstruction`\s.
"""
assert not self.is_polymorphic, self
return (self, ())
class BoundInstruction(object):
"""
@ -675,6 +686,10 @@ class BoundInstruction(object):
def __init__(self, inst, typevars):
self.inst = inst
self.typevars = typevars
assert len(typevars) <= 1 + len(inst.other_typevars)
def __str__(self):
return '.'.join([self.inst.name,] + map(str, self.typevars))
def bind(self, *args):
"""
@ -690,6 +705,17 @@ class BoundInstruction(object):
"""
return self.bind(ValueType.by_name(name))
def fully_bound(self):
"""
Verify that all typevars have been bound, and return a
`(inst, typevars)` pair.
"""
if len(self.typevars) < 1 + len(self.inst.other_typevars):
unb = ', '.join(str(tv) for tv in self.inst.other_typevars[len(self.typevars) - 1:])
raise AssertionError("Unbound typevar {} in {}".format(unb, self))
assert len(self.typevars) == 1 + len(self.inst.other_typevars)
return (self.inst, self.typevars)
# Defining targets
@ -769,17 +795,12 @@ class Encoding(object):
def __init__(self, cpumode, inst, recipe, encbits):
assert isinstance(cpumode, CPUMode)
if isinstance(inst, BoundInstruction):
real_inst = inst.inst
else:
real_inst = inst
assert isinstance(real_inst, Instruction)
assert isinstance(recipe, EncRecipe)
self.inst, self.typevars = inst.fully_bound()
self.cpumode = cpumode
assert real_inst.format == recipe.format, (
assert self.inst.format == recipe.format, (
"Format {} must match recipe: {}".format(
inst.format, recipe.format))
self.inst = inst
self.inst.format, recipe.format))
self.recipe = recipe
self.encbits = encbits

14
meta/target/riscv/encodings.py

@ -10,12 +10,20 @@ from recipes import OP, R
for inst, f3, f7 in [
(base.iadd, 0b000, 0b0000000),
(base.isub, 0b000, 0b0100000),
(base.ishl, 0b001, 0b0000000),
(base.ushr, 0b101, 0b0000000),
(base.sshr, 0b101, 0b0100000),
(base.bxor, 0b100, 0b0000000),
(base.bor, 0b110, 0b0000000),
(base.band, 0b111, 0b0000000)
]:
RV32.enc(inst.i32, R, OP(f3, f7))
RV64.enc(inst.i64, R, OP(f3, f7))
# Dynamic shifts have the same masking semantics as the cton base instructions
for inst, f3, f7 in [
(base.ishl, 0b001, 0b0000000),
(base.ushr, 0b101, 0b0000000),
(base.sshr, 0b101, 0b0100000),
]:
RV32.enc(inst.i32.i32, R, OP(f3, f7))
RV64.enc(inst.i64.i64, R, OP(f3, f7))
# Allow i32 shift amounts in 64-bit shifts.
RV64.enc(inst.i64.i32, R, OP(f3, f7))

Loading…
Cancel
Save