aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2025-09-19 16:56:32 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2025-09-19 16:56:32 +0300
commitd567612fd6344204c6c8438b8fe7fe7dbd54d924 (patch)
treeaf8f09821c108718e8659a391aa1f12762d4fba8
parent798c891dc6ed0016810f7363bc5914764d3c0fc7 (diff)
downloadejit-d567612fd6344204c6c8438b8fe7fe7dbd54d924.tar.gz
ejit-d567612fd6344204c6c8438b8fe7fe7dbd54d924.zip
fix multiple labels at same instructionHEADmaster
-rw-r--r--src/compile/compile.c11
-rw-r--r--tests/z_double_label.c38
2 files changed, 43 insertions, 6 deletions
diff --git a/src/compile/compile.c b/src/compile/compile.c
index 2c72b91..f6bf144 100644
--- a/src/compile/compile.c
+++ b/src/compile/compile.c
@@ -2070,12 +2070,11 @@ static size_t compile_fn_body(struct ejit_func *f, jit_state_t *j, void *arena,
size_t label = 0;
for (size_t ii = 0; ii < insns_len(&f->insns); ++ii) {
/* if we've hit a label, add it to our vector of label addresses */
- if (label < labels_len(&f->labels)) {
- if (*labels_at(&f->labels, label) == ii) {
- compile_label(j, ii, &addrs);
- resolve_relocs(j, &relocs, &addrs, ii);
- label++;
- }
+ while (label < labels_len(&f->labels)
+ && *labels_at(&f->labels, label) == ii) {
+ compile_label(j, ii, &addrs);
+ resolve_relocs(j, &relocs, &addrs, ii);
+ label++;
}
struct ejit_insn i = *insns_at(&f->insns, ii);
diff --git a/tests/z_double_label.c b/tests/z_double_label.c
new file mode 100644
index 0000000..4817d8c
--- /dev/null
+++ b/tests/z_double_label.c
@@ -0,0 +1,38 @@
+#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_func *f = ejit_create_func(EJIT_INT32, 0, NULL);
+ ejit_movi(f, EJIT_GPR(0), 0);
+
+ struct ejit_reloc l1 = ejit_jmp(f);
+ struct ejit_label mid = ejit_label(f);
+ struct ejit_reloc l2 = ejit_jmp(f);
+
+ /* patch relocs to same address with two separate labels. */
+ ejit_patch(f, l1, ejit_label(f));
+ ejit_patch(f, l2, ejit_label(f));
+
+ /* we came from the first jump, jump to the end */
+ struct ejit_reloc end = ejit_beqi(f, EJIT_GPR(0), 1);
+
+ /* set r0 to 1 to indicate that we've done the first jump */
+ ejit_movi(f, EJIT_GPR(0), 1);
+
+ /* jump in between the two jumps */
+ ejit_patch(f, ejit_jmp(f), mid);
+
+ ejit_patch(f, end, ejit_label(f));
+ ejit_reti(f, 0);
+
+
+ ejit_select_compile_func(f, 1, 0, false, do_jit, true);
+
+ assert(ejit_run_func_i(f, 0, NULL) == 0);
+
+ ejit_destroy_func(f);
+}