[Mesa-dev] [PATCH 2/5] compiler/list: add and use for_range_list_safe

Ian Romanick idr at freedesktop.org
Tue May 10 23:31:45 UTC 2016


As time goes on, I become less and less a fan of the proliferation of
for_* macros... especially ones that are only used in one or two places.

On 05/07/2016 03:05 PM, Nicolai Hähnle wrote:
> From: Nicolai Hähnle <nicolai.haehnle at amd.com>
> 
> This macro avoids undefined behaviour that crashes gcc's ubsan.
> ---
>  src/compiler/glsl/list.h                  | 13 +++++++++++++
>  src/compiler/glsl/opt_dead_code_local.cpp |  7 +------
>  src/compiler/glsl/opt_tree_grafting.cpp   |  5 +----
>  3 files changed, 15 insertions(+), 10 deletions(-)
> 
> diff --git a/src/compiler/glsl/list.h b/src/compiler/glsl/list.h
> index 8da9514..12389aa 100644
> --- a/src/compiler/glsl/list.h
> +++ b/src/compiler/glsl/list.h
> @@ -716,4 +716,17 @@ inline void exec_node::insert_before(exec_list *before)
>             (((__node) = exec_node_data(__type, __cur, __field)) || true);  \
>             __cur = __prev, __prev = __prev->prev)
>  
> +/**
> + * Iterate over a range [begin, end) of nodes.
> + */
> +#define for_range_list_safe(__type, __node, __begin, __end) \
> +   for (__type *(__node), **__flag = &(__node); __flag; __flag = NULL) \
> +      for (struct exec_node *__cur = (__begin),                        \
> +                            *__next = __cur->next,                     \
> +                            *__end_stored = (__end);                   \
> +           __cur != __end_stored &&                                    \
> +           (((__node) = (__type *) __cur) || true);                    \
> +           __cur = __next, __next = __next->next)
> +
> +
>  #endif /* LIST_CONTAINER_H */
> diff --git a/src/compiler/glsl/opt_dead_code_local.cpp b/src/compiler/glsl/opt_dead_code_local.cpp
> index d38fd2b..5dd3bfd 100644
> --- a/src/compiler/glsl/opt_dead_code_local.cpp
> +++ b/src/compiler/glsl/opt_dead_code_local.cpp
> @@ -291,7 +291,6 @@ dead_code_local_basic_block(ir_instruction *first,
>  			     ir_instruction *last,
>  			     void *data)
>  {
> -   ir_instruction *ir, *ir_next;
>     /* List of avaialble_copy */
>     exec_list assignments;
>     bool *out_progress = (bool *)data;
> @@ -299,8 +298,7 @@ dead_code_local_basic_block(ir_instruction *first,
>  
>     void *ctx = ralloc_context(NULL);
>     /* Safe looping, since process_assignment */
> -   for (ir = first, ir_next = (ir_instruction *)first->next;;
> -	ir = ir_next, ir_next = (ir_instruction *)ir->next) {
> +   for_range_list_safe(ir_instruction, ir, first, last->next) {

In this case it seems like changing all the types to exec_node* and adding

         ir_instruction *ir = (ir_instruction *) node;

right here would be sufficient.

Unless you're able to hit a case where first or last isn't really an
ir_instruction.  If that's the case, there's a much bigger bug.

>        ir_assignment *ir_assign = ir->as_assignment();
>  
>        if (debug) {
> @@ -314,9 +312,6 @@ dead_code_local_basic_block(ir_instruction *first,
>  	 kill_for_derefs_visitor kill(&assignments);
>  	 ir->accept(&kill);
>        }
> -
> -      if (ir == last)
> -	 break;
>     }
>     *out_progress = progress;
>     ralloc_free(ctx);
> diff --git a/src/compiler/glsl/opt_tree_grafting.cpp b/src/compiler/glsl/opt_tree_grafting.cpp
> index a40e5f7..47fca7d 100644
> --- a/src/compiler/glsl/opt_tree_grafting.cpp
> +++ b/src/compiler/glsl/opt_tree_grafting.cpp
> @@ -347,11 +347,8 @@ tree_grafting_basic_block(ir_instruction *bb_first,
>  			  void *data)
>  {
>     struct tree_grafting_info *info = (struct tree_grafting_info *)data;
> -   ir_instruction *ir, *next;
>  
> -   for (ir = bb_first, next = (ir_instruction *)ir->next;
> -	ir != bb_last->next;
> -	ir = next, next = (ir_instruction *)ir->next) {

I think this could be fixed by changing next to be exec_node*.

> +   for_range_list_safe(ir_instruction, ir, bb_first, bb_last->next) {
>        ir_assignment *assign = ir->as_assignment();
>  
>        if (!assign)
> 



More information about the mesa-dev mailing list