*/\r
\r
#include "imports.h"\r
-#include "slang_utility.h"\r
#include "slang_assemble.h"\r
+#include "slang_compile.h"\r
#include "slang_storage.h"\r
-#include "slang_assemble_typeinfo.h"\r
-#include "slang_assemble_conditional.h"\r
-#include "slang_assemble_assignment.h"\r
-#include "slang_execute.h"\r
\r
/* slang_assembly */\r
\r
/* utility functions */\r
\r
static GLboolean sizeof_variable (slang_assemble_ctx *A, slang_type_specifier *spec,\r
- slang_type_qualifier qual, slang_operation *array_size, GLuint *size)\r
+ slang_type_qualifier qual, GLuint array_len, GLuint *size)\r
{\r
slang_storage_aggregate agg;\r
\r
/* calculate the size of the variable's aggregate */\r
if (!slang_storage_aggregate_construct (&agg))\r
return GL_FALSE;\r
- if (!_slang_aggregate_variable (&agg, spec, array_size, A->space.funcs, A->space.structs,\r
+ if (!_slang_aggregate_variable (&agg, spec, array_len, A->space.funcs, A->space.structs,\r
A->space.vars, A->mach, A->file, A->atoms))\r
{\r
slang_storage_aggregate_destruct (&agg);\r
var->address = *size;\r
if (var->type.qualifier == slang_qual_out || var->type.qualifier == slang_qual_inout)\r
var->address += 4;\r
- return sizeof_variable (A, &var->type.specifier, var->type.qualifier, var->array_size, size);\r
+ return sizeof_variable (A, &var->type.specifier, var->type.qualifier, var->array_len, size);\r
}\r
\r
static GLboolean sizeof_variables (slang_assemble_ctx *A, slang_variable_scope *vars, GLuint start,\r
\r
if (!slang_assembly_typeinfo_construct (&ti))\r
return NULL;\r
- if (!_slang_typeof_operation (¶ms[j], space, &ti, atoms))\r
+ if (!_slang_typeof_operation_ (¶ms[j], space, &ti, atoms))\r
{\r
slang_assembly_typeinfo_destruct (&ti);\r
return NULL;\r
/* calculate return value size */\r
param_size = 0;\r
if (fun->header.type.specifier.type != slang_spec_void)\r
- if (!sizeof_variable (A, &fun->header.type.specifier, slang_qual_none, NULL, ¶m_size))\r
+ if (!sizeof_variable (A, &fun->header.type.specifier, slang_qual_none, 0, ¶m_size))\r
return GL_FALSE;\r
A->local.ret_size = param_size;\r
\r
\r
/* execute the function body */\r
A->file->code[skip].param[0] = A->file->count;\r
- if (!_slang_assemble_operation_ (A, fun->body, /*slang_ref_freelance*/slang_ref_forbid))\r
+ if (!_slang_assemble_operation (A, fun->body, /*slang_ref_freelance*/slang_ref_forbid))\r
return GL_FALSE;\r
\r
/* this is the end of the function - restore the old function frame */\r
return GL_TRUE;\r
}\r
\r
-GLboolean _slang_cleanup_stack_ (slang_assemble_ctx *A, slang_operation *op)\r
+GLboolean _slang_cleanup_stack (slang_assemble_ctx *A, slang_operation *op)\r
{\r
slang_assembly_typeinfo ti;\r
GLuint size = 0;\r
/* get type info of the operation and calculate its size */\r
if (!slang_assembly_typeinfo_construct (&ti))\r
return GL_FALSE;\r
- if (!_slang_typeof_operation (op, &A->space, &ti, A->atoms))\r
+ if (!_slang_typeof_operation (A, op, &ti))\r
{\r
slang_assembly_typeinfo_destruct (&ti);\r
return GL_FALSE;\r
}\r
- if (ti.spec.type != slang_spec_void)\r
- if (A->ref == slang_ref_force)\r
+ if (ti.spec.type != slang_spec_void) {\r
+ if (A->ref == slang_ref_force) {\r
size = 4;\r
- else if (!sizeof_variable (A, &ti.spec, slang_qual_none, NULL, &size))\r
+ }\r
+ else if (!sizeof_variable (A, &ti.spec, slang_qual_none, 0, &size))\r
{\r
slang_assembly_typeinfo_destruct (&ti);\r
return GL_FALSE;\r
}\r
+ }\r
slang_assembly_typeinfo_destruct (&ti);\r
\r
/* if nonzero, free it from the stack */\r
/* get type information of the given operation */\r
if (!slang_assembly_typeinfo_construct (&ti))\r
return GL_FALSE;\r
- if (!_slang_typeof_operation (op, &A->space, &ti, A->atoms))\r
+ if (!_slang_typeof_operation (A, op, &ti))\r
goto end1;\r
\r
/* construct aggregate from the type info */\r
if (!slang_storage_aggregate_construct (&agg))\r
goto end1;\r
- if (!_slang_aggregate_variable (&agg, &ti.spec, ti.array_size, A->space.funcs, A->space.structs,\r
+ if (!_slang_aggregate_variable (&agg, &ti.spec, ti.array_len, A->space.funcs, A->space.structs,\r
A->space.vars, A->mach, A->file, A->atoms))\r
goto end;\r
\r
{\r
GLuint ret_size = 0;\r
\r
- if (!sizeof_variable (A, &fun->header.type.specifier, slang_qual_none, NULL, &ret_size))\r
+ if (!sizeof_variable (A, &fun->header.type.specifier, slang_qual_none, 0, &ret_size))\r
return GL_FALSE;\r
if (!PLAB (A->file, slang_asm_local_alloc, ret_size))\r
return GL_FALSE;\r
if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4))\r
return GL_FALSE;\r
/* TODO: optimize the "out" parameter case */\r
- if (!_slang_assemble_operation_ (A, ¶ms[i], slang_ref_force))\r
+ if (!_slang_assemble_operation (A, ¶ms[i], slang_ref_force))\r
return GL_FALSE;\r
p_swz[i] = A->swz;\r
p_ref[i] = A->ref;\r
}\r
else\r
{\r
- if (!_slang_assemble_operation_ (A, ¶ms[i], slang_ref_forbid))\r
+ if (!_slang_assemble_operation (A, ¶ms[i], slang_ref_forbid))\r
return GL_FALSE;\r
p_swz[i] = A->swz;\r
p_ref[i] = A->ref;\r
else\r
{\r
/* pop the value of the parameter */\r
- if (!_slang_cleanup_stack_ (A, ¶ms[j]))\r
+ if (!_slang_cleanup_stack (A, ¶ms[j]))\r
return GL_FALSE;\r
}\r
}\r
{ "float_noise3", slang_asm_float_noise3, slang_asm_float_copy },\r
{ "float_noise4", slang_asm_float_noise4, slang_asm_float_copy },\r
{ "int_to_float", slang_asm_int_to_float, slang_asm_float_copy },\r
+ { "vec4_tex1d", slang_asm_vec4_tex1d, slang_asm_none },\r
+ { "vec4_tex2d", slang_asm_vec4_tex2d, slang_asm_none },\r
+ { "vec4_tex3d", slang_asm_vec4_tex3d, slang_asm_none },\r
+ { "vec4_texcube", slang_asm_vec4_texcube, slang_asm_none },\r
+ { "vec4_shad1d", slang_asm_vec4_shad1d, slang_asm_none },\r
+ { "vec4_shad2d", slang_asm_vec4_shad2d, slang_asm_none },\r
/* mesa-specific extensions */\r
{ "float_print", slang_asm_float_deref, slang_asm_float_print },\r
{ "int_print", slang_asm_int_deref, slang_asm_int_print },\r
/* get type of operation */\r
if (!slang_assembly_typeinfo_construct (&ti))\r
return GL_FALSE;\r
- if (!_slang_typeof_operation (op, &A->space, &ti, A->atoms))\r
+ if (!_slang_typeof_operation (A, op, &ti))\r
goto end1;\r
\r
/* convert it to an aggregate */\r
if (!slang_storage_aggregate_construct (&agg))\r
goto end1;\r
- if (!_slang_aggregate_variable (&agg, &ti.spec, NULL, A->space.funcs, A->space.structs,\r
+ if (!_slang_aggregate_variable (&agg, &ti.spec, 0, A->space.funcs, A->space.structs,\r
A->space.vars, A->mach, A->file, A->atoms))\r
goto end;\r
\r
GLuint asize = 0, esize = 0;\r
\r
/* get type info of the master expression (matrix, vector or an array */\r
- if (!_slang_typeof_operation (&op->children[0], &A->space, tia, A->atoms))\r
+ if (!_slang_typeof_operation (A, &op->children[0], tia))\r
return GL_FALSE;\r
- if (!sizeof_variable (A, &tia->spec, slang_qual_none, tia->array_size, &asize))\r
+ if (!sizeof_variable (A, &tia->spec, slang_qual_none, tia->array_len, &asize))\r
return GL_FALSE;\r
\r
/* get type info of the result (matrix column, vector row or array element) */\r
- if (!_slang_typeof_operation (op, &A->space, tie, A->atoms))\r
+ if (!_slang_typeof_operation (A, op, tie))\r
return GL_FALSE;\r
- if (!sizeof_variable (A, &tie->spec, slang_qual_none, NULL, &esize))\r
+ if (!sizeof_variable (A, &tie->spec, slang_qual_none, 0, &esize))\r
return GL_FALSE;\r
\r
/* assemble the master expression */\r
- if (!_slang_assemble_operation_ (A, &op->children[0], ref))\r
+ if (!_slang_assemble_operation (A, &op->children[0], ref))\r
return GL_FALSE;\r
\r
/* when indexing an l-value swizzle, push the swizzle_tmp */\r
return GL_FALSE;\r
\r
/* assemble the subscript expression */\r
- if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid))\r
+ if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))\r
return GL_FALSE;\r
\r
if (ref == slang_ref_force && tia->is_swizzled)\r
slang_assembly_typeinfo *tib, slang_operation *op, slang_ref_type ref)\r
{\r
/* get type info of the result (field or swizzle) */\r
- if (!_slang_typeof_operation (op, &A->space, tia, A->atoms))\r
+ if (!_slang_typeof_operation (A, op, tia))\r
return GL_FALSE;\r
\r
/* get type info of the master expression being accessed (struct or vector) */\r
- if (!_slang_typeof_operation (&op->children[0], &A->space, tib, A->atoms))\r
+ if (!_slang_typeof_operation (A, &op->children[0], tib))\r
return GL_FALSE;\r
\r
/* if swizzling a vector in-place, the swizzle temporary is needed */\r
return GL_FALSE;\r
\r
/* assemble the master expression */\r
- if (!_slang_assemble_operation_ (A, &op->children[0], ref))\r
+ if (!_slang_assemble_operation (A, &op->children[0], ref))\r
return GL_FALSE;\r
\r
/* assemble the field expression */\r
else\r
{\r
GLuint i, struct_size = 0, field_offset = 0, field_size = 0;\r
+ GLboolean relocate, shrink;\r
\r
+ /* calculate struct size, field offset and field size */\r
for (i = 0; i < tib->spec._struct->fields->num_variables; i++)\r
{\r
slang_variable *field;\r
field = &tib->spec._struct->fields->variables[i];\r
if (!slang_storage_aggregate_construct (&agg))\r
return GL_FALSE;\r
- if (!_slang_aggregate_variable (&agg, &field->type.specifier, field->array_size,\r
+ if (!_slang_aggregate_variable (&agg, &field->type.specifier, field->array_len,\r
A->space.funcs, A->space.structs, A->space.vars, A->mach, A->file, A->atoms))\r
{\r
slang_storage_aggregate_destruct (&agg);\r
field_offset += size;\r
}\r
\r
- if (!PLAB (A->file, slang_asm_addr_push, field_offset))\r
- return GL_FALSE;\r
+ /*\r
+ * OPTIMIZATION: If selecting the last field, no relocation is needed.\r
+ */\r
+ relocate = field_offset != struct_size - field_size;\r
\r
- if (ref == slang_ref_force)\r
+ /*\r
+ * OPTIMIZATION: If field and struct sizes are equal, no partial free is needed.\r
+ */\r
+ shrink = field_size != struct_size;\r
+\r
+ if (relocate)\r
{\r
- if (!PUSH (A->file, slang_asm_addr_add))\r
+ if (!PLAB (A->file, slang_asm_addr_push, field_offset))\r
return GL_FALSE;\r
}\r
+\r
+ if (ref == slang_ref_force)\r
+ {\r
+ if (relocate)\r
+ {\r
+ if (!PUSH (A->file, slang_asm_addr_add))\r
+ return GL_FALSE;\r
+ }\r
+ }\r
else\r
{\r
- GLuint i;\r
+ GLuint free_b = 0;\r
\r
- /* move the selected element to the beginning of the master expression */\r
- for (i = 0; i < field_size; i += 4)\r
- if (!PLAB2 (A->file, slang_asm_float_move, struct_size - field_size + i + 4, i + 4))\r
- return GL_FALSE;\r
- if (!PLAB (A->file, slang_asm_local_free, 4))\r
- return GL_FALSE;\r
+ if (relocate)\r
+ {\r
+ GLuint i;\r
\r
- /* free the rest of the master expression */\r
- if (!PLAB (A->file, slang_asm_local_free, struct_size - field_size))\r
- return GL_FALSE;\r
+ /* move the selected element to the beginning of the master expression */\r
+ for (i = 0; i < field_size; i += 4)\r
+ if (!PLAB2 (A->file, slang_asm_float_move, struct_size - field_size + i + 4, i + 4))\r
+ return GL_FALSE;\r
+ free_b += 4;\r
+ }\r
+\r
+ if (shrink)\r
+ {\r
+ /* free the rest of the master expression */\r
+ free_b += struct_size - field_size;\r
+ }\r
+\r
+ if (free_b)\r
+ {\r
+ if (!PLAB (A->file, slang_asm_local_free, free_b))\r
+ return GL_FALSE;\r
+ }\r
}\r
}\r
\r
return GL_TRUE;\r
}\r
\r
-GLboolean _slang_assemble_operation_ (slang_assemble_ctx *A, slang_operation *op, slang_ref_type ref)\r
+GLboolean _slang_assemble_operation (slang_assemble_ctx *A, slang_operation *op, slang_ref_type ref)\r
{\r
- GLuint assem;\r
-\r
- assem = A->file->count;\r
- if (!push_new (A->file))\r
- return GL_FALSE;\r
-\r
/* set default results */\r
A->ref = /*(ref == slang_ref_freelance) ? slang_ref_force : */ref;\r
A->swz.num_components = 0;\r
\r
for (i = 0; i < op->num_children; i++)\r
{\r
- if (!_slang_assemble_operation_ (A, &op->children[i], slang_ref_forbid/*slang_ref_freelance*/))\r
+ if (!_slang_assemble_operation (A, &op->children[i], slang_ref_forbid/*slang_ref_freelance*/))\r
return GL_FALSE;\r
- if (!_slang_cleanup_stack_ (A, &op->children[i]))\r
+ if (!_slang_cleanup_stack (A, &op->children[i]))\r
return GL_FALSE;\r
}\r
}\r
{\r
GLuint i;\r
\r
- if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_force))\r
+ if (!_slang_assemble_operation (A, &op->children[0], slang_ref_force))\r
return GL_FALSE;\r
for (i = 1; i < op->num_children; i++)\r
- if (!_slang_assemble_operation_ (A, &op->children[i], slang_ref_forbid))\r
+ if (!_slang_assemble_operation (A, &op->children[i], slang_ref_forbid))\r
return GL_FALSE;\r
if (!call_asm_instruction (A, op->a_id))\r
return GL_FALSE;\r
}\r
break;\r
case slang_oper_break:\r
- A->file->code[assem].type = slang_asm_jump;\r
- A->file->code[assem].param[0] = A->flow.loop_end;\r
+ if (!PLAB (A->file, slang_asm_jump, A->flow.loop_end))\r
+ return GL_FALSE;\r
break;\r
case slang_oper_continue:\r
- A->file->code[assem].type = slang_asm_jump;\r
- A->file->code[assem].param[0] = A->flow.loop_start;\r
+ if (!PLAB (A->file, slang_asm_jump, A->flow.loop_start))\r
+ return GL_FALSE;\r
break;\r
case slang_oper_discard:\r
- A->file->code[assem].type = slang_asm_discard;\r
+ if (!PUSH (A->file, slang_asm_discard))\r
+ return GL_FALSE;\r
if (!PUSH (A->file, slang_asm_exit))\r
return GL_FALSE;\r
break;\r
/* push the result's address */\r
if (!PLAB2 (A->file, slang_asm_local_addr, 0, A->local.ret_size))\r
return GL_FALSE;\r
- if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid))\r
+ if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))\r
return GL_FALSE;\r
\r
A->swz.num_components = 0;\r
case slang_oper_expression:\r
if (ref == slang_ref_force)\r
return GL_FALSE;\r
- if (!_slang_assemble_operation_ (A, &op->children[0], ref))\r
+ if (!_slang_assemble_operation (A, &op->children[0], ref))\r
return GL_FALSE;\r
break;\r
case slang_oper_if:\r
case slang_oper_literal_bool:\r
if (ref == slang_ref_force)\r
return GL_FALSE;\r
- A->file->code[assem].type = slang_asm_bool_push;\r
- A->file->code[assem].literal = op->literal;\r
+ if (!PLIT (A->file, slang_asm_bool_push, op->literal))\r
+ return GL_FALSE;\r
A->ref = slang_ref_forbid;\r
break;\r
case slang_oper_literal_int:\r
if (ref == slang_ref_force)\r
return GL_FALSE;\r
- A->file->code[assem].type = slang_asm_int_push;\r
- A->file->code[assem].literal = op->literal;\r
+ if (!PLIT (A->file, slang_asm_int_push, op->literal))\r
+ return GL_FALSE;\r
A->ref = slang_ref_forbid;\r
break;\r
case slang_oper_literal_float:\r
if (ref == slang_ref_force)\r
return GL_FALSE;\r
- A->file->code[assem].type = slang_asm_float_push;\r
- A->file->code[assem].literal = op->literal;\r
+ if (!PLIT (A->file, slang_asm_float_push, op->literal))\r
+ return GL_FALSE;\r
A->ref = slang_ref_forbid;\r
break;\r
case slang_oper_identifier:\r
if (var == NULL)\r
return GL_FALSE;\r
size = 0;\r
- if (!sizeof_variable (A, &var->type.specifier, slang_qual_none, var->array_size, &size))\r
+ if (!sizeof_variable (A, &var->type.specifier, slang_qual_none, var->array_len, &size))\r
return GL_FALSE;\r
\r
/* prepare stack for dereferencing */\r
/* push the variable's address */\r
if (var->global)\r
{\r
- if (!PLAB (A->file, slang_asm_addr_push, var->address))\r
+ if (!PLAB (A->file, slang_asm_global_addr, var->address))\r
return GL_FALSE;\r
}\r
else\r
case slang_oper_sequence:\r
if (ref == slang_ref_force)\r
return GL_FALSE;\r
- if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/))\r
+ if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/))\r
return GL_FALSE;\r
- if (!_slang_cleanup_stack_ (A, &op->children[0]))\r
+ if (!_slang_cleanup_stack (A, &op->children[0]))\r
return GL_FALSE;\r
- if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid))\r
+ if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))\r
return GL_FALSE;\r
A->ref = slang_ref_forbid;\r
break;\r
case slang_oper_addassign:\r
if (!_slang_assemble_assign (A, op, "+=", ref))\r
return GL_FALSE;\r
+ A->ref = ref;\r
break;\r
case slang_oper_subassign:\r
if (!_slang_assemble_assign (A, op, "-=", ref))\r
return GL_FALSE;\r
+ A->ref = ref;\r
break;\r
case slang_oper_mulassign:\r
if (!_slang_assemble_assign (A, op, "*=", ref))\r
return GL_FALSE;\r
+ A->ref = ref;\r
break;\r
/*case slang_oper_modassign:*/\r
/*case slang_oper_lshassign:*/\r
case slang_oper_divassign:\r
if (!_slang_assemble_assign (A, op, "/=", ref))\r
return GL_FALSE;\r
+ A->ref = ref;\r
break;\r
case slang_oper_select:\r
if (!_slang_assemble_select (A, op))\r
A->ref = slang_ref_forbid;\r
break;\r
case slang_oper_equal:\r
- if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid))\r
+ if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))\r
return GL_FALSE;\r
- if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid))\r
+ if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))\r
return GL_FALSE;\r
if (!equality (A, op->children, GL_TRUE))\r
return GL_FALSE;\r
A->ref = slang_ref_forbid;\r
break;\r
case slang_oper_notequal:\r
- if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid))\r
+ if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))\r
return GL_FALSE;\r
- if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid))\r
+ if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))\r
return GL_FALSE;\r
if (!equality (A, op->children, GL_FALSE))\r
return GL_FALSE;\r
case slang_oper_preincrement:\r
if (!_slang_assemble_assign (A, op, "++", ref))\r
return GL_FALSE;\r
+ A->ref = ref;\r
break;\r
case slang_oper_predecrement:\r
if (!_slang_assemble_assign (A, op, "--", ref))\r
return GL_FALSE;\r
+ A->ref = ref;\r
break;\r
case slang_oper_plus:\r
if (!_slang_dereference (A, op))\r