From e05bc7eb5471d7ea49f4407b641f3b2795190477 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Thu, 28 Sep 2023 20:14:22 -0500 Subject: [PATCH] Address compiler bug with `break`. Using result from `break` expression could trigger code that would work, yet contain invalid, dead code preventing good marshalling. --- src/core/emit.c | 5 ++++- src/core/specials.c | 9 +++------ test/suite-boot.janet | 21 +++++++++++++++++++++ 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/core/emit.c b/src/core/emit.c index e1f921a4..68accc52 100644 --- a/src/core/emit.c +++ b/src/core/emit.c @@ -26,6 +26,7 @@ #include "emit.h" #include "vector.h" #include "regalloc.h" +#include "util.h" #endif /* Get a register */ @@ -128,7 +129,8 @@ static void janetc_movenear(JanetCompiler *c, ((uint32_t)(src.envindex) << 16) | ((uint32_t)(dest) << 8) | JOP_LOAD_UPVALUE); - } else if (src.index > 0xFF || src.index != dest) { + } else if (src.index != dest) { + janet_assert(src.index >= 0, "bad slot"); janetc_emit(c, ((uint32_t)(src.index) << 16) | ((uint32_t)(dest) << 8) | @@ -155,6 +157,7 @@ static void janetc_moveback(JanetCompiler *c, ((uint32_t)(src) << 8) | JOP_SET_UPVALUE); } else if (dest.index != src) { + janet_assert(dest.index >= 0, "bad slot"); janetc_emit(c, ((uint32_t)(dest.index) << 16) | ((uint32_t)(src) << 8) | diff --git a/src/core/specials.c b/src/core/specials.c index c19c728b..9bd58ef8 100644 --- a/src/core/specials.c +++ b/src/core/specials.c @@ -752,9 +752,8 @@ static JanetSlot janetc_break(JanetFopts opts, int32_t argn, const Janet *argv) if (!(scope->flags & JANET_SCOPE_WHILE) && argn) { /* Closure body with return argument */ subopts.flags |= JANET_FOPTS_TAIL; - JanetSlot ret = janetc_value(subopts, argv[0]); - ret.flags |= JANET_SLOT_RETURNED; - return ret; + janetc_value(subopts, argv[0]); + return janetc_cslot(janet_wrap_nil()); } else { /* while loop IIFE or no argument */ if (argn) { @@ -762,9 +761,7 @@ static JanetSlot janetc_break(JanetFopts opts, int32_t argn, const Janet *argv) janetc_value(subopts, argv[0]); } janetc_emit(c, JOP_RETURN_NIL); - JanetSlot s = janetc_cslot(janet_wrap_nil()); - s.flags |= JANET_SLOT_RETURNED; - return s; + return janetc_cslot(janet_wrap_nil()); } } else { if (argn) { diff --git a/test/suite-boot.janet b/test/suite-boot.janet index 911a0c92..a275c6bf 100644 --- a/test/suite-boot.janet +++ b/test/suite-boot.janet @@ -924,4 +924,25 @@ [:strict 3 4 "bar-oops"]]) "maclintf 2") +# Bad bytecode wrt. using result from break expression +(defn bytecode-roundtrip + [f] + (assert-no-error "bytecode round-trip" (unmarshal (marshal f make-image-dict)))) + +(defn case-1 [&] (def x (break 1))) +(bytecode-roundtrip case-1) +(defn foo [&]) +(defn case-2 [&] + (foo (break (foo))) + (foo)) +(bytecode-roundtrip case-2) +(defn case-3 [&] + (def x (break (do (foo))))) +(bytecode-roundtrip case-3) + +# Debug bytecode of these functions +# (pp (disasm case-1)) +# (pp (disasm case-2)) +# (pp (disasm case-3)) + (end-suite)