📄 slang_compile.c
字号:
/* restore the old assembly */ if (!slang_assembly_file_restore_point_load (A->file, &point)) return GL_FALSE; A->local = save_local; /* now we copy the contents of the initialized variable back to the original machine */ _mesa_memcpy ((GLubyte *) A->mach->mem + var->address, (GLubyte *) mach.mem + var->address, var->size); return GL_TRUE;}/* init declarator list */#define DECLARATOR_NONE 0#define DECLARATOR_NEXT 1/* variable declaration */#define VARIABLE_NONE 0#define VARIABLE_IDENTIFIER 1#define VARIABLE_INITIALIZER 2#define VARIABLE_ARRAY_EXPLICIT 3#define VARIABLE_ARRAY_UNKNOWN 4static int parse_init_declarator (slang_parse_ctx *C, slang_output_ctx *O, const slang_fully_specified_type *type){ slang_variable *var; /* empty init declatator (without name, e.g. "float ;") */ if (*C->I++ == VARIABLE_NONE) return 1; /* make room for the new variable and initialize it */ O->vars->variables = (slang_variable *) slang_alloc_realloc (O->vars->variables, O->vars->num_variables * sizeof (slang_variable), (O->vars->num_variables + 1) * sizeof (slang_variable)); if (O->vars->variables == NULL) { slang_info_log_memory (C->L); return 0; } var = &O->vars->variables[O->vars->num_variables]; if (!slang_variable_construct (var)) return 0; O->vars->num_variables++; /* copy the declarator qualifier type, parse the identifier */ var->global = C->global_scope; var->type.qualifier = type->qualifier; var->a_name = parse_identifier (C); if (var->a_name == SLANG_ATOM_NULL) return 0; 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; 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; var->initializer = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation)); if (var->initializer == NULL) { slang_info_log_memory (C->L); return 0; } if (!slang_operation_construct (var->initializer)) { slang_alloc_free (var->initializer); var->initializer = NULL; slang_info_log_memory (C->L); return 0; } if (!parse_expression (C, O, var->initializer)) return 0; break;#if 0 case VARIABLE_ARRAY_UNKNOWN: /* unsized array - mark it as array and copy the specifier to the array element */ if (!convert_to_array (C, var, &type->specifier)) return GL_FALSE; break;#endif case VARIABLE_ARRAY_EXPLICIT: if (!convert_to_array (C, var, &type->specifier)) return GL_FALSE; if (!parse_array_len (C, O, &var->array_len)) return GL_FALSE; break; default: return 0; } /* allocate global address space for a variable with a known size */ if (C->global_scope && !(var->type.specifier.type == slang_spec_array && var->array_len == 0)) { if (!calculate_var_size (C, O, var)) return GL_FALSE; var->address = slang_var_pool_alloc (O->global_pool, var->size); } /* initialize global variable */ if (C->global_scope && var->initializer != NULL) { slang_assemble_ctx A; A.file = O->assembly; A.mach = O->machine; A.atoms = C->atoms; A.space.funcs = O->funs; A.space.structs = O->structs; A.space.vars = O->vars; if (!initialize_global (&A, var)) return 0; } return 1;}static int parse_init_declarator_list (slang_parse_ctx *C, slang_output_ctx *O){ slang_fully_specified_type type; /* parse the fully specified type, common to all declarators */ if (!slang_fully_specified_type_construct (&type)) return 0; if (!parse_fully_specified_type (C, O, &type)) { slang_fully_specified_type_destruct (&type); return 0; } /* parse declarators, pass-in the parsed type */ do { if (!parse_init_declarator (C, O, &type)) { slang_fully_specified_type_destruct (&type); return 0; } } while (*C->I++ == DECLARATOR_NEXT); slang_fully_specified_type_destruct (&type); return 1;}static int parse_function (slang_parse_ctx *C, slang_output_ctx *O, int definition, slang_function **parsed_func_ret){ slang_function parsed_func, *found_func; /* parse function definition/declaration */ if (!slang_function_construct (&parsed_func)) return 0; if (definition) { if (!parse_function_definition (C, O, &parsed_func)) { slang_function_destruct (&parsed_func); return 0; } } else { if (!parse_function_prototype (C, O, &parsed_func)) { slang_function_destruct (&parsed_func); return 0; } } /* find a function with a prototype matching the parsed one - only the current scope * is being searched to allow built-in function overriding */ found_func = slang_function_scope_find (O->funs, &parsed_func, 0); if (found_func == NULL) { /* add the parsed function to the function list */ O->funs->functions = (slang_function *) slang_alloc_realloc (O->funs->functions, O->funs->num_functions * sizeof (slang_function), (O->funs->num_functions + 1) * sizeof (slang_function)); if (O->funs->functions == NULL) { slang_info_log_memory (C->L); slang_function_destruct (&parsed_func); return 0; } O->funs->functions[O->funs->num_functions] = parsed_func; O->funs->num_functions++; /* return the newly parsed function */ *parsed_func_ret = &O->funs->functions[O->funs->num_functions - 1]; } else { /* TODO: check function return type qualifiers and specifiers */ if (definition) { if (found_func->body != NULL) { slang_info_log_error (C->L, "%s: function already has a body", slang_atom_pool_id (C->atoms, parsed_func.header.a_name)); slang_function_destruct (&parsed_func); return 0; } /* destroy the existing function declaration and replace it with the new one, * remember to save the fixup table */ parsed_func.fixups = found_func->fixups; slang_fixup_table_init (&found_func->fixups); slang_function_destruct (found_func); *found_func = parsed_func; } else { /* another declaration of the same function prototype - ignore it */ slang_function_destruct (&parsed_func); } /* return the found function */ *parsed_func_ret = found_func; } /* assemble the parsed function */ { slang_assemble_ctx A; A.file = O->assembly; A.mach = O->machine; A.atoms = C->atoms; A.space.funcs = O->funs; A.space.structs = O->structs; A.space.vars = O->vars; if (!_slang_assemble_function (&A, *parsed_func_ret)) return 0; } return 1;}/* declaration */#define DECLARATION_FUNCTION_PROTOTYPE 1#define DECLARATION_INIT_DECLARATOR_LIST 2static int 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; break; case DECLARATION_FUNCTION_PROTOTYPE: { slang_function *dummy_func; if (!parse_function (C, O, 0, &dummy_func)) return 0; } break; default: return 0; } return 1;}/* external declaration */#define EXTERNAL_NULL 0#define EXTERNAL_FUNCTION_DEFINITION 1#define EXTERNAL_DECLARATION 2static int parse_translation_unit (slang_parse_ctx *C, slang_translation_unit *unit){ slang_output_ctx o; /* setup output context */ o.funs = &unit->functions; o.structs = &unit->structs; o.vars = &unit->globals; o.assembly = unit->assembly; o.global_pool = unit->global_pool; o.machine = unit->machine; /* parse individual functions and declarations */ while (*C->I != EXTERNAL_NULL) { switch (*C->I++) { case EXTERNAL_FUNCTION_DEFINITION: { slang_function *func; if (!parse_function (C, &o, 1, &func)) return 0; } break; case EXTERNAL_DECLARATION: if (!parse_declaration (C, &o)) return 0; break; default: return 0; } } C->I++; return 1;}#define BUILTIN_CORE 0#define BUILTIN_COMMON 1#define BUILTIN_TARGET 2#define BUILTIN_TOTAL 3static int compile_binary (const byte *prod, slang_translation_unit *unit, slang_unit_type type, slang_info_log *log, slang_translation_unit *builtins, slang_assembly_file *file, slang_var_pool *pool, slang_machine *mach, slang_translation_unit *downlink, slang_atom_pool *atoms){ slang_parse_ctx C; /* create translation unit object */ if (file != NULL) { if (!slang_translation_unit_construct2 (unit, file, pool, mach, atoms)) return 0; unit->type = type; } /* set-up parse context */ C.I = prod; C.L = log; C.parsing_builtin = builtins == NULL; C.global_scope = 1; C.atoms = unit->atom_pool; if (!check_revision (&C)) { slang_translation_unit_destruct (unit); return 0; } if (downlink != NULL) { unit->functions.outer_scope = &downlink->functions; unit->globals.outer_scope = &downlink->globals; unit->structs.outer_scope = &downlink->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_translation_unit *builtins){ byte *prod; unsigned int size, start, version; /* retrieve version */ if (!_slang_preprocess_version (source, &version, &start, log)) return 0; /* check the syntax and generate its binary representation */ if (!grammar_fast_check (id, (const byte *) source + start, &prod, &size, 65536)) { char buf[1024]; unsigned int pos; grammar_get_last_error ( (unsigned char*) buf, 1024, (int*) &pos); slang_info_log_error (log, buf); return 0; } /* syntax is okay - translate it to internal representation */ if (!compile_binary (prod, unit, type, log, builtins, NULL, NULL, NULL, &builtins[BUILTIN_TARGET], NULL)) { grammar_alloc_free (prod); return 0; } grammar_alloc_free (prod); return 1;}static const char *slang_shader_syn =#include "library/slang_shader_syn.h";static const byte slang_core_gc[] = {#include "library/slang_core_gc.h"};static const byte slang_common_builtin_gc[] = {#include "library/slang_common_builtin_gc.h"};static const byte slang_fragment_builtin_gc[] = {#include "library/slang_fragment_builtin_gc.h"};static const byte slang_vertex_builtin_gc[] = {#include "library/slang_vertex_builtin_gc.h"};static int compile (grammar *id, slang_translation_unit *builtin_units, int *compiled, const char *source, slang_translation_unit *unit, slang_unit_type type, slang_info_log *log){ slang_translation_unit *builtins = NULL; /* load slang grammar */ *id = grammar_load_from_text ((const byte *) (slang_shader_syn)); if (*id == 0) { byte buf[1024]; int pos; grammar_get_last_error (buf, 1024, &pos); slang_info_log_error (log, (const char *) (buf)); return 0; } /* 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); /* 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) { /* compile core functionality first */ if (!compile_binary (slang_core_gc, &builtin_units[BUILTIN_CORE], slang_unit_fragment_builtin, log, NULL, unit->assembly, unit->global_pool, unit->machine, NULL, unit->atom_pool)) return 0; compiled[BUILTIN_CORE] = 1; /* compile common functions and variables, link to core */ if (!compile_binary (slang_common_builtin_gc, &builtin_units[BUILTIN_COMMON], slang_unit_fragment_builtin, log, NULL, unit->assembly, unit->global_pool, unit->machine, &builtin_units[BUILTIN_CORE], unit->atom_pool)) return 0; compiled[BUILTIN_COMMON] = 1; /* compile target-specific functions and variables, link to common */ if (type == slang_unit_fragment_shader) { if (!compile_binary (slang_fragment_builtin_gc, &builtin_units[BUILTIN_TARGET], slang_unit_fragment_builtin, log, NULL, unit->assembly, unit->global_pool, unit->machine, &builtin_units[BUILTIN_COMMON], unit->atom_pool)) return 0; } else if (type == slang_unit_vertex_shader) { if (!compile_binary (slang_vertex_builtin_gc, &builtin_units[BUILTIN_TARGET], slang_unit_vertex_builtin, log, NULL, unit->assembly, unit->global_pool, unit->machine, &builtin_units[BUILTIN_COMMON], unit->atom_pool)) return 0; } compiled[BUILTIN_TARGET] = 1; /* 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)) return 0; return 1;}int _slang_compile (const char *source, slang_translation_unit *unit, slang_unit_type type, slang_info_log *log){ int success; grammar id = 0;/* slang_translation_unit builtin_units[BUILTIN_TOTAL];*/ slang_translation_unit *builtin_units; int compiled[BUILTIN_TOTAL] = { 0 }; /* create the main unit first */ if (!slang_translation_unit_construct (unit)) return 0; unit->type = type; builtin_units = (slang_translation_unit *) slang_alloc_malloc (BUILTIN_TOTAL * sizeof (slang_translation_unit)); success = compile (&id, builtin_units, compiled, source, unit, type, log); /* destroy built-in library */ /* XXX: free with the unit */ /*if (type == slang_unit_fragment_shader || type == slang_unit_vertex_shader) { int i; for (i = 0; i < BUILTIN_TOTAL; i++) if (compiled[i] != 0) slang_translation_unit_destruct (&builtin_units[i]); }*/ if (id != 0) grammar_destroy (id); if (!success) return 0; unit->exp_data.atoms = unit->atom_pool; if (!_slang_build_export_data_table (&unit->exp_data, &unit->globals)) return 0; unit->exp_code.atoms = unit->atom_pool; if (!_slang_build_export_code_table (&unit->exp_code, &unit->functions, unit)) return 0;#if defined(USE_X86_ASM) || defined(SLANG_X86) /* XXX: lookup the @main label */ if (!_slang_x86_codegen (unit->machine, unit->assembly, unit->exp_code.entries[0].address)) return 0;#endif return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -