mesa/src/intel/executor/executor_macros.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

385 lines
9 KiB
C
Raw Normal View History

/*
* Copyright © 2024 Intel Corporation
* SPDX-License-Identifier: MIT
*/
#include <ctype.h>
#include <stdlib.h>
#include "util/ralloc.h"
#include "executor.h"
static bool
startswith(const char *prefix, const char *s)
{
return !strncmp(prefix, s, strlen(prefix));
}
static char *
skip_prefix(char *prefix, char *start)
{
assert(startswith(prefix, start));
char *c = start += strlen(prefix);
return c;
}
static bool
is_comment(const char *c)
{
assert(c);
return c[0] && c[0] == '/' && c[1] == '/';
}
typedef struct {
char **args;
int count;
} parse_args_result;
static parse_args_result
parse_args(void *mem_ctx, char *c)
{
parse_args_result r = {0};
while (*c) {
/* Skip spaces. */
while (*c && isspace(*c))
c++;
if (!*c || is_comment(c))
break;
char *start = c;
while (*c && !isspace(*c) && !is_comment(c))
c++;
r.args = reralloc_array_size(mem_ctx, r.args, sizeof(char *), r.count + 1);
r.args[r.count++] = ralloc_strndup(mem_ctx, start, c - start);
}
return r;
}
static void
executor_macro_mov(executor_context *ec, char **src, char *line)
{
char *c = skip_prefix("@mov", line);
parse_args_result r = parse_args(ec->mem_ctx, c);
if (r.count != 2)
failf("@mov needs 2 arguments, found %d\n", r.count);
const char *reg = r.args[0];
char *value = r.args[1];
const unsigned width = ec->devinfo->ver >= 20 ? 16 : 8;
if (strchr(value, '.')) {
union {
float f;
uint32_t u;
} val;
val.f = strtof(value, NULL);
ralloc_asprintf_append(src,
"mov (%u) %s:f 0x%08x:f\n",
width, reg, val.u);
} else {
for (char *x = value; *x; x++)
*x = tolower(*x);
ralloc_asprintf_append(src,
"mov (%u) %s %s\n",
width, reg, value);
}
}
static void
executor_macro_syncnop(executor_context *ec, char **src, char *line)
{
switch (ec->devinfo->verx10) {
case 90:
case 110: {
/* Not needed. */
break;
}
case 120: {
ralloc_strcat(src,
"(W) sync.nop (8) null {@1,$1.dst}\n");
break;
}
case 125:
case 200:
case 300: {
ralloc_strcat(src,
"(W) sync.nop (8) null {A@1,$1.dst}\n");
break;
}
default:
build: avoid redefining unreachable() which is standard in C23 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>
2025-07-23 09:17:35 +02:00
UNREACHABLE("invalid gfx version");
}
}
static void
executor_macro_eot(executor_context *ec, char **src, char *line)
{
switch (ec->devinfo->verx10) {
case 90:
case 110: {
ralloc_strcat(src,
"(W) mov (8) r127 r0\n"
"(W) send.ts (8) null r127:1 null:0 0x00000000 0x82000010 {EOT}\n");
break;
}
case 120: {
ralloc_strcat(src,
"(W) mov (8) r127 r0\n"
"(W) send.ts (8) null r127:1 null:0 0x00000000 0x02000000 {@1,EOT}\n");
break;
}
case 125: {
ralloc_strcat(src,
"(W) mov (8) r127 r0\n"
"(W) send.gtwy (8) null r127:1 null:0 0x00000000 0x02000000 {A@1,EOT}\n");
break;
}
case 200:
case 300: {
ralloc_strcat(src,
"(W) mov (16) r127 r0\n"
"(W) send.gtwy (16) null r127:1 null:0 0x00000000 0x02000000 {I@1,EOT}\n");
break;
}
default:
build: avoid redefining unreachable() which is standard in C23 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>
2025-07-23 09:17:35 +02:00
UNREACHABLE("invalid gfx version");
}
}
static void
executor_macro_id(executor_context *ec, char **src, char *line)
{
char *c = skip_prefix("@id", line);
parse_args_result r = parse_args(ec->mem_ctx, c);
if (r.count != 1)
failf("@id needs 1 argument, found %d\n", r.count);
const char *reg = r.args[0];
switch (ec->devinfo->verx10) {
case 90:
case 110:
case 120: {
ralloc_asprintf_append(src,
"(W) mov (8) r127:uw 0x76543210:v\n"
"(W) mov (8) %s r127:uw {@1}\n",
reg);
break;
}
case 125: {
ralloc_asprintf_append(src,
"(W) mov (8) r127:uw 0x76543210:v\n"
"(W) mov (8) %s r127:uw {A@1}\n",
reg);
break;
}
case 200:
case 300: {
ralloc_asprintf_append(src,
"(W) mov (8) r127:uw 0x76543210:v\n"
"(W) add (8) r127.8:uw r127:uw 8:uw {A@1}\n"
"(W) mov (16) %s r127:uw {A@1}\n",
reg);
break;
}
default:
build: avoid redefining unreachable() which is standard in C23 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>
2025-07-23 09:17:35 +02:00
UNREACHABLE("invalid gfx version");
}
}
static void
executor_macro_write(executor_context *ec, char **src, char *line)
{
char *c = skip_prefix("@write", line);
parse_args_result r = parse_args(ec->mem_ctx, c);
if (r.count != 2)
failf("@write needs 2 arguments, found %d\n", r.count);
const char *offset_reg = r.args[0];
const char *data_reg = r.args[1];
assert(ec->bo.data.addr <= 0xFFFFFFFF);
uint32_t base_addr = ec->bo.data.addr;
switch (ec->devinfo->verx10) {
case 90:
case 110:
case 120: {
const char *send_op = ec->devinfo->verx10 < 120 ? "sends.hdc1" : "send.hdc1";
ralloc_asprintf_append(src,
"mul (8) r127 %s 0x4:uw {@1}\n"
"add (8) r127 r127 0x%08x {@1}\n"
"%s (8) null r127:1 %s:1 0x00000040 0x02026efd {@1,$1}\n",
offset_reg, base_addr, send_op, data_reg);
executor_macro_syncnop(ec, src, "@syncnop");
break;
}
case 125: {
ralloc_asprintf_append(src,
"mul (8) r127 %s 0x4:uw {A@1}\n"
"add (8) r127 r127 0x%08x {A@1}\n"
"store.ugm.d32.a32 (8) null r127:1 %s:1 {A@1,$1}\n",
offset_reg, base_addr, data_reg);
executor_macro_syncnop(ec, src, "@syncnop");
break;
}
case 200:
case 300: {
ralloc_asprintf_append(src,
"mul (16) r127 %s 0x4:uw {A@1}\n"
"add (16) r127 r127 0x%08x {A@1}\n"
"store.ugm.d32.a32 (16) null r127:1 %s:1 {A@1,$1}\n",
offset_reg, base_addr, data_reg);
executor_macro_syncnop(ec, src, "@syncnop");
break;
}
default:
build: avoid redefining unreachable() which is standard in C23 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>
2025-07-23 09:17:35 +02:00
UNREACHABLE("invalid gfx version");
}
}
static void
executor_macro_read(executor_context *ec, char **src, char *line)
{
char *c = skip_prefix("@read", line);
parse_args_result r = parse_args(ec->mem_ctx, c);
if (r.count != 2)
failf("@read needs 2 arguments, found %d\n", r.count);
/* Order follows underlying SEND, destination first. */
const char *data_reg = r.args[0];
const char *offset_reg = r.args[1];
assert(ec->bo.data.addr <= 0xFFFFFFFF);
uint32_t base_addr = ec->bo.data.addr;
switch (ec->devinfo->verx10) {
case 90:
case 110:
case 120: {
const char *send_op = ec->devinfo->verx10 < 120 ? "sends.hdc1" : "send.hdc1";
ralloc_asprintf_append(src,
"mul (8) r127 %s 0x4:uw {@1}\n"
"add (8) r127 r127 0x%08x {@1}\n"
"%s (8) %s r127:1 null:0 0x00000000 0x02106efd {@1,$1}\n",
offset_reg, base_addr, send_op, data_reg);
executor_macro_syncnop(ec, src, "@syncnop");
break;
}
case 125: {
ralloc_asprintf_append(src,
"mul (8) r127 %s 0x4:uw {A@1}\n"
"add (8) r127 r127 0x%08x {A@1}\n"
"load.ugm.d32.a32 (8) %s:1 r127:1 {A@1,$1}\n",
offset_reg, base_addr, data_reg);
executor_macro_syncnop(ec, src, "@syncnop");
break;
}
case 200:
case 300: {
ralloc_asprintf_append(src,
"mul (16) r127 %s 0x4:uw {A@1}\n"
"add (16) r127 r127 0x%08x {A@1}\n"
"load.ugm.d32.a32 (16) %s:1 r127:1 {A@1,$1}\n",
offset_reg, base_addr, data_reg);
executor_macro_syncnop(ec, src, "@syncnop");
break;
}
default:
build: avoid redefining unreachable() which is standard in C23 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>
2025-07-23 09:17:35 +02:00
UNREACHABLE("invalid gfx version");
}
}
static char *
find_macro_symbol(char *line)
{
char *c = line;
while (isspace(*c)) c++;
return *c == '@' ? c : NULL;
}
static bool
match_macro_name(const char *name, const char *line)
{
if (!startswith(name, line))
return false;
line += strlen(name);
return !*line || isspace(*line) || is_comment(line);
}
const char *
executor_apply_macros(executor_context *ec, const char *original_src)
{
char *scratch = ralloc_strdup(ec->mem_ctx, original_src);
/* Create a ralloc'ed empty string so can call append to it later. */
char *src = ralloc_strdup(ec->mem_ctx, "");
/* TODO: Create a @send macro for common combinations of MsgDesc. */
static const struct {
const char *name;
void (*func)(executor_context *ec, char **output, char *line);
} macros[] = {
{ "@eot", executor_macro_eot },
{ "@mov", executor_macro_mov },
{ "@write", executor_macro_write },
{ "@read", executor_macro_read },
{ "@id", executor_macro_id },
{ "@syncnop", executor_macro_syncnop },
};
char *next = scratch;
while (next) {
char *line = next;
char *end = line;
while (*end && *end != '\n') end++;
next = *end ? end + 1 : NULL;
*end = '\0';
char *macro = find_macro_symbol(line);
if (!macro) {
ralloc_asprintf_append(&src, "%s\n", line);
} else {
bool found = false;
for (int i = 0; i < ARRAY_SIZE(macros); i++) {
if (match_macro_name(macros[i].name, macro)) {
macros[i].func(ec, &src, macro);
found = true;
break;
}
}
if (!found)
failf("unsupported macro line: %s", macro);
}
}
return src;
}