Home | History | Annotate | Download | only in codegen
      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 "codegen/nv50_ir.h"
     24 #include "codegen/nv50_ir_target.h"
     25 
     26 #include <inttypes.h>
     27 
     28 namespace nv50_ir {
     29 
     30 enum TextStyle
     31 {
     32    TXT_DEFAULT,
     33    TXT_GPR,
     34    TXT_REGISTER,
     35    TXT_FLAGS,
     36    TXT_MEM,
     37    TXT_IMMD,
     38    TXT_BRA,
     39    TXT_INSN
     40 };
     41 
     42 static const char *_colour[8] =
     43 {
     44    "\x1b[00m",
     45    "\x1b[34m",
     46    "\x1b[35m",
     47    "\x1b[35m",
     48    "\x1b[36m",
     49    "\x1b[33m",
     50    "\x1b[37m",
     51    "\x1b[32m"
     52 };
     53 
     54 static const char *_nocolour[8] =
     55 {
     56       "", "", "", "", "", "", "", ""
     57 };
     58 
     59 static const char **colour;
     60 
     61 static void init_colours()
     62 {
     63    if (getenv("NV50_PROG_DEBUG_NO_COLORS") != NULL)
     64       colour = _nocolour;
     65    else
     66       colour = _colour;
     67 }
     68 
     69 const char *operationStr[OP_LAST + 1] =
     70 {
     71    "nop",
     72    "phi",
     73    "union",
     74    "split",
     75    "merge",
     76    "consec",
     77    "mov",
     78    "ld",
     79    "st",
     80    "add",
     81    "sub",
     82    "mul",
     83    "div",
     84    "mod",
     85    "mad",
     86    "fma",
     87    "sad",
     88    "shladd",
     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    "afetch",
    139    "export",
    140    "linterp",
    141    "pinterp",
    142    "emit",
    143    "restart",
    144    "tex",
    145    "texbias",
    146    "texlod",
    147    "texfetch",
    148    "texquery",
    149    "texgrad",
    150    "texgather",
    151    "texquerylod",
    152    "texcsaa",
    153    "texprep",
    154    "suldb",
    155    "suldp",
    156    "sustb",
    157    "sustp",
    158    "suredb",
    159    "suredp",
    160    "sulea",
    161    "subfm",
    162    "suclamp",
    163    "sueau",
    164    "suq",
    165    "madsp",
    166    "texbar",
    167    "dfdx",
    168    "dfdy",
    169    "rdsv",
    170    "wrsv",
    171    "pixld",
    172    "quadop",
    173    "quadon",
    174    "quadpop",
    175    "popcnt",
    176    "insbf",
    177    "extbf",
    178    "bfind",
    179    "permt",
    180    "atom",
    181    "bar",
    182    "vadd",
    183    "vavg",
    184    "vmin",
    185    "vmax",
    186    "vsad",
    187    "vset",
    188    "vshr",
    189    "vshl",
    190    "vsel",
    191    "cctl",
    192    "shfl",
    193    "vote",
    194    "bufq",
    195    "(invalid)"
    196 };
    197 
    198 static const char *atomSubOpStr[] =
    199 {
    200    "add", "min", "max", "inc", "dec", "and", "or", "xor", "cas", "exch"
    201 };
    202 
    203 static const char *ldstSubOpStr[] =
    204 {
    205    "", "lock", "unlock"
    206 };
    207 
    208 static const char *subfmOpStr[] =
    209 {
    210    "", "3d"
    211 };
    212 
    213 static const char *shflOpStr[] =
    214 {
    215   "idx", "up", "down", "bfly"
    216 };
    217 
    218 static const char *pixldOpStr[] =
    219 {
    220    "count", "covmask", "offset", "cent_offset", "sampleid"
    221 };
    222 
    223 static const char *rcprsqOpStr[] =
    224 {
    225    "", "64h"
    226 };
    227 
    228 static const char *emitOpStr[] =
    229 {
    230    "", "restart"
    231 };
    232 
    233 static const char *cctlOpStr[] =
    234 {
    235    "", "", "", "", "", "iv", "ivall"
    236 };
    237 
    238 static const char *barOpStr[] =
    239 {
    240    "sync", "arrive", "red and", "red or", "red popc"
    241 };
    242 
    243 static const char *DataTypeStr[] =
    244 {
    245    "-",
    246    "u8", "s8",
    247    "u16", "s16",
    248    "u32", "s32",
    249    "u64", "s64",
    250    "f16", "f32", "f64",
    251    "b96", "b128"
    252 };
    253 
    254 static const char *RoundModeStr[] =
    255 {
    256    "", "rm", "rz", "rp", "rni", "rmi", "rzi", "rpi"
    257 };
    258 
    259 static const char *CondCodeStr[] =
    260 {
    261    "never",
    262    "lt",
    263    "eq",
    264    "le",
    265    "gt",
    266    "ne",
    267    "ge",
    268    "",
    269    "(invalid)",
    270    "ltu",
    271    "equ",
    272    "leu",
    273    "gtu",
    274    "neu",
    275    "geu",
    276    "",
    277    "no",
    278    "nc",
    279    "ns",
    280    "na",
    281    "a",
    282    "s",
    283    "c",
    284    "o"
    285 };
    286 
    287 static const char *SemanticStr[SV_LAST + 1] =
    288 {
    289    "POSITION",
    290    "VERTEX_ID",
    291    "INSTANCE_ID",
    292    "INVOCATION_ID",
    293    "PRIMITIVE_ID",
    294    "VERTEX_COUNT",
    295    "LAYER",
    296    "VIEWPORT_INDEX",
    297    "Y_DIR",
    298    "FACE",
    299    "POINT_SIZE",
    300    "POINT_COORD",
    301    "CLIP_DISTANCE",
    302    "SAMPLE_INDEX",
    303    "SAMPLE_POS",
    304    "SAMPLE_MASK",
    305    "TESS_OUTER",
    306    "TESS_INNER",
    307    "TESS_COORD",
    308    "TID",
    309    "CTAID",
    310    "NTID",
    311    "GRIDID",
    312    "NCTAID",
    313    "LANEID",
    314    "PHYSID",
    315    "NPHYSID",
    316    "CLOCK",
    317    "LBASE",
    318    "SBASE",
    319    "VERTEX_STRIDE",
    320    "INVOCATION_INFO",
    321    "THREAD_KILL",
    322    "BASEVERTEX",
    323    "BASEINSTANCE",
    324    "DRAWID",
    325    "WORK_DIM",
    326    "LANEMASK_EQ",
    327    "LANEMASK_LT",
    328    "LANEMASK_LE",
    329    "LANEMASK_GT",
    330    "LANEMASK_GE",
    331    "?",
    332    "(INVALID)"
    333 };
    334 
    335 static const char *interpStr[16] =
    336 {
    337    "pass",
    338    "mul",
    339    "flat",
    340    "sc",
    341    "cent pass",
    342    "cent mul",
    343    "cent flat",
    344    "cent sc",
    345    "off pass",
    346    "off mul",
    347    "off flat",
    348    "off sc",
    349    "samp pass",
    350    "samp mul",
    351    "samp flat",
    352    "samp sc"
    353 };
    354 
    355 #define PRINT(args...)                                \
    356    do {                                               \
    357       pos += snprintf(&buf[pos], size - pos, args);   \
    358    } while(0)
    359 
    360 #define SPACE_PRINT(cond, args...)                      \
    361    do {                                                 \
    362       if (cond)                                         \
    363          buf[pos++] = ' ';                              \
    364       pos += snprintf(&buf[pos], size - pos, args);     \
    365    } while(0)
    366 
    367 #define SPACE()                                    \
    368    do {                                            \
    369       if (pos < size)                              \
    370          buf[pos++] = ' ';                         \
    371    } while(0)
    372 
    373 int Modifier::print(char *buf, size_t size) const
    374 {
    375    size_t pos = 0;
    376 
    377    if (bits)
    378       PRINT("%s", colour[TXT_INSN]);
    379 
    380    size_t base = pos;
    381 
    382    if (bits & NV50_IR_MOD_NOT)
    383       PRINT("not");
    384    if (bits & NV50_IR_MOD_SAT)
    385       SPACE_PRINT(pos > base && pos < size, "sat");
    386    if (bits & NV50_IR_MOD_NEG)
    387       SPACE_PRINT(pos > base && pos < size, "neg");
    388    if (bits & NV50_IR_MOD_ABS)
    389       SPACE_PRINT(pos > base && pos < size, "abs");
    390 
    391    return pos;
    392 }
    393 
    394 int LValue::print(char *buf, size_t size, DataType ty) const
    395 {
    396    const char *postFix = "";
    397    size_t pos = 0;
    398    int idx = join->reg.data.id >= 0 ? join->reg.data.id : id;
    399    char p = join->reg.data.id >= 0 ? '$' : '%';
    400    char r;
    401    int col = TXT_DEFAULT;
    402 
    403    switch (reg.file) {
    404    case FILE_GPR:
    405       r = 'r'; col = TXT_GPR;
    406       if (reg.size == 2) {
    407          if (p == '$') {
    408             postFix = (idx & 1) ? "h" : "l";
    409             idx /= 2;
    410          } else {
    411             postFix = "s";
    412          }
    413       } else
    414       if (reg.size == 8) {
    415          postFix = "d";
    416       } else
    417       if (reg.size == 16) {
    418          postFix = "q";
    419       } else
    420       if (reg.size == 12) {
    421          postFix = "t";
    422       }
    423       break;
    424    case FILE_PREDICATE:
    425       r = 'p'; col = TXT_REGISTER;
    426       if (reg.size == 2)
    427          postFix = "d";
    428       else
    429       if (reg.size == 4)
    430          postFix = "q";
    431       break;
    432    case FILE_FLAGS:
    433       r = 'c'; col = TXT_FLAGS;
    434       break;
    435    case FILE_ADDRESS:
    436       r = 'a'; col = TXT_REGISTER;
    437       break;
    438    default:
    439       assert(!"invalid file for lvalue");
    440       r = '?';
    441       break;
    442    }
    443 
    444    PRINT("%s%c%c%i%s", colour[col], p, r, idx, postFix);
    445 
    446    return pos;
    447 }
    448 
    449 int ImmediateValue::print(char *buf, size_t size, DataType ty) const
    450 {
    451    size_t pos = 0;
    452 
    453    PRINT("%s", colour[TXT_IMMD]);
    454 
    455    switch (ty) {
    456    case TYPE_F32: PRINT("%f", reg.data.f32); break;
    457    case TYPE_F64: PRINT("%f", reg.data.f64); break;
    458    case TYPE_U8:  PRINT("0x%02x", reg.data.u8); break;
    459    case TYPE_S8:  PRINT("%i", reg.data.s8); break;
    460    case TYPE_U16: PRINT("0x%04x", reg.data.u16); break;
    461    case TYPE_S16: PRINT("%i", reg.data.s16); break;
    462    case TYPE_U32: PRINT("0x%08x", reg.data.u32); break;
    463    case TYPE_S32: PRINT("%i", reg.data.s32); break;
    464    case TYPE_U64:
    465    case TYPE_S64:
    466    default:
    467       PRINT("0x%016" PRIx64, reg.data.u64);
    468       break;
    469    }
    470    return pos;
    471 }
    472 
    473 int Symbol::print(char *buf, size_t size, DataType ty) const
    474 {
    475    return print(buf, size, NULL, NULL, ty);
    476 }
    477 
    478 int Symbol::print(char *buf, size_t size,
    479                   Value *rel, Value *dimRel, DataType ty) const
    480 {
    481    size_t pos = 0;
    482    char c;
    483 
    484    if (ty == TYPE_NONE)
    485       ty = typeOfSize(reg.size);
    486 
    487    if (reg.file == FILE_SYSTEM_VALUE) {
    488       PRINT("%ssv[%s%s:%i%s", colour[TXT_MEM],
    489             colour[TXT_REGISTER],
    490             SemanticStr[reg.data.sv.sv], reg.data.sv.index, colour[TXT_MEM]);
    491       if (rel) {
    492          PRINT("%s+", colour[TXT_DEFAULT]);
    493          pos += rel->print(&buf[pos], size - pos);
    494       }
    495       PRINT("%s]", colour[TXT_MEM]);
    496       return pos;
    497    }
    498 
    499    switch (reg.file) {
    500    case FILE_MEMORY_CONST:  c = 'c'; break;
    501    case FILE_SHADER_INPUT:  c = 'a'; break;
    502    case FILE_SHADER_OUTPUT: c = 'o'; break;
    503    case FILE_MEMORY_BUFFER: c = 'b'; break; // Only used before lowering
    504    case FILE_MEMORY_GLOBAL: c = 'g'; break;
    505    case FILE_MEMORY_SHARED: c = 's'; break;
    506    case FILE_MEMORY_LOCAL:  c = 'l'; break;
    507    default:
    508       assert(!"invalid file");
    509       c = '?';
    510       break;
    511    }
    512 
    513    if (c == 'c')
    514       PRINT("%s%c%i[", colour[TXT_MEM], c, reg.fileIndex);
    515    else
    516       PRINT("%s%c[", colour[TXT_MEM], c);
    517 
    518    if (dimRel) {
    519       pos += dimRel->print(&buf[pos], size - pos, TYPE_S32);
    520       PRINT("%s][", colour[TXT_MEM]);
    521    }
    522 
    523    if (rel) {
    524       pos += rel->print(&buf[pos], size - pos);
    525       PRINT("%s%c", colour[TXT_DEFAULT], (reg.data.offset < 0) ? '-' : '+');
    526    } else {
    527       assert(reg.data.offset >= 0);
    528    }
    529    PRINT("%s0x%x%s]", colour[TXT_IMMD], abs(reg.data.offset), colour[TXT_MEM]);
    530 
    531    return pos;
    532 }
    533 
    534 void Instruction::print() const
    535 {
    536    #define BUFSZ 512
    537 
    538    const size_t size = BUFSZ;
    539 
    540    char buf[BUFSZ];
    541    int s, d;
    542    size_t pos = 0;
    543 
    544    PRINT("%s", colour[TXT_INSN]);
    545 
    546    if (join)
    547       PRINT("join ");
    548 
    549    if (predSrc >= 0) {
    550       const size_t pre = pos;
    551       if (getSrc(predSrc)->reg.file == FILE_PREDICATE) {
    552          if (cc == CC_NOT_P)
    553             PRINT("not");
    554       } else {
    555          PRINT("%s", CondCodeStr[cc]);
    556       }
    557       if (pos > pre)
    558          SPACE();
    559       pos += getSrc(predSrc)->print(&buf[pos], BUFSZ - pos);
    560       PRINT(" %s", colour[TXT_INSN]);
    561    }
    562 
    563    if (saturate)
    564       PRINT("sat ");
    565 
    566    if (asFlow()) {
    567       PRINT("%s", operationStr[op]);
    568       if (asFlow()->indirect)
    569          PRINT(" ind");
    570       if (asFlow()->absolute)
    571          PRINT(" abs");
    572       if (op == OP_CALL && asFlow()->builtin) {
    573          PRINT(" %sBUILTIN:%i", colour[TXT_BRA], asFlow()->target.builtin);
    574       } else
    575       if (op == OP_CALL && asFlow()->target.fn) {
    576          PRINT(" %s%s:%i", colour[TXT_BRA],
    577                asFlow()->target.fn->getName(),
    578                asFlow()->target.fn->getLabel());
    579       } else
    580       if (asFlow()->target.bb)
    581          PRINT(" %sBB:%i", colour[TXT_BRA], asFlow()->target.bb->getId());
    582    } else {
    583       PRINT("%s ", operationStr[op]);
    584       if (op == OP_LINTERP || op == OP_PINTERP)
    585          PRINT("%s ", interpStr[ipa]);
    586       switch (op) {
    587       case OP_SUREDP:
    588       case OP_SUREDB:
    589       case OP_ATOM:
    590          if (subOp < ARRAY_SIZE(atomSubOpStr))
    591             PRINT("%s ", atomSubOpStr[subOp]);
    592          break;
    593       case OP_LOAD:
    594       case OP_STORE:
    595          if (subOp < ARRAY_SIZE(ldstSubOpStr))
    596             PRINT("%s ", ldstSubOpStr[subOp]);
    597          break;
    598       case OP_SUBFM:
    599          if (subOp < ARRAY_SIZE(subfmOpStr))
    600             PRINT("%s ", subfmOpStr[subOp]);
    601          break;
    602       case OP_SHFL:
    603          if (subOp < ARRAY_SIZE(shflOpStr))
    604             PRINT("%s ", shflOpStr[subOp]);
    605          break;
    606       case OP_PIXLD:
    607          if (subOp < ARRAY_SIZE(pixldOpStr))
    608             PRINT("%s ", pixldOpStr[subOp]);
    609          break;
    610       case OP_RCP:
    611       case OP_RSQ:
    612          if (subOp < ARRAY_SIZE(rcprsqOpStr))
    613             PRINT("%s ", rcprsqOpStr[subOp]);
    614          break;
    615       case OP_EMIT:
    616          if (subOp < ARRAY_SIZE(emitOpStr))
    617             PRINT("%s ", emitOpStr[subOp]);
    618          break;
    619       case OP_CCTL:
    620          if (subOp < ARRAY_SIZE(cctlOpStr))
    621             PRINT("%s ", cctlOpStr[subOp]);
    622          break;
    623       case OP_BAR:
    624          if (subOp < ARRAY_SIZE(barOpStr))
    625             PRINT("%s ", barOpStr[subOp]);
    626          break;
    627       default:
    628          if (subOp)
    629             PRINT("(SUBOP:%u) ", subOp);
    630          break;
    631       }
    632       if (perPatch)
    633          PRINT("patch ");
    634       if (asTex())
    635          PRINT("%s %s$r%u $s%u %s", asTex()->tex.target.getName(),
    636                colour[TXT_MEM], asTex()->tex.r, asTex()->tex.s,
    637                colour[TXT_INSN]);
    638       if (postFactor)
    639          PRINT("x2^%i ", postFactor);
    640       PRINT("%s%s", dnz ? "dnz " : (ftz ? "ftz " : ""),  DataTypeStr[dType]);
    641    }
    642 
    643    if (rnd != ROUND_N)
    644       PRINT(" %s", RoundModeStr[rnd]);
    645 
    646    if (defExists(1))
    647       PRINT(" {");
    648    for (d = 0; defExists(d); ++d) {
    649       SPACE();
    650       pos += getDef(d)->print(&buf[pos], size - pos);
    651    }
    652    if (d > 1)
    653       PRINT(" %s}", colour[TXT_INSN]);
    654    else
    655    if (!d && !asFlow())
    656       PRINT(" %s#", colour[TXT_INSN]);
    657 
    658    if (asCmp())
    659       PRINT(" %s%s", colour[TXT_INSN], CondCodeStr[asCmp()->setCond]);
    660 
    661    if (sType != dType)
    662       PRINT(" %s%s", colour[TXT_INSN], DataTypeStr[sType]);
    663 
    664    for (s = 0; srcExists(s); ++s) {
    665       if (s == predSrc || src(s).usedAsPtr)
    666          continue;
    667       const size_t pre = pos;
    668       SPACE();
    669       pos += src(s).mod.print(&buf[pos], BUFSZ - pos);
    670       if (pos > pre + 1)
    671          SPACE();
    672       if (src(s).isIndirect(0) || src(s).isIndirect(1))
    673          pos += getSrc(s)->asSym()->print(&buf[pos], BUFSZ - pos,
    674                                           getIndirect(s, 0),
    675                                           getIndirect(s, 1));
    676       else
    677          pos += getSrc(s)->print(&buf[pos], BUFSZ - pos, sType);
    678    }
    679    if (exit)
    680       PRINT("%s exit", colour[TXT_INSN]);
    681 
    682    PRINT("%s", colour[TXT_DEFAULT]);
    683 
    684    buf[MIN2(pos, BUFSZ - 1)] = 0;
    685 
    686    INFO("%s (%u)\n", buf, encSize);
    687 }
    688 
    689 class PrintPass : public Pass
    690 {
    691 public:
    692    PrintPass(bool omitLineNum) : serial(0), omit_serial(omitLineNum) { }
    693 
    694    virtual bool visit(Function *);
    695    virtual bool visit(BasicBlock *);
    696    virtual bool visit(Instruction *);
    697 
    698 private:
    699    int serial;
    700    bool omit_serial;
    701 };
    702 
    703 bool
    704 PrintPass::visit(Function *fn)
    705 {
    706    char str[16];
    707 
    708    INFO("\n%s:%i (", fn->getName(), fn->getLabel());
    709 
    710    if (!fn->outs.empty())
    711       INFO("out");
    712    for (std::deque<ValueRef>::iterator it = fn->outs.begin();
    713         it != fn->outs.end();
    714         ++it) {
    715       it->get()->print(str, sizeof(str), typeOfSize(it->get()->reg.size));
    716       INFO(" %s", str);
    717    }
    718 
    719    if (!fn->ins.empty())
    720       INFO("%s%sin", colour[TXT_DEFAULT], fn->outs.empty() ? "" : ", ");
    721    for (std::deque<ValueDef>::iterator it = fn->ins.begin();
    722         it != fn->ins.end();
    723         ++it) {
    724       it->get()->print(str, sizeof(str), typeOfSize(it->get()->reg.size));
    725       INFO(" %s", str);
    726    }
    727    INFO("%s)\n", colour[TXT_DEFAULT]);
    728 
    729    return true;
    730 }
    731 
    732 bool
    733 PrintPass::visit(BasicBlock *bb)
    734 {
    735 #if 0
    736    INFO("---\n");
    737    for (Graph::EdgeIterator ei = bb->cfg.incident(); !ei.end(); ei.next())
    738       INFO(" <- BB:%i (%s)\n",
    739            BasicBlock::get(ei.getNode())->getId(),
    740            ei.getEdge()->typeStr());
    741 #endif
    742    INFO("BB:%i (%u instructions) - ", bb->getId(), bb->getInsnCount());
    743 
    744    if (bb->idom())
    745       INFO("idom = BB:%i, ", bb->idom()->getId());
    746 
    747    INFO("df = { ");
    748    for (DLList::Iterator df = bb->getDF().iterator(); !df.end(); df.next())
    749       INFO("BB:%i ", BasicBlock::get(df)->getId());
    750 
    751    INFO("}\n");
    752 
    753    for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next())
    754       INFO(" -> BB:%i (%s)\n",
    755            BasicBlock::get(ei.getNode())->getId(),
    756            ei.getEdge()->typeStr());
    757 
    758    return true;
    759 }
    760 
    761 bool
    762 PrintPass::visit(Instruction *insn)
    763 {
    764    if (omit_serial)
    765       INFO("     ");
    766    else
    767       INFO("%3i: ", serial);
    768    serial++;
    769    insn->print();
    770    return true;
    771 }
    772 
    773 void
    774 Function::print()
    775 {
    776    PrintPass pass(prog->driver->omitLineNum);
    777    pass.run(this, true, false);
    778 }
    779 
    780 void
    781 Program::print()
    782 {
    783    PrintPass pass(driver->omitLineNum);
    784    init_colours();
    785    pass.run(this, true, false);
    786 }
    787 
    788 void
    789 Function::printLiveIntervals() const
    790 {
    791    INFO("printing live intervals ...\n");
    792 
    793    for (ArrayList::Iterator it = allLValues.iterator(); !it.end(); it.next()) {
    794       const Value *lval = Value::get(it)->asLValue();
    795       if (lval && !lval->livei.isEmpty()) {
    796          INFO("livei(%%%i): ", lval->id);
    797          lval->livei.print();
    798       }
    799    }
    800 }
    801 
    802 } // namespace nv50_ir
    803