OSDN Git Service

Ignore the generated codegen files for now.
[android-x86/external-mesa.git] / ir_to_mesa.cpp
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 /**
25  * \file ir_to_mesa.cpp
26  *
27  * Translates the IR to ARB_fragment_program text if possible,
28  * printing the result
29  *
30  * The code generation is performed using monoburg.  Because monoburg
31  * produces a single C file with the definitions of the node types in
32  * it, this file is included from the monoburg output.
33  */
34
35 /* Quiet compiler warnings due to monoburg not marking functions defined
36  * in the header as inline.
37  */
38 #define g_new
39 #define g_error
40 #include "mesa_codegen.h"
41
42 #include "ir.h"
43 #include "ir_visitor.h"
44 #include "ir_print_visitor.h"
45 #include "ir_expression_flattening.h"
46 #include "glsl_types.h"
47
48 #include "shader/prog_instruction.h"
49
50 ir_to_mesa_src_reg ir_to_mesa_undef = {
51    PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP
52 };
53
54 ir_to_mesa_instruction *
55 ir_to_mesa_emit_op3(struct mbtree *tree, enum prog_opcode op,
56                     ir_to_mesa_dst_reg dst,
57                     ir_to_mesa_src_reg src0,
58                     ir_to_mesa_src_reg src1,
59                     ir_to_mesa_src_reg src2)
60 {
61    ir_to_mesa_instruction *inst = new ir_to_mesa_instruction();
62
63    inst->op = op;
64    inst->dst_reg = dst;
65    inst->src_reg[0] = src0;
66    inst->src_reg[1] = src1;
67    inst->src_reg[2] = src2;
68
69    tree->v->instructions.push_tail(inst);
70
71    return inst;
72 }
73
74
75 ir_to_mesa_instruction *
76 ir_to_mesa_emit_op2(struct mbtree *tree, enum prog_opcode op,
77                     ir_to_mesa_dst_reg dst,
78                     ir_to_mesa_src_reg src0,
79                     ir_to_mesa_src_reg src1)
80 {
81    return ir_to_mesa_emit_op3(tree, op, dst, src0, src1, ir_to_mesa_undef);
82 }
83
84 ir_to_mesa_instruction *
85 ir_to_mesa_emit_op1(struct mbtree *tree, enum prog_opcode op,
86                     ir_to_mesa_dst_reg dst,
87                     ir_to_mesa_src_reg src0)
88 {
89    return ir_to_mesa_emit_op3(tree, op,
90                               dst, src0, ir_to_mesa_undef, ir_to_mesa_undef);
91 }
92
93 struct mbtree *
94 ir_to_mesa_visitor::create_tree(int op, struct mbtree *left, struct mbtree *right)
95 {
96    struct mbtree *tree = (struct mbtree *)calloc(sizeof(struct mbtree), 1);
97
98    tree->op = op;
99    tree->left = left;
100    tree->right = right;
101    tree->v = this;
102    tree->src_reg.swizzle = SWIZZLE_XYZW;
103
104    return tree;
105 }
106
107 const char *
108 produce_swizzle(int8_t *swizzle, const char *reg_name,
109                 const char **swizzle_reg_name)
110 {
111    if (swizzle[0] == 0 &&
112        swizzle[1] == 1 &&
113        swizzle[2] == 2 &&
114        swizzle[3] == 3)
115    {
116       *swizzle_reg_name = reg_name;
117    } else {
118       char swizzle_letters[4] = { 'x', 'y', 'z', 'w' };
119       char *temp;
120       asprintf(&temp, "%s.%c%c%c%c",
121                reg_name,
122                swizzle_letters[swizzle[0]],
123                swizzle_letters[swizzle[1]],
124                swizzle_letters[swizzle[2]],
125                swizzle_letters[swizzle[3]]);
126       *swizzle_reg_name = temp;
127    }
128    return *swizzle_reg_name;
129 }
130
131 /**
132  * In the initial pass of codegen, we assign temporary numbers to
133  * intermediate results.  (not SSA -- variable assignments will reuse
134  * storage).  Actual register allocation for the Mesa VM occurs in a
135  * pass over the Mesa IR later.
136  */
137 void
138 ir_to_mesa_visitor::get_temp(struct mbtree *tree)
139 {
140    tree->src_reg.file = PROGRAM_TEMPORARY;
141    tree->src_reg.index = this->next_temp++;
142 }
143
144 void
145 ir_to_mesa_visitor::get_temp_for_var(ir_variable *var, struct mbtree *tree)
146 {
147    temp_entry *entry;
148
149    foreach_iter(exec_list_iterator, iter, this->variable_storage) {
150       entry = (temp_entry *)iter.get();
151
152       if (entry->var == var) {
153          tree->src_reg.file = entry->file;
154          tree->src_reg.index = entry->index;
155          return;
156       }
157    }
158
159    entry = new temp_entry(var, PROGRAM_TEMPORARY, this->next_temp++);
160    this->variable_storage.push_tail(entry);
161
162    tree->src_reg.file = entry->file;
163    tree->src_reg.index = entry->index;
164 }
165
166 static void
167 reduce(struct mbtree *t, int goal)
168 {
169    struct mbtree *kids[10];
170    int rule = mono_burg_rule((MBState *)t->state, goal);
171    const uint16_t *nts = mono_burg_nts[rule];
172    int i;
173
174    mono_burg_kids (t, rule, kids);
175
176    for (i = 0; nts[i]; i++) {
177       reduce(kids[i], nts[i]);
178    }
179
180    if (t->left) {
181       if (mono_burg_func[rule]) {
182          mono_burg_func[rule](t, NULL);
183       } else {
184          printf("no code for rules %s\n", mono_burg_rule_string[rule]);
185          exit(1);
186       }
187    } else {
188       if (mono_burg_func[rule]) {
189          printf("unused code for rule %s\n", mono_burg_rule_string[rule]);
190          exit(1);
191       }
192    }
193 }
194
195 void
196 ir_to_mesa_visitor::visit(ir_variable *ir)
197 {
198    (void)ir;
199 }
200
201 void
202 ir_to_mesa_visitor::visit(ir_loop *ir)
203 {
204    (void)ir;
205
206    printf("Can't support loops, should be flattened before here\n");
207    exit(1);
208 }
209
210 void
211 ir_to_mesa_visitor::visit(ir_loop_jump *ir)
212 {
213    (void) ir;
214    printf("Can't support loops, should be flattened before here\n");
215    exit(1);
216 }
217
218
219 void
220 ir_to_mesa_visitor::visit(ir_function_signature *ir)
221 {
222    assert(0);
223    (void)ir;
224 }
225
226 void
227 ir_to_mesa_visitor::visit(ir_function *ir)
228 {
229    /* Ignore function bodies other than main() -- we shouldn't see calls to
230     * them since they should all be inlined before we get to ir_to_mesa.
231     */
232    if (strcmp(ir->name, "main") == 0) {
233       const ir_function_signature *sig;
234       exec_list empty;
235
236       sig = ir->matching_signature(&empty);
237
238       assert(sig);
239
240       foreach_iter(exec_list_iterator, iter, sig->body) {
241          ir_instruction *ir = (ir_instruction *)iter.get();
242
243          ir->accept(this);
244       }
245    }
246 }
247
248 void
249 ir_to_mesa_visitor::visit(ir_expression *ir)
250 {
251    unsigned int operand;
252    struct mbtree *op[2];
253    const glsl_type *vec4_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 4, 1);
254    const glsl_type *vec3_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 3, 1);
255    const glsl_type *vec2_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 2, 1);
256
257    for (operand = 0; operand < ir->get_num_operands(); operand++) {
258       this->result = NULL;
259       ir->operands[operand]->accept(this);
260       if (!this->result) {
261          ir_print_visitor v;
262          printf("Failed to get tree for expression operand:\n");
263          ir->operands[operand]->accept(&v);
264          exit(1);
265       }
266       op[operand] = this->result;
267    }
268
269    this->result = NULL;
270
271    switch (ir->operation) {
272    case ir_binop_add:
273       this->result = this->create_tree(MB_TERM_add_vec4_vec4, op[0], op[1]);
274       break;
275    case ir_binop_sub:
276       this->result = this->create_tree(MB_TERM_sub_vec4_vec4, op[0], op[1]);
277       break;
278    case ir_binop_mul:
279       this->result = this->create_tree(MB_TERM_mul_vec4_vec4, op[0], op[1]);
280       break;
281    case ir_binop_div:
282       this->result = this->create_tree(MB_TERM_div_vec4_vec4, op[0], op[1]);
283       break;
284    case ir_binop_dot:
285       if (ir->operands[0]->type == vec4_type) {
286          assert(ir->operands[1]->type == vec4_type);
287          this->result = this->create_tree(MB_TERM_dp4_vec4_vec4, op[0], op[1]);
288       } else if (ir->operands[0]->type == vec3_type) {
289          assert(ir->operands[1]->type == vec3_type);
290          this->result = this->create_tree(MB_TERM_dp3_vec4_vec4, op[0], op[1]);
291       } else if (ir->operands[0]->type == vec2_type) {
292          assert(ir->operands[1]->type == vec2_type);
293          this->result = this->create_tree(MB_TERM_dp2_vec4_vec4, op[0], op[1]);
294       }
295       break;
296    case ir_unop_sqrt:
297       this->result = this->create_tree(MB_TERM_sqrt_vec4, op[0], op[1]);
298       break;
299    default:
300       break;
301    }
302    if (!this->result) {
303       ir_print_visitor v;
304       printf("Failed to get tree for expression:\n");
305       ir->accept(&v);
306       exit(1);
307    }
308 }
309
310
311 void
312 ir_to_mesa_visitor::visit(ir_swizzle *ir)
313 {
314    struct mbtree *tree;
315    int i;
316    int swizzle[4];
317
318    /* FINISHME: Handle swizzles on the left side of an assignment. */
319
320    ir->val->accept(this);
321    assert(this->result);
322
323    tree = this->create_tree(MB_TERM_swizzle_vec4, this->result, NULL);
324
325    for (i = 0; i < 4; i++) {
326       if (i < ir->type->vector_elements) {
327          switch (i) {
328          case 0:
329             swizzle[i] = ir->mask.x;
330             break;
331          case 1:
332             swizzle[i] = ir->mask.y;
333             break;
334          case 2:
335             swizzle[i] = ir->mask.z;
336             break;
337          case 3:
338             swizzle[i] = ir->mask.w;
339             break;
340          }
341       } else {
342          /* If the type is smaller than a vec4, replicate the last
343           * channel out.
344           */
345          swizzle[i] = ir->type->vector_elements - 1;
346       }
347    }
348
349    tree->src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0],
350                                          swizzle[1],
351                                          swizzle[2],
352                                          swizzle[3]);
353
354    this->result = tree;
355 }
356
357
358 void
359 ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
360 {
361    struct mbtree *tree;
362    int size_swizzles[4] = {
363       MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W),
364       MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z),
365       MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y),
366       MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
367    };
368
369    ir_variable *var = ir->var->as_variable();
370
371    /* By the time we make it to this stage, matric`es should be broken down
372     * to vectors.
373     */
374    assert(!var->type->is_matrix());
375
376    tree = this->create_tree(MB_TERM_reference_vec4, NULL, NULL);
377
378    if (strncmp(var->name, "gl_", 3) == 0) {
379       if (strcmp(var->name, "gl_FragColor") == 0) {
380          tree->src_reg.file = PROGRAM_INPUT;
381          tree->src_reg.index = FRAG_ATTRIB_COL0;
382       } else {
383          assert(0);
384       }
385    } else {
386       this->get_temp_for_var(var, tree);
387    }
388
389    /* If the type is smaller than a vec4, replicate the last channel out. */
390    tree->src_reg.swizzle = size_swizzles[ir->type->vector_elements - 1];
391
392    this->result = tree;
393 }
394
395 void
396 ir_to_mesa_visitor::visit(ir_dereference_array *ir)
397 {
398    struct mbtree *tree;
399    int size_swizzles[4] = {
400       MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W),
401       MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z),
402       MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y),
403       MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
404    };
405
406    ir_variable *var = ir->array->as_variable();
407    ir_constant *index = ir->array_index->constant_expression_value();
408    char *name;
409
410    assert(var);
411    assert(index);
412    assert(strcmp(var->name, "gl_TexCoord") == 0);
413
414    asprintf(&name, "fragment.texcoord[%d]", index->value.i[0]);
415    tree = this->create_tree(MB_TERM_reference_vec4, NULL, NULL);
416    tree->reg_name = name;
417
418    /* If the type is smaller than a vec4, replicate the last channel out. */
419    tree->src_reg.swizzle = size_swizzles[ir->type->vector_elements - 1];
420
421    this->result = tree;
422 }
423
424 void
425 ir_to_mesa_visitor::visit(ir_dereference_record *ir)
426 {
427    (void)ir;
428    assert(0);
429 }
430
431 void
432 ir_to_mesa_visitor::visit(ir_assignment *ir)
433 {
434    struct mbtree *l, *r, *t;
435
436    ir->lhs->accept(this);
437    l = this->result;
438    ir->rhs->accept(this);
439    r = this->result;
440    assert(l);
441    assert(r);
442
443    assert(!ir->condition);
444
445    t = this->create_tree(MB_TERM_assign, l, r);
446    mono_burg_label(t, NULL);
447    reduce(t, MB_NTERM_stmt);
448 }
449
450
451 void
452 ir_to_mesa_visitor::visit(ir_constant *ir)
453 {
454    struct mbtree *tree;
455
456    assert(!ir->type->is_matrix());
457
458    tree = this->create_tree(MB_TERM_reference_vec4, NULL, NULL);
459
460    assert(ir->type->base_type == GLSL_TYPE_FLOAT);
461
462    /* FINISHME: This will end up being _mesa_add_unnamed_constant,
463     * which handles sharing values and sharing channels of vec4
464     * constants for small values.
465     */
466    /* FINISHME: Do something with the constant values for now.
467     */
468    tree->src_reg.file = PROGRAM_CONSTANT;
469    tree->src_reg.index = this->next_constant++;
470    tree->src_reg.swizzle = SWIZZLE_NOOP;
471
472    this->result = tree;
473 }
474
475
476 void
477 ir_to_mesa_visitor::visit(ir_call *ir)
478 {
479    printf("Can't support call to %s\n", ir->callee_name());
480    exit(1);
481 }
482
483
484 void
485 ir_to_mesa_visitor::visit(ir_texture *ir)
486 {
487    assert(0);
488
489    ir->coordinate->accept(this);
490 }
491
492 void
493 ir_to_mesa_visitor::visit(ir_return *ir)
494 {
495    assert(0);
496
497    ir->get_value()->accept(this);
498 }
499
500
501 void
502 ir_to_mesa_visitor::visit(ir_if *ir)
503 {
504    (void)ir;
505    printf("Can't support conditionals, should be flattened before here.\n");
506    exit(1);
507 }
508
509 static struct prog_src_register
510 mesa_src_reg_from_ir_src_reg(ir_to_mesa_src_reg reg)
511 {
512    struct prog_src_register mesa_reg;
513
514    mesa_reg.File = reg.file;
515    mesa_reg.Index = reg.index;
516
517    return mesa_reg;
518 }
519
520 void
521 do_ir_to_mesa(exec_list *instructions)
522 {
523    ir_to_mesa_visitor v;
524    struct prog_instruction *mesa_instructions, *mesa_inst;
525
526    visit_exec_list(instructions, &v);
527
528    int num_instructions = 0;
529    foreach_iter(exec_list_iterator, iter, v.instructions) {
530       num_instructions++;
531    }
532
533    mesa_instructions =
534       (struct prog_instruction *)calloc(num_instructions,
535                                         sizeof(*mesa_instructions));
536
537    mesa_inst = mesa_instructions;
538    foreach_iter(exec_list_iterator, iter, v.instructions) {
539       ir_to_mesa_instruction *inst = (ir_to_mesa_instruction *)iter.get();
540       mesa_inst->Opcode = inst->op;
541       mesa_inst->DstReg.File = inst->dst_reg.file;
542       mesa_inst->DstReg.Index = inst->dst_reg.index;
543       mesa_inst->SrcReg[0] = mesa_src_reg_from_ir_src_reg(inst->src_reg[0]);
544       mesa_inst->SrcReg[1] = mesa_src_reg_from_ir_src_reg(inst->src_reg[1]);
545       mesa_inst->SrcReg[2] = mesa_src_reg_from_ir_src_reg(inst->src_reg[2]);
546       mesa_inst++;
547    }
548 }