/*
- * Copyright (C) 2012-2022 Free Software Foundation, Inc.
+ * Copyright (C) 2012-2023 Free Software Foundation, Inc.
*
* This file is part of GNU lightning.
*
# define HIDDEN /**/
#endif
+#if PACKED_STACK || STRONG_TYPE_CHECKING
+# define assert_arg_type(code, expect) \
+ do assert((code) == (expect)); while (0)
+# define assert_putarg_type(code, expect) \
+ do \
+ assert((((code) - jit_code_putargr_c) >> 2) == \
+ ((expect) - jit_code_arg_c)); \
+ while (0)
+#else
+# define assert_arg_type(code, expect) \
+ do assert((int)(code) == (int)(expect) || \
+ (code) == jit_code_arg); while (0)
+# define assert_putarg_type(code, expect) \
+ do \
+ assert(((((code) - jit_code_putargr_c) >> 2) == \
+ ((expect) - jit_code_arg_c)) || \
+ ((code) == jit_code_arg)); \
+ while (0)
+#endif
+
#define rc(value) jit_class_##value
#define rn(reg) (jit_regno(_rvs[jit_regno(reg)].spec))
# define JIT_RET _A0
# define JIT_FRET _FA0
typedef jit_uint64_t jit_regset_t;
+#elif defined(__loongarch__)
+# define JIT_RA0 _A0
+# define JIT_FA0 _FA0
+# define JIT_SP _SP
+# define JIT_RET _A0
+# define JIT_FRET _FA0
+typedef jit_uint64_t jit_regset_t;
#endif
#define jit_data(u,v,w) _jit_data(_jit,u,v,w)
(!jit_regset_tstbit(&_jitc->regarg, regno) && \
!jit_regset_tstbit(&_jitc->regsav, regno))
-#define jit_inc_synth(code) \
+#define jit_code_inc_synth(code) \
+ do { \
+ (void)jit_new_node(code); \
+ jit_synth_inc(); \
+ } while (0)
+#define jit_inc_synth(name) \
+ jit_code_inc_synth(jit_code_##name)
+#define jit_code_inc_synth_w(code, u) \
+ do { \
+ (void)jit_new_node_w(code, u); \
+ jit_synth_inc(); \
+ } while (0)
+#define jit_inc_synth_w(name, u) \
+ jit_code_inc_synth_w(jit_code_##name, u)
+#define jit_code_inc_synth_f(code, u) \
+ do { \
+ (void)jit_new_node_f(code, u); \
+ jit_synth_inc(); \
+ } while (0)
+#define jit_inc_synth_f(name, u) \
+ jit_code_inc_synth_f(jit_code_##name, u)
+#define jit_code_inc_synth_d(code, u) \
do { \
- (void)jit_new_node(jit_code_##code); \
+ (void)jit_new_node_d(code, u); \
jit_synth_inc(); \
} while (0)
-#define jit_inc_synth_w(code, u) \
+#define jit_inc_synth_d(name, u) \
+ jit_code_inc_synth_d(jit_code_##name, u)
+#define jit_code_inc_synth_ww(code, u, v) \
do { \
- (void)jit_new_node_w(jit_code_##code, u); \
+ (void)jit_new_node_ww(code, u, v); \
jit_synth_inc(); \
} while (0)
-#define jit_inc_synth_f(code, u) \
+#define jit_inc_synth_ww(name, u, v) \
+ jit_code_inc_synth_ww(jit_code_##name, u, v)
+#define jit_code_inc_synth_wp(code, u, v) \
do { \
- (void)jit_new_node_f(jit_code_##code, u); \
+ (void)jit_new_node_wp(code, u, v); \
jit_synth_inc(); \
} while (0)
-#define jit_inc_synth_d(code, u) \
+#define jit_inc_synth_wp(name, u, v) \
+ jit_code_inc_synth_wp(jit_code_##name, u, v)
+#define jit_code_inc_synth_fp(code, u, v) \
do { \
- (void)jit_new_node_d(jit_code_##code, u); \
+ (void)jit_new_node_fp(code, u, v); \
jit_synth_inc(); \
} while (0)
-#define jit_inc_synth_ww(code, u, v) \
+#define jit_inc_synth_fp(name, u, v) \
+ jit_code_inc_synth_fp(jit_code_##name, u, v)
+#define jit_code_inc_synth_dp(code, u, v) \
do { \
- (void)jit_new_node_ww(jit_code_##code, u, v); \
+ (void)jit_new_node_dp(code, u, v); \
jit_synth_inc(); \
} while (0)
-#define jit_inc_synth_wp(code, u, v) \
+#define jit_inc_synth_dp(name, u, v) \
+ jit_code_inc_synth_dp(jit_code_##name, u, v)
+#define jit_inc_synth_wf(name, u, v) \
+ jit_code_inc_synth_wf(jit_code_##name, u, v)
+#define jit_code_inc_synth_wf(code, u, v) \
do { \
- (void)jit_new_node_wp(jit_code_##code, u, v); \
+ (void)jit_new_node_wf(code, u, v); \
jit_synth_inc(); \
} while (0)
-#define jit_inc_synth_fp(code, u, v) \
+#define jit_inc_synth_wqf(name, u, v, w, x) \
do { \
- (void)jit_new_node_fp(jit_code_##code, u, v); \
+ (void)jit_new_node_wqf(jit_code_##name, u, v, w, x); \
jit_synth_inc(); \
} while (0)
-#define jit_inc_synth_dp(code, u, v) \
+#define jit_inc_synth_wd(name, u, v) \
+ jit_code_inc_synth_wd(jit_code_##name, u, v)
+#define jit_inc_synth_wqd(name, u, v, w, x) \
do { \
- (void)jit_new_node_dp(jit_code_##code, u, v); \
+ (void)jit_new_node_wqd(jit_code_##name, u, v, w, x); \
+ jit_synth_inc(); \
+ } while (0)
+#define jit_code_inc_synth_wd(code, u, v) \
+ do { \
+ (void)jit_new_node_wd(code, u, v); \
jit_synth_inc(); \
} while (0)
#define jit_dec_synth() jit_synth_dec()
+#define jit_link_alist(node) \
+ do { \
+ node->link = _jitc->function->alist; \
+ _jitc->function->alist = node; \
+ } while (0)
+#define jit_check_frame() \
+ do { \
+ if (!_jitc->function->need_frame) { \
+ _jitc->again = 1; \
+ _jitc->function->need_frame = 1; \
+ } \
+ } while (0)
+#define jit_diffsize() (stack_framesize - _jitc->framesize)
+#define jit_framesize() (stack_framesize - jit_diffsize())
+#define jit_selfsize() (_jitc->function->self.size - jit_diffsize())
+
#define jit_link_prolog() \
do { \
_jitc->tail->link = _jitc->function->prolog->link; \
#define jit_class_xpr 0x80000000 /* float / vector */
/* Used on sparc64 where %f0-%f31 can be encode for single float
* but %f32 to %f62 only as double precision */
-#define jit_class_sng 0x10000000 /* Single precision float */
-#define jit_class_dbl 0x20000000 /* Only double precision float */
+#define jit_class_sng 0x00010000 /* Single precision float */
+#define jit_class_dbl 0x00020000 /* Only double precision float */
#define jit_regno_patch 0x00008000 /* this is a register
* returned by a "user" call
* to jit_get_reg() */
#define jit_cc_a0_cnd 0x00000100 /* arg1 is a conditinally set register */
#define jit_cc_a1_reg 0x00000200 /* arg1 is a register */
#define jit_cc_a1_chg 0x00000400 /* arg1 is modified */
-#define jit_cc_a1_int 0x00001000 /* arg1 is immediate word */
-#define jit_cc_a1_flt 0x00002000 /* arg1 is immediate float */
-#define jit_cc_a1_dbl 0x00004000 /* arg1 is immediate double */
-#define jit_cc_a1_arg 0x00008000 /* arg1 is an argument node */
+#define jit_cc_a1_int 0x00000800 /* arg1 is immediate word */
+#define jit_cc_a1_flt 0x00001000 /* arg1 is immediate float */
+#define jit_cc_a1_dbl 0x00002000 /* arg1 is immediate double */
+#define jit_cc_a1_arg 0x00004000 /* arg1 is an argument node */
+#define jit_cc_a1_rlh 0x00008000 /* arg1 is a register pair */
#define jit_cc_a2_reg 0x00010000 /* arg2 is a register */
#define jit_cc_a2_chg 0x00020000 /* arg2 is modified */
#define jit_cc_a2_int 0x00100000 /* arg2 is immediate word */
} call;
jit_node_t *prolog;
jit_node_t *epilog;
+ jit_node_t *alist;
jit_int32_t *regoff;
jit_regset_t regset;
jit_int32_t stack;
+#if !defined(__arm__)
+ jit_int32_t cvt_offset; /* allocai'd offset for x87<->xmm or
+ * fpr<->gpr transfer using the stack */
+#endif
/* Helper for common jit generation pattern, used in GNU Smalltalk
* and possibly others, where a static frame layout is required or
jit_uint32_t define_frame : 1;
jit_uint32_t assume_frame : 1;
+ jit_uint32_t need_frame : 1; /* need frame pointer? */
+ jit_uint32_t need_stack : 1; /* need stack pointer? */
+ jit_uint32_t need_return : 1; /* not a leaf function */
+
/* alloca offset offset */
jit_int32_t aoffoff;
/* uses allocar flag */
jit_uint32_t allocar : 1;
+#if __arm__
+ /* If will, or might use float registers and vfp is not available.
+ * Use the first 64 bytes always, as the access to the virtual float
+ * registers use hardcoded instructions that can only reach 64 byte
+ * displacements, and to keep code simpler, do not use temporaries. */
+ jit_uint32_t swf_offset : 1;
+ /* If need to call C functions for some operation, or variadic function */
+ jit_uint32_t save_reg_args : 1;
+#endif
+
/* varargs state offsets */
jit_int32_t vaoff; /* offset of jit_va_list */
jit_int32_t vagp; /* first gp va argument */
jit_int32_t rout; /* first output register */
jit_int32_t breg; /* base register for prolog/epilog */
#endif
+#if __mips__
+ struct {
+ jit_int32_t op; /* pending instruction, candidate
+ * to be inserted in a delay slot */
+ jit_bool_t pend; /* non zero if need to emit op */
+ } inst;
+#endif
#if __mips__ || __ia64__ || __alpha__ || \
- (__sparc__ && __WORDSIZE == 64) || __riscv
+ (__sparc__ && __WORDSIZE == 64) || __riscv || __loongarch__
jit_int32_t carry;
#define jit_carry _jitc->carry
#endif
#endif
jit_uint32_t no_data : 1;
jit_uint32_t no_note : 1;
+ /* FIXME undocumented, might be moved to a jit_cpu field or a better
+ * configuration api.
+ * These are switches to a different unld* or unst*.
+ * Defaults are the algorithms that generate shorter code*/
+ jit_uint32_t unld_algorithm : 1;
+ jit_uint32_t unst_algorithm : 1;
+ jit_int32_t framesize; /* space for callee save registers,
+ * frame pointer and return address */
jit_int32_t reglen; /* number of registers */
jit_regset_t regarg; /* cannot allocate */
jit_regset_t regsav; /* automatic spill only once */
jit_regset_t reglive; /* known live registers at some point */
jit_regset_t regmask; /* register mask to update reglive */
+ jit_regset_t explive; /* explicitly marked as live */
struct {
jit_uint8_t *end;
} code;
struct {
jit_uint8_t *ptr;
jit_word_t length;
+ /* PROTECTED bytes starting at PTR are mprotect'd. */
+ jit_word_t protect;
} code;
struct {
jit_uint8_t *ptr;
extern void
_emit_stxi_d(jit_state_t*, jit_word_t, jit_int32_t, jit_int32_t);
-extern void jit_init_print(void);
-extern void jit_init_debug(const char*);
+extern void jit_init_print(FILE*);
+extern void jit_init_debug(const char*, FILE*);
extern void jit_finish_debug(void);
extern void jit_init_note(void);