2 * Copyright 2013 Vadim Girlin <vadimgirlin@gmail.com>
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:
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
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.
27 #include "sb_shader.h"
32 int ra_checker::run() {
38 process_op_dst(sh
.root
);
42 assert(rm_stk_level
== 0);
46 assert(sh
.errors
.empty());
51 void ra_checker::dump_error(const error_info
&e
) {
53 sblog
<< "error at : ";
57 sblog
<< " : " << e
.message
<< "\n";
60 void ra_checker::dump_all_errors() {
61 for (error_map::iterator I
= sh
.errors
.begin(), E
= sh
.errors
.end();
63 dump_error(I
->second
);
68 void ra_checker::error(node
*n
, unsigned id
, std::string msg
) {
73 sh
.errors
.insert(std::make_pair(n
, e
));
76 void ra_checker::push_stack() {
78 if (rm_stack
.size() == rm_stk_level
)
79 rm_stack
.push_back(rm_stack
.back());
81 rm_stack
[rm_stk_level
] = rm_stack
[rm_stk_level
- 1];
84 void ra_checker::pop_stack() {
88 void ra_checker::kill_alu_only_regs() {
92 void ra_checker::check_value_gpr(node
*n
, unsigned id
, value
*v
) {
93 sel_chan gpr
= v
->gpr
;
96 o
<< "operand value " << *v
<< " is not allocated";
97 error(n
, id
, o
.str());
100 reg_value_map::iterator F
= rmap().find(v
->gpr
);
101 if (F
== rmap().end()) {
103 o
<< "operand value " << *v
<< " was not previously written to its gpr";
104 error(n
, id
, o
.str());
107 if (!F
->second
->v_equal(v
)) {
109 o
<< "expected operand value " << *v
110 << ", gpr contains " << *(F
->second
);
111 error(n
, id
, o
.str());
118 void ra_checker::check_src_vec(node
*n
, unsigned id
, vvec
&vv
, bool src
) {
120 for (vvec::iterator I
= vv
.begin(), E
= vv
.end(); I
!= E
; ++I
) {
122 if (!v
|| !v
->is_sgpr())
128 o
<< "expected relative offset in " << *v
;
129 error(n
, id
, o
.str());
133 check_value_gpr(n
, id
, v
);
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);
143 void ra_checker::process_op_dst(node
*n
) {
147 for (vvec::iterator I
= n
->dst
.begin(), E
= n
->dst
.end(); I
!= E
; ++I
) {
159 o
<< "destination operand " << *v
<< " is not allocated";
160 error(n
, id
, o
.str());
165 } else if (v
->is_rel()) {
166 if (v
->rel
->is_const()) {
167 rmap()[v
->get_final_gpr()] = v
;
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
;
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
) {
182 value
*s
= n
->src
[id
];
184 check_value_gpr(n
, id
, s
);
188 void ra_checker::process_phi_dst(container_node
*p
) {
189 for (node_iterator I
= p
->begin(), E
= p
->end(); I
!= E
; ++I
) {
195 void ra_checker::check_alu_group(alu_group_node
*g
) {
197 for (node_iterator I
= g
->begin(), E
= g
->end(); I
!= E
; ++I
) {
199 if (!a
->is_alu_inst()) {
201 o
<< "non-alu node inside alu group";
202 error(a
, 0, o
.str());
209 std::fill(prev_dst
, prev_dst
+ 5, (value
*)NULL
);
211 for (node_iterator I
= g
->begin(), E
= g
->end(); I
!= E
; ++I
) {
212 alu_node
*a
= static_cast<alu_node
*>(*I
);
216 unsigned slot
= a
->bc
.slot
;
217 prev_dst
[slot
] = a
->dst
[0];
221 void ra_checker::run_on(container_node
* c
) {
223 if (c
->is_region()) {
224 region_node
*r
= static_cast<region_node
*>(c
);
226 check_phi_src(r
->loop_phi
, 0);
227 process_phi_dst(r
->loop_phi
);
229 } else if (c
->is_depart()) {
233 } else if (c
->is_repeat()) {
239 for (node_iterator I
= c
->begin(), E
= c
->end(); I
!= E
; ++I
) {
242 if(n
->is_cf_inst() || n
->is_fetch_inst()) {
247 if (n
->is_container()) {
248 if (n
->is_alu_group()) {
249 check_alu_group(static_cast<alu_group_node
*>(n
));
251 container_node
*nc
= static_cast<container_node
*>(n
);
257 if (c
->is_depart()) {
258 depart_node
*r
= static_cast<depart_node
*>(c
);
259 check_phi_src(r
->target
->phi
, r
->dep_id
);
261 } else if (c
->is_repeat()) {
262 repeat_node
*r
= static_cast<repeat_node
*>(c
);
263 assert (r
->target
->loop_phi
);
266 } else if (c
->is_region()) {
267 region_node
*r
= static_cast<region_node
*>(c
);
269 process_phi_dst(r
->phi
);
273 } // namespace r600_sb