Question about "Bound checking in row displays"
Jose E. Marchesi
jemarch@gnu.org
Tue Jun 23 22:11:07 GMT 2026
By the way, the note in the comment:
Note that this is always done at run-time, since the interpretation of
a row display depends on the target type, whether it is a row row or a
row of rows, for example.
is a bit silly (I wrote it 8-)).
On one side, we _do_ know the mode in the current strong syntactic
position, so that can be determined at compile-time, and a compile-error
can be emitted immediately.
But this doesn't mean run-time checks are not sometimes necessary.
Consider:
proc mount_matrix = ([]int a,b) [,]int:
begin
heap[3,3]int res := (a,b);
res
end
There both `a' and `b' are of mode []int, but the number of elments in
these multiples cannot be determined until run-time.
So you must consider both cases: compile-time check and run-time check.
> Hello Kanishka.
>
>> Hi,
>>
>> I'm planning to work on the "Bound checking in row displays" task next.
>>
>> While looking through the frontend, I found the row display lowering code in
>> gcc/algol68/a68-low-clauses.cc (a68_lower_collateral_clause), but I'm not
>> yet
>> sure what specific behavior is currently missing or incorrect.
>>
>> Is there a known testcase, example program, or area of the frontend
>> where the issue is expected to be addressed?
>
> Ok, so this is about doing run-time bound checking in row displays, like
> in:
>
> begin [3,3]int matrix := ((1,2,3),
> (4,5),
> (6,7,8));
> skip
> end
>
> And it basically corresponds to the XXX in
> a68-low-clauses.cc:a68_lower_collateral_clause:
>
> else
> {
> /* Check bounds of this sub-multiple. Note that this is
> always done at run-time, since the interpretation of a row
> display depens on the target type, whether it is a row row
> or a row of rows, for example. */
> // XXX use sub_multiple_lb, sub_multiple_ub and sub_multiple_stride
> }
>
> You can see an example of how to lower GENERIC code that checks bounds
> and calls the corresponding error routine in libga68 in
> a68-low-multiples.cc:a68_multiple_slice:
>
>
> ----
> tree slice = NULL_TREE;
> tree bounds_check = NULL_TREE;
>
> multiple = save_expr (multiple);
> tree index = NULL_TREE;
> for (int idx = 0; idx < num_indexes; ++idx)
> {
> tree lower_bound = a68_multiple_lower_bound (multiple, size_int (idx));
> tree index_expr = save_expr (indexes[idx]);
>
> /* Do run-time bound checking if requested. */
> if (OPTION_BOUNDS_CHECKING (&A68_JOB))
> {
> tree upper_bound = a68_multiple_upper_bound (multiple, size_int (idx));
> 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_expr),
> 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 dim_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_expr),
> lower_bound),
> fold_build2 (LE_EXPR, ssizetype,
> fold_convert (ssizetype,
> index_expr),
> upper_bound)));
> dim_bounds_check = fold_build2_loc (a68_get_node_location (p),
> TRUTH_ORIF_EXPR,
> ssizetype,
> dim_bounds_check, call);
>
> /* bounds_check_ok || call_runtime_error */
> if (bounds_check == NULL_TREE)
> bounds_check = dim_bounds_check;
> else
> bounds_check = fold_build2 (TRUTH_ANDIF_EXPR,
> ssizetype,
> bounds_check,
> dim_bounds_check);
> }
> ----
>
> Note how sub-expressions for checking the bounds in each slice dimension
> are generated, and they have the form:
>
> bounds_check_ok || call_runtime_error
>
> The runtime error routine is A68_LIBCALL_ARRAYBOUNDS. Note the
> information it gets: filename, line number, bounds that are out of
> bound.
>
> For checking row displays, you will want to add a new runtime error
> routine to libga68 so it can emit a proper message.
>
> Remember that a row-display is a collateral clause in a non-void strong
> syntactic position, and that it may be a "vacuum", i.e. ().
More information about the Algol68
mailing list