diff options
Diffstat (limited to 'src/mesa/shader/slang/slang_compile.c')
-rw-r--r-- | src/mesa/shader/slang/slang_compile.c | 546 |
1 files changed, 379 insertions, 167 deletions
diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c index 294e46235c..457a6b92c1 100644 --- a/src/mesa/shader/slang/slang_compile.c +++ b/src/mesa/shader/slang/slang_compile.c @@ -160,10 +160,24 @@ typedef struct slang_output_ctx_ struct gl_program *program; slang_var_table *vartable; GLuint default_precision[TYPE_SPECIFIER_COUNT]; + GLboolean allow_precision; + GLboolean allow_invariant; + GLboolean allow_centroid; + GLboolean allow_array_types; /* float[] syntax */ } slang_output_ctx; /* _slang_compile() */ + +/* Debugging aid, print file/line where parsing error is detected */ +#define RETURN0 \ + do { \ + if (0) \ + printf("slang error at %s:%d\n", __FILE__, __LINE__); \ + return 0; \ + } while (0) + + static void parse_identifier_str(slang_parse_ctx * C, char **id) { @@ -220,7 +234,7 @@ parse_float(slang_parse_ctx * C, float *number) _mesa_strlen(exponent) + 3) * sizeof(char)); if (whole == NULL) { slang_info_log_memory(C->L); - return 0; + RETURN0; } slang_string_copy(whole, integral); @@ -244,7 +258,7 @@ check_revision(slang_parse_ctx * C) { if (*C->I != REVISION) { slang_info_log_error(C->L, "Internal compiler error."); - return 0; + RETURN0; } C->I++; return 1; @@ -331,8 +345,8 @@ static GLboolean convert_to_array(slang_parse_ctx * C, slang_variable * var, const slang_type_specifier * sp) { - /* sized array - mark it as array, copy the specifier to the array element and - * parse the expression */ + /* sized array - mark it as array, copy the specifier to the array element + * and parse the expression */ var->type.specifier.type = SLANG_SPEC_ARRAY; var->type.specifier._array = (slang_type_specifier *) _slang_alloc(sizeof(slang_type_specifier)); @@ -384,23 +398,23 @@ parse_struct_field(slang_parse_ctx * C, slang_output_ctx * O, o.structs = st->structs; if (!parse_type_specifier(C, &o, sp)) - return 0; + RETURN0; do { slang_atom a_name; slang_variable *var = slang_variable_scope_grow(st->fields); if (!var) { slang_info_log_memory(C->L); - return 0; + RETURN0; } a_name = parse_identifier(C); if (_slang_locate_variable(st->fields, a_name, GL_FALSE)) { slang_info_log_error(C->L, "duplicate field '%s'", (char *) a_name); - return 0; + RETURN0; } if (!parse_struct_field_var(C, &o, var, a_name, sp)) - return 0; + RETURN0; } while (*C->I++ != FIELD_NONE); @@ -416,26 +430,26 @@ parse_struct(slang_parse_ctx * C, slang_output_ctx * O, slang_struct ** st) /* parse struct name (if any) and make sure it is unique in current scope */ a_name = parse_identifier(C); if (a_name == SLANG_ATOM_NULL) - return 0; + RETURN0; name = slang_atom_pool_id(C->atoms, a_name); if (name[0] != '\0' && slang_struct_scope_find(O->structs, a_name, 0) != NULL) { slang_info_log_error(C->L, "%s: duplicate type name.", name); - return 0; + RETURN0; } /* set-up a new struct */ *st = (slang_struct *) _slang_alloc(sizeof(slang_struct)); if (*st == NULL) { slang_info_log_memory(C->L); - return 0; + RETURN0; } if (!slang_struct_construct(*st)) { _slang_free(*st); *st = NULL; slang_info_log_memory(C->L); - return 0; + RETURN0; } (**st).a_name = a_name; (**st).structs->outer_scope = O->structs; @@ -447,7 +461,7 @@ parse_struct(slang_parse_ctx * C, slang_output_ctx * O, slang_struct ** st) slang_type_specifier_ctr(&sp); if (!parse_struct_field(C, O, *st, &sp)) { slang_type_specifier_dtr(&sp); - return 0; + RETURN0; } slang_type_specifier_dtr(&sp); } @@ -465,20 +479,62 @@ parse_struct(slang_parse_ctx * C, slang_output_ctx * O, slang_struct ** st) * sizeof(slang_struct)); if (O->structs->structs == NULL) { slang_info_log_memory(C->L); - return 0; + RETURN0; } s = &O->structs->structs[O->structs->num_structs]; if (!slang_struct_construct(s)) - return 0; + RETURN0; O->structs->num_structs++; if (!slang_struct_copy(s, *st)) - return 0; + RETURN0; } return 1; } +/* invariant qualifer */ +#define TYPE_VARIANT 90 +#define TYPE_INVARIANT 91 + +static int +parse_type_variant(slang_parse_ctx * C, slang_type_variant *variant) +{ + GLuint invariant = *C->I++; + switch (invariant) { + case TYPE_VARIANT: + *variant = SLANG_VARIANT; + return 1; + case TYPE_INVARIANT: + *variant = SLANG_INVARIANT; + return 1; + default: + RETURN0; + } +} + + +/* centroid qualifer */ +#define TYPE_CENTER 95 +#define TYPE_CENTROID 96 + +static int +parse_type_centroid(slang_parse_ctx * C, slang_type_centroid *centroid) +{ + GLuint c = *C->I++; + switch (c) { + case TYPE_CENTER: + *centroid = SLANG_CENTER; + return 1; + case TYPE_CENTROID: + *centroid = SLANG_CENTROID; + return 1; + default: + RETURN0; + } +} + + /* type qualifier */ #define TYPE_QUALIFIER_NONE 0 #define TYPE_QUALIFIER_CONST 1 @@ -491,7 +547,8 @@ parse_struct(slang_parse_ctx * C, slang_output_ctx * O, slang_struct ** st) static int parse_type_qualifier(slang_parse_ctx * C, slang_type_qualifier * qual) { - switch (*C->I++) { + GLuint qualifier = *C->I++; + switch (qualifier) { case TYPE_QUALIFIER_NONE: *qual = SLANG_QUAL_NONE; break; @@ -514,7 +571,7 @@ parse_type_qualifier(slang_parse_ctx * C, slang_type_qualifier * qual) *qual = SLANG_QUAL_FIXEDINPUT; break; default: - return 0; + RETURN0; } return 1; } @@ -652,7 +709,7 @@ parse_type_specifier(slang_parse_ctx * C, slang_output_ctx * O, case TYPE_SPECIFIER_STRUCT: spec->type = SLANG_SPEC_STRUCT; if (!parse_struct(C, O, &spec->_struct)) - return 0; + RETURN0; break; case TYPE_SPECIFIER_TYPENAME: spec->type = SLANG_SPEC_STRUCT; @@ -662,77 +719,163 @@ parse_type_specifier(slang_parse_ctx * C, slang_output_ctx * O, a_name = parse_identifier(C); if (a_name == NULL) - return 0; + RETURN0; stru = slang_struct_scope_find(O->structs, a_name, 1); if (stru == NULL) { slang_info_log_error(C->L, "undeclared type name '%s'", slang_atom_pool_id(C->atoms, a_name)); - return 0; + RETURN0; } spec->_struct = (slang_struct *) _slang_alloc(sizeof(slang_struct)); if (spec->_struct == NULL) { slang_info_log_memory(C->L); - return 0; + RETURN0; } if (!slang_struct_construct(spec->_struct)) { _slang_free(spec->_struct); spec->_struct = NULL; - return 0; + RETURN0; } if (!slang_struct_copy(spec->_struct, stru)) - return 0; + RETURN0; } break; default: - return 0; + RETURN0; } return 1; } + #define PRECISION_DEFAULT 0 #define PRECISION_LOW 1 #define PRECISION_MEDIUM 2 #define PRECISION_HIGH 3 static int +parse_type_precision(slang_parse_ctx *C, + slang_type_precision *precision) +{ + GLint prec = *C->I++; + switch (prec) { + case PRECISION_DEFAULT: + *precision = SLANG_PREC_DEFAULT; + return 1; + case PRECISION_LOW: + *precision = SLANG_PREC_LOW; + return 1; + case PRECISION_MEDIUM: + *precision = SLANG_PREC_MEDIUM; + return 1; + case PRECISION_HIGH: + *precision = SLANG_PREC_HIGH; + return 1; + default: + RETURN0; + } +} + + +#define TYPE_ARRAY_SIZE 220 +#define TYPE_NO_ARRAY_SIZE 221 + + +/* + * Parse array size (if present) in something like "uniform float [6] var;". + */ +static int +parse_type_array_size(slang_parse_ctx *C, slang_output_ctx * O, + GLint *size) +{ + GLint arr = *C->I++; + GLuint sz; + + switch (arr) { + case TYPE_ARRAY_SIZE: + if (!parse_array_len(C, O, &sz)) + RETURN0; + *size = sz; + return 1; + case TYPE_NO_ARRAY_SIZE: + *size = -1; /* -1 = not an array */ + return 1; + default: + assert(0); + RETURN0; + } +} + +static int parse_fully_specified_type(slang_parse_ctx * C, slang_output_ctx * O, slang_fully_specified_type * type) { - GLuint precision; + if (!parse_type_variant(C, &type->variant)) + RETURN0; + + if (!parse_type_centroid(C, &type->centroid)) + RETURN0; if (!parse_type_qualifier(C, &type->qualifier)) - return 0; - precision = *C->I++; + RETURN0; + + if (!parse_type_precision(C, &type->precision)) + RETURN0; + if (!parse_type_specifier(C, O, &type->specifier)) - return 0; + RETURN0; - switch (precision) { - case PRECISION_DEFAULT: - assert(type->specifier.type < TYPE_SPECIFIER_COUNT); - if (type->specifier.type < TYPE_SPECIFIER_COUNT) + if (!parse_type_array_size(C, O, &type->array_len)) + RETURN0; + + if (!O->allow_invariant && type->variant == SLANG_INVARIANT) { + slang_info_log_error(C->L, + "'invariant' keyword not allowed (perhaps set #version 120)"); + RETURN0; + } + + if (!O->allow_centroid && type->centroid == SLANG_CENTROID) { + slang_info_log_error(C->L, + "'centroid' keyword not allowed (perhaps set #version 120)"); + RETURN0; + } + else if (type->centroid == SLANG_CENTROID && + type->qualifier != SLANG_QUAL_VARYING) { + slang_info_log_error(C->L, + "'centroid' keyword only allowed for varying vars"); + RETURN0; + } + + + /* need this? + if (type->qualifier != SLANG_QUAL_VARYING && + type->variant == SLANG_INVARIANT) { + slang_info_log_error(C->L, + "invariant qualifer only allowed for varying vars"); + RETURN0; + } + */ + + if (O->allow_precision) { + if (type->precision == SLANG_PREC_DEFAULT) { + assert(type->specifier.type < TYPE_SPECIFIER_COUNT); + /* use the default precision for this datatype */ type->precision = O->default_precision[type->specifier.type]; - break; - case PRECISION_LOW: - type->precision = SLANG_PREC_LOW; - break; - case PRECISION_MEDIUM: - type->precision = SLANG_PREC_MEDIUM; - break; - case PRECISION_HIGH: - type->precision = SLANG_PREC_HIGH; - break; - default: - return 0; + } + } + else { + /* only default is allowed */ + if (type->precision != SLANG_PREC_DEFAULT) { + slang_info_log_error(C->L, "precision qualifiers not allowed"); + RETURN0; + } } -#if !FEATURE_es2_glsl - if (precision != PRECISION_DEFAULT) { - slang_info_log_error(C->L, "precision qualifiers not allowed"); - return 0; + if (!O->allow_array_types && type->array_len >= 0) { + slang_info_log_error(C->L, "first-class array types not allowed"); + RETURN0; } -#endif return 1; } @@ -801,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 /** @@ -841,7 +985,7 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O, oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE; while (*C->I != OP_END) if (!parse_child_operation(C, O, oper, 1)) - return 0; + RETURN0; C->I++; break; case OP_BLOCK_BEGIN_NEW_SCOPE: @@ -853,7 +997,7 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O, o.vars = oper->locals; while (*C->I != OP_END) if (!parse_child_operation(C, &o, oper, 1)) - return 0; + RETURN0; C->I++; } break; @@ -869,7 +1013,7 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O, * than one declarators */ if (!parse_declaration(C, O)) - return 0; + RETURN0; if (first_var < O->vars->num_variables) { const unsigned int num_vars = O->vars->num_variables - first_var; unsigned int i; @@ -878,18 +1022,23 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O, oper->children = slang_operation_new(num_vars); if (oper->children == NULL) { slang_info_log_memory(C->L); - return 0; + RETURN0; } for (i = first_var; i < O->vars->num_variables; i++) { slang_operation *o = &oper->children[i - first_var]; + slang_variable *var = O->vars->variables[i]; o->type = SLANG_OPER_VARIABLE_DECL; o->locals->outer_scope = O->vars; - o->a_id = O->vars->variables[i]->a_name; + o->a_id = var->a_name; + + /* new/someday... + calculate_var_size(C, O, var); + */ if (!legal_identifier(o->a_id)) { slang_info_log_error(C->L, "illegal variable name '%s'", (char *) o->a_id); - return 0; + RETURN0; } } } @@ -902,10 +1051,10 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O, oper->type = SLANG_OPER_ASM; oper->a_id = parse_identifier(C); if (oper->a_id == SLANG_ATOM_NULL) - return 0; + RETURN0; while (*C->I != OP_END) { if (!parse_child_operation(C, O, oper, 0)) - return 0; + RETURN0; } C->I++; break; @@ -921,21 +1070,21 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O, case OP_RETURN: oper->type = SLANG_OPER_RETURN; if (!parse_child_operation(C, O, oper, 0)) - return 0; + RETURN0; break; case OP_EXPRESSION: oper->type = SLANG_OPER_EXPRESSION; if (!parse_child_operation(C, O, oper, 0)) - return 0; + RETURN0; break; case OP_IF: oper->type = SLANG_OPER_IF; if (!parse_child_operation(C, O, oper, 0)) - return 0; + RETURN0; if (!parse_child_operation(C, O, oper, 1)) - return 0; + RETURN0; if (!parse_child_operation(C, O, oper, 1)) - return 0; + RETURN0; break; case OP_WHILE: { @@ -944,17 +1093,17 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O, oper->type = SLANG_OPER_WHILE; o.vars = oper->locals; if (!parse_child_operation(C, &o, oper, 1)) - return 0; + RETURN0; if (!parse_child_operation(C, &o, oper, 1)) - return 0; + RETURN0; } break; case OP_DO: oper->type = SLANG_OPER_DO; if (!parse_child_operation(C, O, oper, 1)) - return 0; + RETURN0; if (!parse_child_operation(C, O, oper, 0)) - return 0; + RETURN0; break; case OP_FOR: { @@ -963,13 +1112,13 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O, oper->type = SLANG_OPER_FOR; o.vars = oper->locals; if (!parse_child_operation(C, &o, oper, 1)) - return 0; + RETURN0; if (!parse_child_operation(C, &o, oper, 1)) - return 0; + RETURN0; if (!parse_child_operation(C, &o, oper, 0)) - return 0; + RETURN0; if (!parse_child_operation(C, &o, oper, 1)) - return 0; + RETURN0; } break; case OP_PRECISION: @@ -983,7 +1132,7 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O, } break; default: - return 0; + RETURN0; } return 1; } @@ -998,7 +1147,7 @@ handle_nary_expression(slang_parse_ctx * C, slang_operation * op, op->children = slang_operation_new(n); if (op->children == NULL) { slang_info_log_memory(C->L); - return 0; + RETURN0; } op->num_children = n; @@ -1016,7 +1165,7 @@ handle_nary_expression(slang_parse_ctx * C, slang_operation * op, *total_ops * sizeof(slang_operation)); if (*ops == NULL) { slang_info_log_memory(C->L); - return 0; + RETURN0; } return 1; } @@ -1049,12 +1198,12 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O, (num_ops + 1) * sizeof(slang_operation)); if (ops == NULL) { slang_info_log_memory(C->L); - return 0; + RETURN0; } op = &ops[num_ops]; if (!slang_operation_construct(op)) { slang_info_log_memory(C->L); - return 0; + RETURN0; } num_ops++; op->locals->outer_scope = O->vars; @@ -1066,7 +1215,7 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O, case OP_PUSH_BOOL: op->type = SLANG_OPER_LITERAL_BOOL; if (!parse_number(C, &number)) - return 0; + RETURN0; op->literal[0] = op->literal[1] = op->literal[2] = @@ -1076,7 +1225,7 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O, case OP_PUSH_INT: op->type = SLANG_OPER_LITERAL_INT; if (!parse_number(C, &number)) - return 0; + RETURN0; op->literal[0] = op->literal[1] = op->literal[2] = @@ -1086,7 +1235,7 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O, case OP_PUSH_FLOAT: op->type = SLANG_OPER_LITERAL_FLOAT; if (!parse_float(C, &op->literal[0])) - return 0; + RETURN0; op->literal[1] = op->literal[2] = op->literal[3] = op->literal[0]; @@ -1096,37 +1245,37 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O, op->type = SLANG_OPER_IDENTIFIER; op->a_id = parse_identifier(C); if (op->a_id == SLANG_ATOM_NULL) - return 0; + RETURN0; break; case OP_SEQUENCE: op->type = SLANG_OPER_SEQUENCE; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; case OP_ASSIGN: op->type = SLANG_OPER_ASSIGN; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; case OP_ADDASSIGN: op->type = SLANG_OPER_ADDASSIGN; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; case OP_SUBASSIGN: op->type = SLANG_OPER_SUBASSIGN; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; case OP_MULASSIGN: op->type = SLANG_OPER_MULASSIGN; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; case OP_DIVASSIGN: op->type = SLANG_OPER_DIVASSIGN; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; /*case OP_MODASSIGN: */ /*case OP_LSHASSIGN: */ @@ -1137,22 +1286,22 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O, case OP_SELECT: op->type = SLANG_OPER_SELECT; if (!handle_nary_expression(C, op, &ops, &num_ops, 3)) - return 0; + RETURN0; break; case OP_LOGICALOR: op->type = SLANG_OPER_LOGICALOR; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; case OP_LOGICALXOR: op->type = SLANG_OPER_LOGICALXOR; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; case OP_LOGICALAND: op->type = SLANG_OPER_LOGICALAND; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; /*case OP_BITOR: */ /*case OP_BITXOR: */ @@ -1160,95 +1309,123 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O, case OP_EQUAL: op->type = SLANG_OPER_EQUAL; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; case OP_NOTEQUAL: op->type = SLANG_OPER_NOTEQUAL; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; case OP_LESS: op->type = SLANG_OPER_LESS; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; case OP_GREATER: op->type = SLANG_OPER_GREATER; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; case OP_LESSEQUAL: op->type = SLANG_OPER_LESSEQUAL; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; case OP_GREATEREQUAL: op->type = SLANG_OPER_GREATEREQUAL; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; /*case OP_LSHIFT: */ /*case OP_RSHIFT: */ case OP_ADD: op->type = SLANG_OPER_ADD; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; case OP_SUBTRACT: op->type = SLANG_OPER_SUBTRACT; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; case OP_MULTIPLY: op->type = SLANG_OPER_MULTIPLY; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; case OP_DIVIDE: op->type = SLANG_OPER_DIVIDE; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; break; /*case OP_MODULUS: */ case OP_PREINCREMENT: op->type = SLANG_OPER_PREINCREMENT; if (!handle_nary_expression(C, op, &ops, &num_ops, 1)) - return 0; + RETURN0; break; case OP_PREDECREMENT: op->type = SLANG_OPER_PREDECREMENT; if (!handle_nary_expression(C, op, &ops, &num_ops, 1)) - return 0; + RETURN0; break; case OP_PLUS: op->type = SLANG_OPER_PLUS; if (!handle_nary_expression(C, op, &ops, &num_ops, 1)) - return 0; + RETURN0; break; case OP_MINUS: op->type = SLANG_OPER_MINUS; if (!handle_nary_expression(C, op, &ops, &num_ops, 1)) - return 0; + RETURN0; break; case OP_NOT: op->type = SLANG_OPER_NOT; if (!handle_nary_expression(C, op, &ops, &num_ops, 1)) - return 0; + RETURN0; break; /*case OP_COMPLEMENT: */ case OP_SUBSCRIPT: op->type = SLANG_OPER_SUBSCRIPT; if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) - return 0; + RETURN0; + break; + case OP_METHOD: + 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); if (op->a_id == SLANG_ATOM_NULL) - return 0; + RETURN0; while (*C->I != OP_END) if (!parse_child_operation(C, O, op, 0)) - return 0; + RETURN0; C->I++; if (!C->parsing_builtin @@ -1258,7 +1435,7 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O, 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); - return 0; + RETURN0; } } break; @@ -1266,22 +1443,22 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O, op->type = SLANG_OPER_FIELD; op->a_id = parse_identifier(C); if (op->a_id == SLANG_ATOM_NULL) - return 0; + RETURN0; if (!handle_nary_expression(C, op, &ops, &num_ops, 1)) - return 0; + RETURN0; break; case OP_POSTINCREMENT: op->type = SLANG_OPER_POSTINCREMENT; if (!handle_nary_expression(C, op, &ops, &num_ops, 1)) - return 0; + RETURN0; break; case OP_POSTDECREMENT: op->type = SLANG_OPER_POSTDECREMENT; if (!handle_nary_expression(C, op, &ops, &num_ops, 1)) - return 0; + RETURN0; break; default: - return 0; + RETURN0; } } C->I++; @@ -1312,7 +1489,7 @@ parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O, * two at most) because not all combinations are valid */ if (!parse_type_qualifier(C, ¶m->type.qualifier)) - return 0; + RETURN0; param_qual = *C->I++; switch (param_qual) { @@ -1320,7 +1497,7 @@ parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O, if (param->type.qualifier != SLANG_QUAL_CONST && param->type.qualifier != SLANG_QUAL_NONE) { slang_info_log_error(C->L, "Invalid type qualifier."); - return 0; + RETURN0; } break; case PARAM_QUALIFIER_OUT: @@ -1328,7 +1505,7 @@ parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O, param->type.qualifier = SLANG_QUAL_OUT; else { slang_info_log_error(C->L, "Invalid type qualifier."); - return 0; + RETURN0; } break; case PARAM_QUALIFIER_INOUT: @@ -1336,11 +1513,11 @@ parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O, param->type.qualifier = SLANG_QUAL_INOUT; else { slang_info_log_error(C->L, "Invalid type qualifier."); - return 0; + RETURN0; } break; default: - return 0; + RETURN0; } /* parse precision qualifier (lowp, mediump, highp */ @@ -1350,10 +1527,10 @@ parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O, /* parse parameter's type specifier and name */ if (!parse_type_specifier(C, O, ¶m->type.specifier)) - return 0; + RETURN0; param->a_name = parse_identifier(C); if (param->a_name == SLANG_ATOM_NULL) - return 0; + RETURN0; /* if the parameter is an array, parse its size (the size must be * explicitly defined @@ -1470,13 +1647,13 @@ parse_operator_name(slang_parse_ctx * C) slang_atom_pool_atom(C->atoms, operator_names[i].o_name); if (atom == SLANG_ATOM_NULL) { slang_info_log_memory(C->L); - return 0; + RETURN0; } C->I++; return atom; } } - return 0; + RETURN0; } @@ -1484,43 +1661,46 @@ static int parse_function_prototype(slang_parse_ctx * C, slang_output_ctx * O, slang_function * func) { + GLuint functype; /* parse function type and name */ if (!parse_fully_specified_type(C, O, &func->header.type)) - return 0; - switch (*C->I++) { + RETURN0; + + functype = *C->I++; + switch (functype) { case FUNCTION_ORDINARY: func->kind = SLANG_FUNC_ORDINARY; func->header.a_name = parse_identifier(C); if (func->header.a_name == SLANG_ATOM_NULL) - return 0; + RETURN0; break; case FUNCTION_CONSTRUCTOR: func->kind = SLANG_FUNC_CONSTRUCTOR; if (func->header.type.specifier.type == SLANG_SPEC_STRUCT) - return 0; + RETURN0; func->header.a_name = slang_atom_pool_atom(C->atoms, slang_type_specifier_type_to_string (func->header.type.specifier.type)); if (func->header.a_name == SLANG_ATOM_NULL) { slang_info_log_memory(C->L); - return 0; + RETURN0; } break; case FUNCTION_OPERATOR: func->kind = SLANG_FUNC_OPERATOR; func->header.a_name = parse_operator_name(C); if (func->header.a_name == SLANG_ATOM_NULL) - return 0; + RETURN0; break; default: - return 0; + RETURN0; } if (!legal_identifier(func->header.a_name)) { slang_info_log_error(C->L, "illegal function name '%s'", (char *) func->header.a_name); - return 0; + RETURN0; } /* parse function parameters */ @@ -1528,10 +1708,10 @@ parse_function_prototype(slang_parse_ctx * C, slang_output_ctx * O, slang_variable *p = slang_variable_scope_grow(func->parameters); if (!p) { slang_info_log_memory(C->L); - return 0; + RETURN0; } if (!parse_parameter_declaration(C, O, p)) - return 0; + RETURN0; } /* if the function returns a value, append a hidden __retVal 'out' @@ -1565,19 +1745,19 @@ parse_function_definition(slang_parse_ctx * C, slang_output_ctx * O, slang_output_ctx o = *O; if (!parse_function_prototype(C, O, func)) - return 0; + RETURN0; /* create function's body operation */ func->body = (slang_operation *) _slang_alloc(sizeof(slang_operation)); if (func->body == NULL) { slang_info_log_memory(C->L); - return 0; + RETURN0; } if (!slang_operation_construct(func->body)) { _slang_free(func->body); func->body = NULL; slang_info_log_memory(C->L); - return 0; + RETURN0; } /* to parse the body the parse context is modified in order to @@ -1586,7 +1766,7 @@ parse_function_definition(slang_parse_ctx * C, slang_output_ctx * O, C->global_scope = GL_FALSE; o.vars = func->parameters; if (!parse_statement(C, &o, func->body)) - return 0; + RETURN0; C->global_scope = GL_TRUE; return 1; @@ -1682,46 +1862,49 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O, slang_info_log_error(C->L, "declaration of '%s' conflicts with previous declaration", (char *) a_name); - return 0; + RETURN0; } /* make room for the new variable and initialize it */ var = slang_variable_scope_grow(O->vars); if (!var) { slang_info_log_memory(C->L); - return 0; + RETURN0; } - /* copy the declarator qualifier type, parse the identifier */ + /* copy the declarator type qualifier/etc info, parse the identifier */ var->type.qualifier = type->qualifier; + var->type.centroid = type->centroid; + var->type.precision = type->precision; + var->type.variant = type->variant; var->a_name = a_name; if (var->a_name == SLANG_ATOM_NULL) - return 0; + RETURN0; switch (*C->I++) { case VARIABLE_NONE: /* simple variable declarator - just copy the specifier */ if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier)) - return 0; + RETURN0; break; case VARIABLE_INITIALIZER: /* initialized variable - copy the specifier and parse the expression */ if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier)) - return 0; + RETURN0; var->initializer = (slang_operation *) _slang_alloc(sizeof(slang_operation)); if (var->initializer == NULL) { slang_info_log_memory(C->L); - return 0; + RETURN0; } if (!slang_operation_construct(var->initializer)) { _slang_free(var->initializer); var->initializer = NULL; slang_info_log_memory(C->L); - return 0; + RETURN0; } if (!parse_expression(C, O, var->initializer)) - return 0; + RETURN0; break; case VARIABLE_ARRAY_UNKNOWN: /* unsized array - mark it as array and copy the specifier to @@ -1737,7 +1920,17 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O, return GL_FALSE; break; default: - return 0; + RETURN0; + } + + if (type->array_len >= 0) { + /* The type was something like "float[4]" */ + if (var->array_len != 0) { + slang_info_log_error(C->L, "multi-dimensional arrays not allowed"); + RETURN0; + } + convert_to_array(C, var, &type->specifier); + var->array_len = type->array_len; } /* allocate global address space for a variable with a known size */ @@ -1761,7 +1954,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O, A.log = C->L; A.curFuncEndLabel = NULL; if (!_slang_codegen_global_variable(&A, var, C->type)) - return 0; + RETURN0; } /* initialize global variable */ @@ -1774,7 +1967,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O, A.space.structs = O->structs; A.space.vars = O->vars; if (!initialize_global(&A, var)) - return 0; + RETURN0; } } return 1; @@ -1791,17 +1984,17 @@ parse_init_declarator_list(slang_parse_ctx * C, slang_output_ctx * O) /* parse the fully specified type, common to all declarators */ if (!slang_fully_specified_type_construct(&type)) - return 0; + RETURN0; if (!parse_fully_specified_type(C, O, &type)) { slang_fully_specified_type_destruct(&type); - return 0; + RETURN0; } /* parse declarators, pass-in the parsed type */ do { if (!parse_init_declarator(C, O, &type)) { slang_fully_specified_type_destruct(&type); - return 0; + RETURN0; } } while (*C->I++ == DECLARATOR_NEXT); @@ -1908,18 +2101,18 @@ parse_declaration(slang_parse_ctx * C, slang_output_ctx * O) switch (*C->I++) { case DECLARATION_INIT_DECLARATOR_LIST: if (!parse_init_declarator_list(C, O)) - return 0; + RETURN0; break; case DECLARATION_FUNCTION_PROTOTYPE: { slang_function *dummy_func; if (!parse_function(C, O, 0, &dummy_func)) - return 0; + RETURN0; } break; default: - return 0; + RETURN0; } return 1; } @@ -1927,9 +2120,13 @@ parse_declaration(slang_parse_ctx * C, slang_output_ctx * O) static int parse_default_precision(slang_parse_ctx * C, slang_output_ctx * O) { -#if FEATURE_es2_glsl int precision, type; + if (!O->allow_precision) { + slang_info_log_error(C->L, "syntax error at \"precision\""); + RETURN0; + } + precision = *C->I++; switch (precision) { case PRECISION_LOW: @@ -1940,7 +2137,7 @@ parse_default_precision(slang_parse_ctx * C, slang_output_ctx * O) default: _mesa_problem(NULL, "unexpected precision %d at %s:%d\n", precision, __FILE__, __LINE__); - return 0; + RETURN0; } type = *C->I++; @@ -1960,17 +2157,13 @@ parse_default_precision(slang_parse_ctx * C, slang_output_ctx * O) default: _mesa_problem(NULL, "unexpected type %d at %s:%d\n", type, __FILE__, __LINE__); - return 0; + RETURN0; } assert(type < TYPE_SPECIFIER_COUNT); O->default_precision[type] = precision; return 1; -#else - slang_info_log_error(C->L, "syntax error at \"precision\""); - return 0; -#endif } @@ -1989,7 +2182,7 @@ init_default_precision(slang_output_ctx *O, slang_unit_type type) O->default_precision[i] = PRECISION_HIGH; #endif } -#if FEATURE_es2_glsl + if (type == SLANG_UNIT_VERTEX_SHADER) { O->default_precision[TYPE_SPECIFIER_FLOAT] = PRECISION_HIGH; O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_HIGH; @@ -1997,14 +2190,13 @@ init_default_precision(slang_output_ctx *O, slang_unit_type type) else { O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_MEDIUM; } -#endif } static int parse_invariant(slang_parse_ctx * C, slang_output_ctx * O) { - if (C->version >= 120 || FEATURE_es2_glsl) { + if (O->allow_invariant) { slang_atom *a = parse_identifier(C); /* XXX not doing anything with this var yet */ /*printf("ID: %s\n", (char*) a);*/ @@ -2012,7 +2204,7 @@ parse_invariant(slang_parse_ctx * C, slang_output_ctx * O) } else { slang_info_log_error(C->L, "syntax error at \"invariant\""); - return 0; + RETURN0; } } @@ -2046,7 +2238,6 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit, } /* setup output context */ - init_default_precision(&o, unit->type); o.funs = &unit->funs; o.structs = &unit->structs; o.vars = &unit->vars; @@ -2055,6 +2246,27 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit, o.vartable = _slang_new_var_table(maxRegs); _slang_push_var_table(o.vartable); + /* allow 'invariant' keyword? */ +#if FEATURE_es2_glsl + o.allow_invariant = GL_TRUE; +#else + o.allow_invariant = (C->version >= 120) ? GL_TRUE : GL_FALSE; +#endif + + /* allow 'centroid' keyword? */ + o.allow_centroid = (C->version >= 120) ? GL_TRUE : GL_FALSE; + + /* allow 'lowp/mediump/highp' keywords? */ +#if FEATURE_es2_glsl + o.allow_precision = GL_TRUE; +#else + o.allow_precision = (C->version >= 120) ? GL_TRUE : GL_FALSE; +#endif + init_default_precision(&o, unit->type); + + /* allow 'float[]' keyword? */ + o.allow_array_types = (C->version >= 120) ? GL_TRUE : GL_FALSE; + /* parse individual functions and declarations */ while (*C->I != EXTERNAL_NULL) { switch (*C->I++) { |