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