[COMMITTED] algol68: run-time bound checking of trimmers
Jose E. Marchesi
jemarch@gnu.org
Sun Mar 16 10:51:39 GMT 2025
This patch implements run-time bound checking (which can be controlled
with -f[no-]a68-bounds-checking) in trimmers.
Note that the bounds of trimmers resulting in flat multiples are not
checked, as mandated by the specification. Thus, given
[20]REAL reals;
Then reals[1000:] results in a flat multiple with bounds [1:0].
---
gcc/algol68/a68-low-multiples.cc | 56 ++++++++++++++++++++++++++++++++
gcc/algol68/a68-low-units.cc | 26 +++++++++++++--
gcc/algol68/a68.h | 1 +
3 files changed, 80 insertions(+), 3 deletions(-)
diff --git a/gcc/algol68/a68-low-multiples.cc b/gcc/algol68/a68-low-multiples.cc
index 0432bf56516..58ae45d59d7 100644
--- a/gcc/algol68/a68-low-multiples.cc
+++ b/gcc/algol68/a68-low-multiples.cc
@@ -802,3 +802,59 @@ a68_rows_upper_bound (tree rows, tree dim)
{
return rows_lower_or_upper_bound (rows, dim, true);
}
+
+/* Return a tree that checks whether the given INDEX falls within the bounds of
+ MULTIPLE in the rank DIM. If the provided index is out of bounds then a
+ call to the run-time function ARRAYBOUNDS is performed.
+
+ DIM must be a sizetype.
+ MULTIPLE must be a multiple value.
+ INDEX must be a ssizetype.
+
+ The parse tree node P is used as the source for the filename and line number
+ passed to the run-time function. */
+
+tree
+a68_multiple_bounds_check (NODE_T *p, tree dim,
+ tree multiple, tree index)
+{
+ index = save_expr (index);
+ multiple = save_expr (multiple);
+
+ tree upper_bound = a68_multiple_upper_bound (multiple, dim);
+ tree lower_bound = a68_multiple_lower_bound (multiple, dim);
+
+ /* Build the call to ARRAYBOUNDS. */
+ unsigned int lineno = NUMBER (LINE (INFO (p)));
+ const char *filename_str = FILENAME (LINE (INFO (p)));
+ tree filename = build_string_literal (strlen (filename_str) + 1,
+ filename_str);
+ tree call = a68_build_libcall (A68_LIBCALL_ARRAYBOUNDS,
+ void_type_node, 5,
+ filename,
+ build_int_cst (unsigned_type_node, lineno),
+ fold_convert (ssizetype, index),
+ fold_convert (ssizetype, lower_bound),
+ fold_convert (ssizetype, upper_bound));
+ call = fold_build2 (COMPOUND_EXPR, a68_bool_type, call, boolean_false_node);
+
+ /* If LB > UB, the dimension contains no elements.
+ Otherwise, it must hold IDX >= LB && IDX <= UB */
+ tree bounds_check = fold_build2 (TRUTH_AND_EXPR, sizetype,
+ fold_build2 (LE_EXPR, ssizetype,
+ lower_bound, upper_bound),
+ fold_build2 (TRUTH_AND_EXPR,
+ boolean_type_node,
+ fold_build2 (GE_EXPR, ssizetype,
+ fold_convert (ssizetype,
+ index),
+ lower_bound),
+ fold_build2 (LE_EXPR, ssizetype,
+ fold_convert (ssizetype,
+ index),
+ upper_bound)));
+ return fold_build2_loc (a68_get_node_location (p),
+ TRUTH_ORIF_EXPR,
+ ssizetype,
+ bounds_check, call);
+}
diff --git a/gcc/algol68/a68-low-units.cc b/gcc/algol68/a68-low-units.cc
index 1c0381843fa..8505d8c6e39 100644
--- a/gcc/algol68/a68-low-units.cc
+++ b/gcc/algol68/a68-low-units.cc
@@ -451,7 +451,9 @@ lower_subscript_for_trimmers (NODE_T *p, LOW_CTX_T ctx,
tree dim_lower_bound = save_expr (a68_multiple_lower_bound (multiple, size_dim));
tree stride = save_expr (a68_multiple_stride (multiple, size_dim));
- /* XXX validate bounds. */
+ /* Validate bounds. */
+ if (OPTION_BOUNDS_CHECKING (&A68_JOB))
+ a68_add_stmt (a68_multiple_bounds_check (p, size_dim, multiple, unit));
/* new_elements += i * strides[dim] */
tree offset = fold_build2 (MULT_EXPR, sizetype,
@@ -540,8 +542,26 @@ lower_subscript_for_trimmers (NODE_T *p, LOW_CTX_T ctx,
}
/* Now lower_bound, upper_bound and at all have their appropriate
- values. First validate bounds. */
- // XXX validate bounds
+ values. First validate bounds, but note that bounds of a trim
+ [a:b] should only be checked if a <= b. Otherwise the result of
+ the trim is a flat array and bound checking shouln't be
+ performed. */
+ if (OPTION_BOUNDS_CHECKING (&A68_JOB))
+ {
+ tree is_flat = fold_build2 (GT_EXPR, ssizetype,
+ lower_bound, upper_bound);
+ tree bound_check
+ = fold_build2 (TRUTH_ORIF_EXPR, integer_type_node,
+ is_flat,
+ fold_build2 (COMPOUND_EXPR, integer_type_node,
+ a68_multiple_bounds_check (p, size_dim,
+ multiple,
+ lower_bound),
+ a68_multiple_bounds_check (p, size_dim,
+ multiple,
+ upper_bound)));
+ a68_add_stmt (bound_check);
+ }
/* new_elements += i * strides[dim] */
tree stride = save_expr (a68_multiple_stride (multiple, size_dim));
diff --git a/gcc/algol68/a68.h b/gcc/algol68/a68.h
index 74c0f53592f..6fdcd2a0780 100644
--- a/gcc/algol68/a68.h
+++ b/gcc/algol68/a68.h
@@ -623,6 +623,7 @@ tree a68_rows_dim (tree exp);
tree a68_rows_value (tree multiple);
tree a68_rows_lower_bound (tree rows, tree dim);
tree a68_rows_upper_bound (tree rows, tree dim);
+tree a68_multiple_bounds_check (NODE_T *p, tree dim, tree multiple, tree index);
/* a68-low-ranges.cc */
--
2.30.2
More information about the Algol68
mailing list