Add fix for #114 (#115)

* Reduce code duplication in TypeConstraint subclasses; Add ConstrainWiderOrEqual to ti and to ireduce,{s,u}extend and f{promote,demote}; Fix bug in emitting constraint edges in TypeEnv.dot(); Modify runtime constraint checks to reject match when they encounter overflow

* Rename Constrain types to something shorter; Move lane_bits/lane_counts in subclasses of ValueType; Add wider_or_eq function in rust and python;
This commit is contained in:
d1m0
2017-07-12 08:51:55 -07:00
committed by Jakob Stoklund Olesen
parent 962c945a3c
commit 7c438f866c
8 changed files with 471 additions and 132 deletions

View File

@@ -11,8 +11,8 @@ from __future__ import absolute_import
from srcgen import Formatter
from base import legalize, instructions
from cdsl.ast import Var
from cdsl.ti import ti_rtl, TypeEnv, get_type_env, ConstrainTVsEqual,\
ConstrainTVInTypeset
from cdsl.ti import ti_rtl, TypeEnv, get_type_env, TypesEqual,\
InTypeset, WiderOrEq
from unique_table import UniqueTable
from gen_instr import gen_typesets_table
from cdsl.typevar import TypeVar
@@ -66,7 +66,7 @@ def get_runtime_typechecks(xform):
assert xform_ts.issubset(src_ts)
if src_ts != xform_ts:
check_l.append(ConstrainTVInTypeset(xform.ti[v], xform_ts))
check_l.append(InTypeset(xform.ti[v], xform_ts))
# 2,3) Add any constraints that appear in xform.ti
check_l.extend(xform.ti.constraints)
@@ -81,6 +81,14 @@ def emit_runtime_typecheck(check, fmt, type_sets):
"""
def build_derived_expr(tv):
# type: (TypeVar) -> str
"""
Build an expression of type Option<Type> corresponding to a concrete
type transformed by the sequence of derivation functions in tv.
We are using Option<Type>, as some constraints may cause an
over/underflow on patterns that do not match them. We want to capture
this without panicking at runtime.
"""
if not tv.is_derived:
assert tv.name.startswith('typeof_')
return "Some({})".format(tv.name)
@@ -102,7 +110,8 @@ def emit_runtime_typecheck(check, fmt, type_sets):
else:
assert False, "Unknown derived function {}".format(tv.derived_func)
if (isinstance(check, ConstrainTVInTypeset)):
if (isinstance(check, InTypeset)):
assert not check.tv.is_derived
tv = check.tv.name
if check.ts not in type_sets.index:
type_sets.add(check.ts)
@@ -112,11 +121,28 @@ def emit_runtime_typecheck(check, fmt, type_sets):
with fmt.indented('if !TYPE_SETS[{}].contains({}) {{'.format(ts, tv),
'};'):
fmt.line('return false;')
elif (isinstance(check, ConstrainTVsEqual)):
tv1 = build_derived_expr(check.tv1)
tv2 = build_derived_expr(check.tv2)
with fmt.indented('if {} != {} {{'.format(tv1, tv2), '};'):
fmt.line('return false;')
elif (isinstance(check, TypesEqual)):
with fmt.indented('{', '};'):
fmt.line('let a = {};'.format(build_derived_expr(check.tv1)))
fmt.line('let b = {};'.format(build_derived_expr(check.tv2)))
fmt.comment('On overflow constraint doesn\'t appply')
with fmt.indented('if a.is_none() || b.is_none() {', '};'):
fmt.line('return false;')
with fmt.indented('if a != b {', '};'):
fmt.line('return false;')
elif (isinstance(check, WiderOrEq)):
with fmt.indented('{', '};'):
fmt.line('let a = {};'.format(build_derived_expr(check.tv1)))
fmt.line('let b = {};'.format(build_derived_expr(check.tv2)))
fmt.comment('On overflow constraint doesn\'t appply')
with fmt.indented('if a.is_none() || b.is_none() {', '};'):
fmt.line('return false;')
with fmt.indented('if !a.wider_or_equal(b) {', '};'):
fmt.line('return false;')
else:
assert False, "Unknown check {}".format(check)