nir/nir_lower_calls_to_builtins: trivially handle IA64 mangled functions

Using __attribute__((overloadable)) when declaring nir ops with
variable-width params in clc results in their symbol names being (IA64)
mangled; this change enables the mangled names to be handled when later
lowering the calls.

Signed-off-by: Simon Perretta <simon.perretta@imgtec.com>
Acked-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36873>
This commit is contained in:
Simon Perretta 2025-08-20 11:17:42 +01:00 committed by Marge Bot
parent 082f4b79ae
commit 880098158d

View file

@ -3,6 +3,7 @@
* SPDX-License-Identifier: MIT
*/
#include <ctype.h>
#include "nir.h"
#include "nir_builder.h"
@ -18,7 +19,7 @@
*
* Mangling allows for multiple definitions of the same instruction with
* different vector lengths and bit sizes. This could be combined with
* __attribute_((overloadable)) for seamless overloads.
* __attribute__((overloadable)) for seamless overloads.
*
* In effect, this pass re-implements nir_builder dynamically. This exposes
* low-level hardware intrinsics to internal driver programs. It is intended for
@ -97,9 +98,23 @@ lower(nir_builder *b, nir_instr *instr, void *data)
nir_call_instr *call = nir_instr_as_call(instr);
nir_function *func = call->callee;
const char *intr_name = func->name;
unsigned len = strlen(intr_name);
/* If the function name has been (IA64) mangled,
* parse out its length and unmangled name.
*/
if (!strncmp("_Z", intr_name, strlen("_Z")) && isdigit(intr_name[2])) {
char *endptr;
len = strtol(&intr_name[2], &endptr, 10);
intr_name = endptr;
}
const char *nir_prefix = "nir_";
const unsigned nir_prefix_len = strlen(nir_prefix);
/* We reserve all functions prefixed nir_* as builtins needing lowering. */
if (strncmp("nir_", func->name, strlen("nir_")) != 0)
if (strncmp(nir_prefix, intr_name, nir_prefix_len) != 0)
return false;
/* Strip the nir_ prefix to give the name of an ALU opcode or intrinsic. Also
@ -107,9 +122,9 @@ lower(nir_builder *b, nir_instr *instr, void *data)
* can recover vector lengths / bit sizes from the NIR. This implements a
* crude form of function overloading.
*/
const char *intr_name = func->name + strlen("nir_");
intr_name += nir_prefix_len;
const char *suffix = strstr(intr_name, "__");
unsigned len = (suffix != NULL) ? (suffix - intr_name) : strlen(intr_name);
len = (suffix != NULL) ? (suffix - intr_name) : (len - nir_prefix_len);
/* From this point on, we must not fail. Remove the call. */
b->cursor = nir_instr_remove(&call->instr);
@ -135,7 +150,7 @@ lower(nir_builder *b, nir_instr *instr, void *data)
}
/* We must have matched something! */
fprintf(stderr, "unknown opcode %s\n", func->name);
fprintf(stderr, "unknown opcode %.*s\n", len, intr_name);
UNREACHABLE("invalid nir opcode/intrinsic");
}