diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 0000000..b12eab1 --- /dev/null +++ b/.dir-locals.el @@ -0,0 +1,2 @@ +((c-mode . ((tab-width . 4) + (indent-tabs-mode . t)))) diff --git a/.gitignore b/.gitignore index 9050e80..c0e0ed1 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ config.h *~ .direnv result -.cache \ No newline at end of file +.cache +.fuse_hidden* diff --git a/all.h b/all.h index 7e67bc0..078c1a0 100644 --- a/all.h +++ b/all.h @@ -159,12 +159,12 @@ enum J { #define JMPS(X) \ X(retw) X(retl) X(rets) X(retd) \ X(retsb) X(retub) X(retsh) X(retuh) \ - X(retc) X(ret0) X(jmp) X(jnz) \ + X(retc) X(ret0) X(jmp) X(jnz) \ X(jfieq) X(jfine) X(jfisge) X(jfisgt) \ X(jfisle) X(jfislt) X(jfiuge) X(jfiugt) \ X(jfiule) X(jfiult) X(jffeq) X(jffge) \ X(jffgt) X(jffle) X(jfflt) X(jffne) \ - X(jffo) X(jffuo) X(hlt) + X(jffo) X(jffuo) X(hlt) X(tail) #define X(j) J##j, JMPS(X) #undef X diff --git a/amd64/isel.c b/amd64/isel.c index 379244a..7201b09 100644 --- a/amd64/isel.c +++ b/amd64/isel.c @@ -602,7 +602,8 @@ seljmp(Blk *b, Fn *fn) if (b->jmp.type == Jret0 || b->jmp.type == Jjmp - || b->jmp.type == Jhlt) + || b->jmp.type == Jhlt + || b->jmp.type == Jtail) return; assert(b->jmp.type == Jjnz); r = b->jmp.arg; diff --git a/amd64/sysv.c b/amd64/sysv.c index 68f548c..da78cd9 100644 --- a/amd64/sysv.c +++ b/amd64/sysv.c @@ -167,7 +167,7 @@ argsclass(Ins *i0, Ins *i1, AClass *ac, int op, AClass *aret, Ref *env) nsse = 8; varc = 0; envc = 0; - for (i=i0, a=ac; iop - op + Oarg) { case Oarg: if (KBASE(i->cls) == 0) @@ -211,8 +211,9 @@ argsclass(Ins *i0, Ins *i1, AClass *ac, int op, AClass *aret, Ref *env) varc = 1; break; default: - die("unreachable"); + die("218 unreachable"); } + } if (varc && envc) err("sysv abi does not support variadic env calls"); @@ -686,7 +687,7 @@ amd64_sysv_abi(Fn *fn) continue; curi = &insb[NIns]; selret(b, fn); - for (i=&b->ins[b->nins]; i!=b->ins;) + for (i=&b->ins[b->nins]; i!=b->ins;) { switch ((--i)->op) { default: emiti(*i); @@ -706,8 +707,13 @@ amd64_sysv_abi(Fn *fn) break; case Oarg: case Oargc: - die("unreachable"); + if (b->jmp.type != Jtail) { + die("710 unreachable"); + } else { + + } } + } if (b == fn->start) for (; ral; ral=ral->link) emiti(ral->i); diff --git a/dump-enums.c b/dump-enums.c new file mode 100644 index 0000000..e69de29 diff --git a/flake.nix b/flake.nix index d8ff59a..992e1e4 100644 --- a/flake.nix +++ b/flake.nix @@ -34,12 +34,8 @@ gcc clang-analyzer clang-tools + gdbgui ]; - # shellHook = '' - # [[ ! -z "$LD_LIBRARY_PATH" ]] \ - # && export LD_LIBRARY_PATH=:$LD_LIBRARY_PATH - # export LD_LIBRARY_PATH="${self.packages.${system}.default.libllvm.lib}/lib$LD_LIBRARY_PATH" - # ''; }; }); }; diff --git a/main.c b/main.c index c413dc2..1afdfec 100644 --- a/main.c +++ b/main.c @@ -17,6 +17,7 @@ char debug['Z'+1] = { ['L'] = 0, /* liveness */ ['S'] = 0, /* spilling */ ['R'] = 0, /* reg. allocation */ + ['E'] = 0, /* enums */ }; extern Target T_amd64_sysv; diff --git a/parse.c b/parse.c index 5d8d039..799c427 100644 --- a/parse.c +++ b/parse.c @@ -53,6 +53,7 @@ enum Token { Tphi, Tjmp, Tjnz, + Ttail, Tret, Thlt, Texport, @@ -113,6 +114,7 @@ static char *kwmap[Ntok] = { [Tphi] = "phi", [Tjmp] = "jmp", [Tjnz] = "jnz", + [Ttail] = "tail", [Tret] = "ret", [Thlt] = "hlt", [Texport] = "export", @@ -664,6 +666,13 @@ parseline(PState ps) curb->jmp.arg = r; } goto Close; + case Ttail: + curb->jmp.type = Jtail; + curb->jmp.arg = parseref (); + /* Ins *restore = curi; */ + parserefl(1); + /* curi = restore; */ + goto Close; case Tjmp: curb->jmp.type = Jjmp; goto Jump; @@ -1434,6 +1443,11 @@ printfn(Fn *fn, FILE *f) if (b->s1 != b->link) fprintf(f, "\tjmp @%s\n", b->s1->name); break; + case Jtail: + fprintf (f, "\ttail "); + printref (b->jmp.arg, fn, f); + fprintf (f, "\n"); + break; default: fprintf(f, "\t%s ", jtoa[b->jmp.type]); if (b->jmp.type == Jjnz) { diff --git a/result b/result deleted file mode 120000 index 3e48ba1..0000000 --- a/result +++ /dev/null @@ -1 +0,0 @@ -/nix/store/662p38x2aqlrk0hnx0nskcj4100as900-qbe-git \ No newline at end of file diff --git a/test/call-factorial.ssa b/test/call-factorial.ssa new file mode 100644 index 0000000..70c3598 --- /dev/null +++ b/test/call-factorial.ssa @@ -0,0 +1,11 @@ +function w $factorial (w %n, w %acc) { +@start + jnz %n, @nz, @z +@z + ret %acc +@nz + %n_next =w sub %n, 1 + %acc_next =w mul %n, %acc + %r =w call $factorial (w %n_next, w %acc) + ret %r +} \ No newline at end of file diff --git a/test/tail.ssa b/test/tail.ssa new file mode 100644 index 0000000..44c6b6b --- /dev/null +++ b/test/tail.ssa @@ -0,0 +1,10 @@ +function w $factorial (w %n, w %acc) { +@start + jnz %n, @nz, @z +@z + ret %acc +@nz + %n_next =w sub %n, 1 + %acc_next =w mul %n, %acc + tail $factorial (w %n_next, w %acc) +} \ No newline at end of file diff --git a/util.c b/util.c index 00bd92b..8ba30d0 100644 --- a/util.c +++ b/util.c @@ -261,6 +261,7 @@ igroup(Blk *b, Ins *i, Ins **i0, Ins **i1) ib = b->ins; ie = ib + b->nins; + switch (i->op) { case Oblit0: *i0 = i; @@ -285,8 +286,12 @@ igroup(Blk *b, Ins *i, Ins **i0, Ins **i1) *i0 = i; for (; iop != Ocall; i++) ; - assert(i < ie); - *i1 = i + 1; + if (b->jmp.type == Jtail) { + *i1 = ie; + } else { + assert(i < ie); + *i1 = i + 1; + } return; case Osel1: for (; i>ib && (i-1)->op == Osel1; i--)