2 #include "main/imports.h"
3 #include "shader/program.h"
4 #include "shader/prog_print.h"
5 #include "slang_compile.h"
6 #include "slang_compile_variable.h"
8 #include "slang_vartable.h"
23 * Variable/register info for one variable scope.
29 slang_variable
**Vars
; /* array [NumVars] */
31 TempState Temps
[MAX_PROGRAM_TEMPS
* 4]; /* per-component state */
32 int ValSize
[MAX_PROGRAM_TEMPS
* 4]; /**< For debug only */
34 struct table
*Parent
; /** Parent scope table */
39 * A variable table is a stack of tables, one per scope.
41 struct slang_var_table_
45 struct table
*Top
; /**< Table at top of stack */
51 _slang_new_var_table(GLuint maxRegisters
)
54 = (slang_var_table
*) _slang_alloc(sizeof(slang_var_table
));
56 vt
->MaxRegisters
= maxRegisters
;
63 _slang_delete_var_table(slang_var_table
*vt
)
66 _mesa_problem(NULL
, "non-empty var table in _slang_delete_var_table()");
75 * Create new table, put at head, return ptr to it.
76 * XXX we should take a maxTemps parameter to indicate how many temporaries
77 * are available for the current shader/program target.
80 _slang_push_var_table(slang_var_table
*vt
)
82 struct table
*t
= (struct table
*) _slang_alloc(sizeof(struct table
));
84 t
->Level
= vt
->CurLevel
++;
87 /* copy the info indicating which temp regs are in use */
88 memcpy(t
->Temps
, t
->Parent
->Temps
, sizeof(t
->Temps
));
89 memcpy(t
->ValSize
, t
->Parent
->ValSize
, sizeof(t
->ValSize
));
92 if (dbg
) printf("Pushing level %d\n", t
->Level
);
98 * Destroy given table, return ptr to Parent
101 _slang_pop_var_table(slang_var_table
*vt
)
103 struct table
*t
= vt
->Top
;
106 if (dbg
) printf("Popping level %d\n", t
->Level
);
108 /* free the storage allocated for each variable */
109 for (i
= 0; i
< t
->NumVars
; i
++) {
110 slang_ir_storage
*store
= (slang_ir_storage
*) t
->Vars
[i
]->aux
;
113 if (dbg
) printf(" Free var %s, size %d at %d\n",
114 (char*) t
->Vars
[i
]->a_name
, store
->Size
,
117 if (store
->Size
== 1)
118 comp
= GET_SWZ(store
->Swizzle
, 0);
122 assert(store
->Index
>= 0);
123 for (j
= 0; j
< store
->Size
; j
++) {
124 assert(t
->Temps
[store
->Index
* 4 + j
+ comp
] == VAR
);
125 t
->Temps
[store
->Index
* 4 + j
+ comp
] = FREE
;
130 /* just verify that any remaining allocations in this scope
133 for (i
= 0; i
< (int) vt
->MaxRegisters
* 4; i
++) {
134 if (t
->Temps
[i
] != FREE
&& t
->Parent
->Temps
[i
] == FREE
) {
135 if (dbg
) printf(" Free reg %d\n", i
/4);
136 assert(t
->Temps
[i
] == TEMP
);
142 _slang_free(t
->Vars
);
153 * Add a new variable to the given symbol table.
156 _slang_add_variable(slang_var_table
*vt
, slang_variable
*v
)
162 if (dbg
) printf("Adding var %s\n", (char *) v
->a_name
);
163 t
->Vars
= (slang_variable
**)
164 _slang_realloc(t
->Vars
,
165 t
->NumVars
* sizeof(slang_variable
*),
166 (t
->NumVars
+ 1) * sizeof(slang_variable
*));
167 t
->Vars
[t
->NumVars
] = v
;
173 * Look for variable by name in given table.
174 * If not found, Parent table will be searched.
177 _slang_find_variable(const slang_var_table
*vt
, slang_atom name
)
179 struct table
*t
= vt
->Top
;
182 for (i
= 0; i
< t
->NumVars
; i
++) {
183 if (t
->Vars
[i
]->a_name
== name
)
196 * \param size var size in floats
197 * \return position for var, measured in floats
200 alloc_reg(slang_var_table
*vt
, GLint size
, GLboolean isTemp
)
202 struct table
*t
= vt
->Top
;
203 /* if size == 1, allocate anywhere, else, pos must be multiple of 4 */
204 const GLuint step
= (size
== 1) ? 1 : 4;
206 assert(size
> 0); /* number of floats */
208 for (i
= 0; i
<= vt
->MaxRegisters
* 4 - size
; i
+= step
) {
210 for (j
= 0; j
< (GLuint
) size
; j
++) {
211 if (i
+ j
< vt
->MaxRegisters
* 4 && t
->Temps
[i
+ j
] == FREE
) {
219 /* found block of size free regs */
222 for (j
= 0; j
< (GLuint
) size
; j
++)
223 t
->Temps
[i
+ j
] = isTemp
? TEMP
: VAR
;
224 assert(i
< MAX_PROGRAM_TEMPS
* 4);
225 t
->ValSize
[i
] = size
;
234 * Allocate temp register(s) for storing a variable.
235 * \param size size needed, in floats
236 * \param swizzle returns swizzle mask for accessing var in register
237 * \return register allocated, or -1
240 _slang_alloc_var(slang_var_table
*vt
, slang_ir_storage
*store
)
242 struct table
*t
= vt
->Top
;
243 const int i
= alloc_reg(vt
, store
->Size
, GL_FALSE
);
247 store
->Index
= i
/ 4;
248 if (store
->Size
== 1) {
249 const GLuint comp
= i
% 4;
250 store
->Swizzle
= MAKE_SWIZZLE4(comp
, comp
, comp
, comp
);
252 else if (store
->Size
== 2) {
253 store
->Swizzle
= MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
,
254 SWIZZLE_NIL
, SWIZZLE_NIL
);
256 else if (store
->Size
== 3) {
257 store
->Swizzle
= MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
,
258 SWIZZLE_Z
, SWIZZLE_NIL
);
261 store
->Swizzle
= SWIZZLE_NOOP
;
265 printf("Alloc var sz %d at %d.%s (level %d)\n",
266 store
->Size
, store
->Index
,
267 _mesa_swizzle_string(store
->Swizzle
, 0, 0),
276 * Allocate temp register(s) for storing an unnamed intermediate value.
279 _slang_alloc_temp(slang_var_table
*vt
, slang_ir_storage
*store
)
281 struct table
*t
= vt
->Top
;
282 const int i
= alloc_reg(vt
, store
->Size
, GL_TRUE
);
286 store
->Index
= i
/ 4;
287 if (store
->Size
== 1) {
288 const GLuint comp
= i
% 4;
289 store
->Swizzle
= MAKE_SWIZZLE4(comp
, comp
, comp
, comp
);
290 if (dbg
) printf("Alloc temp sz %d at %d.%c (level %d)\n",
291 store
->Size
, store
->Index
, "xyzw"[comp
], t
->Level
);
294 /* XXX improve swizzled for size=2/3, use for writemask... */
295 store
->Swizzle
= SWIZZLE_NOOP
;
296 if (dbg
) printf("Alloc temp sz %d at %d.xyzw (level %d)\n",
297 store
->Size
, store
->Index
, t
->Level
);
304 _slang_free_temp(slang_var_table
*vt
, slang_ir_storage
*store
)
306 struct table
*t
= vt
->Top
;
308 GLuint r
= store
->Index
;
309 assert(store
->Size
> 0);
311 assert(r
+ store
->Size
<= vt
->MaxRegisters
* 4);
312 if (dbg
) printf("Free temp sz %d at %d (level %d)\n", store
->Size
, r
, t
->Level
);
313 if (store
->Size
== 1) {
314 const GLuint comp
= GET_SWZ(store
->Swizzle
, 0);
315 assert(store
->Swizzle
== MAKE_SWIZZLE4(comp
, comp
, comp
, comp
));
317 assert(t
->ValSize
[r
* 4 + comp
] == 1);
318 assert(t
->Temps
[r
* 4 + comp
] == TEMP
);
319 t
->Temps
[r
* 4 + comp
] = FREE
;
322 /*assert(store->Swizzle == SWIZZLE_NOOP);*/
323 assert(t
->ValSize
[r
*4] == store
->Size
);
324 for (i
= 0; i
< (GLuint
) store
->Size
; i
++) {
325 assert(t
->Temps
[r
* 4 + i
] == TEMP
);
326 t
->Temps
[r
* 4 + i
] = FREE
;
333 _slang_is_temp(const slang_var_table
*vt
, const slang_ir_storage
*store
)
335 struct table
*t
= vt
->Top
;
337 assert(store
->Index
>= 0);
338 assert(store
->Index
< (int) vt
->MaxRegisters
);
339 if (store
->Swizzle
== SWIZZLE_NOOP
)
342 comp
= GET_SWZ(store
->Swizzle
, 0);
344 if (t
->Temps
[store
->Index
* 4 + comp
] == TEMP
)