Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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.  
  26. #define __STDC_FORMAT_MACROS
  27. #include <inttypes.h>
  28.  
  29. namespace nv50_ir {
  30.  
  31. enum 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.  
  43. static 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.  
  55. static const char *_nocolour[8] =
  56. {
  57.       "", "", "", "", "", "", "", ""
  58. };
  59.  
  60. static const char **colour;
  61.  
  62. static void init_colours()
  63. {
  64.    if (getenv("NV50_PROG_DEBUG_NO_COLORS") != NULL)
  65.       colour = _nocolour;
  66.    else
  67.       colour = _colour;
  68. }
  69.  
  70. const 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.    "abs",
  90.    "neg",
  91.    "not",
  92.    "and",
  93.    "or",
  94.    "xor",
  95.    "shl",
  96.    "shr",
  97.    "max",
  98.    "min",
  99.    "sat",
  100.    "ceil",
  101.    "floor",
  102.    "trunc",
  103.    "cvt",
  104.    "set and",
  105.    "set or",
  106.    "set xor",
  107.    "set",
  108.    "selp",
  109.    "slct",
  110.    "rcp",
  111.    "rsq",
  112.    "lg2",
  113.    "sin",
  114.    "cos",
  115.    "ex2",
  116.    "exp",
  117.    "log",
  118.    "presin",
  119.    "preex2",
  120.    "sqrt",
  121.    "pow",
  122.    "bra",
  123.    "call",
  124.    "ret",
  125.    "cont",
  126.    "break",
  127.    "preret",
  128.    "precont",
  129.    "prebreak",
  130.    "brkpt",
  131.    "joinat",
  132.    "join",
  133.    "discard",
  134.    "exit",
  135.    "membar",
  136.    "vfetch",
  137.    "pfetch",
  138.    "export",
  139.    "linterp",
  140.    "pinterp",
  141.    "emit",
  142.    "restart",
  143.    "tex",
  144.    "texbias",
  145.    "texlod",
  146.    "texfetch",
  147.    "texquery",
  148.    "texgrad",
  149.    "texgather",
  150.    "texcsaa",
  151.    "texprep",
  152.    "suldb",
  153.    "suldp",
  154.    "sustb",
  155.    "sustp",
  156.    "suredb",
  157.    "suredp",
  158.    "sulea",
  159.    "subfm",
  160.    "suclamp",
  161.    "sueau",
  162.    "madsp",
  163.    "texbar",
  164.    "dfdx",
  165.    "dfdy",
  166.    "rdsv",
  167.    "wrsv",
  168.    "quadop",
  169.    "quadon",
  170.    "quadpop",
  171.    "popcnt",
  172.    "insbf",
  173.    "extbf",
  174.    "permt",
  175.    "atom",
  176.    "bar",
  177.    "vadd",
  178.    "vavg",
  179.    "vmin",
  180.    "vmax",
  181.    "vsad",
  182.    "vset",
  183.    "vshr",
  184.    "vshl",
  185.    "vsel",
  186.    "cctl",
  187.    "(invalid)"
  188. };
  189.  
  190. static const char *atomSubOpStr[] =
  191. {
  192.    "add", "min", "max", "inc", "dec", "and", "or", "xor", "cas", "exch"
  193. };
  194.  
  195. static const char *DataTypeStr[] =
  196. {
  197.    "-",
  198.    "u8", "s8",
  199.    "u16", "s16",
  200.    "u32", "s32",
  201.    "u64", "s64",
  202.    "f16", "f32", "f64",
  203.    "b96", "b128"
  204. };
  205.  
  206. static const char *RoundModeStr[] =
  207. {
  208.    "", "rm", "rz", "rp", "rni", "rmi", "rzi", "rpi"
  209. };
  210.  
  211. static const char *CondCodeStr[] =
  212. {
  213.    "never",
  214.    "lt",
  215.    "eq",
  216.    "le",
  217.    "gt",
  218.    "ne",
  219.    "ge",
  220.    "",
  221.    "(invalid)",
  222.    "ltu",
  223.    "equ",
  224.    "leu",
  225.    "gtu",
  226.    "neu",
  227.    "geu",
  228.    "",
  229.    "no",
  230.    "nc",
  231.    "ns",
  232.    "na",
  233.    "a",
  234.    "s",
  235.    "c",
  236.    "o"
  237. };
  238.  
  239. static const char *SemanticStr[SV_LAST + 1] =
  240. {
  241.    "POSITION",
  242.    "VERTEX_ID",
  243.    "INSTANCE_ID",
  244.    "INVOCATION_ID",
  245.    "PRIMITIVE_ID",
  246.    "VERTEX_COUNT",
  247.    "LAYER",
  248.    "VIEWPORT_INDEX",
  249.    "Y_DIR",
  250.    "FACE",
  251.    "POINT_SIZE",
  252.    "POINT_COORD",
  253.    "CLIP_DISTANCE",
  254.    "SAMPLE_INDEX",
  255.    "TESS_FACTOR",
  256.    "TESS_COORD",
  257.    "TID",
  258.    "CTAID",
  259.    "NTID",
  260.    "GRIDID",
  261.    "NCTAID",
  262.    "LANEID",
  263.    "PHYSID",
  264.    "NPHYSID",
  265.    "CLOCK",
  266.    "LBASE",
  267.    "SBASE",
  268.    "?",
  269.    "(INVALID)"
  270. };
  271.  
  272. static const char *interpStr[16] =
  273. {
  274.    "pass",
  275.    "mul",
  276.    "flat",
  277.    "sc",
  278.    "cent pass",
  279.    "cent mul",
  280.    "cent flat",
  281.    "cent sc",
  282.    "off pass",
  283.    "off mul",
  284.    "off flat",
  285.    "off sc",
  286.    "samp pass",
  287.    "samp mul",
  288.    "samp flat",
  289.    "samp sc"
  290. };
  291.  
  292. #define PRINT(args...)                                \
  293.    do {                                               \
  294.       pos += snprintf(&buf[pos], size - pos, args);   \
  295.    } while(0)
  296.  
  297. #define SPACE_PRINT(cond, args...)                      \
  298.    do {                                                 \
  299.       if (cond)                                         \
  300.          buf[pos++] = ' ';                              \
  301.       pos += snprintf(&buf[pos], size - pos, args);     \
  302.    } while(0)
  303.  
  304. #define SPACE()                                    \
  305.    do {                                            \
  306.       if (pos < size)                              \
  307.          buf[pos++] = ' ';                         \
  308.    } while(0)
  309.  
  310. int Modifier::print(char *buf, size_t size) const
  311. {
  312.    size_t pos = 0;
  313.  
  314.    if (bits)
  315.       PRINT("%s", colour[TXT_INSN]);
  316.  
  317.    size_t base = pos;
  318.  
  319.    if (bits & NV50_IR_MOD_NOT)
  320.       PRINT("not");
  321.    if (bits & NV50_IR_MOD_SAT)
  322.       SPACE_PRINT(pos > base && pos < size, "sat");
  323.    if (bits & NV50_IR_MOD_NEG)
  324.       SPACE_PRINT(pos > base && pos < size, "neg");
  325.    if (bits & NV50_IR_MOD_ABS)
  326.       SPACE_PRINT(pos > base && pos < size, "abs");
  327.  
  328.    return pos;
  329. }
  330.  
  331. int LValue::print(char *buf, size_t size, DataType ty) const
  332. {
  333.    const char *postFix = "";
  334.    size_t pos = 0;
  335.    int idx = join->reg.data.id >= 0 ? join->reg.data.id : id;
  336.    char p = join->reg.data.id >= 0 ? '$' : '%';
  337.    char r;
  338.    int col = TXT_DEFAULT;
  339.  
  340.    switch (reg.file) {
  341.    case FILE_GPR:
  342.       r = 'r'; col = TXT_GPR;
  343.       if (reg.size == 2) {
  344.          if (p == '$') {
  345.             postFix = (idx & 1) ? "h" : "l";
  346.             idx /= 2;
  347.          } else {
  348.             postFix = "s";
  349.          }
  350.       } else
  351.       if (reg.size == 8) {
  352.          postFix = "d";
  353.       } else
  354.       if (reg.size == 16) {
  355.          postFix = "q";
  356.       } else
  357.       if (reg.size == 12) {
  358.          postFix = "t";
  359.       }
  360.       break;
  361.    case FILE_PREDICATE:
  362.       r = 'p'; col = TXT_REGISTER;
  363.       if (reg.size == 2)
  364.          postFix = "d";
  365.       else
  366.       if (reg.size == 4)
  367.          postFix = "q";
  368.       break;
  369.    case FILE_FLAGS:
  370.       r = 'c'; col = TXT_FLAGS;
  371.       break;
  372.    case FILE_ADDRESS:
  373.       r = 'a'; col = TXT_REGISTER;
  374.       break;
  375.    default:
  376.       assert(!"invalid file for lvalue");
  377.       r = '?';
  378.       break;
  379.    }
  380.  
  381.    PRINT("%s%c%c%i%s", colour[col], p, r, idx, postFix);
  382.  
  383.    return pos;
  384. }
  385.  
  386. int ImmediateValue::print(char *buf, size_t size, DataType ty) const
  387. {
  388.    size_t pos = 0;
  389.  
  390.    PRINT("%s", colour[TXT_IMMD]);
  391.  
  392.    switch (ty) {
  393.    case TYPE_F32: PRINT("%f", reg.data.f32); break;
  394.    case TYPE_F64: PRINT("%f", reg.data.f64); break;
  395.    case TYPE_U8:  PRINT("0x%02x", reg.data.u8); break;
  396.    case TYPE_S8:  PRINT("%i", reg.data.s8); break;
  397.    case TYPE_U16: PRINT("0x%04x", reg.data.u16); break;
  398.    case TYPE_S16: PRINT("%i", reg.data.s16); break;
  399.    case TYPE_U32: PRINT("0x%08x", reg.data.u32); break;
  400.    case TYPE_S32: PRINT("%i", reg.data.s32); break;
  401.    case TYPE_U64:
  402.    case TYPE_S64:
  403.    default:
  404.       PRINT("0x%016"PRIx64, reg.data.u64);
  405.       break;
  406.    }
  407.    return pos;
  408. }
  409.  
  410. int Symbol::print(char *buf, size_t size, DataType ty) const
  411. {
  412.    return print(buf, size, NULL, NULL, ty);
  413. }
  414.  
  415. int Symbol::print(char *buf, size_t size,
  416.                   Value *rel, Value *dimRel, DataType ty) const
  417. {
  418.    size_t pos = 0;
  419.    char c;
  420.  
  421.    if (ty == TYPE_NONE)
  422.       ty = typeOfSize(reg.size);
  423.  
  424.    if (reg.file == FILE_SYSTEM_VALUE) {
  425.       PRINT("%ssv[%s%s:%i%s", colour[TXT_MEM],
  426.             colour[TXT_REGISTER],
  427.             SemanticStr[reg.data.sv.sv], reg.data.sv.index, colour[TXT_MEM]);
  428.       if (rel) {
  429.          PRINT("%s+", colour[TXT_DEFAULT]);
  430.          pos += rel->print(&buf[pos], size - pos);
  431.       }
  432.       PRINT("%s]", colour[TXT_MEM]);
  433.       return pos;
  434.    }
  435.  
  436.    switch (reg.file) {
  437.    case FILE_MEMORY_CONST:  c = 'c'; break;
  438.    case FILE_SHADER_INPUT:  c = 'a'; break;
  439.    case FILE_SHADER_OUTPUT: c = 'o'; break;
  440.    case FILE_MEMORY_GLOBAL: c = 'g'; break;
  441.    case FILE_MEMORY_SHARED: c = 's'; break;
  442.    case FILE_MEMORY_LOCAL:  c = 'l'; break;
  443.    default:
  444.       assert(!"invalid file");
  445.       c = '?';
  446.       break;
  447.    }
  448.  
  449.    if (c == 'c')
  450.       PRINT("%s%c%i[", colour[TXT_MEM], c, reg.fileIndex);
  451.    else
  452.       PRINT("%s%c[", colour[TXT_MEM], c);
  453.  
  454.    if (dimRel) {
  455.       pos += dimRel->print(&buf[pos], size - pos, TYPE_S32);
  456.       PRINT("%s][", colour[TXT_MEM]);
  457.    }
  458.  
  459.    if (rel) {
  460.       pos += rel->print(&buf[pos], size - pos);
  461.       PRINT("%s%c", colour[TXT_DEFAULT], (reg.data.offset < 0) ? '-' : '+');
  462.    } else {
  463.       assert(reg.data.offset >= 0);
  464.    }
  465.    PRINT("%s0x%x%s]", colour[TXT_IMMD], abs(reg.data.offset), colour[TXT_MEM]);
  466.  
  467.    return pos;
  468. }
  469.  
  470. void Instruction::print() const
  471. {
  472.    #define BUFSZ 512
  473.  
  474.    const size_t size = BUFSZ;
  475.  
  476.    char buf[BUFSZ];
  477.    int s, d;
  478.    size_t pos = 0;
  479.  
  480.    PRINT("%s", colour[TXT_INSN]);
  481.  
  482.    if (join)
  483.       PRINT("join ");
  484.  
  485.    if (predSrc >= 0) {
  486.       const size_t pre = pos;
  487.       if (getSrc(predSrc)->reg.file == FILE_PREDICATE) {
  488.          if (cc == CC_NOT_P)
  489.             PRINT("not");
  490.       } else {
  491.          PRINT("%s", CondCodeStr[cc]);
  492.       }
  493.       if (pos > pre)
  494.          SPACE();
  495.       pos += getSrc(predSrc)->print(&buf[pos], BUFSZ - pos);
  496.       PRINT(" %s", colour[TXT_INSN]);
  497.    }
  498.  
  499.    if (saturate)
  500.       PRINT("sat ");
  501.  
  502.    if (asFlow()) {
  503.       PRINT("%s", operationStr[op]);
  504.       if (asFlow()->indirect)
  505.          PRINT(" ind");
  506.       if (asFlow()->absolute)
  507.          PRINT(" abs");
  508.       if (op == OP_CALL && asFlow()->builtin) {
  509.          PRINT(" %sBUILTIN:%i", colour[TXT_BRA], asFlow()->target.builtin);
  510.       } else
  511.       if (op == OP_CALL && asFlow()->target.fn) {
  512.          PRINT(" %s%s:%i", colour[TXT_BRA],
  513.                asFlow()->target.fn->getName(),
  514.                asFlow()->target.fn->getLabel());
  515.       } else
  516.       if (asFlow()->target.bb)
  517.          PRINT(" %sBB:%i", colour[TXT_BRA], asFlow()->target.bb->getId());
  518.    } else {
  519.       PRINT("%s ", operationStr[op]);
  520.       if (op == OP_LINTERP || op == OP_PINTERP)
  521.          PRINT("%s ", interpStr[ipa]);
  522.       switch (op) {
  523.       case OP_SUREDP:
  524.       case OP_ATOM:
  525.          if (subOp < Elements(atomSubOpStr))
  526.             PRINT("%s ", atomSubOpStr[subOp]);
  527.          break;
  528.       default:
  529.          if (subOp)
  530.             PRINT("(SUBOP:%u) ", subOp);
  531.          break;
  532.       }
  533.       if (perPatch)
  534.          PRINT("patch ");
  535.       if (asTex())
  536.          PRINT("%s %s$r%u $s%u %s", asTex()->tex.target.getName(),
  537.                colour[TXT_MEM], asTex()->tex.r, asTex()->tex.s,
  538.                colour[TXT_INSN]);
  539.       if (postFactor)
  540.          PRINT("x2^%i ", postFactor);
  541.       PRINT("%s%s", dnz ? "dnz " : (ftz ? "ftz " : ""),  DataTypeStr[dType]);
  542.    }
  543.  
  544.    if (rnd != ROUND_N)
  545.       PRINT(" %s", RoundModeStr[rnd]);
  546.  
  547.    if (defExists(1))
  548.       PRINT(" {");
  549.    for (d = 0; defExists(d); ++d) {
  550.       SPACE();
  551.       pos += getDef(d)->print(&buf[pos], size - pos);
  552.    }
  553.    if (d > 1)
  554.       PRINT(" %s}", colour[TXT_INSN]);
  555.    else
  556.    if (!d && !asFlow())
  557.       PRINT(" %s#", colour[TXT_INSN]);
  558.  
  559.    if (asCmp())
  560.       PRINT(" %s%s", colour[TXT_INSN], CondCodeStr[asCmp()->setCond]);
  561.  
  562.    if (sType != dType)
  563.       PRINT(" %s%s", colour[TXT_INSN], DataTypeStr[sType]);
  564.  
  565.    for (s = 0; srcExists(s); ++s) {
  566.       if (s == predSrc || src(s).usedAsPtr)
  567.          continue;
  568.       const size_t pre = pos;
  569.       SPACE();
  570.       pos += src(s).mod.print(&buf[pos], BUFSZ - pos);
  571.       if (pos > pre + 1)
  572.          SPACE();
  573.       if (src(s).isIndirect(0) || src(s).isIndirect(1))
  574.          pos += getSrc(s)->asSym()->print(&buf[pos], BUFSZ - pos,
  575.                                           getIndirect(s, 0),
  576.                                           getIndirect(s, 1));
  577.       else
  578.          pos += getSrc(s)->print(&buf[pos], BUFSZ - pos, sType);
  579.    }
  580.    if (exit)
  581.       PRINT("%s exit", colour[TXT_INSN]);
  582.  
  583.    PRINT("%s", colour[TXT_DEFAULT]);
  584.  
  585.    buf[MIN2(pos, BUFSZ - 1)] = 0;
  586.  
  587.    INFO("%s (%u)\n", buf, encSize);
  588. }
  589.  
  590. class PrintPass : public Pass
  591. {
  592. public:
  593.    PrintPass() : serial(0) { }
  594.  
  595.    virtual bool visit(Function *);
  596.    virtual bool visit(BasicBlock *);
  597.    virtual bool visit(Instruction *);
  598.  
  599. private:
  600.    int serial;
  601. };
  602.  
  603. bool
  604. PrintPass::visit(Function *fn)
  605. {
  606.    char str[16];
  607.  
  608.    INFO("\n%s:%i (", fn->getName(), fn->getLabel());
  609.  
  610.    if (!fn->outs.empty())
  611.       INFO("out");
  612.    for (std::deque<ValueRef>::iterator it = fn->outs.begin();
  613.         it != fn->outs.end();
  614.         ++it) {
  615.       it->get()->print(str, sizeof(str), typeOfSize(it->get()->reg.size));
  616.       INFO(" %s", str);
  617.    }
  618.  
  619.    if (!fn->ins.empty())
  620.       INFO("%s%sin", colour[TXT_DEFAULT], fn->outs.empty() ? "" : ", ");
  621.    for (std::deque<ValueDef>::iterator it = fn->ins.begin();
  622.         it != fn->ins.end();
  623.         ++it) {
  624.       it->get()->print(str, sizeof(str), typeOfSize(it->get()->reg.size));
  625.       INFO(" %s", str);
  626.    }
  627.    INFO("%s)\n", colour[TXT_DEFAULT]);
  628.  
  629.    return true;
  630. }
  631.  
  632. bool
  633. PrintPass::visit(BasicBlock *bb)
  634. {
  635. #if 0
  636.    INFO("---\n");
  637.    for (Graph::EdgeIterator ei = bb->cfg.incident(); !ei.end(); ei.next())
  638.       INFO(" <- BB:%i (%s)\n",
  639.            BasicBlock::get(ei.getNode())->getId(),
  640.            ei.getEdge()->typeStr());
  641. #endif
  642.    INFO("BB:%i (%u instructions) - ", bb->getId(), bb->getInsnCount());
  643.  
  644.    if (bb->idom())
  645.       INFO("idom = BB:%i, ", bb->idom()->getId());
  646.  
  647.    INFO("df = { ");
  648.    for (DLList::Iterator df = bb->getDF().iterator(); !df.end(); df.next())
  649.       INFO("BB:%i ", BasicBlock::get(df)->getId());
  650.  
  651.    INFO("}\n");
  652.  
  653.    for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next())
  654.       INFO(" -> BB:%i (%s)\n",
  655.            BasicBlock::get(ei.getNode())->getId(),
  656.            ei.getEdge()->typeStr());
  657.  
  658.    return true;
  659. }
  660.  
  661. bool
  662. PrintPass::visit(Instruction *insn)
  663. {
  664.    INFO("%3i: ", serial++);
  665.    insn->print();
  666.    return true;
  667. }
  668.  
  669. void
  670. Function::print()
  671. {
  672.    PrintPass pass;
  673.    pass.run(this, true, false);
  674. }
  675.  
  676. void
  677. Program::print()
  678. {
  679.    PrintPass pass;
  680.    init_colours();
  681.    pass.run(this, true, false);
  682. }
  683.  
  684. void
  685. Function::printLiveIntervals() const
  686. {
  687.    INFO("printing live intervals ...\n");
  688.  
  689.    for (ArrayList::Iterator it = allLValues.iterator(); !it.end(); it.next()) {
  690.       const Value *lval = Value::get(it)->asLValue();
  691.       if (lval && !lval->livei.isEmpty()) {
  692.          INFO("livei(%%%i): ", lval->id);
  693.          lval->livei.print();
  694.       }
  695.    }
  696. }
  697.  
  698. } // namespace nv50_ir
  699.