1
0
mirror of https://github.com/janet-lang/janet synced 2025-01-10 07:30:26 +00:00

Add better support for arrays and struct fields in IR.

Also add option for named registers.
This commit is contained in:
Calvin Rose 2023-08-08 18:56:02 -05:00
parent de2440d458
commit 8007806c8e
2 changed files with 154 additions and 36 deletions

View File

@ -4,11 +4,12 @@
(prim 1 f64) (prim 1 f64)
(struct 2 0 1) (struct 2 0 1)
(pointer 3 0) (pointer 3 0)
(array 4 1 1024)
(bind 0 0) (bind 0 0)
(bind 1 0) (bind 1 0)
(bind 2 0) (bind 2 0)
(bind 3 1) (bind 3 1)
(bind 4 1) (bind bob 1)
(bind 5 1) (bind 5 1)
(bind 6 2) (bind 6 2)
(constant 0 10) (constant 0 10)
@ -17,10 +18,8 @@
(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 bob 2)
(fset 2 6 0) (add 5 bob 3)
(fset 3 6 1)
(add 5 4 3)
(jump :location) (jump :location)
(return 5)) (return 5))
:parameter-count 0 :parameter-count 0

View File

@ -22,11 +22,13 @@
/* TODO /* TODO
* [ ] named fields (for debugging mostly) * [ ] named fields (for debugging mostly)
* [ ] named registers and types
* [ ] better type errors (perhaps mostly for compiler debugging - full type system goes on top) * [ ] better type errors (perhaps mostly for compiler debugging - full type system goes on top)
* [ ] x86/x64 machine code target * [ ] x86/x64 machine code target
* [ ] target specific extensions - custom instructions and custom primitives * [ ] target specific extensions - custom instructions and custom primitives
* [ ] better casting semantics * [ ] better casting semantics
* [ ] fixed-size array types * [ ] separate pointer arithmetic from generalized arithmetic (easier to instrument code for safety)?
* [x] fixed-size array types
* [ ] recursive pointer types * [ ] recursive pointer types
* [ ] union types? * [ ] union types?
* [ ] incremental compilation - save type definitions for later * [ ] incremental compilation - save type definitions for later
@ -37,7 +39,7 @@
* [x] composite types - support for load, store, move, and function args. * [x] composite types - support for load, store, move, and function args.
* [x] Have some mechanism for field access (dest = src.offset) * [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. * [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 * [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)
* [ ] better C interface for building up IR * [ ] better C interface for building up IR
@ -65,6 +67,7 @@ typedef enum {
JANET_PRIM_POINTER, JANET_PRIM_POINTER,
JANET_PRIM_BOOLEAN, JANET_PRIM_BOOLEAN,
JANET_PRIM_STRUCT, JANET_PRIM_STRUCT,
JANET_PRIM_ARRAY,
} JanetPrim; } JanetPrim;
typedef struct { typedef struct {
@ -73,6 +76,7 @@ typedef struct {
} JanetPrimName; } JanetPrimName;
static const JanetPrimName prim_names[] = { static const JanetPrimName prim_names[] = {
{"array", JANET_PRIM_ARRAY},
{"boolean", JANET_PRIM_BOOLEAN}, {"boolean", JANET_PRIM_BOOLEAN},
{"f32", JANET_PRIM_F32}, {"f32", JANET_PRIM_F32},
{"f64", JANET_PRIM_F64}, {"f64", JANET_PRIM_F64},
@ -120,9 +124,11 @@ typedef enum {
JANET_SYSOP_TYPE_STRUCT, JANET_SYSOP_TYPE_STRUCT,
JANET_SYSOP_TYPE_BIND, JANET_SYSOP_TYPE_BIND,
JANET_SYSOP_ARG, JANET_SYSOP_ARG,
JANET_SYSOP_FIELD_GET, JANET_SYSOP_FIELD_GETP,
JANET_SYSOP_FIELD_SET, JANET_SYSOP_ARRAY_GETP,
JANET_SYSOP_TYPE_POINTER JANET_SYSOP_ARRAY_PGETP,
JANET_SYSOP_TYPE_POINTER,
JANET_SYSOP_TYPE_ARRAY
} JanetSysOp; } JanetSysOp;
typedef struct { typedef struct {
@ -133,6 +139,9 @@ typedef struct {
static const JanetSysInstrName sys_op_names[] = { static const JanetSysInstrName sys_op_names[] = {
{"add", JANET_SYSOP_ADD}, {"add", JANET_SYSOP_ADD},
{"address", JANET_SYSOP_ADDRESS}, {"address", JANET_SYSOP_ADDRESS},
{"agetp", JANET_SYSOP_ARRAY_GETP},
{"apgetp", JANET_SYSOP_ARRAY_PGETP},
{"array", JANET_SYSOP_TYPE_ARRAY},
{"band", JANET_SYSOP_BAND}, {"band", JANET_SYSOP_BAND},
{"bind", JANET_SYSOP_TYPE_BIND}, {"bind", JANET_SYSOP_TYPE_BIND},
{"bnot", JANET_SYSOP_BNOT}, {"bnot", JANET_SYSOP_BNOT},
@ -144,8 +153,7 @@ static const JanetSysInstrName sys_op_names[] = {
{"constant", JANET_SYSOP_CONSTANT}, {"constant", JANET_SYSOP_CONSTANT},
{"divide", JANET_SYSOP_DIVIDE}, {"divide", JANET_SYSOP_DIVIDE},
{"eq", JANET_SYSOP_EQ}, {"eq", JANET_SYSOP_EQ},
{"fget", JANET_SYSOP_FIELD_GET}, {"fgetp", JANET_SYSOP_FIELD_GETP},
{"fset", JANET_SYSOP_FIELD_SET},
{"gt", JANET_SYSOP_GT}, {"gt", JANET_SYSOP_GT},
{"gte", JANET_SYSOP_GTE}, {"gte", JANET_SYSOP_GTE},
{"jump", JANET_SYSOP_JUMP}, {"jump", JANET_SYSOP_JUMP},
@ -175,6 +183,10 @@ typedef struct {
struct { struct {
uint32_t type; uint32_t type;
} pointer; } pointer;
struct {
uint32_t type;
uint64_t fixed_count;
} array;
}; };
} JanetSysTypeInfo; } JanetSysTypeInfo;
@ -248,6 +260,11 @@ typedef struct {
uint32_t dest_type; uint32_t dest_type;
uint32_t type; uint32_t type;
} pointer; } pointer;
struct {
uint32_t dest_type;
uint32_t type;
uint64_t fixed_count;
} array;
}; };
int32_t line; int32_t line;
int32_t column; int32_t column;
@ -266,6 +283,7 @@ typedef struct {
JanetSysTypeField *field_defs; JanetSysTypeField *field_defs;
JanetSysInstruction *instructions; JanetSysInstruction *instructions;
Janet *constants; Janet *constants;
JanetTable *register_names;
uint32_t parameter_count; uint32_t parameter_count;
} JanetSysIR; } JanetSysIR;
@ -284,6 +302,16 @@ static void instr_assert_min_length(JanetTuple tup, int32_t minlen, Janet x) {
} }
static uint32_t instr_read_operand(Janet x, JanetSysIR *ir) { static uint32_t instr_read_operand(Janet x, JanetSysIR *ir) {
if (janet_checktype(x, JANET_SYMBOL)) {
Janet check = janet_table_get(ir->register_names, x);
if (janet_checktype(check, JANET_NUMBER)) {
return (uint32_t) janet_unwrap_number(check);
} else {
uint32_t operand = ir->register_count++;
janet_table_put(ir->register_names, x, janet_wrap_number(operand));
return operand;
}
}
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);
if (operand >= ir->register_count) { if (operand >= ir->register_count) {
@ -299,6 +327,12 @@ static uint32_t instr_read_field(Janet x, JanetSysIR *ir) {
return operand; return operand;
} }
static uint64_t instr_read_u64(Janet x, JanetSysIR *ir) {
if (!janet_checkuint64(x)) janet_panicf("expected unsigned 64 bit integer, got %v", x);
(void) ir;
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) {
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);
@ -322,6 +356,7 @@ static JanetPrim instr_read_prim(Janet x) {
} }
static uint32_t instr_read_label(JanetSysIR *sysir, Janet x, JanetTable *labels) { static uint32_t instr_read_label(JanetSysIR *sysir, Janet x, JanetTable *labels) {
(void) sysir;
uint32_t ret = 0; uint32_t ret = 0;
Janet check = janet_table_get(labels, x); Janet check = janet_table_get(labels, x);
if (!janet_checktype(check, JANET_NIL)) { if (!janet_checktype(check, JANET_NIL)) {
@ -331,9 +366,6 @@ static uint32_t instr_read_label(JanetSysIR *sysir, Janet x, JanetTable *labels)
if (!janet_checkuint(x)) janet_panicf("expected non-negative integer label, got %v", x); if (!janet_checkuint(x)) janet_panicf("expected non-negative integer label, got %v", x);
ret = (uint32_t) janet_unwrap_number(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; return ret;
} }
@ -396,6 +428,8 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction
case JANET_SYSOP_LTE: case JANET_SYSOP_LTE:
case JANET_SYSOP_EQ: case JANET_SYSOP_EQ:
case JANET_SYSOP_NEQ: case JANET_SYSOP_NEQ:
case JANET_SYSOP_ARRAY_GETP:
case JANET_SYSOP_ARRAY_PGETP:
instr_assert_length(tuple, 4, opvalue); instr_assert_length(tuple, 4, opvalue);
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);
@ -450,8 +484,7 @@ 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);
janet_v_push(ir, instruction); janet_v_push(ir, instruction);
break; break;
case JANET_SYSOP_FIELD_GET: case JANET_SYSOP_FIELD_GETP:
case JANET_SYSOP_FIELD_SET:
instr_assert_length(tuple, 4, opvalue); instr_assert_length(tuple, 4, opvalue);
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);
@ -503,6 +536,14 @@ 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_TYPE_ARRAY: {
instr_assert_length(tuple, 4, opvalue);
instruction.array.dest_type = instr_read_type_operand(tuple[1], out);
instruction.array.type = instr_read_type_operand(tuple[2], out);
instruction.array.fixed_count = instr_read_u64(tuple[3], out);
janet_v_push(ir, instruction);
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);
@ -626,6 +667,13 @@ static void janet_sysir_init_types(JanetSysIR *sysir) {
type_defs[type_def].pointer.type = instruction.pointer.type; type_defs[type_def].pointer.type = instruction.pointer.type;
break; break;
} }
case JANET_SYSOP_TYPE_ARRAY: {
uint32_t type_def = instruction.array.dest_type;
type_defs[type_def].prim = JANET_PRIM_ARRAY;
type_defs[type_def].array.type = instruction.array.type;
type_defs[type_def].array.fixed_count = instruction.array.fixed_count;
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;
@ -647,6 +695,13 @@ static void tcheck_boolean(JanetSysIR *sysir, uint32_t reg1) {
} }
} }
static void tcheck_array(JanetSysIR *sysir, uint32_t reg1) {
uint32_t t1 = sysir->types[reg1];
if (sysir->type_defs[t1].prim != JANET_PRIM_ARRAY) {
janet_panicf("type failure, expected array, got type-id:%d", t1); /* TODO improve this */
}
}
static void tcheck_number(JanetSysIR *sysir, uint32_t reg1) { static void tcheck_number(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_BOOLEAN || if (t1 == JANET_PRIM_BOOLEAN ||
@ -677,6 +732,18 @@ static void tcheck_pointer(JanetSysIR *sysir, uint32_t reg1) {
} }
} }
static void tcheck_pointer_equals(JanetSysIR *sysir, uint32_t preg, uint32_t elreg) {
uint32_t t1 = sysir->types[preg];
if (sysir->type_defs[t1].prim != JANET_PRIM_POINTER) {
janet_panicf("type failure, expected pointer, got type-id:%d", t1);
}
uint32_t tp = sysir->type_defs[t1].pointer.type;
uint32_t t2 = sysir->types[elreg];
if (t2 != tp) {
janet_panicf("type failure, type-id:%d is not compatible with a pointer to type-id:%d", t2, tp);
}
}
static void tcheck_struct(JanetSysIR *sysir, uint32_t reg1) { static void tcheck_struct(JanetSysIR *sysir, uint32_t reg1) {
uint32_t t1 = sysir->types[reg1]; uint32_t t1 = sysir->types[reg1];
if (sysir->type_defs[t1].prim != JANET_PRIM_STRUCT) { if (sysir->type_defs[t1].prim != JANET_PRIM_STRUCT) {
@ -706,6 +773,32 @@ static void tcheck_constant(JanetSysIR *sysir, uint32_t dest, Janet c) {
/* TODO - validate the the constant C can be represented as dest */ /* TODO - validate the the constant C can be represented as dest */
} }
static void tcheck_array_getp(JanetSysIR *sysir, uint32_t dest, uint32_t lhs, uint32_t rhs) {
tcheck_array(sysir, lhs);
tcheck_integer(sysir, rhs);
tcheck_pointer(sysir, dest);
uint32_t dtype = sysir->type_defs[sysir->types[dest]].pointer.type;
uint32_t eltype = sysir->type_defs[sysir->types[lhs]].array.type;
if (dtype != eltype) {
janet_panicf("type failure, type-id:%d does not match type-id:%d", dtype, eltype);
}
}
static void tcheck_array_pgetp(JanetSysIR *sysir, uint32_t dest, uint32_t lhs, uint32_t rhs) {
tcheck_pointer(sysir, lhs);
tcheck_integer(sysir, rhs);
tcheck_pointer(sysir, dest);
uint32_t aptype = sysir->type_defs[sysir->types[lhs]].pointer.type;
if (sysir->type_defs[aptype].prim != JANET_PRIM_ARRAY) {
janet_panicf("type failure, expected array type but got type-id:%d", aptype);
}
uint32_t dtype = sysir->type_defs[sysir->types[dest]].pointer.type;
uint32_t eltype = sysir->type_defs[aptype].array.type;
if (dtype != eltype) {
janet_panicf("type failure, type-id:%d does not match type-id:%d", dtype, eltype);
}
}
/* Add and subtract can be used for pointer math as well as normal arithmetic. Unlike C, only /* Add and subtract can be used for pointer math as well as normal arithmetic. Unlike C, only
* allow pointer on lhs for addition. */ * allow pointer on lhs for addition. */
static void tcheck_pointer_math(JanetSysIR *sysir, uint32_t dest, uint32_t lhs, uint32_t rhs) { static void tcheck_pointer_math(JanetSysIR *sysir, uint32_t dest, uint32_t lhs, uint32_t rhs) {
@ -730,9 +823,15 @@ static void janet_sysir_type_check(JanetSysIR *sysir) {
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_POINTER:
case JANET_SYSOP_TYPE_ARRAY:
case JANET_SYSOP_TYPE_BIND: case JANET_SYSOP_TYPE_BIND:
case JANET_SYSOP_ARG: case JANET_SYSOP_ARG:
break;
case JANET_SYSOP_JUMP: case JANET_SYSOP_JUMP:
;
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];
@ -780,10 +879,10 @@ static void janet_sysir_type_check(JanetSysIR *sysir) {
tcheck_equal(sysir, instruction.three.dest, instruction.three.lhs); tcheck_equal(sysir, instruction.three.dest, instruction.three.lhs);
break; break;
case JANET_SYSOP_LOAD: case JANET_SYSOP_LOAD:
tcheck_pointer(sysir, instruction.two.src); tcheck_pointer_equals(sysir, instruction.two.src, instruction.two.dest);
break; break;
case JANET_SYSOP_STORE: case JANET_SYSOP_STORE:
tcheck_pointer(sysir, instruction.two.dest); tcheck_pointer_equals(sysir, instruction.two.dest, instruction.two.src);
break; break;
case JANET_SYSOP_GT: case JANET_SYSOP_GT:
case JANET_SYSOP_LT: case JANET_SYSOP_LT:
@ -800,6 +899,9 @@ static void janet_sysir_type_check(JanetSysIR *sysir) {
break; break;
case JANET_SYSOP_BRANCH: case JANET_SYSOP_BRANCH:
tcheck_boolean(sysir, instruction.branch.cond); tcheck_boolean(sysir, 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]);
@ -807,8 +909,14 @@ 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_ARRAY_GETP:
case JANET_SYSOP_FIELD_SET: tcheck_array_getp(sysir, instruction.three.dest, instruction.three.lhs, instruction.three.lhs);
break;
case JANET_SYSOP_ARRAY_PGETP:
tcheck_array_pgetp(sysir, instruction.three.dest, instruction.three.lhs, instruction.three.lhs);
break;
case JANET_SYSOP_FIELD_GETP:
tcheck_pointer(sysir, instruction.field.r);
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].st.field_count) { if (instruction.field.field >= sysir->type_defs[struct_type].st.field_count) {
@ -817,8 +925,9 @@ static void janet_sysir_type_check(JanetSysIR *sysir) {
uint32_t field_type = sysir->type_defs[struct_type].st.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) { uint32_t tpdest = sysir->type_defs[tdest].pointer.type;
janet_panicf("field of type type-id:%d does not match type-id:%d", tfield, tdest); if (tfield != tpdest) {
janet_panicf("field of type type-id:%d does not match type-id:%d", tfield, tpdest);
} }
break; break;
case JANET_SYSOP_CALLK: case JANET_SYSOP_CALLK:
@ -841,6 +950,7 @@ void janet_sys_ir_init_from_table(JanetSysIR *ir, JanetTable *table) {
ir->constant_count = 0; ir->constant_count = 0;
ir->return_type = 0; ir->return_type = 0;
ir->parameter_count = 0; ir->parameter_count = 0;
ir->register_names = janet_table(0);
Janet assembly = janet_table_get(table, janet_ckeywordv("instructions")); Janet assembly = janet_table_get(table, janet_ckeywordv("instructions"));
Janet param_count = janet_table_get(table, janet_ckeywordv("parameter-count")); Janet param_count = janet_table_get(table, janet_ckeywordv("parameter-count"));
Janet link_namev = janet_table_get(table, janet_ckeywordv("link-name")); Janet link_namev = janet_table_get(table, janet_ckeywordv("link-name"));
@ -867,7 +977,7 @@ static const char *c_prim_names[] = {
"int64_t", "int64_t",
"float", "float",
"double", "double",
"char *", "void *",
"bool" "bool"
}; };
@ -887,6 +997,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_STRUCT: case JANET_SYSOP_TYPE_STRUCT:
case JANET_SYSOP_TYPE_POINTER: case JANET_SYSOP_TYPE_POINTER:
case JANET_SYSOP_TYPE_ARRAY:
break; break;
} }
if (instruction.line > 0) { if (instruction.line > 0) {
@ -904,26 +1015,28 @@ void janet_sys_ir_lower_to_c(JanetSysIR *ir, JanetBuffer *buffer) {
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, " _t%u _f%u;\n", arg_instruction.arg.args[index], j); janet_formatb(buffer, " _t%u _f%u;\n", arg_instruction.arg.args[index], j);
} }
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: case JANET_SYSOP_TYPE_POINTER:
janet_formatb(buffer, "typedef _t%u *_t%u;\n", instruction.pointer.type, instruction.pointer.dest_type); janet_formatb(buffer, "typedef _t%u *_t%u;\n", instruction.pointer.type, instruction.pointer.dest_type);
break; break;
case JANET_SYSOP_TYPE_ARRAY:
janet_formatb(buffer, "typedef struct { _t%u els[%u]; } _t%u;\n", instruction.array.type, instruction.array.fixed_count, instruction.array.dest_type);
break;
} }
} }
/* Emit header */ /* Emit function header */
janet_formatb(buffer, "_t%u %s(", ir->return_type, (ir->link_name != NULL) ? ir->link_name : janet_cstring("_thunk")); janet_formatb(buffer, "_t%u %s(", ir->return_type, (ir->link_name != NULL) ? ir->link_name : janet_cstring("_thunk"));
for (uint32_t i = 0; i < ir->parameter_count; i++) { for (uint32_t i = 0; i < ir->parameter_count; i++) {
if (i) janet_buffer_push_cstring(buffer, ", "); if (i) janet_buffer_push_cstring(buffer, ", ");
janet_formatb(buffer, "_t%u _r%u", ir->types[i], i); janet_formatb(buffer, " _t%u _r%u", ir->types[i], i);
} }
janet_buffer_push_cstring(buffer, ")\n{\n"); janet_buffer_push_cstring(buffer, ")\n{\n");
for (uint32_t i = ir->parameter_count; i < ir->register_count; i++) { for (uint32_t i = ir->parameter_count; i < ir->register_count; i++) {
janet_formatb(buffer, " _t%u _r%u;\n", ir->types[i], i); janet_formatb(buffer, " _t%u _r%u;\n", ir->types[i], i);
} }
janet_buffer_push_cstring(buffer, "\n"); janet_buffer_push_cstring(buffer, "\n");
@ -936,6 +1049,7 @@ void janet_sys_ir_lower_to_c(JanetSysIR *ir, JanetBuffer *buffer) {
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_TYPE_POINTER:
case JANET_SYSOP_TYPE_ARRAY:
case JANET_SYSOP_ARG: case JANET_SYSOP_ARG:
continue; continue;
default: default:
@ -951,6 +1065,7 @@ void janet_sys_ir_lower_to_c(JanetSysIR *ir, JanetBuffer *buffer) {
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_TYPE_POINTER:
case JANET_SYSOP_TYPE_ARRAY:
case JANET_SYSOP_ARG: case JANET_SYSOP_ARG:
break; break;
case JANET_SYSOP_CONSTANT: { case JANET_SYSOP_CONSTANT: {
@ -1036,7 +1151,7 @@ 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:
/* TODO - making casting rules explicit instead of just from C */ /* TODO - make casting rules explicit instead of just whatever C does */
janet_formatb(buffer, "_r%u = (_t%u) _r%u;\n", instruction.two.dest, ir->types[instruction.two.dest], instruction.two.src); 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:
@ -1046,16 +1161,19 @@ 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);\n", instruction.two.dest, c_prim_names[ir->types[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, "*((%s *) _r%u) = _r%u;\n", c_prim_names[ir->types[instruction.two.src]], 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_GET: 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_FIELD_SET: case JANET_SYSOP_ARRAY_GETP:
janet_formatb(buffer, "_r%u._f%u = _r%u;\n", instruction.field.st, instruction.field.field, instruction.field.r); janet_formatb(buffer, "_r%u = &(_r%u.els[_r%u]);\n", instruction.three.dest, instruction.three.lhs, instruction.three.rhs);
break;
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);
break; break;
} }
} }
@ -1079,6 +1197,7 @@ static int sysir_gc(void *p, size_t s) {
static int sysir_gcmark(void *p, size_t s) { static int sysir_gcmark(void *p, size_t s) {
JanetSysIR *ir = (JanetSysIR *)p; JanetSysIR *ir = (JanetSysIR *)p;
(void) s; (void) s;
janet_mark(janet_wrap_table(ir->register_names));
for (uint32_t i = 0; i < ir->constant_count; i++) { for (uint32_t i = 0; i < ir->constant_count; i++) {
janet_mark(ir->constants[i]); janet_mark(ir->constants[i]);
} }