3 #include "slang_compile.h"
4 #include "slang_compile_variable.h"
5 #include "slang_vartable.h"
7 #include "prog_instruction.h"
21 * Variable/register info for one variable scope.
27 slang_variable
**Vars
; /* array [NumVars] */
29 TempState Temps
[MAX_PROGRAM_TEMPS
* 4]; /* per-component state */
30 int ValSize
[MAX_PROGRAM_TEMPS
]; /* For debug only */
32 struct table
*Parent
; /** Parent scope table */
37 * A variable table is a stack of tables, one per scope.
39 struct slang_var_table_
43 struct table
*Top
; /**< Table at top of stack */
49 _slang_new_var_table(GLuint maxRegisters
)
52 = (slang_var_table
*) _mesa_calloc(sizeof(slang_var_table
));
54 vt
->MaxRegisters
= maxRegisters
;
61 _slang_delete_var_table(slang_var_table
*vt
)
64 _mesa_problem(NULL
, "non-empty var table in _slang_delete_var_table()");
73 * Create new table, put at head, return ptr to it.
74 * XXX we should take a maxTemps parameter to indicate how many temporaries
75 * are available for the current shader/program target.
78 _slang_push_var_table(slang_var_table
*vt
)
80 struct table
*t
= (struct table
*) _mesa_calloc(sizeof(struct table
));
82 t
->Level
= vt
->CurLevel
++;
85 /* copy the info indicating which temp regs are in use */
86 memcpy(t
->Temps
, t
->Parent
->Temps
, sizeof(t
->Temps
));
87 memcpy(t
->ValSize
, t
->Parent
->ValSize
, sizeof(t
->ValSize
));
90 if (dbg
) printf("Pushing level %d\n", t
->Level
);
96 * Destroy given table, return ptr to Parent
99 _slang_pop_var_table(slang_var_table
*vt
)
101 struct table
*t
= vt
->Top
;
104 if (dbg
) printf("Popping level %d\n", t
->Level
);
106 /* free the storage allocated for each variable */
107 for (i
= 0; i
< t
->NumVars
; i
++) {
108 slang_ir_storage
*store
= (slang_ir_storage
*) t
->Vars
[i
]->aux
;
111 if (dbg
) printf(" Free var %s, size %d at %d\n",
112 (char*) t
->Vars
[i
]->a_name
, store
->Size
,
115 if (store
->Size
== 1)
116 comp
= GET_SWZ(store
->Swizzle
, 0);
120 assert(store
->Index
>= 0);
121 for (j
= 0; j
< store
->Size
; j
++) {
122 assert(t
->Temps
[store
->Index
* 4 + j
+ comp
] == VAR
);
123 t
->Temps
[store
->Index
* 4 + j
+ comp
] = FREE
;
128 /* just verify that any remaining allocations in this scope
131 for (i
= 0; i
< vt
->MaxRegisters
* 4; i
++) {
132 if (t
->Temps
[i
] != FREE
&& t
->Parent
->Temps
[i
] == FREE
) {
133 if (dbg
) printf(" Free reg %d\n", i
/4);
134 assert(t
->Temps
[i
] == TEMP
);
149 * Add a new variable to the given symbol table.
152 _slang_add_variable(slang_var_table
*vt
, slang_variable
*v
)
158 if (dbg
) printf("Adding var %s\n", (char *) v
->a_name
);
159 t
->Vars
= realloc(t
->Vars
, (t
->NumVars
+ 1) * sizeof(slang_variable
*));
160 t
->Vars
[t
->NumVars
] = v
;
166 * Look for variable by name in given table.
167 * If not found, Parent table will be searched.
170 _slang_find_variable(const slang_var_table
*vt
, slang_atom name
)
172 struct table
*t
= vt
->Top
;
175 for (i
= 0; i
< t
->NumVars
; i
++) {
176 if (t
->Vars
[i
]->a_name
== name
)
189 * \param size var size in floats
190 * \return position for var, measured in floats
193 alloc_reg(slang_var_table
*vt
, GLint size
, GLboolean isTemp
)
195 struct table
*t
= vt
->Top
;
196 /* if size == 1, allocate anywhere, else, pos must be multiple of 4 */
197 const GLuint step
= (size
== 1) ? 1 : 4;
199 assert(size
> 0); /* number of floats */
201 for (i
= 0; i
<= vt
->MaxRegisters
* 4 - size
; i
+= step
) {
203 for (j
= 0; j
< size
; j
++) {
204 if (i
+ j
< vt
->MaxRegisters
* 4 && t
->Temps
[i
+ j
] == FREE
) {
212 /* found block of size free regs */
215 for (j
= 0; j
< size
; j
++)
216 t
->Temps
[i
+ j
] = isTemp
? TEMP
: VAR
;
217 t
->ValSize
[i
] = size
;
226 * Allocate temp register(s) for storing a variable.
227 * \param size size needed, in floats
228 * \param swizzle returns swizzle mask for accessing var in register
229 * \return register allocated, or -1
232 _slang_alloc_var(slang_var_table
*vt
, slang_ir_storage
*store
)
234 struct table
*t
= vt
->Top
;
235 const int i
= alloc_reg(vt
, store
->Size
, GL_FALSE
);
239 store
->Index
= i
/ 4;
240 if (store
->Size
== 1) {
241 const GLuint comp
= i
% 4;
242 store
->Swizzle
= MAKE_SWIZZLE4(comp
, comp
, comp
, comp
);
243 if (dbg
) printf("Alloc var sz %d at %d.%c (level %d)\n",
244 store
->Size
, store
->Index
, "xyzw"[comp
], t
->Level
);
247 store
->Swizzle
= SWIZZLE_NOOP
;
248 if (dbg
) printf("Alloc var sz %d at %d.xyzw (level %d)\n",
249 store
->Size
, store
->Index
, t
->Level
);
257 * Allocate temp register(s) for storing an unnamed intermediate value.
260 _slang_alloc_temp(slang_var_table
*vt
, slang_ir_storage
*store
)
262 struct table
*t
= vt
->Top
;
263 const int i
= alloc_reg(vt
, store
->Size
, GL_TRUE
);
267 store
->Index
= i
/ 4;
268 if (store
->Size
== 1) {
269 const GLuint comp
= i
% 4;
270 store
->Swizzle
= MAKE_SWIZZLE4(comp
, comp
, comp
, comp
);
271 if (dbg
) printf("Alloc temp sz %d at %d.%c (level %d)\n",
272 store
->Size
, store
->Index
, "xyzw"[comp
], t
->Level
);
275 store
->Swizzle
= SWIZZLE_NOOP
;
276 if (dbg
) printf("Alloc temp sz %d at %d.xyzw (level %d)\n",
277 store
->Size
, store
->Index
, t
->Level
);
284 _slang_free_temp(slang_var_table
*vt
, slang_ir_storage
*store
)
286 struct table
*t
= vt
->Top
;
288 GLuint r
= store
->Index
;
289 assert(store
->Size
> 0);
291 assert(r
+ store
->Size
<= vt
->MaxRegisters
* 4);
292 if (dbg
) printf("Free temp sz %d at %d (level %d)\n", store
->Size
, r
, t
->Level
);
293 if (store
->Size
== 1) {
294 const GLuint comp
= GET_SWZ(store
->Swizzle
, 0);
295 assert(store
->Swizzle
== MAKE_SWIZZLE4(comp
, comp
, comp
, comp
));
297 assert(t
->ValSize
[r
* 4 + comp
] == 1);
298 assert(t
->Temps
[r
* 4 + comp
] == TEMP
);
299 t
->Temps
[r
* 4 + comp
] = FREE
;
302 /*assert(store->Swizzle == SWIZZLE_NOOP);*/
303 assert(t
->ValSize
[r
*4] == store
->Size
);
304 for (i
= 0; i
< store
->Size
; i
++) {
305 assert(t
->Temps
[r
* 4 + i
] == TEMP
);
306 t
->Temps
[r
* 4 + i
] = FREE
;
313 _slang_is_temp(const slang_var_table
*vt
, const slang_ir_storage
*store
)
315 struct table
*t
= vt
->Top
;
316 assert(store
->Index
>= 0);
317 assert(store
->Index
< vt
->MaxRegisters
);
319 if (store
->Swizzle
== SWIZZLE_NOOP
)
322 comp
= GET_SWZ(store
->Swizzle
, 0);
324 if (t
->Temps
[store
->Index
* 4 + comp
] == TEMP
)