diff options
Diffstat (limited to 'src/compiler')
| -rw-r--r-- | src/compiler/analyzer.zc | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/src/compiler/analyzer.zc b/src/compiler/analyzer.zc index c2ea867..d1f6f3d 100644 --- a/src/compiler/analyzer.zc +++ b/src/compiler/analyzer.zc @@ -533,6 +533,7 @@ int proven_n(int ix, int n) { // can own a block. then the size a pointer proof read can change. r[56] the // allocation facts of the locals at the loop entry (lafact_save), which the // loop top forgets. + int body_name(word r, int nm) { if (r[1] >= 32) { r[0] = 1; return 0; } r[2 + r[1]] = nm; r[1]++; @@ -542,6 +543,7 @@ int body_name(word r, int nm) { // an array local can (an owner frees what it held), and so can one to a name // the loop declares, unless a number type comes right before it (pk2, pv2: the // token before the name) + int body_mayfree(int nm, int pk2, int pv2) { int j = findloc(nm); word t; if (j < 0) return !(pk2 == T_ID && (pv2 == sx_int || pv2 == sx_char || pv2 == sx_bool || pv2 == sx_float)); @@ -552,6 +554,7 @@ int body_mayfree(int nm, int pk2, int pv2) { // the scan's view of the token before the current one and the one before that int bs_pk, bs_pv, bs_pk2, bs_pv2; // note what the current token says about the body, then read the next one + int bs_adv(word r) { int j; if (is_id(s_fn)) { peek(); if (pk_tk == T_OP && (pk_tv == s_lp || pk_tv == s_colon)) r[0] = 1; } @@ -564,6 +567,7 @@ int bs_adv(word r) { return 0; } // a bracketed group from the current ( [ or {, through its closer + int bs_group(word r) { int depth = 0; while (1) { @@ -577,6 +581,7 @@ int bs_group(word r) { } // one statement, read the way the parser will: a block, if/else, a loop or // switch with its body, do/while, or anything else up to its ; at depth 0 + int bs_stmt(word r) { int depth = 0; if (tk == T_EOF) { r[0] = 1; return 0; } @@ -619,6 +624,7 @@ int body_scan(word r) { return 0; } // may the loop body behind r change the local named nm? + int ldirty(word r, int nm) { int k = 0; if (!r || r[0]) return 1; @@ -627,6 +633,7 @@ int ldirty(word r, int nm) { } // a local nothing outside the function's own code can change: no address // taken, not captured by a closure + int lclean(int i) { if (laaddr[i]) return 0; if (local_cell && local_cell[i]) return 0; @@ -634,6 +641,7 @@ int lclean(int i) { return 1; } // a fresh record for the loop at depth k, or 0 past the first LPI_N depths + word linfo_new(int k) { word r; if (k >= LPI_N) return 0; @@ -644,6 +652,7 @@ word linfo_new(int k) { return r; } // the record of the live loop at depth k, or 0 + word linfo(int k) { word r; if (k >= LPI_N || !lpinfo) return 0; @@ -659,6 +668,7 @@ word linfo(int k) { // iterations that come first; the flag keeps the check where it was. emits // the load of the flag and the jump over the check; returns the hole to patch // past it, or -1 when the check cannot be hoisted. + int hoist_guard(int ix, int n, int arr) { int k = lsp, j; word r; if (ix < 0 || n <= 0) return 0 - 1; @@ -682,6 +692,7 @@ int hoist_guard(int ix, int n, int arr) { } // the loop entry of a loop with hoisted checks: each flag is 1 when ix < 0 or // bound > n, then on to the test at c0 + int hoist_stub(word r, int c0) { int k = 0; setlit(r[42], here); @@ -696,6 +707,7 @@ int hoist_stub(word r, int c0) { } // i < n for a pointer local arr to a block of n words: a loop test against a // constant of at most n, in a loop whose body leaves arr alone + int proven_p(int ix, int n, int arr) { int k = lsp, w; word r; while (k > loopbase) { @@ -709,6 +721,7 @@ int proven_p(int ix, int n, int arr) { return 0; } // the allocation facts of the function's locals, kept past the loop top that forgets them + word lafact_save() { word b; int i = lbase; if (dry || nloc <= lbase) return 0; @@ -718,6 +731,7 @@ word lafact_save() { } // after a loop that frees nothing: the locals its body left alone get back the // allocation facts the loop forgot + int lafact_keep(word r, word b) { int i; if (!b || dry || r[0] || r[55]) return 0; @@ -727,6 +741,7 @@ int lafact_keep(word r, word b) { } // the allocation fact of the pointer local bl at the entry of the innermost // loop over ix, or 0 + word entry_fact(int ix, int bl) { int k = lsp; word r, b; if (ix < 0 || bl < 0) return 0; @@ -743,6 +758,7 @@ word entry_fact(int ix, int bl) { // the number of elements behind a pointer local: the requested size of the // block it was set from, when the analyzer knows it (never a rounded block // size), for one-word elements; -1 when unknown + int ptr_elems(word f, word et, int bl) { word base; if (bl < 0 || !f || f[1] == 2 || f[0] < 0 || tbytes(et) || tsz(et) != 1) return 0 - 1; @@ -758,6 +774,7 @@ int ptr_elems(word f, word et, int bl) { // is in docs/SPEC.md. the reason codes: const int XC_NOT_LOOP = 1, XC_NOT_INVARIANT = 2, XC_NOT_LEN = 3, XC_SIZE = 4, XC_PACKED = 5, XC_HOISTED = 6, XC_MAYFREE = 7; // why a check of index ix (a local, or -1) into the array local arr stays + int xc_reason(int ix, int arr) { int k = lsp; word r; if (ix < 0) return XC_NOT_LOOP; @@ -774,6 +791,7 @@ int xc_reason(int ix, int arr) { } // the record of one kept check: kind 0 index, 1 pointer; the place of its [ // and, as the end, the token just read (its ]). src/lib/explain.zc writes it. + int xc_note(int kind, int why, int place) { int o1, o2, d = 0, k = loopbase, f; if (!xc_on || dry || cmode || incdepth > 0 || !xc_src || chbase != xc_src || !xc_hook) return 0; @@ -785,6 +803,7 @@ int xc_note(int kind, int why, int place) { } // is argument 1 --explain-checks? the file name for the records is argument 2. // then src/lib/explain.zc is compiled, and its note becomes the hook. + int xc_init() { int n = rt.syscall(rt.SYS_ARGC, 0, 0, 0), k, s, f; word b; if (n < 2) return 0; |
