Home | History | Annotate | Download | only in glsl
      1 /*
      2  * Copyright  2010 Intel Corporation
      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 (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21  * DEALINGS IN THE SOFTWARE.
     22  */
     23 
     24 #include "ir_print_visitor.h"
     25 #include "glsl_types.h"
     26 #include "glsl_parser_extras.h"
     27 #include "program/hash_table.h"
     28 
     29 static void print_type(const glsl_type *t);
     30 
     31 void
     32 ir_instruction::print(void) const
     33 {
     34    ir_instruction *deconsted = const_cast<ir_instruction *>(this);
     35 
     36    ir_print_visitor v;
     37    deconsted->accept(&v);
     38 }
     39 
     40 void
     41 _mesa_print_ir(exec_list *instructions,
     42 	       struct _mesa_glsl_parse_state *state)
     43 {
     44    if (state) {
     45       for (unsigned i = 0; i < state->num_user_structures; i++) {
     46 	 const glsl_type *const s = state->user_structures[i];
     47 
     48 	 printf("(structure (%s) (%s@%p) (%u) (\n",
     49 		s->name, s->name, (void *) s, s->length);
     50 
     51 	 for (unsigned j = 0; j < s->length; j++) {
     52 	    printf("\t((");
     53 	    print_type(s->fields.structure[j].type);
     54 	    printf(")(%s))\n", s->fields.structure[j].name);
     55 	 }
     56 
     57 	 printf(")\n");
     58       }
     59    }
     60 
     61    printf("(\n");
     62    foreach_iter(exec_list_iterator, iter, *instructions) {
     63       ir_instruction *ir = (ir_instruction *)iter.get();
     64       ir->print();
     65       if (ir->ir_type != ir_type_function)
     66 	 printf("\n");
     67    }
     68    printf("\n)");
     69 }
     70 
     71 ir_print_visitor::ir_print_visitor()
     72 {
     73    indentation = 0;
     74    printable_names =
     75       hash_table_ctor(32, hash_table_pointer_hash, hash_table_pointer_compare);
     76    symbols = _mesa_symbol_table_ctor();
     77    mem_ctx = ralloc_context(NULL);
     78 }
     79 
     80 ir_print_visitor::~ir_print_visitor()
     81 {
     82    hash_table_dtor(printable_names);
     83    _mesa_symbol_table_dtor(symbols);
     84    ralloc_free(mem_ctx);
     85 }
     86 
     87 void ir_print_visitor::indent(void)
     88 {
     89    for (int i = 0; i < indentation; i++)
     90       printf("  ");
     91 }
     92 
     93 const char *
     94 ir_print_visitor::unique_name(ir_variable *var)
     95 {
     96    /* var->name can be NULL in function prototypes when a type is given for a
     97     * parameter but no name is given.  In that case, just return an empty
     98     * string.  Don't worry about tracking the generated name in the printable
     99     * names hash because this is the only scope where it can ever appear.
    100     */
    101    if (var->name == NULL) {
    102       static unsigned arg = 1;
    103       return ralloc_asprintf(this->mem_ctx, "parameter@%u", arg++);
    104    }
    105 
    106    /* Do we already have a name for this variable? */
    107    const char *name = (const char *) hash_table_find(this->printable_names, var);
    108    if (name != NULL)
    109       return name;
    110 
    111    /* If there's no conflict, just use the original name */
    112    if (_mesa_symbol_table_find_symbol(this->symbols, -1, var->name) == NULL) {
    113       name = var->name;
    114    } else {
    115       static unsigned i = 1;
    116       name = ralloc_asprintf(this->mem_ctx, "%s@%u", var->name, ++i);
    117    }
    118    hash_table_insert(this->printable_names, (void *) name, var);
    119    _mesa_symbol_table_add_symbol(this->symbols, -1, name, var);
    120    return name;
    121 }
    122 
    123 static void
    124 print_type(const glsl_type *t)
    125 {
    126    if (t->base_type == GLSL_TYPE_ARRAY) {
    127       printf("(array ");
    128       print_type(t->fields.array);
    129       printf(" %u)", t->length);
    130    } else if ((t->base_type == GLSL_TYPE_STRUCT)
    131 	      && (strncmp("gl_", t->name, 3) != 0)) {
    132       printf("%s@%p", t->name, (void *) t);
    133    } else {
    134       printf("%s", t->name);
    135    }
    136 }
    137 
    138 void ir_print_visitor::visit(ir_rvalue *ir)
    139 {
    140    printf("error");
    141 }
    142 
    143 void ir_print_visitor::visit(ir_variable *ir)
    144 {
    145    printf("(declare ");
    146 
    147    const char *const cent = (ir->centroid) ? "centroid " : "";
    148    const char *const inv = (ir->invariant) ? "invariant " : "";
    149    const char *const mode[] = { "", "uniform ", "in ", "out ", "inout ",
    150 			        "const_in ", "sys ", "temporary " };
    151    const char *const interp[] = { "", "flat", "noperspective" };
    152 
    153    printf("(%s%s%s%s) ",
    154 	  cent, inv, mode[ir->mode], interp[ir->interpolation]);
    155 
    156    print_type(ir->type);
    157    printf(" %s)", unique_name(ir));
    158 }
    159 
    160 
    161 void ir_print_visitor::visit(ir_function_signature *ir)
    162 {
    163    _mesa_symbol_table_push_scope(symbols);
    164    printf("(signature ");
    165    indentation++;
    166 
    167    print_type(ir->return_type);
    168    printf("\n");
    169    indent();
    170 
    171    printf("(parameters\n");
    172    indentation++;
    173 
    174    foreach_iter(exec_list_iterator, iter, ir->parameters) {
    175       ir_variable *const inst = (ir_variable *) iter.get();
    176 
    177       indent();
    178       inst->accept(this);
    179       printf("\n");
    180    }
    181    indentation--;
    182 
    183    indent();
    184    printf(")\n");
    185 
    186    indent();
    187 
    188    printf("(\n");
    189    indentation++;
    190 
    191    foreach_iter(exec_list_iterator, iter, ir->body) {
    192       ir_instruction *const inst = (ir_instruction *) iter.get();
    193 
    194       indent();
    195       inst->accept(this);
    196       printf("\n");
    197    }
    198    indentation--;
    199    indent();
    200    printf("))\n");
    201    indentation--;
    202    _mesa_symbol_table_pop_scope(symbols);
    203 }
    204 
    205 
    206 void ir_print_visitor::visit(ir_function *ir)
    207 {
    208    printf("(function %s\n", ir->name);
    209    indentation++;
    210    foreach_iter(exec_list_iterator, iter, *ir) {
    211       ir_function_signature *const sig = (ir_function_signature *) iter.get();
    212       indent();
    213       sig->accept(this);
    214       printf("\n");
    215    }
    216    indentation--;
    217    indent();
    218    printf(")\n\n");
    219 }
    220 
    221 
    222 void ir_print_visitor::visit(ir_expression *ir)
    223 {
    224    printf("(expression ");
    225 
    226    print_type(ir->type);
    227 
    228    printf(" %s ", ir->operator_string());
    229 
    230    for (unsigned i = 0; i < ir->get_num_operands(); i++) {
    231       ir->operands[i]->accept(this);
    232    }
    233 
    234    printf(") ");
    235 }
    236 
    237 
    238 void ir_print_visitor::visit(ir_texture *ir)
    239 {
    240    printf("(%s ", ir->opcode_string());
    241 
    242    print_type(ir->type);
    243    printf(" ");
    244 
    245    ir->sampler->accept(this);
    246    printf(" ");
    247 
    248    if (ir->op != ir_txs) {
    249       ir->coordinate->accept(this);
    250 
    251       printf(" ");
    252 
    253       if (ir->offset != NULL) {
    254 	 ir->offset->accept(this);
    255       } else {
    256 	 printf("0");
    257       }
    258 
    259       printf(" ");
    260    }
    261 
    262    if (ir->op != ir_txf && ir->op != ir_txs) {
    263       if (ir->projector)
    264 	 ir->projector->accept(this);
    265       else
    266 	 printf("1");
    267 
    268       if (ir->shadow_comparitor) {
    269 	 printf(" ");
    270 	 ir->shadow_comparitor->accept(this);
    271       } else {
    272 	 printf(" ()");
    273       }
    274    }
    275 
    276    printf(" ");
    277    switch (ir->op)
    278    {
    279    case ir_tex:
    280       break;
    281    case ir_txb:
    282       ir->lod_info.bias->accept(this);
    283       break;
    284    case ir_txl:
    285    case ir_txf:
    286    case ir_txs:
    287       ir->lod_info.lod->accept(this);
    288       break;
    289    case ir_txd:
    290       printf("(");
    291       ir->lod_info.grad.dPdx->accept(this);
    292       printf(" ");
    293       ir->lod_info.grad.dPdy->accept(this);
    294       printf(")");
    295       break;
    296    };
    297    printf(")");
    298 }
    299 
    300 
    301 void ir_print_visitor::visit(ir_swizzle *ir)
    302 {
    303    const unsigned swiz[4] = {
    304       ir->mask.x,
    305       ir->mask.y,
    306       ir->mask.z,
    307       ir->mask.w,
    308    };
    309 
    310    printf("(swiz ");
    311    for (unsigned i = 0; i < ir->mask.num_components; i++) {
    312       printf("%c", "xyzw"[swiz[i]]);
    313    }
    314    printf(" ");
    315    ir->val->accept(this);
    316    printf(")");
    317 }
    318 
    319 
    320 void ir_print_visitor::visit(ir_dereference_variable *ir)
    321 {
    322    ir_variable *var = ir->variable_referenced();
    323    printf("(var_ref %s) ", unique_name(var));
    324 }
    325 
    326 
    327 void ir_print_visitor::visit(ir_dereference_array *ir)
    328 {
    329    printf("(array_ref ");
    330    ir->array->accept(this);
    331    ir->array_index->accept(this);
    332    printf(") ");
    333 }
    334 
    335 
    336 void ir_print_visitor::visit(ir_dereference_record *ir)
    337 {
    338    printf("(record_ref ");
    339    ir->record->accept(this);
    340    printf(" %s) ", ir->field);
    341 }
    342 
    343 
    344 void ir_print_visitor::visit(ir_assignment *ir)
    345 {
    346    printf("(assign ");
    347 
    348    if (ir->condition)
    349       ir->condition->accept(this);
    350 
    351    char mask[5];
    352    unsigned j = 0;
    353 
    354    for (unsigned i = 0; i < 4; i++) {
    355       if ((ir->write_mask & (1 << i)) != 0) {
    356 	 mask[j] = "xyzw"[i];
    357 	 j++;
    358       }
    359    }
    360    mask[j] = '\0';
    361 
    362    printf(" (%s) ", mask);
    363 
    364    ir->lhs->accept(this);
    365 
    366    printf(" ");
    367 
    368    ir->rhs->accept(this);
    369    printf(") ");
    370 }
    371 
    372 
    373 void ir_print_visitor::visit(ir_constant *ir)
    374 {
    375    printf("(constant ");
    376    print_type(ir->type);
    377    printf(" (");
    378 
    379    if (ir->type->is_array()) {
    380       for (unsigned i = 0; i < ir->type->length; i++)
    381 	 ir->get_array_element(i)->accept(this);
    382    } else if (ir->type->is_record()) {
    383       ir_constant *value = (ir_constant *) ir->components.get_head();
    384       for (unsigned i = 0; i < ir->type->length; i++) {
    385 	 printf("(%s ", ir->type->fields.structure[i].name);
    386 	 value->accept(this);
    387 	 printf(")");
    388 
    389 	 value = (ir_constant *) value->next;
    390       }
    391    } else {
    392       for (unsigned i = 0; i < ir->type->components(); i++) {
    393 	 if (i != 0)
    394 	    printf(" ");
    395 	 switch (ir->type->base_type) {
    396 	 case GLSL_TYPE_UINT:  printf("%u", ir->value.u[i]); break;
    397 	 case GLSL_TYPE_INT:   printf("%d", ir->value.i[i]); break;
    398 	 case GLSL_TYPE_FLOAT: printf("%f", ir->value.f[i]); break;
    399 	 case GLSL_TYPE_BOOL:  printf("%d", ir->value.b[i]); break;
    400 	 default: assert(0);
    401 	 }
    402       }
    403    }
    404    printf(")) ");
    405 }
    406 
    407 
    408 void
    409 ir_print_visitor::visit(ir_call *ir)
    410 {
    411    printf("(call %s ", ir->callee_name());
    412    if (ir->return_deref)
    413       ir->return_deref->accept(this);
    414    printf(" (");
    415    foreach_iter(exec_list_iterator, iter, *ir) {
    416       ir_instruction *const inst = (ir_instruction *) iter.get();
    417 
    418       inst->accept(this);
    419    }
    420    printf("))\n");
    421 }
    422 
    423 
    424 void
    425 ir_print_visitor::visit(ir_return *ir)
    426 {
    427    printf("(return");
    428 
    429    ir_rvalue *const value = ir->get_value();
    430    if (value) {
    431       printf(" ");
    432       value->accept(this);
    433    }
    434 
    435    printf(")");
    436 }
    437 
    438 
    439 void
    440 ir_print_visitor::visit(ir_discard *ir)
    441 {
    442    printf("(discard ");
    443 
    444    if (ir->condition != NULL) {
    445       printf(" ");
    446       ir->condition->accept(this);
    447    }
    448 
    449    printf(")");
    450 }
    451 
    452 
    453 void
    454 ir_print_visitor::visit(ir_if *ir)
    455 {
    456    printf("(if ");
    457    ir->condition->accept(this);
    458 
    459    printf("(\n");
    460    indentation++;
    461 
    462    foreach_iter(exec_list_iterator, iter, ir->then_instructions) {
    463       ir_instruction *const inst = (ir_instruction *) iter.get();
    464 
    465       indent();
    466       inst->accept(this);
    467       printf("\n");
    468    }
    469 
    470    indentation--;
    471    indent();
    472    printf(")\n");
    473 
    474    indent();
    475    if (!ir->else_instructions.is_empty()) {
    476       printf("(\n");
    477       indentation++;
    478 
    479       foreach_iter(exec_list_iterator, iter, ir->else_instructions) {
    480 	 ir_instruction *const inst = (ir_instruction *) iter.get();
    481 
    482 	 indent();
    483 	 inst->accept(this);
    484 	 printf("\n");
    485       }
    486       indentation--;
    487       indent();
    488       printf("))\n");
    489    } else {
    490       printf("())\n");
    491    }
    492 }
    493 
    494 
    495 void
    496 ir_print_visitor::visit(ir_loop *ir)
    497 {
    498    printf("(loop (");
    499    if (ir->counter != NULL)
    500       ir->counter->accept(this);
    501    printf(") (");
    502    if (ir->from != NULL)
    503       ir->from->accept(this);
    504    printf(") (");
    505    if (ir->to != NULL)
    506       ir->to->accept(this);
    507    printf(") (");
    508    if (ir->increment != NULL)
    509       ir->increment->accept(this);
    510    printf(") (\n");
    511    indentation++;
    512 
    513    foreach_iter(exec_list_iterator, iter, ir->body_instructions) {
    514       ir_instruction *const inst = (ir_instruction *) iter.get();
    515 
    516       indent();
    517       inst->accept(this);
    518       printf("\n");
    519    }
    520    indentation--;
    521    indent();
    522    printf("))\n");
    523 }
    524 
    525 
    526 void
    527 ir_print_visitor::visit(ir_loop_jump *ir)
    528 {
    529    printf("%s", ir->is_break() ? "break" : "continue");
    530 }
    531