mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 07:33:01 +00:00 
			
		
		
		
	Update sysir to have better field support.
This commit is contained in:
		| @@ -10,12 +10,15 @@ | |||||||
|      (bind 3 1) |      (bind 3 1) | ||||||
|      (bind 4 1) |      (bind 4 1) | ||||||
|      (bind 5 1) |      (bind 5 1) | ||||||
|  |      (bind 6 2) | ||||||
|      (constant 0 10) |      (constant 0 10) | ||||||
|      (constant 0 21) |      (constant 0 21) | ||||||
|      (add 2 1 0) |      (add 2 1 0) | ||||||
|      (constant 3 1.77) |      (constant 3 1.77) | ||||||
|      (call 3 sin 3) |      (call 3 sin 3) | ||||||
|      (cast 4 2) |      (cast 4 2) | ||||||
|  |      (fset 2 6 0) | ||||||
|  |      (fset 3 6 1) | ||||||
|      (add 5 4 3) |      (add 5 4 3) | ||||||
|      (return 5)) |      (return 5)) | ||||||
|    :parameter-count 0 |    :parameter-count 0 | ||||||
|   | |||||||
							
								
								
									
										103
									
								
								src/core/sysir.c
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								src/core/sysir.c
									
									
									
									
									
								
							| @@ -23,12 +23,12 @@ | |||||||
| /* TODO | /* TODO | ||||||
|  * [ ] pointer math, pointer types |  * [ ] pointer math, pointer types | ||||||
|  * [x] callk - allow linking to other named functions |  * [x] callk - allow linking to other named functions | ||||||
|  * [ ] composite types - support for load, store, move, and function args. |  * [x] composite types - support for load, store, move, and function args. | ||||||
|  * [ ] Have some mechanism for field access (dest = src.offset) |  * [x] Have some mechanism for field access (dest = src.offset) | ||||||
|  * [ ] Related, move type creation as opcodes like in SPIRV - have separate virtual "type slots" and value slots for this. |  * [x] Related, move type creation as opcodes like in SPIRV - have separate virtual "type slots" and value slots for this. | ||||||
|  * [ ] support for stack allocation of arrays |  * [ ] support for stack allocation of arrays | ||||||
|  * [ ] more math intrinsics |  * [ ] more math intrinsics | ||||||
|  * [ ] source mapping (using built in Janet source mapping metadata on tuples) |  * [x] source mapping (using built in Janet source mapping metadata on tuples) | ||||||
|  * [ ] better C interface for building up IR |  * [ ] better C interface for building up IR | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| @@ -36,6 +36,7 @@ | |||||||
| #include "features.h" | #include "features.h" | ||||||
| #include <janet.h> | #include <janet.h> | ||||||
| #include "util.h" | #include "util.h" | ||||||
|  | #include "vector.h" | ||||||
| #include <math.h> | #include <math.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -69,6 +70,7 @@ static const JanetPrimName prim_names[] = { | |||||||
|     {"s32", JANET_PRIM_S32}, |     {"s32", JANET_PRIM_S32}, | ||||||
|     {"s64", JANET_PRIM_S64}, |     {"s64", JANET_PRIM_S64}, | ||||||
|     {"s8", JANET_PRIM_S8}, |     {"s8", JANET_PRIM_S8}, | ||||||
|  |     {"struct", JANET_PRIM_STRUCT}, | ||||||
|     {"u16", JANET_PRIM_U16}, |     {"u16", JANET_PRIM_U16}, | ||||||
|     {"u32", JANET_PRIM_U32}, |     {"u32", JANET_PRIM_U32}, | ||||||
|     {"u64", JANET_PRIM_U64}, |     {"u64", JANET_PRIM_U64}, | ||||||
| @@ -153,8 +155,13 @@ static const JanetSysInstrName sys_op_names[] = { | |||||||
| typedef struct { | typedef struct { | ||||||
|     JanetPrim prim; |     JanetPrim prim; | ||||||
|     uint32_t field_count; |     uint32_t field_count; | ||||||
|  |     uint32_t field_start; | ||||||
| } JanetSysTypeInfo; | } JanetSysTypeInfo; | ||||||
|  |  | ||||||
|  | typedef struct { | ||||||
|  |     uint32_t type; | ||||||
|  | } JanetSysTypeField; | ||||||
|  |  | ||||||
| typedef struct { | typedef struct { | ||||||
|     JanetSysOp opcode; |     JanetSysOp opcode; | ||||||
|     union { |     union { | ||||||
| @@ -206,6 +213,11 @@ typedef struct { | |||||||
|         struct { |         struct { | ||||||
|             uint32_t args[3]; |             uint32_t args[3]; | ||||||
|         } arg; |         } arg; | ||||||
|  |         struct { | ||||||
|  |             uint32_t r; | ||||||
|  |             uint32_t st; | ||||||
|  |             uint32_t field; | ||||||
|  |         } field; | ||||||
|     }; |     }; | ||||||
|     int32_t line; |     int32_t line; | ||||||
|     int32_t column; |     int32_t column; | ||||||
| @@ -216,10 +228,12 @@ typedef struct { | |||||||
|     uint32_t instruction_count; |     uint32_t instruction_count; | ||||||
|     uint32_t register_count; |     uint32_t register_count; | ||||||
|     uint32_t type_def_count; |     uint32_t type_def_count; | ||||||
|  |     uint32_t field_def_count; | ||||||
|     uint32_t constant_count; |     uint32_t constant_count; | ||||||
|     uint32_t return_type; |     uint32_t return_type; | ||||||
|     uint32_t *types; |     uint32_t *types; | ||||||
|     JanetSysTypeInfo *type_defs; |     JanetSysTypeInfo *type_defs; | ||||||
|  |     JanetSysTypeField *field_defs; | ||||||
|     JanetSysInstruction *instructions; |     JanetSysInstruction *instructions; | ||||||
|     Janet *constants; |     Janet *constants; | ||||||
|     uint32_t parameter_count; |     uint32_t parameter_count; | ||||||
| @@ -248,6 +262,13 @@ static uint32_t instr_read_operand(Janet x, JanetSysIR *ir) { | |||||||
|     return operand; |     return operand; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static uint32_t instr_read_field(Janet x, JanetSysIR *ir) { | ||||||
|  |     if (!janet_checkuint(x)) janet_panicf("expected non-negative field index, got %v", x); | ||||||
|  |     (void) ir; /* Perhaps support syntax for named fields instead of numbered */ | ||||||
|  |     uint32_t operand = (uint32_t) janet_unwrap_number(x); | ||||||
|  |     return operand; | ||||||
|  | } | ||||||
|  |  | ||||||
| static uint32_t instr_read_type_operand(Janet x, JanetSysIR *ir) { | static uint32_t instr_read_type_operand(Janet x, JanetSysIR *ir) { | ||||||
|     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); | ||||||
|     uint32_t operand = (uint32_t) janet_unwrap_number(x); |     uint32_t operand = (uint32_t) janet_unwrap_number(x); | ||||||
| @@ -390,6 +411,14 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction | |||||||
|                 instruction.two.src = instr_read_operand(tuple[2], out); |                 instruction.two.src = instr_read_operand(tuple[2], out); | ||||||
|                 ir[cursor++] = instruction; |                 ir[cursor++] = instruction; | ||||||
|                 break; |                 break; | ||||||
|  |             case JANET_SYSOP_FIELD_GET: | ||||||
|  |             case JANET_SYSOP_FIELD_SET: | ||||||
|  |                 instr_assert_length(tuple, 4, opvalue); | ||||||
|  |                 instruction.field.r = instr_read_operand(tuple[1], out); | ||||||
|  |                 instruction.field.st = instr_read_operand(tuple[2], out); | ||||||
|  |                 instruction.field.field = instr_read_field(tuple[3], out); | ||||||
|  |                 ir[cursor++] = instruction; | ||||||
|  |                 break; | ||||||
|             case JANET_SYSOP_RETURN: |             case JANET_SYSOP_RETURN: | ||||||
|                 instr_assert_length(tuple, 2, opvalue); |                 instr_assert_length(tuple, 2, opvalue); | ||||||
|                 instruction.one.src = instr_read_operand(tuple[1], out); |                 instruction.one.src = instr_read_operand(tuple[1], out); | ||||||
| @@ -483,8 +512,8 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction | |||||||
| } | } | ||||||
|  |  | ||||||
| /* Build up type tables */ | /* Build up type tables */ | ||||||
|  |  | ||||||
| static void janet_sysir_init_types(JanetSysIR *sysir) { | static void janet_sysir_init_types(JanetSysIR *sysir) { | ||||||
|  |     JanetSysTypeField *fields = NULL; | ||||||
|     if (sysir->type_def_count == 0) { |     if (sysir->type_def_count == 0) { | ||||||
|         sysir->type_def_count++; |         sysir->type_def_count++; | ||||||
|     } |     } | ||||||
| @@ -494,6 +523,7 @@ static void janet_sysir_init_types(JanetSysIR *sysir) { | |||||||
|     sysir->types = types; |     sysir->types = types; | ||||||
|     sysir->type_defs[0].field_count = 0; |     sysir->type_defs[0].field_count = 0; | ||||||
|     sysir->type_defs[0].prim = JANET_PRIM_S32; |     sysir->type_defs[0].prim = JANET_PRIM_S32; | ||||||
|  | _i4: | ||||||
|     for (uint32_t i = 0; i < sysir->register_count; i++) { |     for (uint32_t i = 0; i < sysir->register_count; i++) { | ||||||
|         sysir->types[i] = 0; |         sysir->types[i] = 0; | ||||||
|     } |     } | ||||||
| @@ -511,8 +541,18 @@ static void janet_sysir_init_types(JanetSysIR *sysir) { | |||||||
|             } |             } | ||||||
|             case JANET_SYSOP_TYPE_STRUCT: { |             case JANET_SYSOP_TYPE_STRUCT: { | ||||||
|                 uint32_t type_def = instruction.type_types.dest_type; |                 uint32_t type_def = instruction.type_types.dest_type; | ||||||
|                 type_defs[type_def].field_count = 0; /* TODO */ |                 type_defs[type_def].field_count = instruction.type_types.arg_count; | ||||||
|                 type_defs[type_def].prim = JANET_PRIM_STRUCT; |                 type_defs[type_def].prim = JANET_PRIM_STRUCT; | ||||||
|  |                 type_defs[type_def].field_start = (uint32_t) janet_v_count(fields); | ||||||
|  |                 for (uint32_t j = 0; j < instruction.type_types.arg_count; j++) { | ||||||
|  |                     uint32_t offset = j / 3 + 1; | ||||||
|  |                     uint32_t index = j % 3; | ||||||
|  |                     JanetSysInstruction arg_instruction = sysir->instructions[i + offset]; | ||||||
|  |                     uint32_t arg = arg_instruction.arg.args[index]; | ||||||
|  |                     JanetSysTypeField field; | ||||||
|  |                     field.type = arg; | ||||||
|  |                     janet_v_push(fields, field); | ||||||
|  |                 } | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             case JANET_SYSOP_TYPE_BIND: { |             case JANET_SYSOP_TYPE_BIND: { | ||||||
| @@ -523,19 +563,21 @@ static void janet_sysir_init_types(JanetSysIR *sysir) { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     sysir->field_defs = janet_v_flatten(fields); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Type checking */ | /* Type checking */ | ||||||
|  |  | ||||||
| static void tcheck_boolean(JanetSysIR *sysir, uint32_t reg1) { | static void tcheck_boolean(JanetSysIR *sysir, uint32_t reg1) { | ||||||
|     uint32_t t1 = sysir->types[reg1]; |     uint32_t t1 = sysir->types[reg1]; | ||||||
|     if (t1 != JANET_PRIM_BOOLEAN) { |     if (sysir->type_defs[t1].prim != JANET_PRIM_BOOLEAN) { | ||||||
|         janet_panicf("type failure, expected boolean, got type-id:%d", t1); /* TODO improve this */ |         janet_panicf("type failure, expected boolean, got type-id:%d", t1); /* TODO improve this */ | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static void tcheck_integer(JanetSysIR *sysir, uint32_t reg1) { | static void tcheck_integer(JanetSysIR *sysir, uint32_t reg1) { | ||||||
|     uint32_t t1 = sysir->types[reg1]; |     JanetPrim t1 = sysir->type_defs[sysir->types[reg1]].prim; | ||||||
|     if (t1 != JANET_PRIM_S32 && |     if (t1 != JANET_PRIM_S32 && | ||||||
|         t1 != JANET_PRIM_S64 && |         t1 != JANET_PRIM_S64 && | ||||||
|         t1 != JANET_PRIM_S16 && |         t1 != JANET_PRIM_S16 && | ||||||
| @@ -550,11 +592,18 @@ static void tcheck_integer(JanetSysIR *sysir, uint32_t reg1) { | |||||||
|  |  | ||||||
| static void tcheck_pointer(JanetSysIR *sysir, uint32_t reg1) { | static void tcheck_pointer(JanetSysIR *sysir, uint32_t reg1) { | ||||||
|     uint32_t t1 = sysir->types[reg1]; |     uint32_t t1 = sysir->types[reg1]; | ||||||
|     if (t1 != JANET_PRIM_POINTER) { |     if (sysir->type_defs[t1].prim != JANET_PRIM_POINTER) { | ||||||
|         janet_panicf("type failure, expected pointer, got type-id:%d", t1); |         janet_panicf("type failure, expected pointer, got type-id:%d", t1); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void tcheck_struct(JanetSysIR *sysir, uint32_t reg1) { | ||||||
|  |     uint32_t t1 = sysir->types[reg1]; | ||||||
|  |     if (sysir->type_defs[t1].prim != JANET_PRIM_STRUCT) { | ||||||
|  |         janet_panicf("type failure, expected struct, got type-id:%d", t1); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| static void tcheck_equal(JanetSysIR *sysir, uint32_t reg1, uint32_t reg2) { | static void tcheck_equal(JanetSysIR *sysir, uint32_t reg1, uint32_t reg2) { | ||||||
|     uint32_t t1 = sysir->types[reg1]; |     uint32_t t1 = sysir->types[reg1]; | ||||||
|     uint32_t t2 = sysir->types[reg2]; |     uint32_t t2 = sysir->types[reg2]; | ||||||
| @@ -643,6 +692,20 @@ static void janet_sysir_type_check(JanetSysIR *sysir) { | |||||||
|             case JANET_SYSOP_CALL: |             case JANET_SYSOP_CALL: | ||||||
|                 tcheck_pointer(sysir, instruction.call.callee); |                 tcheck_pointer(sysir, instruction.call.callee); | ||||||
|                 break; |                 break; | ||||||
|  |             case JANET_SYSOP_FIELD_GET: | ||||||
|  |             case JANET_SYSOP_FIELD_SET: | ||||||
|  |                 tcheck_struct(sysir, instruction.field.st); | ||||||
|  |                 uint32_t struct_type = sysir->types[instruction.field.st]; | ||||||
|  |                 if (instruction.field.field >= sysir->type_defs[struct_type].field_count) { | ||||||
|  |                     janet_panicf("invalid field index %u", instruction.field.field); | ||||||
|  |                 } | ||||||
|  |                 uint32_t field_type = sysir->type_defs[struct_type].field_start + instruction.field.field; | ||||||
|  |                 uint32_t tfield = sysir->field_defs[field_type].type; | ||||||
|  |                 uint32_t tdest = sysir->types[instruction.field.r]; | ||||||
|  |                 if (tfield != tdest) { | ||||||
|  |                     janet_panicf("field of type type-id:%d does not match type-id:%d", tfield, tdest); | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|             case JANET_SYSOP_CALLK: |             case JANET_SYSOP_CALLK: | ||||||
|                 /* TODO - check function return type */ |                 /* TODO - check function return type */ | ||||||
|                 break; |                 break; | ||||||
| @@ -654,10 +717,12 @@ void janet_sys_ir_init_from_table(JanetSysIR *ir, JanetTable *table) { | |||||||
|     ir->instructions = NULL; |     ir->instructions = NULL; | ||||||
|     ir->types = NULL; |     ir->types = NULL; | ||||||
|     ir->type_defs = NULL; |     ir->type_defs = NULL; | ||||||
|  |     ir->field_defs = NULL; | ||||||
|     ir->constants = NULL; |     ir->constants = NULL; | ||||||
|     ir->link_name = NULL; |     ir->link_name = NULL; | ||||||
|     ir->register_count = 0; |     ir->register_count = 0; | ||||||
|     ir->type_def_count = 0; |     ir->type_def_count = 0; | ||||||
|  |     ir->field_def_count = 0; | ||||||
|     ir->constant_count = 0; |     ir->constant_count = 0; | ||||||
|     ir->return_type = 0; |     ir->return_type = 0; | ||||||
|     ir->parameter_count = 0; |     ir->parameter_count = 0; | ||||||
| @@ -696,7 +761,7 @@ void janet_sys_ir_lower_to_c(JanetSysIR *ir, JanetBuffer *buffer) { | |||||||
| #define EMITBINOP(OP) \ | #define EMITBINOP(OP) \ | ||||||
|     janet_formatb(buffer, "_r%u = _r%u " OP " _r%u;\n", instruction.three.dest, instruction.three.lhs, instruction.three.rhs) |     janet_formatb(buffer, "_r%u = _r%u " OP " _r%u;\n", instruction.three.dest, instruction.three.lhs, instruction.three.rhs) | ||||||
|  |  | ||||||
|     janet_formatb(buffer, "#include <stdint.h>\n\n"); |     janet_formatb(buffer, "#include <stdint.h>\n#include <tgmath.h>\n\n"); | ||||||
|  |  | ||||||
|     /* Emit type defs */ |     /* Emit type defs */ | ||||||
|     for (uint32_t i = 0; i < ir->instruction_count; i++) { |     for (uint32_t i = 0; i < ir->instruction_count; i++) { | ||||||
| @@ -755,10 +820,11 @@ void janet_sys_ir_lower_to_c(JanetSysIR *ir, JanetBuffer *buffer) { | |||||||
|             default: |             default: | ||||||
|                 break; |                 break; | ||||||
|         } |         } | ||||||
|         janet_formatb(buffer, "_i%u:\n  ", i); |         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: | ||||||
| @@ -848,7 +914,8 @@ void janet_sys_ir_lower_to_c(JanetSysIR *ir, JanetBuffer *buffer) { | |||||||
|                 janet_formatb(buffer, ");\n"); |                 janet_formatb(buffer, ");\n"); | ||||||
|                 break; |                 break; | ||||||
|             case JANET_SYSOP_CAST: |             case JANET_SYSOP_CAST: | ||||||
|                 janet_formatb(buffer, "_r%u = _r%u;\n", instruction.two.dest, instruction.two.src); |                 /* TODO - making casting rules explicit instead of just from C */ | ||||||
|  |                 janet_formatb(buffer, "_r%u = (_t%u) _r%u;\n", instruction.two.dest, ir->types[instruction.two.dest], 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); | ||||||
| @@ -857,10 +924,16 @@ void janet_sys_ir_lower_to_c(JanetSysIR *ir, JanetBuffer *buffer) { | |||||||
|                 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 = *((%s *) _r%u)", instruction.two.dest, c_prim_names[ir->types[instruction.two.dest]], instruction.two.src); |                 janet_formatb(buffer, "_r%u = *((%s *) _r%u);\n", instruction.two.dest, c_prim_names[ir->types[instruction.two.dest]], instruction.two.src); | ||||||
|                 break; |                 break; | ||||||
|             case JANET_SYSOP_STORE: |             case JANET_SYSOP_STORE: | ||||||
|                 janet_formatb(buffer, "*((%s *) _r%u) = _r%u", c_prim_names[ir->types[instruction.two.src]], instruction.two.dest, instruction.two.src); |                 janet_formatb(buffer, "*((%s *) _r%u) = _r%u;\n", c_prim_names[ir->types[instruction.two.src]], instruction.two.dest, instruction.two.src); | ||||||
|  |                 break; | ||||||
|  |             case JANET_SYSOP_FIELD_GET: | ||||||
|  |                 janet_formatb(buffer, "_r%u = _r%u._f%u;\n", instruction.field.r, instruction.field.st, instruction.field.field); | ||||||
|  |                 break; | ||||||
|  |             case JANET_SYSOP_FIELD_SET: | ||||||
|  |                 janet_formatb(buffer, "_r%u._f%u = _r%u;\n", instruction.field.st, instruction.field.field, instruction.field.r); | ||||||
|                 break; |                 break; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -876,6 +949,8 @@ static int sysir_gc(void *p, size_t s) { | |||||||
|     janet_free(ir->constants); |     janet_free(ir->constants); | ||||||
|     janet_free(ir->types); |     janet_free(ir->types); | ||||||
|     janet_free(ir->instructions); |     janet_free(ir->instructions); | ||||||
|  |     janet_free(ir->type_defs); | ||||||
|  |     janet_free(ir->field_defs); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose