📄 slang_compile.c
字号:
/*
* Mesa 3-D graphics library
* Version: 6.3
*
* Copyright (C) 2005 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_utility.h"
#include "slang_compile.h"
#include "slang_preprocess.h"
#include "slang_storage.h"
#include "slang_assemble.h"
#include "slang_execute.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.
*/
static void slang_variable_construct (slang_variable *);
static int slang_variable_copy (slang_variable *, const slang_variable *);
static void slang_struct_destruct (slang_struct *);
static int slang_struct_equal (const slang_struct *, const slang_struct *);
static void slang_variable_destruct (slang_variable *);
/* slang_type_specifier_type */
/* these must match with slang_type_specifier_type enum */
static const char *type_specifier_type_names[] = {
"void",
"bool",
"bvec2",
"bvec3",
"bvec4",
"int",
"ivec2",
"ivec3",
"ivec4",
"float",
"vec2",
"vec3",
"vec4",
"mat2",
"mat3",
"mat4",
"sampler1D",
"sampler2D",
"sampler3D",
"samplerCube",
"sampler1DShadow",
"sampler2DShadow",
NULL
};
slang_type_specifier_type slang_type_specifier_type_from_string (const char *name)
{
const char **p = type_specifier_type_names;
while (*p != NULL)
{
if (slang_string_compare (*p, name) == 0)
return (slang_type_specifier_type) (p - type_specifier_type_names);
p++;
}
return slang_spec_void;
}
/* slang_type_specifier */
void slang_type_specifier_construct (slang_type_specifier *spec)
{
spec->type = slang_spec_void;
spec->_struct = NULL;
spec->_array = NULL;
}
void slang_type_specifier_destruct (slang_type_specifier *spec)
{
if (spec->_struct != NULL)
{
slang_struct_destruct (spec->_struct);
slang_alloc_free (spec->_struct);
}
if (spec->_array != NULL)
{
slang_type_specifier_destruct (spec->_array);
slang_alloc_free (spec->_array);
}
}
int slang_type_specifier_copy (slang_type_specifier *x, const slang_type_specifier *y)
{
slang_type_specifier_destruct (x);
slang_type_specifier_construct (x);
x->type = y->type;
if (x->type == slang_spec_struct)
{
x->_struct = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct));
if (x->_struct == NULL)
return 0;
if (!slang_struct_construct_a (x->_struct))
{
slang_alloc_free (x->_struct);
x->_struct = NULL;
return 0;
}
return slang_struct_copy (x->_struct, y->_struct);
}
if (x->type == slang_spec_array)
{
x->_array = (slang_type_specifier *) slang_alloc_malloc (sizeof (slang_type_specifier));
if (x->_array == NULL)
return 0;
slang_type_specifier_construct (x->_array);
return slang_type_specifier_copy (x->_array, y->_array);
}
return 1;
}
int slang_type_specifier_equal (const slang_type_specifier *x, const slang_type_specifier *y)
{
if (x->type != y->type)
return 0;
if (x->type == slang_spec_struct)
return slang_struct_equal (x->_struct, y->_struct);
if (x->type == slang_spec_array)
return slang_type_specifier_equal (x->_array, y->_array);
return 1;
}
/* slang_fully_specified_type */
static void slang_fully_specified_type_construct (slang_fully_specified_type *type)
{
type->qualifier = slang_qual_none;
slang_type_specifier_construct (&type->specifier);
}
static void slang_fully_specified_type_destruct (slang_fully_specified_type *type)
{
slang_type_specifier_destruct (&type->specifier);
}
static int slang_fully_specified_type_copy (slang_fully_specified_type *x,
const slang_fully_specified_type *y)
{
slang_fully_specified_type_construct (x);
slang_fully_specified_type_destruct (x);
x->qualifier = y->qualifier;
return slang_type_specifier_copy (&x->specifier, &y->specifier);
}
/* slang_variable_scope */
static void slang_variable_scope_construct (slang_variable_scope *scope)
{
scope->variables = NULL;
scope->num_variables = 0;
scope->outer_scope = NULL;
}
static void slang_variable_scope_destruct (slang_variable_scope *scope)
{
unsigned int i;
for (i = 0; i < scope->num_variables; i++)
slang_variable_destruct (scope->variables + i);
slang_alloc_free (scope->variables);
}
static int slang_variable_scope_copy (slang_variable_scope *x, const slang_variable_scope *y)
{
unsigned int i;
slang_variable_scope_destruct (x);
slang_variable_scope_construct (x);
x->variables = (slang_variable *) slang_alloc_malloc (y->num_variables * sizeof (
slang_variable));
if (x->variables == NULL)
return 0;
x->num_variables = y->num_variables;
for (i = 0; i < x->num_variables; i++)
slang_variable_construct (x->variables + i);
for (i = 0; i < x->num_variables; i++)
if (!slang_variable_copy (x->variables + i, y->variables + i))
return 0;
x->outer_scope = y->outer_scope;
return 1;
}
/* slang_operation */
int slang_operation_construct_a (slang_operation *oper)
{
oper->type = slang_oper_none;
oper->children = NULL;
oper->num_children = 0;
oper->literal = (float) 0;
oper->identifier = NULL;
oper->locals = (slang_variable_scope *) slang_alloc_malloc (sizeof (slang_variable_scope));
if (oper->locals == NULL)
return 0;
slang_variable_scope_construct (oper->locals);
return 1;
}
void slang_operation_destruct (slang_operation *oper)
{
unsigned int i;
for (i = 0; i < oper->num_children; i++)
slang_operation_destruct (oper->children + i);
slang_alloc_free (oper->children);
slang_alloc_free (oper->identifier);
slang_variable_scope_destruct (oper->locals);
slang_alloc_free (oper->locals);
}
static int slang_operation_copy (slang_operation *x, const slang_operation *y)
{
unsigned int i;
for (i = 0; i < x->num_children; i++)
slang_operation_destruct (x->children + i);
slang_alloc_free (x->children);
x->num_children = 0;
slang_alloc_free (x->identifier);
x->identifier = NULL;
slang_variable_scope_destruct (x->locals);
slang_variable_scope_construct (x->locals);
x->type = y->type;
x->children = (slang_operation *) slang_alloc_malloc (y->num_children * sizeof (
slang_operation));
if (x->children == NULL)
return 0;
for (i = 0; i < y->num_children; i++)
if (!slang_operation_construct_a (x->children + i))
{
unsigned int j;
for (j = 0; j < i; j++)
slang_operation_destruct (x->children + j);
slang_alloc_free (x->children);
x->children = NULL;
return 0;
}
x->num_children = y->num_children;
for (i = 0; i < x->num_children; i++)
if (!slang_operation_copy (x->children + i, y->children + i))
return 0;
x->literal = y->literal;
if (y->identifier != NULL)
{
x->identifier = slang_string_duplicate (y->identifier);
if (x->identifier == NULL)
return 0;
}
if (!slang_variable_scope_copy (x->locals, y->locals))
return 0;
return 1;
}
/* slang_variable */
static void slang_variable_construct (slang_variable *var)
{
slang_fully_specified_type_construct (&var->type);
var->name = NULL;
var->array_size = NULL;
var->initializer = NULL;
var->address = ~0;
}
static void slang_variable_destruct (slang_variable *var)
{
slang_fully_specified_type_destruct (&var->type);
slang_alloc_free (var->name);
if (var->array_size != NULL)
{
slang_operation_destruct (var->array_size);
slang_alloc_free (var->array_size);
}
if (var->initializer != NULL)
{
slang_operation_destruct (var->initializer);
slang_alloc_free (var->initializer);
}
}
static int slang_variable_copy (slang_variable *x, const slang_variable *y)
{
slang_variable_destruct (x);
slang_variable_construct (x);
if (!slang_fully_specified_type_copy (&x->type, &y->type))
return 0;
if (y->name != NULL)
{
x->name = slang_string_duplicate (y->name);
if (x->name == NULL)
return 0;
}
if (y->array_size != NULL)
{
x->array_size = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation));
if (x->array_size == NULL)
return 0;
if (!slang_operation_construct_a (x->array_size))
{
slang_alloc_free (x->array_size);
x->array_size = NULL;
return 0;
}
if (!slang_operation_copy (x->array_size, y->array_size))
return 0;
}
if (y->initializer != NULL)
{
x->initializer = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation));
if (x->initializer == NULL)
return 0;
if (!slang_operation_construct_a (x->initializer))
{
slang_alloc_free (x->initializer);
x->initializer = NULL;
return 0;
}
if (!slang_operation_copy (x->initializer, y->initializer))
return 0;
}
return 1;
}
slang_variable *_slang_locate_variable (slang_variable_scope *scope, const char *name, int all)
{
unsigned int i;
for (i = 0; i < scope->num_variables; i++)
if (slang_string_compare (name, scope->variables[i].name) == 0)
return scope->variables + i;
if (all && scope->outer_scope != NULL)
return _slang_locate_variable (scope->outer_scope, name, 1);
return NULL;
}
/* slang_struct_scope */
static void slang_struct_scope_construct (slang_struct_scope *scope)
{
scope->structs = NULL;
scope->num_structs = 0;
scope->outer_scope = NULL;
}
static void slang_struct_scope_destruct (slang_struct_scope *scope)
{
unsigned int i;
for (i = 0; i < scope->num_structs; i++)
slang_struct_destruct (scope->structs + i);
slang_alloc_free (scope->structs);
}
static int slang_struct_scope_copy (slang_struct_scope *x, const slang_struct_scope *y)
{
unsigned int i;
slang_struct_scope_destruct (x);
slang_struct_scope_construct (x);
x->structs = (slang_struct *) slang_alloc_malloc (y->num_structs * sizeof (slang_struct));
if (x->structs == NULL)
return 0;
x->num_structs = y->num_structs;
for (i = 0; i < x->num_structs; i++)
{
unsigned int j;
if (!slang_struct_construct_a (x->structs + i))
{
for (j = 0; j < i; j++)
slang_struct_destruct (x->structs + j);
slang_alloc_free (x->structs);
x->structs = NULL;
return 0;
}
}
for (i = 0; i < x->num_structs; i++)
if (!slang_struct_copy (x->structs + i, y->structs + i))
return 0;
x->outer_scope = y->outer_scope;
return 1;
}
slang_struct *slang_struct_scope_find (slang_struct_scope *stru, const char *name, int all_scopes)
{
unsigned int i;
for (i = 0; i < stru->num_structs; i++)
if (slang_string_compare (name, stru->structs[i].name) == 0)
return stru->structs + i;
if (all_scopes && stru->outer_scope != NULL)
return slang_struct_scope_find (stru->outer_scope, name, 1);
return NULL;
}
/* slang_struct */
int slang_struct_construct_a (slang_struct *stru)
{
stru->name = NULL;
stru->fields = (slang_variable_scope *) slang_alloc_malloc (sizeof (slang_variable_scope));
if (stru->fields == NULL)
return 0;
slang_variable_scope_construct (stru->fields);
stru->structs = (slang_struct_scope *) slang_alloc_malloc (sizeof (slang_struct_scope));
if (stru->structs == NULL)
{
slang_variable_scope_destruct (stru->fields);
slang_alloc_free (stru->fields);
return 0;
}
slang_struct_scope_construct (stru->structs);
return 1;
}
static void slang_struct_destruct (slang_struct *stru)
{
slang_alloc_free (stru->name);
slang_variable_scope_destruct (stru->fields);
slang_alloc_free (stru->fields);
slang_struct_scope_destruct (stru->structs);
slang_alloc_free (stru->structs);
}
int slang_struct_copy (slang_struct *x, const slang_struct *y)
{
slang_alloc_free (x->name);
x->name = NULL;
slang_variable_scope_destruct (x->fields);
slang_variable_scope_construct (x->fields);
slang_struct_scope_destruct (x->structs);
slang_struct_scope_construct (x->structs);
if (y->name != NULL)
{
x->name = slang_string_duplicate (y->name);
if (x->name == NULL)
return 0;
}
if (!slang_variable_scope_copy (x->fields, y->fields))
return 0;
if (!slang_struct_scope_copy (x->structs, y->structs))
return 0;
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -