aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/expr.zc14
-rw-r--r--src/lsp/server.zc3
2 files changed, 10 insertions, 7 deletions
diff --git a/src/compiler/expr.zc b/src/compiler/expr.zc
index c76b74c..1536744 100644
--- a/src/compiler/expr.zc
+++ b/src/compiler/expr.zc
@@ -1322,12 +1322,14 @@ int range_jz(int ix, int src, int fld) {
return 0;
}
// the inline check of a fixed array T[n]: the index is on top of the stack and
-// stays there. one "outside" enhancement against the constant length and a
-// branch to the oob report, the same shape as range_jz.
+// stays there. i is outside 0..n-1 exactly when i | (n - 1 - i) is negative:
+// one subtract, one or and one compare, then a branch to the oob report. no
+// enhancement: the x86-64 jit calls one rather than inlining it.
int fixed_chk(int n) {
- int k = lookup(s_outside), j;
- if (k < 0 || skind[k] != K_ENH) return 0;
- lit(0); op(O_PICK); lit(n); op(XOP0 + sval[k]);
+ int j;
+ lit(0); op(O_PICK); lit(n - 1); op(O_SWAP); op(O_SUB);
+ lit(1); op(O_PICK); op(17);
+ lit(0); op(O_LT);
j = hole(); op(O_JZ);
lit(n); callname(s_oob);
setlit(j, here);
@@ -1753,7 +1755,7 @@ int bin(int minp) {
if (top) {
ft_nops++;
if (ft_nops > 1) ft_iv = -1;
- else if (bname[b] == s_lt && blen[b] > 0 && il >= 0 && ft_ir >= 0 && !lf && !rf && !ls && !rs) { ft_iv = il; ft_bd = ft_ir; }
+ else if (bname[b] == s_lt && blen[b] > 0 && il >= 0 && (ft_ir >= 0 || ft_ck >= 0) && !lf && !rf && !ls && !rs) { ft_iv = il; ft_bd = ft_ir; }
}
lv = 0; lvk = LV_NONE; c = C_PLAIN; xzero = 0; xconst = 0; xlenloc = -1; xstamp = 0; xaf = 0; xvk = 0;
effect_value = 0; if (isptr(xty) || xty == tword) effect_value = left_mask | right_mask;
diff --git a/src/lsp/server.zc b/src/lsp/server.zc
index 9a903f0..52e5e9a 100644
--- a/src/lsp/server.zc
+++ b/src/lsp/server.zc
@@ -391,7 +391,7 @@ int isopc(int c) {
// is the name n one of the words the highlighter shows as keywords even when the
// compiler has no record for it.
int iskeyword(int n) {
- return n == run.s_fn || n == run.s_var || n == run.s_const || n == run.s_else || n == run.s_as || n == run.s_unchecked || n == run.s_immediate
+ return n == run.s_fn || n == run.s_var || n == run.s_const || n == run.s_else || n == run.s_as || n == run.s_unchecked || n == run.s_unbounded || n == run.s_immediate
|| n == run.s_case || n == run.s_default || n == run.s_do || n == run.s_while || n == run.s_enum || n == run.s_include || n == run.s_memdebug
|| n == run.s_enhance || n == run.s_micro || n == run.s_vm || n == run.s_struct || n == run.s_type || n == run.s_typedef || n == run.s_typecheck || n == run.s_static;
}
@@ -1683,6 +1683,7 @@ char* kwtext() {
if (hname_is("const")) return "const [type] NAME = e / const fixed T[N] name~declares a compile-time constant or read-only storage. fixed and const may appear in either order; read-only storage cannot be modified or converted to a mutable reference.";
if (hname_is("else")) return "else~the other branch of an if. after an enhance's body, else names the fallback function that runs where the enhancement can't.";
if (hname_is("as")) return "e as T~changes the type of an expression without changing its bits.";
+ if (hname_is("unbounded")) return "unbounded fn f() { } / unbounded { } / unbounded;~turns index bounds checks off for a function, a block, a statement, or the rest of the unit. o3 code is unbounded too.";
if (hname_is("unchecked")) return "unchecked fn f() { } / unchecked { } / unchecked;~turns the lifetime analyzer off for a function, a block, or the rest of the unit. the code is not checked, so the analyzer's rules don't apply to it.";
if (hname_is("immediate")) return "immediate fn name() { }~a parse word. it runs during compilation whenever its name shows up as a statement, inside an expression or at the top level.";
if (hname_is("case")) return "case v:~a label in a switch. each case ends where the next one begins, so cases don't fall through.";