PR #23816 opened by Ramiro Polla (ramiro)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23816
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23816.patch

AVBPrint can be #include'd directly into aarch64/ops_asmgen so it can
keep working standalone. This move will help implementing runtime JIT
support for aarch64.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <[email protected]>


>From 9d3984af7ee74c8f2021e022dc97aa6b0382e4cb Mon Sep 17 00:00:00 2001
From: Ramiro Polla <[email protected]>
Date: Thu, 25 Jun 2026 19:30:59 +0200
Subject: [PATCH] swscale/aarch64/rasm: use AVBPrint instead of custom string
 functions

AVBPrint can be #include'd directly into aarch64/ops_asmgen so it can
keep working standalone. This move will help implementing runtime JIT
support for aarch64.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <[email protected]>
---
 libswscale/aarch64/ops_asmgen.c |  23 ++++-
 libswscale/aarch64/rasm.h       |   5 +-
 libswscale/aarch64/rasm_print.c | 177 +++++++++++++++-----------------
 3 files changed, 108 insertions(+), 97 deletions(-)

diff --git a/libswscale/aarch64/ops_asmgen.c b/libswscale/aarch64/ops_asmgen.c
index 20da4d5bcc..2346a26035 100644
--- a/libswscale/aarch64/ops_asmgen.c
+++ b/libswscale/aarch64/ops_asmgen.c
@@ -48,6 +48,7 @@
 #define av_free(p)       free(p)
 #define FFMAX(a,b) ((a) > (b) ? (a) : (b))
 #define FFMIN(a,b) ((a) > (b) ? (b) : (a))
+#define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24))
 
 static void av_freep(void *ptr)
 {
@@ -60,6 +61,17 @@ static void av_freep(void *ptr)
     }
 }
 
+static void *av_memdup(const void *p, size_t size)
+{
+    void *ptr = NULL;
+    if (p) {
+        ptr = av_malloc(size);
+        if (ptr)
+            memcpy(ptr, p, size);
+    }
+    return ptr;
+}
+
 #include "libavutil/dynarray.h"
 
 static void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size,
@@ -78,6 +90,8 @@ static void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, 
size_t elem_size,
     return tab_elem_data;
 }
 
+#include "libavutil/bprint.c"
+
 /*********************************************************************/
 #include "rasm.c"
 #include "rasm_print.c"
@@ -1514,8 +1528,11 @@ static int asmgen(void)
         return AVERROR(ENOMEM);
 
     SwsAArch64Context s = { .rctx = rctx };
+    AVBPrint bp;
     int ret;
 
+    av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
+
     /**
      * The entry point of the SwsOpFunc is the `process` function. The
      * first kernel function is called from `process`, and subsequent
@@ -1608,9 +1625,13 @@ static int asmgen(void)
     /* Print all rasm functions to stdout. */
     printf("#include \"libavutil/aarch64/asm.S\"\n");
     printf("\n");
-    ret = rasm_print(s.rctx, stdout);
+    ret = rasm_print(s.rctx, &bp);
+    if (ret < 0)
+        goto error;
+    fputs(bp.str, stdout);
 
 error:
+    av_bprint_finalize(&bp, NULL);
     rasm_free(&s.rctx);
     return ret;
 }
diff --git a/libswscale/aarch64/rasm.h b/libswscale/aarch64/rasm.h
index 2ced8d0e95..ac37efed86 100644
--- a/libswscale/aarch64/rasm.h
+++ b/libswscale/aarch64/rasm.h
@@ -27,6 +27,7 @@
 #include <stdio.h>
 
 #include "libavutil/attributes.h"
+#include "libavutil/bprint.h"
 #include "libavutil/avassert.h"
 
 /**
@@ -233,8 +234,8 @@ void rasm_annotate_next(RasmContext *rctx, const char 
*comment);
 void rasm_annotate_nextf(RasmContext *rctx, char *s, size_t n,
                          const char *fmt, ...) av_printf_format(4, 5);
 
-/* Emit the assembled IR as GNU assembler text to fp. */
-int rasm_print(RasmContext *rctx, FILE *fp);
+/* Emit the assembled IR as GNU assembler text to bp. */
+int rasm_print(RasmContext *rctx, AVBPrint *bp);
 
 /*********************************************************************/
 /* AArch64-specific */
diff --git a/libswscale/aarch64/rasm_print.c b/libswscale/aarch64/rasm_print.c
index ff870f8a27..c32edaa491 100644
--- a/libswscale/aarch64/rasm_print.c
+++ b/libswscale/aarch64/rasm_print.c
@@ -19,7 +19,10 @@
  */
 
 #include <stdarg.h>
+#include <string.h>
 
+#include "libavutil/bprint.h"
+#include "libavutil/error.h"
 #include "libavutil/mem.h"
 
 #include "rasm.h"
@@ -35,50 +38,37 @@
 #define INSTR_INDENT  8
 #define COMMENT_COL  56
 
-av_printf_format(3, 4)
-static int pos_fprintf(FILE *fp, int64_t *pos, const char *fmt, ...)
+static void indent_to(AVBPrint *bp, unsigned line_start, int col)
 {
-    int ret;
-    va_list args;
-    va_start(args, fmt);
-    ret = vfprintf(fp, fmt, args);
-    va_end(args);
-    if (ret >= 0)
-        *pos += ret;
-    return ret;
-}
-
-static void indent_to(FILE *fp, int64_t *pos, int64_t line_start, int col)
-{
-    int cur_col = *pos - line_start;
-    pos_fprintf(fp, pos, "%*s", FFMAX(col - cur_col, 1), "");
+    int cur_col = bp->len - line_start;
+    av_bprintf(bp, "%*s", FFMAX(col - cur_col, 1), "");
 }
 
 /*********************************************************************/
 /* RASM_OP_IMM */
 
-static void print_op_imm(FILE *fp, int64_t *pos, RasmOp op)
+static void print_op_imm(AVBPrint *bp, RasmOp op)
 {
-    pos_fprintf(fp, pos, "#%d", rasm_op_imm_val(op));
+    av_bprintf(bp, "#%d", rasm_op_imm_val(op));
 }
 
 /*********************************************************************/
 /* RASM_OP_LABEL */
 
 static void print_op_label(const RasmContext *rctx,
-                           FILE *fp, int64_t *pos,
+                           AVBPrint *bp,
                            RasmOp op, const int *local_labels)
 {
     int id = rasm_op_label_id(op);
     av_assert0(id >= 0 && id < rctx->num_labels);
     if (rctx->labels[id]) {
-        pos_fprintf(fp, pos, "%s", rctx->labels[id]);
+        av_bprintf(bp, "%s", rctx->labels[id]);
     } else {
         int local_id = local_labels[id];
         if (local_id < 0) {
-            pos_fprintf(fp, pos, "%db", -local_id);
+            av_bprintf(bp, "%db", -local_id);
         } else {
-            pos_fprintf(fp, pos, "%df",  local_id);
+            av_bprintf(bp, "%df",  local_id);
         }
     }
 }
@@ -86,19 +76,19 @@ static void print_op_label(const RasmContext *rctx,
 /*********************************************************************/
 /* AARCH64_OP_GPR */
 
-static void print_op_gpr(FILE *fp, int64_t *pos, RasmOp op)
+static void print_op_gpr(AVBPrint *bp, RasmOp op)
 {
     uint8_t n    = a64op_gpr_n(op);
     uint8_t size = a64op_gpr_size(op);
 
     if (n == 31) {
-        pos_fprintf(fp, pos, "%s", size == sizeof(uint32_t) ? "wsp" : "sp");
+        av_bprintf(bp, "%s", size == sizeof(uint32_t) ? "wsp" : "sp");
         return;
     }
 
     switch (size) {
-    case sizeof(uint32_t): pos_fprintf(fp, pos, "w%d", n); break;
-    case sizeof(uint64_t): pos_fprintf(fp, pos, "x%d", n); break;
+    case sizeof(uint32_t): av_bprintf(bp, "w%d", n); break;
+    case sizeof(uint64_t): av_bprintf(bp, "x%d", n); break;
     default:
         av_assert0(!"Invalid GPR size!");
     }
@@ -120,21 +110,21 @@ static char elem_type_char(uint8_t elem_size)
     return '\0';
 }
 
-static void print_vec_reg(FILE *fp, int64_t *pos,
+static void print_vec_reg(AVBPrint *bp,
                           uint8_t n, uint8_t el_count, uint8_t el_size, 
uint8_t idx_p1)
 {
     if (el_size == 0) {
-        pos_fprintf(fp, pos, "v%u", n);
+        av_bprintf(bp, "v%u", n);
     } else if (el_count != 0) {
-        pos_fprintf(fp, pos, "v%u.%d%c", n, el_count, elem_type_char(el_size));
+        av_bprintf(bp, "v%u.%d%c", n, el_count, elem_type_char(el_size));
     } else if (idx_p1) {
-        pos_fprintf(fp, pos, "v%u.%c[%u]", n, elem_type_char(el_size), idx_p1 
- 1);
+        av_bprintf(bp, "v%u.%c[%u]", n, elem_type_char(el_size), idx_p1 - 1);
     } else {
-        pos_fprintf(fp, pos, "%c%u", elem_type_char(el_size), n);
+        av_bprintf(bp, "%c%u", elem_type_char(el_size), n);
     }
 }
 
-static void print_op_vec(FILE *fp, int64_t *pos, RasmOp op)
+static void print_op_vec(AVBPrint *bp, RasmOp op)
 {
     uint8_t n        = a64op_vec_n(op);
     uint8_t el_count = a64op_vec_el_count(op);
@@ -142,31 +132,31 @@ static void print_op_vec(FILE *fp, int64_t *pos, RasmOp 
op)
     uint8_t num_regs = a64op_vec_num_regs(op);
 
     if (num_regs) {
-        pos_fprintf(fp, pos, "{");
+        av_bprintf(bp, "{");
         for (int i = 0; i < num_regs; i++) {
             if (i > 0)
-                pos_fprintf(fp, pos, ", ");
-            print_vec_reg(fp, pos, (n + i) & 0x1f, el_count, el_size, 0);
+                av_bprintf(bp, ", ");
+            print_vec_reg(bp, (n + i) & 0x1f, el_count, el_size, 0);
         }
-        pos_fprintf(fp, pos, "}");
+        av_bprintf(bp, "}");
     } else {
         uint8_t idx_p1 = a64op_vec_idx_p1(op);
-        print_vec_reg(fp, pos, n, el_count, el_size, idx_p1);
+        print_vec_reg(bp, n, el_count, el_size, idx_p1);
     }
 }
 
 /*********************************************************************/
 /* AARCH64_OP_BASE */
 
-static void print_base_reg(FILE *fp, int64_t *pos, uint8_t n)
+static void print_base_reg(AVBPrint *bp, uint8_t n)
 {
     if (n == 31)
-        pos_fprintf(fp, pos, "sp");
+        av_bprintf(bp, "sp");
     else
-        pos_fprintf(fp, pos, "x%d", n);
+        av_bprintf(bp, "x%d", n);
 }
 
-static void print_op_base(FILE *fp, int64_t *pos, RasmOp op)
+static void print_op_base(AVBPrint *bp, RasmOp op)
 {
     uint8_t n    = a64op_base_n(op);
     uint8_t mode = a64op_base_mode(op);
@@ -174,23 +164,23 @@ static void print_op_base(FILE *fp, int64_t *pos, RasmOp 
op)
 
     switch (mode) {
     case AARCH64_BASE_OFFSET: {
-        pos_fprintf(fp, pos, "[");
-        print_base_reg(fp, pos, n);
+        av_bprintf(bp, "[");
+        print_base_reg(bp, n);
         if (imm)
-            pos_fprintf(fp, pos, ", #%d]", imm);
+            av_bprintf(bp, ", #%d]", imm);
         else
-            pos_fprintf(fp, pos, "]");
+            av_bprintf(bp, "]");
         break;
     }
     case AARCH64_BASE_PRE:
-        pos_fprintf(fp, pos, "[");
-        print_base_reg(fp, pos, n);
-        pos_fprintf(fp, pos, ", #%d]!", imm);
+        av_bprintf(bp, "[");
+        print_base_reg(bp, n);
+        av_bprintf(bp, ", #%d]!", imm);
         break;
     case AARCH64_BASE_POST:
-        pos_fprintf(fp, pos, "[");
-        print_base_reg(fp, pos, n);
-        pos_fprintf(fp, pos, "], #%d", imm);
+        av_bprintf(bp, "[");
+        print_base_reg(bp, n);
+        av_bprintf(bp, "], #%d", imm);
         break;
     }
 }
@@ -226,36 +216,36 @@ static const char *cond_name(uint8_t cond)
     return cond_names[cond];
 }
 
-static void print_op_cond(FILE *fp, int64_t *pos, RasmOp op)
+static void print_op_cond(AVBPrint *bp, RasmOp op)
 {
-    pos_fprintf(fp, pos, "%s", cond_name(a64op_cond_val(op)));
+    av_bprintf(bp, "%s", cond_name(a64op_cond_val(op)));
 }
 
 /*********************************************************************/
 /* Instruction operands */
 
 static void print_op(const RasmContext *rctx,
-                     FILE *fp, int64_t *pos,
+                     AVBPrint *bp,
                      const int *local_labels, RasmOp op)
 {
     switch (rasm_op_type(op)) {
     case RASM_OP_IMM:
-        print_op_imm(fp, pos, op);
+        print_op_imm(bp, op);
         break;
     case RASM_OP_LABEL:
-        print_op_label(rctx, fp, pos, op, local_labels);
+        print_op_label(rctx, bp, op, local_labels);
         break;
     case AARCH64_OP_GPR:
-        print_op_gpr(fp, pos, op);
+        print_op_gpr(bp, op);
         break;
     case AARCH64_OP_VEC:
-        print_op_vec(fp, pos, op);
+        print_op_vec(bp, op);
         break;
     case AARCH64_OP_BASE:
-        print_op_base(fp, pos, op);
+        print_op_base(bp, op);
         break;
     case AARCH64_OP_COND:
-        print_op_cond(fp, pos, op);
+        print_op_cond(bp, op);
         break;
     default:
         av_assert0(0);
@@ -337,20 +327,20 @@ static const char *insn_name(int id)
 }
 
 static void print_node_insn(const RasmContext *rctx,
-                            FILE *fp, int64_t *pos, int64_t line_start,
+                            AVBPrint *bp, unsigned line_start,
                             const RasmNode *node,
                             const int *local_labels)
 {
-    indent_to(fp, pos, line_start, INSTR_INDENT);
+    indent_to(bp, line_start, INSTR_INDENT);
 
     int op_start = 0;
     if (node->insn.id == AARCH64_INSN_BCOND) {
-        pos_fprintf(fp, pos, "b.%-14s", 
cond_name(a64op_cond_val(node->insn.op[0])));
+        av_bprintf(bp, "b.%-14s", cond_name(a64op_cond_val(node->insn.op[0])));
         op_start = 1;
     } else if (rasm_op_type(node->insn.op[0]) == RASM_OP_NONE) {
-        pos_fprintf(fp, pos, "%s", insn_name(node->insn.id));
+        av_bprintf(bp, "%s", insn_name(node->insn.id));
     } else {
-        pos_fprintf(fp, pos, "%-16s", insn_name(node->insn.id));
+        av_bprintf(bp, "%-16s", insn_name(node->insn.id));
     }
 
     for (int j = op_start; j < 4; j++) {
@@ -358,8 +348,8 @@ static void print_node_insn(const RasmContext *rctx,
         if (rasm_op_type(op) == RASM_OP_NONE)
             break;
         if (j != op_start)
-            pos_fprintf(fp, pos, ", ");
-        print_op(rctx, fp, pos, local_labels, op);
+            av_bprintf(bp, ", ");
+        print_op(rctx, bp, local_labels, op);
     }
 }
 
@@ -367,31 +357,31 @@ static void print_node_insn(const RasmContext *rctx,
 /* RASM_NODE_COMMENT */
 
 static void print_node_comment(const RasmContext *rctx,
-                               FILE *fp, int64_t *pos, int64_t line_start,
+                               AVBPrint *bp, unsigned line_start,
                                const RasmNode *node)
 {
-    indent_to(fp, pos, line_start, INSTR_INDENT);
-    pos_fprintf(fp, pos, "// %s", node->comment.text);
+    indent_to(bp, line_start, INSTR_INDENT);
+    av_bprintf(bp, "// %s", node->comment.text);
 }
 
 /*********************************************************************/
 /* RASM_NODE_LABEL */
 
 static void print_node_label(const RasmContext *rctx,
-                             FILE *fp, int64_t *pos, int64_t line_start,
+                             AVBPrint *bp, unsigned line_start,
                              const RasmNode *node,
                              int *local_labels)
 {
     int id = node->label.id;
     if (rctx->labels[id]) {
-        pos_fprintf(fp, pos, "%s:", rctx->labels[id]);
+        av_bprintf(bp, "%s:", rctx->labels[id]);
     } else {
         /* Local label. */
         int local_id = local_labels[id];
         if (local_id < 0) {
-            pos_fprintf(fp, pos, "%d:", -local_id);
+            av_bprintf(bp, "%d:", -local_id);
         } else {
-            pos_fprintf(fp, pos, "%d:",  local_id);
+            av_bprintf(bp, "%d:",  local_id);
             local_labels[id] = -local_id;
         }
     }
@@ -401,35 +391,35 @@ static void print_node_label(const RasmContext *rctx,
 /* RASM_NODE_FUNCTION */
 
 static void print_node_function(const RasmContext *rctx,
-                                FILE *fp, int64_t *pos, int64_t line_start,
+                                AVBPrint *bp, unsigned line_start,
                                 const RasmNode *node)
 {
-    pos_fprintf(fp, pos, "function %s, export=%d, jumpable=%d",
-                node->func.name, node->func.export, node->func.jumpable);
+    av_bprintf(bp, "function %s, export=%d, jumpable=%d",
+               node->func.name, node->func.export, node->func.jumpable);
 }
 
 /*********************************************************************/
 /* RASM_NODE_ENDFUNC */
 
 static void print_node_endfunc(const RasmContext *rctx,
-                               FILE *fp, int64_t *pos, int64_t line_start,
+                               AVBPrint *bp, unsigned line_start,
                                const RasmNode *node)
 {
-    pos_fprintf(fp, pos, "endfunc");
+    av_bprintf(bp, "endfunc");
 }
 
 /*********************************************************************/
 /* RASM_NODE_DIRECTIVE */
 
 static void print_node_directive(const RasmContext *rctx,
-                                 FILE *fp, int64_t *pos, int64_t line_start,
+                                 AVBPrint *bp, unsigned line_start,
                                  const RasmNode *node)
 {
-    pos_fprintf(fp, pos, "%s", node->directive.text);
+    av_bprintf(bp, "%s", node->directive.text);
 }
 
 /*********************************************************************/
-int rasm_print(RasmContext *rctx, FILE *fp)
+int rasm_print(RasmContext *rctx, AVBPrint *bp)
 {
     if (rctx->error)
         return rctx->error;
@@ -442,7 +432,6 @@ int rasm_print(RasmContext *rctx, FILE *fp)
             return AVERROR(ENOMEM);
     }
 
-    int64_t pos = 0;
     for (int i = 0; i < rctx->num_entries; i++) {
         const RasmEntry *entry = &rctx->entries[i];
 
@@ -460,40 +449,40 @@ int rasm_print(RasmContext *rctx, FILE *fp)
         }
 
         for (const RasmNode *node = entry->start; node != NULL; node = 
node->next) {
-            int64_t line_start = pos;
+            unsigned line_start = bp->len;
 
             switch (node->type) {
             case RASM_NODE_INSN:
-                print_node_insn(rctx, fp, &pos, line_start, node, 
local_labels);
+                print_node_insn(rctx, bp, line_start, node, local_labels);
                 break;
             case RASM_NODE_COMMENT:
-                print_node_comment(rctx, fp, &pos, line_start, node);
+                print_node_comment(rctx, bp, line_start, node);
                 break;
             case RASM_NODE_LABEL:
-                print_node_label(rctx, fp, &pos, line_start, node, 
local_labels);
+                print_node_label(rctx, bp, line_start, node, local_labels);
                 break;
             case RASM_NODE_FUNCTION:
-                print_node_function(rctx, fp, &pos, line_start, node);
+                print_node_function(rctx, bp, line_start, node);
                 break;
             case RASM_NODE_ENDFUNC:
-                print_node_endfunc(rctx, fp, &pos, line_start, node);
+                print_node_endfunc(rctx, bp, line_start, node);
                 break;
             case RASM_NODE_DIRECTIVE:
-                print_node_directive(rctx, fp, &pos, line_start, node);
+                print_node_directive(rctx, bp, line_start, node);
                 break;
             default:
                 break;
             }
 
             if (node->inline_comment) {
-                indent_to(fp, &pos, line_start, COMMENT_COL);
-                pos_fprintf(fp, &pos, "// %s", node->inline_comment);
+                indent_to(bp, line_start, COMMENT_COL);
+                av_bprintf(bp, "// %s", node->inline_comment);
             }
-            pos_fprintf(fp, &pos, "\n");
+            av_bprintf(bp, "\n");
 
             /* Add extra line after end of functions. */
             if (node->type == RASM_NODE_ENDFUNC)
-                pos_fprintf(fp, &pos, "\n");
+                av_bprintf(bp, "\n");
         }
     }
 
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to