1
0
mirror of https://github.com/janet-lang/janet synced 2024-09-30 16:00:40 +00:00

Update sysir to have better field support.

This commit is contained in:
Calvin Rose 2023-08-06 20:00:49 -05:00
parent 7c7136fd70
commit 75be5fd4c6
3 changed files with 92 additions and 38 deletions

View File

@ -10,12 +10,15 @@
(bind 3 1)
(bind 4 1)
(bind 5 1)
(bind 6 2)
(constant 0 10)
(constant 0 21)
(add 2 1 0)
(constant 3 1.77)
(call 3 sin 3)
(cast 4 2)
(fset 2 6 0)
(fset 3 6 1)
(add 5 4 3)
(return 5))
:parameter-count 0

View File

@ -23,12 +23,12 @@
/* TODO
* [ ] pointer math, pointer types
* [x] callk - allow linking to other named functions
* [ ] composite types - support for load, store, move, and function args.
* [ ] 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] composite types - support for load, store, move, and function args.
* [x] Have some mechanism for field access (dest = src.offset)
* [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
* [ ] 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
*/
@ -36,6 +36,7 @@
#include "features.h"
#include <janet.h>
#include "util.h"
#include "vector.h"
#include <math.h>
#endif
@ -69,6 +70,7 @@ static const JanetPrimName prim_names[] = {
{"s32", JANET_PRIM_S32},
{"s64", JANET_PRIM_S64},
{"s8", JANET_PRIM_S8},
{"struct", JANET_PRIM_STRUCT},
{"u16", JANET_PRIM_U16},
{"u32", JANET_PRIM_U32},
{"u64", JANET_PRIM_U64},
@ -153,8 +155,13 @@ static const JanetSysInstrName sys_op_names[] = {
typedef struct {
JanetPrim prim;
uint32_t field_count;
uint32_t field_start;
} JanetSysTypeInfo;
typedef struct {
uint32_t type;
} JanetSysTypeField;
typedef struct {
JanetSysOp opcode;
union {
@ -206,6 +213,11 @@ typedef struct {
struct {
uint32_t args[3];
} arg;
struct {
uint32_t r;
uint32_t st;
uint32_t field;
} field;
};
int32_t line;
int32_t column;
@ -216,10 +228,12 @@ typedef struct {
uint32_t instruction_count;
uint32_t register_count;
uint32_t type_def_count;
uint32_t field_def_count;
uint32_t constant_count;
uint32_t return_type;
uint32_t *types;
JanetSysTypeInfo *type_defs;
JanetSysTypeField *field_defs;
JanetSysInstruction *instructions;
Janet *constants;
uint32_t parameter_count;
@ -248,6 +262,13 @@ static uint32_t instr_read_operand(Janet x, JanetSysIR *ir) {
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) {
if (!janet_checkuint(x)) janet_panicf("expected non-negative integer operand, got %v", 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);
ir[cursor++] = instruction;
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:
instr_assert_length(tuple, 2, opvalue);
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 */
static void janet_sysir_init_types(JanetSysIR *sysir) {
JanetSysTypeField *fields = NULL;
if (sysir->type_def_count == 0) {
sysir->type_def_count++;
}
@ -494,6 +523,7 @@ static void janet_sysir_init_types(JanetSysIR *sysir) {
sysir->types = types;
sysir->type_defs[0].field_count = 0;
sysir->type_defs[0].prim = JANET_PRIM_S32;
_i4:
for (uint32_t i = 0; i < sysir->register_count; i++) {
sysir->types[i] = 0;
}
@ -511,8 +541,18 @@ static void janet_sysir_init_types(JanetSysIR *sysir) {
}
case JANET_SYSOP_TYPE_STRUCT: {
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].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;
}
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 */
static void tcheck_boolean(JanetSysIR *sysir, uint32_t 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 */
}
}
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 &&
t1 != JANET_PRIM_S64 &&
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) {
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);
}
}
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) {
uint32_t t1 = sysir->types[reg1];
uint32_t t2 = sysir->types[reg2];
@ -643,6 +692,20 @@ static void janet_sysir_type_check(JanetSysIR *sysir) {
case JANET_SYSOP_CALL:
tcheck_pointer(sysir, instruction.call.callee);
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:
/* TODO - check function return type */
break;
@ -654,10 +717,12 @@ void janet_sys_ir_init_from_table(JanetSysIR *ir, JanetTable *table) {
ir->instructions = NULL;
ir->types = NULL;
ir->type_defs = NULL;
ir->field_defs = NULL;
ir->constants = NULL;
ir->link_name = NULL;
ir->register_count = 0;
ir->type_def_count = 0;
ir->field_def_count = 0;
ir->constant_count = 0;
ir->return_type = 0;
ir->parameter_count = 0;
@ -696,7 +761,7 @@ void janet_sys_ir_lower_to_c(JanetSysIR *ir, JanetBuffer *buffer) {
#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, "#include <stdint.h>\n\n");
janet_formatb(buffer, "#include <stdint.h>\n#include <tgmath.h>\n\n");
/* Emit type defs */
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:
break;
}
janet_formatb(buffer, "_i%u:\n ", i);
janet_formatb(buffer, "_i%u:\n", i);
if (instruction.line > 0) {
janet_formatb(buffer, "#line %d\n ", instruction.line);
}
janet_buffer_push_cstring(buffer, " ");
switch (instruction.opcode) {
case JANET_SYSOP_TYPE_PRIMITIVE:
case JANET_SYSOP_TYPE_BIND:
@ -848,7 +914,8 @@ void janet_sys_ir_lower_to_c(JanetSysIR *ir, JanetBuffer *buffer) {
janet_formatb(buffer, ");\n");
break;
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;
case JANET_SYSOP_MOVE:
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);
break;
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;
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;
}
}
@ -876,6 +949,8 @@ static int sysir_gc(void *p, size_t s) {
janet_free(ir->constants);
janet_free(ir->types);
janet_free(ir->instructions);
janet_free(ir->type_defs);
janet_free(ir->field_defs);
return 0;
}

24
temp.c
View File

@ -1,24 +0,0 @@
#include <stdint.h>
#line 3
typedef int32_t _t0;
_t0 main()
{
_t0 _r0;
_t0 _r1;
_t0 _r2;
_i4:
#line 7
_r0 = (_t0) 10;
_i5:
#line 8
_r1 = (_t0) 20;
_i6:
#line 9
_r2 = _r1 + _r0;
_i7:
#line 10
return _r2;
}