mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-22 13:08:09 +02:00
In the C23 standard unreachable() is now a predefined function-like macro in <stddef.h> See https://android.googlesource.com/platform/bionic/+/HEAD/docs/c23.md#is-now-a-predefined-function_like-macro-in And this causes build errors when building for C23: ----------------------------------------------------------------------- In file included from ../src/util/log.h:30, from ../src/util/log.c:30: ../src/util/macros.h:123:9: warning: "unreachable" redefined 123 | #define unreachable(str) \ | ^~~~~~~~~~~ In file included from ../src/util/macros.h:31: /usr/lib/gcc/x86_64-linux-gnu/14/include/stddef.h:456:9: note: this is the location of the previous definition 456 | #define unreachable() (__builtin_unreachable ()) | ^~~~~~~~~~~ ----------------------------------------------------------------------- So don't redefine it with the same name, but use the name UNREACHABLE() to also signify it's a macro. Using a different name also makes sense because the behavior of the macro was extending the one of __builtin_unreachable() anyway, and it also had a different signature, accepting one argument, compared to the standard unreachable() with no arguments. This change improves the chances of building mesa with the C23 standard, which for instance is the default in recent AOSP versions. All the instances of the macro, including the definition, were updated with the following command line: git grep -l '[^_]unreachable(' -- "src/**" | sort | uniq | \ while read file; \ do \ sed -e 's/\([^_]\)unreachable(/\1UNREACHABLE(/g' -i "$file"; \ done && \ sed -e 's/#undef unreachable/#undef UNREACHABLE/g' -i src/intel/isl/isl_aux_info.c Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36437>
111 lines
3.3 KiB
C
111 lines
3.3 KiB
C
/*
|
|
* Copyright © 2024 Collabora, Ltd.
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include "nir.h"
|
|
#include "nir_builder.h"
|
|
|
|
static bool
|
|
nir_lower_terminate_cf_list(nir_builder *b, struct exec_list *cf_list)
|
|
{
|
|
bool progress = false;
|
|
|
|
foreach_list_typed_safe(nir_cf_node, node, node, cf_list) {
|
|
switch (node->type) {
|
|
case nir_cf_node_block: {
|
|
nir_block *block = nir_cf_node_as_block(node);
|
|
|
|
nir_foreach_instr_safe(instr, block) {
|
|
if (instr->type != nir_instr_type_intrinsic)
|
|
continue;
|
|
|
|
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
|
|
switch (intrin->intrinsic) {
|
|
case nir_intrinsic_terminate: {
|
|
/* Everything after the terminate is dead */
|
|
nir_cf_list dead_cf;
|
|
nir_cf_extract(&dead_cf, nir_after_instr(&intrin->instr),
|
|
nir_after_cf_list(cf_list));
|
|
nir_cf_delete(&dead_cf);
|
|
|
|
intrin->intrinsic = nir_intrinsic_demote;
|
|
b->cursor = nir_after_instr(&intrin->instr);
|
|
nir_jump(b, nir_jump_halt);
|
|
|
|
/* We just removed the remainder of this list of CF nodes.
|
|
* It's not safe to continue iterating.
|
|
*/
|
|
return true;
|
|
}
|
|
|
|
case nir_intrinsic_terminate_if:
|
|
b->cursor = nir_before_instr(&intrin->instr);
|
|
nir_push_if(b, intrin->src[0].ssa);
|
|
{
|
|
nir_demote(b);
|
|
nir_jump(b, nir_jump_halt);
|
|
}
|
|
nir_instr_remove(&intrin->instr);
|
|
progress = true;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case nir_cf_node_if: {
|
|
nir_if *nif = nir_cf_node_as_if(node);
|
|
progress |= nir_lower_terminate_cf_list(b, &nif->then_list);
|
|
progress |= nir_lower_terminate_cf_list(b, &nif->else_list);
|
|
break;
|
|
}
|
|
|
|
case nir_cf_node_loop: {
|
|
nir_loop *loop = nir_cf_node_as_loop(node);
|
|
progress |= nir_lower_terminate_cf_list(b, &loop->body);
|
|
progress |= nir_lower_terminate_cf_list(b, &loop->continue_list);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
UNREACHABLE("Unknown CF node type");
|
|
}
|
|
}
|
|
|
|
return progress;
|
|
}
|
|
|
|
static bool
|
|
nir_lower_terminate_impl(nir_function_impl *impl)
|
|
{
|
|
nir_builder b = nir_builder_create(impl);
|
|
bool progress = nir_lower_terminate_cf_list(&b, &impl->body);
|
|
|
|
return nir_progress(progress, impl, nir_metadata_none);
|
|
}
|
|
|
|
/** Lowers nir_intrinsic_terminate to demote + halt
|
|
*
|
|
* The semantics of nir_intrinsic_terminate require that threads immediately
|
|
* exit. In SPIR-V, terminate is branch instruction even though it's only an
|
|
* intrinsic in NIR. This pass lowers terminate to demote + halt. Since halt
|
|
* is a jump instruction in NIR, this restores those semantics and NIR can
|
|
* reason about dead threads after a halt. It allows lets back-ends to only
|
|
* implement nir_intrinsic_demote as long as they also implement nir_jump_halt.
|
|
*/
|
|
bool
|
|
nir_lower_terminate_to_demote(nir_shader *nir)
|
|
{
|
|
bool progress = false;
|
|
|
|
nir_foreach_function_impl(impl, nir) {
|
|
if (nir_lower_terminate_impl(impl))
|
|
progress = true;
|
|
}
|
|
|
|
return progress;
|
|
}
|