Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright 2013 Vadim Girlin <vadimgirlin@gmail.com>
  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.  * on the rights to use, copy, modify, merge, publish, distribute, sub
  8.  * license, and/or sell copies of the Software, and to permit persons to whom
  9.  * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
  18.  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
  19.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  20.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  21.  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  22.  *
  23.  * Authors:
  24.  *      Vadim Girlin
  25.  */
  26.  
  27. #include "sb_shader.h"
  28. #include "sb_pass.h"
  29.  
  30. namespace r600_sb {
  31.  
  32. int ra_checker::run() {
  33.  
  34.         rm_stack.clear();
  35.         rm_stack.resize(1);
  36.         rm_stk_level = 0;
  37.  
  38.         process_op_dst(sh.root);
  39.  
  40.         run_on(sh.root);
  41.  
  42.         assert(rm_stk_level == 0);
  43.  
  44.         dump_all_errors();
  45.  
  46.         assert(sh.errors.empty());
  47.  
  48.         return 0;
  49. }
  50.  
  51. void ra_checker::dump_error(const error_info &e) {
  52.  
  53.         sblog << "error at : ";
  54.         dump::dump_op(e.n);
  55.  
  56.         sblog << "\n";
  57.         sblog << "  : " << e.message << "\n";
  58. }
  59.  
  60. void ra_checker::dump_all_errors() {
  61.         for (error_map::iterator I = sh.errors.begin(), E = sh.errors.end();
  62.                         I != E; ++I) {
  63.                 dump_error(I->second);
  64.         }
  65. }
  66.  
  67.  
  68. void ra_checker::error(node *n, unsigned id, std::string msg) {
  69.         error_info e;
  70.         e.n = n;
  71.         e.arg_index = id;
  72.         e.message = msg;
  73.         sh.errors.insert(std::make_pair(n, e));
  74. }
  75.  
  76. void ra_checker::push_stack() {
  77.         ++rm_stk_level;
  78.         if (rm_stack.size() == rm_stk_level)
  79.                 rm_stack.push_back(rm_stack.back());
  80.         else
  81.                 rm_stack[rm_stk_level] = rm_stack[rm_stk_level - 1];
  82. }
  83.  
  84. void ra_checker::pop_stack() {
  85.         --rm_stk_level;
  86. }
  87.  
  88. void ra_checker::kill_alu_only_regs() {
  89.         // TODO
  90. }
  91.  
  92. void ra_checker::check_value_gpr(node *n, unsigned id, value *v) {
  93.         sel_chan gpr = v->gpr;
  94.         if (!gpr) {
  95.                 sb_ostringstream o;
  96.                 o << "operand value " << *v << " is not allocated";
  97.                 error(n, id, o.str());
  98.                 return;
  99.         }
  100.         reg_value_map::iterator F = rmap().find(v->gpr);
  101.         if (F == rmap().end()) {
  102.                 sb_ostringstream o;
  103.                 o << "operand value " << *v << " was not previously written to its gpr";
  104.                 error(n, id, o.str());
  105.                 return;
  106.         }
  107.         if (!F->second->v_equal(v)) {
  108.                 sb_ostringstream o;
  109.                 o << "expected operand value " << *v
  110.                                 << ", gpr contains " << *(F->second);
  111.                 error(n, id, o.str());
  112.                 return;
  113.         }
  114.  
  115.  
  116. }
  117.  
  118. void ra_checker::check_src_vec(node *n, unsigned id, vvec &vv, bool src) {
  119.  
  120.         for (vvec::iterator I = vv.begin(), E = vv.end(); I != E; ++I) {
  121.                 value *v = *I;
  122.                 if (!v || !v->is_sgpr())
  123.                         continue;
  124.  
  125.                 if (v->is_rel()) {
  126.                         if (!v->rel) {
  127.                                 sb_ostringstream o;
  128.                                 o << "expected relative offset in " << *v;
  129.                                 error(n, id, o.str());
  130.                                 return;
  131.                         }
  132.                 } else if (src) {
  133.                         check_value_gpr(n, id, v);
  134.                 }
  135.         }
  136. }
  137.  
  138. void ra_checker::check_op_src(node *n) {
  139.         check_src_vec(n, 0, n->dst, false);
  140.         check_src_vec(n, 100, n->src, true);
  141. }
  142.  
  143. void ra_checker::process_op_dst(node *n) {
  144.  
  145.         unsigned id = 0;
  146.  
  147.         for (vvec::iterator I = n->dst.begin(), E = n->dst.end(); I != E; ++I) {
  148.                 value *v = *I;
  149.  
  150.                 ++id;
  151.  
  152.                 if (!v)
  153.                         continue;
  154.  
  155.                 if (v->is_sgpr()) {
  156.  
  157.                         if (!v->gpr) {
  158.                                 sb_ostringstream o;
  159.                                 o << "destination operand " << *v << " is not allocated";
  160.                                 error(n, id, o.str());
  161.                                 return;
  162.                         }
  163.  
  164.                         rmap()[v->gpr] = v;
  165.                 } else if (v->is_rel()) {
  166.                         if (v->rel->is_const()) {
  167.                                 rmap()[v->get_final_gpr()] = v;
  168.                         } else {
  169.                                 unsigned sz = v->array->array_size;
  170.                                 unsigned start = v->array->gpr;
  171.                                 for (unsigned i = 0; i < sz; ++i) {
  172.                                         rmap()[start + (i << 2)] = v;
  173.                                 }
  174.                         }
  175.                 }
  176.         }
  177. }
  178.  
  179. void ra_checker::check_phi_src(container_node *p, unsigned id) {
  180.         for (node_iterator I = p->begin(), E = p->end(); I != E; ++I) {
  181.                 node *n = *I;
  182.                 value *s = n->src[id];
  183.                 if (s->is_sgpr())
  184.                         check_value_gpr(n, id, s);
  185.         }
  186. }
  187.  
  188. void ra_checker::process_phi_dst(container_node *p) {
  189.         for (node_iterator I = p->begin(), E = p->end(); I != E; ++I) {
  190.                 node *n = *I;
  191.                 process_op_dst(n);
  192.         }
  193. }
  194.  
  195. void ra_checker::check_alu_group(alu_group_node *g) {
  196.  
  197.         for (node_iterator I = g->begin(), E = g->end(); I != E; ++I) {
  198.                 node *a = *I;
  199.                 if (!a->is_alu_inst()) {
  200.                         sb_ostringstream o;
  201.                         o << "non-alu node inside alu group";
  202.                         error(a, 0, o.str());
  203.                         return;
  204.                 }
  205.  
  206.                 check_op_src(a);
  207.         }
  208.  
  209.         std::fill(prev_dst, prev_dst + 5, (value*)NULL);
  210.  
  211.         for (node_iterator I = g->begin(), E = g->end(); I != E; ++I) {
  212.                 alu_node *a = static_cast<alu_node*>(*I);
  213.  
  214.                 process_op_dst(a);
  215.  
  216.                 unsigned slot = a->bc.slot;
  217.                 prev_dst[slot] = a->dst[0];
  218.         }
  219. }
  220.  
  221. void ra_checker::run_on(container_node* c) {
  222.  
  223.         if (c->is_region()) {
  224.                 region_node *r = static_cast<region_node*>(c);
  225.                 if (r->loop_phi) {
  226.                         check_phi_src(r->loop_phi, 0);
  227.                         process_phi_dst(r->loop_phi);
  228.                 }
  229.         } else if (c->is_depart()) {
  230.  
  231.                 push_stack();
  232.  
  233.         } else if (c->is_repeat()) {
  234.  
  235.                 push_stack();
  236.  
  237.         }
  238.  
  239.         for (node_iterator I = c->begin(), E = c->end(); I != E; ++I) {
  240.                 node *n = *I;
  241.  
  242.                 if(n->is_cf_inst() || n->is_fetch_inst()) {
  243.                         check_op_src(n);
  244.                         process_op_dst(n);
  245.                 }
  246.  
  247.                 if (n->is_container()) {
  248.                         if (n->is_alu_group()) {
  249.                                 check_alu_group(static_cast<alu_group_node*>(n));
  250.                         } else {
  251.                                 container_node *nc = static_cast<container_node*>(n);
  252.                                 run_on(nc);
  253.                         }
  254.                 }
  255.         }
  256.  
  257.         if (c->is_depart()) {
  258.                 depart_node *r = static_cast<depart_node*>(c);
  259.                 check_phi_src(r->target->phi, r->dep_id);
  260.                 pop_stack();
  261.         } else if (c->is_repeat()) {
  262.                 repeat_node *r = static_cast<repeat_node*>(c);
  263.                 assert (r->target->loop_phi);
  264.  
  265.                 pop_stack();
  266.         } else if (c->is_region()) {
  267.                 region_node *r = static_cast<region_node*>(c);
  268.                 if (r->phi)
  269.                         process_phi_dst(r->phi);
  270.         }
  271. }
  272.  
  273. } // namespace r600_sb
  274.