mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-16 13:40:29 +01:00
mesa: added support for GLSL 1.20 array.length() method
This is the only method supported in GLSL 1.20 so we take a few short-cuts.
(cherry picked from commit 8d95e66cf7)
This commit is contained in:
parent
d450ede4c4
commit
06f2139b82
7 changed files with 112 additions and 0 deletions
|
|
@ -251,6 +251,7 @@
|
|||
.emtcode OP_POSTINCREMENT 60
|
||||
.emtcode OP_POSTDECREMENT 61
|
||||
.emtcode OP_PRECISION 62
|
||||
.emtcode OP_METHOD 63
|
||||
|
||||
/* parameter qualifier */
|
||||
.emtcode PARAM_QUALIFIER_IN 0
|
||||
|
|
@ -342,6 +343,25 @@ integer_expression
|
|||
* <function_call> ::= <function_call_generic>
|
||||
*/
|
||||
function_call
|
||||
function_call_or_method;
|
||||
|
||||
/*
|
||||
* <function_call_or_method> ::= <regular_function_call>
|
||||
* | <postfix_expression> "." <function_call_generic>
|
||||
*/
|
||||
function_call_or_method
|
||||
regular_function_call .or method_call;
|
||||
|
||||
/*
|
||||
* <method_call> ::= <identifier> "." <function_call_generic>
|
||||
*/
|
||||
method_call
|
||||
identifier .emit OP_METHOD .and dot .and function_call_generic .and .true .emit OP_END;
|
||||
|
||||
/*
|
||||
* <regular_function_call> ::= <function_call_generic>
|
||||
*/
|
||||
regular_function_call
|
||||
function_call_generic .emit OP_CALL .and .true .emit OP_END;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@
|
|||
".emtcode OP_POSTINCREMENT 60\n"
|
||||
".emtcode OP_POSTDECREMENT 61\n"
|
||||
".emtcode OP_PRECISION 62\n"
|
||||
".emtcode OP_METHOD 63\n"
|
||||
".emtcode PARAM_QUALIFIER_IN 0\n"
|
||||
".emtcode PARAM_QUALIFIER_OUT 1\n"
|
||||
".emtcode PARAM_QUALIFIER_INOUT 2\n"
|
||||
|
|
@ -175,6 +176,12 @@
|
|||
"integer_expression\n"
|
||||
" expression;\n"
|
||||
"function_call\n"
|
||||
" function_call_or_method;\n"
|
||||
"function_call_or_method\n"
|
||||
" regular_function_call .or method_call;\n"
|
||||
"method_call\n"
|
||||
" identifier .emit OP_METHOD .and dot .and function_call_generic .and .true .emit OP_END;\n"
|
||||
"regular_function_call\n"
|
||||
" function_call_generic .emit OP_CALL .and .true .emit OP_END;\n"
|
||||
"function_call_generic\n"
|
||||
" function_call_generic_1 .or function_call_generic_2;\n"
|
||||
|
|
|
|||
|
|
@ -2039,6 +2039,46 @@ _slang_gen_function_call_name(slang_assemble_ctx *A, const char *name,
|
|||
}
|
||||
|
||||
|
||||
static slang_ir_node *
|
||||
_slang_gen_method_call(slang_assemble_ctx *A, slang_operation *oper)
|
||||
{
|
||||
slang_atom *a_length = slang_atom_pool_atom(A->atoms, "length");
|
||||
slang_ir_node *n;
|
||||
slang_variable *var;
|
||||
|
||||
/* NOTE: In GLSL 1.20, there's only one kind of method
|
||||
* call: array.length(). Anything else is an error.
|
||||
*/
|
||||
if (oper->a_id != a_length) {
|
||||
slang_info_log_error(A->log,
|
||||
"Undefined method call '%s'", (char *) oper->a_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* length() takes no arguments */
|
||||
if (oper->num_children > 0) {
|
||||
slang_info_log_error(A->log, "Invalid arguments to length() method");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* lookup the object/variable */
|
||||
var = _slang_locate_variable(oper->locals, oper->a_obj, GL_TRUE);
|
||||
if (!var || var->type.specifier.type != SLANG_SPEC_ARRAY) {
|
||||
slang_info_log_error(A->log,
|
||||
"Undefined object '%s'", (char *) oper->a_obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create a float/literal IR node encoding the array length */
|
||||
n = new_node0(IR_FLOAT);
|
||||
if (n) {
|
||||
n->Value[0] = (float) var->array_len;
|
||||
n->Store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, 1);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
static GLboolean
|
||||
_slang_is_constant_cond(const slang_operation *oper, GLboolean *value)
|
||||
{
|
||||
|
|
@ -3531,6 +3571,8 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
|
|||
case SLANG_OPER_CALL:
|
||||
return _slang_gen_function_call_name(A, (const char *) oper->a_id,
|
||||
oper, NULL);
|
||||
case SLANG_OPER_METHOD:
|
||||
return _slang_gen_method_call(A, oper);
|
||||
case SLANG_OPER_RETURN:
|
||||
return _slang_gen_return(A, oper);
|
||||
case SLANG_OPER_LABEL:
|
||||
|
|
|
|||
|
|
@ -944,6 +944,7 @@ parse_fully_specified_type(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
#define OP_POSTINCREMENT 60
|
||||
#define OP_POSTDECREMENT 61
|
||||
#define OP_PRECISION 62
|
||||
#define OP_METHOD 63
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -1389,6 +1390,35 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
|
|||
if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
|
||||
RETURN0;
|
||||
break;
|
||||
case OP_METHOD:
|
||||
printf("******* begin OP_METHOD\n");
|
||||
op->type = SLANG_OPER_METHOD;
|
||||
op->a_obj = parse_identifier(C);
|
||||
if (op->a_obj == SLANG_ATOM_NULL)
|
||||
RETURN0;
|
||||
|
||||
op->a_id = parse_identifier(C);
|
||||
if (op->a_id == SLANG_ATOM_NULL)
|
||||
RETURN0;
|
||||
|
||||
while (*C->I != OP_END)
|
||||
if (!parse_child_operation(C, O, op, 0))
|
||||
RETURN0;
|
||||
C->I++;
|
||||
#if 0
|
||||
/* don't lookup the method (not yet anyway) */
|
||||
if (!C->parsing_builtin
|
||||
&& !slang_function_scope_find_by_name(O->funs, op->a_id, 1)) {
|
||||
const char *id;
|
||||
|
||||
id = slang_atom_pool_id(C->atoms, op->a_id);
|
||||
if (!is_constructor_name(id, op->a_id, O->structs)) {
|
||||
slang_info_log_error(C->L, "%s: undeclared function name.", id);
|
||||
RETURN0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case OP_CALL:
|
||||
op->type = SLANG_OPER_CALL;
|
||||
op->a_id = parse_identifier(C);
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ typedef enum slang_operation_type_
|
|||
SLANG_OPER_SUBSCRIPT, /* [expr] "[" [expr] "]" */
|
||||
SLANG_OPER_CALL, /* [func name] [param] [param] [...] */
|
||||
SLANG_OPER_NON_INLINED_CALL, /* a real function call */
|
||||
SLANG_OPER_METHOD, /* method call, such as v.length() */
|
||||
SLANG_OPER_FIELD, /* i.e.: ".next" or ".xzy" or ".xxx" etc */
|
||||
SLANG_OPER_POSTINCREMENT, /* [var] "++" */
|
||||
SLANG_OPER_POSTDECREMENT /* [var] "--" */
|
||||
|
|
@ -115,6 +116,7 @@ typedef struct slang_operation_
|
|||
GLfloat literal[4]; /**< Used for float, int and bool values */
|
||||
GLuint literal_size; /**< 1, 2, 3, or 4 */
|
||||
slang_atom a_id; /**< type: asm, identifier, call, field */
|
||||
slang_atom a_obj; /**< object in a method call */
|
||||
slang_variable_scope *locals; /**< local vars for scope */
|
||||
struct slang_function_ *fun; /**< If type == SLANG_OPER_CALL */
|
||||
struct slang_variable_ *var; /**< If type == slang_oper_identier */
|
||||
|
|
|
|||
|
|
@ -653,6 +653,11 @@ slang_print_tree(const slang_operation *op, int indent)
|
|||
printf(")\n");
|
||||
break;
|
||||
|
||||
case SLANG_OPER_METHOD:
|
||||
spaces(indent);
|
||||
printf("METHOD CALL %s.%s\n", (char *) op->a_obj, (char *) op->a_id);
|
||||
break;
|
||||
|
||||
case SLANG_OPER_FIELD:
|
||||
spaces(indent);
|
||||
printf("FIELD %s of\n", (char*) op->a_id);
|
||||
|
|
|
|||
|
|
@ -630,6 +630,12 @@ _slang_typeof_operation_(slang_operation * op,
|
|||
}
|
||||
}
|
||||
break;
|
||||
case SLANG_OPER_METHOD:
|
||||
/* at this time, GLSL 1.20 only has one method: array.length()
|
||||
* which returns an integer.
|
||||
*/
|
||||
ti->spec.type = SLANG_SPEC_INT;
|
||||
break;
|
||||
case SLANG_OPER_FIELD:
|
||||
{
|
||||
slang_typeinfo _ti;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue