Fix Windows newlines.
[mesa.git] / src / mesa / shader / slang / slang_assemble_assignment.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file slang_assemble_assignment.c
27 * slang assignment expressions assembler
28 * \author Michal Krol
29 */
30
31 #include "imports.h"
32 #include "slang_assemble.h"
33 #include "slang_storage.h"
34
35 /*
36 * _slang_assemble_assignment()
37 *
38 * Copies values on the stack (<component 0> to <component N-1>) to a memory
39 * location pointed by <addr of variable>.
40 *
41 * in:
42 * +------------------+
43 * | addr of variable |
44 * +------------------+
45 * | component N-1 |
46 * | ... |
47 * | component 0 |
48 * +------------------+
49 *
50 * out:
51 * +------------------+
52 * | addr of variable |
53 * +------------------+
54 */
55
56 static GLboolean
57 assign_basic (slang_assemble_ctx *A, slang_storage_type type, GLuint *index, GLuint size)
58 {
59 GLuint dst_offset, dst_addr_loc;
60 slang_assembly_type ty;
61
62 /* Calculate the offset within destination variable to write. */
63 if (A->swz.num_components != 0)
64 dst_offset = A->swz.swizzle[*index / 4] * 4;
65 else
66 dst_offset = *index;
67
68 switch (type) {
69 case slang_stor_bool:
70 ty = slang_asm_bool_copy;
71 break;
72 case slang_stor_int:
73 ty = slang_asm_int_copy;
74 break;
75 case slang_stor_float:
76 ty = slang_asm_float_copy;
77 break;
78 #if defined(USE_X86_ASM) || defined(SLANG_X86)
79 case slang_stor_vec4:
80 ty = slang_asm_vec4_copy;
81 break;
82 #endif
83 default:
84 _mesa_problem(NULL, "Unexpected arr->type in assign_basic");
85 ty = slang_asm_none;
86 }
87
88 /* Calculate the distance from top of the stack to the destination address. As the
89 * copy operation progresses, components of the source are being successively popped
90 * off the stack by the amount of *index increase step.
91 */
92 dst_addr_loc = size - *index;
93
94 if (!slang_assembly_file_push_label2 (A->file, ty, dst_addr_loc, dst_offset))
95 return GL_FALSE;
96 *index += _slang_sizeof_type (type);
97
98 return GL_TRUE;
99 }
100
101 static GLboolean
102 assign_aggregate (slang_assemble_ctx *A, const slang_storage_aggregate *agg, GLuint *index,
103 GLuint size)
104 {
105 GLuint i;
106
107 for (i = 0; i < agg->count; i++) {
108 const slang_storage_array *arr = &agg->arrays[i];
109 GLuint j;
110
111 for (j = 0; j < arr->length; j++) {
112 if (arr->type == slang_stor_aggregate) {
113 if (!assign_aggregate (A, arr->aggregate, index, size))
114 return GL_FALSE;
115 }
116 else {
117 /* When the destination is swizzled, we are forced to do float_copy, even if
118 * vec4 extension is enabled with vec4_copy operation.
119 */
120 if (A->swz.num_components != 0 && arr->type == slang_stor_vec4) {
121 if (!assign_basic (A, slang_stor_float, index, size))
122 return GL_FALSE;
123 if (!assign_basic (A, slang_stor_float, index, size))
124 return GL_FALSE;
125 if (!assign_basic (A, slang_stor_float, index, size))
126 return GL_FALSE;
127 if (!assign_basic (A, slang_stor_float, index, size))
128 return GL_FALSE;
129 }
130 else {
131 if (!assign_basic (A, arr->type, index, size))
132 return GL_FALSE;
133 }
134 }
135 }
136 }
137
138 return GL_TRUE;
139 }
140
141 GLboolean _slang_assemble_assignment (slang_assemble_ctx *A, slang_operation *op)
142 {
143 slang_assembly_typeinfo ti;
144 GLboolean result = GL_FALSE;
145 slang_storage_aggregate agg;
146 GLuint index, size;
147
148 if (!slang_assembly_typeinfo_construct (&ti))
149 return GL_FALSE;
150 if (!_slang_typeof_operation (A, op, &ti))
151 goto end1;
152
153 if (!slang_storage_aggregate_construct (&agg))
154 goto end1;
155 if (!_slang_aggregate_variable (&agg, &ti.spec, 0, A->space.funcs, A->space.structs,
156 A->space.vars, A->mach, A->file, A->atoms))
157 goto end;
158
159 index = 0;
160 size = _slang_sizeof_aggregate (&agg);
161 result = assign_aggregate (A, &agg, &index, size);
162
163 end1:
164 slang_storage_aggregate_destruct (&agg);
165 end:
166 slang_assembly_typeinfo_destruct (&ti);
167 return result;
168 }
169
170 /*
171 * _slang_assemble_assign()
172 *
173 * Performs unary (pre ++ and --) or binary (=, +=, -=, *=, /=) assignment on the operation's
174 * children.
175 */
176
177 GLboolean _slang_assemble_assign (slang_assemble_ctx *A, slang_operation *op, const char *oper,
178 slang_ref_type ref)
179 {
180 slang_swizzle swz;
181
182 if (ref == slang_ref_forbid)
183 {
184 if (!slang_assembly_file_push_label2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4))
185 return GL_FALSE;
186 }
187
188 if (slang_string_compare ("=", oper) == 0)
189 {
190 if (!_slang_assemble_operation (A, &op->children[0], slang_ref_force))
191 return GL_FALSE;
192 swz = A->swz;
193 if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
194 return GL_FALSE;
195 A->swz = swz;
196 if (!_slang_assemble_assignment (A, op->children))
197 return GL_FALSE;
198 }
199 else
200 {
201 if (!_slang_assemble_function_call_name (A, oper, op->children, op->num_children, GL_TRUE))
202 return GL_FALSE;
203 }
204
205 if (ref == slang_ref_forbid)
206 {
207 if (!slang_assembly_file_push (A->file, slang_asm_addr_copy))
208 return GL_FALSE;
209 if (!slang_assembly_file_push_label (A->file, slang_asm_local_free, 4))
210 return GL_FALSE;
211 if (!_slang_dereference (A, op->children))
212 return GL_FALSE;
213 }
214
215 return GL_TRUE;
216 }
217