1 /*
2 * Copyright © 2024 Imagination Technologies Ltd.
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7 /**
8 * \file pco_print.c
9 *
10 * \brief PCO printing functions.
11 */
12
13 #include "pco.h"
14 #include "pco_builder.h"
15 #include "pco_common.h"
16 #include "pco_internal.h"
17 #include "util/bitscan.h"
18 #include "util/list.h"
19 #include "util/macros.h"
20 #include "util/u_hexdump.h"
21
22 #include <assert.h>
23 #include <inttypes.h>
24 #include <stdarg.h>
25 #include <stdbool.h>
26 #include <stdint.h>
27 #include <stdio.h>
28
29 typedef struct _pco_print_state {
30 FILE *fp; /** The print target file pointer. */
31 pco_shader *shader; /** The shader being printed. */
32 unsigned indent; /** The current printing indent. */
33 bool is_grouped; /** Whether the shader uses igrps. */
34 bool verbose; /** Whether to print additional info. */
35 } pco_print_state;
36
37 /* Forward declarations. */
38 static void _pco_print_cf_node(pco_print_state *state, pco_cf_node *cf_node);
39 static void pco_print_block_name(pco_print_state *state, pco_block *block);
40 static void
41 pco_print_func_sig(pco_print_state *state, pco_func *func, bool call);
42
43 enum color_esc {
44 ESC_RESET = 0,
45 ESC_BLACK,
46 ESC_RED,
47 ESC_GREEN,
48 ESC_YELLOW,
49 ESC_BLUE,
50 ESC_PURPLE,
51 ESC_CYAN,
52 ESC_WHITE,
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(pco_print_state * state)82 static inline void RESET(pco_print_state *state)
83 {
84 fputs(color_esc[pco_color][ESC_RESET], state->fp);
85 }
86
BLACK(pco_print_state * state)87 static inline void BLACK(pco_print_state *state)
88 {
89 fputs(color_esc[pco_color][ESC_BLACK], state->fp);
90 }
91
RED(pco_print_state * state)92 static inline void RED(pco_print_state *state)
93 {
94 fputs(color_esc[pco_color][ESC_RED], state->fp);
95 }
96
GREEN(pco_print_state * state)97 static inline void GREEN(pco_print_state *state)
98 {
99 fputs(color_esc[pco_color][ESC_GREEN], state->fp);
100 }
101
YELLOW(pco_print_state * state)102 static inline void YELLOW(pco_print_state *state)
103 {
104 fputs(color_esc[pco_color][ESC_YELLOW], state->fp);
105 }
106
BLUE(pco_print_state * state)107 static inline void BLUE(pco_print_state *state)
108 {
109 fputs(color_esc[pco_color][ESC_BLUE], state->fp);
110 }
111
PURPLE(pco_print_state * state)112 static inline void PURPLE(pco_print_state *state)
113 {
114 fputs(color_esc[pco_color][ESC_PURPLE], state->fp);
115 }
116
CYAN(pco_print_state * state)117 static inline void CYAN(pco_print_state *state)
118 {
119 fputs(color_esc[pco_color][ESC_CYAN], state->fp);
120 }
121
WHITE(pco_print_state * state)122 static inline void WHITE(pco_print_state *state)
123 {
124 fputs(color_esc[pco_color][ESC_WHITE], state->fp);
125 }
126
true_false_str(bool b)127 inline static const char *true_false_str(bool b)
128 {
129 return b ? "true" : "false";
130 }
131
132 static void
_pco_printf(pco_print_state * state,bool nl,const char * fmt,va_list args)133 _pco_printf(pco_print_state *state, bool nl, const char *fmt, va_list args)
134 {
135 if (nl)
136 for (unsigned u = 0; u < state->indent; ++u)
137 fputs(" ", state->fp);
138
139 vfprintf(state->fp, fmt, args);
140 }
141
142 /**
143 * \brief Formatted print.
144 *
145 * \param[in] state Print state.
146 * \param[in] fmt Print format.
147 */
148 PRINTFLIKE(2, 3)
pco_printf(pco_print_state * state,const char * fmt,...)149 static void pco_printf(pco_print_state *state, const char *fmt, ...)
150 {
151 va_list args;
152 va_start(args, fmt);
153 _pco_printf(state, false, fmt, args);
154 va_end(args);
155 }
156
157 /**
158 * \brief Formatted print, with indentation.
159 *
160 * \param[in] state Print state.
161 * \param[in] fmt Print format.
162 */
163 PRINTFLIKE(2, 3)
pco_printfi(pco_print_state * state,const char * fmt,...)164 static void pco_printfi(pco_print_state *state, const char *fmt, ...)
165 {
166 va_list args;
167 va_start(args, fmt);
168 _pco_printf(state, true, fmt, args);
169 va_end(args);
170 }
171
172 /**
173 * \brief Returns a space if the string is not empty.
174 *
175 * \param[in] str String.
176 * \return A space if the string is not empty, else an empty string.
177 */
space_if_str(const char * str)178 static inline const char *space_if_str(const char *str)
179 {
180 return str[0] != '\0' ? " " : "";
181 }
182
183 /**
184 * \brief Print PCO reference flags/modifiers.
185 *
186 * \param[in] state Print state.
187 * \param[in] ref PCO reference.
188 */
pco_print_ref_mods(pco_print_state * state,pco_ref ref)189 static void pco_print_ref_mods(pco_print_state *state, pco_ref ref)
190 {
191 if (ref.oneminus)
192 pco_printf(state, ".oneminus");
193 if (ref.clamp)
194 pco_printf(state, ".clamp");
195 if (ref.flr)
196 pco_printf(state, ".flr");
197 if (ref.abs)
198 pco_printf(state, ".abs");
199 if (ref.neg)
200 pco_printf(state, ".neg");
201
202 u_foreach_bit (e, ref.elem) {
203 pco_printf(state, ".e%u", e);
204 }
205 }
206
207 /**
208 * \brief Print PCO reference color.
209 *
210 * \param[in] state Print state.
211 * \param[in] ref PCO reference.
212 */
pco_print_ref_color(pco_print_state * state,pco_ref ref)213 static void pco_print_ref_color(pco_print_state *state, pco_ref ref)
214 {
215 switch (ref.type) {
216 case PCO_REF_TYPE_NULL:
217 return;
218
219 case PCO_REF_TYPE_SSA:
220 case PCO_REF_TYPE_REG:
221 case PCO_REF_TYPE_IDX_REG:
222 YELLOW(state);
223 return;
224
225 case PCO_REF_TYPE_IMM:
226 BLUE(state);
227 return;
228
229 case PCO_REF_TYPE_IO:
230 case PCO_REF_TYPE_PRED:
231 case PCO_REF_TYPE_DRC:
232 WHITE(state);
233 return;
234
235 default:
236 break;
237 }
238
239 unreachable();
240 }
241
242 /**
243 * \brief Print PCO reference.
244 *
245 * \param[in] state Print state.
246 * \param[in] ref PCO reference.
247 */
_pco_print_ref(pco_print_state * state,pco_ref ref)248 static void _pco_print_ref(pco_print_state *state, pco_ref ref)
249 {
250 pco_print_ref_color(state, ref);
251 pco_printf(state, "%s", pco_ref_type_str(ref.type));
252
253 switch (ref.type) {
254 case PCO_REF_TYPE_NULL:
255 break;
256
257 case PCO_REF_TYPE_SSA:
258 pco_printf(state, "%u", ref.val);
259 break;
260
261 case PCO_REF_TYPE_REG:
262 pco_printf(state, "%s%u", pco_reg_class_str(ref.reg_class), ref.val);
263 break;
264
265 case PCO_REF_TYPE_IDX_REG:
266 _pco_print_ref(state, pco_ref_get_idx_pointee(ref));
267 pco_print_ref_color(state, ref);
268 pco_printf(state, "[idx%u", ref.idx_reg.num);
269 break;
270
271 case PCO_REF_TYPE_IMM:
272 assert(pco_ref_is_scalar(ref));
273 switch (ref.dtype) {
274 case PCO_DTYPE_ANY:
275 pco_printf(state, "0x%" PRIx64, pco_ref_get_imm(ref));
276 break;
277
278 case PCO_DTYPE_UNSIGNED:
279 pco_printf(state, "%" PRIu64, pco_ref_get_imm(ref));
280 break;
281
282 case PCO_DTYPE_SIGNED:
283 pco_printf(state, "%" PRId64, pco_ref_get_imm(ref));
284 break;
285
286 case PCO_DTYPE_FLOAT:
287 pco_printf(state, "%f", uif(pco_ref_get_imm(ref)));
288 break;
289
290 default:
291 unreachable();
292 }
293 pco_printf(state, "%s", pco_dtype_str(ref.dtype));
294 break;
295
296 case PCO_REF_TYPE_IO:
297 assert(pco_ref_is_scalar(ref));
298 pco_printf(state, "%s", pco_io_str(ref.val));
299 break;
300
301 case PCO_REF_TYPE_PRED:
302 assert(pco_ref_is_scalar(ref));
303 pco_printf(state, "%s", pco_pred_str(ref.val));
304 break;
305
306 case PCO_REF_TYPE_DRC:
307 assert(pco_ref_is_scalar(ref));
308 pco_printf(state, "%s", pco_drc_str(ref.val));
309 break;
310
311 default:
312 unreachable();
313 }
314
315 unsigned chans = pco_ref_get_chans(ref);
316 if (chans > 1 && !pco_ref_is_ssa(ref))
317 pco_printf(state, "..%u", ref.val + chans - 1);
318
319 if (ref.type == PCO_REF_TYPE_IDX_REG)
320 pco_printf(state, "]");
321
322 RESET(state);
323
324 /* Modifiers. */
325 pco_print_ref_mods(state, ref);
326 }
327
328 /**
329 * \brief Print PCO reference specification.
330 *
331 * \param[in] state Print state.
332 * \param[in] ref PCO reference.
333 */
pco_print_ref_spec(pco_print_state * state,pco_ref ref)334 static void pco_print_ref_spec(pco_print_state *state, pco_ref ref)
335 {
336 pco_printf(state,
337 "(%s%ux%u)",
338 pco_dtype_str(pco_ref_get_dtype(ref)),
339 pco_ref_get_bits(ref),
340 pco_ref_get_chans(ref));
341 }
342
343 /**
344 * \brief Print PCO phi source.
345 *
346 * \param[in] state Print state.
347 * \param[in] phi_src PCO phi source.
348 */
pco_print_phi_src(pco_print_state * state,pco_phi_src * phi_src)349 static void pco_print_phi_src(pco_print_state *state, pco_phi_src *phi_src)
350 {
351 pco_print_block_name(state, phi_src->pred);
352 pco_printf(state, ": ");
353 _pco_print_ref(state, phi_src->ref);
354 }
355
356 /**
357 * \brief Print PCO instruction modifiers.
358 *
359 * \param[in] state Print state.
360 * \param[in] op_info The instruction op info.
361 * \param[in] instr PCO instruction.
362 * \param[in] print_early Whether the mods are being printed before the
363 * instruction name.
364 */
pco_print_instr_mods(pco_print_state * state,const struct pco_op_info * op_info,pco_instr * instr,bool print_early)365 static void pco_print_instr_mods(pco_print_state *state,
366 const struct pco_op_info *op_info,
367 pco_instr *instr,
368 bool print_early)
369 {
370 u_foreach_bit64 (op_mod, op_info->mods) {
371 const struct pco_op_mod_info *mod_info = &pco_op_mod_info[op_mod];
372 if (mod_info->print_early != print_early)
373 continue;
374
375 uint32_t val = pco_instr_get_mod(instr, op_mod);
376
377 switch (mod_info->type) {
378 case PCO_MOD_TYPE_BOOL:
379 if (val && strlen(mod_info->str)) {
380 if (print_early)
381 pco_printf(state, "%s ", mod_info->str);
382 else
383 pco_printf(state, ".%s", mod_info->str);
384 }
385 break;
386
387 case PCO_MOD_TYPE_UINT:
388 if ((!mod_info->nzdefault || val != mod_info->nzdefault) &&
389 strlen(mod_info->str)) {
390 if (print_early)
391 pco_printf(state, "%s%u ", mod_info->str, val);
392 else
393 pco_printf(state, "%s%u", mod_info->str, val);
394 }
395 break;
396
397 case PCO_MOD_TYPE_ENUM:
398 if (mod_info->is_bitset) {
399 u_foreach_bit (bit, val) {
400 pco_printf(state, ".%s", mod_info->strs[1U << bit]);
401 }
402 } else {
403 if (strlen(mod_info->strs[val])) {
404 if (print_early)
405 pco_printf(state, "%s ", mod_info->strs[val]);
406 else
407 pco_printf(state, ".%s", mod_info->strs[val]);
408 }
409 }
410 break;
411
412 default:
413 unreachable();
414 }
415 }
416 }
417
418 /**
419 * \brief Print PCO instruction.
420 *
421 * \param[in] state Print state.
422 * \param[in] instr PCO instruction.
423 */
_pco_print_instr(pco_print_state * state,pco_instr * instr)424 static void _pco_print_instr(pco_print_state *state, pco_instr *instr)
425 {
426 const struct pco_op_info *info = &pco_op_info[instr->op];
427
428 if (!state->is_grouped)
429 pco_printfi(state, "%04u: ", instr->index);
430
431 /* Early mods. */
432 pco_print_instr_mods(state, info, instr, true);
433
434 if (info->type == PCO_OP_TYPE_PSEUDO)
435 RED(state);
436 else
437 GREEN(state);
438 pco_printf(state, "%s", info->str);
439 RESET(state);
440
441 /* "Late" mods. */
442 pco_print_instr_mods(state, info, instr, false);
443
444 bool printed = false;
445
446 /* Destinations. */
447 for (unsigned d = 0; d < instr->num_dests; ++d) {
448 if (printed)
449 pco_printf(state, ",");
450 pco_printf(state, " ");
451 _pco_print_ref(state, instr->dest[d]);
452 printed = true;
453 }
454
455 /* Special parameters. */
456 if (info->has_target_cf_node) {
457 if (printed)
458 pco_printf(state, ",");
459 pco_printf(state, " ");
460
461 switch (instr->target_cf_node->type) {
462 case PCO_CF_NODE_TYPE_BLOCK: {
463 pco_block *target_block = pco_cf_node_as_block(instr->target_cf_node);
464 pco_printf(state, " ");
465 pco_print_block_name(state, target_block);
466 break;
467 }
468
469 case PCO_CF_NODE_TYPE_FUNC: {
470 pco_func *target_func = pco_cf_node_as_func(instr->target_cf_node);
471 pco_printf(state, " ");
472 pco_print_func_sig(state, target_func, true);
473 break;
474 }
475
476 default:
477 unreachable();
478 }
479 printed = true;
480 } else if (!list_is_empty(&instr->phi_srcs)) {
481 pco_foreach_phi_src_in_instr (phi_src, instr) {
482 if (printed)
483 pco_printf(state, ",");
484 pco_printf(state, " ");
485 pco_print_phi_src(state, phi_src);
486 printed = true;
487 }
488 }
489
490 /* Sources. */
491 for (unsigned s = 0; s < instr->num_srcs; ++s) {
492 if (printed)
493 pco_printf(state, ",");
494 pco_printf(state, " ");
495 _pco_print_ref(state, instr->src[s]);
496 printed = true;
497 }
498 pco_printf(state, ";");
499
500 /* Spec for destinations. */
501 if (state->verbose && !state->is_grouped && instr->num_dests) {
502 pco_printf(state, " /*");
503
504 printed = false;
505 for (unsigned d = 0; d < instr->num_dests; ++d) {
506 if (printed)
507 pco_printf(state, ",");
508 pco_printf(state, " ");
509
510 _pco_print_ref(state, instr->dest[d]);
511 pco_printf(state, ":");
512 pco_print_ref_spec(state, instr->dest[d]);
513
514 printed = true;
515 }
516
517 pco_printf(state, " */");
518 }
519
520 if (state->verbose && instr->comment)
521 pco_printf(state, " /* %s */", instr->comment);
522 }
523
524 /**
525 * \brief Print the name of a phase.
526 *
527 * \param[in] state Print state.
528 * \param[in] alutype ALU type.
529 * \param[in] phase Phase.
530 */
pco_print_phase(pco_print_state * state,enum pco_alutype alutype,enum pco_op_phase phase)531 static void pco_print_phase(pco_print_state *state,
532 enum pco_alutype alutype,
533 enum pco_op_phase phase)
534 {
535 switch (alutype) {
536 case PCO_ALUTYPE_MAIN:
537 pco_printf(state, "%s", pco_op_phase_str(phase));
538 return;
539
540 case PCO_ALUTYPE_BITWISE:
541 pco_printf(state, "p%c", '0' + phase);
542 return;
543
544 case PCO_ALUTYPE_CONTROL:
545 pco_printf(state, "ctrl");
546 return;
547
548 default:
549 break;
550 }
551 unreachable();
552 }
553
554 /**
555 * \brief Print phases present in a PCO instruction group.
556 *
557 * \param[in] state Print state.
558 * \param[in] igrp PCO instruction group.
559 */
pco_print_igrp_phases(pco_print_state * state,pco_igrp * igrp)560 static void pco_print_igrp_phases(pco_print_state *state, pco_igrp *igrp)
561 {
562 bool printed = false;
563 for (enum pco_op_phase phase = 0; phase < _PCO_OP_PHASE_COUNT; ++phase) {
564 if (!igrp->instrs[phase])
565 continue;
566
567 if (printed)
568 pco_printf(state, ",");
569
570 pco_print_phase(state, igrp->hdr.alutype, phase);
571
572 printed = true;
573 }
574 }
575
576 /**
577 * \brief Print the sources in a PCO instruction group.
578 *
579 * \param[in] state Print state.
580 * \param[in] igrp PCO instruction group.
581 * \param[in] upper Whether to print the upper sources.
582 */
583 static void
pco_print_igrp_srcs(pco_print_state * state,pco_igrp * igrp,bool upper)584 pco_print_igrp_srcs(pco_print_state *state, pco_igrp *igrp, bool upper)
585 {
586 unsigned offset = upper ? ROGUE_ALU_INPUT_GROUP_SIZE : 0;
587 bool printed = false;
588 for (unsigned u = 0; u < ROGUE_ALU_INPUT_GROUP_SIZE; ++u) {
589 const pco_ref *src = &igrp->srcs.s[u + offset];
590 if (pco_ref_is_null(*src))
591 continue;
592
593 if (printed)
594 pco_printf(state, ", ");
595
596 pco_printf(state, "s%u = ", u + offset);
597 _pco_print_ref(state, *src);
598 printed = true;
599 }
600 }
601
602 /**
603 * \brief Print the internal source selector in a PCO instruction group.
604 *
605 * \param[in] state Print state.
606 * \param[in] igrp PCO instruction group.
607 */
pco_print_igrp_iss(pco_print_state * state,pco_igrp * igrp)608 static void pco_print_igrp_iss(pco_print_state *state, pco_igrp *igrp)
609 {
610 bool printed = false;
611 for (unsigned u = 0; u < ROGUE_MAX_ALU_INTERNAL_SOURCES; ++u) {
612 const pco_ref *iss = &igrp->iss.is[u];
613 if (pco_ref_is_null(*iss))
614 continue;
615
616 if (printed)
617 pco_printf(state, ", ");
618
619 pco_printf(state, "is%u = ", u);
620 _pco_print_ref(state, *iss);
621 printed = true;
622 }
623 }
624
625 /**
626 * \brief Print the dests in a PCO instruction group.
627 *
628 * \param[in] state Print state.
629 * \param[in] igrp PCO instruction group.
630 */
pco_print_igrp_dests(pco_print_state * state,pco_igrp * igrp)631 static void pco_print_igrp_dests(pco_print_state *state, pco_igrp *igrp)
632 {
633 bool printed = false;
634 for (unsigned u = 0; u < ROGUE_MAX_ALU_OUTPUTS; ++u) {
635 const pco_ref *dest = &igrp->dests.w[u];
636 if (pco_ref_is_null(*dest))
637 continue;
638
639 if (printed)
640 pco_printf(state, ", ");
641
642 pco_printf(state, "w%u = ", u);
643 _pco_print_ref(state, *dest);
644 printed = true;
645 }
646 }
647
648 /**
649 * \brief Print PCO instruction group.
650 *
651 * \param[in] state Print state.
652 * \param[in] igrp PCO instruction group.
653 */
_pco_print_igrp(pco_print_state * state,pco_igrp * igrp)654 static void _pco_print_igrp(pco_print_state *state, pco_igrp *igrp)
655 {
656 bool printed = false;
657
658 pco_printfi(state,
659 "%04u:%s%s { ",
660 igrp->index,
661 space_if_str(pco_cc_str(igrp->hdr.cc)),
662 pco_cc_str(igrp->hdr.cc));
663
664 if (state->verbose) {
665 unsigned padding_size =
666 igrp->enc.len.word_padding + igrp->enc.len.align_padding;
667 unsigned unpadded_size = igrp->enc.len.total - padding_size;
668
669 pco_printf(state, "/* @ 0x%08x [", igrp->enc.offset);
670 pco_print_igrp_phases(state, igrp);
671 pco_printf(state,
672 "] len: %u, pad: %u, total: %u, da: %u",
673 unpadded_size,
674 padding_size,
675 igrp->enc.len.total,
676 igrp->hdr.da);
677
678 if (igrp->hdr.w0p)
679 pco_printf(state, ", w0p");
680
681 if (igrp->hdr.w1p)
682 pco_printf(state, ", w1p");
683
684 pco_printf(state, " */\n");
685 ++state->indent;
686
687 pco_printfi(state,
688 "type %s /* hdr bytes: %u */\n",
689 pco_alutype_str(igrp->hdr.alutype),
690 igrp->enc.len.hdr);
691 }
692
693 if (igrp->hdr.alutype != PCO_ALUTYPE_CONTROL && igrp->hdr.rpt > 1) {
694 if (state->verbose)
695 pco_printfi(state, "repeat %u\n", igrp->hdr.rpt);
696 else
697 pco_printf(state, "repeat %u ", igrp->hdr.rpt);
698
699 printed = true;
700 }
701
702 if (igrp->enc.len.lower_srcs) {
703 if (state->verbose)
704 pco_printfi(state, "%s", "");
705
706 if (!pco_igrp_srcs_unset(igrp, false)) {
707 if (!state->verbose && printed)
708 pco_printf(state, ", ");
709
710 pco_print_igrp_srcs(state, igrp, false);
711
712 if (state->verbose)
713 pco_printf(state, " ");
714 }
715
716 if (state->verbose)
717 pco_printf(state,
718 "/* lo src bytes: %u */\n",
719 igrp->enc.len.lower_srcs);
720
721 printed = true;
722 }
723
724 if (igrp->enc.len.upper_srcs) {
725 if (state->verbose)
726 pco_printfi(state, "%s", "");
727
728 if (!pco_igrp_srcs_unset(igrp, true)) {
729 if (!state->verbose && printed)
730 pco_printf(state, ", ");
731
732 pco_print_igrp_srcs(state, igrp, true);
733
734 if (state->verbose)
735 pco_printf(state, " ");
736 }
737
738 if (state->verbose)
739 pco_printf(state,
740 "/* up src bytes: %u */\n",
741 igrp->enc.len.upper_srcs);
742
743 printed = true;
744 }
745
746 if (igrp->enc.len.iss) {
747 if (state->verbose)
748 pco_printfi(state, "%s", "");
749
750 if (!pco_igrp_iss_unset(igrp)) {
751 if (!state->verbose && printed)
752 pco_printf(state, ", ");
753
754 pco_print_igrp_iss(state, igrp);
755
756 if (state->verbose)
757 pco_printf(state, " ");
758 }
759
760 if (state->verbose)
761 pco_printf(state, "/* iss bytes: %u */\n", igrp->enc.len.iss);
762
763 printed = true;
764 }
765
766 for (enum pco_op_phase phase = 0; phase < _PCO_OP_PHASE_COUNT; ++phase) {
767 if (!igrp->instrs[phase])
768 continue;
769
770 if (state->verbose)
771 pco_printfi(state, "%s", "");
772 else if (printed)
773 pco_printf(state, " ");
774
775 pco_print_phase(state, igrp->hdr.alutype, phase);
776 pco_printf(state, ": ");
777 _pco_print_instr(state, igrp->instrs[phase]);
778
779 if (state->verbose) {
780 pco_printf(state, " /* ");
781 pco_print_phase(state, igrp->hdr.alutype, phase);
782 pco_printf(state, " bytes: %u */\n", igrp->enc.len.instrs[phase]);
783 }
784
785 printed = true;
786 }
787
788 if (igrp->enc.len.dests) {
789 if (state->verbose)
790 pco_printfi(state, "%s", "");
791
792 if (!pco_igrp_dests_unset(igrp)) {
793 if (!state->verbose && printed)
794 pco_printf(state, " ");
795
796 pco_print_igrp_dests(state, igrp);
797
798 if (state->verbose)
799 pco_printf(state, " ");
800 }
801
802 if (state->verbose)
803 pco_printf(state, "/* dest bytes: %u */\n", igrp->enc.len.dests);
804
805 printed = true;
806 }
807
808 if (state->verbose)
809 --state->indent;
810 else
811 pco_printf(state, " ");
812
813 if (state->verbose)
814 pco_printfi(state, "}");
815 else
816 pco_printf(state, "}");
817
818 if (igrp->hdr.olchk)
819 pco_printf(state, ".olchk");
820
821 if (igrp->hdr.alutype != PCO_ALUTYPE_CONTROL) {
822 if (igrp->hdr.atom)
823 pco_printf(state, ".atom");
824
825 if (igrp->hdr.end)
826 pco_printf(state, ".end");
827 }
828
829 if (state->verbose && igrp->comment)
830 pco_printf(state, " /* %s */", igrp->comment);
831
832 pco_printf(state, "\n");
833 }
834
835 /**
836 * \brief Print PCO block name.
837 *
838 * \param[in] state Print state.
839 * \param[in] block PCO block.
840 */
pco_print_block_name(pco_print_state * state,pco_block * block)841 static void pco_print_block_name(pco_print_state *state, pco_block *block)
842 {
843 pco_printf(state, "B%u", block->index);
844 }
845
846 /**
847 * \brief Print PCO block.
848 *
849 * \param[in] state Print state.
850 * \param[in] block PCO block.
851 */
pco_print_block(pco_print_state * state,pco_block * block)852 static void pco_print_block(pco_print_state *state, pco_block *block)
853 {
854 pco_printfi(state, "block ");
855 pco_print_block_name(state, block);
856 pco_printfi(state, ":\n");
857 ++state->indent;
858
859 if (state->is_grouped) {
860 pco_foreach_igrp_in_block (igrp, block) {
861 _pco_print_igrp(state, igrp);
862 }
863 } else {
864 pco_foreach_instr_in_block (instr, block) {
865 _pco_print_instr(state, instr);
866 pco_printf(state, "\n");
867 }
868 }
869
870 --state->indent;
871 }
872
873 /**
874 * \brief Print PCO if name.
875 *
876 * \param[in] state Print state.
877 * \param[in] pif PCO if.
878 */
pco_print_if_name(pco_print_state * state,pco_if * pif)879 static void pco_print_if_name(pco_print_state *state, pco_if *pif)
880 {
881 pco_printf(state, "I%u", pif->index);
882 }
883
884 /**
885 * \brief Print PCO if.
886 *
887 * \param[in] state Print state.
888 * \param[in] pif PCO if.
889 */
pco_print_if(pco_print_state * state,pco_if * pif)890 static void pco_print_if(pco_print_state *state, pco_if *pif)
891 {
892 pco_printfi(state, "if ");
893 pco_print_if_name(state, pif);
894 pco_printfi(state, " (");
895 _pco_print_ref(state, pif->cond);
896 pco_printf(state, ") {\n");
897 ++state->indent;
898
899 pco_foreach_cf_node_in_if_then (cf_node, pif) {
900 _pco_print_cf_node(state, cf_node);
901 }
902
903 --state->indent;
904 if (list_is_empty(&pif->else_body)) {
905 pco_printf(state, "}\n");
906 return;
907 }
908
909 pco_printf(state, "} else {\n");
910 ++state->indent;
911
912 pco_foreach_cf_node_in_if_else (cf_node, pif) {
913 _pco_print_cf_node(state, cf_node);
914 }
915
916 --state->indent;
917 pco_printf(state, "}\n");
918 }
919
920 /**
921 * \brief Print PCO loop name.
922 *
923 * \param[in] state Print state.
924 * \param[in] loop PCO loop.
925 */
pco_print_loop_name(pco_print_state * state,pco_loop * loop)926 static void pco_print_loop_name(pco_print_state *state, pco_loop *loop)
927 {
928 pco_printf(state, "L%u", loop->index);
929 }
930
931 /**
932 * \brief Print PCO loop.
933 *
934 * \param[in] state Print state.
935 * \param[in] loop PCO loop.
936 */
pco_print_loop(pco_print_state * state,pco_loop * loop)937 static void pco_print_loop(pco_print_state *state, pco_loop *loop)
938 {
939 pco_printfi(state, "loop ");
940 pco_print_loop_name(state, loop);
941 pco_printfi(state, " {\n");
942 ++state->indent;
943
944 pco_foreach_cf_node_in_loop (cf_node, loop) {
945 _pco_print_cf_node(state, cf_node);
946 }
947
948 --state->indent;
949 pco_printf(state, "}\n");
950 }
951
952 /**
953 * \brief Print PCO function signature.
954 *
955 * \param[in] state Print state.
956 * \param[in] func PCO function.
957 * \param[in] call Whether the signature is for a function call/reference.
958 */
959 static void
pco_print_func_sig(pco_print_state * state,pco_func * func,bool call)960 pco_print_func_sig(pco_print_state *state, pco_func *func, bool call)
961 {
962 if (!call) {
963 switch (func->type) {
964 case PCO_FUNC_TYPE_CALLABLE:
965 break;
966
967 case PCO_FUNC_TYPE_PREAMBLE:
968 pco_printf(state, " PREAMBLE");
969 break;
970
971 case PCO_FUNC_TYPE_ENTRYPOINT:
972 pco_printf(state, " ENTRY");
973 break;
974
975 case PCO_FUNC_TYPE_PHASE_CHANGE:
976 pco_printf(state, " PHASE CHANGE");
977 break;
978
979 default:
980 unreachable();
981 }
982 }
983
984 if (func->name)
985 pco_printf(state, " %s", func->name);
986 else
987 pco_printf(state, " _%u", func->index);
988
989 pco_printf(state, "(");
990
991 if (!call) {
992 /* TODO: Function parameter support. */
993 assert(func->num_params == 0 && func->params == NULL);
994 if (!func->num_params)
995 pco_printf(state, "void");
996 }
997
998 pco_printf(state, ")");
999 }
1000
1001 /**
1002 * \brief Print PCO function.
1003 *
1004 * \param[in] state Print state.
1005 * \param[in] func PCO function.
1006 */
pco_print_func(pco_print_state * state,pco_func * func)1007 static void pco_print_func(pco_print_state *state, pco_func *func)
1008 {
1009 pco_printfi(state, "func");
1010 pco_print_func_sig(state, func, false);
1011 if (state->is_grouped)
1012 pco_printf(state, " /* temps: %u */", func->temps);
1013 pco_printf(state, "\n");
1014
1015 pco_printfi(state, "{\n");
1016
1017 pco_foreach_cf_node_in_func (cf_node, func) {
1018 _pco_print_cf_node(state, cf_node);
1019 }
1020
1021 pco_printfi(state, "}\n");
1022 }
1023
1024 /**
1025 * \brief Print PCO control flow node.
1026 *
1027 * \param[in] state Print state.
1028 * \param[in] cf_node PCO control flow node.
1029 */
_pco_print_cf_node(pco_print_state * state,pco_cf_node * cf_node)1030 static void _pco_print_cf_node(pco_print_state *state, pco_cf_node *cf_node)
1031 {
1032 switch (cf_node->type) {
1033 case PCO_CF_NODE_TYPE_BLOCK:
1034 return pco_print_block(state, pco_cf_node_as_block(cf_node));
1035
1036 case PCO_CF_NODE_TYPE_IF:
1037 return pco_print_if(state, pco_cf_node_as_if(cf_node));
1038
1039 case PCO_CF_NODE_TYPE_LOOP:
1040 return pco_print_loop(state, pco_cf_node_as_loop(cf_node));
1041
1042 case PCO_CF_NODE_TYPE_FUNC:
1043 return pco_print_func(state, pco_cf_node_as_func(cf_node));
1044
1045 default:
1046 break;
1047 }
1048
1049 unreachable();
1050 }
1051
1052 /**
1053 * \brief Print PCO shader info.
1054 *
1055 * \param[in] state Print state.
1056 * \param[in] shader PCO shader.
1057 */
_pco_print_shader_info(pco_print_state * state,pco_shader * shader)1058 static void _pco_print_shader_info(pco_print_state *state, pco_shader *shader)
1059 {
1060 if (shader->name)
1061 pco_printfi(state, "name: \"%s\"\n", shader->name);
1062 pco_printfi(state, "stage: %s\n", gl_shader_stage_name(shader->stage));
1063 pco_printfi(state, "internal: %s\n", true_false_str(shader->is_internal));
1064 /* TODO: more info/stats, e.g. temps/other regs used, etc.? */
1065 }
1066
1067 /**
1068 * \brief Print PCO shader.
1069 *
1070 * \param[in] shader PCO shader.
1071 * \param[in] fp Print target file pointer.
1072 * \param[in] when When the printing is being performed.
1073 */
pco_print_shader(pco_shader * shader,FILE * fp,const char * when)1074 void pco_print_shader(pco_shader *shader, FILE *fp, const char *when)
1075 {
1076 pco_print_state state = {
1077 .fp = fp,
1078 .shader = shader,
1079 .indent = 0,
1080 .is_grouped = shader->is_grouped,
1081 .verbose = PCO_DEBUG_PRINT(VERBOSE),
1082 };
1083
1084 if (when)
1085 fprintf(fp, "shader ir %s:\n", when);
1086 else
1087 fputs("shader ir:\n", fp);
1088
1089 _pco_print_shader_info(&state, shader);
1090
1091 pco_foreach_func_in_shader (func, shader) {
1092 pco_print_func(&state, func);
1093 }
1094 }
1095
1096 /**
1097 * \brief Print PCO shader binary.
1098 *
1099 * \param[in] shader PCO shader.
1100 * \param[in] fp Print target file pointer.
1101 * \param[in] when When the printing is being performed.
1102 */
pco_print_binary(pco_shader * shader,FILE * fp,const char * when)1103 void pco_print_binary(pco_shader *shader, FILE *fp, const char *when)
1104 {
1105 pco_print_state state = {
1106 .fp = fp,
1107 .shader = shader,
1108 .indent = 0,
1109 .is_grouped = shader->is_grouped,
1110 .verbose = PCO_DEBUG_PRINT(VERBOSE),
1111 };
1112
1113 if (when)
1114 fprintf(fp, "shader binary %s:\n", when);
1115 else
1116 fputs("shader binary:", fp);
1117
1118 _pco_print_shader_info(&state, shader);
1119
1120 return u_hexdump(fp,
1121 pco_shader_binary_data(shader),
1122 pco_shader_binary_size(shader),
1123 false);
1124 }
1125
1126 /**
1127 * \brief Print PCO reference (wrapper).
1128 *
1129 * \param[in] shader PCO shader.
1130 * \param[in] ref PCO reference.
1131 */
pco_print_ref(pco_shader * shader,pco_ref ref)1132 void pco_print_ref(pco_shader *shader, pco_ref ref)
1133 {
1134 pco_print_state state = {
1135 .fp = stdout,
1136 .shader = shader,
1137 .indent = 0,
1138 .is_grouped = shader->is_grouped,
1139 .verbose = false,
1140 };
1141 return _pco_print_ref(&state, ref);
1142 }
1143
1144 /**
1145 * \brief Print PCO instruction (wrapper).
1146 *
1147 * \param[in] shader PCO shader.
1148 * \param[in] instr PCO instruction.
1149 */
pco_print_instr(pco_shader * shader,pco_instr * instr)1150 void pco_print_instr(pco_shader *shader, pco_instr *instr)
1151 {
1152 pco_print_state state = {
1153 .fp = stdout,
1154 .shader = shader,
1155 .indent = 0,
1156 .is_grouped = shader->is_grouped,
1157 .verbose = false,
1158 };
1159 return _pco_print_instr(&state, instr);
1160 }
1161
1162 /**
1163 * \brief Print PCO instruction group (wrapper).
1164 *
1165 * \param[in] shader PCO shader.
1166 * \param[in] igrp PCO instruction group.
1167 */
pco_print_igrp(pco_shader * shader,pco_igrp * igrp)1168 void pco_print_igrp(pco_shader *shader, pco_igrp *igrp)
1169 {
1170 pco_print_state state = {
1171 .fp = stdout,
1172 .shader = shader,
1173 .indent = 0,
1174 .is_grouped = shader->is_grouped,
1175 .verbose = false,
1176 };
1177 return _pco_print_igrp(&state, igrp);
1178 }
1179
1180 /**
1181 * \brief Print PCO control flow node name (wrapper).
1182 *
1183 * \param[in] shader PCO shader.
1184 * \param[in] cf_node PCO control flow node.
1185 */
pco_print_cf_node_name(pco_shader * shader,pco_cf_node * cf_node)1186 void pco_print_cf_node_name(pco_shader *shader, pco_cf_node *cf_node)
1187 {
1188 pco_print_state state = {
1189 .fp = stdout,
1190 .shader = shader,
1191 .indent = 0,
1192 .is_grouped = shader->is_grouped,
1193 .verbose = false,
1194 };
1195
1196 switch (cf_node->type) {
1197 case PCO_CF_NODE_TYPE_BLOCK:
1198 pco_printf(&state, "block ");
1199 return pco_print_block_name(&state, pco_cf_node_as_block(cf_node));
1200
1201 case PCO_CF_NODE_TYPE_IF:
1202 pco_printf(&state, "if ");
1203 return pco_print_if_name(&state, pco_cf_node_as_if(cf_node));
1204
1205 case PCO_CF_NODE_TYPE_LOOP:
1206 pco_printf(&state, "loop ");
1207 return pco_print_loop_name(&state, pco_cf_node_as_loop(cf_node));
1208
1209 case PCO_CF_NODE_TYPE_FUNC:
1210 pco_printf(&state, "func");
1211 return pco_print_func_sig(&state, pco_cf_node_as_func(cf_node), true);
1212
1213 default:
1214 break;
1215 }
1216
1217 unreachable();
1218 }
1219
1220 /**
1221 * \brief Print PCO shader info (wrapper).
1222 *
1223 * \param[in] shader PCO shader.
1224 */
pco_print_shader_info(pco_shader * shader)1225 void pco_print_shader_info(pco_shader *shader)
1226 {
1227 pco_print_state state = {
1228 .fp = stdout,
1229 .shader = shader,
1230 .indent = 0,
1231 .is_grouped = shader->is_grouped,
1232 .verbose = false,
1233 };
1234 return _pco_print_shader_info(&state, shader);
1235 }
1236