1/*
2 * Copyright 2011 Christoph Bumiller
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23#include "nv50_ir.h"
24#include "nv50_ir_target.h"
25#include "nv50_ir_driver.h"
26
27#include <inttypes.h>
28
29namespace nv50_ir {
30
31enum TextStyle
32{
33   TXT_DEFAULT,
34   TXT_GPR,
35   TXT_REGISTER,
36   TXT_FLAGS,
37   TXT_MEM,
38   TXT_IMMD,
39   TXT_BRA,
40   TXT_INSN
41};
42
43static const char *_colour[8] =
44{
45   "\x1b[00m",
46   "\x1b[34m",
47   "\x1b[35m",
48   "\x1b[35m",
49   "\x1b[36m",
50   "\x1b[33m",
51   "\x1b[37m",
52   "\x1b[32m"
53};
54
55static const char *_nocolour[8] =
56{
57      "", "", "", "", "", "", "", ""
58};
59
60static const char **colour;
61
62static void init_colours()
63{
64   if (getenv("NV50_PROG_DEBUG_NO_COLORS") != NULL)
65      colour = _nocolour;
66   else
67      colour = _colour;
68}
69
70const char *operationStr[OP_LAST + 1] =
71{
72   "nop",
73   "phi",
74   "union",
75   "split",
76   "merge",
77   "consec",
78   "mov",
79   "ld",
80   "st",
81   "add",
82   "sub",
83   "mul",
84   "div",
85   "mod",
86   "mad",
87   "fma",
88   "sad",
89   "shladd",
90   "xmad",
91   "abs",
92   "neg",
93   "not",
94   "and",
95   "or",
96   "xor",
97   "lop3 lut",
98   "shl",
99   "shr",
100   "shf",
101   "max",
102   "min",
103   "sat",
104   "ceil",
105   "floor",
106   "trunc",
107   "cvt",
108   "set and",
109   "set or",
110   "set xor",
111   "set",
112   "selp",
113   "slct",
114   "rcp",
115   "rsq",
116   "lg2",
117   "sin",
118   "cos",
119   "ex2",
120   "exp",
121   "log",
122   "presin",
123   "preex2",
124   "sqrt",
125   "pow",
126   "bra",
127   "call",
128   "ret",
129   "cont",
130   "break",
131   "preret",
132   "precont",
133   "prebreak",
134   "brkpt",
135   "joinat",
136   "join",
137   "discard",
138   "exit",
139   "membar",
140   "vfetch",
141   "pfetch",
142   "afetch",
143   "export",
144   "linterp",
145   "pinterp",
146   "emit",
147   "restart",
148   "final",
149   "tex",
150   "texbias",
151   "texlod",
152   "texfetch",
153   "texquery",
154   "texgrad",
155   "texgather",
156   "texquerylod",
157   "texcsaa",
158   "texprep",
159   "suldb",
160   "suldp",
161   "sustb",
162   "sustp",
163   "suredb",
164   "suredp",
165   "sulea",
166   "subfm",
167   "suclamp",
168   "sueau",
169   "suq",
170   "madsp",
171   "texbar",
172   "dfdx",
173   "dfdy",
174   "rdsv",
175   "wrsv",
176   "pixld",
177   "quadop",
178   "quadon",
179   "quadpop",
180   "popcnt",
181   "insbf",
182   "extbf",
183   "bfind",
184   "brev",
185   "bmsk",
186   "permt",
187   "sgxt",
188   "atom",
189   "bar",
190   "vadd",
191   "vavg",
192   "vmin",
193   "vmax",
194   "vsad",
195   "vset",
196   "vshr",
197   "vshl",
198   "vsel",
199   "cctl",
200   "shfl",
201   "vote",
202   "bufq",
203   "warpsync",
204   "(invalid)"
205};
206
207static const char *atomSubOpStr[] =
208{
209   "add", "min", "max", "inc", "dec", "and", "or", "xor", "cas", "exch"
210};
211
212static const char *ldstSubOpStr[] =
213{
214   "", "lock", "unlock"
215};
216
217static const char *subfmOpStr[] =
218{
219   "", "3d"
220};
221
222static const char *shflOpStr[] =
223{
224  "idx", "up", "down", "bfly"
225};
226
227static const char *pixldOpStr[] =
228{
229   "count", "covmask", "covered", "offset", "cent_offset", "sampleid"
230};
231
232static const char *rcprsqOpStr[] =
233{
234   "", "64h"
235};
236
237static const char *emitOpStr[] =
238{
239   "", "restart"
240};
241
242static const char *cctlOpStr[] =
243{
244   "", "", "", "", "", "iv", "ivall"
245};
246
247static const char *barOpStr[] =
248{
249   "sync", "arrive", "red and", "red or", "red popc"
250};
251
252static const char *xmadOpCModeStr[] =
253{
254   "clo", "chi", "csfu", "cbcc"
255};
256
257static const char *DataTypeStr[] =
258{
259   "-",
260   "u8", "s8",
261   "u16", "s16",
262   "u32", "s32",
263   "u64", "s64",
264   "f16", "f32", "f64",
265   "b96", "b128"
266};
267
268static const char *RoundModeStr[] =
269{
270   "", "rm", "rz", "rp", "rni", "rmi", "rzi", "rpi"
271};
272
273static const char *CondCodeStr[] =
274{
275   "never",
276   "lt",
277   "eq",
278   "le",
279   "gt",
280   "ne",
281   "ge",
282   "",
283   "(invalid)",
284   "ltu",
285   "equ",
286   "leu",
287   "gtu",
288   "neu",
289   "geu",
290   "",
291   "no",
292   "nc",
293   "ns",
294   "na",
295   "a",
296   "s",
297   "c",
298   "o"
299};
300
301static const char *SemanticStr[] =
302{
303   "POSITION",
304   "VERTEX_ID",
305   "INSTANCE_ID",
306   "INVOCATION_ID",
307   "PRIMITIVE_ID",
308   "VERTEX_COUNT",
309   "LAYER",
310   "VIEWPORT_INDEX",
311   "VIEWPORT_MASK",
312   "Y_DIR",
313   "FACE",
314   "POINT_SIZE",
315   "POINT_COORD",
316   "CLIP_DISTANCE",
317   "SAMPLE_INDEX",
318   "SAMPLE_POS",
319   "SAMPLE_MASK",
320   "TESS_OUTER",
321   "TESS_INNER",
322   "TESS_COORD",
323   "TID",
324   "COMBINED_TID",
325   "CTAID",
326   "NTID",
327   "GRIDID",
328   "NCTAID",
329   "LANEID",
330   "PHYSID",
331   "NPHYSID",
332   "CLOCK",
333   "LBASE",
334   "SBASE",
335   "VERTEX_STRIDE",
336   "INVOCATION_INFO",
337   "THREAD_KILL",
338   "BASEVERTEX",
339   "BASEINSTANCE",
340   "DRAWID",
341   "WORK_DIM",
342   "LANEMASK_EQ",
343   "LANEMASK_LT",
344   "LANEMASK_LE",
345   "LANEMASK_GT",
346   "LANEMASK_GE",
347   "?",
348   "(INVALID)"
349};
350
351static const char *TSStr[17] =
352{
353   "THREAD_STATE_ENUM0",
354   "THREAD_STATE_ENUM1",
355   "THREAD_STATE_ENUM2",
356   "THREAD_STATE_ENUM3",
357   "THREAD_STATE_ENUM4",
358   "TRAP_RETURN_PC_LO",
359   "TRAP_RETURN_PC_HI",
360   "TRAP_RETURN_MASK",
361   "MEXITED",
362   "MKILL",
363   "MACTIVE",
364   "MATEXIT",
365   "OPT_STACK",
366   "API_CALL_DEPTH",
367   "ATEXIT_PC_LO",
368   "ATEXIT_PC_HI",
369   "PQUAD_MACTIVE",
370};
371
372static const char *interpStr[16] =
373{
374   "pass",
375   "mul",
376   "flat",
377   "sc",
378   "cent pass",
379   "cent mul",
380   "cent flat",
381   "cent sc",
382   "off pass",
383   "off mul",
384   "off flat",
385   "off sc",
386   "samp pass",
387   "samp mul",
388   "samp flat",
389   "samp sc"
390};
391
392static const char *texMaskStr[16] =
393{
394   "____",
395   "r___",
396   "_g__",
397   "rg__",
398   "__b_",
399   "r_b_",
400   "_gb_",
401   "rgb_",
402   "___a",
403   "r__a",
404   "_g_a",
405   "rg_a",
406   "__ba",
407   "r_ba",
408   "_gba",
409   "rgba",
410};
411
412static const char *gatherCompStr[4] =
413{
414   "r", "g", "b", "a",
415};
416
417#define PRINT(args...)                                \
418   do {                                               \
419      pos += snprintf(&buf[pos], size - pos, args);   \
420   } while(0)
421
422#define SPACE_PRINT(cond, args...)                      \
423   do {                                                 \
424      if (cond)                                         \
425         buf[pos++] = ' ';                              \
426      pos += snprintf(&buf[pos], size - pos, args);     \
427   } while(0)
428
429#define SPACE()                                    \
430   do {                                            \
431      if (pos < size)                              \
432         buf[pos++] = ' ';                         \
433   } while(0)
434
435int Modifier::print(char *buf, size_t size) const
436{
437   size_t pos = 0;
438
439   if (bits)
440      PRINT("%s", colour[TXT_INSN]);
441
442   size_t base = pos;
443
444   if (bits & NV50_IR_MOD_NOT)
445      PRINT("not");
446   if (bits & NV50_IR_MOD_SAT)
447      SPACE_PRINT(pos > base && pos < size, "sat");
448   if (bits & NV50_IR_MOD_NEG)
449      SPACE_PRINT(pos > base && pos < size, "neg");
450   if (bits & NV50_IR_MOD_ABS)
451      SPACE_PRINT(pos > base && pos < size, "abs");
452
453   return pos;
454}
455
456int LValue::print(char *buf, size_t size, DataType ty) const
457{
458   const char *postFix = "";
459   size_t pos = 0;
460   int idx = join->reg.data.id >= 0 ? join->reg.data.id : id;
461   char p = join->reg.data.id >= 0 ? '$' : '%';
462   char r;
463   int col = TXT_DEFAULT;
464
465   switch (reg.file) {
466   case FILE_GPR:
467      r = 'r'; col = TXT_GPR;
468      if (reg.size == 2) {
469         if (p == '$') {
470            postFix = (idx & 1) ? "h" : "l";
471            idx /= 2;
472         } else {
473            postFix = "s";
474         }
475      } else
476      if (reg.size == 8) {
477         postFix = "d";
478      } else
479      if (reg.size == 16) {
480         postFix = "q";
481      } else
482      if (reg.size == 12) {
483         postFix = "t";
484      }
485      break;
486   case FILE_PREDICATE:
487      r = 'p'; col = TXT_REGISTER;
488      if (reg.size == 2)
489         postFix = "d";
490      else
491      if (reg.size == 4)
492         postFix = "q";
493      break;
494   case FILE_FLAGS:
495      r = 'c'; col = TXT_FLAGS;
496      break;
497   case FILE_ADDRESS:
498      r = 'a'; col = TXT_REGISTER;
499      break;
500   case FILE_BARRIER:
501      r = 'b'; col = TXT_REGISTER;
502      break;
503   default:
504      assert(!"invalid file for lvalue");
505      r = '?';
506      break;
507   }
508
509   PRINT("%s%c%c%i%s", colour[col], p, r, idx, postFix);
510
511   return pos;
512}
513
514int ImmediateValue::print(char *buf, size_t size, DataType ty) const
515{
516   size_t pos = 0;
517
518   PRINT("%s", colour[TXT_IMMD]);
519
520   switch (ty) {
521   case TYPE_F32: PRINT("%f", reg.data.f32); break;
522   case TYPE_F64: PRINT("%f", reg.data.f64); break;
523   case TYPE_U8:  PRINT("0x%02x", reg.data.u8); break;
524   case TYPE_S8:  PRINT("%i", reg.data.s8); break;
525   case TYPE_U16: PRINT("0x%04x", reg.data.u16); break;
526   case TYPE_S16: PRINT("%i", reg.data.s16); break;
527   case TYPE_U32: PRINT("0x%08x", reg.data.u32); break;
528   case TYPE_S32: PRINT("%i", reg.data.s32); break;
529   case TYPE_U64:
530   case TYPE_S64:
531   default:
532      PRINT("0x%016" PRIx64, reg.data.u64);
533      break;
534   }
535   return pos;
536}
537
538int Symbol::print(char *buf, size_t size, DataType ty) const
539{
540   return print(buf, size, NULL, NULL, ty);
541}
542
543int Symbol::print(char *buf, size_t size,
544                  Value *rel, Value *dimRel, DataType ty) const
545{
546   STATIC_ASSERT(ARRAY_SIZE(SemanticStr) == SV_LAST + 1);
547
548   size_t pos = 0;
549   char c;
550
551   if (ty == TYPE_NONE)
552      ty = typeOfSize(reg.size);
553
554   if (reg.file == FILE_SYSTEM_VALUE) {
555      PRINT("%ssv[%s%s:%i%s", colour[TXT_MEM],
556            colour[TXT_REGISTER],
557            SemanticStr[reg.data.sv.sv], reg.data.sv.index, colour[TXT_MEM]);
558      if (rel) {
559         PRINT("%s+", colour[TXT_DEFAULT]);
560         pos += rel->print(&buf[pos], size - pos);
561      }
562      PRINT("%s]", colour[TXT_MEM]);
563      return pos;
564   } else if (reg.file == FILE_THREAD_STATE) {
565      PRINT("%sts[%s%s%s]", colour[TXT_MEM], colour[TXT_REGISTER],
566            TSStr[reg.data.ts], colour[TXT_MEM]);
567      return pos;
568   }
569
570   switch (reg.file) {
571   case FILE_MEMORY_CONST:  c = 'c'; break;
572   case FILE_SHADER_INPUT:  c = 'a'; break;
573   case FILE_SHADER_OUTPUT: c = 'o'; break;
574   case FILE_MEMORY_BUFFER: c = 'b'; break; // Only used before lowering
575   case FILE_MEMORY_GLOBAL: c = 'g'; break;
576   case FILE_MEMORY_SHARED: c = 's'; break;
577   case FILE_MEMORY_LOCAL:  c = 'l'; break;
578   case FILE_BARRIER:       c = 'b'; break;
579   default:
580      assert(!"invalid file");
581      c = '?';
582      break;
583   }
584
585   if (c == 'c')
586      PRINT("%s%c%i[", colour[TXT_MEM], c, reg.fileIndex);
587   else
588      PRINT("%s%c[", colour[TXT_MEM], c);
589
590   if (dimRel) {
591      pos += dimRel->print(&buf[pos], size - pos, TYPE_S32);
592      PRINT("%s][", colour[TXT_MEM]);
593   }
594
595   if (rel) {
596      pos += rel->print(&buf[pos], size - pos);
597      PRINT("%s%c", colour[TXT_DEFAULT], (reg.data.offset < 0) ? '-' : '+');
598   } else {
599      assert(reg.data.offset >= 0);
600   }
601   PRINT("%s0x%x%s]", colour[TXT_IMMD], abs(reg.data.offset), colour[TXT_MEM]);
602
603   return pos;
604}
605
606void Instruction::print() const
607{
608   #define BUFSZ 512
609
610   const size_t size = BUFSZ;
611
612   char buf[BUFSZ];
613   int s, d;
614   size_t pos = 0;
615
616   PRINT("%s", colour[TXT_INSN]);
617
618   if (join)
619      PRINT("join ");
620
621   if (predSrc >= 0) {
622      const size_t pre = pos;
623      if (getSrc(predSrc)->reg.file == FILE_PREDICATE) {
624         if (cc == CC_NOT_P)
625            PRINT("not");
626      } else {
627         PRINT("%s", CondCodeStr[cc]);
628      }
629      if (pos > pre)
630         SPACE();
631      pos += getSrc(predSrc)->print(&buf[pos], BUFSZ - pos);
632      PRINT(" %s", colour[TXT_INSN]);
633   }
634
635   if (saturate)
636      PRINT("sat ");
637
638   if (asFlow()) {
639      PRINT("%s", operationStr[op]);
640      if (asFlow()->indirect)
641         PRINT(" ind");
642      if (asFlow()->absolute)
643         PRINT(" abs");
644      if (op == OP_CALL && asFlow()->builtin) {
645         PRINT(" %sBUILTIN:%i", colour[TXT_BRA], asFlow()->target.builtin);
646      } else
647      if (op == OP_CALL && asFlow()->target.fn) {
648         PRINT(" %s%s:%i", colour[TXT_BRA],
649               asFlow()->target.fn->getName(),
650               asFlow()->target.fn->getLabel());
651      } else
652      if (asFlow()->target.bb)
653         PRINT(" %sBB:%i", colour[TXT_BRA], asFlow()->target.bb->getId());
654   } else {
655      if (asTex())
656         PRINT("%s%s ", operationStr[op], asTex()->tex.scalar ? "s" : "");
657      else
658         PRINT("%s ", operationStr[op]);
659      if (op == OP_LINTERP || op == OP_PINTERP)
660         PRINT("%s ", interpStr[ipa]);
661      switch (op) {
662      case OP_SUREDP:
663      case OP_SUREDB:
664      case OP_ATOM:
665         if (subOp < ARRAY_SIZE(atomSubOpStr))
666            PRINT("%s ", atomSubOpStr[subOp]);
667         break;
668      case OP_LOAD:
669      case OP_STORE:
670         if (subOp < ARRAY_SIZE(ldstSubOpStr))
671            PRINT("%s ", ldstSubOpStr[subOp]);
672         break;
673      case OP_SUBFM:
674         if (subOp < ARRAY_SIZE(subfmOpStr))
675            PRINT("%s ", subfmOpStr[subOp]);
676         break;
677      case OP_SHFL:
678         if (subOp < ARRAY_SIZE(shflOpStr))
679            PRINT("%s ", shflOpStr[subOp]);
680         break;
681      case OP_PIXLD:
682         if (subOp < ARRAY_SIZE(pixldOpStr))
683            PRINT("%s ", pixldOpStr[subOp]);
684         break;
685      case OP_RCP:
686      case OP_RSQ:
687         if (subOp < ARRAY_SIZE(rcprsqOpStr))
688            PRINT("%s ", rcprsqOpStr[subOp]);
689         break;
690      case OP_EMIT:
691         if (subOp < ARRAY_SIZE(emitOpStr))
692            PRINT("%s ", emitOpStr[subOp]);
693         break;
694      case OP_CCTL:
695         if (subOp < ARRAY_SIZE(cctlOpStr))
696            PRINT("%s ", cctlOpStr[subOp]);
697         break;
698      case OP_BAR:
699         if (subOp < ARRAY_SIZE(barOpStr))
700            PRINT("%s ", barOpStr[subOp]);
701         break;
702      case OP_XMAD: {
703         if (subOp & NV50_IR_SUBOP_XMAD_PSL)
704            PRINT("psl ");
705         if (subOp & NV50_IR_SUBOP_XMAD_MRG)
706            PRINT("mrg ");
707         unsigned cmode = (subOp & NV50_IR_SUBOP_XMAD_CMODE_MASK);
708         cmode >>= NV50_IR_SUBOP_XMAD_CMODE_SHIFT;
709         if (cmode && cmode <= ARRAY_SIZE(xmadOpCModeStr))
710            PRINT("%s ", xmadOpCModeStr[cmode - 1]);
711         for (int i = 0; i < 2; i++)
712            PRINT("h%d ", (subOp & NV50_IR_SUBOP_XMAD_H1(i)) ? 1 : 0);
713         break;
714      }
715      default:
716         if (subOp)
717            PRINT("(SUBOP:%u) ", subOp);
718         break;
719      }
720      if (perPatch)
721         PRINT("patch ");
722      if (asTex()) {
723         PRINT("%s %s$r%u $s%u ", asTex()->tex.target.getName(),
724               colour[TXT_MEM], asTex()->tex.r, asTex()->tex.s);
725         if (op == OP_TXG)
726            PRINT("%s ", gatherCompStr[asTex()->tex.gatherComp]);
727         PRINT("%s %s", texMaskStr[asTex()->tex.mask], colour[TXT_INSN]);
728      }
729
730      if (postFactor)
731         PRINT("x2^%i ", postFactor);
732      PRINT("%s%s", dnz ? "dnz " : (ftz ? "ftz " : ""),  DataTypeStr[dType]);
733   }
734
735   if (rnd != ROUND_N)
736      PRINT(" %s", RoundModeStr[rnd]);
737
738   if (defExists(1))
739      PRINT(" {");
740   for (d = 0; defExists(d); ++d) {
741      SPACE();
742      pos += getDef(d)->print(&buf[pos], size - pos);
743   }
744   if (d > 1)
745      PRINT(" %s}", colour[TXT_INSN]);
746   else
747   if (!d && !asFlow())
748      PRINT(" %s#", colour[TXT_INSN]);
749
750   if (asCmp())
751      PRINT(" %s%s", colour[TXT_INSN], CondCodeStr[asCmp()->setCond]);
752
753   if (sType != dType)
754      PRINT(" %s%s", colour[TXT_INSN], DataTypeStr[sType]);
755
756   for (s = 0; srcExists(s); ++s) {
757      if (s == predSrc || src(s).usedAsPtr)
758         continue;
759      const size_t pre = pos;
760      SPACE();
761      pos += src(s).mod.print(&buf[pos], BUFSZ - pos);
762      if (pos > pre + 1)
763         SPACE();
764      if (src(s).isIndirect(0) || src(s).isIndirect(1))
765         pos += getSrc(s)->asSym()->print(&buf[pos], BUFSZ - pos,
766                                          getIndirect(s, 0),
767                                          getIndirect(s, 1));
768      else
769         pos += getSrc(s)->print(&buf[pos], BUFSZ - pos, sType);
770   }
771   if (exit)
772      PRINT("%s exit", colour[TXT_INSN]);
773
774   PRINT("%s", colour[TXT_DEFAULT]);
775
776   buf[MIN2(pos, BUFSZ - 1)] = 0;
777
778   INFO("%s (%u)\n", buf, encSize);
779}
780
781class PrintPass : public Pass
782{
783public:
784   PrintPass(bool omitLineNum) : serial(0), omit_serial(omitLineNum) { }
785
786   virtual bool visit(Function *);
787   virtual bool visit(BasicBlock *);
788   virtual bool visit(Instruction *);
789
790private:
791   int serial;
792   bool omit_serial;
793};
794
795bool
796PrintPass::visit(Function *fn)
797{
798   char str[16];
799
800   INFO("\n%s:%i (", fn->getName(), fn->getLabel());
801
802   if (!fn->outs.empty())
803      INFO("out");
804   for (std::deque<ValueRef>::iterator it = fn->outs.begin();
805        it != fn->outs.end();
806        ++it) {
807      it->get()->print(str, sizeof(str), typeOfSize(it->get()->reg.size));
808      INFO(" %s", str);
809   }
810
811   if (!fn->ins.empty())
812      INFO("%s%sin", colour[TXT_DEFAULT], fn->outs.empty() ? "" : ", ");
813   for (std::deque<ValueDef>::iterator it = fn->ins.begin();
814        it != fn->ins.end();
815        ++it) {
816      it->get()->print(str, sizeof(str), typeOfSize(it->get()->reg.size));
817      INFO(" %s", str);
818   }
819   INFO("%s)\n", colour[TXT_DEFAULT]);
820
821   return true;
822}
823
824bool
825PrintPass::visit(BasicBlock *bb)
826{
827#if 0
828   INFO("---\n");
829   for (Graph::EdgeIterator ei = bb->cfg.incident(); !ei.end(); ei.next())
830      INFO(" <- BB:%i (%s)\n",
831           BasicBlock::get(ei.getNode())->getId(),
832           ei.getEdge()->typeStr());
833#endif
834   INFO("BB:%i (%u instructions) - ", bb->getId(), bb->getInsnCount());
835
836   if (bb->idom())
837      INFO("idom = BB:%i, ", bb->idom()->getId());
838
839   INFO("df = { ");
840   for (DLList::Iterator df = bb->getDF().iterator(); !df.end(); df.next())
841      INFO("BB:%i ", BasicBlock::get(df)->getId());
842
843   INFO("}\n");
844
845   for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next())
846      INFO(" -> BB:%i (%s)\n",
847           BasicBlock::get(ei.getNode())->getId(),
848           ei.getEdge()->typeStr());
849
850   return true;
851}
852
853bool
854PrintPass::visit(Instruction *insn)
855{
856   if (omit_serial)
857      INFO("     ");
858   else
859      INFO("%3i: ", serial);
860   serial++;
861   insn->print();
862   return true;
863}
864
865void
866Function::print()
867{
868   PrintPass pass(prog->driver->omitLineNum);
869   pass.run(this, true, false);
870}
871
872void
873Program::print()
874{
875   PrintPass pass(driver->omitLineNum);
876   init_colours();
877   pass.run(this, true, false);
878}
879
880void
881Function::printLiveIntervals() const
882{
883   INFO("printing live intervals ...\n");
884
885   for (ArrayList::Iterator it = allLValues.iterator(); !it.end(); it.next()) {
886      const Value *lval = Value::get(it)->asLValue();
887      if (lval && !lval->livei.isEmpty()) {
888         INFO("livei(%%%i): ", lval->id);
889         lval->livei.print();
890      }
891   }
892}
893
894} // namespace nv50_ir
895
896extern void
897nv50_ir_prog_info_out_print(struct nv50_ir_prog_info_out *info_out)
898{
899   int i;
900
901   INFO("{\n");
902   INFO("   \"target\":\"%d\",\n", info_out->target);
903   INFO("   \"type\":\"%d\",\n", info_out->type);
904
905   // Bin
906   INFO("   \"bin\":{\n");
907   INFO("      \"maxGPR\":\"%d\",\n", info_out->bin.maxGPR);
908   INFO("      \"tlsSpace\":\"%d\",\n", info_out->bin.tlsSpace);
909   INFO("      \"smemSize\":\"%d\",\n", info_out->bin.smemSize);
910   INFO("      \"codeSize\":\"%d\",\n", info_out->bin.codeSize);
911   INFO("      \"instructions\":\"%d\",\n", info_out->bin.instructions);
912
913   // RelocInfo
914   INFO("      \"RelocInfo\":");
915   if (!info_out->bin.relocData) {
916      INFO("\"NULL\",\n");
917   } else {
918      nv50_ir::RelocInfo *reloc = (nv50_ir::RelocInfo *)info_out->bin.relocData;
919      INFO("{\n");
920      INFO("         \"codePos\":\"%d\",\n", reloc->codePos);
921      INFO("         \"libPos\":\"%d\",\n", reloc->libPos);
922      INFO("         \"dataPos\":\"%d\",\n", reloc->dataPos);
923      INFO("         \"count\":\"%d\",\n", reloc->count);
924      INFO("         \"RelocEntry\":[\n");
925      for (unsigned int i = 0; i < reloc->count; i++) {
926         INFO("            {\"data\":\"%d\",\t\"mask\":\"%d\",\t\"offset\":\"%d\",\t\"bitPos\":\"%d\",\t\"type\":\"%d\"}",
927                   reloc->entry[i].data, reloc->entry[i].mask, reloc->entry[i].offset, reloc->entry[i].bitPos, reloc->entry[i].type
928                   );
929      }
930      INFO("\n");
931      INFO("         ]\n");
932      INFO("      },\n");
933   }
934
935   // FixupInfo
936   INFO("      \"FixupInfo\":");
937   if (!info_out->bin.fixupData) {
938      INFO("\"NULL\"\n");
939   } else {
940      nv50_ir::FixupInfo *fixup = (nv50_ir::FixupInfo *)info_out->bin.fixupData;
941      INFO("{\n");
942      INFO("         \"count\":\"%d\"\n", fixup->count);
943      INFO("         \"FixupEntry\":[\n");
944      for (unsigned int i = 0; i < fixup->count; i++) {
945         INFO("            {\"apply\":\"%p\",\t\"ipa\":\"%d\",\t\"reg\":\"%d\",\t\"loc\":\"%d\"}\n",
946                   fixup->entry[i].apply, fixup->entry[i].ipa, fixup->entry[i].reg, fixup->entry[i].loc);
947      }
948      INFO("\n");
949      INFO("         ]\n");
950      INFO("      }\n");
951
952      INFO("   },\n");
953   }
954
955   if (info_out->numSysVals) {
956      INFO("   \"sv\":[\n");
957      for (i = 0; i < info_out->numSysVals; i++) {
958         if (&(info_out->sv[i])) {
959            INFO("      {\"id\":\"%d\", \"sn\":\"%d\", \"si\":\"%d\"}\n",
960                   info_out->sv[i].id, info_out->sv[i].sn, info_out->sv[i].si);
961         }
962      }
963      INFO("\n   ],\n");
964   }
965   if (info_out->numInputs) {
966      INFO("   \"in\":[\n");
967      for (i = 0; i < info_out->numInputs; i++) {
968         if (&(info_out->in[i])) {
969            INFO("      {\"id\":\"%d\",\t\"sn\":\"%d\",\t\"si\":\"%d\"}\n",
970                info_out->in[i].id, info_out->in[i].sn, info_out->in[i].si);
971         }
972      }
973      INFO("\n   ],\n");
974   }
975   if (info_out->numOutputs) {
976      INFO("   \"out\":[\n");
977      for (i = 0; i < info_out->numOutputs; i++) {
978         if (&(info_out->out[i])) {
979            INFO("      {\"id\":\"%d\",\t\"sn\":\"%d\",\t\"si\":\"%d\"}\n",
980                   info_out->out[i].id, info_out->out[i].sn, info_out->out[i].si);
981         }
982      }
983      INFO("\n   ],\n");
984   }
985
986   INFO("   \"numInputs\":\"%d\",\n", info_out->numInputs);
987   INFO("   \"numOutputs\":\"%d\",\n", info_out->numOutputs);
988   INFO("   \"numPatchConstants\":\"%d\",\n", info_out->numPatchConstants);
989   INFO("   \"numSysVals\":\"%d\",\n", info_out->numSysVals);
990
991   INFO("   \"prop\":{\n");
992   switch (info_out->type) {
993      case PIPE_SHADER_VERTEX:
994         INFO("      \"vp\": {\"usesDrawParameters\":\"%s\"}\n",
995               info_out->prop.vp.usesDrawParameters ? "true" : "false");
996         break;
997      case PIPE_SHADER_TESS_CTRL:
998      case PIPE_SHADER_TESS_EVAL:
999         INFO("      \"tp\":{\n");
1000         INFO("         \"outputPatchSize\":\"%d\"\n", info_out->prop.tp.outputPatchSize);
1001         INFO("         \"partitioning\":\"%d\"\n", info_out->prop.tp.partitioning);
1002         INFO("         \"winding\":\"%d\"\n", info_out->prop.tp.winding);
1003         INFO("         \"domain\":\"%d\"\n", info_out->prop.tp.domain);
1004         INFO("         \"outputPrim\":\"%d\"\n", info_out->prop.tp.outputPrim);
1005         break;
1006      case PIPE_SHADER_GEOMETRY:
1007         INFO("      \"gp\":{\n");
1008         INFO("         \"outputPrim\":\"%d\"\n", info_out->prop.gp.outputPrim);
1009         INFO("         \"instancesCount\":\"%d\"\n", info_out->prop.gp.instanceCount);
1010         INFO("         \"maxVertices\":\"%d\"\n", info_out->prop.gp.maxVertices);
1011         break;
1012      case PIPE_SHADER_FRAGMENT:
1013         INFO("      \"fp\":{\n");
1014         INFO("         \"numColourResults\":\"%d\"\n", info_out->prop.fp.numColourResults);
1015         INFO("         \"writesDepth\":\"%s\"\n", info_out->prop.fp.writesDepth ? "true" : "false");
1016         INFO("         \"earlyFragTests\":\"%s\"\n", info_out->prop.fp.earlyFragTests ? "true" : "false");
1017         INFO("         \"postDepthCoverage\":\"%s\"\n", info_out->prop.fp.postDepthCoverage ? "true" : "false");
1018         INFO("         \"usesDiscard\":\"%s\"\n", info_out->prop.fp.usesDiscard ? "true" : "false");
1019         INFO("         \"usesSampleMaskIn\":\"%s\"\n", info_out->prop.fp.usesSampleMaskIn ? "true" : "false");
1020         INFO("         \"readsFramebuffer\":\"%s\"\n", info_out->prop.fp.readsFramebuffer ? "true" : "false");
1021         INFO("         \"readsSampleLocations\":\"%s\"\n", info_out->prop.fp.readsSampleLocations ? "true" : "false");
1022         INFO("         \"separateFragData\":\"%s\"\n", info_out->prop.fp.separateFragData ? "true" : "false");
1023         break;
1024      default:
1025         assert("!unhandled pipe shader type\n");
1026   }
1027   INFO("      }\n");
1028   INFO("   }\n");
1029
1030   INFO("   \"io\":{\n");
1031   INFO("      \"clipDistances\":\"%d\"\n", info_out->io.clipDistances);
1032   INFO("      \"cullDistances\":\"%d\"\n", info_out->io.cullDistances);
1033   INFO("      \"genUserClip\":\"%d\"\n", info_out->io.genUserClip);
1034   INFO("      \"instanceId\":\"%d\"\n", info_out->io.instanceId);
1035   INFO("      \"vertexId\":\"%d\"\n", info_out->io.vertexId);
1036   INFO("      \"edgeFlagIn\":\"%d\"\n", info_out->io.edgeFlagIn);
1037   INFO("      \"edgeFlagOut\":\"%d\"\n", info_out->io.edgeFlagOut);
1038   INFO("      \"fragDepth\":\"%d\"\n", info_out->io.fragDepth);
1039   INFO("      \"sampleMask\":\"%d\"\n", info_out->io.sampleMask);
1040   INFO("      \"globalAccess\":\"%d\"\n", info_out->io.globalAccess);
1041   INFO("      \"fp64\":\"%s\"\n", info_out->io.fp64 ? "true" : "false");
1042   INFO("      \"layer_viewport_relative\":\"%s\"\n", info_out->io.layer_viewport_relative ? "true" : "false");
1043   INFO("   \"}\n");
1044   INFO("   \"numBarriers\":\"%d\"\n", info_out->numBarriers);
1045   INFO("   \"driverPriv\":\"%p\"\n", info_out->driverPriv);
1046
1047   INFO("}\n");
1048}
1049