2 * Mesa 3-D graphics library
5 * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
26 * \file slang_assemble_constructor.c
27 * slang constructor and vector swizzle assembler
32 #include "slang_assemble.h"
33 #include "slang_storage.h"
35 /* _slang_is_swizzle() */
37 GLboolean
_slang_is_swizzle (const char *field
, GLuint rows
, slang_swizzle
*swz
)
40 GLboolean xyzw
= GL_FALSE
, rgba
= GL_FALSE
, stpq
= GL_FALSE
;
42 /* the swizzle can be at most 4-component long */
43 swz
->num_components
= slang_string_length (field
);
44 if (swz
->num_components
> 4)
47 for (i
= 0; i
< swz
->num_components
; i
++)
49 /* mark which swizzle group is used */
74 /* collect swizzle component */
99 /* check if the component is valid for given vector's row count */
100 if (rows
<= swz
->swizzle
[i
])
104 /* only one swizzle group can be used */
105 if ((xyzw
&& rgba
) || (xyzw
&& stpq
) || (rgba
&& stpq
))
111 /* _slang_is_swizzle_mask() */
113 GLboolean
_slang_is_swizzle_mask (const slang_swizzle
*swz
, GLuint rows
)
117 /* the swizzle may not be longer than the vector dim */
118 if (swz
->num_components
> rows
)
121 /* the swizzle components cannot be duplicated */
122 for (i
= 0; i
< swz
->num_components
; i
++)
124 if ((c
& (1 << swz
->swizzle
[i
])) != 0)
126 c
|= 1 << swz
->swizzle
[i
];
132 /* _slang_multiply_swizzles() */
134 GLvoid
_slang_multiply_swizzles (slang_swizzle
*dst
, const slang_swizzle
*left
,
135 const slang_swizzle
*right
)
139 dst
->num_components
= right
->num_components
;
140 for (i
= 0; i
< right
->num_components
; i
++)
141 dst
->swizzle
[i
] = left
->swizzle
[right
->swizzle
[i
]];
144 /* _slang_assemble_constructor() */
147 sizeof_argument (slang_assemble_ctx
*A
, GLuint
*size
, slang_operation
*op
)
149 slang_assembly_typeinfo ti
;
150 GLboolean result
= GL_FALSE
;
151 slang_storage_aggregate agg
;
153 if (!slang_assembly_typeinfo_construct (&ti
))
155 if (!_slang_typeof_operation (A
, op
, &ti
))
158 if (!slang_storage_aggregate_construct (&agg
))
160 if (!_slang_aggregate_variable (&agg
, &ti
.spec
, 0, A
->space
.funcs
, A
->space
.structs
,
161 A
->space
.vars
, A
->mach
, A
->file
, A
->atoms
))
164 *size
= _slang_sizeof_aggregate (&agg
);
168 slang_storage_aggregate_destruct (&agg
);
170 slang_assembly_typeinfo_destruct (&ti
);
174 static GLboolean
constructor_aggregate (slang_assemble_ctx
*A
, const slang_storage_aggregate
*flat
,
175 slang_operation
*op
, GLuint garbage_size
)
177 slang_assembly_typeinfo ti
;
178 GLboolean result
= GL_FALSE
;
179 slang_storage_aggregate agg
, flat_agg
;
181 if (!slang_assembly_typeinfo_construct (&ti
))
183 if (!_slang_typeof_operation (A
, op
, &ti
))
186 if (!slang_storage_aggregate_construct (&agg
))
188 if (!_slang_aggregate_variable (&agg
, &ti
.spec
, 0, A
->space
.funcs
, A
->space
.structs
,
189 A
->space
.vars
, A
->mach
, A
->file
, A
->atoms
))
192 if (!slang_storage_aggregate_construct (&flat_agg
))
194 if (!_slang_flatten_aggregate (&flat_agg
, &agg
))
197 if (!_slang_assemble_operation (A
, op
, slang_ref_forbid
))
200 /* TODO: convert (generic) elements */
202 /* free the garbage */
203 if (garbage_size
!= 0)
207 /* move the non-garbage part to the end of the argument */
208 if (!slang_assembly_file_push_label (A
->file
, slang_asm_addr_push
, 0))
210 for (i
= flat_agg
.count
* 4 - garbage_size
; i
> 0; i
-= 4)
212 if (!slang_assembly_file_push_label2 (A
->file
, slang_asm_float_move
,
213 garbage_size
+ i
, i
))
218 if (!slang_assembly_file_push_label (A
->file
, slang_asm_local_free
, garbage_size
+ 4))
224 slang_storage_aggregate_destruct (&flat_agg
);
226 slang_storage_aggregate_destruct (&agg
);
228 slang_assembly_typeinfo_destruct (&ti
);
232 GLboolean
_slang_assemble_constructor (slang_assemble_ctx
*A
, slang_operation
*op
)
234 slang_assembly_typeinfo ti
;
235 GLboolean result
= GL_FALSE
;
236 slang_storage_aggregate agg
, flat
;
240 /* get typeinfo of the constructor (the result of constructor expression) */
241 if (!slang_assembly_typeinfo_construct (&ti
))
243 if (!_slang_typeof_operation (A
, op
, &ti
))
246 /* create an aggregate of the constructor */
247 if (!slang_storage_aggregate_construct (&agg
))
249 if (!_slang_aggregate_variable (&agg
, &ti
.spec
, 0, A
->space
.funcs
, A
->space
.structs
,
250 A
->space
.vars
, A
->mach
, A
->file
, A
->atoms
))
253 /* calculate size of the constructor */
254 size
= _slang_sizeof_aggregate (&agg
);
256 /* flatten the constructor */
257 if (!slang_storage_aggregate_construct (&flat
))
259 if (!_slang_flatten_aggregate (&flat
, &agg
))
262 /* collect the last two constructor's argument size sums */
263 arg_sums
[0] = 0; /* will hold all but the last argument's size sum */
264 arg_sums
[1] = 0; /* will hold all argument's size sum */
265 for (i
= 0; i
< op
->num_children
; i
++)
269 if (!sizeof_argument (A
, &arg_size
, &op
->children
[i
]))
272 arg_sums
[0] = arg_sums
[1];
273 arg_sums
[1] += arg_size
;
276 /* check if there are too many arguments */
277 if (arg_sums
[0] >= size
)
279 /* TODO: info log: too many arguments in constructor list */
283 /* check if there are too few arguments */
284 if (arg_sums
[1] < size
)
286 /* TODO: info log: too few arguments in constructor list */
290 /* traverse the children that form the constructor expression */
291 for (i
= op
->num_children
; i
> 0; i
--)
295 /* the last argument may be too big - calculate the unnecessary data size */
296 if (i
== op
->num_children
)
297 garbage_size
= arg_sums
[1] - size
;
301 if (!constructor_aggregate (A
, &flat
, &op
->children
[i
- 1], garbage_size
))
307 slang_storage_aggregate_destruct (&flat
);
309 slang_storage_aggregate_destruct (&agg
);
311 slang_assembly_typeinfo_destruct (&ti
);
315 /* _slang_assemble_constructor_from_swizzle() */
317 GLboolean
_slang_assemble_constructor_from_swizzle (slang_assemble_ctx
*A
, const slang_swizzle
*swz
,
318 slang_type_specifier
*spec
, slang_type_specifier
*master_spec
)
320 GLuint master_rows
, i
;
322 master_rows
= _slang_type_dim (master_spec
->type
);
323 for (i
= 0; i
< master_rows
; i
++)
325 switch (_slang_type_base (master_spec
->type
))
327 case slang_spec_bool
:
328 if (!slang_assembly_file_push_label2 (A
->file
, slang_asm_bool_copy
,
329 (master_rows
- i
) * 4, i
* 4))
333 if (!slang_assembly_file_push_label2 (A
->file
, slang_asm_int_copy
,
334 (master_rows
- i
) * 4, i
* 4))
337 case slang_spec_float
:
338 if (!slang_assembly_file_push_label2 (A
->file
, slang_asm_float_copy
,
339 (master_rows
- i
) * 4, i
* 4))
346 if (!slang_assembly_file_push_label (A
->file
, slang_asm_local_free
, 4))
348 for (i
= swz
->num_components
; i
> 0; i
--)
352 if (!slang_assembly_file_push_label2 (A
->file
, slang_asm_local_addr
, A
->local
.swizzle_tmp
, 16))
354 if (!slang_assembly_file_push_label (A
->file
, slang_asm_addr_push
, swz
->swizzle
[n
] * 4))
356 if (!slang_assembly_file_push (A
->file
, slang_asm_addr_add
))
358 switch (_slang_type_base (master_spec
->type
))
360 case slang_spec_bool
:
361 if (!slang_assembly_file_push (A
->file
, slang_asm_bool_deref
))
365 if (!slang_assembly_file_push (A
->file
, slang_asm_int_deref
))
368 case slang_spec_float
:
369 if (!slang_assembly_file_push (A
->file
, slang_asm_float_deref
))