1 /*
2 * Copyright © 2022 Imagination Technologies Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #include "compiler/shader_enums.h"
25 #include "rogue.h"
26 #include "util/bitscan.h"
27 #include "util/macros.h"
28
29 #include <inttypes.h>
30 #include <stdbool.h>
31
32 /**
33 * \file rogue_print.c
34 *
35 * \brief Contains functions to print Rogue IR types and structures.
36 */
37
38 /* TODO NEXT: Go through and make types the same, i.e. decide on using ONLY
39 * unsigned, uint32/64_t, etc., and then use inttypes if so */
40 /* TODO NEXT: Make fp the last argument. */
41
42 enum color_esc {
43 ESC_RESET = 0,
44 ESC_BLACK,
45 ESC_RED,
46 ESC_GREEN,
47 ESC_YELLOW,
48 ESC_BLUE,
49 ESC_PURPLE,
50 ESC_CYAN,
51 ESC_WHITE,
52
53 ESC_COUNT,
54 };
55
56 static
57 const char *color_esc[2][ESC_COUNT] = {
58 [0] = {
59 [ESC_RESET] = "",
60 [ESC_BLACK] = "",
61 [ESC_RED] = "",
62 [ESC_GREEN] = "",
63 [ESC_YELLOW] = "",
64 [ESC_BLUE] = "",
65 [ESC_PURPLE] = "",
66 [ESC_CYAN] = "",
67 [ESC_WHITE] = "",
68 },
69 [1] = {
70 [ESC_RESET] = "\033[0m",
71 [ESC_BLACK] = "\033[0;30m",
72 [ESC_RED] = "\033[0;31m",
73 [ESC_GREEN] = "\033[0;32m",
74 [ESC_YELLOW] = "\033[0;33m",
75 [ESC_BLUE] = "\033[0;34m",
76 [ESC_PURPLE] = "\033[0;35m",
77 [ESC_CYAN] = "\033[0;36m",
78 [ESC_WHITE] = "\033[0;37m",
79 },
80 };
81
RESET(FILE * fp)82 static inline void RESET(FILE *fp)
83 {
84 fputs(color_esc[rogue_color][ESC_RESET], fp);
85 }
86
BLACK(FILE * fp)87 static inline void BLACK(FILE *fp)
88 {
89 fputs(color_esc[rogue_color][ESC_BLACK], fp);
90 }
91
RED(FILE * fp)92 static inline void RED(FILE *fp)
93 {
94 fputs(color_esc[rogue_color][ESC_RED], fp);
95 }
96
GREEN(FILE * fp)97 static inline void GREEN(FILE *fp)
98 {
99 fputs(color_esc[rogue_color][ESC_GREEN], fp);
100 }
101
YELLOW(FILE * fp)102 static inline void YELLOW(FILE *fp)
103 {
104 fputs(color_esc[rogue_color][ESC_YELLOW], fp);
105 }
106
BLUE(FILE * fp)107 static inline void BLUE(FILE *fp)
108 {
109 fputs(color_esc[rogue_color][ESC_BLUE], fp);
110 }
111
PURPLE(FILE * fp)112 static inline void PURPLE(FILE *fp)
113 {
114 fputs(color_esc[rogue_color][ESC_PURPLE], fp);
115 }
116
CYAN(FILE * fp)117 static inline void CYAN(FILE *fp)
118 {
119 fputs(color_esc[rogue_color][ESC_CYAN], fp);
120 }
121
WHITE(FILE * fp)122 static inline void WHITE(FILE *fp)
123 {
124 fputs(color_esc[rogue_color][ESC_WHITE], fp);
125 }
126
rogue_print_val(FILE * fp,unsigned val)127 static inline void rogue_print_val(FILE *fp, unsigned val)
128 {
129 PURPLE(fp);
130 fprintf(fp, "%u", val);
131 RESET(fp);
132 }
133
rogue_print_reg(FILE * fp,const rogue_reg * reg)134 static inline void rogue_print_reg(FILE *fp, const rogue_reg *reg)
135 {
136 const rogue_reg_info *info = &rogue_reg_infos[reg->class];
137 YELLOW(fp);
138 fprintf(fp, "%s%" PRIu32, info->str, reg->index);
139 RESET(fp);
140 }
141
rogue_print_regarray(FILE * fp,const rogue_regarray * regarray)142 static inline void rogue_print_regarray(FILE *fp,
143 const rogue_regarray *regarray)
144 {
145 const rogue_reg *reg = regarray->regs[0];
146 const rogue_reg_info *info = &rogue_reg_infos[reg->class];
147 YELLOW(fp);
148 fprintf(fp, "%s[%" PRIu32, info->str, reg->index);
149 if (regarray->size > 1) {
150 RESET(fp);
151 fputs("..", fp);
152 YELLOW(fp);
153 fprintf(fp, "%" PRIu32, regarray->size + reg->index - 1);
154 }
155 fputs("]", fp);
156 RESET(fp);
157 }
158
rogue_print_imm(FILE * fp,const rogue_imm * imm)159 static inline void rogue_print_imm(FILE *fp, const rogue_imm *imm)
160 {
161 PURPLE(fp);
162 fprintf(fp, "0x%" PRIx32, imm->imm.u32);
163 RESET(fp);
164 }
165
rogue_print_io(FILE * fp,enum rogue_io io)166 static inline void rogue_print_io(FILE *fp, enum rogue_io io)
167 {
168 const rogue_io_info *info = &rogue_io_infos[io];
169 BLUE(fp);
170 fprintf(fp, "%s", info->str);
171 RESET(fp);
172 }
173
rogue_print_drc(FILE * fp,const rogue_drc * drc)174 static inline void rogue_print_drc(FILE *fp, const rogue_drc *drc)
175 {
176 RED(fp);
177 fprintf(fp, "drc%u", drc->index);
178 RESET(fp);
179 }
180
rogue_print_ref(FILE * fp,const rogue_ref * ref)181 static inline void rogue_print_ref(FILE *fp, const rogue_ref *ref)
182 {
183 switch (ref->type) {
184 case ROGUE_REF_TYPE_VAL:
185 rogue_print_val(fp, ref->val);
186 break;
187
188 case ROGUE_REF_TYPE_REG:
189 rogue_print_reg(fp, ref->reg);
190 break;
191
192 case ROGUE_REF_TYPE_REGARRAY:
193 rogue_print_regarray(fp, ref->regarray);
194 break;
195
196 case ROGUE_REF_TYPE_IMM:
197 rogue_print_imm(fp, &ref->imm);
198 break;
199
200 case ROGUE_REF_TYPE_IO:
201 rogue_print_io(fp, ref->io);
202 break;
203
204 case ROGUE_REF_TYPE_DRC:
205 rogue_print_drc(fp, &ref->drc);
206 break;
207
208 default:
209 unreachable("Unsupported ref type.");
210 }
211 }
212
rogue_print_alu_dst(FILE * fp,const rogue_instr_dst * dst)213 static inline void rogue_print_alu_dst(FILE *fp, const rogue_instr_dst *dst)
214 {
215 rogue_print_ref(fp, &dst->ref);
216
217 uint64_t mod = dst->mod;
218 while (mod) {
219 enum rogue_alu_dst_mod dst_mod = u_bit_scan64(&mod);
220 assert(dst_mod < ROGUE_ALU_DST_MOD_COUNT);
221 fprintf(fp, ".%s", rogue_alu_dst_mod_infos[dst_mod].str);
222 }
223 }
224
rogue_print_alu_src(FILE * fp,const rogue_instr_src * src)225 static inline void rogue_print_alu_src(FILE *fp, const rogue_instr_src *src)
226 {
227 rogue_print_ref(fp, &src->ref);
228
229 uint64_t mod = src->mod;
230 while (mod) {
231 enum rogue_alu_src_mod src_mod = u_bit_scan64(&mod);
232 assert(src_mod < ROGUE_ALU_SRC_MOD_COUNT);
233 fprintf(fp, ".%s", rogue_alu_src_mod_infos[src_mod].str);
234 }
235 }
236
rogue_print_alu_mods(FILE * fp,const rogue_alu_instr * alu)237 static inline void rogue_print_alu_mods(FILE *fp, const rogue_alu_instr *alu)
238 {
239 uint64_t mod = alu->mod;
240 while (mod) {
241 enum rogue_alu_op_mod op_mod = u_bit_scan64(&mod);
242 assert(op_mod < ROGUE_ALU_OP_MOD_COUNT);
243 fprintf(fp, ".%s", rogue_alu_op_mod_infos[op_mod].str);
244 }
245 }
246
rogue_print_alu_instr(FILE * fp,const rogue_alu_instr * alu)247 static inline void rogue_print_alu_instr(FILE *fp, const rogue_alu_instr *alu)
248 {
249 const rogue_alu_op_info *info = &rogue_alu_op_infos[alu->op];
250
251 /* TODO: Print conditional info once supported. */
252
253 fprintf(fp, "%s", info->str);
254
255 rogue_print_alu_mods(fp, alu);
256
257 for (unsigned i = 0; i < info->num_dsts; ++i) {
258 if (i > 0)
259 fputs(",", fp);
260
261 fputs(" ", fp);
262
263 rogue_print_alu_dst(fp, &alu->dst[i]);
264 }
265
266 for (unsigned i = 0; i < info->num_srcs; ++i) {
267 if (i == 0 && !info->num_dsts)
268 fputs(" ", fp);
269 else
270 fputs(", ", fp);
271
272 rogue_print_alu_src(fp, &alu->src[i]);
273 }
274 }
275
rogue_print_block_label(FILE * fp,const rogue_block * block)276 static inline void rogue_print_block_label(FILE *fp, const rogue_block *block)
277 {
278 /* For debug purposes. */
279 if (block->label)
280 fprintf(fp, "%s", block->label);
281 else
282 fprintf(fp, "block%u", block->index);
283 }
284
rogue_print_backend_dst(FILE * fp,const rogue_instr_dst * dst)285 static inline void rogue_print_backend_dst(FILE *fp, const rogue_instr_dst *dst)
286 {
287 rogue_print_ref(fp, &dst->ref);
288 }
289
rogue_print_backend_src(FILE * fp,const rogue_instr_src * src)290 static inline void rogue_print_backend_src(FILE *fp, const rogue_instr_src *src)
291 {
292 rogue_print_ref(fp, &src->ref);
293 }
294
rogue_print_backend_mods(FILE * fp,const rogue_backend_instr * backend)295 static inline void rogue_print_backend_mods(FILE *fp,
296 const rogue_backend_instr *backend)
297 {
298 uint64_t mod = backend->mod;
299 while (mod) {
300 enum rogue_backend_op_mod op_mod = u_bit_scan64(&mod);
301 assert(op_mod < ROGUE_BACKEND_OP_MOD_COUNT);
302 fprintf(fp, ".%s", rogue_backend_op_mod_infos[op_mod].str);
303 }
304 }
305
rogue_print_backend_instr(FILE * fp,const rogue_backend_instr * backend)306 static inline void rogue_print_backend_instr(FILE *fp,
307 const rogue_backend_instr *backend)
308 {
309 const rogue_backend_op_info *info = &rogue_backend_op_infos[backend->op];
310
311 fprintf(fp, "%s", info->str);
312
313 rogue_print_backend_mods(fp, backend);
314
315 for (unsigned i = 0; i < info->num_dsts; ++i) {
316 if (i > 0)
317 fputs(",", fp);
318
319 fputs(" ", fp);
320
321 rogue_print_backend_dst(fp, &backend->dst[i]);
322 }
323
324 for (unsigned i = 0; i < info->num_srcs; ++i) {
325 if (i == 0 && !info->num_dsts)
326 fputs(" ", fp);
327 else
328 fputs(", ", fp);
329
330 rogue_print_backend_src(fp, &backend->src[i]);
331 }
332 }
333
rogue_print_ctrl_mods(FILE * fp,const rogue_ctrl_instr * ctrl)334 static inline void rogue_print_ctrl_mods(FILE *fp, const rogue_ctrl_instr *ctrl)
335 {
336 uint64_t mod = ctrl->mod;
337 while (mod) {
338 enum rogue_ctrl_op_mod op_mod = u_bit_scan64(&mod);
339 assert(op_mod < ROGUE_CTRL_OP_MOD_COUNT);
340 fprintf(fp, ".%s", rogue_ctrl_op_mod_infos[op_mod].str);
341 }
342 }
343
rogue_print_ctrl_src(FILE * fp,const rogue_instr_src * src)344 static inline void rogue_print_ctrl_src(FILE *fp, const rogue_instr_src *src)
345 {
346 rogue_print_ref(fp, &src->ref);
347 }
348
rogue_print_ctrl_instr(FILE * fp,const rogue_ctrl_instr * ctrl)349 static inline void rogue_print_ctrl_instr(FILE *fp,
350 const rogue_ctrl_instr *ctrl)
351 {
352 const rogue_ctrl_op_info *info = &rogue_ctrl_op_infos[ctrl->op];
353
354 /* TODO: Print conditional info once supported. */
355
356 fprintf(fp, "%s", info->str);
357
358 rogue_print_ctrl_mods(fp, ctrl);
359
360 if (ctrl->target_block) {
361 fputs(" ", fp);
362 rogue_print_block_label(fp, ctrl->target_block);
363 }
364
365 /* TODO NEXT: Dests. */
366 /* TODO: Special case for the conditional ctrl instructions as they're
367 * printed as source 0, then dest, then rest of the sources. */
368
369 for (unsigned i = 0; i < info->num_srcs; ++i) {
370 if (i == 0 && !info->num_dsts)
371 fputs(" ", fp);
372 else
373 fputs(", ", fp);
374
375 rogue_print_ctrl_src(fp, &ctrl->src[i]);
376 }
377 }
378
rogue_print_bitwise_dst(FILE * fp,const rogue_instr_dst * dst)379 static inline void rogue_print_bitwise_dst(FILE *fp, const rogue_instr_dst *dst)
380 {
381 rogue_print_ref(fp, &dst->ref);
382 }
383
rogue_print_bitwise_src(FILE * fp,const rogue_instr_src * src)384 static inline void rogue_print_bitwise_src(FILE *fp, const rogue_instr_src *src)
385 {
386 rogue_print_ref(fp, &src->ref);
387 }
388
rogue_print_bitwise_instr(FILE * fp,const rogue_bitwise_instr * bitwise)389 static inline void rogue_print_bitwise_instr(FILE *fp,
390 const rogue_bitwise_instr *bitwise)
391 {
392 const rogue_bitwise_op_info *info = &rogue_bitwise_op_infos[bitwise->op];
393
394 fprintf(fp, "%s", info->str);
395
396 /* rogue_print_bitwise_mods(fp, bitwise); */
397
398 for (unsigned i = 0; i < info->num_dsts; ++i) {
399 if (i > 0)
400 fputs(",", fp);
401
402 fputs(" ", fp);
403
404 rogue_print_bitwise_dst(fp, &bitwise->dst[i]);
405 }
406
407 for (unsigned i = 0; i < info->num_srcs; ++i) {
408 if (i == 0 && !info->num_dsts)
409 fputs(" ", fp);
410 else
411 fputs(", ", fp);
412
413 rogue_print_bitwise_src(fp, &bitwise->src[i]);
414 }
415 }
416
417 PUBLIC
rogue_print_instr(FILE * fp,const rogue_instr * instr)418 void rogue_print_instr(FILE *fp, const rogue_instr *instr)
419 {
420 if (instr->exec_cond > ROGUE_EXEC_COND_PE_TRUE)
421 fprintf(fp, "%s ", rogue_exec_cond_str[instr->exec_cond]);
422
423 if (instr->repeat > 1)
424 fprintf(fp, "(rpt%u) ", instr->repeat);
425
426 GREEN(fp);
427 switch (instr->type) {
428 case ROGUE_INSTR_TYPE_ALU:
429 rogue_print_alu_instr(fp, rogue_instr_as_alu(instr));
430 break;
431
432 case ROGUE_INSTR_TYPE_BACKEND:
433 rogue_print_backend_instr(fp, rogue_instr_as_backend(instr));
434 break;
435
436 case ROGUE_INSTR_TYPE_CTRL:
437 rogue_print_ctrl_instr(fp, rogue_instr_as_ctrl(instr));
438 break;
439
440 case ROGUE_INSTR_TYPE_BITWISE:
441 rogue_print_bitwise_instr(fp, rogue_instr_as_bitwise(instr));
442 break;
443
444 default:
445 unreachable("Unsupported instruction type.");
446 }
447 RESET(fp);
448
449 if (instr->end)
450 fputs(" {end}", fp);
451
452 /* For debug purposes. */
453 fputs(";", fp);
454
455 if (instr->comment)
456 fprintf(fp, " /* %s */", instr->comment);
457 }
458
459 /* TODO NEXT: Split this up into separate functions for printing lower srcs,
460 * upper srcs, etc. since we'd want to print them in-between instructions. */
461 /* TODO NEXT: Commonise with printing the ref io stuff. */
462 static inline void
rogue_print_instr_group_io_sel(FILE * fp,const rogue_instr_group_io_sel * io_sel)463 rogue_print_instr_group_io_sel(FILE *fp, const rogue_instr_group_io_sel *io_sel)
464 {
465 bool present = false;
466
467 fputs(" ", fp);
468
469 /* TODO NEXT: Commonise this code!! */
470 /* Print upper and lower sources. */
471 for (unsigned i = 0; i < ARRAY_SIZE(io_sel->srcs); ++i) {
472 if (rogue_ref_is_null(&io_sel->srcs[i]))
473 continue;
474
475 if (present && i > 0)
476 fputs(", ", fp);
477
478 present = true;
479
480 rogue_print_io(fp, ROGUE_IO_S0 + i);
481 fputs("=", fp);
482
483 if (rogue_ref_is_reg(&io_sel->srcs[i]))
484 rogue_print_reg(fp, io_sel->srcs[i].reg);
485 else if (rogue_ref_is_regarray(&io_sel->srcs[i]))
486 rogue_print_regarray(fp, io_sel->srcs[i].regarray);
487 else if (rogue_ref_is_io(&io_sel->srcs[i]))
488 rogue_print_io(fp, io_sel->srcs[i].io);
489 else
490 unreachable("Unsupported src map.");
491 }
492 if (present)
493 fputs(" ", fp);
494
495 /* Print internal sources. */
496 present = false;
497 for (unsigned i = 0; i < ARRAY_SIZE(io_sel->iss); ++i) {
498 if (rogue_ref_is_null(&io_sel->iss[i]))
499 continue;
500
501 if (present && i > 0)
502 fputs(", ", fp);
503
504 present = true;
505
506 rogue_print_io(fp, ROGUE_IO_IS0 + i);
507 fputs("=", fp);
508
509 if (rogue_ref_is_reg(&io_sel->iss[i]))
510 rogue_print_reg(fp, io_sel->iss[i].reg);
511 else if (rogue_ref_is_regarray(&io_sel->iss[i]))
512 rogue_print_regarray(fp, io_sel->iss[i].regarray);
513 else if (rogue_ref_is_io(&io_sel->iss[i]))
514 rogue_print_io(fp, io_sel->iss[i].io);
515 else
516 unreachable("Unsupported iss map.");
517 }
518 if (present)
519 fputs(" ", fp);
520
521 /* Print destinations. */
522 present = false;
523 for (unsigned i = 0; i < ARRAY_SIZE(io_sel->dsts); ++i) {
524 if (rogue_ref_is_null(&io_sel->dsts[i]))
525 continue;
526
527 if (present && i > 0)
528 fputs(", ", fp);
529
530 present = true;
531
532 rogue_print_io(fp, ROGUE_IO_W0 + i);
533 fputs("=", fp);
534
535 if (rogue_ref_is_reg(&io_sel->dsts[i]))
536 rogue_print_reg(fp, io_sel->dsts[i].reg);
537 else if (rogue_ref_is_regarray(&io_sel->dsts[i]))
538 rogue_print_regarray(fp, io_sel->dsts[i].regarray);
539 else if (rogue_ref_is_io(&io_sel->dsts[i]))
540 rogue_print_io(fp, io_sel->dsts[i].io);
541 else
542 unreachable("Unsupported dst map.");
543 }
544 if (present)
545 fputs(" ", fp);
546 }
547
rogue_print_instr_phase(FILE * fp,enum rogue_alu alu,enum rogue_instr_phase phase)548 static inline void rogue_print_instr_phase(FILE *fp,
549 enum rogue_alu alu,
550 enum rogue_instr_phase phase)
551 {
552 const char *phase_str = rogue_instr_phase_str[alu][phase];
553 assert(phase_str);
554 fputs(phase_str, fp);
555 }
556
557 static inline void
rogue_print_instr_group_header(FILE * fp,const rogue_instr_group * group)558 rogue_print_instr_group_header(FILE *fp, const rogue_instr_group *group)
559 {
560 /* ALU specific */
561 switch (group->header.alu) {
562 case ROGUE_ALU_MAIN:
563 break;
564
565 case ROGUE_ALU_BITWISE:
566 break;
567
568 case ROGUE_ALU_CONTROL:
569 break;
570
571 default:
572 unreachable("Unsupported instruction group ALU.");
573 }
574
575 if (group->header.end)
576 fputs(".end", fp);
577 }
578
rogue_print_instr_group(FILE * fp,const rogue_instr_group * group)579 static inline void rogue_print_instr_group(FILE *fp,
580 const rogue_instr_group *group)
581 {
582 /* For debug purposes. */
583 fprintf(fp, "%u", group->index);
584 fputs(": ", fp);
585
586 if (group->header.exec_cond > ROGUE_EXEC_COND_PE_TRUE)
587 fprintf(fp, "%s ", rogue_exec_cond_str[group->header.exec_cond]);
588
589 if (group->header.repeat > 1)
590 fprintf(fp, "(rpt%u) ", group->header.repeat);
591
592 fputs("{ ", fp);
593
594 CYAN(fp);
595 fprintf(fp, "%s", rogue_alu_str[group->header.alu]);
596 RESET(fp);
597
598 /* Print each instruction. */
599 rogue_foreach_phase_in_set (p, group->header.phases) {
600 const rogue_instr *instr = group->instrs[p];
601 assert(instr);
602
603 fputs(" ", fp);
604 rogue_print_instr_phase(fp, group->header.alu, p);
605 fputs(": ", fp);
606 rogue_print_instr(fp, instr);
607 }
608
609 /* Print source/dest mappings (if present). */
610 rogue_print_instr_group_io_sel(fp, &group->io_sel);
611
612 fputs("}", fp);
613
614 /* Print group header info. */
615 rogue_print_instr_group_header(fp, group);
616 }
617
rogue_print_block(FILE * fp,const rogue_block * block)618 static inline void rogue_print_block(FILE *fp, const rogue_block *block)
619 {
620 rogue_print_block_label(fp, block);
621 fputs(":\n", fp);
622
623 if (!block->shader->is_grouped) {
624 rogue_foreach_instr_in_block (instr, block) {
625 fputs("\t", fp);
626 fprintf(fp, "%u", instr->index);
627 fputs(": ", fp);
628 fprintf(fp, "%s: ", rogue_instr_type_str[instr->type]);
629 rogue_print_instr(fp, instr);
630 fputs("\n", fp);
631 }
632 } else {
633 rogue_foreach_instr_group_in_block (group, block) {
634 fputs("\t", fp);
635 rogue_print_instr_group(fp, group);
636 fputs("\n", fp);
637 }
638 }
639 }
640
641 PUBLIC
rogue_print_shader(FILE * fp,const rogue_shader * shader)642 void rogue_print_shader(FILE *fp, const rogue_shader *shader)
643 {
644 fputs("/*", fp);
645
646 if (shader->stage == MESA_SHADER_NONE)
647 fputs(" USC program", fp);
648 else
649 fprintf(fp, " %s shader", _mesa_shader_stage_to_string(shader->stage));
650
651 if (shader->name)
652 fprintf(fp, " - %s", shader->name);
653
654 fputs(" */\n", fp);
655
656 rogue_foreach_block (block, shader)
657 rogue_print_block(fp, block);
658 }
659
rogue_print_instr_ref(FILE * fp,const rogue_instr * instr,bool dst,unsigned index,bool is_grouped)660 static void rogue_print_instr_ref(FILE *fp,
661 const rogue_instr *instr,
662 bool dst,
663 unsigned index,
664 bool is_grouped)
665 {
666 if (is_grouped) {
667 fprintf(fp, "%u", instr->group->index);
668 fputs(": { ", fp);
669 rogue_print_instr_phase(fp, instr->group->header.alu, instr->index);
670 } else {
671 fprintf(fp, "%u", instr->index);
672 if (index != ~0)
673 fputs(": ", fp);
674 }
675
676 if (index != ~0) {
677 BLUE(fp);
678 fprintf(fp, "[%s%u]", dst ? "dst" : "src", index);
679 RESET(fp);
680 }
681
682 if (is_grouped)
683 fputs(" }", fp);
684 }
685
686 PUBLIC
rogue_print_reg_writes(FILE * fp,const rogue_shader * shader)687 void rogue_print_reg_writes(FILE *fp, const rogue_shader *shader)
688 {
689 fputs("/* register writes */\n", fp);
690 for (enum rogue_reg_class class = 0; class < ROGUE_REG_CLASS_COUNT;
691 ++class) {
692 rogue_foreach_reg (reg, shader, class) {
693 bool unused = true;
694
695 rogue_print_reg(fp, reg);
696 fputs(":", fp);
697
698 rogue_foreach_reg_write (write, reg) {
699 assert(write->instr);
700 unused = false;
701
702 fputs(" ", fp);
703 rogue_print_instr_ref(fp,
704 write->instr,
705 true,
706 write->dst_index,
707 shader->is_grouped);
708 }
709
710 if (reg->regarray) {
711 rogue_foreach_regarray_write (write, reg->regarray) {
712 assert(write->instr);
713 unused = false;
714
715 fputs(" ", fp);
716 rogue_print_instr_ref(fp,
717 write->instr,
718 false,
719 write->dst_index,
720 shader->is_grouped);
721 }
722
723 rogue_foreach_subarray (subarray, reg->regarray) {
724 unsigned subarray_start = subarray->regs[0]->index;
725 unsigned subarray_end = subarray_start + subarray->size - 1;
726 if (reg->index < subarray_start || reg->index > subarray_end)
727 continue;
728
729 rogue_foreach_regarray_write (write, subarray) {
730 assert(write->instr);
731 unused = false;
732
733 fputs(" ", fp);
734 rogue_print_instr_ref(fp,
735 write->instr,
736 false,
737 write->dst_index,
738 shader->is_grouped);
739 }
740 }
741 }
742
743 if (unused) {
744 fputs(" <none>\n", fp);
745 continue;
746 }
747
748 fputs("\n", fp);
749 }
750 }
751 }
752
753 PUBLIC
rogue_print_reg_uses(FILE * fp,const rogue_shader * shader)754 void rogue_print_reg_uses(FILE *fp, const rogue_shader *shader)
755 {
756 fputs("/* register uses */\n", fp);
757 for (enum rogue_reg_class class = 0; class < ROGUE_REG_CLASS_COUNT;
758 ++class) {
759 rogue_foreach_reg (reg, shader, class) {
760 bool unused = true;
761
762 rogue_print_reg(fp, reg);
763 fputs(":", fp);
764
765 rogue_foreach_reg_use (use, reg) {
766 assert(use->instr);
767 unused = false;
768
769 fputs(" ", fp);
770 rogue_print_instr_ref(fp,
771 use->instr,
772 false,
773 use->src_index,
774 shader->is_grouped);
775 }
776
777 if (reg->regarray) {
778 rogue_foreach_regarray_use (use, reg->regarray) {
779 assert(use->instr);
780 unused = false;
781
782 fputs(" ", fp);
783 rogue_print_instr_ref(fp,
784 use->instr,
785 false,
786 use->src_index,
787 shader->is_grouped);
788 }
789
790 rogue_foreach_subarray (subarray, reg->regarray) {
791 unsigned subarray_start = subarray->regs[0]->index;
792 unsigned subarray_end = subarray_start + subarray->size - 1;
793 if (reg->index < subarray_start || reg->index > subarray_end)
794 continue;
795
796 rogue_foreach_regarray_use (use, subarray) {
797 assert(use->instr);
798 unused = false;
799
800 fputs(" ", fp);
801 rogue_print_instr_ref(fp,
802 use->instr,
803 false,
804 use->src_index,
805 shader->is_grouped);
806 }
807 }
808 }
809
810 if (unused) {
811 fputs(" <none>\n", fp);
812 continue;
813 }
814
815 fputs("\n", fp);
816 }
817 }
818 }
819
820 PUBLIC
rogue_print_block_uses(FILE * fp,const rogue_shader * shader)821 void rogue_print_block_uses(FILE *fp, const rogue_shader *shader)
822 {
823 fputs("/* block uses */\n", fp);
824 rogue_foreach_block (block, shader) {
825 rogue_print_block_label(fp, block);
826 fputs(":", fp);
827
828 if (list_is_empty(&block->uses)) {
829 if (list_first_entry(&shader->blocks, rogue_block, link) == block)
830 fputs(" <entry>\n", fp);
831 else
832 fputs(" <none>\n", fp);
833
834 continue;
835 }
836
837 rogue_foreach_block_use (use, block) {
838 assert(use->instr);
839
840 fputs(" ", fp);
841 rogue_print_instr_ref(fp, use->instr, false, ~0, shader->is_grouped);
842 }
843
844 fputs("\n", fp);
845 }
846 }
847
rogue_print_drc_trxn(FILE * fp,const rogue_shader * shader,const rogue_drc_trxn * drc_trxn,unsigned index)848 static void rogue_print_drc_trxn(FILE *fp,
849 const rogue_shader *shader,
850 const rogue_drc_trxn *drc_trxn,
851 unsigned index)
852 {
853 fprintf(fp, "drc%u: ack: ", index);
854
855 rogue_print_instr_ref(fp, drc_trxn->acquire, false, ~0, shader->is_grouped);
856
857 fputs(", rel: ", fp);
858
859 if (drc_trxn->release) {
860 rogue_print_instr_ref(fp,
861 drc_trxn->release,
862 false,
863 ~0,
864 shader->is_grouped);
865 } else {
866 fputs("<none>", fp);
867 }
868
869 fputs("\n", fp);
870 }
871
872 PUBLIC
rogue_print_drc_trxns(FILE * fp,const rogue_shader * shader)873 void rogue_print_drc_trxns(FILE *fp, const rogue_shader *shader)
874 {
875 fputs("/* DRC transactions */\n", fp);
876
877 rogue_foreach_drc_trxn (drc_trxn, shader, 0) {
878 rogue_print_drc_trxn(fp, shader, drc_trxn, 0);
879 }
880
881 rogue_foreach_drc_trxn (drc_trxn, shader, 1) {
882 rogue_print_drc_trxn(fp, shader, drc_trxn, 1);
883 }
884 }
885