Module: Mesa
Branch: master
Commit: a820eb537c3dd1e48e5f5d29d1b96c942e36416c
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=a820eb537c3dd1e48e5f5d29d1b96c942e36416c

Author: Connor Abbott <[email protected]>
Date:   Mon Mar  8 19:37:03 2021 +0100

ir3/parser: Support labels

This fixes the assembly for many scenarios where you want to use shader
replacement.

Note: unfortunately this leaks the identifier string created while
lexing, but I couldn't find a way to avoid leaking it except for
bringing in ralloc or something (which would be way more complicated).
The only other place doing something similar in mesa is the glsl parser,
which is using ralloc (actually a linear context).

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9463>

---

 src/freedreno/ir3/ir3.h        |  1 +
 src/freedreno/ir3/ir3_lexer.l  |  5 ++++-
 src/freedreno/ir3/ir3_parser.y | 40 +++++++++++++++++++++++++++++++++++++++-
 3 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h
index 50eee637ce2..c869844fa38 100644
--- a/src/freedreno/ir3/ir3.h
+++ b/src/freedreno/ir3/ir3.h
@@ -253,6 +253,7 @@ struct ir3_instruction {
                        char comp1, comp2;
                        int  immed;
                        struct ir3_block *target;
+                       const char *target_label;
                        brtype_t brtype;
                        unsigned idx;  /* for brac.N */
                } cat0;
diff --git a/src/freedreno/ir3/ir3_lexer.l b/src/freedreno/ir3/ir3_lexer.l
index 7d11ef4902f..4b6e46453fb 100644
--- a/src/freedreno/ir3/ir3_lexer.l
+++ b/src/freedreno/ir3/ir3_lexer.l
@@ -23,6 +23,7 @@
 
 %{
 #include <stdlib.h>
+#include "util/ralloc.h"
 #include "ir3/ir3.h"
 #include "ir3_parser.h"
 
@@ -30,6 +31,7 @@
 #define YY_NO_UNPUT
 #define TOKEN(t) (ir3_yylval.tok = t)
 extern YYSTYPE ir3_yylval;
+extern void *ir3_parser_dead_ctx;
 
 void ir3_yyset_input(FILE *f);
 
@@ -396,10 +398,11 @@ static int parse_w(const char *str)
 ">"                               return '>';
 "!"                               return '!';
 "#"                               return '#';
+":"                               return ':';
 
 "nan"                             return TOKEN(T_NAN);
 "inf"                             return TOKEN(T_INF);
 
-[a-zA-Z_][a-zA-Z_0-9]*            ir3_yylval.str = yytext;     return 
T_IDENTIFIER;
+[a-zA-Z_][a-zA-Z_0-9]*            ir3_yylval.str = 
ralloc_strdup(ir3_parser_dead_ctx, yytext); return T_IDENTIFIER;
 .                                 fprintf(stderr, "error at line %d: Unknown 
token: %s\n", ir3_yyget_lineno(), yytext); yyterminate();
 %%
diff --git a/src/freedreno/ir3/ir3_parser.y b/src/freedreno/ir3/ir3_parser.y
index 2766822a36f..1f936b57afa 100644
--- a/src/freedreno/ir3/ir3_parser.y
+++ b/src/freedreno/ir3/ir3_parser.y
@@ -66,6 +66,10 @@ static struct ir3_shader_variant *variant;
  */
 static struct ir3_block          *block;   /* current shader block */
 static struct ir3_instruction    *instr;   /* current instruction */
+static unsigned ip; /* current instruction pointer */
+static struct hash_table *labels;
+
+void *ir3_parser_dead_ctx;
 
 static struct {
        unsigned flags;
@@ -80,6 +84,12 @@ static struct {
 
 int ir3_yyget_lineno(void);
 
+static void new_label(const char *name)
+{
+       ralloc_steal(labels, (void *) name);
+       _mesa_hash_table_insert(labels, name, (void *)(uintptr_t)ip);
+}
+
 static struct ir3_instruction * new_instr(opc_t opc)
 {
        instr = ir3_instr_create(block, opc, 5);
@@ -88,6 +98,7 @@ static struct ir3_instruction * new_instr(opc_t opc)
        instr->nop = iflags.nop;
        instr->line = ir3_yyget_lineno();
        iflags.flags = iflags.repeat = iflags.nop = 0;
+       ip++;
        return instr;
 }
 
@@ -96,6 +107,9 @@ static void new_shader(void)
        variant->ir = ir3_create(variant->shader->compiler, variant);
        block = ir3_block_create(variant->ir);
        list_addtail(&block->node, &variant->ir->block_list);
+       ip = 0;
+       labels = _mesa_hash_table_create(variant, _mesa_hash_string, 
_mesa_key_string_equal);
+       ir3_parser_dead_ctx = ralloc_context(NULL);
 }
 
 static type_t parse_type(const char **type)
@@ -204,6 +218,24 @@ static void add_sysval(unsigned reg, unsigned compmask, 
gl_system_value sysval)
        variant->total_in++;
 }
 
+static bool resolve_labels(void)
+{
+       int instr_ip = 0;
+       foreach_instr (instr, &block->instr_list) {
+               if (opc_cat(instr->opc) == 0 && instr->cat0.target_label) {
+                       struct hash_entry *entry = 
_mesa_hash_table_search(labels, instr->cat0.target_label);
+                       if (!entry) {
+                               fprintf(stderr, "unknown label %s\n", 
instr->cat0.target_label);
+                               return false;
+                       }
+                       int target_ip = (uintptr_t)entry->data;
+                       instr->cat0.immed = target_ip - instr_ip;
+               }
+               instr_ip++;
+       }
+       return true;
+}
+
 #ifdef YYDEBUG
 int yydebug;
 #endif
@@ -229,10 +261,12 @@ struct ir3 * ir3_parse(struct ir3_shader_variant *v,
 #endif
        info = k;
        variant = v;
-       if (yyparse()) {
+       if (yyparse() || !resolve_labels()) {
                ir3_destroy(variant->ir);
                variant->ir = NULL;
        }
+       ralloc_free(labels);
+       ralloc_free(ir3_parser_dead_ctx);
        return variant->ir;
 }
 %}
@@ -670,6 +704,9 @@ instr:             iflags cat0_instr
 |                  iflags cat5_instr { fixup_cat5_s2en(); }
 |                  iflags cat6_instr
 |                  iflags cat7_instr
+|                  label
+
+label:             T_IDENTIFIER ':' { new_label($1); }
 
 cat0_src1:         '!' T_P0        { instr->cat0.inv1 = true; 
instr->cat0.comp1 = $2 >> 1; }
 |                  T_P0            { instr->cat0.comp1 = $1 >> 1; }
@@ -678,6 +715,7 @@ cat0_src2:         '!' T_P0        { instr->cat0.inv2 = 
true; instr->cat0.comp2
 |                  T_P0            { instr->cat0.comp2 = $1 >> 1; }
 
 cat0_immed:        '#' integer     { instr->cat0.immed = $2; }
+|                  '#' T_IDENTIFIER { ralloc_steal(instr, (void *)$2); 
instr->cat0.target_label = $2; }
 
 cat0_instr:        T_OP_NOP        { new_instr(OPC_NOP); }
 |                  T_OP_BR         { new_instr(OPC_B)->cat0.brtype = 
BRANCH_PLAIN; } cat0_src1 ',' cat0_immed

_______________________________________________
mesa-commit mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to