From: Michal Krol Date: Fri, 22 Apr 2005 10:43:36 +0000 (+0000) Subject: Add more error checking. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=addcc6afbd5a94bf0c35ad04e914503056d0e994;p=mesa.git Add more error checking. --- diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c index d49d104323c..06dc7df9536 100644 --- a/src/mesa/shader/slang/slang_compile.c +++ b/src/mesa/shader/slang/slang_compile.c @@ -28,7 +28,7 @@ * \author Michal Krol */ -#include "imports.h" +#include "imports.h" #include "grammar_mesa.h" #include "slang_utility.h" #include "slang_compile.h" @@ -417,6 +417,18 @@ static void slang_function_scope_destruct (slang_function_scope *scope) slang_alloc_free (scope->functions); } +static int slang_function_scope_find_by_name (slang_function_scope *funcs, const char *name, + int all_scopes) +{ + unsigned int i; + for (i = 0; i < funcs->num_functions; i++) + if (slang_string_compare (name, funcs->functions[i].header.name) == 0) + return 1; + if (all_scopes && funcs->outer_scope != NULL) + return slang_function_scope_find_by_name (funcs->outer_scope, name, 1); + return 0; +} + static slang_function *slang_function_scope_find (slang_function_scope *funcs, slang_function *fun, int all_scopes) { @@ -446,23 +458,19 @@ static slang_function *slang_function_scope_find (slang_function_scope *funcs, s } /* slang_translation_unit */ -/* XXX mem! */ -static void slang_translation_unit_construct (slang_translation_unit *unit) + +void slang_translation_unit_construct (slang_translation_unit *unit) { - unit->globals = (slang_variable_scope *) slang_alloc_malloc (sizeof (slang_variable_scope)); - slang_variable_scope_construct (unit->globals); + slang_variable_scope_construct (&unit->globals); slang_function_scope_construct (&unit->functions); - unit->structs = (slang_struct_scope *) slang_alloc_malloc (sizeof (slang_struct_scope)); - slang_struct_scope_construct (unit->structs); + slang_struct_scope_construct (&unit->structs); } -static void slang_translation_unit_destruct (slang_translation_unit *unit) +void slang_translation_unit_destruct (slang_translation_unit *unit) { - slang_variable_scope_destruct (unit->globals); - slang_alloc_free (unit->globals); + slang_variable_scope_destruct (&unit->globals); slang_function_scope_destruct (&unit->functions); - slang_struct_scope_destruct (unit->structs); - slang_alloc_free (unit->structs); + slang_struct_scope_destruct (&unit->structs); } /* slang_info_log */ @@ -509,17 +517,29 @@ static int slang_info_log_message (slang_info_log *log, const char *prefix, cons int slang_info_log_error (slang_info_log *log, const char *msg, ...) { - if (slang_info_log_message (log, "error", msg)) + va_list va; + char buf[1024]; + + va_start (va, msg); + vsprintf (buf, msg, va); + if (slang_info_log_message (log, "error", buf)) return 1; slang_info_log_memory (log); + va_end (va); return 0; } int slang_info_log_warning (slang_info_log *log, const char *msg, ...) { - if (slang_info_log_message (log, "warning", msg)) + va_list va; + char buf[1024]; + + va_start (va, msg); + vsprintf (buf, msg, va); + if (slang_info_log_message (log, "warning", buf)) return 1; slang_info_log_memory (log); + va_end (va); return 0; } @@ -538,6 +558,7 @@ typedef struct slang_parse_ctx_ { const byte *I; slang_info_log *L; + int parsing_builtin; } slang_parse_ctx; /* --- */ @@ -640,9 +661,9 @@ static int check_revision (slang_parse_ctx *C) } static int parse_statement (slang_parse_ctx *, slang_operation *, slang_variable_scope *, - slang_struct_scope *); + slang_struct_scope *, slang_function_scope *); static int parse_expression (slang_parse_ctx *, slang_operation *, slang_variable_scope *, - slang_struct_scope *); + slang_struct_scope *, slang_function_scope *); /* type qualifier */ #define TYPE_QUALIFIER_NONE 0 @@ -716,7 +737,7 @@ static int parse_type_qualifier (slang_parse_ctx *C, slang_type_qualifier *qual) #define FIELD_ARRAY 2 static int parse_type_specifier (slang_parse_ctx *C, slang_type_specifier *spec, - slang_struct_scope *structs, slang_variable_scope *scope) + slang_struct_scope *structs, slang_variable_scope *scope, slang_function_scope *funcs) { switch (*C->I++) { @@ -813,7 +834,7 @@ static int parse_type_specifier (slang_parse_ctx *C, slang_type_specifier *spec, { slang_type_specifier sp; slang_type_specifier_construct (&sp); - if (!parse_type_specifier (C, &sp, spec->_struct->structs, scope)) + if (!parse_type_specifier (C, &sp, spec->_struct->structs, scope, funcs)) { slang_type_specifier_destruct (&sp); return 0; @@ -858,7 +879,7 @@ static int parse_type_specifier (slang_parse_ctx *C, slang_type_specifier *spec, return 0; } slang_operation_construct (var->array_size); - if (!parse_expression (C, var->array_size, scope, structs)) + if (!parse_expression (C, var->array_size, scope, structs, funcs)) { slang_type_specifier_destruct (&sp); return 0; @@ -922,11 +943,11 @@ static int parse_type_specifier (slang_parse_ctx *C, slang_type_specifier *spec, } static int parse_fully_specified_type (slang_parse_ctx *C, slang_fully_specified_type *type, - slang_struct_scope *structs, slang_variable_scope *scope) + slang_struct_scope *structs, slang_variable_scope *scope, slang_function_scope *funcs) { if (!parse_type_qualifier (C, &type->qualifier)) return 0; - return parse_type_specifier (C, &type->specifier, structs, scope); + return parse_type_specifier (C, &type->specifier, structs, scope, funcs); } /* operation */ @@ -994,7 +1015,7 @@ static int parse_fully_specified_type (slang_parse_ctx *C, slang_fully_specified #define OP_POSTDECREMENT 61 static int parse_child_operation (slang_parse_ctx *C, slang_operation *oper, int statement, - slang_variable_scope *scope, slang_struct_scope *structs) + slang_variable_scope *scope, slang_struct_scope *structs, slang_function_scope *funcs) { oper->children = (slang_operation *) slang_alloc_realloc (oper->children, oper->num_children * sizeof (slang_operation), @@ -1007,15 +1028,15 @@ static int parse_child_operation (slang_parse_ctx *C, slang_operation *oper, int slang_operation_construct (oper->children + oper->num_children); oper->num_children++; if (statement) - return parse_statement (C, oper->children + oper->num_children - 1, scope, structs); - return parse_expression (C, oper->children + oper->num_children - 1, scope, structs); + return parse_statement (C, oper->children + oper->num_children - 1, scope, structs, funcs); + return parse_expression (C, oper->children + oper->num_children - 1, scope, structs, funcs); } static int parse_declaration (slang_parse_ctx *C, slang_variable_scope *, slang_struct_scope *, slang_function_scope *); static int parse_statement (slang_parse_ctx *C, slang_operation *oper, slang_variable_scope *scope, - slang_struct_scope *structs) + slang_struct_scope *structs, slang_function_scope *funcs) { oper->locals->outer_scope = scope; switch (*C->I++) @@ -1023,14 +1044,14 @@ static int parse_statement (slang_parse_ctx *C, slang_operation *oper, slang_var case OP_BLOCK_BEGIN_NO_NEW_SCOPE: oper->type = slang_oper_block_no_new_scope; while (*C->I != OP_END) - if (!parse_child_operation (C, oper, 1, scope, structs)) + if (!parse_child_operation (C, oper, 1, scope, structs, funcs)) return 0; C->I++; break; case OP_BLOCK_BEGIN_NEW_SCOPE: oper->type = slang_oper_block_new_scope; while (*C->I != OP_END) - if (!parse_child_operation (C, oper, 1, oper->locals, structs)) + if (!parse_child_operation (C, oper, 1, oper->locals, structs, funcs)) return 0; C->I++; break; @@ -1038,7 +1059,7 @@ static int parse_statement (slang_parse_ctx *C, slang_operation *oper, slang_var oper->type = slang_oper_variable_decl; { const unsigned int first_var = scope->num_variables; - if (!parse_declaration (C, scope, structs, NULL)) + if (!parse_declaration (C, scope, structs, funcs)) return 0; if (first_var < scope->num_variables) { @@ -1074,7 +1095,7 @@ static int parse_statement (slang_parse_ctx *C, slang_operation *oper, slang_var if (!parse_identifier (C, &oper->identifier)) return 0; while (*C->I != OP_END) - if (!parse_child_operation (C, oper, 0, scope, structs)) + if (!parse_child_operation (C, oper, 0, scope, structs, funcs)) return 0; C->I++; break; @@ -1089,46 +1110,46 @@ static int parse_statement (slang_parse_ctx *C, slang_operation *oper, slang_var break; case OP_RETURN: oper->type = slang_oper_return; - if (!parse_child_operation (C, oper, 0, scope, structs)) + if (!parse_child_operation (C, oper, 0, scope, structs, funcs)) return 0; break; case OP_EXPRESSION: oper->type = slang_oper_expression; - if (!parse_child_operation (C, oper, 0, scope, structs)) + if (!parse_child_operation (C, oper, 0, scope, structs, funcs)) return 0; break; case OP_IF: oper->type = slang_oper_if; - if (!parse_child_operation (C, oper, 0, scope, structs)) + if (!parse_child_operation (C, oper, 0, scope, structs, funcs)) return 0; - if (!parse_child_operation (C, oper, 1, scope, structs)) + if (!parse_child_operation (C, oper, 1, scope, structs, funcs)) return 0; - if (!parse_child_operation (C, oper, 1, scope, structs)) + if (!parse_child_operation (C, oper, 1, scope, structs, funcs)) return 0; break; case OP_WHILE: oper->type = slang_oper_while; - if (!parse_child_operation (C, oper, 1, oper->locals, structs)) + if (!parse_child_operation (C, oper, 1, oper->locals, structs, funcs)) return 0; - if (!parse_child_operation (C, oper, 1, oper->locals, structs)) + if (!parse_child_operation (C, oper, 1, oper->locals, structs, funcs)) return 0; break; case OP_DO: oper->type = slang_oper_do; - if (!parse_child_operation (C, oper, 1, scope, structs)) + if (!parse_child_operation (C, oper, 1, scope, structs, funcs)) return 0; - if (!parse_child_operation (C, oper, 0, scope, structs)) + if (!parse_child_operation (C, oper, 0, scope, structs, funcs)) return 0; break; case OP_FOR: oper->type = slang_oper_for; - if (!parse_child_operation (C, oper, 1, oper->locals, structs)) + if (!parse_child_operation (C, oper, 1, oper->locals, structs, funcs)) return 0; - if (!parse_child_operation (C, oper, 1, oper->locals, structs)) + if (!parse_child_operation (C, oper, 1, oper->locals, structs, funcs)) return 0; - if (!parse_child_operation (C, oper, 0, oper->locals, structs)) + if (!parse_child_operation (C, oper, 0, oper->locals, structs, funcs)) return 0; - if (!parse_child_operation (C, oper, 1, oper->locals, structs)) + if (!parse_child_operation (C, oper, 1, oper->locals, structs, funcs)) return 0; break; default: @@ -1209,8 +1230,44 @@ static int handle_unary_expression (slang_parse_ctx *C, slang_operation *op, return 1; } +/* these must match with slang_type_specifier_type enum */ +static const char *builtin_constructor_names[] = { + "void", + "bool", + "bvec2", + "bvec3", + "bvec4", + "int", + "ivec2", + "ivec3", + "ivec4", + "float", + "vec2", + "vec3", + "vec4", + "mat2", + "mat3", + "mat4", + "sampler1D", + "sampler2D", + "sampler3D", + "samplerCube", + "sampler1DShadow", + "sampler2DShadow", + NULL +}; + +static int is_constructor_name (const char *name, slang_struct_scope *structs) +{ + const char **p = &builtin_constructor_names[1]; + while (*p != NULL) + if (slang_string_compare (*p++, name) == 0) + return 1; + return slang_struct_scope_find (structs, name, 1) != NULL; +} + static int parse_expression (slang_parse_ctx *C, slang_operation *oper, slang_variable_scope *scope, - slang_struct_scope *structs) + slang_struct_scope *structs, slang_function_scope *funcs) { slang_operation *ops = NULL; unsigned int num_ops = 0; @@ -1406,9 +1463,16 @@ static int parse_expression (slang_parse_ctx *C, slang_operation *oper, slang_va if (!parse_identifier (C, &op->identifier)) return 0; while (*C->I != OP_END) - if (!parse_child_operation (C, op, 0, scope, structs)) + if (!parse_child_operation (C, op, 0, scope, structs, funcs)) return 0; C->I++; + if (!C->parsing_builtin && + !slang_function_scope_find_by_name (funcs, op->identifier, 1) && + !is_constructor_name (op->identifier, structs)) + { + slang_info_log_error (C->L, "%s: undeclared function name", op->identifier); + return 0; + } break; case OP_FIELD: op->type = slang_oper_field; @@ -1447,7 +1511,7 @@ static int parse_expression (slang_parse_ctx *C, slang_operation *oper, slang_va #define PARAMETER_ARRAY_PRESENT 1 static int parse_parameter_declaration (slang_parse_ctx *C, slang_variable *param, - slang_struct_scope *structs, slang_variable_scope *scope) + slang_struct_scope *structs, slang_variable_scope *scope, slang_function_scope *funcs) { if (!parse_type_qualifier (C, ¶m->type.qualifier)) return 0; @@ -1481,7 +1545,7 @@ static int parse_parameter_declaration (slang_parse_ctx *C, slang_variable *para default: return 0; } - if (!parse_type_specifier (C, ¶m->type.specifier, structs, scope)) + if (!parse_type_specifier (C, ¶m->type.specifier, structs, scope, funcs)) return 0; if (!parse_identifier (C, ¶m->name)) return 0; @@ -1494,7 +1558,7 @@ static int parse_parameter_declaration (slang_parse_ctx *C, slang_variable *para return 0; } slang_operation_construct (param->array_size); - if (!parse_expression (C, param->array_size, scope, structs)) + if (!parse_expression (C, param->array_size, scope, structs, funcs)) return 0; } return 1; @@ -1543,32 +1607,6 @@ static int parse_parameter_declaration (slang_parse_ctx *C, slang_variable *para /*#define OPERATOR_COMPLEMENT 31*/ #define OPERATOR_NOT 32 -/* these must match with slang_type_specifier_type enum */ -static const char *type_specifier_names[] = { - "void", - "bool", - "bvec2", - "bvec3", - "bvec4", - "int", - "ivec2", - "ivec3", - "ivec4", - "float", - "vec2", - "vec3", - "vec4", - "mat2", - "mat3", - "mat4", - "sampler1D", - "sampler2D", - "sampler3D", - "samplerCube", - "sampler1DShadow", - "sampler2DShadow" -}; - static const struct { unsigned int o_code; const char *o_name; @@ -1626,9 +1664,9 @@ static int parse_operator_name (slang_parse_ctx *C, char **pname) } static int parse_function_prototype (slang_parse_ctx *C, slang_function *func, - slang_struct_scope *structs, slang_variable_scope *scope) + slang_struct_scope *structs, slang_variable_scope *scope, slang_function_scope *funcs) { - if (!parse_fully_specified_type (C, &func->header.type, structs, scope)) + if (!parse_fully_specified_type (C, &func->header.type, structs, scope, funcs)) return 0; switch (*C->I++) { @@ -1642,7 +1680,7 @@ static int parse_function_prototype (slang_parse_ctx *C, slang_function *func, if (func->header.type.specifier.type == slang_spec_struct) return 0; func->header.name = slang_string_duplicate ( - type_specifier_names[func->header.type.specifier.type]); + builtin_constructor_names[func->header.type.specifier.type]); if (func->header.name == NULL) { slang_info_log_memory (C->L); @@ -1672,7 +1710,7 @@ static int parse_function_prototype (slang_parse_ctx *C, slang_function *func, slang_variable_construct (func->parameters->variables + func->parameters->num_variables); func->parameters->num_variables++; if (!parse_parameter_declaration (C, func->parameters->variables + - func->parameters->num_variables - 1, structs, scope)) + func->parameters->num_variables - 1, structs, scope, funcs)) return 0; } func->param_count = func->parameters->num_variables; @@ -1680,9 +1718,9 @@ static int parse_function_prototype (slang_parse_ctx *C, slang_function *func, } static int parse_function_definition (slang_parse_ctx *C, slang_function *func, - slang_struct_scope *structs, slang_variable_scope *scope) + slang_struct_scope *structs, slang_variable_scope *scope, slang_function_scope *funcs) { - if (!parse_function_prototype (C, func, structs, scope)) + if (!parse_function_prototype (C, func, structs, scope, funcs)) return 0; func->body = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation)); if (func->body == NULL) @@ -1691,7 +1729,7 @@ static int parse_function_definition (slang_parse_ctx *C, slang_function *func, return 0; } slang_operation_construct (func->body); - if (!parse_statement (C, func->body, func->parameters, structs)) + if (!parse_statement (C, func->body, func->parameters, structs, funcs)) return 0; return 1; } @@ -1708,7 +1746,7 @@ static int parse_function_definition (slang_parse_ctx *C, slang_function *func, #define VARIABLE_ARRAY_UNKNOWN 4 static int parse_init_declarator (slang_parse_ctx *C, const slang_fully_specified_type *type, - slang_variable_scope *vars, slang_struct_scope *structs) + slang_variable_scope *vars, slang_struct_scope *structs, slang_function_scope *funcs) { slang_variable *var; @@ -1744,7 +1782,7 @@ static int parse_init_declarator (slang_parse_ctx *C, const slang_fully_specifie return 0; } slang_operation_construct (var->initializer); - if (!parse_expression (C, var->initializer, vars, structs)) + if (!parse_expression (C, var->initializer, vars, structs, funcs)) return 0; break; case VARIABLE_ARRAY_UNKNOWN: @@ -1779,7 +1817,7 @@ static int parse_init_declarator (slang_parse_ctx *C, const slang_fully_specifie return 0; } slang_operation_construct (var->array_size); - if (!parse_expression (C, var->array_size, vars, structs)) + if (!parse_expression (C, var->array_size, vars, structs, funcs)) return 0; break; default: @@ -1789,19 +1827,19 @@ static int parse_init_declarator (slang_parse_ctx *C, const slang_fully_specifie } static int parse_init_declarator_list (slang_parse_ctx *C, slang_variable_scope *vars, - slang_struct_scope *structs) + slang_struct_scope *structs, slang_function_scope *funcs) { slang_fully_specified_type type; slang_fully_specified_type_construct (&type); - if (!parse_fully_specified_type (C, &type, structs, vars)) + if (!parse_fully_specified_type (C, &type, structs, vars, funcs)) { slang_fully_specified_type_destruct (&type); return 0; } do { - if (!parse_init_declarator (C, &type, vars, structs)) + if (!parse_init_declarator (C, &type, vars, structs, funcs)) { slang_fully_specified_type_destruct (&type); return 0; @@ -1813,14 +1851,15 @@ static int parse_init_declarator_list (slang_parse_ctx *C, slang_variable_scope } static int parse_function (slang_parse_ctx *C, int definition, slang_struct_scope *structs, - slang_function_scope *funcs, slang_variable_scope *scope) + slang_function_scope *funcs, slang_variable_scope *scope, slang_function **parsed_func_ret) { slang_function parsed_func, *found_func; + /* parse function definition/declaration */ slang_function_construct (&parsed_func); if (definition) { - if (!parse_function_definition (C, &parsed_func, structs, scope)) + if (!parse_function_definition (C, &parsed_func, structs, scope, funcs)) { slang_function_destruct (&parsed_func); return 0; @@ -1828,15 +1867,18 @@ static int parse_function (slang_parse_ctx *C, int definition, slang_struct_scop } else { - if (!parse_function_prototype (C, &parsed_func, structs, scope)) + if (!parse_function_prototype (C, &parsed_func, structs, scope, funcs)) { slang_function_destruct (&parsed_func); return 0; } } + + /* find a function with a prototype matching the parsed one */ found_func = slang_function_scope_find (funcs, &parsed_func, 0); if (found_func == NULL) { + /* add the parsed function to the function list */ funcs->functions = (slang_function *) slang_alloc_realloc (funcs->functions, funcs->num_functions * sizeof (slang_function), (funcs->num_functions + 1) * sizeof ( slang_function)); @@ -1848,12 +1890,16 @@ static int parse_function (slang_parse_ctx *C, int definition, slang_struct_scop } funcs->functions[funcs->num_functions] = parsed_func; funcs->num_functions++; + + /* return the newly parsed function */ + *parsed_func_ret = funcs->functions + funcs->num_functions - 1; } else { - /* TODO check function return type qualifiers and specifiers */ + /* TODO: check function return type qualifiers and specifiers */ if (definition) { + /* destroy the existing function declaration and replace it with the new one */ if (found_func->body != NULL) { slang_info_log_error (C->L, "%s: function already has a body", @@ -1866,8 +1912,12 @@ static int parse_function (slang_parse_ctx *C, int definition, slang_struct_scop } else { + /* another declaration of the same function prototype - ignore it */ slang_function_destruct (&parsed_func); } + + /* return the found function */ + *parsed_func_ret = found_func; } return 1; } @@ -1879,14 +1929,16 @@ static int parse_function (slang_parse_ctx *C, int definition, slang_struct_scop static int parse_declaration (slang_parse_ctx *C, slang_variable_scope *scope, slang_struct_scope *structs, slang_function_scope *funcs) { + slang_function *dummy_func; + switch (*C->I++) { case DECLARATION_INIT_DECLARATOR_LIST: - if (!parse_init_declarator_list (C, scope, structs)) + if (!parse_init_declarator_list (C, scope, structs, funcs)) return 0; break; case DECLARATION_FUNCTION_PROTOTYPE: - if (!parse_function (C, 0, structs, funcs, scope)) + if (!parse_function (C, 0, structs, funcs, scope, &dummy_func)) return 0; break; default: @@ -1904,14 +1956,16 @@ static int parse_translation_unit (slang_parse_ctx *C, slang_translation_unit *u { while (*C->I != EXTERNAL_NULL) { + slang_function *func; + switch (*C->I++) { case EXTERNAL_FUNCTION_DEFINITION: - if (!parse_function (C, 1, unit->structs, &unit->functions, unit->globals)) + if (!parse_function (C, 1, &unit->structs, &unit->functions, &unit->globals, &func)) return 0; break; case EXTERNAL_DECLARATION: - if (!parse_declaration (C, unit->globals, unit->structs, &unit->functions)) + if (!parse_declaration (C, &unit->globals, &unit->structs, &unit->functions)) return 0; break; default: @@ -1922,19 +1976,59 @@ static int parse_translation_unit (slang_parse_ctx *C, slang_translation_unit *u return 1; } +static int compile_binary (const byte *prod, slang_translation_unit *unit, slang_unit_type type, + slang_info_log *log, slang_translation_unit *builtins) +{ + slang_parse_ctx C; + + /* set-up parse context */ + C.I = prod; + C.L = log; + C.parsing_builtin = builtins == NULL; + + if (!check_revision (&C)) + return 0; + + /* create translation unit object */ + slang_translation_unit_construct (unit); + unit->type = type; + + if (builtins != NULL) + { + /* link to built-in functions */ + builtins[1].functions.outer_scope = &builtins[0].functions; + builtins[2].functions.outer_scope = &builtins[1].functions; + unit->functions.outer_scope = &builtins[2].functions; + + /* link to built-in variables - core unit does not define any */ + builtins[2].globals.outer_scope = &builtins[1].globals; + unit->globals.outer_scope = &builtins[2].globals; + + /* link to built-in structure typedefs - only in common unit */ + unit->structs.outer_scope = &builtins[1].structs; + } + + /* parse translation unit */ + if (!parse_translation_unit (&C, unit)) + { + slang_translation_unit_destruct (unit); + return 0; + } + + return 1; +} + static int compile_with_grammar (grammar id, const char *source, slang_translation_unit *unit, - slang_unit_type type, slang_info_log *log) + slang_unit_type type, slang_info_log *log, slang_translation_unit *builtins) { byte *prod; unsigned int size, start, version; - slang_parse_ctx C; /* retrieve version */ if (!_slang_preprocess_version (source, &version, &start, log)) return 0; - slang_translation_unit_construct (unit); - unit->type = type; + /* check the syntax */ if (!grammar_fast_check (id, (const byte *) source + start, &prod, &size, 65536)) { char buf[1024]; @@ -1943,19 +2037,13 @@ static int compile_with_grammar (grammar id, const char *source, slang_translati slang_info_log_error (log, buf); return 0; } - C.I = prod; - C.L = log; - if (!check_revision (&C)) + + if (!compile_binary (prod, unit, type, log, builtins)) { grammar_alloc_free (prod); return 0; } - if (!parse_translation_unit (&C, unit)) - { - slang_translation_unit_destruct (unit); - grammar_alloc_free (prod); - return 0; - } + grammar_alloc_free (prod); return 1; } @@ -1964,11 +2052,30 @@ static const char *slang_shader_syn = #include "library/slang_shader_syn.h" ; +static const byte slang_core_gc_bin[] = { +#include "library/slang_core_gc_bin.h" +}; + +static const byte slang_common_builtin_gc_bin[] = { +#include "library/slang_common_builtin_gc_bin.h" +}; + +static const byte slang_fragment_builtin_gc_bin[] = { +#include "library/slang_fragment_builtin_gc_bin.h" +}; + +static const byte slang_vertex_builtin_gc_bin[] = { +#include "library/slang_vertex_builtin_gc_bin.h" +}; + int _slang_compile (const char *source, slang_translation_unit *unit, slang_unit_type type, slang_info_log *log) { grammar id; + slang_translation_unit builtin_units[3]; + slang_translation_unit *builtins = NULL; + /* load slang grammar */ id = grammar_load_from_text ((const byte *) slang_shader_syn); if (id == 0) { @@ -1979,18 +2086,79 @@ int _slang_compile (const char *source, slang_translation_unit *unit, slang_unit return 0; } - grammar_set_reg8 (id, (const byte *) "parsing_builtin", 1); - if (type == slang_unit_fragment_shader) + /* set shader type - the syntax is slightly different for different shaders */ + if (type == slang_unit_fragment_shader || type == slang_unit_fragment_builtin) grammar_set_reg8 (id, (const byte *) "shader_type", 1); else grammar_set_reg8 (id, (const byte *) "shader_type", 2); - if (!compile_with_grammar (id, source, unit, type, log)) + /* enable language extensions */ + grammar_set_reg8 (id, (const byte *) "parsing_builtin", 1); + + /* if parsing user-specified shader, load built-in library */ + if (type == slang_unit_fragment_shader || type == slang_unit_vertex_shader) { + if (!compile_binary (slang_core_gc_bin, builtin_units, + slang_unit_fragment_builtin, log, NULL)) + { + grammar_destroy (id); + return 0; + } + if (!compile_binary (slang_common_builtin_gc_bin, builtin_units + 1, + slang_unit_fragment_builtin, log, NULL)) + { + slang_translation_unit_destruct (builtin_units); + grammar_destroy (id); + return 0; + } + if (type == slang_unit_fragment_shader) + { + if (!compile_binary (slang_fragment_builtin_gc_bin, builtin_units + 2, + slang_unit_fragment_builtin, log, NULL)) + { + slang_translation_unit_destruct (builtin_units); + slang_translation_unit_destruct (builtin_units + 1); + grammar_destroy (id); + return 0; + } + } + else if (type == slang_unit_vertex_shader) + { + if (!compile_binary (slang_vertex_builtin_gc_bin, builtin_units + 2, + slang_unit_vertex_builtin, log, NULL)) + { + slang_translation_unit_destruct (builtin_units); + slang_translation_unit_destruct (builtin_units + 1); + grammar_destroy (id); + return 0; + } + } + + /* disable language extensions */ + grammar_set_reg8 (id, (const byte *) "parsing_builtin", 0); + builtins = builtin_units; + } + + /* compile the actual shader - pass-in built-in library for external shader */ + if (!compile_with_grammar (id, source, unit, type, log, builtins)) + { + if (type == slang_unit_fragment_shader || type == slang_unit_vertex_shader) + { + slang_translation_unit_destruct (builtin_units); + slang_translation_unit_destruct (builtin_units + 1); + slang_translation_unit_destruct (builtin_units + 2); + } grammar_destroy (id); return 0; } + /* destroy built-in library */ + if (type == slang_unit_fragment_shader || type == slang_unit_vertex_shader) + { + slang_translation_unit_destruct (builtin_units); + slang_translation_unit_destruct (builtin_units + 1); + slang_translation_unit_destruct (builtin_units + 2); + } grammar_destroy (id); return 1; } diff --git a/src/mesa/shader/slang/slang_compile.h b/src/mesa/shader/slang/slang_compile.h index 0458f3a2b2a..25a0ef8ad81 100644 --- a/src/mesa/shader/slang/slang_compile.h +++ b/src/mesa/shader/slang/slang_compile.h @@ -214,17 +214,22 @@ typedef struct slang_function_scope_ typedef enum slang_unit_type_ { slang_unit_fragment_shader, - slang_unit_vertex_shader + slang_unit_vertex_shader, + slang_unit_fragment_builtin, + slang_unit_vertex_builtin } slang_unit_type; typedef struct slang_translation_unit_ { - slang_variable_scope *globals; + slang_variable_scope globals; slang_function_scope functions; - slang_struct_scope *structs; + slang_struct_scope structs; slang_unit_type type; } slang_translation_unit; +void slang_translation_unit_construct (slang_translation_unit *); +void slang_translation_unit_destruct (slang_translation_unit *); + typedef struct slang_info_log_ { char *text;