Commit 372d0019b3 for ffmpeg
commit 372d0019b34c44d814e1e27d5eaaacca337c0347
Author: Niklas Haas <git@haasn.dev>
Date: Thu Oct 22 19:55:59 2026 +0200
swscale/uops_macros_gen: add -nasm option
Additionally writes the uops as NASM macros to the given file, as one
DECL_<TYPE>_<UOP> macro per uop group invoking DECL_OP for each uop. This is
an alternative to running the C preprocessor over the C macros.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
diff --git a/libswscale/uops_macros_gen.c b/libswscale/uops_macros_gen.c
index b3286f2530..7ac33e8dc7 100644
--- a/libswscale/uops_macros_gen.c
+++ b/libswscale/uops_macros_gen.c
@@ -16,7 +16,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <errno.h>
#include <stdbool.h>
+#include <stdio.h>
#include <string.h>
#ifdef _WIN32
@@ -150,6 +152,19 @@ static int generate_entry_args(void *opaque, void *key)
return 0;
}
+static int generate_entry_nasm(void *opaque, void *key)
+{
+ const SwsUOp *ref = opaque;
+ const SwsUOp *uop = key;
+ AVBPrint *bp = ref->data.opaque;
+ char name[SWS_UOP_NAME_MAX];
+ ff_sws_uop_name(uop, name);
+ av_bprintf(bp, "\n DECL_OP %%1, %-40s, %-13s, %-24s, 0x%x",
+ name, pixel_types[uop->type].full, uop_names[uop->uop].full, uop->mask);
+ print_params(bp, uop, false);
+ return 0;
+}
+
struct EnumPriv {
struct AVTreeNode *root;
AVMutex lock;
@@ -339,6 +354,8 @@ fail:
return ret;
}
+#define BPRINT_STR(str) av_bprint_append_data(bp, str, strlen(str))
+
/**
* Generate a set of boilerplate C preprocessor macros for describing and
* programmatically iterating over all SwsUOps in the tree at `root`.
@@ -351,7 +368,6 @@ static int print_macros(struct AVTreeNode *root, char **out_str)
AVBPrint bprint, *const bp = &bprint;
av_bprint_init(bp, 0, AV_BPRINT_SIZE_UNLIMITED);
- #define BPRINT_STR(str) av_bprint_append_data(bp, str, strlen(str))
BPRINT_STR(
"/**\n"
" * This file is automatically generated. Do not edit manually.\n"
@@ -393,12 +409,80 @@ static int print_macros(struct AVTreeNode *root, char **out_str)
return av_bprint_finalize(bp, out_str);
}
+/**
+ * Generate the equivalent NASM macros, as one DECL_<TYPE>_<UOP> macro per
+ * uop group. Same return semantics as print_macros().
+ */
+static int print_nasm_macros(struct AVTreeNode *root, char **out_str)
+{
+ AVBPrint bprint, *const bp = &bprint;
+ av_bprint_init(bp, 0, AV_BPRINT_SIZE_UNLIMITED);
+
+ BPRINT_STR(
+";******************************************************************************\n"
+";* This file is automatically generated. Do not edit manually.\n"
+";* To regenerate, run: make fate-sws-uops-macros GEN=1\n"
+";*\n"
+";* Boilerplate helper macros, for template-based backends. Invoking\n"
+";* DECL_<TYPE>_<UOP> MACRO will instantiate, for every matching uop:\n"
+";* DECL_OP MACRO, NAME, TYPE, UOP, MASK, [PARAMS]\n"
+";* with parameters in struct order.\n"
+";******************************************************************************");
+
+ SwsUOp key = { .data.opaque = bp };
+ for (key.type = SWS_PIXEL_NONE + 1; key.type < SWS_PIXEL_TYPE_NB; key.type++) {
+ for (key.uop = SWS_UOP_INVALID + 1; key.uop < SWS_UOP_TYPE_NB; key.uop++) {
+ const char *macro = uop_names[key.uop].full + sizeof("SWS_UOP_") - 1;
+ const char *prefix = pixel_types[key.type].prefix;
+ av_bprintf(bp, "\n\n%%macro DECL_%s%s 1", prefix, macro);
+ av_tree_enumerate(root, &key, enum_type, generate_entry_nasm);
+ av_bprintf(bp, "\n%%endmacro");
+ }
+ }
+
+ return av_bprint_finalize(bp, out_str);
+}
+
+static int write_file(const char *path, const char *str)
+{
+ FILE *out = fopen(path, "wb");
+ if (!out) {
+ int ret = AVERROR(errno);
+ fprintf(stderr, "Failed to open %s: %s\n", path, av_err2str(ret));
+ return ret;
+ }
+
+ int ret = 0;
+ if (fputs(str, out) < 0 || fputc('\n', out) < 0)
+ ret = AVERROR(EIO);
+ if (fclose(out) != 0 && ret >= 0)
+ ret = AVERROR(errno);
+ return ret;
+}
+
+static int usage(void)
+{
+ fprintf(stderr, "Usage: uops_macros_gen [-nasm FILE]\n"
+ "Writes C macros to stdout, and optionally NASM macros to FILE\n");
+ return 1;
+}
+
int main(int argc, char **argv)
{
#ifdef _WIN32
_setmode(_fileno(stdout), _O_BINARY);
#endif
+ const char *nasm_path = NULL;
+ for (int i = 1; i < argc; i += 2) {
+ if (i + 1 >= argc)
+ return usage();
+ if (!strcmp(argv[i], "-nasm"))
+ nasm_path = argv[i + 1];
+ else
+ return usage();
+ }
+
struct AVTreeNode *root = NULL;
int ret = collect_uops(&root);
if (ret < 0)
@@ -409,6 +493,14 @@ int main(int argc, char **argv)
if (ret >= 0)
puts(macros);
av_free(macros);
+
+ if (ret >= 0 && nasm_path) {
+ ret = print_nasm_macros(root, ¯os);
+ if (ret >= 0)
+ ret = write_file(nasm_path, macros);
+ av_free(macros);
+ }
+
free_uops(&root);
return ret;
}