Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.h"
  25.  
  26. /**
  27.  * \file ir_hv_accept.cpp
  28.  * Implementations of all hierarchical visitor accept methods for IR
  29.  * instructions.
  30.  */
  31.  
  32. /**
  33.  * Process a list of nodes using a hierarchical vistor.
  34.  *
  35.  * If statement_list is true (the default), this is a list of statements, so
  36.  * v->base_ir will be set to point to each statement just before iterating
  37.  * over it, and restored after iteration is complete.  If statement_list is
  38.  * false, this is a list that appears inside a statement (e.g. a parameter
  39.  * list), so v->base_ir will be left alone.
  40.  *
  41.  * \warning
  42.  * This function will operate correctly if a node being processed is removed
  43.  * from the list.  However, if nodes are added to the list after the node being
  44.  * processed, some of the added nodes may not be processed.
  45.  */
  46. ir_visitor_status
  47. visit_list_elements(ir_hierarchical_visitor *v, exec_list *l,
  48.                     bool statement_list)
  49. {
  50.    ir_instruction *prev_base_ir = v->base_ir;
  51.  
  52.    foreach_in_list_safe(ir_instruction, ir, l) {
  53.       if (statement_list)
  54.          v->base_ir = ir;
  55.       ir_visitor_status s = ir->accept(v);
  56.  
  57.       if (s != visit_continue)
  58.          return s;
  59.    }
  60.    if (statement_list)
  61.       v->base_ir = prev_base_ir;
  62.  
  63.    return visit_continue;
  64. }
  65.  
  66.  
  67. ir_visitor_status
  68. ir_rvalue::accept(ir_hierarchical_visitor *v)
  69. {
  70.    return v->visit(this);
  71. }
  72.  
  73.  
  74. ir_visitor_status
  75. ir_variable::accept(ir_hierarchical_visitor *v)
  76. {
  77.    return v->visit(this);
  78. }
  79.  
  80.  
  81. ir_visitor_status
  82. ir_loop::accept(ir_hierarchical_visitor *v)
  83. {
  84.    ir_visitor_status s = v->visit_enter(this);
  85.  
  86.    if (s != visit_continue)
  87.       return (s == visit_continue_with_parent) ? visit_continue : s;
  88.  
  89.    s = visit_list_elements(v, &this->body_instructions);
  90.    if (s == visit_stop)
  91.       return s;
  92.  
  93.    return v->visit_leave(this);
  94. }
  95.  
  96.  
  97. ir_visitor_status
  98. ir_loop_jump::accept(ir_hierarchical_visitor *v)
  99. {
  100.    return v->visit(this);
  101. }
  102.  
  103.  
  104. ir_visitor_status
  105. ir_function_signature::accept(ir_hierarchical_visitor *v)
  106. {
  107.    ir_visitor_status s = v->visit_enter(this);
  108.    if (s != visit_continue)
  109.       return (s == visit_continue_with_parent) ? visit_continue : s;
  110.  
  111.    s = visit_list_elements(v, &this->parameters);
  112.    if (s == visit_stop)
  113.       return s;
  114.  
  115.    s = visit_list_elements(v, &this->body);
  116.    return (s == visit_stop) ? s : v->visit_leave(this);
  117. }
  118.  
  119.  
  120. ir_visitor_status
  121. ir_function::accept(ir_hierarchical_visitor *v)
  122. {
  123.    ir_visitor_status s = v->visit_enter(this);
  124.    if (s != visit_continue)
  125.       return (s == visit_continue_with_parent) ? visit_continue : s;
  126.  
  127.    s = visit_list_elements(v, &this->signatures, false);
  128.    return (s == visit_stop) ? s : v->visit_leave(this);
  129. }
  130.  
  131.  
  132. ir_visitor_status
  133. ir_expression::accept(ir_hierarchical_visitor *v)
  134. {
  135.    ir_visitor_status s = v->visit_enter(this);
  136.  
  137.    if (s != visit_continue)
  138.       return (s == visit_continue_with_parent) ? visit_continue : s;
  139.  
  140.    for (unsigned i = 0; i < this->get_num_operands(); i++) {
  141.       switch (this->operands[i]->accept(v)) {
  142.       case visit_continue:
  143.          break;
  144.  
  145.       case visit_continue_with_parent:
  146.          // I wish for Java's labeled break-statement here.
  147.          goto done;
  148.  
  149.       case visit_stop:
  150.          return s;
  151.       }
  152.    }
  153.  
  154. done:
  155.    return v->visit_leave(this);
  156. }
  157.  
  158. ir_visitor_status
  159. ir_texture::accept(ir_hierarchical_visitor *v)
  160. {
  161.    ir_visitor_status s = v->visit_enter(this);
  162.    if (s != visit_continue)
  163.       return (s == visit_continue_with_parent) ? visit_continue : s;
  164.  
  165.    s = this->sampler->accept(v);
  166.    if (s != visit_continue)
  167.       return (s == visit_continue_with_parent) ? visit_continue : s;
  168.  
  169.    if (this->coordinate) {
  170.       s = this->coordinate->accept(v);
  171.       if (s != visit_continue)
  172.          return (s == visit_continue_with_parent) ? visit_continue : s;
  173.    }
  174.  
  175.    if (this->projector) {
  176.       s = this->projector->accept(v);
  177.       if (s != visit_continue)
  178.          return (s == visit_continue_with_parent) ? visit_continue : s;
  179.    }
  180.  
  181.    if (this->shadow_comparitor) {
  182.       s = this->shadow_comparitor->accept(v);
  183.       if (s != visit_continue)
  184.          return (s == visit_continue_with_parent) ? visit_continue : s;
  185.    }
  186.  
  187.    if (this->offset) {
  188.       s = this->offset->accept(v);
  189.       if (s != visit_continue)
  190.          return (s == visit_continue_with_parent) ? visit_continue : s;
  191.    }
  192.  
  193.    switch (this->op) {
  194.    case ir_tex:
  195.    case ir_lod:
  196.    case ir_query_levels:
  197.       break;
  198.    case ir_txb:
  199.       s = this->lod_info.bias->accept(v);
  200.       if (s != visit_continue)
  201.          return (s == visit_continue_with_parent) ? visit_continue : s;
  202.       break;
  203.    case ir_txl:
  204.    case ir_txf:
  205.    case ir_txs:
  206.       s = this->lod_info.lod->accept(v);
  207.       if (s != visit_continue)
  208.          return (s == visit_continue_with_parent) ? visit_continue : s;
  209.       break;
  210.    case ir_txf_ms:
  211.       s = this->lod_info.sample_index->accept(v);
  212.       if (s != visit_continue)
  213.          return (s == visit_continue_with_parent) ? visit_continue : s;
  214.       break;
  215.    case ir_txd:
  216.       s = this->lod_info.grad.dPdx->accept(v);
  217.       if (s != visit_continue)
  218.          return (s == visit_continue_with_parent) ? visit_continue : s;
  219.  
  220.       s = this->lod_info.grad.dPdy->accept(v);
  221.       if (s != visit_continue)
  222.          return (s == visit_continue_with_parent) ? visit_continue : s;
  223.       break;
  224.    case ir_tg4:
  225.       s = this->lod_info.component->accept(v);
  226.       if (s != visit_continue)
  227.          return (s == visit_continue_with_parent) ? visit_continue : s;
  228.       break;
  229.    }
  230.  
  231.    return (s == visit_stop) ? s : v->visit_leave(this);
  232. }
  233.  
  234.  
  235. ir_visitor_status
  236. ir_swizzle::accept(ir_hierarchical_visitor *v)
  237. {
  238.    ir_visitor_status s = v->visit_enter(this);
  239.    if (s != visit_continue)
  240.       return (s == visit_continue_with_parent) ? visit_continue : s;
  241.  
  242.    s = this->val->accept(v);
  243.    return (s == visit_stop) ? s : v->visit_leave(this);
  244. }
  245.  
  246.  
  247. ir_visitor_status
  248. ir_dereference_variable::accept(ir_hierarchical_visitor *v)
  249. {
  250.    return v->visit(this);
  251. }
  252.  
  253.  
  254. ir_visitor_status
  255. ir_dereference_array::accept(ir_hierarchical_visitor *v)
  256. {
  257.    ir_visitor_status s = v->visit_enter(this);
  258.    if (s != visit_continue)
  259.       return (s == visit_continue_with_parent) ? visit_continue : s;
  260.  
  261.    /* The array index is not the target of the assignment, so clear the
  262.     * 'in_assignee' flag.  Restore it after returning from the array index.
  263.     */
  264.    const bool was_in_assignee = v->in_assignee;
  265.    v->in_assignee = false;
  266.    s = this->array_index->accept(v);
  267.    v->in_assignee = was_in_assignee;
  268.  
  269.    if (s != visit_continue)
  270.       return (s == visit_continue_with_parent) ? visit_continue : s;
  271.  
  272.    s = this->array->accept(v);
  273.    return (s == visit_stop) ? s : v->visit_leave(this);
  274. }
  275.  
  276.  
  277. ir_visitor_status
  278. ir_dereference_record::accept(ir_hierarchical_visitor *v)
  279. {
  280.    ir_visitor_status s = v->visit_enter(this);
  281.    if (s != visit_continue)
  282.       return (s == visit_continue_with_parent) ? visit_continue : s;
  283.  
  284.    s = this->record->accept(v);
  285.    return (s == visit_stop) ? s : v->visit_leave(this);
  286. }
  287.  
  288.  
  289. ir_visitor_status
  290. ir_assignment::accept(ir_hierarchical_visitor *v)
  291. {
  292.    ir_visitor_status s = v->visit_enter(this);
  293.    if (s != visit_continue)
  294.       return (s == visit_continue_with_parent) ? visit_continue : s;
  295.  
  296.    v->in_assignee = true;
  297.    s = this->lhs->accept(v);
  298.    v->in_assignee = false;
  299.    if (s != visit_continue)
  300.       return (s == visit_continue_with_parent) ? visit_continue : s;
  301.  
  302.    s = this->rhs->accept(v);
  303.    if (s != visit_continue)
  304.       return (s == visit_continue_with_parent) ? visit_continue : s;
  305.  
  306.    if (this->condition)
  307.       s = this->condition->accept(v);
  308.  
  309.    return (s == visit_stop) ? s : v->visit_leave(this);
  310. }
  311.  
  312.  
  313. ir_visitor_status
  314. ir_constant::accept(ir_hierarchical_visitor *v)
  315. {
  316.    return v->visit(this);
  317. }
  318.  
  319.  
  320. ir_visitor_status
  321. ir_call::accept(ir_hierarchical_visitor *v)
  322. {
  323.    ir_visitor_status s = v->visit_enter(this);
  324.    if (s != visit_continue)
  325.       return (s == visit_continue_with_parent) ? visit_continue : s;
  326.  
  327.    if (this->return_deref != NULL) {
  328.       v->in_assignee = true;
  329.       s = this->return_deref->accept(v);
  330.       v->in_assignee = false;
  331.       if (s != visit_continue)
  332.          return (s == visit_continue_with_parent) ? visit_continue : s;
  333.    }
  334.  
  335.    s = visit_list_elements(v, &this->actual_parameters, false);
  336.    if (s == visit_stop)
  337.       return s;
  338.  
  339.    return v->visit_leave(this);
  340. }
  341.  
  342.  
  343. ir_visitor_status
  344. ir_return::accept(ir_hierarchical_visitor *v)
  345. {
  346.    ir_visitor_status s = v->visit_enter(this);
  347.    if (s != visit_continue)
  348.       return (s == visit_continue_with_parent) ? visit_continue : s;
  349.  
  350.    ir_rvalue *val = this->get_value();
  351.    if (val) {
  352.       s = val->accept(v);
  353.       if (s != visit_continue)
  354.          return (s == visit_continue_with_parent) ? visit_continue : s;
  355.    }
  356.  
  357.    return v->visit_leave(this);
  358. }
  359.  
  360.  
  361. ir_visitor_status
  362. ir_discard::accept(ir_hierarchical_visitor *v)
  363. {
  364.    ir_visitor_status s = v->visit_enter(this);
  365.    if (s != visit_continue)
  366.       return (s == visit_continue_with_parent) ? visit_continue : s;
  367.  
  368.    if (this->condition != NULL) {
  369.       s = this->condition->accept(v);
  370.       if (s != visit_continue)
  371.          return (s == visit_continue_with_parent) ? visit_continue : s;
  372.    }
  373.  
  374.    return v->visit_leave(this);
  375. }
  376.  
  377.  
  378. ir_visitor_status
  379. ir_if::accept(ir_hierarchical_visitor *v)
  380. {
  381.    ir_visitor_status s = v->visit_enter(this);
  382.    if (s != visit_continue)
  383.       return (s == visit_continue_with_parent) ? visit_continue : s;
  384.  
  385.    s = this->condition->accept(v);
  386.    if (s != visit_continue)
  387.       return (s == visit_continue_with_parent) ? visit_continue : s;
  388.  
  389.    if (s != visit_continue_with_parent) {
  390.       s = visit_list_elements(v, &this->then_instructions);
  391.       if (s == visit_stop)
  392.          return s;
  393.    }
  394.  
  395.    if (s != visit_continue_with_parent) {
  396.       s = visit_list_elements(v, &this->else_instructions);
  397.       if (s == visit_stop)
  398.          return s;
  399.    }
  400.  
  401.    return v->visit_leave(this);
  402. }
  403.  
  404. ir_visitor_status
  405. ir_emit_vertex::accept(ir_hierarchical_visitor *v)
  406. {
  407.    ir_visitor_status s = v->visit_enter(this);
  408.    if (s != visit_continue)
  409.       return (s == visit_continue_with_parent) ? visit_continue : s;
  410.  
  411.    s = this->stream->accept(v);
  412.    if (s != visit_continue)
  413.       return (s == visit_continue_with_parent) ? visit_continue : s;
  414.  
  415.    return (s == visit_stop) ? s : v->visit_leave(this);
  416. }
  417.  
  418.  
  419. ir_visitor_status
  420. ir_end_primitive::accept(ir_hierarchical_visitor *v)
  421. {
  422.    ir_visitor_status s = v->visit_enter(this);
  423.    if (s != visit_continue)
  424.       return (s == visit_continue_with_parent) ? visit_continue : s;
  425.  
  426.    s = this->stream->accept(v);
  427.    if (s != visit_continue)
  428.       return (s == visit_continue_with_parent) ? visit_continue : s;
  429.  
  430.    return (s == visit_stop) ? s : v->visit_leave(this);
  431. }
  432.