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>
This commit is contained in:
Niklas HaasandClaude Opus 5.5 authored and Niklas Haas committed 2026-10-25 02:23:01 +00:00
1 parent 5104bf0245
commit 372d0019b3
1 file changed
+93 -1
+93 -1
View File
@@ -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, &macros);
if (ret >= 0)
ret = write_file(nasm_path, macros);
av_free(macros);
}
free_uops(&root);
return ret;
}