2 #include "main/imports.h"
3 #include "shader/prog_instruction.h"
4 #include "slang_compile.h"
5 #include "slang_compile_variable.h"
7 #include "slang_vartable.h"
22 * Variable/register info for one variable scope.
28 slang_variable
**Vars
; /* array [NumVars] */
30 TempState Temps
[MAX_PROGRAM_TEMPS
* 4]; /* per-component state */
31 int ValSize
[MAX_PROGRAM_TEMPS
]; /* For debug only */
33 struct table
*Parent
; /** Parent scope table */
38 * A variable table is a stack of tables, one per scope.
40 struct slang_var_table_
44 struct table
*Top
; /**< Table at top of stack */
50 _slang_new_var_table(GLuint maxRegisters
)
53 = (slang_var_table
*) _slang_alloc(sizeof(slang_var_table
));
55 vt
->MaxRegisters
= maxRegisters
;
62 _slang_delete_var_table(slang_var_table
*vt
)
65 _mesa_problem(NULL
, "non-empty var table in _slang_delete_var_table()");
74 * Create new table, put at head, return ptr to it.
75 * XXX we should take a maxTemps parameter to indicate how many temporaries
76 * are available for the current shader/program target.
79 _slang_push_var_table(slang_var_table
*vt
)
81 struct table
*t
= (struct table
*) _slang_alloc(sizeof(struct table
));
83 t
->Level
= vt
->CurLevel
++;
86 /* copy the info indicating which temp regs are in use */
87 memcpy(t
->Temps
, t
->Parent
->Temps
, sizeof(t
->Temps
));
88 memcpy(t
->ValSize
, t
->Parent
->ValSize
, sizeof(t
->ValSize
));
91 if (dbg
) printf("Pushing level %d\n", t
->Level
);
97 * Destroy given table, return ptr to Parent
100 _slang_pop_var_table(slang_var_table
*vt
)
102 struct table
*t
= vt
->Top
;
105 if (dbg
) printf("Popping level %d\n", t
->Level
);
107 /* free the storage allocated for each variable */
108 for (i
= 0; i
< t
->NumVars
; i
++) {
109 slang_ir_storage
*store
= (slang_ir_storage
*) t
->Vars
[i
]->aux
;
112 if (dbg
) printf(" Free var %s, size %d at %d\n",
113 (char*) t
->Vars
[i
]->a_name
, store
->Size
,
116 if (store
->Size
== 1)
117 comp
= GET_SWZ(store
->Swizzle
, 0);
121 assert(store
->Index
>= 0);
122 for (j
= 0; j
< store
->Size
; j
++) {
123 assert(t
->Temps
[store
->Index
* 4 + j
+ comp
] == VAR
);
124 t
->Temps
[store
->Index
* 4 + j
+ comp
] = FREE
;
129 /* just verify that any remaining allocations in this scope
132 for (i
= 0; i
< vt
->MaxRegisters
* 4; i
++) {
133 if (t
->Temps
[i
] != FREE
&& t
->Parent
->Temps
[i
] == FREE
) {
134 if (dbg
) printf(" Free reg %d\n", i
/4);
135 assert(t
->Temps
[i
] == TEMP
);
141 _slang_free(t
->Vars
);
152 * Add a new variable to the given symbol table.
155 _slang_add_variable(slang_var_table
*vt
, slang_variable
*v
)
161 if (dbg
) printf("Adding var %s\n", (char *) v
->a_name
);
162 t
->Vars
= (slang_variable
**)
163 _slang_realloc(t
->Vars
,
164 t
->NumVars
* sizeof(slang_variable
*),
165 (t
->NumVars
+ 1) * sizeof(slang_variable
*));
166 t
->Vars
[t
->NumVars
] = v
;
172 * Look for variable by name in given table.
173 * If not found, Parent table will be searched.
176 _slang_find_variable(const slang_var_table
*vt
, slang_atom name
)
178 struct table
*t
= vt
->Top
;
181 for (i
= 0; i
< t
->NumVars
; i
++) {
182 if (t
->Vars
[i
]->a_name
== name
)
195 * \param size var size in floats
196 * \return position for var, measured in floats
199 alloc_reg(slang_var_table
*vt
, GLint size
, GLboolean isTemp
)
201 struct table
*t
= vt
->Top
;
202 /* if size == 1, allocate anywhere, else, pos must be multiple of 4 */
203 const GLuint step
= (size
== 1) ? 1 : 4;
205 assert(size
> 0); /* number of floats */
207 for (i
= 0; i
<= vt
->MaxRegisters
* 4 - size
; i
+= step
) {
209 for (j
= 0; j
< size
; j
++) {
210 if (i
+ j
< vt
->MaxRegisters
* 4 && t
->Temps
[i
+ j
] == FREE
) {
218 /* found block of size free regs */
221 for (j
= 0; j
< size
; j
++)
222 t
->Temps
[i
+ j
] = isTemp
? TEMP
: VAR
;
223 t
->ValSize
[i
] = size
;
232 * Allocate temp register(s) for storing a variable.
233 * \param size size needed, in floats
234 * \param swizzle returns swizzle mask for accessing var in register
235 * \return register allocated, or -1
238 _slang_alloc_var(slang_var_table
*vt
, slang_ir_storage
*store
)
240 struct table
*t
= vt
->Top
;
241 const int i
= alloc_reg(vt
, store
->Size
, GL_FALSE
);
245 store
->Index
= i
/ 4;
246 if (store
->Size
== 1) {
247 const GLuint comp
= i
% 4;
248 store
->Swizzle
= MAKE_SWIZZLE4(comp
, comp
, comp
, comp
);
249 if (dbg
) printf("Alloc var sz %d at %d.%c (level %d)\n",
250 store
->Size
, store
->Index
, "xyzw"[comp
], t
->Level
);
253 store
->Swizzle
= SWIZZLE_NOOP
;
254 if (dbg
) printf("Alloc var sz %d at %d.xyzw (level %d)\n",
255 store
->Size
, store
->Index
, t
->Level
);
263 * Allocate temp register(s) for storing an unnamed intermediate value.
266 _slang_alloc_temp(slang_var_table
*vt
, slang_ir_storage
*store
)
268 struct table
*t
= vt
->Top
;
269 const int i
= alloc_reg(vt
, store
->Size
, GL_TRUE
);
273 store
->Index
= i
/ 4;
274 if (store
->Size
== 1) {
275 const GLuint comp
= i
% 4;
276 store
->Swizzle
= MAKE_SWIZZLE4(comp
, comp
, comp
, comp
);
277 if (dbg
) printf("Alloc temp sz %d at %d.%c (level %d)\n",
278 store
->Size
, store
->Index
, "xyzw"[comp
], t
->Level
);
281 store
->Swizzle
= SWIZZLE_NOOP
;
282 if (dbg
) printf("Alloc temp sz %d at %d.xyzw (level %d)\n",
283 store
->Size
, store
->Index
, t
->Level
);
290 _slang_free_temp(slang_var_table
*vt
, slang_ir_storage
*store
)
292 struct table
*t
= vt
->Top
;
294 GLuint r
= store
->Index
;
295 assert(store
->Size
> 0);
297 assert(r
+ store
->Size
<= vt
->MaxRegisters
* 4);
298 if (dbg
) printf("Free temp sz %d at %d (level %d)\n", store
->Size
, r
, t
->Level
);
299 if (store
->Size
== 1) {
300 const GLuint comp
= GET_SWZ(store
->Swizzle
, 0);
301 assert(store
->Swizzle
== MAKE_SWIZZLE4(comp
, comp
, comp
, comp
));
303 assert(t
->ValSize
[r
* 4 + comp
] == 1);
304 assert(t
->Temps
[r
* 4 + comp
] == TEMP
);
305 t
->Temps
[r
* 4 + comp
] = FREE
;
308 /*assert(store->Swizzle == SWIZZLE_NOOP);*/
309 assert(t
->ValSize
[r
*4] == store
->Size
);
310 for (i
= 0; i
< store
->Size
; i
++) {
311 assert(t
->Temps
[r
* 4 + i
] == TEMP
);
312 t
->Temps
[r
* 4 + i
] = FREE
;
319 _slang_is_temp(const slang_var_table
*vt
, const slang_ir_storage
*store
)
321 struct table
*t
= vt
->Top
;
323 assert(store
->Index
>= 0);
324 assert(store
->Index
< vt
->MaxRegisters
);
325 if (store
->Swizzle
== SWIZZLE_NOOP
)
328 comp
= GET_SWZ(store
->Swizzle
, 0);
330 if (t
->Temps
[store
->Index
* 4 + comp
] == TEMP
)