void slang_variable_destruct (slang_variable *var)
{
	slang_fully_specified_type_destruct (&var->type);
	if (var->initializer != NULL)
	{
		slang_operation_destruct (var->initializer);
		slang_alloc_free (var->initializer);
	}
}
void slang_function_destruct (slang_function *func)
{
	slang_variable_destruct (&func->header);
	slang_variable_scope_destruct (func->parameters);
	slang_alloc_free (func->parameters);
	if (func->body != NULL)
	{
		slang_operation_destruct (func->body);
		slang_alloc_free (func->body);
	}
	slang_fixup_table_free (&func->fixups);
}
Ejemplo n.º 3
0
void
slang_variable_destruct(slang_variable * var)
{
   slang_fully_specified_type_destruct(&var->type);
   if (var->initializer != NULL) {
      slang_operation_destruct(var->initializer);
      _slang_free(var->initializer);
   }
#if 0
   if (var->aux) {
      free(var->aux);
   }
#endif
}
Ejemplo n.º 4
0
static GLboolean assemble_function_call_name_dummyint (slang_assemble_ctx *A, const char *name,
	slang_operation *params)
{
	slang_operation p[2];
	GLboolean result;

	p[0] = params[0];
	if (!slang_operation_construct (&p[1]))
		return GL_FALSE;
	p[1].type = slang_oper_literal_int;
	result = _slang_assemble_function_call_name (A, name, p, 2, GL_FALSE);
	slang_operation_destruct (&p[1]);
	return result;
}
Ejemplo n.º 5
0
/**
 * Recursively traverse an AST tree, applying simplifications wherever
 * possible.
 * At the least, we do constant folding.  We need to do that much so that
 * compile-time expressions can be evaluated for things like array
 * declarations.  I.e.:  float foo[3 + 5];
 */
void
_slang_simplify(slang_operation *oper,
                const slang_name_space * space,
                slang_atom_pool * atoms)
{
   GLboolean isFloat[4];
   GLboolean isBool[4];
   GLuint i, n;

   if (oper->type == SLANG_OPER_IDENTIFIER) {
      /* see if it's a named constant */
      GLint value = _slang_lookup_constant((char *) oper->a_id);
      if (value >= 0) {
         oper->literal[0] =
         oper->literal[1] =
         oper->literal[2] =
         oper->literal[3] = value;
         oper->type = SLANG_OPER_LITERAL_INT;
         return;
      }
   }

   /* first, simplify children */
   for (i = 0; i < oper->num_children; i++) {
      _slang_simplify(&oper->children[i], space, atoms);
   }

   /* examine children */
   n = MIN2(oper->num_children, 4);
   for (i = 0; i < n; i++) {
      isFloat[i] = (oper->children[i].type == SLANG_OPER_LITERAL_FLOAT ||
                   oper->children[i].type == SLANG_OPER_LITERAL_INT);
      isBool[i] = (oper->children[i].type == SLANG_OPER_LITERAL_BOOL);
   }
                              
   if (oper->num_children == 2 && isFloat[0] && isFloat[1]) {
      /* probably simple arithmetic */
      switch (oper->type) {
      case SLANG_OPER_ADD:
         for (i = 0; i < 4; i++) {
            oper->literal[i]
               = oper->children[0].literal[i] + oper->children[1].literal[i];
         }
         oper->literal_size = oper->children[0].literal_size;
         slang_operation_destruct(oper);
         oper->type = SLANG_OPER_LITERAL_FLOAT;
         return;
      case SLANG_OPER_SUBTRACT:
         for (i = 0; i < 4; i++) {
            oper->literal[i]
               = oper->children[0].literal[i] - oper->children[1].literal[i];
         }
         oper->literal_size = oper->children[0].literal_size;
         slang_operation_destruct(oper);
         oper->type = SLANG_OPER_LITERAL_FLOAT;
         return;
      case SLANG_OPER_MULTIPLY:
         for (i = 0; i < 4; i++) {
            oper->literal[i]
               = oper->children[0].literal[i] * oper->children[1].literal[i];
         }
         oper->literal_size = oper->children[0].literal_size;
         slang_operation_destruct(oper);
         oper->type = SLANG_OPER_LITERAL_FLOAT;
         return;
      case SLANG_OPER_DIVIDE:
         for (i = 0; i < 4; i++) {
            oper->literal[i]
               = oper->children[0].literal[i] / oper->children[1].literal[i];
         }
         oper->literal_size = oper->children[0].literal_size;
         slang_operation_destruct(oper);
         oper->type = SLANG_OPER_LITERAL_FLOAT;
         return;
      default:
         ; /* nothing */
      }
   }

   if (oper->num_children == 1 && isFloat[0]) {
      switch (oper->type) {
      case SLANG_OPER_MINUS:
         for (i = 0; i < 4; i++) {
            oper->literal[i] = -oper->children[0].literal[i];
         }
         oper->literal_size = oper->children[0].literal_size;
         slang_operation_destruct(oper);
         oper->type = SLANG_OPER_LITERAL_FLOAT;
         return;
      case SLANG_OPER_PLUS:
         COPY_4V(oper->literal, oper->children[0].literal);
         oper->literal_size = oper->children[0].literal_size;
         slang_operation_destruct(oper);
         oper->type = SLANG_OPER_LITERAL_FLOAT;
         return;
      default:
         ; /* nothing */
      }
   }

   if (oper->num_children == 2 && isBool[0] && isBool[1]) {
      /* simple boolean expression */
      switch (oper->type) {
      case SLANG_OPER_LOGICALAND:
         for (i = 0; i < 4; i++) {
            const GLint a = oper->children[0].literal[i] ? 1 : 0;
            const GLint b = oper->children[1].literal[i] ? 1 : 0;
            oper->literal[i] = (GLfloat) (a && b);
         }
         oper->literal_size = oper->children[0].literal_size;
         slang_operation_destruct(oper);
         oper->type = SLANG_OPER_LITERAL_BOOL;
         return;
      case SLANG_OPER_LOGICALOR:
         for (i = 0; i < 4; i++) {
            const GLint a = oper->children[0].literal[i] ? 1 : 0;
            const GLint b = oper->children[1].literal[i] ? 1 : 0;
            oper->literal[i] = (GLfloat) (a || b);
         }
         oper->literal_size = oper->children[0].literal_size;
         slang_operation_destruct(oper);
         oper->type = SLANG_OPER_LITERAL_BOOL;
         return;
      case SLANG_OPER_LOGICALXOR:
         for (i = 0; i < 4; i++) {
            const GLint a = oper->children[0].literal[i] ? 1 : 0;
            const GLint b = oper->children[1].literal[i] ? 1 : 0;
            oper->literal[i] = (GLfloat) (a ^ b);
         }
         oper->literal_size = oper->children[0].literal_size;
         slang_operation_destruct(oper);
         oper->type = SLANG_OPER_LITERAL_BOOL;
         return;
      default:
         ; /* nothing */
      }
   }

   if (oper->num_children == 4
       && isFloat[0] && isFloat[1] && isFloat[2] && isFloat[3]) {
      /* vec4(flt, flt, flt, flt) constructor */
      if (oper->type == SLANG_OPER_CALL) {
         if (strcmp((char *) oper->a_id, "vec4") == 0) {
            oper->literal[0] = oper->children[0].literal[0];
            oper->literal[1] = oper->children[1].literal[0];
            oper->literal[2] = oper->children[2].literal[0];
            oper->literal[3] = oper->children[3].literal[0];
            oper->literal_size = 4;
            slang_operation_destruct(oper);
            oper->type = SLANG_OPER_LITERAL_FLOAT;
            return;
         }
      }
   }

   if (oper->num_children == 3 && isFloat[0] && isFloat[1] && isFloat[2]) {
      /* vec3(flt, flt, flt) constructor */
      if (oper->type == SLANG_OPER_CALL) {
         if (strcmp((char *) oper->a_id, "vec3") == 0) {
            oper->literal[0] = oper->children[0].literal[0];
            oper->literal[1] = oper->children[1].literal[0];
            oper->literal[2] = oper->children[2].literal[0];
            oper->literal[3] = oper->literal[2];
            oper->literal_size = 3;
            slang_operation_destruct(oper);
            oper->type = SLANG_OPER_LITERAL_FLOAT;
            return;
         }
      }
   }

   if (oper->num_children == 2 && isFloat[0] && isFloat[1]) {
      /* vec2(flt, flt) constructor */
      if (oper->type == SLANG_OPER_CALL) {
         if (strcmp((char *) oper->a_id, "vec2") == 0) {
            oper->literal[0] = oper->children[0].literal[0];
            oper->literal[1] = oper->children[1].literal[0];
            oper->literal[2] = oper->literal[1];
            oper->literal[3] = oper->literal[1];
            oper->literal_size = 2;
            slang_operation_destruct(oper); /* XXX oper->locals goes NULL! */
            oper->type = SLANG_OPER_LITERAL_FLOAT;
            assert(oper->num_children == 0);
            return;
         }
      }
   }

   if (oper->num_children == 1 && isFloat[0]) {
      /* vec2/3/4(flt, flt) constructor */
      if (oper->type == SLANG_OPER_CALL) {
         const char *func = (const char *) oper->a_id;
         if (strncmp(func, "vec", 3) == 0 && func[3] >= '2' && func[3] <= '4') {
            oper->literal[0] =
            oper->literal[1] =
            oper->literal[2] =
            oper->literal[3] = oper->children[0].literal[0];
            oper->literal_size = func[3] - '0';
            assert(oper->literal_size >= 2);
            assert(oper->literal_size <= 4);
            slang_operation_destruct(oper); /* XXX oper->locals goes NULL! */
            oper->type = SLANG_OPER_LITERAL_FLOAT;
            assert(oper->num_children == 0);
            return;
         }
      }
   }
}
Ejemplo n.º 6
0
GLboolean _slang_assemble_operation (slang_assemble_ctx *A, slang_operation *op, slang_ref_type ref)
{
	/* set default results */
	A->ref = /*(ref == slang_ref_freelance) ? slang_ref_force : */ref;
	A->swz.num_components = 0;

	switch (op->type)
	{
	case slang_oper_block_no_new_scope:
	case slang_oper_block_new_scope:
		{
			GLuint i;

			for (i = 0; i < op->num_children; i++)
			{
				if (!_slang_assemble_operation (A, &op->children[i], slang_ref_forbid/*slang_ref_freelance*/))
					return GL_FALSE;
				if (!_slang_cleanup_stack (A, &op->children[i]))
					return GL_FALSE;
			}
		}
		break;
	case slang_oper_variable_decl:
		{
			GLuint i;
			slang_operation assign;
			GLboolean result;

			/* Construct assignment expression placeholder. */
			if (!slang_operation_construct (&assign))
				return GL_FALSE;
			assign.type = slang_oper_assign;
			assign.children = (slang_operation *) slang_alloc_malloc (2 * sizeof (slang_operation));
			if (assign.children == NULL)
			{
				slang_operation_destruct (&assign);
				return GL_FALSE;
			}
			for (assign.num_children = 0; assign.num_children < 2; assign.num_children++)
				if (!slang_operation_construct (&assign.children[assign.num_children]))
				{
					slang_operation_destruct (&assign);
					return GL_FALSE;
				}

			result = GL_TRUE;
			for (i = 0; i < op->num_children; i++)
			{
				slang_variable *var;

				var = _slang_locate_variable (op->children[i].locals, op->children[i].a_id, GL_TRUE);
				if (var == NULL)
				{
					result = GL_FALSE;
					break;
				}
				if (var->initializer == NULL)
					continue;

				if (!slang_operation_copy (&assign.children[0], &op->children[i]) ||
					!slang_operation_copy (&assign.children[1], var->initializer) ||
					!_slang_assemble_assign (A, &assign, "=", slang_ref_forbid) ||
					!_slang_cleanup_stack (A, &assign))
				{
					result = GL_FALSE;
					break;
				}
			}
			slang_operation_destruct (&assign);
			if (!result)
				return GL_FALSE;
		}
		break;
	case slang_oper_asm:
		{
			GLuint i;

			if (!_slang_assemble_operation (A, &op->children[0], slang_ref_force))
				return GL_FALSE;
			for (i = 1; i < op->num_children; i++)
				if (!_slang_assemble_operation (A, &op->children[i], slang_ref_forbid))
					return GL_FALSE;
			if (!call_asm_instruction (A, op->a_id))
				return GL_FALSE;
		}
		break;
	case slang_oper_break:
		if (!PLAB (A->file, slang_asm_jump, A->flow.loop_end))
			return GL_FALSE;
		break;
	case slang_oper_continue:
		if (!PLAB (A->file, slang_asm_jump, A->flow.loop_start))
			return GL_FALSE;
		break;
	case slang_oper_discard:
		if (!PUSH (A->file, slang_asm_discard))
			return GL_FALSE;
		if (!PUSH (A->file, slang_asm_exit))
			return GL_FALSE;
		break;
	case slang_oper_return:
		if (A->local.ret_size != 0)
		{
			/* push the result's address */
			if (!PLAB2 (A->file, slang_asm_local_addr, 0, A->local.ret_size))
				return GL_FALSE;
			if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
				return GL_FALSE;

			A->swz.num_components = 0;
			/* assign the operation to the function result (it was reserved on the stack) */
			if (!_slang_assemble_assignment (A, op->children))
				return GL_FALSE;

			if (!PLAB (A->file, slang_asm_local_free, 4))
				return GL_FALSE;
		}
		if (!PLAB (A->file, slang_asm_jump, A->flow.function_end))
			return GL_FALSE;
		break;
	case slang_oper_expression:
		if (ref == slang_ref_force)
			return GL_FALSE;
		if (!_slang_assemble_operation (A, &op->children[0], ref))
			return GL_FALSE;
		break;
	case slang_oper_if:
		if (!_slang_assemble_if (A, op))
			return GL_FALSE;
		break;
	case slang_oper_while:
		if (!_slang_assemble_while (A, op))
			return GL_FALSE;
		break;
	case slang_oper_do:
		if (!_slang_assemble_do (A, op))
			return GL_FALSE;
		break;
	case slang_oper_for:
		if (!_slang_assemble_for (A, op))
			return GL_FALSE;
		break;
	case slang_oper_void:
		break;
	case slang_oper_literal_bool:
		if (ref == slang_ref_force)
			return GL_FALSE;
		if (!PLIT (A->file, slang_asm_bool_push, op->literal))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	case slang_oper_literal_int:
		if (ref == slang_ref_force)
			return GL_FALSE;
		if (!PLIT (A->file, slang_asm_int_push, op->literal))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	case slang_oper_literal_float:
		if (ref == slang_ref_force)
			return GL_FALSE;
		if (!PLIT (A->file, slang_asm_float_push, op->literal))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	case slang_oper_identifier:
		{
			slang_variable *var;
			GLuint size;

			/* find the variable and calculate its size */
			var = _slang_locate_variable (op->locals, op->a_id, GL_TRUE);
			if (var == NULL)
				return GL_FALSE;
			size = 0;
			if (!sizeof_variable (A, &var->type.specifier, slang_qual_none, var->array_len, &size))
				return GL_FALSE;

			/* prepare stack for dereferencing */
			if (ref == slang_ref_forbid)
				if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4))
					return GL_FALSE;

			/* push the variable's address */
			if (var->global)
			{
				if (!PLAB (A->file, slang_asm_global_addr, var->address))
					return GL_FALSE;
			}
			else
			{
				if (!PLAB2 (A->file, slang_asm_local_addr, var->address, size))
					return GL_FALSE;
			}

			/* perform the dereference */
			if (ref == slang_ref_forbid)
			{
				if (!PUSH (A->file, slang_asm_addr_copy))
					return GL_FALSE;
				if (!PLAB (A->file, slang_asm_local_free, 4))
					return GL_FALSE;
				if (!_slang_dereference (A, op))
					return GL_FALSE;
			}
		}
		break;
	case slang_oper_sequence:
		if (ref == slang_ref_force)
			return GL_FALSE;
		if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/))
			return GL_FALSE;
		if (!_slang_cleanup_stack (A, &op->children[0]))
			return GL_FALSE;
		if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	case slang_oper_assign:
		if (!_slang_assemble_assign (A, op, "=", ref))
			return GL_FALSE;
		break;
	case slang_oper_addassign:
		if (!_slang_assemble_assign (A, op, "+=", ref))
			return GL_FALSE;
		A->ref = ref;
		break;
	case slang_oper_subassign:
		if (!_slang_assemble_assign (A, op, "-=", ref))
			return GL_FALSE;
		A->ref = ref;
		break;
	case slang_oper_mulassign:
		if (!_slang_assemble_assign (A, op, "*=", ref))
			return GL_FALSE;
		A->ref = ref;
		break;
	/*case slang_oper_modassign:*/
	/*case slang_oper_lshassign:*/
	/*case slang_oper_rshassign:*/
	/*case slang_oper_orassign:*/
	/*case slang_oper_xorassign:*/
	/*case slang_oper_andassign:*/
	case slang_oper_divassign:
		if (!_slang_assemble_assign (A, op, "/=", ref))
			return GL_FALSE;
		A->ref = ref;
		break;
	case slang_oper_select:
		if (!_slang_assemble_select (A, op))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	case slang_oper_logicalor:
		if (!_slang_assemble_logicalor (A, op))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	case slang_oper_logicaland:
		if (!_slang_assemble_logicaland (A, op))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	case slang_oper_logicalxor:
		if (!_slang_assemble_function_call_name (A, "^^", op->children, 2, GL_FALSE))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	/*case slang_oper_bitor:*/
	/*case slang_oper_bitxor:*/
	/*case slang_oper_bitand:*/
	case slang_oper_less:
		if (!_slang_assemble_function_call_name (A, "<", op->children, 2, GL_FALSE))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	case slang_oper_greater:
		if (!_slang_assemble_function_call_name (A, ">", op->children, 2, GL_FALSE))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	case slang_oper_lessequal:
		if (!_slang_assemble_function_call_name (A, "<=", op->children, 2, GL_FALSE))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	case slang_oper_greaterequal:
		if (!_slang_assemble_function_call_name (A, ">=", op->children, 2, GL_FALSE))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	/*case slang_oper_lshift:*/
	/*case slang_oper_rshift:*/
	case slang_oper_add:
		if (!_slang_assemble_function_call_name (A, "+", op->children, 2, GL_FALSE))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	case slang_oper_subtract:
		if (!_slang_assemble_function_call_name (A, "-", op->children, 2, GL_FALSE))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	case slang_oper_multiply:
		if (!_slang_assemble_function_call_name (A, "*", op->children, 2, GL_FALSE))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	/*case slang_oper_modulus:*/
	case slang_oper_divide:
		if (!_slang_assemble_function_call_name (A, "/", op->children, 2, GL_FALSE))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	case slang_oper_equal:
		if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
			return GL_FALSE;
		if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
			return GL_FALSE;
		if (!equality (A, op->children, GL_TRUE))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	case slang_oper_notequal:
		if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
			return GL_FALSE;
		if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
			return GL_FALSE;
		if (!equality (A, op->children, GL_FALSE))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	case slang_oper_preincrement:
		if (!_slang_assemble_assign (A, op, "++", ref))
			return GL_FALSE;
		A->ref = ref;
		break;
	case slang_oper_predecrement:
		if (!_slang_assemble_assign (A, op, "--", ref))
			return GL_FALSE;
		A->ref = ref;
		break;
	case slang_oper_plus:
		if (!_slang_dereference (A, op))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	case slang_oper_minus:
		if (!_slang_assemble_function_call_name (A, "-", op->children, 1, GL_FALSE))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	/*case slang_oper_complement:*/
	case slang_oper_not:
		if (!_slang_assemble_function_call_name (A, "!", op->children, 1, GL_FALSE))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	case slang_oper_subscript:
		{
			slang_assembly_typeinfo ti_arr, ti_elem;

			if (!slang_assembly_typeinfo_construct (&ti_arr))
				return GL_FALSE;
			if (!slang_assembly_typeinfo_construct (&ti_elem))
			{
				slang_assembly_typeinfo_destruct (&ti_arr);
				return GL_FALSE;
			}
			if (!handle_subscript (A, &ti_elem, &ti_arr, op, ref))
			{
				slang_assembly_typeinfo_destruct (&ti_arr);
				slang_assembly_typeinfo_destruct (&ti_elem);
				return GL_FALSE;
			}
			slang_assembly_typeinfo_destruct (&ti_arr);
			slang_assembly_typeinfo_destruct (&ti_elem);
		}
		break;
	case slang_oper_call:
		{
			slang_function *fun;

			fun = _slang_locate_function (A->space.funcs, op->a_id, op->children, op->num_children,
				&A->space, A->atoms);
			if (fun == NULL)
			{
				if (!_slang_assemble_constructor (A, op))
					return GL_FALSE;
			}
			else
			{
				if (!_slang_assemble_function_call (A, fun, op->children, op->num_children, GL_FALSE))
					return GL_FALSE;
			}
			A->ref = slang_ref_forbid;
		}
		break;
	case slang_oper_field:
		{
			slang_assembly_typeinfo ti_after, ti_before;

			if (!slang_assembly_typeinfo_construct (&ti_after))
				return GL_FALSE;
			if (!slang_assembly_typeinfo_construct (&ti_before))
			{
				slang_assembly_typeinfo_destruct (&ti_after);
				return GL_FALSE;
			}
			if (!handle_field (A, &ti_after, &ti_before, op, ref))
			{
				slang_assembly_typeinfo_destruct (&ti_after);
				slang_assembly_typeinfo_destruct (&ti_before);
				return GL_FALSE;
			}
			slang_assembly_typeinfo_destruct (&ti_after);
			slang_assembly_typeinfo_destruct (&ti_before);
		}
		break;
	case slang_oper_postincrement:
		if (!assemble_function_call_name_dummyint (A, "++", op->children))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	case slang_oper_postdecrement:
		if (!assemble_function_call_name_dummyint (A, "--", op->children))
			return GL_FALSE;
		A->ref = slang_ref_forbid;
		break;
	default:
		return GL_FALSE;
	}

	return GL_TRUE;
}