nv50,nvc0: hold references to the framebuffer surfaces
[mesa.git] / src / gallium / drivers / nv50 / codegen / nv50_ir_print.cpp
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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #include "nv50_ir.h"
24 #include "nv50_ir_target.h"
25
26 namespace nv50_ir {
27
28 enum TextStyle
29 {
30 TXT_DEFAULT,
31 TXT_GPR,
32 TXT_REGISTER,
33 TXT_FLAGS,
34 TXT_MEM,
35 TXT_IMMD,
36 TXT_BRA,
37 TXT_INSN
38 };
39
40 static const char *colour[8] =
41 {
42 #if 1
43 "\x1b[00m",
44 "\x1b[34m",
45 "\x1b[35m",
46 "\x1b[35m",
47 "\x1b[36m",
48 "\x1b[33m",
49 "\x1b[37m",
50 "\x1b[32m"
51 #else
52 "", "", "", "", "", "", "", ""
53 #endif
54 };
55
56 const char *operationStr[OP_LAST + 1] =
57 {
58 "nop",
59 "phi",
60 "union",
61 "split",
62 "merge",
63 "consec",
64 "mov",
65 "ld",
66 "st",
67 "add",
68 "sub",
69 "mul",
70 "div",
71 "mod",
72 "mad",
73 "fma",
74 "sad",
75 "abs",
76 "neg",
77 "not",
78 "and",
79 "or",
80 "xor",
81 "shl",
82 "shr",
83 "max",
84 "min",
85 "sat",
86 "ceil",
87 "floor",
88 "trunc",
89 "cvt",
90 "set and",
91 "set or",
92 "set xor",
93 "set",
94 "selp",
95 "slct",
96 "rcp",
97 "rsq",
98 "lg2",
99 "sin",
100 "cos",
101 "ex2",
102 "exp",
103 "log",
104 "presin",
105 "preex2",
106 "sqrt",
107 "pow",
108 "bra",
109 "call",
110 "ret",
111 "cont",
112 "break",
113 "preret",
114 "precont",
115 "prebreak",
116 "brkpt",
117 "joinat",
118 "join",
119 "discard",
120 "exit",
121 "barrier",
122 "vfetch",
123 "pfetch",
124 "export",
125 "linterp",
126 "pinterp",
127 "emit",
128 "restart",
129 "tex",
130 "texbias",
131 "texlod",
132 "texfetch",
133 "texquery",
134 "texgrad",
135 "texgather",
136 "texcsaa",
137 "suld",
138 "sust",
139 "dfdx",
140 "dfdy",
141 "rdsv",
142 "wrsv",
143 "pixld",
144 "quadop",
145 "quadon",
146 "quadpop",
147 "popcnt",
148 "insbf",
149 "extbf",
150 "(invalid)"
151 };
152
153 static const char *DataTypeStr[] =
154 {
155 "-",
156 "u8", "s8",
157 "u16", "s16",
158 "u32", "s32",
159 "u64", "s64",
160 "f16", "f32", "f64",
161 "b96", "b128"
162 };
163
164 static const char *RoundModeStr[] =
165 {
166 "", "rm", "rz", "rp", "rni", "rmi", "rzi", "rpi"
167 };
168
169 static const char *CondCodeStr[] =
170 {
171 "never",
172 "lt",
173 "eq",
174 "le",
175 "gt",
176 "ne",
177 "ge",
178 "",
179 "(invalid)",
180 "ltu",
181 "equ",
182 "leu",
183 "gtu",
184 "neu",
185 "geu",
186 "",
187 "no",
188 "nc",
189 "ns",
190 "na",
191 "a",
192 "s",
193 "c",
194 "o"
195 };
196
197 static const char *SemanticStr[SV_LAST + 1] =
198 {
199 "POSITION",
200 "VERTEX_ID",
201 "INSTANCE_ID",
202 "INVOCATION_ID",
203 "PRIMITIVE_ID",
204 "VERTEX_COUNT",
205 "LAYER",
206 "VIEWPORT_INDEX",
207 "Y_DIR",
208 "FACE",
209 "POINT_SIZE",
210 "POINT_COORD",
211 "CLIP_DISTANCE",
212 "SAMPLE_INDEX",
213 "TESS_FACTOR",
214 "TESS_COORD",
215 "TID",
216 "CTAID",
217 "NTID",
218 "GRIDID",
219 "NCTAID",
220 "LANEID",
221 "PHYSID",
222 "NPHYSID",
223 "CLOCK",
224 "LBASE",
225 "SBASE",
226 "?",
227 "(INVALID)"
228 };
229
230 #define PRINT(args...) \
231 do { \
232 pos += snprintf(&buf[pos], size - pos, args); \
233 } while(0)
234
235 #define SPACE_PRINT(cond, args...) \
236 do { \
237 if (cond) \
238 buf[pos++] = ' '; \
239 pos += snprintf(&buf[pos], size - pos, args); \
240 } while(0)
241
242 #define SPACE() \
243 do { \
244 if (pos < size) \
245 buf[pos++] = ' '; \
246 } while(0)
247
248 int Modifier::print(char *buf, size_t size) const
249 {
250 size_t pos = 0;
251
252 if (bits)
253 PRINT("%s", colour[TXT_INSN]);
254
255 size_t base = pos;
256
257 if (bits & NV50_IR_MOD_NOT)
258 PRINT("not");
259 if (bits & NV50_IR_MOD_SAT)
260 SPACE_PRINT(pos > base && pos < size, "sat");
261 if (bits & NV50_IR_MOD_NEG)
262 SPACE_PRINT(pos > base && pos < size, "neg");
263 if (bits & NV50_IR_MOD_ABS)
264 SPACE_PRINT(pos > base && pos < size, "abs");
265
266 return pos;
267 }
268
269 int LValue::print(char *buf, size_t size, DataType ty) const
270 {
271 const char *postFix = "";
272 size_t pos = 0;
273 int idx = join->reg.data.id >= 0 ? join->reg.data.id : id;
274 char p = join->reg.data.id >= 0 ? '$' : '%';
275 char r;
276 int col = TXT_DEFAULT;
277
278 switch (reg.file) {
279 case FILE_GPR:
280 r = 'r'; col = TXT_GPR;
281 if (reg.size == 8)
282 postFix = "d";
283 else
284 if (reg.size == 16)
285 postFix = "q";
286 break;
287 case FILE_PREDICATE:
288 r = 'p'; col = TXT_REGISTER;
289 if (reg.size == 2)
290 postFix = "d";
291 else
292 if (reg.size == 4)
293 postFix = "q";
294 break;
295 case FILE_FLAGS:
296 r = 'c'; col = TXT_FLAGS;
297 break;
298 case FILE_ADDRESS:
299 r = 'a'; col = TXT_REGISTER;
300 break;
301 default:
302 assert(!"invalid file for lvalue");
303 r = '?';
304 break;
305 }
306
307 PRINT("%s%c%c%i%s", colour[col], p, r, idx, postFix);
308
309 return pos;
310 }
311
312 int ImmediateValue::print(char *buf, size_t size, DataType ty) const
313 {
314 size_t pos = 0;
315
316 PRINT("%s", colour[TXT_IMMD]);
317
318 switch (ty) {
319 case TYPE_F32: PRINT("%f", reg.data.f32); break;
320 case TYPE_F64: PRINT("%f", reg.data.f64); break;
321 case TYPE_U8: PRINT("0x%02x", reg.data.u8); break;
322 case TYPE_S8: PRINT("%i", reg.data.s8); break;
323 case TYPE_U16: PRINT("0x%04x", reg.data.u16); break;
324 case TYPE_S16: PRINT("%i", reg.data.s16); break;
325 case TYPE_U32: PRINT("0x%08x", reg.data.u32); break;
326 case TYPE_S32: PRINT("%i", reg.data.s32); break;
327 case TYPE_U64:
328 case TYPE_S64:
329 default:
330 PRINT("0x%016lx", reg.data.u64);
331 break;
332 }
333 return pos;
334 }
335
336 int Symbol::print(char *buf, size_t size, DataType ty) const
337 {
338 return print(buf, size, NULL, NULL, ty);
339 }
340
341 int Symbol::print(char *buf, size_t size,
342 Value *rel, Value *dimRel, DataType ty) const
343 {
344 size_t pos = 0;
345 char c;
346
347 if (ty == TYPE_NONE)
348 ty = typeOfSize(reg.size);
349
350 if (reg.file == FILE_SYSTEM_VALUE) {
351 PRINT("%ssv[%s%s:%i%s", colour[TXT_MEM],
352 colour[TXT_REGISTER],
353 SemanticStr[reg.data.sv.sv], reg.data.sv.index, colour[TXT_MEM]);
354 if (rel) {
355 PRINT("%s+", colour[TXT_DEFAULT]);
356 pos += rel->print(&buf[pos], size - pos);
357 }
358 PRINT("%s]", colour[TXT_MEM]);
359 return pos;
360 }
361
362 switch (reg.file) {
363 case FILE_MEMORY_CONST: c = 'c'; break;
364 case FILE_SHADER_INPUT: c = 'a'; break;
365 case FILE_SHADER_OUTPUT: c = 'o'; break;
366 case FILE_MEMORY_GLOBAL: c = 'g'; break;
367 case FILE_MEMORY_SHARED: c = 's'; break;
368 case FILE_MEMORY_LOCAL: c = 'l'; break;
369 default:
370 assert(!"invalid file");
371 c = '?';
372 break;
373 }
374
375 if (c == 'c')
376 PRINT("%s%c%i[", colour[TXT_MEM], c, reg.fileIndex);
377 else
378 PRINT("%s%c[", colour[TXT_MEM], c);
379
380 if (dimRel) {
381 pos += dimRel->print(&buf[pos], size - pos, TYPE_S32);
382 PRINT("%s][", colour[TXT_MEM]);
383 }
384
385 if (rel) {
386 pos += rel->print(&buf[pos], size - pos);
387 PRINT("%s%c", colour[TXT_DEFAULT], (reg.data.offset < 0) ? '-' : '+');
388 } else {
389 assert(reg.data.offset >= 0);
390 }
391 PRINT("%s0x%x%s]", colour[TXT_IMMD], abs(reg.data.offset), colour[TXT_MEM]);
392
393 return pos;
394 }
395
396 void Instruction::print() const
397 {
398 #define BUFSZ 512
399
400 const size_t size = BUFSZ;
401
402 char buf[BUFSZ];
403 int s, d;
404 size_t pos = 0;
405
406 PRINT("%s", colour[TXT_INSN]);
407
408 if (join)
409 PRINT("join ");
410
411 if (predSrc >= 0) {
412 const size_t pre = pos;
413 if (getSrc(predSrc)->reg.file == FILE_PREDICATE) {
414 if (cc == CC_NOT_P)
415 PRINT("not");
416 } else {
417 PRINT("%s", CondCodeStr[cc]);
418 }
419 if (pos > pre + 1)
420 SPACE();
421 pos += src[predSrc].get()->print(&buf[pos], BUFSZ - pos);
422 PRINT(" %s", colour[TXT_INSN]);
423 }
424
425 if (saturate)
426 PRINT("sat ");
427
428 if (asFlow()) {
429 PRINT("%s", operationStr[op]);
430 if (op == OP_CALL && asFlow()->builtin) {
431 PRINT(" %sBUILTIN:%i", colour[TXT_BRA], asFlow()->target.builtin);
432 } else
433 if (op == OP_CALL && asFlow()->target.fn) {
434 PRINT(" %s%s", colour[TXT_BRA], asFlow()->target.fn->getName());
435 } else
436 if (asFlow()->target.bb)
437 PRINT(" %sBB:%i", colour[TXT_BRA], asFlow()->target.bb->getId());
438 } else {
439 PRINT("%s ", operationStr[op]);
440 if (subOp)
441 PRINT("(SUBOP:%u) ", subOp);
442 if (perPatch)
443 PRINT("patch ");
444 if (asTex())
445 PRINT("%s ", asTex()->tex.target.getName());
446 if (postFactor)
447 PRINT("x2^%i ", postFactor);
448 PRINT("%s%s", dnz ? "dnz " : (ftz ? "ftz " : ""), DataTypeStr[dType]);
449 }
450
451 if (rnd != ROUND_N)
452 PRINT(" %s", RoundModeStr[rnd]);
453
454 if (def[1].exists())
455 PRINT(" {");
456 for (d = 0; defExists(d); ++d) {
457 SPACE();
458 pos += def[d].get()->print(&buf[pos], size - pos);
459 }
460 if (d > 1)
461 PRINT(" %s}", colour[TXT_INSN]);
462 else
463 if (!d && !asFlow())
464 PRINT(" %s#", colour[TXT_INSN]);
465
466 if (asCmp())
467 PRINT(" %s%s", colour[TXT_INSN], CondCodeStr[asCmp()->setCond]);
468
469 if (sType != dType)
470 PRINT(" %s%s", colour[TXT_INSN], DataTypeStr[sType]);
471
472 for (s = 0; srcExists(s); ++s) {
473 if (s == predSrc || src[s].usedAsPtr)
474 continue;
475 const size_t pre = pos;
476 SPACE();
477 pos += src[s].mod.print(&buf[pos], BUFSZ - pos);
478 if (pos > pre + 1)
479 SPACE();
480 if (src[s].isIndirect(0) || src[s].isIndirect(1))
481 pos += src[s].get()->asSym()->print(&buf[pos], BUFSZ - pos,
482 getIndirect(s, 0),
483 getIndirect(s, 1));
484 else
485 pos += src[s].get()->print(&buf[pos], BUFSZ - pos, sType);
486 }
487
488 PRINT("%s", colour[TXT_DEFAULT]);
489
490 buf[MIN2(pos, BUFSZ - 1)] = 0;
491
492 INFO("%s (%u)\n", buf, encSize);
493 }
494
495 class PrintPass : public Pass
496 {
497 public:
498 PrintPass() : serial(0) { }
499
500 virtual bool visit(Function *);
501 virtual bool visit(BasicBlock *);
502 virtual bool visit(Instruction *);
503
504 private:
505 int serial;
506 };
507
508 bool
509 PrintPass::visit(Function *fn)
510 {
511 INFO("\n%s:\n", fn->getName());
512
513 return true;
514 }
515
516 bool
517 PrintPass::visit(BasicBlock *bb)
518 {
519 #if 0
520 INFO("---\n");
521 for (Graph::EdgeIterator ei = bb->cfg.incident(); !ei.end(); ei.next())
522 INFO(" <- BB:%i (%s)\n",
523 BasicBlock::get(ei.getNode())->getId(),
524 ei.getEdge()->typeStr());
525 #endif
526 INFO("BB:%i (%u instructions) - ", bb->getId(), bb->getInsnCount());
527
528 if (bb->idom())
529 INFO("idom = BB:%i, ", bb->idom()->getId());
530
531 INFO("df = { ");
532 for (DLList::Iterator df = bb->getDF().iterator(); !df.end(); df.next())
533 INFO("BB:%i ", BasicBlock::get(df)->getId());
534
535 INFO("}\n");
536
537 for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next())
538 INFO(" -> BB:%i (%s)\n",
539 BasicBlock::get(ei.getNode())->getId(),
540 ei.getEdge()->typeStr());
541
542 return true;
543 }
544
545 bool
546 PrintPass::visit(Instruction *insn)
547 {
548 INFO("%3i: ", serial++);
549 insn->print();
550 return true;
551 }
552
553 void
554 Function::print()
555 {
556 PrintPass pass;
557 pass.run(this, true, false);
558 }
559
560 void
561 Program::print()
562 {
563 PrintPass pass;
564 pass.run(this, true, false);
565 }
566
567 void
568 Function::printLiveIntervals() const
569 {
570 INFO("printing live intervals ...\n");
571
572 for (ArrayList::Iterator it = allLValues.iterator(); !it.end(); it.next()) {
573 const Value *lval = Value::get(it)->asLValue();
574 if (lval && !lval->livei.isEmpty()) {
575 INFO("livei(%%%i): ", lval->id);
576 lval->livei.print();
577 }
578 }
579 }
580
581 } // namespace nv50_ir