mirror of
https://github.com/janet-lang/janet
synced 2025-01-10 15:40:30 +00:00
Have separate instructions for pointer arith
This commit is contained in:
parent
1e1e7a5cfd
commit
4b8e7a416f
56
examples/sysir/typeerr0.janet
Normal file
56
examples/sysir/typeerr0.janet
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
### typedef struct {float x; float y; float z;} Vec3;
|
||||||
|
###
|
||||||
|
### Vec3 addv(Vec3 a, Vec3 b) {
|
||||||
|
### Vec3 ret;
|
||||||
|
### ret.x = a.x + b.x;
|
||||||
|
### ret.y = a.y + b.y;
|
||||||
|
### ret.z = a.z + b.z;
|
||||||
|
### return ret;
|
||||||
|
### }
|
||||||
|
|
||||||
|
(def ir-asm
|
||||||
|
@{:instructions
|
||||||
|
'(
|
||||||
|
# Types
|
||||||
|
(type-prim Real f32)
|
||||||
|
(type-struct Vec3 Real Real Real)
|
||||||
|
(type-pointer PReal Real)
|
||||||
|
|
||||||
|
# Declarations
|
||||||
|
(bind position Vec3)
|
||||||
|
(bind velocity Vec3)
|
||||||
|
(bind next-position Vec3)
|
||||||
|
(bind dest Real)
|
||||||
|
(bind lhs Real)
|
||||||
|
(bind rhs Real)
|
||||||
|
(bind pdest PReal)
|
||||||
|
(bind plhs PReal)
|
||||||
|
(bind prhs PReal)
|
||||||
|
|
||||||
|
# Code (has type errors)
|
||||||
|
(fgetp pdest next-position 0)
|
||||||
|
(fgetp plhs position 0)
|
||||||
|
(fgetp prhs velocity 0)
|
||||||
|
(add dest plhs prhs)
|
||||||
|
(store pdest dest)
|
||||||
|
|
||||||
|
(fgetp pdest next-position 1)
|
||||||
|
(fgetp plhs position 1)
|
||||||
|
(fgetp prhs velocity 1)
|
||||||
|
(add dest lhs rhs)
|
||||||
|
(load lhs plhs)
|
||||||
|
(load rhs prhs)
|
||||||
|
(store pdest dest)
|
||||||
|
|
||||||
|
(fgetp pdest next-position 2)
|
||||||
|
(fgetp plhs position 2)
|
||||||
|
(fgetp prhs velocity 2)
|
||||||
|
(add dest plhs prhs)
|
||||||
|
(store pdest dest)
|
||||||
|
|
||||||
|
(return next-position))
|
||||||
|
:parameter-count 2
|
||||||
|
:link-name "addv_with_err"})
|
||||||
|
|
||||||
|
(def as (sysir/asm ir-asm))
|
||||||
|
(print (sysir/to-c as))
|
@ -20,14 +20,21 @@
|
|||||||
* IN THE SOFTWARE.
|
* IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/****
|
||||||
|
*
|
||||||
|
* The System Dialect Intermediate Representation (sysir) is a compiler intermediate representation
|
||||||
|
* that is a target of a language frontend. Sysir can then be retargeted to C or direct to machine
|
||||||
|
* code for JIT or AOT compilation.
|
||||||
|
*/
|
||||||
|
|
||||||
/* TODO
|
/* TODO
|
||||||
* [ ] named fields (for debugging mostly)
|
* [ ] named fields (for debugging mostly)
|
||||||
* [x] named registers and types
|
* [x] named registers and types
|
||||||
* [ ] better type errors (perhaps mostly for compiler debugging - full type system goes on top)
|
* [x] 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
|
||||||
* [ ] separate pointer arithmetic from generalized arithmetic (easier to instrument code for safety)?
|
* [x] separate pointer arithmetic from generalized arithmetic (easier to instrument code for safety)?
|
||||||
* [x] fixed-size array types
|
* [x] fixed-size array types
|
||||||
* [ ] recursive pointer types
|
* [ ] recursive pointer types
|
||||||
* [x] union types?
|
* [x] union types?
|
||||||
@ -42,7 +49,15 @@
|
|||||||
* [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)
|
||||||
* [ ] better C interface for building up IR
|
* [ ] unit type or void type
|
||||||
|
* [ ] (typed) function pointer types and remove calling untyped pointers
|
||||||
|
* [ ] APL array semantics for binary operands (maybe?)
|
||||||
|
* [ ] a few built-in array combinators (maybe?)
|
||||||
|
* [ ] partial evaluator (maybe?)
|
||||||
|
* [ ] sysir interpreter (maybe?)
|
||||||
|
* [ ] multiple error messages in one pass
|
||||||
|
* [ ] better verification of constants
|
||||||
|
* [ ] forward type inference
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef JANET_AMALG
|
#ifndef JANET_AMALG
|
||||||
@ -131,6 +146,8 @@ typedef enum {
|
|||||||
JANET_SYSOP_TYPE_POINTER,
|
JANET_SYSOP_TYPE_POINTER,
|
||||||
JANET_SYSOP_TYPE_ARRAY,
|
JANET_SYSOP_TYPE_ARRAY,
|
||||||
JANET_SYSOP_TYPE_UNION,
|
JANET_SYSOP_TYPE_UNION,
|
||||||
|
JANET_SYSOP_POINTER_ADD,
|
||||||
|
JANET_SYSOP_POINTER_SUBTRACT,
|
||||||
} JanetSysOp;
|
} JanetSysOp;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -164,6 +181,8 @@ 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-add", JANET_SYSOP_POINTER_ADD},
|
||||||
|
{"pointer-subtract", JANET_SYSOP_POINTER_SUBTRACT},
|
||||||
{"return", JANET_SYSOP_RETURN},
|
{"return", JANET_SYSOP_RETURN},
|
||||||
{"shl", JANET_SYSOP_SHL},
|
{"shl", JANET_SYSOP_SHL},
|
||||||
{"shr", JANET_SYSOP_SHR},
|
{"shr", JANET_SYSOP_SHR},
|
||||||
@ -473,6 +492,8 @@ static void janet_sysir_init_instructions(JanetSysIRBuilder *out, JanetView inst
|
|||||||
case JANET_SYSOP_NEQ:
|
case JANET_SYSOP_NEQ:
|
||||||
case JANET_SYSOP_ARRAY_GETP:
|
case JANET_SYSOP_ARRAY_GETP:
|
||||||
case JANET_SYSOP_ARRAY_PGETP:
|
case JANET_SYSOP_ARRAY_PGETP:
|
||||||
|
case JANET_SYSOP_POINTER_ADD:
|
||||||
|
case JANET_SYSOP_POINTER_SUBTRACT:
|
||||||
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);
|
||||||
@ -861,21 +882,29 @@ static void tcheck_array_pgetp(JanetSysIR *sysir, uint32_t dest, uint32_t lhs, u
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tcheck_fgetp(JanetSysIR *sysir, uint32_t dest, uint32_t st, uint32_t field) {
|
||||||
|
tcheck_pointer(sysir, dest);
|
||||||
|
tcheck_struct_or_union(sysir, st);
|
||||||
|
uint32_t struct_type = sysir->types[st];
|
||||||
|
if (field >= sysir->type_defs[struct_type].st.field_count) {
|
||||||
|
janet_panicf("invalid field index %u", field);
|
||||||
|
}
|
||||||
|
uint32_t field_type = sysir->type_defs[struct_type].st.field_start + field;
|
||||||
|
uint32_t tfield = sysir->field_defs[field_type].type;
|
||||||
|
uint32_t tdest = sysir->types[dest];
|
||||||
|
uint32_t tpdest = sysir->type_defs[tdest].pointer.type;
|
||||||
|
if (tfield != tpdest) {
|
||||||
|
janet_panicf("field of type %V does not match %V",
|
||||||
|
tname(sysir, tfield),
|
||||||
|
tname(sysir, tpdest));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 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) {
|
||||||
uint32_t tdest = sysir->types[dest];
|
tcheck_pointer_equals(sysir, dest, lhs);
|
||||||
uint32_t tlhs = sysir->types[lhs];
|
tcheck_integer(sysir, rhs);
|
||||||
if (tdest != tlhs) {
|
|
||||||
janet_panicf("type failure, %V does not match %V", tname(sysir, tdest),
|
|
||||||
tname(sysir, 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) {
|
||||||
@ -917,10 +946,12 @@ static void janet_sysir_type_check(JanetSysIR *sysir) {
|
|||||||
case JANET_SYSOP_CAST:
|
case JANET_SYSOP_CAST:
|
||||||
tcheck_cast(sysir, instruction.two.dest, instruction.two.src);
|
tcheck_cast(sysir, instruction.two.dest, instruction.two.src);
|
||||||
break;
|
break;
|
||||||
case JANET_SYSOP_ADD:
|
case JANET_SYSOP_POINTER_ADD:
|
||||||
case JANET_SYSOP_SUBTRACT:
|
case JANET_SYSOP_POINTER_SUBTRACT:
|
||||||
tcheck_pointer_math(sysir, instruction.three.dest, instruction.three.lhs, instruction.three.rhs);
|
tcheck_pointer_math(sysir, instruction.three.dest, instruction.three.lhs, instruction.three.rhs);
|
||||||
break;
|
break;
|
||||||
|
case JANET_SYSOP_ADD:
|
||||||
|
case JANET_SYSOP_SUBTRACT:
|
||||||
case JANET_SYSOP_MULTIPLY:
|
case JANET_SYSOP_MULTIPLY:
|
||||||
case JANET_SYSOP_DIVIDE:
|
case JANET_SYSOP_DIVIDE:
|
||||||
tcheck_number(sysir, instruction.three.dest);
|
tcheck_number(sysir, instruction.three.dest);
|
||||||
@ -930,7 +961,7 @@ static void janet_sysir_type_check(JanetSysIR *sysir) {
|
|||||||
case JANET_SYSOP_BAND:
|
case JANET_SYSOP_BAND:
|
||||||
case JANET_SYSOP_BOR:
|
case JANET_SYSOP_BOR:
|
||||||
case JANET_SYSOP_BXOR:
|
case JANET_SYSOP_BXOR:
|
||||||
tcheck_integer(sysir, instruction.three.lhs);
|
tcheck_integer(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;
|
||||||
@ -982,21 +1013,7 @@ static void janet_sysir_type_check(JanetSysIR *sysir) {
|
|||||||
tcheck_array_pgetp(sysir, instruction.three.dest, instruction.three.lhs, instruction.three.lhs);
|
tcheck_array_pgetp(sysir, instruction.three.dest, instruction.three.lhs, instruction.three.lhs);
|
||||||
break;
|
break;
|
||||||
case JANET_SYSOP_FIELD_GETP:
|
case JANET_SYSOP_FIELD_GETP:
|
||||||
tcheck_pointer(sysir, instruction.field.r);
|
tcheck_fgetp(sysir, instruction.field.r, instruction.field.st, instruction.field.field);
|
||||||
tcheck_struct_or_union(sysir, instruction.field.st);
|
|
||||||
uint32_t struct_type = sysir->types[instruction.field.st];
|
|
||||||
if (instruction.field.field >= sysir->type_defs[struct_type].st.field_count) {
|
|
||||||
janet_panicf("invalid field index %u", 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 tdest = sysir->types[instruction.field.r];
|
|
||||||
uint32_t tpdest = sysir->type_defs[tdest].pointer.type;
|
|
||||||
if (tfield != tpdest) {
|
|
||||||
janet_panicf("field of type %V does not match %V",
|
|
||||||
tname(sysir, tfield),
|
|
||||||
tname(sysir, tpdest));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case JANET_SYSOP_CALLK:
|
case JANET_SYSOP_CALLK:
|
||||||
/* TODO - check function return type */
|
/* TODO - check function return type */
|
||||||
@ -1007,6 +1024,7 @@ static void janet_sysir_type_check(JanetSysIR *sysir) {
|
|||||||
|
|
||||||
void janet_sys_ir_init_from_table(JanetSysIR *out, JanetTable *table) {
|
void janet_sys_ir_init_from_table(JanetSysIR *out, JanetTable *table) {
|
||||||
JanetSysIRBuilder b;
|
JanetSysIRBuilder b;
|
||||||
|
memset(out, 0, sizeof(*out));
|
||||||
|
|
||||||
b.ir.instructions = NULL;
|
b.ir.instructions = NULL;
|
||||||
b.ir.types = NULL;
|
b.ir.types = NULL;
|
||||||
@ -1171,9 +1189,11 @@ void janet_sys_ir_lower_to_c(JanetSysIR *ir, JanetBuffer *buffer) {
|
|||||||
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:
|
||||||
EMITBINOP("+");
|
EMITBINOP("+");
|
||||||
break;
|
break;
|
||||||
case JANET_SYSOP_SUBTRACT:
|
case JANET_SYSOP_SUBTRACT:
|
||||||
|
case JANET_SYSOP_POINTER_SUBTRACT:
|
||||||
EMITBINOP("-");
|
EMITBINOP("-");
|
||||||
break;
|
break;
|
||||||
case JANET_SYSOP_MULTIPLY:
|
case JANET_SYSOP_MULTIPLY:
|
||||||
@ -1236,7 +1256,6 @@ 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 - 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:
|
||||||
|
Loading…
Reference in New Issue
Block a user