mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 07:33:01 +00:00 
			
		
		
		
	Change how labels are recorded.
Disallow jumping to arbitrary instructions - instead, only allow jumps to label ids. This will make various transformations and validations easier since adding or remove instructions does not break jumps.
This commit is contained in:
		| @@ -45,7 +45,8 @@ | |||||||
|   t) |   t) | ||||||
|  |  | ||||||
| (defn setup-default-types | (defn setup-default-types | ||||||
|   [into] |   [ctx] | ||||||
|  |   (def into @[]) | ||||||
|   (defn add-prim-type |   (defn add-prim-type | ||||||
|     [name native-name] |     [name native-name] | ||||||
|     (array/push into ~(type-prim ,name ,native-name)) |     (array/push into ~(type-prim ,name ,native-name)) | ||||||
| @@ -54,7 +55,9 @@ | |||||||
|   (add-prim-type 'double 'f64) |   (add-prim-type 'double 'f64) | ||||||
|   (add-prim-type 'int 's32) |   (add-prim-type 'int 's32) | ||||||
|   (add-prim-type 'pointer 'pointer) |   (add-prim-type 'pointer 'pointer) | ||||||
|   (add-prim-type 'boolean 'boolean)) |   (add-prim-type 'boolean 'boolean) | ||||||
|  |   (sysir/asm ctx into) | ||||||
|  |   ctx) | ||||||
|  |  | ||||||
| (defn type-extract | (defn type-extract | ||||||
|   "Given a symbol:type combination, extract the proper name and the type separately" |   "Given a symbol:type combination, extract the proper name and the type separately" | ||||||
| @@ -66,9 +69,13 @@ | |||||||
| (var do-binop nil) | (var do-binop nil) | ||||||
| (var do-comp nil) | (var do-comp nil) | ||||||
|  |  | ||||||
|  | ### | ||||||
|  | ### Inside functions | ||||||
|  | ### | ||||||
|  |  | ||||||
| (defn visit1 | (defn visit1 | ||||||
|   "Take in a form and compile code and put it into `into`. Return result slot." |   "Take in a form and compile code and put it into `into`. Return result slot." | ||||||
|   [code into] |   [code into &opt no-return] | ||||||
|   (cond |   (cond | ||||||
|  |  | ||||||
|     # Compile a constant |     # Compile a constant | ||||||
| @@ -79,6 +86,14 @@ | |||||||
|       (array/push into ~(constant ,slot ,code)) |       (array/push into ~(constant ,slot ,code)) | ||||||
|       slot) |       slot) | ||||||
|  |  | ||||||
|  |     # Booleans | ||||||
|  |     (boolean? code) | ||||||
|  |     (let [slot (get-slot) | ||||||
|  |           slottype 'boolean] | ||||||
|  |       (array/push into ~(bind ,slot ,slottype)) | ||||||
|  |       (array/push into ~(constant ,slot ,(if code -1 0))) | ||||||
|  |       slot) | ||||||
|  |  | ||||||
|     # Binding |     # Binding | ||||||
|     (symbol? code) |     (symbol? code) | ||||||
|     (named-slot code) |     (named-slot code) | ||||||
| @@ -136,13 +151,27 @@ | |||||||
|           (array/push into ~(move ,slot ,result)) |           (array/push into ~(move ,slot ,result)) | ||||||
|           slot) |           slot) | ||||||
|  |  | ||||||
|  |         # Named variables | ||||||
|  |         'var | ||||||
|  |         (do | ||||||
|  |           (assert (= 2 (length args))) | ||||||
|  |           (def [full-name value] args) | ||||||
|  |           (assert (symbol? full-name)) | ||||||
|  |           (def [name tp] (type-extract full-name 'int)) | ||||||
|  |           (def result (visit1 value into)) | ||||||
|  |           (def slot (get-slot name)) | ||||||
|  |           (when tp | ||||||
|  |             (array/push into ~(bind ,slot ,tp))) | ||||||
|  |           (array/push into ~(move ,slot ,result)) | ||||||
|  |           slot) | ||||||
|  |  | ||||||
|         # Assignment |         # Assignment | ||||||
|         'set |         'set | ||||||
|         (do |         (do | ||||||
|           (assert (= 2 (length args))) |           (assert (= 2 (length args))) | ||||||
|           (def [to x] args) |           (def [to x] args) | ||||||
|           (def result (visit1 x into)) |           (def result (visit1 x into)) | ||||||
|           (def toslot (get-slot to)) |           (def toslot (named-slot to)) | ||||||
|           (array/push into ~(move ,toslot ,result)) |           (array/push into ~(move ,toslot ,result)) | ||||||
|           toslot) |           toslot) | ||||||
|  |  | ||||||
| @@ -160,9 +189,24 @@ | |||||||
|         # Sequence of operations |         # Sequence of operations | ||||||
|         'do |         'do | ||||||
|         (do |         (do | ||||||
|           (var ret nil) |           (each form (slice args 0 -2) (visit1 form into true)) | ||||||
|           (each form args (set ret (visit1 form into))) |           (visit1 (last args) into)) | ||||||
|           ret) |  | ||||||
|  |         # While loop | ||||||
|  |         'while | ||||||
|  |         (do | ||||||
|  |           (def lab-test (keyword (gensym))) | ||||||
|  |           (def lab-exit (keyword (gensym))) | ||||||
|  |           (assert (< 1 (length args))) | ||||||
|  |           (def [cnd & body] args) | ||||||
|  |           (array/push into lab-test) | ||||||
|  |           (def condition-slot (visit1 cnd into)) | ||||||
|  |           (array/push into ~(branch-not ,condition-slot ,lab-exit)) | ||||||
|  |           (each code body | ||||||
|  |             (visit1 code into true)) | ||||||
|  |           (array/push into ~(jump ,lab-test)) | ||||||
|  |           (array/push into lab-exit) | ||||||
|  |           nil) | ||||||
|  |  | ||||||
|         # Branch |         # Branch | ||||||
|         'if |         'if | ||||||
| @@ -186,7 +230,7 @@ | |||||||
|         # Assume function call |         # Assume function call | ||||||
|         (do |         (do | ||||||
|           (def slots @[]) |           (def slots @[]) | ||||||
|           (def ret (get-slot)) |           (def ret (if no-return nil (get-slot))) | ||||||
|           (each arg args |           (each arg args | ||||||
|             (array/push slots (visit1 arg into))) |             (array/push slots (visit1 arg into))) | ||||||
|           (array/push into ~(call ,ret ,op ,;slots)) |           (array/push into ~(call ,ret ,op ,;slots)) | ||||||
| @@ -235,28 +279,79 @@ | |||||||
|     (set left right)) |     (set left right)) | ||||||
|   result) |   result) | ||||||
|  |  | ||||||
|  | ### | ||||||
|  | ### Top level | ||||||
|  | ### | ||||||
|  |  | ||||||
|  | (defn top | ||||||
|  |   "Visit and emit code for a top level form." | ||||||
|  |   [ctx form] | ||||||
|  |   (assert (tuple? form)) | ||||||
|  |   (def [head & rest] form) | ||||||
|  |   (case head | ||||||
|  |  | ||||||
|  |     # Top level function definition | ||||||
|  |     'defn | ||||||
|  |     (do | ||||||
|  |       # TODO doc strings | ||||||
|  |       (table/clear name-to-slot) | ||||||
|  |       (array/clear slot-to-name) | ||||||
|  |       (def [name args & body] rest) | ||||||
|  |       (assert (tuple? args)) | ||||||
|  |       (def [fn-name fn-tp] (type-extract name 'int)) | ||||||
|  |       (def pcount (length args)) #TODO - more complicated signatures | ||||||
|  |       (def ir-asm | ||||||
|  |         @[~(link-name ,(string fn-name)) | ||||||
|  |           ~(parameter-count ,pcount)]) | ||||||
|  |       (each arg args | ||||||
|  |         (def [name tp] (type-extract arg 'int)) | ||||||
|  |         (def slot (get-slot name)) | ||||||
|  |         (array/push ir-asm ~(bind ,slot ,tp))) | ||||||
|  |       (each part body | ||||||
|  |         (visit1 part ir-asm true)) | ||||||
|  |       (eprintf "%.99M\n" ir-asm) | ||||||
|  |       (sysir/asm ctx ir-asm)) | ||||||
|  |  | ||||||
|  |     (errorf "unknown form %v" form))) | ||||||
|  |  | ||||||
| ### | ### | ||||||
| ### | ### | ||||||
| ### | ### | ||||||
|  |  | ||||||
| (def myprog | (def myprog | ||||||
|   '(do |   '(defn myprog [] | ||||||
|      (def xyz:int (+ 1 2 3)) |      (def xyz:int (+ 1 2 3)) | ||||||
|      (def abc:int (* 4 5 6)) |      (def abc:int (* 4 5 6)) | ||||||
|      (def x:boolean (= 5 7)) |      (def x:boolean (= 5 7)) | ||||||
|      (the int (printf "hello, world!\n%d\n" (the int (if x abc xyz)))) |      (var i:int 0) | ||||||
|  |      (while (< i 10) | ||||||
|  |        (set i (+ 1 i)) | ||||||
|  |        (printf "i = %d\n" (the int i))) | ||||||
|  |      (printf "hello, world!\n%d\n" (the int (if x abc xyz))) | ||||||
|      (return (/ abc xyz)))) |      (return (/ abc xyz)))) | ||||||
|  |  | ||||||
|  | (def doloop | ||||||
|  |   '(defn doloop [x:int y:int] | ||||||
|  |      (var i:int x) | ||||||
|  |      (while (< i y) | ||||||
|  |        (set i (+ 1 i)) | ||||||
|  |        (printf "i = %d\n" (the int i))) | ||||||
|  |      (return x))) | ||||||
|  |  | ||||||
|  | (def main-fn | ||||||
|  |   '(defn main:int [] | ||||||
|  |      (var x:int 10) | ||||||
|  |      (doloop 10 20) | ||||||
|  |      (printf "done!\n") | ||||||
|  |      (return (the int 0)))) | ||||||
|  |  | ||||||
| (defn dotest | (defn dotest | ||||||
|   [] |   [] | ||||||
|   (def ctx (sysir/context)) |   (def ctx (sysir/context)) | ||||||
|   (def ir-asm |   (setup-default-types ctx) | ||||||
|     @['(link-name "main") |   #(top ctx myprog) | ||||||
|       '(parameter-count 0)]) |   (top ctx doloop) | ||||||
|   (setup-default-types ir-asm) |   (top ctx main-fn) | ||||||
|   (visit1 myprog ir-asm) |  | ||||||
|   (eprintf "%.99M" ir-asm) |  | ||||||
|   (sysir/asm ctx ir-asm) |  | ||||||
|   (print (sysir/to-c ctx))) |   (print (sysir/to-c ctx))) | ||||||
|  |  | ||||||
| (dotest) | (dotest) | ||||||
|   | |||||||
							
								
								
									
										218
									
								
								src/core/sysir.c
									
									
									
									
									
								
							
							
						
						
									
										218
									
								
								src/core/sysir.c
									
									
									
									
									
								
							| @@ -51,7 +51,7 @@ | |||||||
|  * [x] support for stack allocation of arrays |  * [x] support for stack allocation of arrays | ||||||
|  * [ ] more math intrinsics |  * [ ] more math intrinsics | ||||||
|  * [x] source mapping (using built in Janet source mapping metadata on tuples) |  * [x] source mapping (using built in Janet source mapping metadata on tuples) | ||||||
|  * [ ] unit type or void type |  * [x] unit type or void type | ||||||
|  * [ ] (typed) function pointer types and remove calling untyped pointers |  * [ ] (typed) function pointer types and remove calling untyped pointers | ||||||
|  * [x] APL array semantics for binary operands (maybe?) |  * [x] APL array semantics for binary operands (maybe?) | ||||||
|  * [ ] a few built-in array combinators (maybe?) |  * [ ] a few built-in array combinators (maybe?) | ||||||
| @@ -66,7 +66,6 @@ | |||||||
| #include <janet.h> | #include <janet.h> | ||||||
| #include "util.h" | #include "util.h" | ||||||
| #include "vector.h" | #include "vector.h" | ||||||
| #include <math.h> |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| typedef enum { | typedef enum { | ||||||
| @@ -85,6 +84,7 @@ typedef enum { | |||||||
|     JANET_PRIM_STRUCT, |     JANET_PRIM_STRUCT, | ||||||
|     JANET_PRIM_UNION, |     JANET_PRIM_UNION, | ||||||
|     JANET_PRIM_ARRAY, |     JANET_PRIM_ARRAY, | ||||||
|  |     JANET_PRIM_VOID, | ||||||
|     JANET_PRIM_UNKNOWN |     JANET_PRIM_UNKNOWN | ||||||
| } JanetPrim; | } JanetPrim; | ||||||
|  |  | ||||||
| @@ -109,6 +109,7 @@ static const JanetPrimName prim_names[] = { | |||||||
|     {"u64", JANET_PRIM_U64}, |     {"u64", JANET_PRIM_U64}, | ||||||
|     {"u8", JANET_PRIM_U8}, |     {"u8", JANET_PRIM_U8}, | ||||||
|     {"union", JANET_PRIM_UNION}, |     {"union", JANET_PRIM_UNION}, | ||||||
|  |     {"void", JANET_PRIM_VOID}, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| typedef enum { | typedef enum { | ||||||
| @@ -139,6 +140,7 @@ typedef enum { | |||||||
|     JANET_SYSOP_RETURN, |     JANET_SYSOP_RETURN, | ||||||
|     JANET_SYSOP_JUMP, |     JANET_SYSOP_JUMP, | ||||||
|     JANET_SYSOP_BRANCH, |     JANET_SYSOP_BRANCH, | ||||||
|  |     JANET_SYSOP_BRANCH_NOT, | ||||||
|     JANET_SYSOP_ADDRESS, |     JANET_SYSOP_ADDRESS, | ||||||
|     JANET_SYSOP_CALLK, |     JANET_SYSOP_CALLK, | ||||||
|     JANET_SYSOP_TYPE_PRIMITIVE, |     JANET_SYSOP_TYPE_PRIMITIVE, | ||||||
| @@ -153,6 +155,7 @@ typedef enum { | |||||||
|     JANET_SYSOP_TYPE_UNION, |     JANET_SYSOP_TYPE_UNION, | ||||||
|     JANET_SYSOP_POINTER_ADD, |     JANET_SYSOP_POINTER_ADD, | ||||||
|     JANET_SYSOP_POINTER_SUBTRACT, |     JANET_SYSOP_POINTER_SUBTRACT, | ||||||
|  |     JANET_SYSOP_LABEL | ||||||
| } JanetSysOp; | } JanetSysOp; | ||||||
|  |  | ||||||
| typedef struct { | typedef struct { | ||||||
| @@ -170,6 +173,7 @@ static const JanetSysInstrName sys_op_names[] = { | |||||||
|     {"bnot", JANET_SYSOP_BNOT}, |     {"bnot", JANET_SYSOP_BNOT}, | ||||||
|     {"bor", JANET_SYSOP_BOR}, |     {"bor", JANET_SYSOP_BOR}, | ||||||
|     {"branch", JANET_SYSOP_BRANCH}, |     {"branch", JANET_SYSOP_BRANCH}, | ||||||
|  |     {"branch-not", JANET_SYSOP_BRANCH_NOT}, | ||||||
|     {"bxor", JANET_SYSOP_BXOR}, |     {"bxor", JANET_SYSOP_BXOR}, | ||||||
|     {"call", JANET_SYSOP_CALL}, |     {"call", JANET_SYSOP_CALL}, | ||||||
|     {"cast", JANET_SYSOP_CAST}, |     {"cast", JANET_SYSOP_CAST}, | ||||||
| @@ -180,6 +184,7 @@ static const JanetSysInstrName sys_op_names[] = { | |||||||
|     {"gt", JANET_SYSOP_GT}, |     {"gt", JANET_SYSOP_GT}, | ||||||
|     {"gte", JANET_SYSOP_GTE}, |     {"gte", JANET_SYSOP_GTE}, | ||||||
|     {"jump", JANET_SYSOP_JUMP}, |     {"jump", JANET_SYSOP_JUMP}, | ||||||
|  |     {"label", JANET_SYSOP_LABEL}, | ||||||
|     {"link-name", JANET_SYSOP_LINK_NAME}, |     {"link-name", JANET_SYSOP_LINK_NAME}, | ||||||
|     {"load", JANET_SYSOP_LOAD}, |     {"load", JANET_SYSOP_LOAD}, | ||||||
|     {"lt", JANET_SYSOP_LT}, |     {"lt", JANET_SYSOP_LT}, | ||||||
| @@ -235,7 +240,14 @@ typedef struct { | |||||||
|             uint32_t dest; |             uint32_t dest; | ||||||
|             uint32_t callee; |             uint32_t callee; | ||||||
|             uint32_t arg_count; |             uint32_t arg_count; | ||||||
|  |             uint32_t has_dest; | ||||||
|         } call; |         } call; | ||||||
|  |         struct { | ||||||
|  |             uint32_t dest; | ||||||
|  |             uint32_t constant; | ||||||
|  |             uint32_t arg_count; | ||||||
|  |             uint32_t has_dest; | ||||||
|  |         } callk; | ||||||
|         struct { |         struct { | ||||||
|             uint32_t dest; |             uint32_t dest; | ||||||
|             uint32_t src; |             uint32_t src; | ||||||
| @@ -244,27 +256,16 @@ typedef struct { | |||||||
|             uint32_t src; |             uint32_t src; | ||||||
|         } one; |         } one; | ||||||
|         struct { |         struct { | ||||||
|             union { |  | ||||||
|             uint32_t to; |             uint32_t to; | ||||||
|                 Janet temp_label; |  | ||||||
|             }; |  | ||||||
|         } jump; |         } jump; | ||||||
|         struct { |         struct { | ||||||
|             uint32_t cond; |             uint32_t cond; | ||||||
|             union { |  | ||||||
|             uint32_t to; |             uint32_t to; | ||||||
|                 Janet temp_label; |  | ||||||
|             }; |  | ||||||
|         } branch; |         } branch; | ||||||
|         struct { |         struct { | ||||||
|             uint32_t dest; |             uint32_t dest; | ||||||
|             uint32_t constant; |             uint32_t constant; | ||||||
|         } constant; |         } constant; | ||||||
|         struct { |  | ||||||
|             uint32_t dest; |  | ||||||
|             uint32_t constant; |  | ||||||
|             uint32_t arg_count; |  | ||||||
|         } callk; |  | ||||||
|         struct { |         struct { | ||||||
|             uint32_t dest_type; |             uint32_t dest_type; | ||||||
|             uint32_t prim; |             uint32_t prim; | ||||||
| @@ -294,6 +295,9 @@ typedef struct { | |||||||
|             uint32_t type; |             uint32_t type; | ||||||
|             uint64_t fixed_count; |             uint64_t fixed_count; | ||||||
|         } array; |         } array; | ||||||
|  |         struct { | ||||||
|  |             uint32_t id; | ||||||
|  |         } label; | ||||||
|     }; |     }; | ||||||
|     int32_t line; |     int32_t line; | ||||||
|     int32_t column; |     int32_t column; | ||||||
| @@ -328,12 +332,11 @@ typedef struct { | |||||||
|     uint32_t constant_count; |     uint32_t constant_count; | ||||||
|     uint32_t return_type; |     uint32_t return_type; | ||||||
|     uint32_t parameter_count; |     uint32_t parameter_count; | ||||||
|  |     uint32_t label_count; | ||||||
|     uint32_t *types; |     uint32_t *types; | ||||||
|     JanetSysInstruction *instructions; |     JanetSysInstruction *instructions; | ||||||
|     JanetString *register_names; |     JanetString *register_names; | ||||||
|     Janet *constants; |     Janet *constants; | ||||||
|  |  | ||||||
|     /* Can/should we remove this info after initial compilation? */ |  | ||||||
|     JanetTable *register_name_lookup; |     JanetTable *register_name_lookup; | ||||||
|     JanetTable *labels; |     JanetTable *labels; | ||||||
| } JanetSysIR; | } JanetSysIR; | ||||||
| @@ -406,16 +409,21 @@ static uint64_t instr_read_u64(Janet x, JanetSysIR *ir) { | |||||||
|     return janet_getuinteger64(&x, 0); |     return janet_getuinteger64(&x, 0); | ||||||
| } | } | ||||||
|  |  | ||||||
| static uint32_t instr_read_type_operand(Janet x, JanetSysIR *ir) { | static uint32_t instr_read_type_operand(Janet x, JanetSysIR *ir, int is_definition) { | ||||||
|     JanetSysIRLinkage *linkage = ir->linkage; |     JanetSysIRLinkage *linkage = ir->linkage; | ||||||
|     if (janet_checktype(x, JANET_SYMBOL)) { |     if (janet_checktype(x, JANET_SYMBOL)) { | ||||||
|         Janet check = janet_table_get(linkage->type_name_lookup, x); |         Janet check = janet_table_get(linkage->type_name_lookup, x); | ||||||
|         if (janet_checktype(check, JANET_NUMBER)) { |         if (janet_checktype(check, JANET_NUMBER)) { | ||||||
|  |             if (is_definition) { | ||||||
|  |                 janet_panicf("cannot redefine type %v", x); | ||||||
|  |             } | ||||||
|             return (uint32_t) janet_unwrap_number(check); |             return (uint32_t) janet_unwrap_number(check); | ||||||
|         } else { |         } else if (is_definition) { | ||||||
|             uint32_t operand = linkage->type_def_count++; |             uint32_t operand = linkage->type_def_count++; | ||||||
|             janet_table_put(linkage->type_name_lookup, x, janet_wrap_number(operand)); |             janet_table_put(linkage->type_name_lookup, x, janet_wrap_number(operand)); | ||||||
|             return operand; |             return operand; | ||||||
|  |         } else { | ||||||
|  |             janet_panicf("unknown type %v", x); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     if (!janet_checkuint(x)) janet_panicf("expected non-negative integer operand, got %v", x); |     if (!janet_checkuint(x)) janet_panicf("expected non-negative integer operand, got %v", x); | ||||||
| @@ -440,15 +448,13 @@ static JanetPrim instr_read_prim(Janet x) { | |||||||
| } | } | ||||||
|  |  | ||||||
| static uint32_t instr_read_label(JanetSysIR *sysir, Janet x) { | static uint32_t instr_read_label(JanetSysIR *sysir, Janet x) { | ||||||
|     (void) sysir; |  | ||||||
|     uint32_t ret = 0; |     uint32_t ret = 0; | ||||||
|     Janet check = janet_table_get(sysir->labels, x); |     Janet check = janet_table_get(sysir->labels, x); | ||||||
|     if (!janet_checktype(check, JANET_NIL)) { |     if (janet_checktype(check, JANET_NIL)) { | ||||||
|         ret = (uint32_t) janet_unwrap_number(check); |         ret = sysir->label_count++; | ||||||
|  |         janet_table_put(sysir->labels, x, janet_wrap_number(ret)); | ||||||
|     } else { |     } else { | ||||||
|         if (janet_checktype(x, JANET_KEYWORD)) janet_panicf("unknown label %v", x); |         ret = (uint32_t) janet_unwrap_number(check); | ||||||
|         if (!janet_checkuint(x)) janet_panicf("expected non-negative integer label, got %v", x); |  | ||||||
|         ret = (uint32_t) janet_unwrap_number(x); |  | ||||||
|     } |     } | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| @@ -465,8 +471,22 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction | |||||||
|     Janet x = janet_wrap_nil(); |     Janet x = janet_wrap_nil(); | ||||||
|     for (int32_t i = 0; i < instructions.len; i++) { |     for (int32_t i = 0; i < instructions.len; i++) { | ||||||
|         x = instructions.items[i]; |         x = instructions.items[i]; | ||||||
|  |         /* Shorthand for labels */ | ||||||
|         if (janet_checktype(x, JANET_KEYWORD)) { |         if (janet_checktype(x, JANET_KEYWORD)) { | ||||||
|             janet_table_put(labels, x, janet_wrap_number(janet_v_count(ir))); |             /* Check for existing label */ | ||||||
|  |             JanetSysInstruction instruction; | ||||||
|  |             instruction.opcode = JANET_SYSOP_LABEL; | ||||||
|  |             instruction.line = -1; | ||||||
|  |             instruction.column = -1; | ||||||
|  |             instruction.label.id = instr_read_label(out, x); | ||||||
|  |             Janet label_id = janet_wrap_number(instruction.label.id); | ||||||
|  |             Janet check_defined = janet_table_get(labels, label_id); | ||||||
|  |             if (janet_checktype(check_defined, JANET_NIL)) { | ||||||
|  |                 janet_table_put(labels, label_id, janet_wrap_number(janet_v_count(ir))); | ||||||
|  |             } else { | ||||||
|  |                 janet_panicf("label %v already defined", x); | ||||||
|  |             } | ||||||
|  |             janet_v_push(ir, instruction); | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
|         if (!janet_checktype(x, JANET_TUPLE)) { |         if (!janet_checktype(x, JANET_TUPLE)) { | ||||||
| @@ -540,7 +560,13 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction | |||||||
|                 break; |                 break; | ||||||
|             case JANET_SYSOP_CALL: |             case JANET_SYSOP_CALL: | ||||||
|                 instr_assert_min_length(tuple, 2, opvalue); |                 instr_assert_min_length(tuple, 2, opvalue); | ||||||
|  |                 if (janet_checktype(tuple[1], JANET_NIL)) { | ||||||
|  |                     instruction.call.dest = 0; | ||||||
|  |                     instruction.call.has_dest = 0; | ||||||
|  |                 } else { | ||||||
|                     instruction.call.dest = instr_read_operand(tuple[1], out); |                     instruction.call.dest = instr_read_operand(tuple[1], out); | ||||||
|  |                     instruction.call.has_dest = 1; | ||||||
|  |                 } | ||||||
|                 Janet c = tuple[2]; |                 Janet c = tuple[2]; | ||||||
|                 if (janet_checktype(c, JANET_SYMBOL)) { |                 if (janet_checktype(c, JANET_SYMBOL)) { | ||||||
|                     instruction.callk.arg_count = janet_tuple_length(tuple) - 3; |                     instruction.callk.arg_count = janet_tuple_length(tuple) - 3; | ||||||
| @@ -599,14 +625,15 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction | |||||||
|                 janet_v_push(ir, instruction); |                 janet_v_push(ir, instruction); | ||||||
|                 break; |                 break; | ||||||
|             case JANET_SYSOP_BRANCH: |             case JANET_SYSOP_BRANCH: | ||||||
|  |             case JANET_SYSOP_BRANCH_NOT: | ||||||
|                 instr_assert_length(tuple, 3, opvalue); |                 instr_assert_length(tuple, 3, opvalue); | ||||||
|                 instruction.branch.cond = instr_read_operand(tuple[1], out); |                 instruction.branch.cond = instr_read_operand(tuple[1], out); | ||||||
|                 instruction.branch.temp_label = tuple[2]; |                 instruction.branch.to = instr_read_label(out, tuple[2]); | ||||||
|                 janet_v_push(ir, instruction); |                 janet_v_push(ir, instruction); | ||||||
|                 break; |                 break; | ||||||
|             case JANET_SYSOP_JUMP: |             case JANET_SYSOP_JUMP: | ||||||
|                 instr_assert_length(tuple, 2, opvalue); |                 instr_assert_length(tuple, 2, opvalue); | ||||||
|                 instruction.jump.temp_label = tuple[1]; |                 instruction.jump.to = instr_read_label(out, tuple[1]); | ||||||
|                 janet_v_push(ir, instruction); |                 janet_v_push(ir, instruction); | ||||||
|                 break; |                 break; | ||||||
|             case JANET_SYSOP_CONSTANT: { |             case JANET_SYSOP_CONSTANT: { | ||||||
| @@ -626,22 +653,22 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction | |||||||
|             } |             } | ||||||
|             case JANET_SYSOP_TYPE_PRIMITIVE: { |             case JANET_SYSOP_TYPE_PRIMITIVE: { | ||||||
|                 instr_assert_length(tuple, 3, opvalue); |                 instr_assert_length(tuple, 3, opvalue); | ||||||
|                 instruction.type_prim.dest_type = instr_read_type_operand(tuple[1], out); |                 instruction.type_prim.dest_type = instr_read_type_operand(tuple[1], out, 1); | ||||||
|                 instruction.type_prim.prim = instr_read_prim(tuple[2]); |                 instruction.type_prim.prim = instr_read_prim(tuple[2]); | ||||||
|                 janet_v_push(ir, instruction); |                 janet_v_push(ir, instruction); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             case JANET_SYSOP_TYPE_POINTER: { |             case JANET_SYSOP_TYPE_POINTER: { | ||||||
|                 instr_assert_length(tuple, 3, opvalue); |                 instr_assert_length(tuple, 3, opvalue); | ||||||
|                 instruction.pointer.dest_type = instr_read_type_operand(tuple[1], out); |                 instruction.pointer.dest_type = instr_read_type_operand(tuple[1], out, 1); | ||||||
|                 instruction.pointer.type = instr_read_type_operand(tuple[2], out); |                 instruction.pointer.type = instr_read_type_operand(tuple[2], out, 0); | ||||||
|                 janet_v_push(ir, instruction); |                 janet_v_push(ir, instruction); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             case JANET_SYSOP_TYPE_ARRAY: { |             case JANET_SYSOP_TYPE_ARRAY: { | ||||||
|                 instr_assert_length(tuple, 4, opvalue); |                 instr_assert_length(tuple, 4, opvalue); | ||||||
|                 instruction.array.dest_type = instr_read_type_operand(tuple[1], out); |                 instruction.array.dest_type = instr_read_type_operand(tuple[1], out, 1); | ||||||
|                 instruction.array.type = instr_read_type_operand(tuple[2], out); |                 instruction.array.type = instr_read_type_operand(tuple[2], out, 0); | ||||||
|                 instruction.array.fixed_count = instr_read_u64(tuple[3], out); |                 instruction.array.fixed_count = instr_read_u64(tuple[3], out); | ||||||
|                 janet_v_push(ir, instruction); |                 janet_v_push(ir, instruction); | ||||||
|                 break; |                 break; | ||||||
| @@ -649,7 +676,7 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction | |||||||
|             case JANET_SYSOP_TYPE_STRUCT: |             case JANET_SYSOP_TYPE_STRUCT: | ||||||
|             case JANET_SYSOP_TYPE_UNION: { |             case JANET_SYSOP_TYPE_UNION: { | ||||||
|                 instr_assert_min_length(tuple, 1, opvalue); |                 instr_assert_min_length(tuple, 1, opvalue); | ||||||
|                 instruction.type_types.dest_type = instr_read_type_operand(tuple[1], out); |                 instruction.type_types.dest_type = instr_read_type_operand(tuple[1], out, 1); | ||||||
|                 instruction.type_types.arg_count = janet_tuple_length(tuple) - 2; |                 instruction.type_types.arg_count = janet_tuple_length(tuple) - 2; | ||||||
|                 janet_v_push(ir, instruction); |                 janet_v_push(ir, instruction); | ||||||
|                 for (int32_t j = 2; j < janet_tuple_length(tuple); j += 3) { |                 for (int32_t j = 2; j < janet_tuple_length(tuple); j += 3) { | ||||||
| @@ -663,7 +690,7 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction | |||||||
|                     int32_t remaining = janet_tuple_length(tuple) - j; |                     int32_t remaining = janet_tuple_length(tuple) - j; | ||||||
|                     if (remaining > 3) remaining = 3; |                     if (remaining > 3) remaining = 3; | ||||||
|                     for (int32_t k = 0; k < remaining; k++) { |                     for (int32_t k = 0; k < remaining; k++) { | ||||||
|                         arginstr.arg.args[k] = instr_read_type_operand(tuple[j + k], out); |                         arginstr.arg.args[k] = instr_read_type_operand(tuple[j + k], out, 0); | ||||||
|                     } |                     } | ||||||
|                     janet_v_push(ir, arginstr); |                     janet_v_push(ir, arginstr); | ||||||
|                 } |                 } | ||||||
| @@ -672,7 +699,24 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction | |||||||
|             case JANET_SYSOP_TYPE_BIND: { |             case JANET_SYSOP_TYPE_BIND: { | ||||||
|                 instr_assert_length(tuple, 3, opvalue); |                 instr_assert_length(tuple, 3, opvalue); | ||||||
|                 instruction.type_bind.dest = instr_read_operand(tuple[1], out); |                 instruction.type_bind.dest = instr_read_operand(tuple[1], out); | ||||||
|                 instruction.type_bind.type = instr_read_type_operand(tuple[2], out); |                 instruction.type_bind.type = instr_read_type_operand(tuple[2], out, 0); | ||||||
|  |                 janet_v_push(ir, instruction); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             case JANET_SYSOP_LABEL: { | ||||||
|  |                 instr_assert_length(tuple, 2, opvalue); | ||||||
|  |                 Janet x = tuple[1]; | ||||||
|  |                 if (!janet_checktype(x, JANET_KEYWORD)) { | ||||||
|  |                     janet_panicf("expected keyword label, got %v", x); | ||||||
|  |                 } | ||||||
|  |                 instruction.label.id = instr_read_label(out, x); | ||||||
|  |                 Janet label_id = janet_wrap_number(instruction.label.id); | ||||||
|  |                 Janet check_defined = janet_table_get(labels, label_id); | ||||||
|  |                 if (janet_checktype(check_defined, JANET_NIL)) { | ||||||
|  |                     janet_table_put(labels, label_id, janet_wrap_number(janet_v_count(ir))); | ||||||
|  |                 } else { | ||||||
|  |                     janet_panicf("label %v already defined", x); | ||||||
|  |                 } | ||||||
|                 janet_v_push(ir, instruction); |                 janet_v_push(ir, instruction); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
| @@ -705,7 +749,7 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction | |||||||
|     } |     } | ||||||
|     int32_t lasti = ircount - 1; |     int32_t lasti = ircount - 1; | ||||||
|     if ((ir[lasti].opcode != JANET_SYSOP_JUMP) && (ir[lasti].opcode != JANET_SYSOP_RETURN)) { |     if ((ir[lasti].opcode != JANET_SYSOP_JUMP) && (ir[lasti].opcode != JANET_SYSOP_RETURN)) { | ||||||
|         janet_panicf("last instruction must be jump or return, got %v", x); |         janet_panicf("last instruction must be jump or return, got %q", x); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -716,24 +760,6 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction | |||||||
|                      out->register_count, out->parameter_count); |                      out->register_count, out->parameter_count); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Fix up labels */ |  | ||||||
|     for (uint32_t i = 0; i < ircount; i++) { |  | ||||||
|         JanetSysInstruction instruction = out->instructions[i]; |  | ||||||
|         uint32_t label_target; |  | ||||||
|         switch (instruction.opcode) { |  | ||||||
|             default: |  | ||||||
|                 break; |  | ||||||
|             case JANET_SYSOP_BRANCH: |  | ||||||
|                 label_target = instr_read_label(out, instruction.branch.temp_label); |  | ||||||
|                 out->instructions[i].branch.to = label_target; |  | ||||||
|                 break; |  | ||||||
|             case JANET_SYSOP_JUMP: |  | ||||||
|                 label_target = instr_read_label(out, instruction.jump.temp_label); |  | ||||||
|                 out->instructions[i].jump.to = label_target; |  | ||||||
|                 break; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* Build constants */ |     /* Build constants */ | ||||||
|     out->constant_count = next_constant; |     out->constant_count = next_constant; | ||||||
|     out->constants = next_constant ? janet_malloc(sizeof(Janet) * out->constant_count) : NULL; |     out->constants = next_constant ? janet_malloc(sizeof(Janet) * out->constant_count) : NULL; | ||||||
| @@ -986,6 +1012,7 @@ static int tcheck_cast_type(JanetSysIR *sysir, uint32_t td, uint32_t ts) { | |||||||
|             case JANET_PRIM_UNKNOWN: |             case JANET_PRIM_UNKNOWN: | ||||||
|             case JANET_PRIM_ARRAY: |             case JANET_PRIM_ARRAY: | ||||||
|             case JANET_PRIM_POINTER: |             case JANET_PRIM_POINTER: | ||||||
|  |             case JANET_PRIM_VOID: | ||||||
|                 return -1; |                 return -1; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -1069,7 +1096,7 @@ static void tcheck_pointer_math(JanetSysIR *sysir, uint32_t dest, uint32_t lhs, | |||||||
| static JanetString rname(JanetSysIR *sysir, uint32_t regid) { | static JanetString rname(JanetSysIR *sysir, uint32_t regid) { | ||||||
|     JanetString name = sysir->register_names[regid]; |     JanetString name = sysir->register_names[regid]; | ||||||
|     if (NULL == name) { |     if (NULL == name) { | ||||||
|         return janet_formatc("value%u", regid); |         return janet_formatc("value[%u]", regid); | ||||||
|     } |     } | ||||||
|     return name; |     return name; | ||||||
| } | } | ||||||
| @@ -1150,6 +1177,7 @@ static void janet_sysir_type_check(JanetSysIR *sysir) { | |||||||
|                 tcheck_pointer(sysir, sysir->types[instruction.two.dest]); |                 tcheck_pointer(sysir, sysir->types[instruction.two.dest]); | ||||||
|                 break; |                 break; | ||||||
|             case JANET_SYSOP_BRANCH: |             case JANET_SYSOP_BRANCH: | ||||||
|  |             case JANET_SYSOP_BRANCH_NOT: | ||||||
|                 tcheck_boolean(sysir, sysir->types[instruction.branch.cond]); |                 tcheck_boolean(sysir, sysir->types[instruction.branch.cond]); | ||||||
|                 if (instruction.branch.to >= sysir->instruction_count) { |                 if (instruction.branch.to >= sysir->instruction_count) { | ||||||
|                     janet_panicf("label outside of range [0, %u), got %u", sysir->instruction_count, instruction.branch.to); |                     janet_panicf("label outside of range [0, %u), got %u", sysir->instruction_count, instruction.branch.to); | ||||||
| @@ -1201,12 +1229,8 @@ static void janet_sysir_type_check(JanetSysIR *sysir) { | |||||||
|             case JANET_SYSOP_ARG: |             case JANET_SYSOP_ARG: | ||||||
|             case JANET_SYSOP_LINK_NAME: |             case JANET_SYSOP_LINK_NAME: | ||||||
|             case JANET_SYSOP_PARAMETER_COUNT: |             case JANET_SYSOP_PARAMETER_COUNT: | ||||||
|                 break; |  | ||||||
|             case JANET_SYSOP_JUMP: |             case JANET_SYSOP_JUMP: | ||||||
|                 ; |             case JANET_SYSOP_LABEL: | ||||||
|                 if (instruction.jump.to >= sysir->instruction_count) { |  | ||||||
|                     janet_panicf("label outside of range [0, %u), got %u", sysir->instruction_count, instruction.jump.to); |  | ||||||
|                 } |  | ||||||
|                 break; |                 break; | ||||||
|             case JANET_SYSOP_RETURN: { |             case JANET_SYSOP_RETURN: { | ||||||
|                 uint32_t ret_type = sysir->types[instruction.one.src]; |                 uint32_t ret_type = sysir->types[instruction.one.src]; | ||||||
| @@ -1279,10 +1303,8 @@ static void janet_sysir_type_check(JanetSysIR *sysir) { | |||||||
|                 tcheck_pointer(sysir, sysir->types[instruction.two.dest]); |                 tcheck_pointer(sysir, sysir->types[instruction.two.dest]); | ||||||
|                 break; |                 break; | ||||||
|             case JANET_SYSOP_BRANCH: |             case JANET_SYSOP_BRANCH: | ||||||
|  |             case JANET_SYSOP_BRANCH_NOT: | ||||||
|                 tcheck_boolean(sysir, sysir->types[instruction.branch.cond]); |                 tcheck_boolean(sysir, sysir->types[instruction.branch.cond]); | ||||||
|                 if (instruction.branch.to >= sysir->instruction_count) { |  | ||||||
|                     janet_panicf("label outside of range [0, %u), got %u", sysir->instruction_count, instruction.branch.to); |  | ||||||
|                 } |  | ||||||
|                 break; |                 break; | ||||||
|             case JANET_SYSOP_CONSTANT: |             case JANET_SYSOP_CONSTANT: | ||||||
|                 tcheck_constant(sysir, instruction.constant.dest, sysir->constants[instruction.constant.constant]); |                 tcheck_constant(sysir, instruction.constant.dest, sysir->constants[instruction.constant.constant]); | ||||||
| @@ -1388,7 +1410,7 @@ static void emit_binop(JanetSysIR *ir, JanetBuffer *buffer, JanetBuffer *tempbuf | |||||||
|  |  | ||||||
|     /* Add nested for loops for any dimensionality of array */ |     /* Add nested for loops for any dimensionality of array */ | ||||||
|     while (linkage->type_defs[operand_type].prim == JANET_PRIM_ARRAY) { |     while (linkage->type_defs[operand_type].prim == JANET_PRIM_ARRAY) { | ||||||
|         janet_formatb(buffer, "for (size_t _j%u = 0; _j%u < %u; _j%u++) ", |         janet_formatb(buffer, "  for (size_t _j%u = 0; _j%u < %u; _j%u++) ", | ||||||
|                       index_index, index_index, |                       index_index, index_index, | ||||||
|                       linkage->type_defs[operand_type].array.fixed_count, |                       linkage->type_defs[operand_type].array.fixed_count, | ||||||
|                       index_index); |                       index_index); | ||||||
| @@ -1403,14 +1425,14 @@ static void emit_binop(JanetSysIR *ir, JanetBuffer *buffer, JanetBuffer *tempbuf | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (is_pointer) { |     if (is_pointer) { | ||||||
|         janet_formatb(buffer, "*_r%u = *_r%u %s *_r%u;\n", |         janet_formatb(buffer, "  *_r%u = *_r%u %s *_r%u;\n", | ||||||
|                       instruction.three.dest, |                       instruction.three.dest, | ||||||
|                       instruction.three.lhs, |                       instruction.three.lhs, | ||||||
|                       op, |                       op, | ||||||
|                       instruction.three.rhs); |                       instruction.three.rhs); | ||||||
|     } else { |     } else { | ||||||
|         Janet index_part = janet_wrap_buffer(tempbuf); |         Janet index_part = janet_wrap_buffer(tempbuf); | ||||||
|         janet_formatb(buffer, "_r%u%V = _r%u%V %s _r%u%V;\n", |         janet_formatb(buffer, "  _r%u%V = _r%u%V %s _r%u%V;\n", | ||||||
|                       instruction.three.dest, index_part, |                       instruction.three.dest, index_part, | ||||||
|                       instruction.three.lhs, index_part, |                       instruction.three.lhs, index_part, | ||||||
|                       op, |                       op, | ||||||
| @@ -1492,23 +1514,9 @@ void janet_sys_ir_lower_to_c(JanetSysIRLinkage *linkage, JanetBuffer *buffer) { | |||||||
|         /* Emit body */ |         /* Emit body */ | ||||||
|         for (uint32_t i = 0; i < ir->instruction_count; i++) { |         for (uint32_t i = 0; i < ir->instruction_count; i++) { | ||||||
|             JanetSysInstruction instruction = ir->instructions[i]; |             JanetSysInstruction instruction = ir->instructions[i]; | ||||||
|             /* Skip instruction label for some opcodes */ |  | ||||||
|             switch (instruction.opcode) { |  | ||||||
|                 case JANET_SYSOP_TYPE_PRIMITIVE: |  | ||||||
|                 case JANET_SYSOP_TYPE_BIND: |  | ||||||
|                 case JANET_SYSOP_TYPE_STRUCT: |  | ||||||
|                 case JANET_SYSOP_TYPE_UNION: |  | ||||||
|                 case JANET_SYSOP_TYPE_POINTER: |  | ||||||
|                 case JANET_SYSOP_TYPE_ARRAY: |  | ||||||
|                     continue; |  | ||||||
|                 default: |  | ||||||
|                     break; |  | ||||||
|             } |  | ||||||
|             janet_formatb(buffer, "_i%u:\n", i); |  | ||||||
|             if (instruction.line > 0) { |             if (instruction.line > 0) { | ||||||
|                 janet_formatb(buffer, "#line %d\n  ", instruction.line); |                 janet_formatb(buffer, "#line %d\n  ", instruction.line); | ||||||
|             } |             } | ||||||
|             janet_buffer_push_cstring(buffer, "  "); |  | ||||||
|             switch (instruction.opcode) { |             switch (instruction.opcode) { | ||||||
|                 case JANET_SYSOP_TYPE_PRIMITIVE: |                 case JANET_SYSOP_TYPE_PRIMITIVE: | ||||||
|                 case JANET_SYSOP_TYPE_BIND: |                 case JANET_SYSOP_TYPE_BIND: | ||||||
| @@ -1520,22 +1528,29 @@ void janet_sys_ir_lower_to_c(JanetSysIRLinkage *linkage, JanetBuffer *buffer) { | |||||||
|                 case JANET_SYSOP_LINK_NAME: |                 case JANET_SYSOP_LINK_NAME: | ||||||
|                 case JANET_SYSOP_PARAMETER_COUNT: |                 case JANET_SYSOP_PARAMETER_COUNT: | ||||||
|                     break; |                     break; | ||||||
|  |                 case JANET_SYSOP_LABEL: { | ||||||
|  |                     janet_formatb(buffer, "\n_label_%u:\n", instruction.label.id); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|                 case JANET_SYSOP_CONSTANT: { |                 case JANET_SYSOP_CONSTANT: { | ||||||
|                     uint32_t cast = ir->types[instruction.two.dest]; |                     uint32_t cast = ir->types[instruction.two.dest]; | ||||||
|                     janet_formatb(buffer, "_r%u = (_t%u) %j;\n", instruction.two.dest, cast, ir->constants[instruction.two.src]); |                     janet_formatb(buffer, "  _r%u = (_t%u) %j;\n", instruction.two.dest, cast, ir->constants[instruction.two.src]); | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|                 case JANET_SYSOP_ADDRESS: |                 case JANET_SYSOP_ADDRESS: | ||||||
|                     janet_formatb(buffer, "_r%u = (char *) &_r%u;\n", instruction.two.dest, instruction.two.src); |                     janet_formatb(buffer, "  _r%u = (char *) &_r%u;\n", instruction.two.dest, instruction.two.src); | ||||||
|                     break; |                     break; | ||||||
|                 case JANET_SYSOP_JUMP: |                 case JANET_SYSOP_JUMP: | ||||||
|                     janet_formatb(buffer, "goto _i%u;\n", instruction.jump.to); |                     janet_formatb(buffer, "  goto _label_%u;\n", instruction.jump.to); | ||||||
|                     break; |                     break; | ||||||
|                 case JANET_SYSOP_BRANCH: |                 case JANET_SYSOP_BRANCH: | ||||||
|                     janet_formatb(buffer, "if (_r%u) goto _i%u;\n", instruction.branch.cond, instruction.branch.to); |                     janet_formatb(buffer, "  if (_r%u) goto _label_%u;\n", instruction.branch.cond, instruction.branch.to); | ||||||
|  |                     break; | ||||||
|  |                 case JANET_SYSOP_BRANCH_NOT: | ||||||
|  |                     janet_formatb(buffer, "  if (!_r%u) goto _label_%u;\n", instruction.branch.cond, instruction.branch.to); | ||||||
|                     break; |                     break; | ||||||
|                 case JANET_SYSOP_RETURN: |                 case JANET_SYSOP_RETURN: | ||||||
|                     janet_formatb(buffer, "return _r%u;\n", instruction.one.src); |                     janet_formatb(buffer, "  return _r%u;\n", instruction.one.src); | ||||||
|                     break; |                     break; | ||||||
|                 case JANET_SYSOP_ADD: |                 case JANET_SYSOP_ADD: | ||||||
|                 case JANET_SYSOP_POINTER_ADD: |                 case JANET_SYSOP_POINTER_ADD: | ||||||
| @@ -1584,51 +1599,60 @@ void janet_sys_ir_lower_to_c(JanetSysIRLinkage *linkage, JanetBuffer *buffer) { | |||||||
|                 case JANET_SYSOP_SHR: |                 case JANET_SYSOP_SHR: | ||||||
|                     EMITBINOP(">>"); |                     EMITBINOP(">>"); | ||||||
|                     break; |                     break; | ||||||
|                 case JANET_SYSOP_CALL: |                 case JANET_SYSOP_CALL: { | ||||||
|                     janet_formatb(buffer, "_r%u = _r%u(", instruction.call.dest, instruction.call.callee); |                     if (instruction.call.has_dest) { | ||||||
|  |                         janet_formatb(buffer, "  _r%u = _r%u(", instruction.call.dest, instruction.call.callee); | ||||||
|  |                     } else { | ||||||
|  |                         janet_formatb(buffer, "  _r%u(", instruction.call.callee); | ||||||
|  |                     } | ||||||
|                     for (uint32_t j = 0; j < instruction.call.arg_count; j++) { |                     for (uint32_t j = 0; j < instruction.call.arg_count; j++) { | ||||||
|                         uint32_t offset = j / 3 + 1; |                         uint32_t offset = j / 3 + 1; | ||||||
|                         uint32_t index = j % 3; |                         uint32_t index = j % 3; | ||||||
|                         JanetSysInstruction arg_instruction = ir->instructions[i + offset]; |                         JanetSysInstruction arg_instruction = ir->instructions[i + offset]; | ||||||
|                         janet_formatb(buffer, j ? ", _r%u" : "_r%u", arg_instruction.arg.args[index]); |                         janet_formatb(buffer, j ? ", _r%u" : "_r%u", arg_instruction.arg.args[index]); | ||||||
|                     } |                     } | ||||||
|                     janet_formatb(buffer, ");\n"); |                     janet_formatb(buffer, "); // CALL\n"); | ||||||
|                     break; |                     break; | ||||||
|  |                 } | ||||||
|                 case JANET_SYSOP_CALLK: |                 case JANET_SYSOP_CALLK: | ||||||
|                     janet_formatb(buffer, "_r%u = %j(", instruction.callk.dest, ir->constants[instruction.callk.constant]); |                     if (instruction.callk.has_dest) { | ||||||
|  |                         janet_formatb(buffer, "  _r%u = %v(", instruction.callk.dest, ir->constants[instruction.callk.constant]); | ||||||
|  |                     } else { | ||||||
|  |                         janet_formatb(buffer, "  %v(", ir->constants[instruction.callk.constant]); | ||||||
|  |                     } | ||||||
|                     for (uint32_t j = 0; j < instruction.callk.arg_count; j++) { |                     for (uint32_t j = 0; j < instruction.callk.arg_count; j++) { | ||||||
|                         uint32_t offset = j / 3 + 1; |                         uint32_t offset = j / 3 + 1; | ||||||
|                         uint32_t index = j % 3; |                         uint32_t index = j % 3; | ||||||
|                         JanetSysInstruction arg_instruction = ir->instructions[i + offset]; |                         JanetSysInstruction arg_instruction = ir->instructions[i + offset]; | ||||||
|                         janet_formatb(buffer, j ? ", _r%u" : "_r%u", arg_instruction.arg.args[index]); |                         janet_formatb(buffer, j ? ", _r%u" : "_r%u", arg_instruction.arg.args[index]); | ||||||
|                     } |                     } | ||||||
|                     janet_formatb(buffer, ");\n"); |                     janet_formatb(buffer, "); // CALLK\n"); | ||||||
|                     break; |                     break; | ||||||
|                 case JANET_SYSOP_CAST: { |                 case JANET_SYSOP_CAST: { | ||||||
|                     uint32_t to = ir->types[instruction.two.dest]; |                     uint32_t to = ir->types[instruction.two.dest]; | ||||||
|                     janet_formatb(buffer, "_r%u = (_t%u) (_r%u);\n", instruction.two.dest, to, instruction.two.src); |                     janet_formatb(buffer, "  _r%u = (_t%u) (_r%u);\n", instruction.two.dest, to, instruction.two.src); | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|                 case JANET_SYSOP_MOVE: |                 case JANET_SYSOP_MOVE: | ||||||
|                     janet_formatb(buffer, "_r%u = _r%u;\n", instruction.two.dest, instruction.two.src); |                     janet_formatb(buffer, "  _r%u = _r%u;\n", instruction.two.dest, instruction.two.src); | ||||||
|                     break; |                     break; | ||||||
|                 case JANET_SYSOP_BNOT: |                 case JANET_SYSOP_BNOT: | ||||||
|                     janet_formatb(buffer, "_r%u = ~_r%u;\n", instruction.two.dest, instruction.two.src); |                     janet_formatb(buffer, "  _r%u = ~_r%u;\n", instruction.two.dest, instruction.two.src); | ||||||
|                     break; |                     break; | ||||||
|                 case JANET_SYSOP_LOAD: |                 case JANET_SYSOP_LOAD: | ||||||
|                     janet_formatb(buffer, "_r%u = *(_r%u);\n", instruction.two.dest, instruction.two.src); |                     janet_formatb(buffer, "  _r%u = *(_r%u);\n", instruction.two.dest, instruction.two.src); | ||||||
|                     break; |                     break; | ||||||
|                 case JANET_SYSOP_STORE: |                 case JANET_SYSOP_STORE: | ||||||
|                     janet_formatb(buffer, "*(_r%u) = _r%u;\n", instruction.two.dest, instruction.two.src); |                     janet_formatb(buffer, "  *(_r%u) = _r%u;\n", instruction.two.dest, instruction.two.src); | ||||||
|                     break; |                     break; | ||||||
|                 case JANET_SYSOP_FIELD_GETP: |                 case JANET_SYSOP_FIELD_GETP: | ||||||
|                     janet_formatb(buffer, "_r%u = &(_r%u._f%u);\n", instruction.field.r, instruction.field.st, instruction.field.field); |                     janet_formatb(buffer, "  _r%u = &(_r%u._f%u);\n", instruction.field.r, instruction.field.st, instruction.field.field); | ||||||
|                     break; |                     break; | ||||||
|                 case JANET_SYSOP_ARRAY_GETP: |                 case JANET_SYSOP_ARRAY_GETP: | ||||||
|                     janet_formatb(buffer, "_r%u = &(_r%u.els[_r%u]);\n", instruction.three.dest, instruction.three.lhs, instruction.three.rhs); |                     janet_formatb(buffer, "  _r%u = &(_r%u.els[_r%u]);\n", instruction.three.dest, instruction.three.lhs, instruction.three.rhs); | ||||||
|                     break; |                     break; | ||||||
|                 case JANET_SYSOP_ARRAY_PGETP: |                 case JANET_SYSOP_ARRAY_PGETP: | ||||||
|                     janet_formatb(buffer, "_r%u = &(_r%u->els[_r%u]);\n", instruction.three.dest, instruction.three.lhs, instruction.three.rhs); |                     janet_formatb(buffer, "  _r%u = &(_r%u->els[_r%u]);\n", instruction.three.dest, instruction.three.lhs, instruction.three.rhs); | ||||||
|                     break; |                     break; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose