summary refs log tree commit diff
path: root/load.c
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2021-04-11 01:49:15 -0700
committerQuentin Carbonneaux <quentin@c9x.me>2021-07-29 23:37:57 +0200
commit98cd2e817616fff14622b8e514fc88b378a100ef (patch)
tree9d58b2183ad879f8b12cb07ccd1bea51d5082eae /load.c
parentb543ffed71497fb079bfdca53934870a1189c325 (diff)
downloadroux-98cd2e817616fff14622b8e514fc88b378a100ef.tar.gz
load: handle all cases in cast()
Previously, all casts but d->w, d->s, l->s, s->d, w->d were supported.
At least the first three can occur by storing to then loading from
a slot, currently triggering an assertion failure. Though the other
two might not be possible, they are easy enough to support as well.

Fixes hare#360.
Diffstat (limited to 'load.c')
-rw-r--r--load.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/load.c b/load.c
index ae9cfcf..f3a695b 100644
--- a/load.c
+++ b/load.c
@@ -92,14 +92,17 @@ cast(Ref *r, int cls, Loc *l)
 	cls0 = curf->tmp[r->val].cls;
 	if (cls0 == cls || (cls == Kw && cls0 == Kl))
 		return;
-	assert(!KWIDE(cls0) || KWIDE(cls));
-	if (KWIDE(cls) == KWIDE(cls0))
-		*r = iins(cls, Ocast, *r, R, l);
-	else {
-		assert(cls == Kl);
+	if (KWIDE(cls0) < KWIDE(cls)) {
 		if (cls0 == Ks)
 			*r = iins(Kw, Ocast, *r, R, l);
 		*r = iins(Kl, Oextuw, *r, R, l);
+		if (cls == Kd)
+			*r = iins(Kd, Ocast, *r, R, l);
+	} else {
+		if (cls0 == Kd && cls != Kl)
+			*r = iins(Kl, Ocast, *r, R, l);
+		if (cls0 != Kd || cls != Kw)
+			*r = iins(cls, Ocast, *r, R, l);
 	}
 }