diff options
Diffstat (limited to 'include/ejit/ejit.h')
-rw-r--r-- | include/ejit/ejit.h | 196 |
1 files changed, 132 insertions, 64 deletions
diff --git a/include/ejit/ejit.h b/include/ejit/ejit.h index 4ab2bbc..ab06d8f 100644 --- a/include/ejit/ejit.h +++ b/include/ejit/ejit.h @@ -72,29 +72,20 @@ static inline enum ejit_type ejit_signed_type(size_t w) struct ejit_arg { union { - int8_t i8; - uint8_t u8; + int8_t i8; int16_t i16; - uint16_t u16; int32_t i32; - uint32_t u32; int64_t i64; - uint64_t u64; - signed char c; - unsigned char uc; - signed short s; - unsigned short us; - signed int i; - unsigned int ui; - signed long l; - unsigned long ul; - signed long long ll; - unsigned long long ull; + uint8_t u8; + uint16_t u16; + uint32_t u32; + uint64_t u64; float f; double d; void *p; + long l; }; enum ejit_type type; }; @@ -113,6 +104,7 @@ static inline bool ejit_int_type(enum ejit_type t) case EJIT_POINTER: return true; default: + break; } return false; @@ -125,6 +117,7 @@ static inline bool ejit_float_type(enum ejit_type t) case EJIT_DOUBLE: return true; default: + break; } return false; @@ -136,15 +129,15 @@ static inline struct ejit_arg ejit_build_arg(enum ejit_type type, uint64_t x) a.type = type; switch (type) { - case EJIT_INT8: a.u64 = (int8_t)x; break; - case EJIT_INT16: a.u64 = (int16_t)x; break; - case EJIT_INT32: a.u64 = (int32_t)x; break; - case EJIT_INT64: a.u64 = (int64_t)x; break; - case EJIT_UINT8: a.u64 = (uint8_t)x; break; - case EJIT_UINT16: a.u64 = (uint16_t)x; break; - case EJIT_UINT32: a.u64 = (uint32_t)x; break; - case EJIT_UINT64: a.u64 = (uint64_t)x; break; - case EJIT_POINTER: a.p = (void *)(uintptr_t)x; break; + case EJIT_INT8: a.i8 = (int8_t)x; break; + case EJIT_INT16: a.i16 = (int16_t)x; break; + case EJIT_INT32: a.i32 = (int32_t)x; break; + case EJIT_INT64: a.i64 = (int64_t)x; break; + case EJIT_UINT8: a.u8 = (uint8_t)x; break; + case EJIT_UINT16: a.u16 = (uint16_t)x; break; + case EJIT_UINT32: a.u32 = (uint32_t)x; break; + case EJIT_UINT64: a.u64 = (uint64_t)x; break; + case EJIT_POINTER: a.p = (void *)(uintptr_t)x; break; default: abort(); } @@ -157,7 +150,7 @@ static inline struct ejit_arg ejit_build_arg_f(enum ejit_type type, double x) a.type = type; switch (type) { - case EJIT_FLOAT: a.f = x; break; + case EJIT_FLOAT: a.f = (float)x; break; case EJIT_DOUBLE: a.d = x; break; default: abort(); } @@ -223,21 +216,6 @@ double ejit_run_func_d(struct ejit_func *f, size_t argc, struct ejit_arg ejit_run_func(struct ejit_func *f, size_t argc, struct ejit_arg args[argc]); - -/* currently unused, the idea is that an escape could get the interpreter state - * and pass it on to speed up entering/exiting the VM, could be useful for more - * dynamic languages */ -struct interp_state; - -long ejit_run_func_ctx_i(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx); - -int64_t ejit_run_func_ctx_l(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx); - -float ejit_run_func_ctx_f(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx); - -double ejit_run_func_ctx_d(struct ejit_func *f, size_t argc, struct ejit_arg args[argc], struct interp_state *ctx); - - void ejit_destroy_func(struct ejit_func *s); #define EJIT_GPR(x) ((struct ejit_gpr){.r = (x)}) @@ -260,23 +238,23 @@ void ejit_destroy_func(struct ejit_func *s); .type = (t)}) #define EJIT_OPERAND_FLT(x, t) \ ((struct ejit_operand){ .kind = EJIT_OPERAND_FLT, \ - .r = (double)(x), \ + .d = (double)(x), \ .type = (t)}) /* maybe slight hack, but increase width to interpeter register width */ static inline struct ejit_arg ejit_i8(int8_t a) { - return (struct ejit_arg){.i64 = a, .type = EJIT_INT8}; + return (struct ejit_arg){.i8 = a, .type = EJIT_INT8}; } static inline struct ejit_arg ejit_i16(int16_t a) { - return (struct ejit_arg){.i64 = a, .type = EJIT_INT16}; + return (struct ejit_arg){.i16 = a, .type = EJIT_INT16}; } static inline struct ejit_arg ejit_i32(int32_t a) { - return (struct ejit_arg){.i64 = a, .type = EJIT_INT32}; + return (struct ejit_arg){.i32 = a, .type = EJIT_INT32}; } static inline struct ejit_arg ejit_i64(int64_t a) @@ -286,22 +264,22 @@ static inline struct ejit_arg ejit_i64(int64_t a) static inline struct ejit_arg ejit_u8(uint8_t a) { - return (struct ejit_arg){.i64 = a, .type = EJIT_UINT8}; + return (struct ejit_arg){.u8 = a, .type = EJIT_UINT8}; } static inline struct ejit_arg ejit_u16(uint16_t a) { - return (struct ejit_arg){.i64 = a, .type = EJIT_UINT16}; + return (struct ejit_arg){.u16 = a, .type = EJIT_UINT16}; } static inline struct ejit_arg ejit_u32(uint32_t a) { - return (struct ejit_arg){.i64 = a, .type = EJIT_UINT32}; + return (struct ejit_arg){.u32 = a, .type = EJIT_UINT32}; } static inline struct ejit_arg ejit_u64(uint64_t a) { - return (struct ejit_arg){.i64 = a, .type = EJIT_UINT64}; + return (struct ejit_arg){.u64 = a, .type = EJIT_UINT64}; } static inline struct ejit_arg ejit_pointer(void *p) @@ -387,6 +365,77 @@ static inline struct ejit_arg ejit_pointer_arg(void *p, size_t w) #define EJIT_AUTO(x) \ EJIT_ARG(x, typeof(x)) +static inline int64_t ejit_signed_param(size_t argc, const struct ejit_arg args[argc], + size_t idx, enum ejit_type type) +{ + assert(idx < argc); + assert(args[idx].type == type); + switch (type) { + case EJIT_INT64: return args[idx].i64; + case EJIT_INT32: return args[idx].i32; + case EJIT_INT16: return args[idx].i16; + case EJIT_INT8: return args[idx].i8; + default: abort(); + } + + return 0; +} + +static inline uint64_t ejit_unsigned_param(size_t argc, const struct ejit_arg args[argc], + size_t idx, enum ejit_type type) +{ + assert(idx < argc); + assert(args[idx].type == type); + switch (type) { + case EJIT_UINT64: return args[idx].u64; + case EJIT_UINT32: return args[idx].u32; + case EJIT_UINT16: return args[idx].u16; + case EJIT_UINT8: return args[idx].u8; + default: abort(); + } +} + +static inline float ejit_float_param(size_t argc, const struct ejit_arg args[argc], + size_t idx, enum ejit_type type) +{ + assert(idx < argc); + assert(args[idx].type == type && type == EJIT_FLOAT); + return args[idx].f; +} + +static inline double ejit_double_param(size_t argc, const struct ejit_arg args[argc], + size_t idx, enum ejit_type type) +{ + assert(idx < argc); + assert(args[idx].type == type && type == EJIT_DOUBLE); + return args[idx].d; +} + +static inline void *ejit_pointer_param(size_t argc, const struct ejit_arg args[argc], + size_t idx, enum ejit_type type) +{ + assert(idx < argc); + assert(args[idx].type == type && type == EJIT_POINTER); + return args[idx].p; +} + +#define EJIT_PARAM(argc, args, idx, t) \ + _Generic((t)(0), \ + signed char : ejit_signed_param, \ + signed short : ejit_signed_param, \ + signed int : ejit_signed_param, \ + signed long : ejit_signed_param, \ + signed long long : ejit_signed_param, \ + unsigned char : ejit_unsigned_param, \ + unsigned short : ejit_unsigned_param, \ + unsigned int : ejit_unsigned_param, \ + unsigned long : ejit_unsigned_param, \ + unsigned long long: ejit_unsigned_param, \ + float : ejit_float_param, \ + double : ejit_double_param, \ + default : ejit_pointer_param \ + )(argc, args, idx, EJIT_TYPE(t)) + static inline bool ejit_use64(struct ejit_arg a) { if (a.type == EJIT_INT64 || a.type == EJIT_UINT64) @@ -405,29 +454,39 @@ typedef double (*ejit_escape_d_t)(size_t argc, const struct ejit_arg args[argc]) struct ejit_label ejit_label(struct ejit_func *s); -void ejit_calli_i(struct ejit_func *s, struct ejit_func *f, size_t argc, - const struct ejit_operand args[argc]); +void ejit_tailr(struct ejit_func *s, struct ejit_gpr target, + size_t argc, const struct ejit_operand args[argc]); + +void ejit_taili(struct ejit_func *s, struct ejit_func *f, + size_t argc, const struct ejit_operand args[argc]); -void ejit_calli_l(struct ejit_func *s, struct ejit_func *f, size_t argc, - const struct ejit_operand args[argc]); +/* return type can be deduced */ +void ejit_calli(struct ejit_func *s, struct ejit_func *f, + size_t argc, const struct ejit_operand args[argc]); -void ejit_calli_f(struct ejit_func *s, struct ejit_func *f, size_t argc, - const struct ejit_operand args[argc]); +void ejit_callr_i(struct ejit_func *s, struct ejit_gpr target, + size_t argc, const struct ejit_operand args[argc]); -void ejit_calli_d(struct ejit_func *s, struct ejit_func *f, size_t argc, - const struct ejit_operand args[argc]); +void ejit_callr_l(struct ejit_func *s, struct ejit_gpr target, + size_t argc, const struct ejit_operand args[argc]); -void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f, size_t argc, - const struct ejit_operand args[argc]); +void ejit_callr_f(struct ejit_func *s, struct ejit_gpr target, + size_t argc, const struct ejit_operand args[argc]); -void ejit_escapei_l(struct ejit_func *s, ejit_escape_l_t f, size_t argc, - const struct ejit_operand args[argc]); +void ejit_callr_d(struct ejit_func *s, struct ejit_gpr target, + size_t argc, const struct ejit_operand args[argc]); -void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, size_t argc, - const struct ejit_operand args[argc]); +void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f, + size_t argc, const struct ejit_operand args[argc]); -void ejit_escapei_d(struct ejit_func *s, ejit_escape_d_t f, size_t argc, - const struct ejit_operand args[argc]); +void ejit_escapei_l(struct ejit_func *s, ejit_escape_l_t f, + size_t argc, const struct ejit_operand args[argc]); + +void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, + size_t argc, const struct ejit_operand args[argc]); + +void ejit_escapei_d(struct ejit_func *s, ejit_escape_d_t f, + size_t argc, const struct ejit_operand args[argc]); void ejit_ret(struct ejit_func *s); void ejit_retr(struct ejit_func *s, struct ejit_gpr r0); @@ -820,6 +879,15 @@ void ejit_truncr_d_32(struct ejit_func *s, struct ejit_gpr r0, void ejit_truncr_d_64(struct ejit_func *s, struct ejit_gpr r0, struct ejit_fpr r1); +void ejit_sqrtr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1); +void ejit_sqrtr_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1); + +void ejit_minr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2); +void ejit_minr_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2); + +void ejit_maxr_f(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2); +void ejit_maxr_d(struct ejit_func *s, struct ejit_fpr r0, struct ejit_fpr r1, struct ejit_fpr r2); + struct ejit_reloc ejit_bltr(struct ejit_func *s, struct ejit_gpr r0, struct ejit_gpr r1); struct ejit_reloc ejit_bner(struct ejit_func *s, struct ejit_gpr r0, |