📄 slang_compile.c
字号:
#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 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_function_scope *funcs)
{
slang_variable *var;
if (*C->I++ == VARIABLE_NONE)
return 1;
vars->variables = (slang_variable *) slang_alloc_realloc (vars->variables,
vars->num_variables * sizeof (slang_variable),
(vars->num_variables + 1) * sizeof (slang_variable));
if (vars->variables == NULL)
{
slang_info_log_memory (C->L);
return 0;
}
var = vars->variables + vars->num_variables;
vars->num_variables++;
slang_variable_construct (var);
var->type.qualifier = type->qualifier;
if (!parse_identifier (C, &var->name))
return 0;
switch (*C->I++)
{
case VARIABLE_NONE:
if (!slang_type_specifier_copy (&var->type.specifier, &type->specifier))
return 0;
break;
case VARIABLE_INITIALIZER:
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_a (var->initializer))
{
slang_alloc_free (var->initializer);
var->initializer = NULL;
slang_info_log_memory (C->L);
return 0;
}
if (!parse_expression (C, var->initializer, vars, structs, funcs))
return 0;
break;
case VARIABLE_ARRAY_UNKNOWN:
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 0;
}
slang_type_specifier_construct (var->type.specifier._array);
if (!slang_type_specifier_copy (var->type.specifier._array, &type->specifier))
return 0;
break;
case VARIABLE_ARRAY_EXPLICIT:
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 0;
}
slang_type_specifier_construct (var->type.specifier._array);
if (!slang_type_specifier_copy (var->type.specifier._array, &type->specifier))
return 0;
var->array_size = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation));
if (var->array_size == NULL)
{
slang_info_log_memory (C->L);
return 0;
}
if (!slang_operation_construct_a (var->array_size))
{
slang_alloc_free (var->array_size);
var->array_size = NULL;
slang_info_log_memory (C->L);
return 0;
}
if (!parse_expression (C, var->array_size, vars, structs, funcs))
return 0;
break;
default:
return 0;
}
if (!(var->type.specifier.type == slang_spec_array && var->array_size == NULL))
{
slang_storage_aggregate agg;
slang_storage_aggregate_construct (&agg);
if (!_slang_aggregate_variable (&agg, &var->type.specifier, var->array_size, funcs,
structs))
{
slang_storage_aggregate_destruct (&agg);
return 0;
}
slang_storage_aggregate_destruct (&agg);
}
return 1;
}
static int parse_init_declarator_list (slang_parse_ctx *C, slang_variable_scope *vars,
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, funcs))
{
slang_fully_specified_type_destruct (&type);
return 0;
}
do
{
if (!parse_init_declarator (C, &type, vars, structs, funcs))
{
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, int definition, slang_struct_scope *structs,
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, funcs))
{
slang_function_destruct (&parsed_func);
return 0;
}
}
else
{
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 - only the current scope
is being searched to allow built-in function overriding */
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));
if (funcs->functions == NULL)
{
slang_info_log_memory (C->L);
slang_function_destruct (&parsed_func);
return 0;
}
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 */
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",
parsed_func.header.name);
slang_function_destruct (&parsed_func);
return 0;
}
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 */
if (definition)
{
static int x = 0;
static
slang_assembly_file file;
slang_assembly_name_space space;
x++;
if (x == 1)
slang_assembly_file_construct (&file);
space.funcs = funcs;
space.structs = structs;
space.vars = scope;
if (x == 1)
xxx_first (&file);
(**parsed_func_ret).address = file.count;
if (!_slang_assemble_function (&file, *parsed_func_ret, &space))
{
slang_assembly_file_destruct (&file);
return 0;
}
if (slang_string_compare ("main", (**parsed_func_ret).header.name) == 0)
{
xxx_prolog (&file, (**parsed_func_ret).address);
_slang_execute (&file);
slang_assembly_file_destruct (&file);
exit (0);
}
}
return 1;
}
/* declaration */
#define DECLARATION_FUNCTION_PROTOTYPE 1
#define DECLARATION_INIT_DECLARATOR_LIST 2
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, funcs))
return 0;
break;
case DECLARATION_FUNCTION_PROTOTYPE:
if (!parse_function (C, 0, structs, funcs, scope, &dummy_func))
return 0;
break;
default:
return 0;
}
return 1;
}
/* external declaration */
#define EXTERNAL_NULL 0
#define EXTERNAL_FUNCTION_DEFINITION 1
#define EXTERNAL_DECLARATION 2
static int parse_translation_unit (slang_parse_ctx *C, slang_translation_unit *unit)
{
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, &func))
return 0;
break;
case EXTERNAL_DECLARATION:
if (!parse_declaration (C, &unit->globals, &unit->structs, &unit->functions))
return 0;
break;
default:
return 0;
}
}
C->I++;
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_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 */
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;
}
if (!compile_binary (prod, unit, type, log, builtins))
{
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_bin[] = {
#include "library/slang_core_gc_bin.h"
};*/
static const byte slang_core_gc[] = {
#include "library/slang_core_gc.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)
{
char buf[1024];
unsigned int pos;
grammar_get_last_error ( (unsigned char*) buf, 1024, (int*) &pos);
slang_info_log_error (log, 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)
{
/*if (!compile_binary (slang_core_gc_bin, builtin_units,
slang_unit_fragment_builtin, log, NULL))*/
if (!compile_with_grammar (id, (const char*) slang_core_gc, 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)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -