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_utility.h"
33 #include "slang_assemble_constructor.h"
34 #include "slang_assemble_typeinfo.h"
35 #include "slang_storage.h"
37 /* _slang_is_swizzle() */
39 GLboolean
_slang_is_swizzle (const char *field
, GLuint rows
, slang_swizzle
*swz
)
42 GLboolean xyzw
= GL_FALSE
, rgba
= GL_FALSE
, stpq
= GL_FALSE
;
44 /* the swizzle can be at most 4-component long */
45 swz
->num_components
= slang_string_length (field
);
46 if (swz
->num_components
> 4)
49 for (i
= 0; i
< swz
->num_components
; i
++)
51 /* mark which swizzle group is used */
76 /* collect swizzle component */
101 /* check if the component is valid for given vector's row count */
102 if (rows
<= swz
->swizzle
[i
])
106 /* only one swizzle group can be used */
107 if ((xyzw
&& rgba
) || (xyzw
&& stpq
) || (rgba
&& stpq
))
113 /* _slang_is_swizzle_mask() */
115 GLboolean
_slang_is_swizzle_mask (const slang_swizzle
*swz
, GLuint rows
)
119 /* the swizzle may not be longer than the vector dim */
120 if (swz
->num_components
> rows
)
123 /* the swizzle components cannot be duplicated */
124 for (i
= 0; i
< swz
->num_components
; i
++)
126 if ((c
& (1 << swz
->swizzle
[i
])) != 0)
128 c
|= 1 << swz
->swizzle
[i
];
134 /* _slang_multiply_swizzles() */
136 GLvoid
_slang_multiply_swizzles (slang_swizzle
*dst
, const slang_swizzle
*left
,
137 const slang_swizzle
*right
)
141 dst
->num_components
= right
->num_components
;
142 for (i
= 0; i
< right
->num_components
; i
++)
143 dst
->swizzle
[i
] = left
->swizzle
[right
->swizzle
[i
]];
146 /* _slang_assemble_constructor() */
148 static GLboolean
constructor_aggregate (slang_assemble_ctx
*A
, const slang_storage_aggregate
*flat
,
149 GLuint
*index
, slang_operation
*op
, GLuint size
)
151 slang_assembly_typeinfo ti
;
152 GLboolean result
= GL_FALSE
;
153 slang_storage_aggregate agg
, flat_agg
;
156 if (!slang_assembly_typeinfo_construct (&ti
))
158 if (!_slang_typeof_operation (op
, &A
->space
, &ti
, A
->atoms
))
161 if (!slang_storage_aggregate_construct (&agg
))
163 if (!_slang_aggregate_variable (&agg
, &ti
.spec
, NULL
, A
->space
.funcs
, A
->space
.structs
,
164 A
->space
.vars
, A
->mach
, A
->file
, A
->atoms
))
167 if (!slang_storage_aggregate_construct (&flat_agg
))
169 if (!_slang_flatten_aggregate (&flat_agg
, &agg
))
172 if (!_slang_assemble_operation_ (A
, op
, slang_ref_forbid
))
175 for (i
= 0; i
< flat_agg
.count
; i
++)
177 const slang_storage_array
*arr1
= &flat_agg
.arrays
[i
];
178 const slang_storage_array
*arr2
= &flat
->arrays
[*index
];
180 if (arr1
->type
!= arr2
->type
)
182 /* TODO: convert (generic) from arr1 to arr2 */
185 /* TODO: watch the index, if it reaches the size, pop off the stack subsequent values */
190 slang_storage_aggregate_destruct (&flat_agg
);
192 slang_storage_aggregate_destruct (&agg
);
194 slang_assembly_typeinfo_destruct (&ti
);
198 GLboolean
_slang_assemble_constructor (slang_assemble_ctx
*A
, slang_operation
*op
)
200 slang_assembly_typeinfo ti
;
201 GLboolean result
= GL_FALSE
;
202 slang_storage_aggregate agg
, flat
;
203 GLuint size
, index
, i
;
205 /* get typeinfo of the constructor (the result of constructor expression) */
206 if (!slang_assembly_typeinfo_construct (&ti
))
208 if (!_slang_typeof_operation (op
, &A
->space
, &ti
, A
->atoms
))
211 /* create an aggregate of the constructor */
212 if (!slang_storage_aggregate_construct (&agg
))
214 if (!_slang_aggregate_variable (&agg
, &ti
.spec
, NULL
, A
->space
.funcs
, A
->space
.structs
,
215 A
->space
.vars
, A
->mach
, A
->file
, A
->atoms
))
218 /* calculate size of the constructor */
219 size
= _slang_sizeof_aggregate (&agg
);
221 /* flatten the constructor */
222 if (!slang_storage_aggregate_construct (&flat
))
224 if (!_slang_flatten_aggregate (&flat
, &agg
))
227 /* XXX: The children operations are traversed in a reversed order, so it poses a
228 * problem when there is more data than the constructor needs. We must fix it! */
230 /* traverse the children that form the constructor expression */
232 for (i
= op
->num_children
; i
> 0; i
--)
234 if (!constructor_aggregate (A
, &flat
, &index
, &op
->children
[i
- 1], size
))
236 /* TODO: watch the index, if it reaches the size, raise an error */
241 slang_storage_aggregate_destruct (&flat
);
243 slang_storage_aggregate_destruct (&agg
);
245 slang_assembly_typeinfo_destruct (&ti
);
249 /* _slang_assemble_constructor_from_swizzle() */
251 GLboolean
_slang_assemble_constructor_from_swizzle (slang_assemble_ctx
*A
, const slang_swizzle
*swz
,
252 slang_type_specifier
*spec
, slang_type_specifier
*master_spec
)
254 GLuint master_rows
, i
;
256 master_rows
= _slang_type_dim (master_spec
->type
);
257 for (i
= 0; i
< master_rows
; i
++)
259 switch (_slang_type_base (master_spec
->type
))
261 case slang_spec_bool
:
262 if (!slang_assembly_file_push_label2 (A
->file
, slang_asm_bool_copy
,
263 (master_rows
- i
) * 4, i
* 4))
267 if (!slang_assembly_file_push_label2 (A
->file
, slang_asm_int_copy
,
268 (master_rows
- i
) * 4, i
* 4))
271 case slang_spec_float
:
272 if (!slang_assembly_file_push_label2 (A
->file
, slang_asm_float_copy
,
273 (master_rows
- i
) * 4, i
* 4))
280 if (!slang_assembly_file_push_label (A
->file
, slang_asm_local_free
, 4))
282 for (i
= swz
->num_components
; i
> 0; i
--)
286 if (!slang_assembly_file_push_label2 (A
->file
, slang_asm_local_addr
, A
->local
.swizzle_tmp
, 16))
288 if (!slang_assembly_file_push_label (A
->file
, slang_asm_addr_push
, swz
->swizzle
[n
] * 4))
290 if (!slang_assembly_file_push (A
->file
, slang_asm_addr_add
))
292 switch (_slang_type_base (master_spec
->type
))
294 case slang_spec_bool
:
295 if (!slang_assembly_file_push (A
->file
, slang_asm_bool_deref
))
299 if (!slang_assembly_file_push (A
->file
, slang_asm_int_deref
))
302 case slang_spec_float
:
303 if (!slang_assembly_file_push (A
->file
, slang_asm_float_deref
))