Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/*
2
 * Copyright 2013 Vadim Girlin 
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(*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(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(n));
250
			} else {
251
				container_node *nc = static_cast(n);
252
				run_on(nc);
253
			}
254
		}
255
	}
256
 
257
	if (c->is_depart()) {
258
		depart_node *r = static_cast(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(c);
263
		assert (r->target->loop_phi);
264
 
265
		pop_stack();
266
	} else if (c->is_region()) {
267
		region_node *r = static_cast(c);
268
		if (r->phi)
269
			process_phi_dst(r->phi);
270
	}
271
}
272
 
273
} // namespace r600_sb