1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-05 16:26:17 +00:00

Add labels back to sysir

This commit is contained in:
Calvin Rose 2023-08-07 09:10:15 -05:00
parent 75be5fd4c6
commit 3fe4cfd14c
2 changed files with 171 additions and 53 deletions

View File

@ -3,7 +3,7 @@
'((prim 0 s32) '((prim 0 s32)
(prim 1 f64) (prim 1 f64)
(struct 2 0 1) (struct 2 0 1)
(struct 3) (pointer 3 0)
(bind 0 0) (bind 0 0)
(bind 1 0) (bind 1 0)
(bind 2 0) (bind 2 0)
@ -13,6 +13,7 @@
(bind 6 2) (bind 6 2)
(constant 0 10) (constant 0 10)
(constant 0 21) (constant 0 21)
:location
(add 2 1 0) (add 2 1 0)
(constant 3 1.77) (constant 3 1.77)
(call 3 sin 3) (call 3 sin 3)
@ -20,9 +21,10 @@
(fset 2 6 0) (fset 2 6 0)
(fset 3 6 1) (fset 3 6 1)
(add 5 4 3) (add 5 4 3)
(jump :location)
(return 5)) (return 5))
:parameter-count 0 :parameter-count 0
:link-name "main"}) :link-name "test_function"})
(def as (sysir/asm ir-asm)) (def as (sysir/asm ir-asm))
(print (sysir/to-c as)) (print (sysir/to-c as))

View File

@ -111,6 +111,7 @@ typedef enum {
JANET_SYSOP_ARG, JANET_SYSOP_ARG,
JANET_SYSOP_FIELD_GET, JANET_SYSOP_FIELD_GET,
JANET_SYSOP_FIELD_SET, JANET_SYSOP_FIELD_SET,
JANET_SYSOP_TYPE_POINTER
} JanetSysOp; } JanetSysOp;
typedef struct { typedef struct {
@ -143,6 +144,7 @@ static const JanetSysInstrName sys_op_names[] = {
{"move", JANET_SYSOP_MOVE}, {"move", JANET_SYSOP_MOVE},
{"multiply", JANET_SYSOP_MULTIPLY}, {"multiply", JANET_SYSOP_MULTIPLY},
{"neq", JANET_SYSOP_NEQ}, {"neq", JANET_SYSOP_NEQ},
{"pointer", JANET_SYSOP_TYPE_POINTER},
{"prim", JANET_SYSOP_TYPE_PRIMITIVE}, {"prim", JANET_SYSOP_TYPE_PRIMITIVE},
{"return", JANET_SYSOP_RETURN}, {"return", JANET_SYSOP_RETURN},
{"shl", JANET_SYSOP_SHL}, {"shl", JANET_SYSOP_SHL},
@ -154,8 +156,15 @@ static const JanetSysInstrName sys_op_names[] = {
typedef struct { typedef struct {
JanetPrim prim; JanetPrim prim;
uint32_t field_count; union {
uint32_t field_start; struct {
uint32_t field_count;
uint32_t field_start;
} st;
struct {
uint32_t type;
} pointer;
};
} JanetSysTypeInfo; } JanetSysTypeInfo;
typedef struct { typedef struct {
@ -183,11 +192,17 @@ typedef struct {
uint32_t src; uint32_t src;
} one; } one;
struct { struct {
uint32_t to; union {
uint32_t to;
Janet temp_label;
};
} jump; } jump;
struct { struct {
uint32_t cond; uint32_t cond;
uint32_t to; union {
uint32_t to;
Janet temp_label;
};
} branch; } branch;
struct { struct {
uint32_t dest; uint32_t dest;
@ -218,6 +233,10 @@ typedef struct {
uint32_t st; uint32_t st;
uint32_t field; uint32_t field;
} field; } field;
struct {
uint32_t dest_type;
uint32_t type;
} pointer;
}; };
int32_t line; int32_t line;
int32_t column; int32_t column;
@ -291,20 +310,30 @@ static JanetPrim instr_read_prim(Janet x) {
return namedata->prim; return namedata->prim;
} }
static uint32_t instr_read_label(Janet x, JanetTable *labels) { static uint32_t instr_read_label(JanetSysIR *sysir, Janet x, JanetTable *labels) {
uint32_t ret = 0;
Janet check = janet_table_get(labels, x); Janet check = janet_table_get(labels, x);
if (!janet_checktype(check, JANET_NIL)) return (uint32_t) janet_unwrap_number(check); if (!janet_checktype(check, JANET_NIL)) {
if (!janet_checkuint(x)) janet_panicf("expected non-negative integer label, got %v", x); ret = (uint32_t) janet_unwrap_number(check);
return (uint32_t) janet_unwrap_number(x); } else {
if (janet_checktype(x, JANET_KEYWORD)) janet_panicf("unknown label %v", x);
if (!janet_checkuint(x)) janet_panicf("expected non-negative integer label, got %v", x);
ret = (uint32_t) janet_unwrap_number(x);
}
if (ret >= sysir->instruction_count) {
janet_panicf("label outside of range [0, %u), got %u", sysir->instruction_count, ret);
}
return ret;
} }
typedef struct {
uint32_t instr;
Janet label;
} LabelTarget;
static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instructions) { static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instructions) {
// TODO - add labels back JanetSysInstruction *ir = NULL;
JanetSysInstruction *ir = janet_malloc(sizeof(JanetSysInstruction) * 100);
out->instructions = ir;
uint32_t cursor = 0;
JanetTable *labels = janet_table(0); JanetTable *labels = janet_table(0);
JanetTable *constant_cache = janet_table(0); JanetTable *constant_cache = janet_table(0);
uint32_t next_constant = 0; uint32_t next_constant = 0;
@ -313,7 +342,10 @@ 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];
if (janet_checktype(x, JANET_KEYWORD)) continue; if (janet_checktype(x, JANET_KEYWORD)) {
janet_table_put(labels, x, janet_wrap_number(janet_v_count(ir)));
continue;
}
if (!janet_checktype(x, JANET_TUPLE)) { if (!janet_checktype(x, JANET_TUPLE)) {
janet_panicf("expected instruction to be tuple, got %V", x); janet_panicf("expected instruction to be tuple, got %V", x);
} }
@ -341,7 +373,7 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction
switch (opcode) { switch (opcode) {
case JANET_SYSOP_CALLK: case JANET_SYSOP_CALLK:
case JANET_SYSOP_ARG: case JANET_SYSOP_ARG:
janet_panicf("invalid instruction %v", x); janet_assert(0, "not reachable");
break; break;
case JANET_SYSOP_ADD: case JANET_SYSOP_ADD:
case JANET_SYSOP_SUBTRACT: case JANET_SYSOP_SUBTRACT:
@ -362,13 +394,14 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction
instruction.three.dest = instr_read_operand(tuple[1], out); instruction.three.dest = instr_read_operand(tuple[1], out);
instruction.three.lhs = instr_read_operand(tuple[2], out); instruction.three.lhs = instr_read_operand(tuple[2], out);
instruction.three.rhs = instr_read_operand(tuple[3], out); instruction.three.rhs = instr_read_operand(tuple[3], out);
ir[cursor++] = instruction; janet_v_push(ir, 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);
instruction.call.dest = instr_read_operand(tuple[1], out); instruction.call.dest = instr_read_operand(tuple[1], out);
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;
Janet check = janet_table_get(constant_cache, c); Janet check = janet_table_get(constant_cache, c);
if (janet_checktype(check, JANET_NUMBER)) { if (janet_checktype(check, JANET_NUMBER)) {
instruction.callk.constant = (uint32_t) janet_unwrap_number(check); instruction.callk.constant = (uint32_t) janet_unwrap_number(check);
@ -380,10 +413,10 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction
opcode = JANET_SYSOP_CALLK; opcode = JANET_SYSOP_CALLK;
instruction.opcode = opcode; instruction.opcode = opcode;
} else { } else {
instruction.call.arg_count = janet_tuple_length(tuple) - 3;
instruction.call.callee = instr_read_operand(tuple[2], out); instruction.call.callee = instr_read_operand(tuple[2], out);
} }
instruction.call.arg_count = janet_tuple_length(tuple) - 3; janet_v_push(ir, instruction);
ir[cursor++] = instruction;
for (int32_t j = 3; j < janet_tuple_length(tuple); j += 3) { for (int32_t j = 3; j < janet_tuple_length(tuple); j += 3) {
JanetSysInstruction arginstr; JanetSysInstruction arginstr;
arginstr.opcode = JANET_SYSOP_ARG; arginstr.opcode = JANET_SYSOP_ARG;
@ -397,7 +430,7 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction
for (int32_t k = 0; k < remaining; k++) { for (int32_t k = 0; k < remaining; k++) {
arginstr.arg.args[k] = instr_read_operand(tuple[j + k], out); arginstr.arg.args[k] = instr_read_operand(tuple[j + k], out);
} }
ir[cursor++] = arginstr; janet_v_push(ir, arginstr);
} }
break; break;
case JANET_SYSOP_LOAD: case JANET_SYSOP_LOAD:
@ -409,7 +442,7 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction
instr_assert_length(tuple, 3, opvalue); instr_assert_length(tuple, 3, opvalue);
instruction.two.dest = instr_read_operand(tuple[1], out); instruction.two.dest = instr_read_operand(tuple[1], out);
instruction.two.src = instr_read_operand(tuple[2], out); instruction.two.src = instr_read_operand(tuple[2], out);
ir[cursor++] = instruction; janet_v_push(ir, instruction);
break; break;
case JANET_SYSOP_FIELD_GET: case JANET_SYSOP_FIELD_GET:
case JANET_SYSOP_FIELD_SET: case JANET_SYSOP_FIELD_SET:
@ -417,23 +450,23 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction
instruction.field.r = instr_read_operand(tuple[1], out); instruction.field.r = instr_read_operand(tuple[1], out);
instruction.field.st = instr_read_operand(tuple[2], out); instruction.field.st = instr_read_operand(tuple[2], out);
instruction.field.field = instr_read_field(tuple[3], out); instruction.field.field = instr_read_field(tuple[3], out);
ir[cursor++] = instruction; janet_v_push(ir, instruction);
break; 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);
ir[cursor++] = instruction; janet_v_push(ir, instruction);
break; break;
case JANET_SYSOP_BRANCH: case JANET_SYSOP_BRANCH:
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.to = instr_read_label(tuple[2], labels); instruction.branch.temp_label = tuple[2];
ir[cursor++] = 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.to = instr_read_label(tuple[1], labels); instruction.jump.temp_label = tuple[1];
ir[cursor++] = instruction; janet_v_push(ir, instruction);
break; break;
case JANET_SYSOP_CONSTANT: { case JANET_SYSOP_CONSTANT: {
instr_assert_length(tuple, 3, opvalue); instr_assert_length(tuple, 3, opvalue);
@ -447,21 +480,28 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction
janet_table_put(constant_cache, c, janet_wrap_number(next_constant)); janet_table_put(constant_cache, c, janet_wrap_number(next_constant));
next_constant++; next_constant++;
} }
ir[cursor++] = instruction; janet_v_push(ir, instruction);
break; break;
} }
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);
instruction.type_prim.prim = instr_read_prim(tuple[2]); instruction.type_prim.prim = instr_read_prim(tuple[2]);
ir[cursor++] = instruction; janet_v_push(ir, instruction);
break;
}
case JANET_SYSOP_TYPE_POINTER: {
instr_assert_length(tuple, 3, opvalue);
instruction.pointer.dest_type = instr_read_type_operand(tuple[1], out);
instruction.pointer.type = instr_read_type_operand(tuple[2], out);
janet_v_push(ir, instruction);
break; break;
} }
case JANET_SYSOP_TYPE_STRUCT: { case JANET_SYSOP_TYPE_STRUCT: {
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);
instruction.type_types.arg_count = janet_tuple_length(tuple) - 2; instruction.type_types.arg_count = janet_tuple_length(tuple) - 2;
ir[cursor++] = 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) {
JanetSysInstruction arginstr; JanetSysInstruction arginstr;
arginstr.opcode = JANET_SYSOP_ARG; arginstr.opcode = JANET_SYSOP_ARG;
@ -475,7 +515,7 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction
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);
} }
ir[cursor++] = arginstr; janet_v_push(ir, arginstr);
} }
break; break;
} }
@ -483,21 +523,43 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction
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);
ir[cursor++] = instruction; janet_v_push(ir, instruction);
break; break;
} }
} }
} }
/* Check last instruction is jump or return */ /* Check last instruction is jump or return */
if ((ir[cursor - 1].opcode != JANET_SYSOP_JUMP) && (ir[cursor - 1].opcode != JANET_SYSOP_RETURN)) { uint32_t ircount = (uint32_t) janet_v_count(ir);
if (ircount == 0) {
janet_panic("empty ir");
}
int32_t lasti = ircount - 1;
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 %v", x);
} }
/* Fix up instructions table */ /* Fix up instructions table */
ir = janet_realloc(ir, sizeof(JanetSysInstruction) * cursor); out->instructions = janet_v_flatten(ir);
out->instructions = ir; out->instruction_count = ircount;
out->instruction_count = cursor;
/* 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, labels);
out->instructions[i].branch.to = label_target;
break;
case JANET_SYSOP_JUMP:
label_target = instr_read_label(out, instruction.jump.temp_label, labels);
out->instructions[i].jump.to = label_target;
break;
}
}
/* Build constants */ /* Build constants */
out->constant_count = next_constant; out->constant_count = next_constant;
@ -521,9 +583,7 @@ static void janet_sysir_init_types(JanetSysIR *sysir) {
uint32_t *types = janet_malloc(sizeof(uint32_t) * sysir->register_count); uint32_t *types = janet_malloc(sizeof(uint32_t) * sysir->register_count);
sysir->type_defs = type_defs; sysir->type_defs = type_defs;
sysir->types = types; sysir->types = types;
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;
} }
@ -535,15 +595,14 @@ _i4:
break; break;
case JANET_SYSOP_TYPE_PRIMITIVE: { case JANET_SYSOP_TYPE_PRIMITIVE: {
uint32_t type_def = instruction.type_prim.dest_type; uint32_t type_def = instruction.type_prim.dest_type;
type_defs[type_def].field_count = 0;
type_defs[type_def].prim = instruction.type_prim.prim; type_defs[type_def].prim = instruction.type_prim.prim;
break; break;
} }
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 = 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); type_defs[type_def].st.field_count = instruction.type_types.arg_count;
type_defs[type_def].st.field_start = (uint32_t) janet_v_count(fields);
for (uint32_t j = 0; j < instruction.type_types.arg_count; j++) { for (uint32_t j = 0; j < instruction.type_types.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;
@ -555,6 +614,12 @@ _i4:
} }
break; break;
} }
case JANET_SYSOP_TYPE_POINTER: {
uint32_t type_def = instruction.pointer.dest_type;
type_defs[type_def].prim = JANET_PRIM_POINTER;
type_defs[type_def].pointer.type = instruction.pointer.type;
break;
}
case JANET_SYSOP_TYPE_BIND: { case JANET_SYSOP_TYPE_BIND: {
uint32_t type = instruction.type_bind.type; uint32_t type = instruction.type_bind.type;
uint32_t dest = instruction.type_bind.dest; uint32_t dest = instruction.type_bind.dest;
@ -576,17 +641,26 @@ static void tcheck_boolean(JanetSysIR *sysir, uint32_t reg1) {
} }
} }
static void tcheck_number(JanetSysIR *sysir, uint32_t reg1) {
JanetPrim t1 = sysir->type_defs[sysir->types[reg1]].prim;
if (t1 == JANET_PRIM_BOOLEAN ||
t1 == JANET_PRIM_POINTER ||
t1 == JANET_PRIM_STRUCT) {
janet_panicf("type failure, expected numeric type, 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) {
JanetPrim t1 = sysir->type_defs[sysir->types[reg1]].prim; 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 &&
t1 != JANET_PRIM_S8 && t1 != JANET_PRIM_S8 &&
t1 != JANET_PRIM_U32 && t1 != JANET_PRIM_U32 &&
t1 != JANET_PRIM_U64 && t1 != JANET_PRIM_U64 &&
t1 != JANET_PRIM_U16 && t1 != JANET_PRIM_U16 &&
t1 != JANET_PRIM_U8) { t1 != JANET_PRIM_U8) {
janet_panicf("type failure, expected integer, got type-id:%d", t1); /* TODO improve this */ janet_panicf("type failure, expected integer type, got type-id:%d", t1); /* TODO improve this */
} }
} }
@ -612,6 +686,36 @@ static void tcheck_equal(JanetSysIR *sysir, uint32_t reg1, uint32_t reg2) {
} }
} }
static void tcheck_cast(JanetSysIR *sysir, uint32_t dest, uint32_t src) {
(void) sysir;
(void) dest;
(void) src;
/* TODO - casting rules */
}
static void tcheck_constant(JanetSysIR *sysir, uint32_t dest, Janet c) {
(void) sysir;
(void) dest;
(void) c;
/* TODO - validate the the constant C can be represented as dest */
}
/* Add and subtract can be used for pointer math as well as normal arithmetic. Unlike C, only
* allow pointer on lhs for addition. */
static void tcheck_pointer_math(JanetSysIR *sysir, uint32_t dest, uint32_t lhs, uint32_t rhs) {
uint32_t tdest = sysir->types[dest];
uint32_t tlhs = sysir->types[lhs];
if (tdest != tlhs) {
janet_panicf("type failure, type-id:%d does not match type-id:%d", tdest, tlhs);
}
uint32_t pdest = sysir->type_defs[tdest].prim;
if (pdest == JANET_PRIM_POINTER) {
tcheck_integer(sysir, rhs);
} else {
tcheck_equal(sysir, lhs, rhs);
}
}
static void janet_sysir_type_check(JanetSysIR *sysir) { static void janet_sysir_type_check(JanetSysIR *sysir) {
int found_return = 0; int found_return = 0;
for (uint32_t i = 0; i < sysir->instruction_count; i++) { for (uint32_t i = 0; i < sysir->instruction_count; i++) {
@ -619,6 +723,7 @@ static void janet_sysir_type_check(JanetSysIR *sysir) {
switch (instruction.opcode) { switch (instruction.opcode) {
case JANET_SYSOP_TYPE_PRIMITIVE: case JANET_SYSOP_TYPE_PRIMITIVE:
case JANET_SYSOP_TYPE_STRUCT: case JANET_SYSOP_TYPE_STRUCT:
case JANET_SYSOP_TYPE_POINTER:
case JANET_SYSOP_TYPE_BIND: case JANET_SYSOP_TYPE_BIND:
case JANET_SYSOP_ARG: case JANET_SYSOP_ARG:
case JANET_SYSOP_JUMP: case JANET_SYSOP_JUMP:
@ -639,11 +744,15 @@ static void janet_sysir_type_check(JanetSysIR *sysir) {
tcheck_equal(sysir, instruction.two.dest, instruction.two.src); tcheck_equal(sysir, instruction.two.dest, instruction.two.src);
break; break;
case JANET_SYSOP_CAST: case JANET_SYSOP_CAST:
tcheck_cast(sysir, instruction.two.dest, instruction.two.src);
break; break;
case JANET_SYSOP_ADD: case JANET_SYSOP_ADD:
case JANET_SYSOP_SUBTRACT: case JANET_SYSOP_SUBTRACT:
tcheck_pointer_math(sysir, instruction.three.dest, instruction.three.lhs, instruction.three.rhs);
break;
case JANET_SYSOP_MULTIPLY: case JANET_SYSOP_MULTIPLY:
case JANET_SYSOP_DIVIDE: case JANET_SYSOP_DIVIDE:
tcheck_number(sysir, instruction.three.dest);
tcheck_equal(sysir, instruction.three.lhs, instruction.three.rhs); tcheck_equal(sysir, instruction.three.lhs, instruction.three.rhs);
tcheck_equal(sysir, instruction.three.dest, instruction.three.lhs); tcheck_equal(sysir, instruction.three.dest, instruction.three.lhs);
break; break;
@ -687,7 +796,7 @@ static void janet_sysir_type_check(JanetSysIR *sysir) {
tcheck_boolean(sysir, instruction.branch.cond); tcheck_boolean(sysir, instruction.branch.cond);
break; break;
case JANET_SYSOP_CONSTANT: case JANET_SYSOP_CONSTANT:
/* TODO - check constant matches type */ tcheck_constant(sysir, instruction.constant.dest, sysir->constants[instruction.constant.constant]);
break; break;
case JANET_SYSOP_CALL: case JANET_SYSOP_CALL:
tcheck_pointer(sysir, instruction.call.callee); tcheck_pointer(sysir, instruction.call.callee);
@ -696,10 +805,10 @@ static void janet_sysir_type_check(JanetSysIR *sysir) {
case JANET_SYSOP_FIELD_SET: case JANET_SYSOP_FIELD_SET:
tcheck_struct(sysir, instruction.field.st); tcheck_struct(sysir, instruction.field.st);
uint32_t struct_type = sysir->types[instruction.field.st]; uint32_t struct_type = sysir->types[instruction.field.st];
if (instruction.field.field >= sysir->type_defs[struct_type].field_count) { if (instruction.field.field >= sysir->type_defs[struct_type].st.field_count) {
janet_panicf("invalid field index %u", instruction.field.field); 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 field_type = sysir->type_defs[struct_type].st.field_start + instruction.field.field;
uint32_t tfield = sysir->field_defs[field_type].type; uint32_t tfield = sysir->field_defs[field_type].type;
uint32_t tdest = sysir->types[instruction.field.r]; uint32_t tdest = sysir->types[instruction.field.r];
if (tfield != tdest) { if (tfield != tdest) {
@ -771,6 +880,7 @@ void janet_sys_ir_lower_to_c(JanetSysIR *ir, JanetBuffer *buffer) {
continue; continue;
case JANET_SYSOP_TYPE_PRIMITIVE: case JANET_SYSOP_TYPE_PRIMITIVE:
case JANET_SYSOP_TYPE_STRUCT: case JANET_SYSOP_TYPE_STRUCT:
case JANET_SYSOP_TYPE_POINTER:
break; break;
} }
if (instruction.line > 0) { if (instruction.line > 0) {
@ -792,6 +902,10 @@ void janet_sys_ir_lower_to_c(JanetSysIR *ir, JanetBuffer *buffer) {
} }
janet_formatb(buffer, "} _t%u;\n", instruction.type_types.dest_type); janet_formatb(buffer, "} _t%u;\n", instruction.type_types.dest_type);
break; break;
case JANET_SYSOP_TYPE_POINTER:
janet_formatb(buffer, "typedef _t%u *_t%u;\n", instruction.pointer.type, instruction.pointer.dest_type);
break;
} }
} }
@ -815,6 +929,7 @@ void janet_sys_ir_lower_to_c(JanetSysIR *ir, JanetBuffer *buffer) {
case JANET_SYSOP_TYPE_PRIMITIVE: case JANET_SYSOP_TYPE_PRIMITIVE:
case JANET_SYSOP_TYPE_BIND: case JANET_SYSOP_TYPE_BIND:
case JANET_SYSOP_TYPE_STRUCT: case JANET_SYSOP_TYPE_STRUCT:
case JANET_SYSOP_TYPE_POINTER:
case JANET_SYSOP_ARG: case JANET_SYSOP_ARG:
continue; continue;
default: default:
@ -829,6 +944,7 @@ void janet_sys_ir_lower_to_c(JanetSysIR *ir, JanetBuffer *buffer) {
case JANET_SYSOP_TYPE_PRIMITIVE: case JANET_SYSOP_TYPE_PRIMITIVE:
case JANET_SYSOP_TYPE_BIND: case JANET_SYSOP_TYPE_BIND:
case JANET_SYSOP_TYPE_STRUCT: case JANET_SYSOP_TYPE_STRUCT:
case JANET_SYSOP_TYPE_POINTER:
case JANET_SYSOP_ARG: case JANET_SYSOP_ARG:
break; break;
case JANET_SYSOP_CONSTANT: { case JANET_SYSOP_CONSTANT: {