diff options
author | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-04-10 22:23:08 +0300 |
---|---|---|
committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-04-10 22:23:08 +0300 |
commit | 7628ce2432108ae6306457f242e7cc3ac75b9ac0 (patch) | |
tree | 32a7b59f0e91b4c82bdeb4de3f75c1a04cc247da /tests | |
parent | 0ba52d9043985baff61d4fae225420274d9ad9ab (diff) | |
parent | 531d307d310881e69efc8ae8c8119f5f5799e0f9 (diff) | |
download | ejit-7628ce2432108ae6306457f242e7cc3ac75b9ac0.tar.gz ejit-7628ce2432108ae6306457f242e7cc3ac75b9ac0.zip |
Diffstat (limited to 'tests')
-rw-r--r-- | tests/calli.c | 41 | ||||
-rw-r--r-- | tests/callr_i.c | 42 | ||||
-rw-r--r-- | tests/escapei_10.c | 30 | ||||
-rw-r--r-- | tests/escapei_double.c | 6 | ||||
-rw-r--r-- | tests/escapei_float.c | 6 | ||||
-rw-r--r-- | tests/escapei_immediate_10.c | 63 | ||||
-rw-r--r-- | tests/makefile | 44 | ||||
-rw-r--r-- | tests/maxr_d.c | 28 | ||||
-rw-r--r-- | tests/maxr_f.c | 28 | ||||
-rw-r--r-- | tests/minr_d.c | 28 | ||||
-rw-r--r-- | tests/minr_f.c | 28 | ||||
-rw-r--r-- | tests/sqrtr_d.c | 23 | ||||
-rw-r--r-- | tests/sqrtr_f.c | 23 | ||||
-rw-r--r-- | tests/taili.c | 39 | ||||
-rw-r--r-- | tests/tailr.c | 41 |
15 files changed, 425 insertions, 45 deletions
diff --git a/tests/calli.c b/tests/calli.c new file mode 100644 index 0000000..991e97d --- /dev/null +++ b/tests/calli.c @@ -0,0 +1,41 @@ +#include <ejit/ejit.h> +#include <assert.h> +#include "do_jit.h" + +struct ejit_func *compile(bool do_jit) +{ + struct ejit_operand operands[2] = { + EJIT_OPERAND_GPR(0, EJIT_TYPE(long)), + EJIT_OPERAND_GPR(1, EJIT_TYPE(long)) + }; + struct ejit_func *f = ejit_create_func(EJIT_TYPE(long), 2, operands); + ejit_addr(f, EJIT_GPR(0), EJIT_GPR(0), EJIT_GPR(1)); + ejit_retr(f, EJIT_GPR(0)); + ejit_select_compile_func(f, 2, 0, EJIT_USE64(long), do_jit, true); + return f; +} + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_func *target = compile(do_jit); + + struct ejit_operand operands[2] = { + EJIT_OPERAND_GPR(0, EJIT_TYPE(long)), + EJIT_OPERAND_GPR(1, EJIT_TYPE(long)) + }; + + struct ejit_func *f = ejit_create_func(EJIT_TYPE(long), 2, operands); + ejit_calli(f, target, 2, operands); + ejit_retval(f, EJIT_GPR(0)); + ejit_retr(f, EJIT_GPR(0)); + ejit_select_compile_func(f, 2, 0, EJIT_USE64(long), do_jit, true); + + assert(erfi2(f, + EJIT_ARG(42, long), + EJIT_ARG(69, long)) == 111); + + ejit_destroy_func(target); + ejit_destroy_func(f); +} diff --git a/tests/callr_i.c b/tests/callr_i.c new file mode 100644 index 0000000..00b5374 --- /dev/null +++ b/tests/callr_i.c @@ -0,0 +1,42 @@ +#include <ejit/ejit.h> +#include <assert.h> +#include "do_jit.h" + +struct ejit_func *compile(bool do_jit) +{ + struct ejit_operand operands[2] = { + EJIT_OPERAND_GPR(0, EJIT_TYPE(long)), + EJIT_OPERAND_GPR(1, EJIT_TYPE(long)) + }; + struct ejit_func *f = ejit_create_func(EJIT_TYPE(long), 2, operands); + ejit_addr(f, EJIT_GPR(0), EJIT_GPR(0), EJIT_GPR(1)); + ejit_retr(f, EJIT_GPR(0)); + ejit_select_compile_func(f, 2, 0, EJIT_USE64(long), do_jit, true); + return f; +} + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_func *target = compile(do_jit); + + struct ejit_operand operands[2] = { + EJIT_OPERAND_GPR(0, EJIT_TYPE(long)), + EJIT_OPERAND_GPR(1, EJIT_TYPE(long)) + }; + + struct ejit_func *f = ejit_create_func(EJIT_TYPE(long), 2, operands); + ejit_movi(f, EJIT_GPR(2), (uintptr_t)target); + ejit_callr_i(f, EJIT_GPR(2), 2, operands); + ejit_retval(f, EJIT_GPR(0)); + ejit_retr(f, EJIT_GPR(0)); + ejit_select_compile_func(f, 3, 0, EJIT_USE64(long), do_jit, true); + + assert(erfi2(f, + EJIT_ARG(42, long), + EJIT_ARG(69, long)) == 111); + + ejit_destroy_func(target); + ejit_destroy_func(f); +} diff --git a/tests/escapei_10.c b/tests/escapei_10.c index 4ae00b8..ec48df0 100644 --- a/tests/escapei_10.c +++ b/tests/escapei_10.c @@ -21,26 +21,16 @@ static int32_t func(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, static long escape_func(size_t argc, const struct ejit_arg args[argc]) { assert(argc == 10); - assert(args[0].type == EJIT_INT32); - assert(args[1].type == EJIT_INT32); - assert(args[3].type == EJIT_INT32); - assert(args[4].type == EJIT_INT32); - assert(args[5].type == EJIT_INT32); - assert(args[6].type == EJIT_INT32); - assert(args[7].type == EJIT_INT32); - assert(args[8].type == EJIT_INT32); - assert(args[9].type == EJIT_INT32); - - int32_t a = args[0].i32; - int32_t b = args[1].i32; - int32_t c = args[2].i32; - int32_t d = args[3].i32; - int32_t e = args[4].i32; - int32_t f = args[5].i32; - int32_t g = args[6].i32; - int32_t h = args[7].i32; - int32_t i = args[8].i32; - int32_t j = args[9].i32; + int32_t a = EJIT_PARAM(argc, args, 0, int32_t); + int32_t b = EJIT_PARAM(argc, args, 1, int32_t); + int32_t c = EJIT_PARAM(argc, args, 2, int32_t); + int32_t d = EJIT_PARAM(argc, args, 3, int32_t); + int32_t e = EJIT_PARAM(argc, args, 4, int32_t); + int32_t f = EJIT_PARAM(argc, args, 5, int32_t); + int32_t g = EJIT_PARAM(argc, args, 6, int32_t); + int32_t h = EJIT_PARAM(argc, args, 7, int32_t); + int32_t i = EJIT_PARAM(argc, args, 8, int32_t); + int32_t j = EJIT_PARAM(argc, args, 9, int32_t); return func(a, b, c, d, e, f, g, h, i, j); } diff --git a/tests/escapei_double.c b/tests/escapei_double.c index 6ea9f90..736e978 100644 --- a/tests/escapei_double.c +++ b/tests/escapei_double.c @@ -9,10 +9,8 @@ static double func(int32_t a, double b) { static double escape_func(size_t argc, const struct ejit_arg args[argc]) { assert(argc == 2); - assert(args[0].type == EJIT_INT32); - assert(args[1].type == EJIT_DOUBLE); - int32_t a = args[0].i32; - double b = args[1].d; + int32_t a = EJIT_PARAM(argc, args, 0, int32_t); + double b = EJIT_PARAM(argc, args, 1, double); return func(a, b); } diff --git a/tests/escapei_float.c b/tests/escapei_float.c index 7a1b923..7cdc30d 100644 --- a/tests/escapei_float.c +++ b/tests/escapei_float.c @@ -9,10 +9,8 @@ static float func(int32_t a, float b) { static float escape_func(size_t argc, const struct ejit_arg args[argc]) { assert(argc == 2); - assert(args[0].type == EJIT_INT32); - assert(args[1].type == EJIT_FLOAT); - int32_t a = args[0].i32; - float b = args[1].f; + int32_t a = EJIT_PARAM(argc, args, 0, int32_t); + float b = EJIT_PARAM(argc, args, 1, float); return func(a, b); } diff --git a/tests/escapei_immediate_10.c b/tests/escapei_immediate_10.c new file mode 100644 index 0000000..5517c35 --- /dev/null +++ b/tests/escapei_immediate_10.c @@ -0,0 +1,63 @@ +#include <ejit/ejit.h> +#include <assert.h> +#include "do_jit.h" + +static int32_t func(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, + int32_t f, int32_t g, int32_t h, int32_t i, int32_t j) +{ + assert(a == 0); + assert(b == 1); + assert(c == 2); + assert(d == 3); + assert(e == 4); + assert(f == 5); + assert(g == 6); + assert(h == 7); + assert(i == 8); + assert(j == 9); + return 42; +} + +static long escape_func(size_t argc, const struct ejit_arg args[argc]) +{ + assert(argc == 10); + int32_t a = EJIT_PARAM(argc, args, 0, int32_t); + int32_t b = EJIT_PARAM(argc, args, 1, int32_t); + int32_t c = EJIT_PARAM(argc, args, 2, int32_t); + int32_t d = EJIT_PARAM(argc, args, 3, int32_t); + int32_t e = EJIT_PARAM(argc, args, 4, int32_t); + int32_t f = EJIT_PARAM(argc, args, 5, int32_t); + int32_t g = EJIT_PARAM(argc, args, 6, int32_t); + int32_t h = EJIT_PARAM(argc, args, 7, int32_t); + int32_t i = EJIT_PARAM(argc, args, 8, int32_t); + int32_t j = EJIT_PARAM(argc, args, 9, int32_t); + return func(a, b, c, d, e, f, g, h, i, j); +} + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_func *f = ejit_create_func(EJIT_INT32, 0, NULL); + struct ejit_operand args[10] = { + EJIT_OPERAND_IMM(0, EJIT_INT32), + EJIT_OPERAND_IMM(1, EJIT_INT32), + EJIT_OPERAND_IMM(2, EJIT_INT32), + EJIT_OPERAND_IMM(3, EJIT_INT32), + EJIT_OPERAND_IMM(4, EJIT_INT32), + EJIT_OPERAND_IMM(5, EJIT_INT32), + EJIT_OPERAND_IMM(6, EJIT_INT32), + EJIT_OPERAND_IMM(7, EJIT_INT32), + EJIT_OPERAND_IMM(8, EJIT_INT32), + EJIT_OPERAND_IMM(9, EJIT_INT32), + }; + ejit_escapei_i(f, escape_func, 10, args); + ejit_retval(f, EJIT_GPR(0)); + ejit_retr(f, EJIT_GPR(0)); + + ejit_select_compile_func(f, 11, 0, false, do_jit, true); + + assert(ejit_run_func_i(f, 0, NULL) == 42); + + ejit_destroy_func(f); +} diff --git a/tests/makefile b/tests/makefile index 5aeef98..53115de 100644 --- a/tests/makefile +++ b/tests/makefile @@ -1,25 +1,35 @@ include ./tests.mk -LLVM ?= 0 -CROSS_COMPILE := -COMPILER != [ "$(LLVM)" != "0" ] \ - && echo clang --target="$(CROSS_COMPILE)" \ - || echo $(CROSS_COMPILE)gcc +LLVM ?= 0 +COMPILER != [ -n "$(CROSS_COMPILE)" ] \ + && { \ + [ "$(LLVM)" != "0" ] \ + && echo clang --target="$(CROSS_COMPILE)" \ + || echo $(CROSS_COMPILE)gcc \ + ; \ + } \ + || echo $(CC) -CFLAGS := -Wall -Wextra -O0 -g +RELEASE ?= 0 +OPTFLAGS != [ "$(RELEASE)" != "0" ] \ + && echo "-O2" \ + || echo "-O0" + +LTO ?= 0 +LTOFLAGS != [ "$(LTO)" != "0" ] \ + && echo "-flto=auto" + +DEBUG ?= 1 +DEBUGFLAGS != [ "$(DEBUG)" != "0" ] \ + && echo "-DDEBUG=1" \ + || echo "-DNDEBUG=1" + +OBFLAGS := -g +WARNFLAGS := -Wall -Wextra INCLUDE_FLAGS := -I include -COMPILE_TEST := $(COMPILER) $(CFLAGS) $(INCLUDE_FLAGS) +COMPILE_TEST := $(COMPILER) $(WARNFLAGS) $(OPTFLAGS) $(LTOFLAGS) \ + $(OBFLAGS) $(CFLAGS) $(DEBUGFLAGS) $(INCLUDE_FLAGS) .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!" diff --git a/tests/maxr_d.c b/tests/maxr_d.c new file mode 100644 index 0000000..3e35665 --- /dev/null +++ b/tests/maxr_d.c @@ -0,0 +1,28 @@ +#include <ejit/ejit.h> +#include <assert.h> +#include "do_jit.h" + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_operand operands[2] = { + EJIT_OPERAND_FPR(0, EJIT_TYPE(double)), + EJIT_OPERAND_FPR(1, EJIT_TYPE(double)) + }; + + struct ejit_func *f = ejit_create_func(EJIT_TYPE(double), 2, operands); + + ejit_maxr_d(f, EJIT_FPR(2), EJIT_FPR(0), EJIT_FPR(1)); + ejit_retr_d(f, EJIT_FPR(2)); + + ejit_select_compile_func(f, 0, 3, EJIT_USE64(double), do_jit, true); + + assert(erfd2(f, EJIT_ARG(42., double), EJIT_ARG(69., double) + ) == 69.); + + assert(erfd2(f, EJIT_ARG(-42., double), EJIT_ARG(-69., double) + ) == -42.); + + ejit_destroy_func(f); +} diff --git a/tests/maxr_f.c b/tests/maxr_f.c new file mode 100644 index 0000000..581f867 --- /dev/null +++ b/tests/maxr_f.c @@ -0,0 +1,28 @@ +#include <ejit/ejit.h> +#include <assert.h> +#include "do_jit.h" + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_operand operands[2] = { + EJIT_OPERAND_FPR(0, EJIT_TYPE(float)), + EJIT_OPERAND_FPR(1, EJIT_TYPE(float)) + }; + + struct ejit_func *f = ejit_create_func(EJIT_TYPE(float), 2, operands); + + ejit_maxr_f(f, EJIT_FPR(2), EJIT_FPR(0), EJIT_FPR(1)); + ejit_retr_f(f, EJIT_FPR(2)); + + ejit_select_compile_func(f, 0, 3, EJIT_USE64(float), do_jit, true); + + assert(erff2(f, EJIT_ARG(42., float), EJIT_ARG(69., float) + ) == 69.); + + assert(erff2(f, EJIT_ARG(-42., float), EJIT_ARG(-69., float) + ) == -42.); + + ejit_destroy_func(f); +} diff --git a/tests/minr_d.c b/tests/minr_d.c new file mode 100644 index 0000000..d0fb7c8 --- /dev/null +++ b/tests/minr_d.c @@ -0,0 +1,28 @@ +#include <ejit/ejit.h> +#include <assert.h> +#include "do_jit.h" + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_operand operands[2] = { + EJIT_OPERAND_FPR(0, EJIT_TYPE(double)), + EJIT_OPERAND_FPR(1, EJIT_TYPE(double)) + }; + + struct ejit_func *f = ejit_create_func(EJIT_TYPE(double), 2, operands); + + ejit_minr_d(f, EJIT_FPR(2), EJIT_FPR(0), EJIT_FPR(1)); + ejit_retr_d(f, EJIT_FPR(2)); + + ejit_select_compile_func(f, 0, 3, EJIT_USE64(double), do_jit, true); + + assert(erfd2(f, EJIT_ARG(42., double), EJIT_ARG(69., double) + ) == 42.); + + assert(erfd2(f, EJIT_ARG(-42., double), EJIT_ARG(-69., double) + ) == -69.); + + ejit_destroy_func(f); +} diff --git a/tests/minr_f.c b/tests/minr_f.c new file mode 100644 index 0000000..b02ec06 --- /dev/null +++ b/tests/minr_f.c @@ -0,0 +1,28 @@ +#include <ejit/ejit.h> +#include <assert.h> +#include "do_jit.h" + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_operand operands[2] = { + EJIT_OPERAND_FPR(0, EJIT_TYPE(float)), + EJIT_OPERAND_FPR(1, EJIT_TYPE(float)) + }; + + struct ejit_func *f = ejit_create_func(EJIT_TYPE(float), 2, operands); + + ejit_minr_f(f, EJIT_FPR(2), EJIT_FPR(0), EJIT_FPR(1)); + ejit_retr_f(f, EJIT_FPR(2)); + + ejit_select_compile_func(f, 0, 3, EJIT_USE64(float), do_jit, true); + + assert(erff2(f, EJIT_ARG(42., float), EJIT_ARG(69., float) + ) == 42.); + + assert(erff2(f, EJIT_ARG(-42., float), EJIT_ARG(-69., float) + ) == -69.); + + ejit_destroy_func(f); +} diff --git a/tests/sqrtr_d.c b/tests/sqrtr_d.c new file mode 100644 index 0000000..06e7894 --- /dev/null +++ b/tests/sqrtr_d.c @@ -0,0 +1,23 @@ +#include <ejit/ejit.h> +#include <assert.h> +#include "do_jit.h" + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_operand operands[1] = { + EJIT_OPERAND_FPR(0, EJIT_TYPE(double)), + }; + struct ejit_func *f = ejit_create_func(EJIT_TYPE(double), 1, operands); + + ejit_sqrtr_d(f, EJIT_FPR(0), EJIT_FPR(0)); + ejit_retr_d(f, EJIT_FPR(0)); + + ejit_select_compile_func(f, 0, 1, EJIT_USE64(double), do_jit, true); + + assert(erfd1(f, EJIT_ARG( 0.0, double)) == 0.0); + assert(erfd1(f, EJIT_ARG( 4.0, double)) == 2.0); + assert(erfd1(f, EJIT_ARG(-4.0, double)) + != erfd1(f, EJIT_ARG(-4.0, double))); // nan +} diff --git a/tests/sqrtr_f.c b/tests/sqrtr_f.c new file mode 100644 index 0000000..3baa00d --- /dev/null +++ b/tests/sqrtr_f.c @@ -0,0 +1,23 @@ +#include <ejit/ejit.h> +#include <assert.h> +#include "do_jit.h" + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_operand operands[1] = { + EJIT_OPERAND_FPR(0, EJIT_TYPE(float)), + }; + struct ejit_func *f = ejit_create_func(EJIT_TYPE(float), 1, operands); + + ejit_sqrtr_f(f, EJIT_FPR(0), EJIT_FPR(0)); + ejit_retr_f(f, EJIT_FPR(0)); + + ejit_select_compile_func(f, 0, 1, EJIT_USE64(float), do_jit, true); + + assert(erff1(f, EJIT_ARG( 0.0, float)) == 0.0); + assert(erff1(f, EJIT_ARG( 4.0, float)) == 2.0); + assert(erff1(f, EJIT_ARG(-4.0, float)) + != erff1(f, EJIT_ARG(-4.0, float))); // nan +} diff --git a/tests/taili.c b/tests/taili.c new file mode 100644 index 0000000..cc09f59 --- /dev/null +++ b/tests/taili.c @@ -0,0 +1,39 @@ +#include <ejit/ejit.h> +#include <assert.h> +#include "do_jit.h" + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_operand operands[2] = { + EJIT_OPERAND_GPR(0, EJIT_INT32), /* s */ + EJIT_OPERAND_GPR(1, EJIT_INT32) /* n */ + }; + + struct ejit_func *f = ejit_create_func(EJIT_INT32, 2, operands); + + /* n == 0, return s */ + struct ejit_reloc r = ejit_bnei(f, EJIT_GPR(1), 0); + ejit_retr(f, EJIT_GPR(0)); + ejit_patch(f, r, ejit_label(f)); + + /* s += n */ + ejit_addr(f, EJIT_GPR(0), EJIT_GPR(0), EJIT_GPR(1)); + + /* n -= 1 */ + ejit_subi(f, EJIT_GPR(1), EJIT_GPR(1), 1); + + struct ejit_operand args[2] = { + EJIT_OPERAND_GPR(0, EJIT_INT32), /* s */ + EJIT_OPERAND_GPR(1, EJIT_INT32) /* n */ + }; + ejit_taili(f, f, 2, args); + + ejit_select_compile_func(f, 2, 0, EJIT_USE64(uintptr_t), do_jit, true); + + /* arbitrary number but large enough to most likely cause a stack fault + * if the tail call leaks memory or something */ + assert((int32_t)erfi2(f, EJIT_ARG(0, int32_t), EJIT_ARG(1000000, int32_t)) == 1784293664); + ejit_destroy_func(f); +} diff --git a/tests/tailr.c b/tests/tailr.c new file mode 100644 index 0000000..69ad44b --- /dev/null +++ b/tests/tailr.c @@ -0,0 +1,41 @@ +#include <ejit/ejit.h> +#include <assert.h> +#include "do_jit.h" + +int main(int argc, char *argv[]) +{ + (void)argv; + bool do_jit = argc > 1; + struct ejit_operand operands[2] = { + EJIT_OPERAND_GPR(0, EJIT_INT32), /* s */ + EJIT_OPERAND_GPR(1, EJIT_INT32) /* n */ + }; + + struct ejit_func *f = ejit_create_func(EJIT_INT32, 2, operands); + + /* n == 0, return s */ + struct ejit_reloc r = ejit_bnei(f, EJIT_GPR(1), 0); + ejit_retr(f, EJIT_GPR(0)); + ejit_patch(f, r, ejit_label(f)); + + /* s += n */ + ejit_addr(f, EJIT_GPR(0), EJIT_GPR(0), EJIT_GPR(1)); + + /* n -= 1 */ + ejit_subi(f, EJIT_GPR(1), EJIT_GPR(1), 1); + + struct ejit_operand args[2] = { + EJIT_OPERAND_GPR(0, EJIT_INT32), /* s */ + EJIT_OPERAND_GPR(1, EJIT_INT32) /* n */ + }; + + ejit_movi(f, EJIT_GPR(2), (uintptr_t)f); + ejit_tailr(f, EJIT_GPR(2), 2, args); + + ejit_select_compile_func(f, 3, 0, EJIT_USE64(uintptr_t), do_jit, true); + + /* arbitrary number but large enough to most likely cause a stack fault + * if the tail call leaks memory or something */ + assert((int32_t)erfi2(f, EJIT_ARG(0, int32_t), EJIT_ARG(1000000, int32_t)) == 1784293664); + ejit_destroy_func(f); +} |