Add support for type variable wildcards in bound instructions.

Instructions will multiple type variables can now use `any` to indicate
encodings that don't care about the value of a secondary type variable:

    ishl.i32.any instead of ishl.i32.i32

This is only allowed for secondary type variables (which are converted
to instruction predicates). The controlling type variable must still be
fully specified because it is used to key the encoding tables.
This commit is contained in:
Jakob Stoklund Olesen
2017-07-26 14:55:26 -07:00
parent ac830e0446
commit 06bab60fcc
3 changed files with 36 additions and 28 deletions

View File

@@ -314,6 +314,7 @@ class Instruction(object):
>>> iadd.i32 >>> iadd.i32
""" """
assert name != 'any', 'Wildcard not allowed for ctrl_typevar'
return self.bind(ValueType.by_name(name)) return self.bind(ValueType.by_name(name))
def fully_bound(self): def fully_bound(self):
@@ -386,6 +387,10 @@ class BoundInstruction(object):
>>> uext.i32.i8 >>> uext.i32.i8
""" """
if name == 'any':
# This is a wild card bind represented as a None type variable.
return self.bind(None)
return self.bind(ValueType.by_name(name)) return self.bind(ValueType.by_name(name))
def fully_bound(self): def fully_bound(self):

View File

@@ -424,6 +424,9 @@ class Encoding(object):
# Add secondary type variables to the instruction predicate. # Add secondary type variables to the instruction predicate.
if len(self.typevars) > 1: if len(self.typevars) > 1:
for tv, vt in zip(self.inst.other_typevars, self.typevars[1:]): for tv, vt in zip(self.inst.other_typevars, self.typevars[1:]):
# A None tv is an 'any' wild card: `ishl.i32.any`.
if vt is None:
continue
typred = TypePredicate.typevar_check(self.inst, tv, vt) typred = TypePredicate.typevar_check(self.inst, tv, vt)
instp = And.combine(instp, typred) instp = And.combine(instp, typred)

View File

@@ -104,10 +104,10 @@ for inst, rrr in [
(base.ishl, 4), (base.ishl, 4),
(base.ushr, 5), (base.ushr, 5),
(base.sshr, 7)]: (base.sshr, 7)]:
I32.enc(inst.i32.i32, *r.rc(0xd3, rrr=rrr)) I32.enc(inst.i32.any, *r.rc(0xd3, rrr=rrr))
I64.enc(inst.i64.i64, *r.rc.rex(0xd3, rrr=rrr, w=1)) I64.enc(inst.i64.any, *r.rc.rex(0xd3, rrr=rrr, w=1))
I64.enc(inst.i32.i32, *r.rc.rex(0xd3, rrr=rrr)) I64.enc(inst.i32.any, *r.rc.rex(0xd3, rrr=rrr))
I64.enc(inst.i32.i32, *r.rc(0xd3, rrr=rrr)) I64.enc(inst.i32.any, *r.rc(0xd3, rrr=rrr))
# Population count. # Population count.
I32.enc(base.popcnt.i32, *r.urm(0xf3, 0x0f, 0xb8), isap=cfg.use_popcnt) I32.enc(base.popcnt.i32, *r.urm(0xf3, 0x0f, 0xb8), isap=cfg.use_popcnt)
@@ -131,37 +131,37 @@ I64.enc(base.ctz.i32, *r.urm.rex(0xf3, 0x0f, 0xbc), isap=cfg.use_bmi1)
I64.enc(base.ctz.i32, *r.urm(0xf3, 0x0f, 0xbc), isap=cfg.use_bmi1) I64.enc(base.ctz.i32, *r.urm(0xf3, 0x0f, 0xbc), isap=cfg.use_bmi1)
# Loads and stores. # Loads and stores.
I32.enc(base.store.i32.i32, *r.st(0x89)) I32.enc(base.store.i32.any, *r.st(0x89))
I32.enc(base.store.i32.i32, *r.stDisp8(0x89)) I32.enc(base.store.i32.any, *r.stDisp8(0x89))
I32.enc(base.store.i32.i32, *r.stDisp32(0x89)) I32.enc(base.store.i32.any, *r.stDisp32(0x89))
I32.enc(base.istore16.i32.i32, *r.st(0x66, 0x89)) I32.enc(base.istore16.i32.any, *r.st(0x66, 0x89))
I32.enc(base.istore16.i32.i32, *r.stDisp8(0x66, 0x89)) I32.enc(base.istore16.i32.any, *r.stDisp8(0x66, 0x89))
I32.enc(base.istore16.i32.i32, *r.stDisp32(0x66, 0x89)) I32.enc(base.istore16.i32.any, *r.stDisp32(0x66, 0x89))
I32.enc(base.istore8.i32.i32, *r.st_abcd(0x88)) I32.enc(base.istore8.i32.any, *r.st_abcd(0x88))
I32.enc(base.istore8.i32.i32, *r.stDisp8_abcd(0x88)) I32.enc(base.istore8.i32.any, *r.stDisp8_abcd(0x88))
I32.enc(base.istore8.i32.i32, *r.stDisp32_abcd(0x88)) I32.enc(base.istore8.i32.any, *r.stDisp32_abcd(0x88))
I32.enc(base.load.i32.i32, *r.ld(0x8b)) I32.enc(base.load.i32.any, *r.ld(0x8b))
I32.enc(base.load.i32.i32, *r.ldDisp8(0x8b)) I32.enc(base.load.i32.any, *r.ldDisp8(0x8b))
I32.enc(base.load.i32.i32, *r.ldDisp32(0x8b)) I32.enc(base.load.i32.any, *r.ldDisp32(0x8b))
I32.enc(base.uload16.i32.i32, *r.ld(0x0f, 0xb7)) I32.enc(base.uload16.i32.any, *r.ld(0x0f, 0xb7))
I32.enc(base.uload16.i32.i32, *r.ldDisp8(0x0f, 0xb7)) I32.enc(base.uload16.i32.any, *r.ldDisp8(0x0f, 0xb7))
I32.enc(base.uload16.i32.i32, *r.ldDisp32(0x0f, 0xb7)) I32.enc(base.uload16.i32.any, *r.ldDisp32(0x0f, 0xb7))
I32.enc(base.sload16.i32.i32, *r.ld(0x0f, 0xbf)) I32.enc(base.sload16.i32.any, *r.ld(0x0f, 0xbf))
I32.enc(base.sload16.i32.i32, *r.ldDisp8(0x0f, 0xbf)) I32.enc(base.sload16.i32.any, *r.ldDisp8(0x0f, 0xbf))
I32.enc(base.sload16.i32.i32, *r.ldDisp32(0x0f, 0xbf)) I32.enc(base.sload16.i32.any, *r.ldDisp32(0x0f, 0xbf))
I32.enc(base.uload8.i32.i32, *r.ld(0x0f, 0xb6)) I32.enc(base.uload8.i32.any, *r.ld(0x0f, 0xb6))
I32.enc(base.uload8.i32.i32, *r.ldDisp8(0x0f, 0xb6)) I32.enc(base.uload8.i32.any, *r.ldDisp8(0x0f, 0xb6))
I32.enc(base.uload8.i32.i32, *r.ldDisp32(0x0f, 0xb6)) I32.enc(base.uload8.i32.any, *r.ldDisp32(0x0f, 0xb6))
I32.enc(base.sload8.i32.i32, *r.ld(0x0f, 0xbe)) I32.enc(base.sload8.i32.any, *r.ld(0x0f, 0xbe))
I32.enc(base.sload8.i32.i32, *r.ldDisp8(0x0f, 0xbe)) I32.enc(base.sload8.i32.any, *r.ldDisp8(0x0f, 0xbe))
I32.enc(base.sload8.i32.i32, *r.ldDisp32(0x0f, 0xbe)) I32.enc(base.sload8.i32.any, *r.ldDisp32(0x0f, 0xbe))
# #
# Call/return # Call/return