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