📄 slang_compile.c
字号:
/* * Mesa 3-D graphics library * Version: 6.5 * * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *//** * \file slang_compile.c * slang front-end compiler * \author Michal Krol */#include "imports.h"#include "grammar_mesa.h"#include "slang_compile.h"#include "slang_preprocess.h"#include "slang_storage.h"/* * This is a straightforward implementation of the slang front-end compiler. * Lots of error-checking functionality is missing but every well-formed shader source should * compile successfully and execute as expected. However, some semantically ill-formed shaders * may be accepted resulting in undefined behaviour. *//* slang_var_pool */static GLuint slang_var_pool_alloc (slang_var_pool *pool, unsigned int size){ GLuint addr; addr = pool->next_addr; pool->next_addr += size; return addr;}/* slang_translation_unit */int slang_translation_unit_construct (slang_translation_unit *unit){ unit->assembly = (slang_assembly_file *) slang_alloc_malloc (sizeof (slang_assembly_file)); if (unit->assembly == NULL) return 0; if (!slang_assembly_file_construct (unit->assembly)) { slang_alloc_free (unit->assembly); return 0; } unit->global_pool = (slang_var_pool *) slang_alloc_malloc (sizeof (slang_var_pool)); if (unit->global_pool == NULL) { slang_assembly_file_destruct (unit->assembly); slang_alloc_free (unit->assembly); return 0; } unit->global_pool->next_addr = 0; unit->machine = (slang_machine *) slang_alloc_malloc (sizeof (slang_machine)); if (unit->machine == NULL) { slang_alloc_free (unit->global_pool); slang_assembly_file_destruct (unit->assembly); slang_alloc_free (unit->assembly); return 0; } slang_machine_ctr (unit->machine); unit->atom_pool = (slang_atom_pool *) slang_alloc_malloc (sizeof (slang_atom_pool)); if (unit->atom_pool == NULL) { slang_alloc_free (unit->machine); slang_alloc_free (unit->global_pool); slang_assembly_file_destruct (unit->assembly); slang_alloc_free (unit->assembly); return 0; } slang_atom_pool_construct (unit->atom_pool); if (!slang_translation_unit_construct2 (unit, unit->assembly, unit->global_pool, unit->machine, unit->atom_pool)) { slang_alloc_free (unit->atom_pool); slang_alloc_free (unit->machine); slang_alloc_free (unit->global_pool); slang_assembly_file_destruct (unit->assembly); slang_alloc_free (unit->assembly); return 0; } unit->free_assembly = 1; unit->free_global_pool = 1; unit->free_machine = 1; unit->free_atom_pool = 1; return 1;}int slang_translation_unit_construct2 (slang_translation_unit *unit, slang_assembly_file *file, slang_var_pool *pool, struct slang_machine_ *mach, slang_atom_pool *atoms){ if (!slang_variable_scope_construct (&unit->globals)) return 0; if (!slang_function_scope_construct (&unit->functions)) { slang_variable_scope_destruct (&unit->globals); return 0; } if (!slang_struct_scope_construct (&unit->structs)) { slang_variable_scope_destruct (&unit->globals); slang_function_scope_destruct (&unit->functions); return 0; } unit->assembly = file; unit->free_assembly = 0; unit->global_pool = pool; unit->free_global_pool = 0; unit->machine = mach; unit->free_machine = 0; unit->atom_pool = atoms; unit->free_atom_pool = 0; slang_export_data_table_ctr (&unit->exp_data); slang_export_code_table_ctr (&unit->exp_code); return 1;}void slang_translation_unit_destruct (slang_translation_unit *unit){ slang_variable_scope_destruct (&unit->globals); slang_function_scope_destruct (&unit->functions); slang_struct_scope_destruct (&unit->structs); if (unit->free_assembly) { slang_assembly_file_destruct (unit->assembly); slang_alloc_free (unit->assembly); } if (unit->free_global_pool) slang_alloc_free (unit->global_pool); if (unit->free_machine) { slang_machine_dtr (unit->machine); slang_alloc_free (unit->machine); } if (unit->free_atom_pool) { slang_atom_pool_destruct (unit->atom_pool); slang_alloc_free (unit->atom_pool); } slang_export_data_table_dtr (&unit->exp_data); slang_export_code_table_ctr (&unit->exp_code);}/* slang_info_log */static char *out_of_memory = "error: out of memory\n";void slang_info_log_construct (slang_info_log *log){ log->text = NULL; log->dont_free_text = 0;}void slang_info_log_destruct (slang_info_log *log){ if (!log->dont_free_text) slang_alloc_free (log->text);}static int slang_info_log_message (slang_info_log *log, const char *prefix, const char *msg){ unsigned int new_size; if (log->dont_free_text) return 0; new_size = slang_string_length (prefix) + 3 + slang_string_length (msg); if (log->text != NULL) { unsigned int text_len = slang_string_length (log->text); log->text = (char *) slang_alloc_realloc (log->text, text_len + 1, new_size + text_len + 1); } else { log->text = (char *) slang_alloc_malloc (new_size + 1); if (log->text != NULL) log->text[0] = '\0'; } if (log->text == NULL) return 0; slang_string_concat (log->text, prefix); slang_string_concat (log->text, ": "); slang_string_concat (log->text, msg); slang_string_concat (log->text, "\n"); return 1;}int slang_info_log_error (slang_info_log *log, const char *msg, ...){ va_list va; char buf[1024]; va_start (va, msg); _mesa_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, ...){ va_list va; char buf[1024]; va_start (va, msg); _mesa_vsprintf (buf, msg, va); if (slang_info_log_message (log, "warning", buf)) return 1; slang_info_log_memory (log); va_end (va); return 0;}void slang_info_log_memory (slang_info_log *log){ if (!slang_info_log_message (log, "error", "out of memory")) { log->dont_free_text = 1; log->text = out_of_memory; }}/* slang_parse_ctx */typedef struct slang_parse_ctx_{ const byte *I; slang_info_log *L; int parsing_builtin; int global_scope; slang_atom_pool *atoms;} slang_parse_ctx;/* slang_output_ctx */typedef struct slang_output_ctx_{ slang_variable_scope *vars; slang_function_scope *funs; slang_struct_scope *structs; slang_assembly_file *assembly; slang_var_pool *global_pool; slang_machine *machine;} slang_output_ctx;/* _slang_compile() */static void parse_identifier_str (slang_parse_ctx *C, char **id){ *id = (char *) C->I; C->I += _mesa_strlen (*id) + 1;}static slang_atom parse_identifier (slang_parse_ctx *C){ const char *id; id = (const char *) C->I; C->I += _mesa_strlen (id) + 1; return slang_atom_pool_atom (C->atoms, id);}static int parse_number (slang_parse_ctx *C, int *number){ const int radix = (int) (*C->I++); *number = 0; while (*C->I != '\0') { int digit; if (*C->I >= '0' && *C->I <= '9') digit = (int) (*C->I - '0'); else if (*C->I >= 'A' && *C->I <= 'Z') digit = (int) (*C->I - 'A') + 10; else digit = (int) (*C->I - 'a') + 10; *number = *number * radix + digit; C->I++; } C->I++; if (*number > 65535) slang_info_log_warning (C->L, "%d: literal integer overflow", *number); return 1;}static int parse_float (slang_parse_ctx *C, float *number){ char *integral = NULL; char *fractional = NULL; char *exponent = NULL; char *whole = NULL; parse_identifier_str (C, &integral); parse_identifier_str (C, &fractional); parse_identifier_str (C, &exponent); whole = (char *) (slang_alloc_malloc ((_mesa_strlen (integral) + _mesa_strlen (fractional) + _mesa_strlen (exponent) + 3) * sizeof (char))); if (whole == NULL) { slang_info_log_memory (C->L); return 0; } slang_string_copy (whole, integral); slang_string_concat (whole, "."); slang_string_concat (whole, fractional); slang_string_concat (whole, "E"); slang_string_concat (whole, exponent); *number = (float) (_mesa_strtod(whole, (char **)NULL)); slang_alloc_free (whole); return 1;}/* revision number - increment after each change affecting emitted output */#define REVISION 3static int check_revision (slang_parse_ctx *C){ if (*C->I != REVISION) { slang_info_log_error (C->L, "internal compiler error"); return 0; } C->I++; return 1;}static int parse_statement (slang_parse_ctx *, slang_output_ctx *, slang_operation *);static int parse_expression (slang_parse_ctx *, slang_output_ctx *, slang_operation *);static int parse_type_specifier (slang_parse_ctx *, slang_output_ctx *, slang_type_specifier *);static GLboolean parse_array_len (slang_parse_ctx *C, slang_output_ctx *O, GLuint *len){ slang_operation array_size; slang_assembly_name_space space; GLboolean result; if (!slang_operation_construct (&array_size)) return GL_FALSE; if (!parse_expression (C, O, &array_size)) { slang_operation_destruct (&array_size); return GL_FALSE; } space.funcs = O->funs; space.structs = O->structs; space.vars = O->vars; result = _slang_evaluate_int (O->assembly, O->machine, &space, &array_size, len, C->atoms); slang_operation_destruct (&array_size); return result;}static GLboolean calculate_var_size (slang_parse_ctx *C, slang_output_ctx *O, slang_variable *var){ slang_storage_aggregate agg; if (!slang_storage_aggregate_construct (&agg)) return GL_FALSE; if (!_slang_aggregate_variable (&agg, &var->type.specifier, var->array_len, O->funs, O->structs, O->vars, O->machine, O->assembly, C->atoms)) { slang_storage_aggregate_destruct (&agg); return GL_FALSE; } var->size = _slang_sizeof_aggregate (&agg); slang_storage_aggregate_destruct (&agg); return GL_TRUE;}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 */ var->type.specifier.type = slang_spec_array; var->type.specifier._array = (slang_type_specifier *) slang_alloc_malloc (sizeof ( slang_type_specifier)); if (var->type.specifier._array == NULL) { slang_info_log_memory (C->L); return GL_FALSE; } slang_type_specifier_ctr (var->type.specifier._array); return slang_type_specifier_copy (var->type.specifier._array, sp);}/* structure field */#define FIELD_NONE 0#define FIELD_NEXT 1#define FIELD_ARRAY 2static GLboolean parse_struct_field_var (slang_parse_ctx *C, slang_output_ctx *O, slang_variable *var, const slang_type_specifier *sp){ var->a_name = parse_identifier (C); if (var->a_name == SLANG_ATOM_NULL) return GL_FALSE; switch (*C->I++) { case FIELD_NONE: if (!slang_type_specifier_copy (&var->type.specifier, sp)) return GL_FALSE; break; case FIELD_ARRAY: if (!convert_to_array (C, var, sp)) return GL_FALSE; if (!parse_array_len (C, O, &var->array_len)) return GL_FALSE; break; default: return GL_FALSE; } return calculate_var_size (C, O, var);}static int parse_struct_field (slang_parse_ctx *C, slang_output_ctx *O, slang_struct *st, slang_type_specifier *sp){ slang_output_ctx o = *O; o.structs = st->structs; if (!parse_type_specifier (C, &o, sp)) return 0; do { slang_variable *var; st->fields->variables = (slang_variable *) slang_alloc_realloc (st->fields->variables, st->fields->num_variables * sizeof (slang_variable), (st->fields->num_variables + 1) * sizeof (slang_variable)); if (st->fields->variables == NULL) { slang_info_log_memory (C->L); return 0; } var = &st->fields->variables[st->fields->num_variables]; if (!slang_variable_construct (var)) return 0; st->fields->num_variables++; if (!parse_struct_field_var (C, &o, var, sp)) return 0; } while (*C->I++ != FIELD_NONE); return 1;}static int parse_struct (slang_parse_ctx *C, slang_output_ctx *O, slang_struct **st){ slang_atom a_name; const char *name; /* 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; 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; } /* set-up a new struct */ *st = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct)); if (*st == NULL) { slang_info_log_memory (C->L); return 0; } if (!slang_struct_construct (*st)) { slang_alloc_free (*st); *st = NULL; slang_info_log_memory (C->L); return 0; } (**st).a_name = a_name; (**st).structs->outer_scope = O->structs; /* parse individual struct fields */ do { slang_type_specifier sp; slang_type_specifier_ctr (&sp); if (!parse_struct_field (C, O, *st, &sp)) { slang_type_specifier_dtr (&sp); return 0; } slang_type_specifier_dtr (&sp); } while (*C->I++ != FIELD_NONE); /* if named struct, copy it to current scope */ if (name[0] != '\0') { slang_struct *s; O->structs->structs = (slang_struct *) slang_alloc_realloc (O->structs->structs, O->structs->num_structs * sizeof (slang_struct), (O->structs->num_structs + 1) * sizeof (slang_struct)); if (O->structs->structs == NULL) { slang_info_log_memory (C->L); return 0; } s = &O->structs->structs[O->structs->num_structs];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -