mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 15:43:01 +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:
		| @@ -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) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose