xref: /aosp_15_r20/external/mesa3d/src/intel/compiler/brw_asm.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2018 Intel Corporation
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "brw_asm.h"
7 #include "brw_asm_internal.h"
8 #include "brw_disasm_info.h"
9 
10 /* TODO: Check if we can use bison/flex without globals. */
11 
12 extern FILE *yyin;
13 struct list_head instr_labels;
14 struct list_head target_labels;
15 
16 struct brw_codegen *p;
17 const char *input_filename;
18 int errors;
19 
20 static bool
i965_postprocess_labels()21 i965_postprocess_labels()
22 {
23    void *store = p->store;
24 
25    struct target_label *tlabel;
26    struct instr_label *ilabel, *s;
27 
28    const unsigned to_bytes_scale = brw_jump_scale(p->devinfo);
29 
30    LIST_FOR_EACH_ENTRY(tlabel, &target_labels, link) {
31       LIST_FOR_EACH_ENTRY_SAFE(ilabel, s, &instr_labels, link) {
32          if (!strcmp(tlabel->name, ilabel->name)) {
33             brw_inst *inst = store + ilabel->offset;
34 
35             int relative_offset = (tlabel->offset - ilabel->offset) / sizeof(brw_inst);
36             relative_offset *= to_bytes_scale;
37 
38             unsigned opcode = brw_inst_opcode(p->isa, inst);
39 
40             if (ilabel->type == INSTR_LABEL_JIP) {
41                switch (opcode) {
42                case BRW_OPCODE_IF:
43                case BRW_OPCODE_ELSE:
44                case BRW_OPCODE_ENDIF:
45                case BRW_OPCODE_WHILE:
46                   brw_inst_set_jip(p->devinfo, inst, relative_offset);
47                   break;
48                case BRW_OPCODE_BREAK:
49                case BRW_OPCODE_HALT:
50                case BRW_OPCODE_CONTINUE:
51                   brw_inst_set_jip(p->devinfo, inst, relative_offset);
52                   break;
53                default:
54                   fprintf(stderr, "Unknown opcode %d with JIP label\n", opcode);
55                   return false;
56                }
57             } else {
58                switch (opcode) {
59                case BRW_OPCODE_IF:
60                case BRW_OPCODE_ELSE:
61                   brw_inst_set_uip(p->devinfo, inst, relative_offset);
62                   break;
63                case BRW_OPCODE_WHILE:
64                case BRW_OPCODE_ENDIF:
65                   fprintf(stderr, "WHILE/ENDIF cannot have UIP offset\n");
66                   return false;
67                case BRW_OPCODE_BREAK:
68                case BRW_OPCODE_CONTINUE:
69                case BRW_OPCODE_HALT:
70                   brw_inst_set_uip(p->devinfo, inst, relative_offset);
71                   break;
72                default:
73                   fprintf(stderr, "Unknown opcode %d with UIP label\n", opcode);
74                   return false;
75                }
76             }
77 
78             list_del(&ilabel->link);
79          }
80       }
81    }
82 
83    LIST_FOR_EACH_ENTRY(ilabel, &instr_labels, link) {
84       fprintf(stderr, "Unknown label '%s'\n", ilabel->name);
85    }
86 
87    return list_is_empty(&instr_labels);
88 }
89 
90 /* TODO: Would be nice to make this operate on string instead on a FILE. */
91 
92 brw_assemble_result
brw_assemble(void * mem_ctx,const struct intel_device_info * devinfo,FILE * f,const char * filename,brw_assemble_flags flags)93 brw_assemble(void *mem_ctx, const struct intel_device_info *devinfo,
94              FILE *f, const char *filename, brw_assemble_flags flags)
95 {
96    brw_assemble_result result = {0};
97 
98    list_inithead(&instr_labels);
99    list_inithead(&target_labels);
100 
101    struct brw_isa_info isa;
102    brw_init_isa_info(&isa, devinfo);
103 
104    p = rzalloc(mem_ctx, struct brw_codegen);
105    brw_init_codegen(&isa, p, p);
106 
107    yyin = f;
108    input_filename = filename;
109 
110    int err = yyparse();
111    if (err || errors)
112       goto end;
113 
114    if (!i965_postprocess_labels())
115       goto end;
116 
117    struct disasm_info *disasm_info = disasm_initialize(p->isa, NULL);
118    if (!disasm_info) {
119       ralloc_free(disasm_info);
120       fprintf(stderr, "Unable to initialize disasm_info struct instance\n");
121       goto end;
122    }
123 
124    if (!brw_validate_instructions(p->isa, p->store, 0,
125                                   p->next_insn_offset, disasm_info)) {
126       ralloc_free(disasm_info);
127       fprintf(stderr, "Invalid instructions\n");
128       goto end;
129    }
130 
131    result.bin = p->store;
132    result.bin_size = p->next_insn_offset;
133    result.inst_count = p->next_insn_offset / 16;
134 
135    if ((flags & BRW_ASSEMBLE_COMPACT) != 0) {
136       brw_compact_instructions(p, 0, disasm_info);
137 
138       /* Adjust bin size to account for compacted instructions. */
139       int compacted = 0;
140       for (int i = 0; i < result.inst_count; i++) {
141          const brw_inst *inst = result.bin + i;
142          if (brw_inst_cmpt_control(devinfo, inst))
143             compacted++;
144       }
145       result.bin_size -= compacted * 8;
146    }
147 
148    ralloc_free(disasm_info);
149 
150 end:
151    /* Reset internal state. */
152    yyin = NULL;
153    input_filename = NULL;
154    p = NULL;
155    list_inithead(&instr_labels);
156    list_inithead(&target_labels);
157 
158    return result;
159 }
160 
161