diff options
author | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-04-10 22:22:33 +0300 |
---|---|---|
committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-04-10 22:22:33 +0300 |
commit | 531d307d310881e69efc8ae8c8119f5f5799e0f9 (patch) | |
tree | 0038e06d042db954cd85f8b0076f5d1394a55421 | |
parent | be5c83ba8e57bc67beee41bc2c7227e6b8ebd9d5 (diff) | |
download | ejit-tail.tar.gz ejit-tail.zip |
improve tests a bittail
+ Runs tests on all arches that I have easy access to
-rw-r--r-- | Makefile | 125 | ||||
-rwxr-xr-x | scripts/gen-tests | 2 | ||||
-rw-r--r-- | src/compile/compile.c | 53 | ||||
-rw-r--r-- | src/interp.c | 2 | ||||
-rw-r--r-- | tests/makefile | 10 |
5 files changed, 157 insertions, 35 deletions
@@ -12,16 +12,121 @@ check: all @./scripts/gen-tests $$(echo tests/*.c) $(MAKE) -f tests/makefile check -# this kicks all unrecognised targets to the client script. -# note that trying to compile individual files, e.g. -# -# make kernel.elf -# -# will not work, you would need -# -# make -f scripts/makefile kernel.elf -# -# instead +# supported by jit +.PHONY: check_linux_amd64 +check_linux_amd64: + $(MAKE) clean + QEMU_LD_PREFIX=/usr/x86_64-linux-gnu \ + $(MAKE) ARCH=amd64 CROSS_COMPILE=x86_64-linux-gnu- check + +.PHONY: check_linux_x86 +check_linux_x86: + $(MAKE) clean + QEMU_LD_PREFIX=/usr/i686-linux-gnu \ + $(MAKE) ARCH=x86 CROSS_COMPILE=i686-linux-gnu- check + +.PHONY: check_linux_aarch64 +check_linux_aarch64: + $(MAKE) clean + QEMU_LD_PREFIX=/usr/aarch64-linux-gnu \ + $(MAKE) ARCH=aarch64 CROSS_COMPILE=aarch64-linux-gnu- check + +.PHONY: check_linux_armhf +check_linux_armhf: + $(MAKE) clean + QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf \ + $(MAKE) ARCH=armhf CROSS_COMPILE=arm-linux-gnueabihf- check + +.PHONY: check_linux_powerpc64le +check_linux_powerpc64le: + $(MAKE) clean + QEMU_LD_PREFIX=/usr/powerpc64le-linux-gnu \ + $(MAKE) ARCH=powerpc64le CROSS_COMPILE=powerpc64le-linux-gnu- check + +# note: older than revision 6 +.PHONY: check_linux_mips64el +check_linux_mips64el: + $(MAKE) clean + QEMU_LD_PREFIX=/usr/mips64el-linux-gnuabi64 \ + $(MAKE) ARCH=mips64el CROSS_COMPILE=mips64el-linux-gnuabi64- check + +.PHONY: check_linux_mipsel +check_linux_mipsel: + $(MAKE) clean + QEMU_LD_PREFIX=/usr/mipsel-linux-gnu \ + $(MAKE) ARCH=mipsel CROSS_COMPILE=mipsel-linux-gnu- check + +# not supported by jit atm +.PHONY: check_linux_powerpc64 +check_linux_powerpc64: + $(MAKE) clean + QEMU_LD_PREFIX=/usr/powerpc64-linux-gnu \ + $(MAKE) ARCH=powerpc64 CROSS_COMPILE=powerpc64-linux-gnu- check + +.PHONY: check_linux_powerpc +check_linux_powerpc: + $(MAKE) clean + QEMU_LD_PREFIX=/usr/powerpc-linux-gnu \ + $(MAKE) ARCH=powerpc CROSS_COMPILE=powerpc-linux-gnu- check + +.PHONY: check_linux_sparc64 +check_linux_sparc64: + $(MAKE) clean + QEMU_LD_PREFIX=/usr/sparc64-linux-gnu \ + $(MAKE) ARCH=sparc64 CROSS_COMPILE=sparc64-linux-gnu- check + +.PHONY: check_linux_riscv64 +check_linux_riscv64: + $(MAKE) clean + QEMU_LD_PREFIX=/usr/riscv64-linux-gnu \ + $(MAKE) ARCH=riscv64 CROSS_COMPILE=riscv64-linux-gnu- check + +.PHONY: check_linux_s390x +check_linux_s390x: + $(MAKE) clean + QEMU_LD_PREFIX=/usr/s390x-linux-gnu \ + $(MAKE) ARCH=s390x CROSS_COMPILE=s390x-linux-gnu- check + +.PHONY: check_linux_alpha +check_linux_alpha: + $(MAKE) clean + QEMU_LD_PREFIX=/usr/alpha-linux-gnu \ + $(MAKE) ARCH=alpha CROSS_COMPILE=alpha-linux-gnu- check + +.PHONY: check_linux_hppa +check_linux_hppa: + $(MAKE) clean + QEMU_LD_PREFIX=/usr/hppa-linux-gnu \ + $(MAKE) ARCH=hppa CROSS_COMPILE=hppa-linux-gnu- check + +.PHONY: check_linux_m68k +check_linux_m68k: + $(MAKE) clean + QEMU_LD_PREFIX=/usr/m68k-linux-gnu \ + $(MAKE) ARCH=m68k CROSS_COMPILE=m68k-linux-gnu- check + +.PHONY: check_linux +check_linux: + $(MAKE) check_linux_amd64 + $(MAKE) check_linux_x86 + $(MAKE) check_linux_aarch64 + $(MAKE) check_linux_armhf + $(MAKE) check_linux_powerpc64le + $(MAKE) check_linux_mips64el + $(MAKE) check_linux_mipsel + $(MAKE) check_linux_powerpc64 + $(MAKE) check_linux_powerpc + $(MAKE) check_linux_sparc64 + $(MAKE) check_linux_riscv64 + $(MAKE) check_linux_s390x + $(MAKE) check_linux_alpha + $(MAKE) check_linux_hppa + $(MAKE) check_linux_m68k + # compiler+emulator not available or broken + #$(MAKE) check_linux_hppa64 + #$(MAKE) check_linux_arc + #$(MAKE) check_linux_sh4 + .DEFAULT: setup $(MAKE) -f scripts/makefile $< diff --git a/scripts/gen-tests b/scripts/gen-tests index deac247..47ff9c9 100755 --- a/scripts/gen-tests +++ b/scripts/gen-tests @@ -12,4 +12,6 @@ do echo "-include ${dep}" >> tests.mk echo "${exe}: ${s} libejit.a" >> tests.mk echo " \$(COMPILE_TEST) ${s} libejit.a -o ${exe} -lm" >> tests.mk + echo " ./${exe} \t# bytecode" >> tests.mk + echo " ./${exe} 1\t# jit" >> tests.mk done diff --git a/src/compile/compile.c b/src/compile/compile.c index bfcb12d..5432bc1 100644 --- a/src/compile/compile.c +++ b/src/compile/compile.c @@ -52,6 +52,19 @@ static void assert_helper(const char *msg) assert(false && msg); } +static bool gpr_free(size_t argc, jit_operand_t args[argc], jit_gpr_t r) +{ + for (size_t i = 0; i < argc; ++i) { + if (args[i].kind != JIT_OPERAND_KIND_GPR) + continue; + + if (jit_gpr_regno(args[i].loc.gpr.gpr) == jit_gpr_regno(r)) + return false; + } + + return true; +} + static void free_arena(void *arena, size_t size) { munmap(arena, size); @@ -2489,7 +2502,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, * argument stack address */ jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R0) }; - compile_imm_call(j, &src, &dst, (void *)(uintptr_t)i.o, 2, args); + compile_imm_call(j, &src, &dst, (void *)i.p, 2, args); restore_caller_save_regs(f, j); operands_reset(&src); @@ -2502,7 +2515,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, /* a bit of copy-paste between this and the next func, * hmm */ assert(operands_len(&direct) <= 2); - struct ejit_func *f = (struct ejit_func *)(uintptr_t)i.o; + struct ejit_func *f = (struct ejit_func *)i.p; assert(f->direct_call); jit_operand_t regs[2] = { @@ -2560,32 +2573,44 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, (jit_imm_t)"trying to tail call interpreted function")); jit_patch_here(j, direct_reloc); #endif + size_t argc = operands_len(&direct); + /* r0 = target, r1 = arg1, r2 = arg2 */ jit_ldxi(j, JIT_R0, r, offsetof(struct ejit_func, direct_call)); - jit_operand_t regs[2] = { + jit_operand_t regs[3] = { jit_operand_gpr(JIT_OPERAND_ABI_WORD, JIT_R1), jit_operand_gpr(JIT_OPERAND_ABI_WORD, JIT_R2) }; - jit_move_operands(j, regs, direct.buf, operands_len(&direct)); + jit_move_operands(j, regs, direct.buf, argc); /* with args safely in registers, reset stack/state * while avoiding overwriting the call target */ - jit_gpr_t tmp = get_callr_temp(j); - jit_movr(j, tmp, JIT_R0); - int frame_size = j->frame_size; jit_shrink_stack(j, stack); jit_leave_jit_abi(j, gprs, fprs, frame); - /* now move args into place */ - jit_operand_t args[2] = {}; - foreach_vec(oi, direct) { + /* now move args into place, making sure we avoid our + * target register */ + jit_operand_t args[3] = {}; + for (size_t oi = 0; oi < argc; ++oi) { args[oi] = *operands_at(&direct, oi); } - jit_locate_args(j, operands_len(&direct), args); - jit_move_operands(j, args, regs, operands_len(&direct)); - jit_jmpr(j, tmp); + jit_locate_args(j, argc, args); + + /* we know that at least one gpr must be free */ + jit_gpr_t target = gpr_free(argc, args, JIT_R0) ? JIT_R0 + : gpr_free(argc, args, JIT_R1) ? JIT_R1 + : gpr_free(argc, args, JIT_R2) ? JIT_R2 + : (abort(), JIT_R0); + + /* move our target in JIT_R0 to whatever the free + * register is to avoid it being clobbered when we move + * the actual arguments */ + args[argc] = jit_operand_gpr(JIT_OPERAND_ABI_POINTER, target); + regs[argc] = jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R0); + jit_move_operands(j, args, regs, argc + 1); + jit_jmpr(j, target); j->frame_size = frame_size; operands_reset(&src); @@ -2641,7 +2666,7 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena, case EJIT_OP_CALLI: { save_caller_save_regs(f, j); - struct ejit_func *f = (struct ejit_func *)(uintptr_t)i.o; + struct ejit_func *f = (struct ejit_func *)i.p; #if __WORDSIZE != 64 assert(f->rtype != EJIT_INT64 && f->rtype != EJIT_UINT64); #endif diff --git a/src/interp.c b/src/interp.c index 6f94f98..894be30 100644 --- a/src/interp.c +++ b/src/interp.c @@ -1063,7 +1063,7 @@ top: DISPATCH(); DO(TAILI); - f = (struct ejit_func *)(uintptr_t)i.o; + f = (struct ejit_func *)i.p; assert(!f->direct_call && "trying to interpret compiled fun"); diff --git a/tests/makefile b/tests/makefile index 081170f..53115de 100644 --- a/tests/makefile +++ b/tests/makefile @@ -32,14 +32,4 @@ COMPILE_TEST := $(COMPILER) $(WARNFLAGS) $(OPTFLAGS) $(LTOFLAGS) \ .PHONY: check check: $(TESTS) - @echo "Running bytecode tests..." - @set -e; for test in $(TESTS); do \ - echo "Testing: $$test"; \ - ./$$test; \ - done - @echo "Running jit tests..." - @set -e; for test in $(TESTS); do \ - echo "Testing: $$test"; \ - ./$$test 1; \ - done @echo "Success!" |