*/
#include "imports.h"
+#include "context.h"
+#include "program.h"
+#include "prog_parameter.h"
#include "grammar_mesa.h"
+#include "slang_codegen.h"
#include "slang_compile.h"
#include "slang_preprocess.h"
#include "slang_storage.h"
+#include "slang_error.h"
+#include "slang_emit.h"
+#include "slang_vartable.h"
+
+#include "slang_print.h"
/*
* This is a straightforward implementation of the slang front-end
for (i = 0; i < SLANG_BUILTIN_TOTAL; i++)
_slang_code_unit_ctr(&self->builtin[i], self);
_slang_code_unit_ctr(&self->unit, self);
+#if 01
_slang_assembly_file_ctr(&self->assembly);
+#endif
slang_machine_ctr(&self->machine);
self->varpool.next_addr = 0;
slang_atom_pool_construct(&self->atompool);
for (i = 0; i < SLANG_BUILTIN_TOTAL; i++)
_slang_code_unit_dtr(&self->builtin[i]);
_slang_code_unit_dtr(&self->unit);
+#if 01
slang_assembly_file_destruct(&self->assembly);
+#endif
slang_machine_dtr(&self->machine);
slang_atom_pool_destruct(&self->atompool);
slang_export_data_table_dtr(&self->expdata);
log->dont_free_text = 1;
log->text = out_of_memory;
}
+ abort();
}
/* slang_parse_ctx */
int parsing_builtin;
GLboolean global_scope; /**< Is object being declared a global? */
slang_atom_pool *atoms;
+ slang_unit_type type; /**< Vertex vs. Fragment */
} slang_parse_ctx;
/* slang_output_ctx */
slang_assembly_file *assembly;
slang_var_pool *global_pool;
slang_machine *machine;
+ struct gl_program *program;
+ slang_var_table *vartable;
} slang_output_ctx;
/* _slang_compile() */
stru = slang_struct_scope_find(O->structs, a_name, 1);
if (stru == NULL) {
- slang_info_log_error(C->L, "%s: undeclared type name.",
+ slang_info_log_error(C->L, "undeclared type name '%s'",
slang_atom_pool_id(C->atoms, a_name));
return 0;
}
{
if (!parse_type_qualifier(C, &type->qualifier))
return 0;
- return parse_type_specifier(C, O, &type->specifier);
+ if (!parse_type_specifier(C, O, &type->specifier))
+ return 0;
+ return 1;
}
/* operation */
* \param C the parsing context
* \param O the output context
* \param oper the operation we're parsing
- * \param statment which child of the operation is being parsed
+ * \param statement indicates whether parsing a statement, or expression
* \return 1 if success, 0 if error
*/
static int
parse_child_operation(slang_parse_ctx * C, slang_output_ctx * O,
- slang_operation * oper, unsigned int statement)
+ slang_operation * oper, GLboolean statement)
{
slang_operation *ch;
/* grow child array */
- oper->children = (slang_operation *)
- slang_alloc_realloc(oper->children,
- oper->num_children * sizeof(slang_operation),
- (oper->num_children + 1) * sizeof(slang_operation));
- if (oper->children == NULL) {
- slang_info_log_memory(C->L);
- return 0;
- }
-
- ch = &oper->children[oper->num_children];
- if (!slang_operation_construct(ch)) {
- slang_info_log_memory(C->L);
- return 0;
- }
- oper->num_children++;
- /* XXX I guess the 0th "statement" is not really a statement? */
+ ch = slang_operation_grow(&oper->num_children, &oper->children);
if (statement)
return parse_statement(C, O, ch);
return parse_expression(C, O, ch);
/* local variable declaration, individual declarators are stored as
* children identifiers
*/
- oper->type = slang_oper_variable_decl;
+ oper->type = slang_oper_block_no_new_scope;
{
const unsigned int first_var = O->vars->num_variables;
const unsigned int num_vars = O->vars->num_variables - first_var;
unsigned int i;
- oper->children = (slang_operation *)
- slang_alloc_malloc(num_vars * sizeof(slang_operation));
+ oper->num_children = num_vars;
+ oper->children = slang_operation_new(num_vars);
if (oper->children == NULL) {
slang_info_log_memory(C->L);
return 0;
}
- for (oper->num_children = 0; oper->num_children < num_vars;
- oper->num_children++) {
- if (!slang_operation_construct
- (&oper->children[oper->num_children])) {
- slang_info_log_memory(C->L);
- return 0;
- }
- }
for (i = first_var; i < O->vars->num_variables; i++) {
slang_operation *o = &oper->children[i - first_var];
- o->type = slang_oper_identifier;
+ o->type = slang_oper_variable_decl;
o->locals->outer_scope = O->vars;
- o->a_id = O->vars->variables[i].a_name;
+ o->a_id = O->vars->variables[i]->a_name;
}
}
}
op->type = slang_oper_literal_bool;
if (!parse_number(C, &number))
return 0;
- op->literal = (GLfloat) number;
+ op->literal[0] =
+ op->literal[1] =
+ op->literal[2] =
+ op->literal[3] = (GLfloat) number;
break;
case OP_PUSH_INT:
op->type = slang_oper_literal_int;
if (!parse_number(C, &number))
return 0;
- op->literal = (GLfloat) number;
+ op->literal[0] =
+ op->literal[1] =
+ op->literal[2] =
+ op->literal[3] = (GLfloat) number;
break;
case OP_PUSH_FLOAT:
op->type = slang_oper_literal_float;
- if (!parse_float(C, &op->literal))
+ if (!parse_float(C, &op->literal[0]))
return 0;
+ op->literal[1] =
+ op->literal[2] =
+ op->literal[3] = op->literal[0];
break;
case OP_PUSH_IDENTIFIER:
op->type = slang_oper_identifier;
return 0;
}
+#if 111
+ /* if the function returns a value, append a hidden __retVal 'out'
+ * parameter that corresponds to the return value.
+ */
+ if (_slang_function_has_return_value(func)) {
+ slang_variable *p = slang_variable_scope_grow(func->parameters);
+ slang_atom a_retVal = slang_atom_pool_atom(C->atoms, "__retVal");
+ assert(a_retVal);
+ p->a_name = a_retVal;
+ p->type = func->header.type;
+ p->type.qualifier = slang_qual_out;
+ }
+#endif
+
/* function formal parameters and local variables share the same
* scope, so save the information about param count in a seperate
* place also link the scope to the global variable scope so when a
*/
func->param_count = func->parameters->num_variables;
func->parameters->outer_scope = O->vars;
+
return 1;
}
static GLboolean
initialize_global(slang_assemble_ctx * A, slang_variable * var)
{
+#if 01
slang_assembly_file_restore_point point;
+#endif
slang_machine mach;
slang_assembly_local_info save_local = A->local;
slang_operation op_id, op_assign;
GLboolean result;
+#if 01
/* save the current assembly */
if (!slang_assembly_file_restore_point_save(A->file, &point))
return GL_FALSE;
+#endif
/* setup the machine */
mach = *A->mach;
/* put the variable into operation's scope */
op_id.locals->variables =
- (slang_variable *) slang_alloc_malloc(sizeof(slang_variable));
+ (slang_variable **) slang_alloc_malloc(sizeof(slang_variable *));
if (op_id.locals->variables == NULL) {
slang_operation_destruct(&op_id);
return GL_FALSE;
}
op_id.locals->num_variables = 1;
- op_id.locals->variables[0] = *var;
+ op_id.locals->variables[0] = var;
/* construct the assignment expression */
if (!slang_operation_construct(&op_assign)) {
op_assign.children[0] = op_id;
op_assign.children[1] = *var->initializer;
+#if 0 /* this should go away */
/* insert the actual expression */
result = _slang_assemble_operation(A, &op_assign, slang_ref_forbid);
+#else
+ result = 1;
+#endif
/* carefully destroy the operations */
op_assign.num_children = 0;
return GL_FALSE;
/* execute the expression */
+#if 0
if (!_slang_execute2(A->file, &mach))
return GL_FALSE;
+#endif
+#if 01
/* restore the old assembly */
if (!slang_assembly_file_restore_point_load(A->file, &point))
return GL_FALSE;
+#endif
A->local = save_local;
/* now we copy the contents of the initialized variable back to the original machine */
return 0;
}
+#if 1
+ if (C->global_scope) {
+ 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;
+ A.program = O->program;
+#if 0
+ A.codegen = O->codegen;
+#endif
+ A.vartable = O->vartable;
+
+ _slang_codegen_global_variable(&A, var, C->type);
+ }
+#endif
+
/* allocate global address space for a variable with a known size */
if (C->global_scope
&& !(var->type.specifier.type == slang_spec_array
* \param O output context
* \param definition if non-zero expect a definition, else a declaration
* \param parsed_func_ret returns the parsed function
- * \return 1 if success, 0 if failure
+ * \return GL_TRUE if success, GL_FALSE if failure
*/
-static int
+static GLboolean
parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
slang_function ** parsed_func_ret)
{
/* parse function definition/declaration */
if (!slang_function_construct(&parsed_func))
- return 0;
+ return GL_FALSE;
if (definition) {
if (!parse_function_definition(C, O, &parsed_func)) {
slang_function_destruct(&parsed_func);
- return 0;
+ return GL_FALSE;
}
}
else {
if (!parse_function_prototype(C, O, &parsed_func)) {
slang_function_destruct(&parsed_func);
- return 0;
+ return GL_FALSE;
}
}
*/
found_func = slang_function_scope_find(O->funs, &parsed_func, 0);
if (found_func == NULL) {
- /* add the parsed function to the function list */
+ /* New function, add it to the function list */
O->funs->functions =
(slang_function *) slang_alloc_realloc(O->funs->functions,
O->funs->num_functions *
if (O->funs->functions == NULL) {
slang_info_log_memory(C->L);
slang_function_destruct(&parsed_func);
- return 0;
+ return GL_FALSE;
}
O->funs->functions[O->funs->num_functions] = parsed_func;
O->funs->num_functions++;
*parsed_func_ret = &O->funs->functions[O->funs->num_functions - 1];
}
else {
+ /* previously defined or declared */
/* TODO: check function return type qualifiers and specifiers */
if (definition) {
if (found_func->body != NULL) {
parsed_func.header.
a_name));
slang_function_destruct(&parsed_func);
- return 0;
+ return GL_FALSE;
}
/* destroy the existing function declaration and replace it
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;
+ A.program = O->program;
+#if 0
+ A.codegen = O->codegen;
+#endif
+ A.vartable = O->vartable;
+
+ _slang_reset_error();
+
+#if 0
+ printf("*************** Assemble function %s ****\n", (char *) (*parsed_func_ret)->header.a_name);
+ slang_print_var_scope((*parsed_func_ret)->parameters,
+ (*parsed_func_ret)->param_count);
+#endif
+
+#if 0
+ if (!_slang_assemble_function(&A, *parsed_func_ret)) {
+ /* propogate the error message back through the info log */
+ C->L->text = _mesa_strdup(_slang_error_text());
+ C->L->dont_free_text = GL_FALSE;
+ return GL_FALSE;
+ }
+#endif
+
+#if 0
+ printf("**************************************\n");
+#endif
+#if 1
+ _slang_codegen_function(&A, *parsed_func_ret);
+#endif
}
- return 1;
+ return GL_TRUE;
}
/* declaration */
#define EXTERNAL_DECLARATION 2
static GLboolean
-parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit)
+parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
+ struct gl_program *program)
{
slang_output_ctx o;
+ GLboolean success;
/* setup output context */
o.funs = &unit->funs;
o.assembly = &unit->object->assembly;
o.global_pool = &unit->object->varpool;
o.machine = &unit->object->machine;
+ o.program = program;
+ o.vartable = _slang_push_var_table(NULL);
/* parse individual functions and declarations */
while (*C->I != EXTERNAL_NULL) {
case EXTERNAL_FUNCTION_DEFINITION:
{
slang_function *func;
-
- if (!parse_function(C, &o, 1, &func))
- return 0;
+ success = parse_function(C, &o, 1, &func);
}
break;
case EXTERNAL_DECLARATION:
- if (!parse_declaration(C, &o))
- return 0;
+ success = parse_declaration(C, &o);
break;
default:
- return 0;
+ success = GL_FALSE;
+ }
+
+ if (!success) {
+ /* xxx free codegen */
+ _slang_pop_var_table(o.vartable);
+ return GL_FALSE;
}
}
C->I++;
- return 1;
+
+ _slang_pop_var_table(o.vartable);
+ return GL_TRUE;
}
static GLboolean
compile_binary(const byte * prod, slang_code_unit * unit,
slang_unit_type type, slang_info_log * infolog,
- slang_code_unit * builtin, slang_code_unit * downlink)
+ slang_code_unit * builtin, slang_code_unit * downlink,
+ struct gl_program *program)
{
slang_parse_ctx C;
C.parsing_builtin = (builtin == NULL);
C.global_scope = GL_TRUE;
C.atoms = &unit->object->atompool;
+ C.type = type;
if (!check_revision(&C))
return GL_FALSE;
}
/* parse translation unit */
- return parse_code_unit(&C, unit);
+ return parse_code_unit(&C, unit, program);
}
static GLboolean
compile_with_grammar(grammar id, const char *source, slang_code_unit * unit,
slang_unit_type type, slang_info_log * infolog,
- slang_code_unit * builtin)
+ slang_code_unit * builtin,
+ struct gl_program *program)
{
byte *prod;
GLuint size, start, version;
}
/* Finally check the syntax and generate its binary representation. */
- if (!grammar_fast_check
- (id, (const byte *) (slang_string_cstr(&preprocessed)), &prod, &size,
+ if (!grammar_fast_check(id,
+ (const byte *) (slang_string_cstr(&preprocessed)),
+ &prod, &size,
65536)) {
char buf[1024];
GLint pos;
slang_string_free(&preprocessed);
grammar_get_last_error((byte *) (buf), sizeof(buf), &pos);
slang_info_log_error(infolog, buf);
- return GL_FALSE;
+ RETURN_ERROR("syntax error (possibly in library code)", 0);
}
slang_string_free(&preprocessed);
/* Syntax is okay - translate it to internal representation. */
- if (!compile_binary
- (prod, unit, type, infolog, builtin,
- &builtin[SLANG_BUILTIN_TOTAL - 1])) {
+ if (!compile_binary(prod, unit, type, infolog, builtin,
+ &builtin[SLANG_BUILTIN_TOTAL - 1],
+ program)) {
grammar_alloc_free(prod);
return GL_FALSE;
}
};
#if defined(USE_X86_ASM) || defined(SLANG_X86)
+foo
static const byte slang_builtin_vec4_gc[] = {
#include "library/slang_builtin_vec4_gc.h"
};
static GLboolean
compile_object(grammar * id, const char *source, slang_code_object * object,
- slang_unit_type type, slang_info_log * infolog)
+ slang_unit_type type, slang_info_log * infolog,
+ struct gl_program *program)
{
slang_code_unit *builtins = NULL;
/* 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, &object->builtin[SLANG_BUILTIN_CORE],
- slang_unit_fragment_builtin, infolog, NULL, NULL))
+ if (!compile_binary(slang_core_gc,
+ &object->builtin[SLANG_BUILTIN_CORE],
+ slang_unit_fragment_builtin, infolog,
+ NULL, NULL, NULL))
return GL_FALSE;
/* compile common functions and variables, link to core */
- if (!compile_binary
- (slang_common_builtin_gc, &object->builtin[SLANG_BUILTIN_COMMON],
- slang_unit_fragment_builtin, infolog, NULL,
- &object->builtin[SLANG_BUILTIN_CORE]))
+ if (!compile_binary(slang_common_builtin_gc,
+ &object->builtin[SLANG_BUILTIN_COMMON],
+ slang_unit_fragment_builtin, infolog, NULL,
+ &object->builtin[SLANG_BUILTIN_CORE], NULL))
return GL_FALSE;
/* compile target-specific functions and variables, link to common */
if (type == slang_unit_fragment_shader) {
- if (!compile_binary
- (slang_fragment_builtin_gc,
- &object->builtin[SLANG_BUILTIN_TARGET],
- slang_unit_fragment_builtin, infolog, NULL,
- &object->builtin[SLANG_BUILTIN_COMMON]))
+ if (!compile_binary(slang_fragment_builtin_gc,
+ &object->builtin[SLANG_BUILTIN_TARGET],
+ slang_unit_fragment_builtin, infolog, NULL,
+ &object->builtin[SLANG_BUILTIN_COMMON], NULL))
return GL_FALSE;
}
else if (type == slang_unit_vertex_shader) {
- if (!compile_binary
- (slang_vertex_builtin_gc, &object->builtin[SLANG_BUILTIN_TARGET],
- slang_unit_vertex_builtin, infolog, NULL,
- &object->builtin[SLANG_BUILTIN_COMMON]))
+ if (!compile_binary(slang_vertex_builtin_gc,
+ &object->builtin[SLANG_BUILTIN_TARGET],
+ slang_unit_vertex_builtin, infolog, NULL,
+ &object->builtin[SLANG_BUILTIN_COMMON], NULL))
return GL_FALSE;
}
#if defined(USE_X86_ASM) || defined(SLANG_X86)
/* compile x86 4-component vector overrides, link to target */
- if (!compile_binary
- (slang_builtin_vec4_gc, &object->builtin[SLANG_BUILTIN_VEC4],
- slang_unit_fragment_builtin, infolog, NULL,
- &object->builtin[SLANG_BUILTIN_TARGET]))
+ if (!compile_binary(slang_builtin_vec4_gc,
+ &object->builtin[SLANG_BUILTIN_VEC4],
+ slang_unit_fragment_builtin, infolog, NULL,
+ &object->builtin[SLANG_BUILTIN_TARGET]))
return GL_FALSE;
#endif
/* disable language extensions */
+#if NEW_SLANG /* allow-built-ins */
+ grammar_set_reg8(*id, (const byte *) "parsing_builtin", 1);
+#else
grammar_set_reg8(*id, (const byte *) "parsing_builtin", 0);
+#endif
builtins = object->builtin;
}
/* compile the actual shader - pass-in built-in library for external shader */
return compile_with_grammar(*id, source, &object->unit, type, infolog,
- builtins);
+ builtins, program);
}
-GLboolean
-_slang_compile(const char *source, slang_code_object * object,
- slang_unit_type type, slang_info_log * infolog)
+
+#if 0
+static void
+slang_create_uniforms(const slang_export_data_table *exports,
+ struct gl_program *program)
+{
+ /* XXX only add uniforms that are actually going to get used */
+ GLuint i;
+ for (i = 0; i < exports->count; i++) {
+ if (exports->entries[i].access == slang_exp_uniform) {
+ const char *name = (char *) exports->entries[i].quant.name;
+ GLint j = _mesa_add_uniform(program->Parameters, name, 4);
+ assert(j >= 0);
+ }
+ }
+}
+#endif
+
+
+static GLboolean
+compile_shader(GLcontext *ctx, slang_code_object * object,
+ slang_unit_type type, slang_info_log * infolog,
+ struct gl_shader *shader)
{
+ struct gl_program *program = shader->Programs[0];
GLboolean success;
grammar id = 0;
+ assert(program);
+
_slang_code_object_dtr(object);
_slang_code_object_ctr(object);
- success = compile_object(&id, source, object, type, infolog);
+ success = compile_object(&id, shader->Source, object, type, infolog, program);
if (id != 0)
grammar_destroy(id);
if (!success)
if (!_slang_build_export_data_table(&object->expdata, &object->unit.vars))
return GL_FALSE;
- if (!_slang_build_export_code_table
- (&object->expcode, &object->unit.funs, &object->unit))
+ if (!_slang_build_export_code_table(&object->expcode, &object->unit.funs,
+ &object->unit))
return GL_FALSE;
-#if defined(USE_X86_ASM) || defined(SLANG_X86)
- /* XXX: lookup the @main label */
- if (!_slang_x86_codegen
- (&object->machine, &object->assembly,
- object->expcode.entries[0].address))
- return GL_FALSE;
+#if NEW_SLANG
+ {
+ slang_create_uniforms(&object->expdata, shader);
+ _mesa_print_program(program);
+ _mesa_print_program_parameters(ctx, program);
+ }
#endif
return GL_TRUE;
}
+
+
+
+GLboolean
+_slang_compile(GLcontext *ctx, struct gl_shader *shader)
+{
+ GLboolean success;
+ slang_info_log info_log;
+ slang_code_object obj;
+ slang_unit_type type;
+
+ if (shader->Type == GL_VERTEX_SHADER) {
+ type = slang_unit_vertex_shader;
+ }
+ else {
+ assert(shader->Type == GL_FRAGMENT_SHADER);
+ type = slang_unit_fragment_shader;
+ }
+
+ /* XXX temporary hack */
+ if (!shader->Programs) {
+ GLenum progTarget;
+ if (shader->Type == GL_VERTEX_SHADER)
+ progTarget = GL_VERTEX_PROGRAM_ARB;
+ else
+ progTarget = GL_FRAGMENT_PROGRAM_ARB;
+ shader->Programs
+ = (struct gl_program **) malloc(sizeof(struct gl_program*));
+ shader->Programs[0] = _mesa_new_program(ctx, progTarget, 1);
+ shader->NumPrograms = 1;
+
+ shader->Programs[0]->Parameters = _mesa_new_parameter_list();
+ shader->Programs[0]->Varying = _mesa_new_parameter_list();
+ shader->Programs[0]->Attributes = _mesa_new_parameter_list();
+ }
+
+ slang_info_log_construct(&info_log);
+ _slang_code_object_ctr(&obj);
+
+ success = compile_shader(ctx, &obj, type, &info_log, shader);
+
+ if (success) {
+#if 0
+ slang_create_uniforms(&object->expdata, shader);
+ _mesa_print_program(program);
+ _mesa_print_program_parameters(ctx, program);
+#endif
+ }
+ else {
+ /* XXX more work on info log needed here */
+ if (info_log.text) {
+ if (shader->InfoLog) {
+ free(shader->InfoLog);
+ shader->InfoLog = NULL;
+ }
+ shader->InfoLog = strdup(info_log.text);
+ }
+ }
+
+ slang_info_log_destruct(&info_log);
+ _slang_code_object_dtr(&obj);
+
+ return success;
+}
+