Skip to content

Commit 882baa9

Browse files
committed
Type Equality/Compatibility Revamp
Taken from #213, but with some refinements
1 parent ecb616f commit 882baa9

File tree

7 files changed

+298
-123
lines changed

7 files changed

+298
-123
lines changed

py/dml/codegen.py

+3-15
Original file line numberDiff line numberDiff line change
@@ -1306,18 +1306,7 @@ def expr_cast(tree, location, scope):
13061306
for (site, _) in struct_defs:
13071307
report(EANONSTRUCT(site, "'cast' expression"))
13081308

1309-
if (compat.dml12_misc in dml.globals.enabled_compat
1310-
and isinstance(expr, InterfaceMethodRef)):
1311-
# Workaround for SIMICS-9868
1312-
return mkLit(tree.site, "%s->%s" % (
1313-
expr.node_expr.read(), expr.method_name), type)
1314-
1315-
if isinstance(expr, NonValue) and (
1316-
not isinstance(expr, NodeRef)
1317-
or not isinstance(safe_realtype(type), TTrait)):
1318-
raise expr.exc()
1319-
else:
1320-
return mkCast(tree.site, expr, type)
1309+
return mkCast(tree.site, expr, type)
13211310

13221311
@expression_dispatcher
13231312
def expr_undefined(tree, location, scope):
@@ -2008,9 +1997,8 @@ def mk_sym(name, typ, mkunique=not dml.globals.debuggable):
20081997
for (name, typ) in decls:
20091998
sym = mk_sym(name, typ)
20101999
tgt_typ = safe_realtype_shallow(typ)
2011-
if tgt_typ.const:
2012-
nonconst_typ = tgt_typ.clone()
2013-
nonconst_typ.const = False
2000+
if shallow_const(tgt_typ):
2001+
nonconst_typ = safe_realtype_unconst(tgt_typ)
20142002
tgt_sym = mk_sym('_tmp_' + name, nonconst_typ, True)
20152003
sym.init = ExpressionInitializer(mkLocalVariable(stmt.site,
20162004
tgt_sym))

py/dml/ctree.py

+44-22
Original file line numberDiff line numberDiff line change
@@ -1222,7 +1222,7 @@ def mkIfExpr(site, cond, texpr, fexpr):
12221222
(texpr, fexpr, utype) = usual_int_conv(
12231223
texpr, ttype, fexpr, ftype)
12241224
else:
1225-
if not compatible_types(ttype, ftype):
1225+
if not compatible_types_fuzzy(ttype, ftype):
12261226
raise EBINOP(site, ':', texpr, fexpr)
12271227
# TODO: in C, the rules are more complex,
12281228
# but our type system is too primitive to cover that
@@ -1396,7 +1396,7 @@ def make(cls, site, lh, rh):
13961396
if ((lhtype.is_arith and rhtype.is_arith)
13971397
or (isinstance(lhtype, (TPtr, TArray))
13981398
and isinstance(rhtype, (TPtr, TArray))
1399-
and compatible_types(lhtype.base, rhtype.base))):
1399+
and compatible_types_fuzzy(lhtype.base, rhtype.base))):
14001400
return cls.make_simple(site, lh, rh)
14011401
raise EILLCOMP(site, lh, lhtype, rh, rhtype)
14021402

@@ -1601,7 +1601,7 @@ def make(cls, site, lh, rh):
16011601
if ((lhtype.is_arith and rhtype.is_arith)
16021602
or (isinstance(lhtype, (TPtr, TArray))
16031603
and isinstance(rhtype, (TPtr, TArray))
1604-
and compatible_types(lhtype, rhtype))
1604+
and compatible_types_fuzzy(lhtype, rhtype))
16051605
or (isinstance(lhtype, TBool) and isinstance(rhtype, TBool))):
16061606
return Equals(site, lh, rh)
16071607

@@ -2932,8 +2932,8 @@ def mkInterfaceMethodRef(site, iface_node, indices, method_name):
29322932
if (not isinstance(ftype, TPtr)
29332933
or not isinstance(ftype.base, TFunction)
29342934
or not ftype.base.input_types
2935-
or TPtr(safe_realtype(TNamed('conf_object_t'))).cmp(
2936-
safe_realtype(ftype.base.input_types[0])) != 0):
2935+
or TPtr(safe_realtype_unconst(TNamed('conf_object_t'))).cmp(
2936+
safe_realtype_unconst(ftype.base.input_types[0])) != 0):
29372937
# non-method members are not accessible
29382938
raise EMEMBER(site, struct_name, method_name)
29392939

@@ -4674,7 +4674,10 @@ class ArrayRef(LValue):
46744674
explicit_type = True
46754675
@auto_init
46764676
def __init__(self, site, expr, idx):
4677-
self.type = realtype_shallow(expr.ctype()).base
4677+
expr_type = realtype_shallow(expr.ctype())
4678+
self.type = conv_const(expr_type.const
4679+
and isinstance(expr_type, TArray),
4680+
expr_type.base)
46784681
def __str__(self):
46794682
return '%s[%s]' % (self.expr, self.idx)
46804683
def read(self):
@@ -4787,30 +4790,41 @@ def mkCast(site, expr, new_type):
47874790
raise ETEMPLATEUPCAST(site, "object", new_type)
47884791
else:
47894792
return mkTraitUpcast(site, expr, real.trait)
4793+
4794+
if (compat.dml12_misc in dml.globals.enabled_compat
4795+
and isinstance(expr, InterfaceMethodRef)):
4796+
# Workaround for SIMICS-9868
4797+
return mkLit(site, "%s->%s" % (
4798+
expr.node_expr.read(), expr.method_name), new_type)
4799+
4800+
if isinstance(expr, NonValue):
4801+
raise expr.exc()
47904802
old_type = safe_realtype(expr.ctype())
47914803
if (dml.globals.compat_dml12_int(site)
47924804
and (isinstance(old_type, (TStruct, TVector))
47934805
or isinstance(real, (TStruct, TVector)))):
47944806
# these casts are permitted by C only if old and new are
47954807
# the same type, which is useless
47964808
return Cast(site, expr, new_type)
4797-
if isinstance(real, TStruct):
4798-
if isinstance(old_type, TStruct) and old_type.label == real.label:
4799-
return expr
4800-
raise ECAST(site, expr, new_type)
4801-
if isinstance(real, TExternStruct):
4802-
if isinstance(old_type, TExternStruct) and old_type.id == real.id:
4803-
return expr
4809+
if isinstance(real, (TVoid, TArray, TFunction)):
48044810
raise ECAST(site, expr, new_type)
4805-
if isinstance(real, (TVoid, TArray, TVector, TTraitList, TFunction)):
4811+
if old_type.cmp(real) == 0:
4812+
if (old_type.is_int
4813+
and not old_type.is_endian
4814+
and dml.globals.compat_dml12_int(expr.site)):
4815+
# 1.2 integer expressions often lie about their actual type,
4816+
# and require a "redundant" cast! Why yes, this IS horrid!
4817+
return Cast(site, expr, new_type)
4818+
return mkRValue(expr)
4819+
if isinstance(real, (TStruct, TExternStruct, TVector, TTraitList)):
48064820
raise ECAST(site, expr, new_type)
48074821
if isinstance(old_type, (TVoid, TStruct, TVector, TTraitList, TTrait)):
48084822
raise ECAST(site, expr, new_type)
48094823
if old_type.is_int and old_type.is_endian:
48104824
expr = as_int(expr)
48114825
old_type = safe_realtype(expr.ctype())
48124826
if real.is_int and not real.is_endian:
4813-
if isinstance(expr, IntegerConstant):
4827+
if old_type.is_int and expr.constant:
48144828
value = truncate_int_bits(expr.value, real.signed, real.bits)
48154829
if dml.globals.compat_dml12_int(site):
48164830
return IntegerConstant_dml12(site, value, real)
@@ -4821,8 +4835,8 @@ def mkCast(site, expr, new_type):
48214835
# Shorten redundant chains of integer casts. Avoids insane C
48224836
# output for expressions like a+b+c+d.
48234837
if (isinstance(expr, Cast)
4824-
and isinstance(expr.type, TInt)
4825-
and expr.type.bits >= real.bits):
4838+
and isinstance(old_type, TInt)
4839+
and old_type.bits >= real.bits):
48264840
# (uint64)(int64)x -> (uint64)x
48274841
expr = expr.expr
48284842
old_type = safe_realtype(expr.ctype())
@@ -4858,9 +4872,7 @@ def mkCast(site, expr, new_type):
48584872
return expr
48594873
elif real.is_int and real.is_endian:
48604874
old_type = safe_realtype(expr.ctype())
4861-
if real.cmp(old_type) == 0:
4862-
return expr
4863-
elif old_type.is_arith or isinstance(old_type, TPtr):
4875+
if old_type.is_arith or isinstance(old_type, TPtr):
48644876
return mkApply(
48654877
expr.site,
48664878
mkLit(expr.site, *real.get_store_fun()),
@@ -4917,7 +4929,6 @@ def mkCast(site, expr, new_type):
49174929
class RValue(Expression):
49184930
'''Wraps an lvalue to prohibit write. Useful when a composite
49194931
expression is reduced down to a single variable.'''
4920-
writable = False
49214932
@auto_init
49224933
def __init__(self, site, expr): pass
49234934
def __str__(self):
@@ -4926,11 +4937,22 @@ def ctype(self):
49264937
return self.expr.ctype()
49274938
def read(self):
49284939
return self.expr.read()
4929-
def discard(self): pass
4940+
def discard(self):
4941+
return self.expr.discard()
49304942
def incref(self):
49314943
self.expr.incref()
49324944
def decref(self):
49334945
self.expr.decref()
4946+
@property
4947+
def explicit_type(self):
4948+
return self.expr.explicit_type
4949+
@property
4950+
def type(self):
4951+
assert self.explicit_type
4952+
return self.expr.type
4953+
@property
4954+
def is_pointer_to_stack_allocation(self):
4955+
return self.expr.is_pointer_to_stack_allocation
49344956

49354957
def mkRValue(expr):
49364958
if isinstance(expr, LValue) or expr.writable:

py/dml/ctree_test.py

+2
Original file line numberDiff line numberDiff line change
@@ -1416,6 +1416,8 @@ def const_types(self):
14161416
# abstract type
14171417
types.IntegerType,
14181418
# abstract type
1419+
types.ArchDependentIntegerType,
1420+
# abstract type
14191421
types.StructType,
14201422
# 1.2, weird
14211423
types.TUnknown,

py/dml/structure.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,8 @@ def typecheck_method_override(m1, m2, location):
674674
# TODO move to caller
675675
(_, type1) = eval_type(t1, a1.site, location, global_scope)
676676
(_, type2) = eval_type(t2, a2.site, location, global_scope)
677-
if safe_realtype(type1).cmp(safe_realtype(type2)) != 0:
677+
if safe_realtype_unconst(type1).cmp(
678+
safe_realtype_unconst(type2)) != 0:
678679
raise EMETH(a1.site, a2.site,
679680
f"mismatching types in input argument {n1}")
680681

@@ -683,7 +684,8 @@ def typecheck_method_override(m1, m2, location):
683684
((n1, t1), (n2, t2)) = (a1.args, a2.args)
684685
(_, type1) = eval_type(t1, a1.site, location, global_scope)
685686
(_, type2) = eval_type(t2, a2.site, location, global_scope)
686-
if safe_realtype(type1).cmp(safe_realtype(type2)) != 0:
687+
if safe_realtype_unconst(type1).cmp(
688+
safe_realtype_unconst(type2)) != 0:
687689
msg = "mismatching types in return value"
688690
if len(outp1) > 1:
689691
msg += f" {i + 1}"

py/dml/traits.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -398,11 +398,11 @@ def typecheck_method_override(left, right):
398398
if throws0 != throws1:
399399
raise EMETH(site0, site1, "different nothrow annotations")
400400
for ((n, t0), (_, t1)) in zip(inp0, inp1):
401-
if realtype(t0).cmp(realtype(t1)) != 0:
401+
if safe_realtype_unconst(t0).cmp(safe_realtype_unconst(t1)) != 0:
402402
raise EMETH(site0, site1,
403403
"mismatching types in input argument %s" % (n,))
404404
for (i, ((_, t0), (_, t1))) in enumerate(zip(outp0, outp1)):
405-
if realtype(t0).cmp(realtype(t1)) != 0:
405+
if safe_realtype_unconst(t0).cmp(safe_realtype_unconst(t1)) != 0:
406406
raise EMETH(site0, site1,
407407
"mismatching types in output argument %d" % (i + 1,))
408408

0 commit comments

Comments
 (0)