• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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