mirror of
https://github.com/janet-lang/janet
synced 2025-07-08 13:02:55 +00:00
Address compiler bug with break
.
Using result from `break` expression could trigger code that would work, yet contain invalid, dead code preventing good marshalling.
This commit is contained in:
parent
b63d41102e
commit
e05bc7eb54
@ -26,6 +26,7 @@
|
|||||||
#include "emit.h"
|
#include "emit.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
#include "regalloc.h"
|
#include "regalloc.h"
|
||||||
|
#include "util.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Get a register */
|
/* Get a register */
|
||||||
@ -128,7 +129,8 @@ static void janetc_movenear(JanetCompiler *c,
|
|||||||
((uint32_t)(src.envindex) << 16) |
|
((uint32_t)(src.envindex) << 16) |
|
||||||
((uint32_t)(dest) << 8) |
|
((uint32_t)(dest) << 8) |
|
||||||
JOP_LOAD_UPVALUE);
|
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,
|
janetc_emit(c,
|
||||||
((uint32_t)(src.index) << 16) |
|
((uint32_t)(src.index) << 16) |
|
||||||
((uint32_t)(dest) << 8) |
|
((uint32_t)(dest) << 8) |
|
||||||
@ -155,6 +157,7 @@ static void janetc_moveback(JanetCompiler *c,
|
|||||||
((uint32_t)(src) << 8) |
|
((uint32_t)(src) << 8) |
|
||||||
JOP_SET_UPVALUE);
|
JOP_SET_UPVALUE);
|
||||||
} else if (dest.index != src) {
|
} else if (dest.index != src) {
|
||||||
|
janet_assert(dest.index >= 0, "bad slot");
|
||||||
janetc_emit(c,
|
janetc_emit(c,
|
||||||
((uint32_t)(dest.index) << 16) |
|
((uint32_t)(dest.index) << 16) |
|
||||||
((uint32_t)(src) << 8) |
|
((uint32_t)(src) << 8) |
|
||||||
|
@ -752,9 +752,8 @@ static JanetSlot janetc_break(JanetFopts opts, int32_t argn, const Janet *argv)
|
|||||||
if (!(scope->flags & JANET_SCOPE_WHILE) && argn) {
|
if (!(scope->flags & JANET_SCOPE_WHILE) && argn) {
|
||||||
/* Closure body with return argument */
|
/* Closure body with return argument */
|
||||||
subopts.flags |= JANET_FOPTS_TAIL;
|
subopts.flags |= JANET_FOPTS_TAIL;
|
||||||
JanetSlot ret = janetc_value(subopts, argv[0]);
|
janetc_value(subopts, argv[0]);
|
||||||
ret.flags |= JANET_SLOT_RETURNED;
|
return janetc_cslot(janet_wrap_nil());
|
||||||
return ret;
|
|
||||||
} else {
|
} else {
|
||||||
/* while loop IIFE or no argument */
|
/* while loop IIFE or no argument */
|
||||||
if (argn) {
|
if (argn) {
|
||||||
@ -762,9 +761,7 @@ static JanetSlot janetc_break(JanetFopts opts, int32_t argn, const Janet *argv)
|
|||||||
janetc_value(subopts, argv[0]);
|
janetc_value(subopts, argv[0]);
|
||||||
}
|
}
|
||||||
janetc_emit(c, JOP_RETURN_NIL);
|
janetc_emit(c, JOP_RETURN_NIL);
|
||||||
JanetSlot s = janetc_cslot(janet_wrap_nil());
|
return janetc_cslot(janet_wrap_nil());
|
||||||
s.flags |= JANET_SLOT_RETURNED;
|
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (argn) {
|
if (argn) {
|
||||||
|
@ -924,4 +924,25 @@
|
|||||||
[:strict 3 4 "bar-oops"]])
|
[:strict 3 4 "bar-oops"]])
|
||||||
"maclintf 2")
|
"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)
|
(end-suite)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user