From 8d95e66cf78921cd067c4bcf6a1053a7ec3a2ed4 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Mon, 24 Nov 2008 17:18:56 -0700 Subject: [PATCH] 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. --- src/mesa/shader/slang/library/slang_shader.syn | 20 +++++++++++ src/mesa/shader/slang/library/slang_shader_syn.h | 7 ++++ src/mesa/shader/slang/slang_codegen.c | 42 ++++++++++++++++++++++++ src/mesa/shader/slang/slang_compile.c | 30 +++++++++++++++++ src/mesa/shader/slang/slang_compile_operation.h | 2 ++ src/mesa/shader/slang/slang_print.c | 5 +++ src/mesa/shader/slang/slang_typeinfo.c | 6 ++++ 7 files changed, 112 insertions(+) diff --git a/src/mesa/shader/slang/library/slang_shader.syn b/src/mesa/shader/slang/library/slang_shader.syn index a02a3ac..760dfbc 100644 --- a/src/mesa/shader/slang/library/slang_shader.syn +++ b/src/mesa/shader/slang/library/slang_shader.syn @@ -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_or_method; + +/* + * ::= + * | "." + */ +function_call_or_method + regular_function_call .or method_call; + +/* + * ::= "." + */ +method_call + identifier .emit OP_METHOD .and dot .and function_call_generic .and .true .emit OP_END; + +/* + * ::= + */ +regular_function_call function_call_generic .emit OP_CALL .and .true .emit OP_END; /* diff --git a/src/mesa/shader/slang/library/slang_shader_syn.h b/src/mesa/shader/slang/library/slang_shader_syn.h index f695717..42ff92b 100644 --- a/src/mesa/shader/slang/library/slang_shader_syn.h +++ b/src/mesa/shader/slang/library/slang_shader_syn.h @@ -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" diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index f2cb75f..8d2655e 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -2042,6 +2042,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) { @@ -3534,6 +3574,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: diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c index eadc37f..efae4e9 100644 --- a/src/mesa/shader/slang/slang_compile.c +++ b/src/mesa/shader/slang/slang_compile.c @@ -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); diff --git a/src/mesa/shader/slang/slang_compile_operation.h b/src/mesa/shader/slang/slang_compile_operation.h index 4f92aa9..ec99338 100644 --- a/src/mesa/shader/slang/slang_compile_operation.h +++ b/src/mesa/shader/slang/slang_compile_operation.h @@ -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 */ diff --git a/src/mesa/shader/slang/slang_print.c b/src/mesa/shader/slang/slang_print.c index b88cefc..1194d0b 100644 --- a/src/mesa/shader/slang/slang_print.c +++ b/src/mesa/shader/slang/slang_print.c @@ -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); diff --git a/src/mesa/shader/slang/slang_typeinfo.c b/src/mesa/shader/slang/slang_typeinfo.c index b2f0f14..b1afd96 100644 --- a/src/mesa/shader/slang/slang_typeinfo.c +++ b/src/mesa/shader/slang/slang_typeinfo.c @@ -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; -- 2.7.4