2 * Copyright 2011 Christoph Bumiller
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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
24 #include "nv50_ir_target.h"
40 static const char *colour
[8] =
52 "", "", "", "", "", "", "", ""
56 const char *operationStr
[OP_LAST
+ 1] =
153 static const char *DataTypeStr
[] =
164 static const char *RoundModeStr
[] =
166 "", "rm", "rz", "rp", "rni", "rmi", "rzi", "rpi"
169 static const char *CondCodeStr
[] =
197 static const char *SemanticStr
[SV_LAST
+ 1] =
230 #define PRINT(args...) \
232 pos += snprintf(&buf[pos], size - pos, args); \
235 #define SPACE_PRINT(cond, args...) \
239 pos += snprintf(&buf[pos], size - pos, args); \
248 int Modifier::print(char *buf
, size_t size
) const
253 PRINT("%s", colour
[TXT_INSN
]);
257 if (bits
& NV50_IR_MOD_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");
269 int LValue::print(char *buf
, size_t size
, DataType ty
) const
271 const char *postFix
= "";
273 int idx
= join
->reg
.data
.id
>= 0 ? join
->reg
.data
.id
: id
;
274 char p
= join
->reg
.data
.id
>= 0 ? '$' : '%';
276 int col
= TXT_DEFAULT
;
280 r
= 'r'; col
= TXT_GPR
;
288 r
= 'p'; col
= TXT_REGISTER
;
296 r
= 'c'; col
= TXT_FLAGS
;
299 r
= 'a'; col
= TXT_REGISTER
;
302 assert(!"invalid file for lvalue");
307 PRINT("%s%c%c%i%s", colour
[col
], p
, r
, idx
, postFix
);
312 int ImmediateValue::print(char *buf
, size_t size
, DataType ty
) const
316 PRINT("%s", colour
[TXT_IMMD
]);
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;
330 PRINT("0x%016lx", reg
.data
.u64
);
336 int Symbol::print(char *buf
, size_t size
, DataType ty
) const
338 return print(buf
, size
, NULL
, NULL
, ty
);
341 int Symbol::print(char *buf
, size_t size
,
342 Value
*rel
, Value
*dimRel
, DataType ty
) const
348 ty
= typeOfSize(reg
.size
);
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
]);
355 PRINT("%s+", colour
[TXT_DEFAULT
]);
356 pos
+= rel
->print(&buf
[pos
], size
- pos
);
358 PRINT("%s]", colour
[TXT_MEM
]);
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;
370 assert(!"invalid file");
376 PRINT("%s%c%i[", colour
[TXT_MEM
], c
, reg
.fileIndex
);
378 PRINT("%s%c[", colour
[TXT_MEM
], c
);
381 pos
+= dimRel
->print(&buf
[pos
], size
- pos
, TYPE_S32
);
382 PRINT("%s][", colour
[TXT_MEM
]);
386 pos
+= rel
->print(&buf
[pos
], size
- pos
);
387 PRINT("%s%c", colour
[TXT_DEFAULT
], (reg
.data
.offset
< 0) ? '-' : '+');
389 assert(reg
.data
.offset
>= 0);
391 PRINT("%s0x%x%s]", colour
[TXT_IMMD
], abs(reg
.data
.offset
), colour
[TXT_MEM
]);
396 void Instruction::print() const
400 const size_t size
= BUFSZ
;
406 PRINT("%s", colour
[TXT_INSN
]);
412 const size_t pre
= pos
;
413 if (getSrc(predSrc
)->reg
.file
== FILE_PREDICATE
) {
417 PRINT("%s", CondCodeStr
[cc
]);
421 pos
+= src
[predSrc
].get()->print(&buf
[pos
], BUFSZ
- pos
);
422 PRINT(" %s", colour
[TXT_INSN
]);
429 PRINT("%s", operationStr
[op
]);
430 if (op
== OP_CALL
&& asFlow()->builtin
) {
431 PRINT(" %sBUILTIN:%i", colour
[TXT_BRA
], asFlow()->target
.builtin
);
433 if (op
== OP_CALL
&& asFlow()->target
.fn
) {
434 PRINT(" %s%s", colour
[TXT_BRA
], asFlow()->target
.fn
->getName());
436 if (asFlow()->target
.bb
)
437 PRINT(" %sBB:%i", colour
[TXT_BRA
], asFlow()->target
.bb
->getId());
439 PRINT("%s ", operationStr
[op
]);
441 PRINT("(SUBOP:%u) ", subOp
);
445 PRINT("%s ", asTex()->tex
.target
.getName());
447 PRINT("x2^%i ", postFactor
);
448 PRINT("%s%s", dnz
? "dnz " : (ftz
? "ftz " : ""), DataTypeStr
[dType
]);
452 PRINT(" %s", RoundModeStr
[rnd
]);
456 for (d
= 0; defExists(d
); ++d
) {
458 pos
+= def
[d
].get()->print(&buf
[pos
], size
- pos
);
461 PRINT(" %s}", colour
[TXT_INSN
]);
464 PRINT(" %s#", colour
[TXT_INSN
]);
467 PRINT(" %s%s", colour
[TXT_INSN
], CondCodeStr
[asCmp()->setCond
]);
470 PRINT(" %s%s", colour
[TXT_INSN
], DataTypeStr
[sType
]);
472 for (s
= 0; srcExists(s
); ++s
) {
473 if (s
== predSrc
|| src
[s
].usedAsPtr
)
475 const size_t pre
= pos
;
477 pos
+= src
[s
].mod
.print(&buf
[pos
], BUFSZ
- pos
);
480 if (src
[s
].isIndirect(0) || src
[s
].isIndirect(1))
481 pos
+= src
[s
].get()->asSym()->print(&buf
[pos
], BUFSZ
- pos
,
485 pos
+= src
[s
].get()->print(&buf
[pos
], BUFSZ
- pos
, sType
);
488 PRINT("%s", colour
[TXT_DEFAULT
]);
490 buf
[MIN2(pos
, BUFSZ
- 1)] = 0;
492 INFO("%s (%u)\n", buf
, encSize
);
495 class PrintPass
: public Pass
498 PrintPass() : serial(0) { }
500 virtual bool visit(Function
*);
501 virtual bool visit(BasicBlock
*);
502 virtual bool visit(Instruction
*);
509 PrintPass::visit(Function
*fn
)
511 INFO("\n%s:\n", fn
->getName());
517 PrintPass::visit(BasicBlock
*bb
)
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());
526 INFO("BB:%i (%u instructions) - ", bb
->getId(), bb
->getInsnCount());
529 INFO("idom = BB:%i, ", bb
->idom()->getId());
532 for (DLList::Iterator df
= bb
->getDF().iterator(); !df
.end(); df
.next())
533 INFO("BB:%i ", BasicBlock::get(df
)->getId());
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());
546 PrintPass::visit(Instruction
*insn
)
548 INFO("%3i: ", serial
++);
557 pass
.run(this, true, false);
564 pass
.run(this, true, false);
568 Function::printLiveIntervals() const
570 INFO("printing live intervals ...\n");
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
);
581 } // namespace nv50_ir