intermediate code generator (not finished);

generic back-end interpreter (interprets directly intermediate code)
This commit is contained in:
Michal Krol 2005-05-19 11:50:53 +00:00
parent e5ff2b94ff
commit 02168254a8
15 changed files with 4059 additions and 77 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,145 @@
/*
* 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.
*/
#if !defined SLANG_ASSEMBLE_H
#define SLANG_ASSEMBLE_H
#include "slang_compile.h"
#if defined __cplusplus
extern "C" {
#endif
typedef enum slang_assembly_type_
{
/* core */
slang_asm_none,
slang_asm_float_copy,
slang_asm_float_move,
slang_asm_float_push,
slang_asm_float_deref,
slang_asm_float_add,
slang_asm_float_multiply,
slang_asm_float_divide,
slang_asm_float_negate,
slang_asm_float_less,
slang_asm_float_equal,
slang_asm_float_to_int,
slang_asm_int_copy,
slang_asm_int_move,
slang_asm_int_push,
slang_asm_int_deref,
slang_asm_int_to_float,
slang_asm_int_to_addr,
slang_asm_bool_copy,
slang_asm_bool_move,
slang_asm_bool_push,
slang_asm_bool_deref,
slang_asm_addr_copy,
slang_asm_addr_push,
slang_asm_addr_deref,
slang_asm_addr_add,
slang_asm_addr_multiply,
slang_asm_jump,
slang_asm_jump_if_zero,
slang_asm_enter,
slang_asm_leave,
slang_asm_local_alloc,
slang_asm_local_free,
slang_asm_local_addr,
slang_asm_call,
slang_asm_return,
slang_asm_discard,
slang_asm_exit,
slang_asm__last
} slang_assembly_type;
typedef struct slang_assembly_
{
slang_assembly_type type;
GLfloat literal;
GLuint param[2];
} slang_assembly;
typedef struct slang_assembly_file_
{
slang_assembly *code;
unsigned int count;
} slang_assembly_file;
void slang_assembly_file_construct (slang_assembly_file *);
void slang_assembly_file_destruct (slang_assembly_file *);
int slang_assembly_file_push (slang_assembly_file *, slang_assembly_type);
int slang_assembly_file_push_label (slang_assembly_file *, slang_assembly_type, GLuint);
int slang_assembly_file_push_label2 (slang_assembly_file *, slang_assembly_type, GLuint, GLuint);
int slang_assembly_file_push_literal (slang_assembly_file *, slang_assembly_type, GLfloat);
typedef struct slang_assembly_flow_control_
{
unsigned int loop_start; /* for "continue" statement */
unsigned int loop_end; /* for "break" statement */
unsigned int function_end; /* for "return" statement */
} slang_assembly_flow_control;
typedef struct slang_assembly_name_space_
{
struct slang_function_scope_ *funcs;
struct slang_struct_scope_ *structs;
struct slang_variable_scope_ *vars;
} slang_assembly_name_space;
slang_function *_slang_locate_function (const char *name, slang_operation *params,
unsigned int num_params, slang_assembly_name_space *space);
int _slang_assemble_function (slang_assembly_file *, struct slang_function_ *,
slang_assembly_name_space *);
typedef struct slang_assembly_stack_info_
{
unsigned int swizzle_mask;
} slang_assembly_stack_info;
int _slang_cleanup_stack (slang_assembly_file *, slang_operation *, int ref,
slang_assembly_name_space *);
typedef struct slang_assembly_local_info_
{
unsigned int ret_size;
unsigned int addr_tmp;
unsigned int swizzle_tmp;
} slang_assembly_local_info;
int _slang_assemble_operation (slang_assembly_file *, struct slang_operation_ *, int reference,
slang_assembly_flow_control *, slang_assembly_name_space *, slang_assembly_local_info *,
slang_assembly_stack_info *);
void xxx_first (slang_assembly_file *);
void xxx_prolog (slang_assembly_file *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,485 @@
/*
* 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_assemble_conditional.c
* slang condtional expressions assembler
* \author Michal Krol
*/
#include "imports.h"
#include "slang_utility.h"
#include "slang_assemble_conditional.h"
#include "slang_assemble.h"
/* _slang_assemble_logicaland() */
int _slang_assemble_logicaland (slang_assembly_file *file, slang_operation *op,
slang_assembly_flow_control *flow, slang_assembly_name_space *space,
slang_assembly_local_info *info)
{
/*
and:
<left-expression>
jumpz zero
<right-expression>
jump end
zero:
push 0
end:
*/
unsigned int zero_jump, end_jump;
slang_assembly_stack_info stk;
/* evaluate left expression */
if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk))
return 0;
/* TODO: inspect stk */
/* jump to pushing 0 if not true */
zero_jump = file->count;
if (!slang_assembly_file_push (file, slang_asm_jump_if_zero))
return 0;
/* evaluate right expression */
if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk))
return 0;
/* TODO: inspect stk */
/* jump to the end of the expression */
end_jump = file->count;
if (!slang_assembly_file_push (file, slang_asm_jump))
return 0;
/* push 0 on stack */
file->code[zero_jump].param[0] = file->count;
if (!slang_assembly_file_push (file, slang_asm_bool_push))
return 0;
/* the end of the expression */
file->code[end_jump].param[0] = file->count;
return 1;
}
/* _slang_assemble_logicalor() */
int _slang_assemble_logicalor (slang_assembly_file *file, slang_operation *op,
slang_assembly_flow_control *flow, slang_assembly_name_space *space,
slang_assembly_local_info *info)
{
/*
or:
<left-expression>
jumpz right
push 1
jump end
right:
<right-expression>
end:
*/
unsigned int right_jump, end_jump;
slang_assembly_stack_info stk;
/* evaluate left expression */
if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk))
return 0;
/* TODO: inspect stk */
/* jump to evaluation of right expression if not true */
right_jump = file->count;
if (!slang_assembly_file_push (file, slang_asm_jump_if_zero))
return 0;
/* push 1 on stack */
if (!slang_assembly_file_push_literal (file, slang_asm_bool_push, 1.0f))
return 0;
/* jump to the end of the expression */
end_jump = file->count;
if (!slang_assembly_file_push (file, slang_asm_jump))
return 0;
/* evaluate right expression */
file->code[right_jump].param[0] = file->count;
if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk))
return 0;
/* TODO: inspect stk */
/* the end of the expression */
file->code[end_jump].param[0] = file->count;
return 1;
}
/* _slang_assemble_select() */
int _slang_assemble_select (slang_assembly_file *file, slang_operation *op,
slang_assembly_flow_control *flow, slang_assembly_name_space *space,
slang_assembly_local_info *info)
{
/*
select:
<condition-expression>
jumpz false
<true-expression>
jump end
false:
<false-expression>
end:
*/
unsigned int cond_jump, end_jump;
slang_assembly_stack_info stk;
/* execute condition expression */
if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk))
return 0;
/* TODO: inspect stk */
/* jump to false expression if not true */
cond_jump = file->count;
if (!slang_assembly_file_push (file, slang_asm_jump_if_zero))
return 0;
/* execute true expression */
if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk))
return 0;
/* TODO: inspect stk */
/* jump to the end of the expression */
end_jump = file->count;
if (!slang_assembly_file_push (file, slang_asm_jump))
return 0;
/* resolve false point */
file->code[cond_jump].param[0] = file->count;
/* execute false expression */
if (!_slang_assemble_operation (file, op->children + 2, 0, flow, space, info, &stk))
return 0;
/* TODO: inspect stk */
/* resolve the end of the expression */
file->code[end_jump].param[0] = file->count;
return 1;
}
/* _slang_assemble_for() */
int _slang_assemble_for (slang_assembly_file *file, slang_operation *op,
slang_assembly_flow_control *flow, slang_assembly_name_space *space,
slang_assembly_local_info *info)
{
/*
for:
<init-statement>
jump start
break:
jump end
continue:
<loop-increment>
start:
<condition-statement>
jumpz end
<loop-body>
jump continue
end:
*/
unsigned int start_jump, end_jump, cond_jump;
unsigned int break_label, cont_label;
slang_assembly_flow_control loop_flow = *flow;
slang_assembly_stack_info stk;
/* execute initialization statement */
if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk))
return 0;
/* TODO: pass-in stk to cleanup */
if (!_slang_cleanup_stack (file, op->children, 0, space))
return 0;
/* skip the "go to the end of the loop" and loop-increment statements */
start_jump = file->count;
if (!slang_assembly_file_push (file, slang_asm_jump))
return 0;
/* go to the end of the loop - break statements are directed here */
break_label = file->count;
end_jump = file->count;
if (!slang_assembly_file_push (file, slang_asm_jump))
return 0;
/* resolve the beginning of the loop - continue statements are directed here */
cont_label = file->count;
/* execute loop-increment statement */
if (!_slang_assemble_operation (file, op->children + 2, 0, flow, space, info, &stk))
return 0;
/* TODO: pass-in stk to cleanup */
if (!_slang_cleanup_stack (file, op->children + 2, 0, space))
return 0;
/* resolve the condition point */
file->code[start_jump].param[0] = file->count;
/* execute condition statement */
if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk))
return 0;
/* TODO: inspect stk */
/* jump to the end of the loop if not true */
cond_jump = file->count;
if (!slang_assembly_file_push (file, slang_asm_jump_if_zero))
return 0;
/* execute loop body */
loop_flow.loop_start = cont_label;
loop_flow.loop_end = break_label;
if (!_slang_assemble_operation (file, op->children + 3, 0, &loop_flow, space, info, &stk))
return 0;
/* TODO: pass-in stk to cleanup */
if (!_slang_cleanup_stack (file, op->children + 3, 0, space))
return 0;
/* go to the beginning of the loop */
if (!slang_assembly_file_push_label (file, slang_asm_jump, cont_label))
return 0;
/* resolve the end of the loop */
file->code[end_jump].param[0] = file->count;
file->code[cond_jump].param[0] = file->count;
return 1;
}
/* _slang_assemble_do() */
int _slang_assemble_do (slang_assembly_file *file, slang_operation *op,
slang_assembly_flow_control *flow, slang_assembly_name_space *space,
slang_assembly_local_info *info)
{
/*
do:
jump start
break:
jump end
continue:
jump condition
start:
<loop-body>
condition:
<condition-statement>
jumpz end
jump start
end:
*/
unsigned int skip_jump, end_jump, cont_jump, cond_jump;
unsigned int break_label, cont_label;
slang_assembly_flow_control loop_flow = *flow;
slang_assembly_stack_info stk;
/* skip the "go to the end of the loop" and "go to condition" statements */
skip_jump = file->count;
if (!slang_assembly_file_push (file, slang_asm_jump))
return 0;
/* go to the end of the loop - break statements are directed here */
break_label = file->count;
end_jump = file->count;
if (!slang_assembly_file_push (file, slang_asm_jump))
return 0;
/* go to condition - continue statements are directed here */
cont_label = file->count;
cont_jump = file->count;
if (!slang_assembly_file_push (file, slang_asm_jump))
return 0;
/* resolve the beginning of the loop */
file->code[skip_jump].param[0] = file->count;
/* execute loop body */
loop_flow.loop_start = cont_label;
loop_flow.loop_end = break_label;
if (!_slang_assemble_operation (file, op->children, 0, &loop_flow, space, info, &stk))
return 0;
/* TODO: pass-in stk to cleanup */
if (!_slang_cleanup_stack (file, op->children, 0, space))
return 0;
/* resolve condition point */
file->code[cont_jump].param[0] = file->count;
/* execute condition statement */
if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk))
return 0;
/* TODO: pass-in stk to cleanup */
/* jump to the end of the loop if not true */
cond_jump = file->count;
if (!slang_assembly_file_push (file, slang_asm_jump_if_zero))
return 0;
/* jump to the beginning of the loop */
if (!slang_assembly_file_push_label (file, slang_asm_jump, file->code[skip_jump].param[0]))
return 0;
/* resolve the end of the loop */
file->code[end_jump].param[0] = file->count;
file->code[cond_jump].param[0] = file->count;
return 1;
}
/* _slang_assemble_while() */
int _slang_assemble_while (slang_assembly_file *file, slang_operation *op,
slang_assembly_flow_control *flow, slang_assembly_name_space *space,
slang_assembly_local_info *info)
{
/*
while:
jump continue
break:
jump end
continue:
<condition-statement>
jumpz end
<loop-body>
jump continue
end:
*/
unsigned int skip_jump, end_jump, cond_jump;
unsigned int break_label;
slang_assembly_flow_control loop_flow = *flow;
slang_assembly_stack_info stk;
/* skip the "go to the end of the loop" statement */
skip_jump = file->count;
if (!slang_assembly_file_push (file, slang_asm_jump))
return 0;
/* go to the end of the loop - break statements are directed here */
break_label = file->count;
end_jump = file->count;
if (!slang_assembly_file_push (file, slang_asm_jump))
return 0;
/* resolve the beginning of the loop - continue statements are directed here */
file->code[skip_jump].param[0] = file->count;
/* execute condition statement */
if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk))
return 0;
/* TODO: pass-in stk to cleanup */
/* jump to the end of the loop if not true */
cond_jump = file->count;
if (!slang_assembly_file_push (file, slang_asm_jump_if_zero))
return 0;
/* execute loop body */
loop_flow.loop_start = file->code[skip_jump].param[0];
loop_flow.loop_end = break_label;
if (!_slang_assemble_operation (file, op->children + 1, 0, &loop_flow, space, info, &stk))
return 0;
/* TODO: pass-in stk to cleanup */
if (!_slang_cleanup_stack (file, op->children + 1, 0, space))
return 0;
/* jump to the beginning of the loop */
if (!slang_assembly_file_push_label (file, slang_asm_jump, file->code[skip_jump].param[0]))
return 0;
/* resolve the end of the loop */
file->code[end_jump].param[0] = file->count;
file->code[cond_jump].param[0] = file->count;
return 1;
}
/* _slang_assemble_if() */
int _slang_assemble_if (slang_assembly_file *file, slang_operation *op,
slang_assembly_flow_control *flow, slang_assembly_name_space *space,
slang_assembly_local_info *info)
{
/*
if:
<condition-statement>
jumpz else
<true-statement>
jump end
else:
<false-statement>
end:
*/
unsigned int cond_jump, else_jump;
slang_assembly_stack_info stk;
/* execute condition statement */
if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk))
return 0;
/* TODO: pass-in stk to cleanup */
/* jump to false-statement if not true */
cond_jump = file->count;
if (!slang_assembly_file_push (file, slang_asm_jump_if_zero))
return 0;
/* execute true-statement */
if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk))
return 0;
/* TODO: pass-in stk to cleanup */
if (!_slang_cleanup_stack (file, op->children + 1, 0, space))
return 0;
/* skip if-false statement */
else_jump = file->count;
if (!slang_assembly_file_push (file, slang_asm_jump))
return 0;
/* resolve start of false-statement */
file->code[cond_jump].param[0] = file->count;
/* execute false-statement */
if (!_slang_assemble_operation (file, op->children + 2, 0, flow, space, info, &stk))
return 0;
/* TODO: pass-in stk to cleanup */
if (!_slang_cleanup_stack (file, op->children + 2, 0, space))
return 0;
/* resolve end of if-false statement */
file->code[else_jump].param[0] = file->count;
return 1;
}

View file

@ -0,0 +1,66 @@
/*
* 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.
*/
#if !defined SLANG_ASSEMBLE_CONDITIONAL_H
#define SLANG_ASSEMBLE_CONDITIONAL_H
#include "slang_assemble.h"
#if defined __cplusplus
extern "C" {
#endif
int _slang_assemble_logicaland (slang_assembly_file *file, slang_operation *op,
slang_assembly_flow_control *flow, slang_assembly_name_space *space,
slang_assembly_local_info *info);
int _slang_assemble_logicalor (slang_assembly_file *file, slang_operation *op,
slang_assembly_flow_control *flow, slang_assembly_name_space *space,
slang_assembly_local_info *info);
int _slang_assemble_select (slang_assembly_file *file, slang_operation *op,
slang_assembly_flow_control *flow, slang_assembly_name_space *space,
slang_assembly_local_info *info);
int _slang_assemble_for (slang_assembly_file *file, slang_operation *op,
slang_assembly_flow_control *flow, slang_assembly_name_space *space,
slang_assembly_local_info *info);
int _slang_assemble_do (slang_assembly_file *file, slang_operation *op,
slang_assembly_flow_control *flow, slang_assembly_name_space *space,
slang_assembly_local_info *info);
int _slang_assemble_while (slang_assembly_file *file, slang_operation *op,
slang_assembly_flow_control *flow, slang_assembly_name_space *space,
slang_assembly_local_info *info);
int _slang_assemble_if (slang_assembly_file *file, slang_operation *op,
slang_assembly_flow_control *flow, slang_assembly_name_space *space,
slang_assembly_local_info *info);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,333 @@
/*
* 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_assemble_constructor.c
* slang constructor and vector swizzle assembler
* \author Michal Krol
*/
#include "imports.h"
#include "slang_utility.h"
#include "slang_assemble_constructor.h"
#include "slang_assemble_typeinfo.h"
#include "slang_storage.h"
/* _slang_is_swizzle() */
int _slang_is_swizzle (const char *field, unsigned int rows, slang_swizzle *swz)
{
unsigned int i;
int xyzw = 0, rgba = 0, stpq = 0;
/* the swizzle can be at most 4-component long */
swz->num_components = slang_string_length (field);
if (swz->num_components > 4)
return 0;
for (i = 0; i < swz->num_components; i++)
{
/* mark which swizzle group is used */
switch (field[i])
{
case 'x':
case 'y':
case 'z':
case 'w':
xyzw = 1;
break;
case 'r':
case 'g':
case 'b':
case 'a':
rgba = 1;
break;
case 's':
case 't':
case 'p':
case 'q':
stpq = 1;
break;
default:
return 0;
}
/* collect swizzle component */
switch (field[i])
{
case 'x':
case 'r':
case 's':
swz->swizzle[i] = 0;
break;
case 'y':
case 'g':
case 't':
if (rows < 2)
return 0;
swz->swizzle[i] = 1;
break;
case 'z':
case 'b':
case 'p':
if (rows < 3)
return 0;
swz->swizzle[i] = 2;
break;
case 'w':
case 'a':
case 'q':
if (rows < 4)
return 0;
swz->swizzle[i] = 3;
break;
}
}
/* only one swizzle group can be used */
if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq))
return 0;
return 1;
}
/* _slang_is_swizzle_mask() */
int _slang_is_swizzle_mask (const slang_swizzle *swz, unsigned int rows)
{
unsigned int c, i;
if (swz->num_components > rows)
return 0;
c = swz->swizzle[0];
for (i = 1; i < swz->num_components; i++)
{
if (swz->swizzle[i] <= c)
return 0;
c = swz->swizzle[i];
}
return 1;
}
/* _slang_multiply_swizzles() */
void _slang_multiply_swizzles (slang_swizzle *dst, const slang_swizzle *left,
const slang_swizzle *right)
{
unsigned int i;
dst->num_components = right->num_components;
for (i = 0; i < right->num_components; i++)
dst->swizzle[i] = left->swizzle[right->swizzle[i]];
}
/* _slang_assemble_constructor() */
static int constructor_aggregate (slang_assembly_file *file, const slang_storage_aggregate *flat,
unsigned int *index, slang_operation *op, unsigned int size, slang_assembly_flow_control *flow,
slang_assembly_name_space *space, slang_assembly_local_info *info)
{
slang_assembly_typeinfo ti;
int result;
slang_storage_aggregate agg, flat_agg;
slang_assembly_stack_info stk;
unsigned int i;
slang_assembly_typeinfo_construct (&ti);
if (!(result = _slang_typeof_operation (op, space, &ti)))
goto end1;
slang_storage_aggregate_construct (&agg);
if (!(result = _slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs)))
goto end2;
slang_storage_aggregate_construct (&flat_agg);
if (!(result = _slang_flatten_aggregate (&flat_agg, &agg)))
goto end;
if (!(result = _slang_assemble_operation (file, op, 0, flow, space, info, &stk)))
goto end;
for (i = 0; i < flat_agg.count; i++)
{
const slang_storage_array *arr1 = flat_agg.arrays + i;
const slang_storage_array *arr2 = flat->arrays + *index;
if (arr1->type != arr2->type)
{
/* TODO: convert (generic) from arr1 to arr2 */
}
(*index)++;
/* TODO: watch the index, if it reaches the size, pop off the stack subsequent values */
}
result = 1;
end:
slang_storage_aggregate_destruct (&flat_agg);
end2:
slang_storage_aggregate_destruct (&agg);
end1:
slang_assembly_typeinfo_destruct (&ti);
return result;
}
/* XXX: general swizzle! */
int _slang_assemble_constructor (slang_assembly_file *file, slang_operation *op,
slang_assembly_flow_control *flow, slang_assembly_name_space *space,
slang_assembly_local_info *info)
{
slang_assembly_typeinfo ti;
int result;
slang_storage_aggregate agg, flat;
unsigned int size, index, i;
slang_assembly_typeinfo_construct (&ti);
if (!(result = _slang_typeof_operation (op, space, &ti)))
goto end1;
slang_storage_aggregate_construct (&agg);
if (!(result = _slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs)))
goto end2;
size = _slang_sizeof_aggregate (&agg);
slang_storage_aggregate_construct (&flat);
if (!(result = _slang_flatten_aggregate (&flat, &agg)))
goto end;
index = 0;
for (i = 0; i < op->num_children; i++)
{
if (!(result = constructor_aggregate (file, &flat, &index, op->children + i, size, flow,
space, info)))
goto end;
/* TODO: watch the index, if it reaches the size, raise an error */
}
result = 1;
end:
slang_storage_aggregate_destruct (&flat);
end2:
slang_storage_aggregate_destruct (&agg);
end1:
slang_assembly_typeinfo_destruct (&ti);
return result;
}
/* _slang_assemble_constructor_from_swizzle() */
/* XXX: wrong */
int _slang_assemble_constructor_from_swizzle (slang_assembly_file *file, const slang_swizzle *swz,
slang_type_specifier *spec, slang_type_specifier *master_spec, slang_assembly_local_info *info)
{
unsigned int master_rows, i;
switch (master_spec->type)
{
case slang_spec_bool:
case slang_spec_int:
case slang_spec_float:
master_rows = 1;
break;
case slang_spec_bvec2:
case slang_spec_ivec2:
case slang_spec_vec2:
master_rows = 2;
break;
case slang_spec_bvec3:
case slang_spec_ivec3:
case slang_spec_vec3:
master_rows = 3;
break;
case slang_spec_bvec4:
case slang_spec_ivec4:
case slang_spec_vec4:
master_rows = 4;
break;
}
for (i = 0; i < master_rows; i++)
{
switch (master_spec->type)
{
case slang_spec_bool:
case slang_spec_bvec2:
case slang_spec_bvec3:
case slang_spec_bvec4:
if (!slang_assembly_file_push_label2 (file, slang_asm_bool_copy, (master_rows - i) * 4,
i * 4))
return 0;
break;
case slang_spec_int:
case slang_spec_ivec2:
case slang_spec_ivec3:
case slang_spec_ivec4:
if (!slang_assembly_file_push_label2 (file, slang_asm_int_copy, (master_rows - i) * 4,
i * 4))
return 0;
break;
case slang_spec_float:
case slang_spec_vec2:
case slang_spec_vec3:
case slang_spec_vec4:
if (!slang_assembly_file_push_label2 (file, slang_asm_float_copy,
(master_rows - i) * 4, i * 4))
return 0;
break;
}
}
if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4))
return 0;
for (i = swz->num_components; i > 0; i--)
{
unsigned int n = i - 1;
if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, info->swizzle_tmp, 16))
return 0;
if (!slang_assembly_file_push_label (file, slang_asm_addr_push, swz->swizzle[n] * 4))
return 0;
if (!slang_assembly_file_push (file, slang_asm_addr_add))
return 0;
switch (master_spec->type)
{
case slang_spec_bool:
case slang_spec_bvec2:
case slang_spec_bvec3:
case slang_spec_bvec4:
if (!slang_assembly_file_push (file, slang_asm_bool_deref))
return 0;
break;
case slang_spec_int:
case slang_spec_ivec2:
case slang_spec_ivec3:
case slang_spec_ivec4:
if (!slang_assembly_file_push (file, slang_asm_int_deref))
return 0;
break;
case slang_spec_float:
case slang_spec_vec2:
case slang_spec_vec3:
case slang_spec_vec4:
if (!slang_assembly_file_push (file, slang_asm_float_deref))
return 0;
break;
}
}
return 1;
}

View file

@ -0,0 +1,80 @@
/*
* 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.
*/
#if !defined SLANG_ASSEMBLE_CONSTRUCTOR_H
#define SLANG_ASSEMBLE_CONSTRUCTOR_H
#include "slang_assemble.h"
#include "slang_compile.h"
#if defined __cplusplus
extern "C" {
#endif
/*
holds a complete information about vector swizzle - the <swizzle> array contains
vector component sources indices, where 0 is "x", 1 is "y", ...
example: "xwz" --> { 3, { 0, 3, 2, n/u } }
*/
typedef struct slang_swizzle_
{
unsigned int num_components;
unsigned int swizzle[4];
} slang_swizzle;
/*
checks if a field selector is a general swizzle (an r-value swizzle with replicated
components or an l-value swizzle mask) for a vector
returns 1 if this is the case, <swz> is filled with swizzle information
returns 0 otherwise
*/
int _slang_is_swizzle (const char *field, unsigned int rows, slang_swizzle *swz);
/*
checks if a general swizzle is an l-value swizzle - these swizzles do not have
duplicated fields and they are specified in order
returns 1 if this is a swizzle mask
returns 0 otherwise
*/
int _slang_is_swizzle_mask (const slang_swizzle *swz, unsigned int rows);
/*
combines two swizzles to form single swizzle
example: "wzyx.yx" --> "zw"
*/
void _slang_multiply_swizzles (slang_swizzle *, const slang_swizzle *, const slang_swizzle *);
int _slang_assemble_constructor (slang_assembly_file *file, slang_operation *op,
slang_assembly_flow_control *flow, slang_assembly_name_space *space,
slang_assembly_local_info *info);
int _slang_assemble_constructor_from_swizzle (slang_assembly_file *file, const slang_swizzle *swz,
slang_type_specifier *spec, slang_type_specifier *master_spec, slang_assembly_local_info *info);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,428 @@
/*
* 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_assemble_typeinfo.c
* slang type info
* \author Michal Krol
*/
#include "imports.h"
#include "slang_utility.h"
#include "slang_assemble_typeinfo.h"
/* slang_assembly_typeinfo */
void slang_assembly_typeinfo_construct (slang_assembly_typeinfo *ti)
{
slang_type_specifier_construct (&ti->spec);
}
void slang_assembly_typeinfo_destruct (slang_assembly_typeinfo *ti)
{
slang_type_specifier_destruct (&ti->spec);
}
/* _slang_typeof_operation() */
int _slang_typeof_operation (slang_operation *op, slang_assembly_name_space *space,
slang_assembly_typeinfo *ti)
{
ti->can_be_referenced = 0;
ti->is_swizzled = 0;
switch (op->type)
{
case slang_oper_block_no_new_scope:
case slang_oper_block_new_scope:
case slang_oper_variable_decl:
case slang_oper_asm:
case slang_oper_break:
case slang_oper_continue:
case slang_oper_discard:
case slang_oper_return:
case slang_oper_if:
case slang_oper_while:
case slang_oper_do:
case slang_oper_for:
case slang_oper_void:
ti->spec.type = slang_spec_void;
break;
case slang_oper_expression:
case slang_oper_assign:
case slang_oper_addassign:
case slang_oper_subassign:
case slang_oper_mulassign:
case slang_oper_divassign:
case slang_oper_preincrement:
case slang_oper_predecrement:
if (!_slang_typeof_operation (op->children, space, ti))
return 0;
break;
case slang_oper_literal_bool:
case slang_oper_logicalor:
case slang_oper_logicalxor:
case slang_oper_logicaland:
case slang_oper_equal:
case slang_oper_notequal:
case slang_oper_less:
case slang_oper_greater:
case slang_oper_lessequal:
case slang_oper_greaterequal:
case slang_oper_not:
ti->spec.type = slang_spec_bool;
break;
case slang_oper_literal_int:
ti->spec.type = slang_spec_int;
break;
case slang_oper_literal_float:
ti->spec.type = slang_spec_float;
break;
case slang_oper_identifier:
{
slang_variable *var;
var = _slang_locate_variable (op->locals, op->identifier, 1);
if (var == NULL)
return 0;
if (!slang_type_specifier_copy (&ti->spec, &var->type.specifier))
return 0;
ti->can_be_referenced = 1;
}
break;
case slang_oper_sequence:
/* TODO: check [0] and [1] if they match */
if (!_slang_typeof_operation (op->children + 1, space, ti))
return 0;
ti->can_be_referenced = 0;
ti->is_swizzled = 0;
break;
/*case slang_oper_modassign:*/
/*case slang_oper_lshassign:*/
/*case slang_oper_rshassign:*/
/*case slang_oper_orassign:*/
/*case slang_oper_xorassign:*/
/*case slang_oper_andassign:*/
case slang_oper_select:
/* TODO: check [1] and [2] if they match */
if (!_slang_typeof_operation (op->children + 1, space, ti))
return 0;
ti->can_be_referenced = 0;
ti->is_swizzled = 0;
break;
/*case slang_oper_bitor:*/
/*case slang_oper_bitxor:*/
/*case slang_oper_bitand:*/
/*case slang_oper_lshift:*/
/*case slang_oper_rshift:*/
case slang_oper_add:
{
int exists;
if (!_slang_typeof_function ("+", op->children, 2, space, &ti->spec, &exists))
return 0;
if (!exists)
return 0;
}
break;
case slang_oper_subtract:
{
int exists;
if (!_slang_typeof_function ("-", op->children, 2, space, &ti->spec, &exists))
return 0;
if (!exists)
return 0;
}
break;
case slang_oper_multiply:
{
int exists;
if (!_slang_typeof_function ("*", op->children, 2, space, &ti->spec, &exists))
return 0;
if (!exists)
return 0;
}
break;
case slang_oper_divide:
{
int exists;
if (!_slang_typeof_function ("/", op->children, 2, space, &ti->spec, &exists))
return 0;
if (!exists)
return 0;
}
break;
/*case slang_oper_modulus:*/
case slang_oper_plus:
{
int exists;
if (!_slang_typeof_function ("+", op->children, 1, space, &ti->spec, &exists))
return 0;
if (!exists)
return 0;
}
break;
case slang_oper_minus:
{
int exists;
if (!_slang_typeof_function ("-", op->children, 1, space, &ti->spec, &exists))
return 0;
if (!exists)
return 0;
}
break;
/*case slang_oper_complement:*/
case slang_oper_subscript:
{
slang_assembly_typeinfo _ti;
slang_assembly_typeinfo_construct (&_ti);
if (!_slang_typeof_operation (op->children, space, &_ti))
{
slang_assembly_typeinfo_destruct (&_ti);
return 0;
}
ti->can_be_referenced = _ti.can_be_referenced;
switch (_ti.spec.type)
{
case slang_spec_bvec2:
case slang_spec_bvec3:
case slang_spec_bvec4:
ti->spec.type = slang_spec_bool;
break;
case slang_spec_ivec2:
case slang_spec_ivec3:
case slang_spec_ivec4:
ti->spec.type = slang_spec_int;
break;
case slang_spec_vec2:
case slang_spec_vec3:
case slang_spec_vec4:
ti->spec.type = slang_spec_float;
break;
case slang_spec_mat2:
ti->spec.type = slang_spec_vec2;
break;
case slang_spec_mat3:
ti->spec.type = slang_spec_vec3;
break;
case slang_spec_mat4:
ti->spec.type = slang_spec_vec4;
break;
case slang_spec_array:
if (!slang_type_specifier_copy (&ti->spec, _ti.spec._array))
{
slang_assembly_typeinfo_destruct (&_ti);
return 0;
}
break;
default:
slang_assembly_typeinfo_destruct (&_ti);
return 0;
}
slang_assembly_typeinfo_destruct (&_ti);
}
break;
case slang_oper_call:
{
int exists;
if (!_slang_typeof_function (op->identifier, op->children, op->num_children, space,
&ti->spec, &exists))
return 0;
if (!exists)
{
slang_struct *s = slang_struct_scope_find (space->structs, op->identifier, 1);
if (s != NULL)
{
ti->spec.type = slang_spec_struct;
ti->spec._struct = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct));
if (ti->spec._struct == NULL)
return 0;
if (!slang_struct_construct_a (ti->spec._struct))
{
slang_alloc_free (ti->spec._struct);
ti->spec._struct = NULL;
return 0;
}
if (!slang_struct_copy (ti->spec._struct, s))
return 0;
}
else
{
slang_type_specifier_type type = slang_type_specifier_type_from_string (
op->identifier);
if (type == slang_spec_void)
return 0;
ti->spec.type = type;
}
}
}
break;
case slang_oper_field:
{
slang_assembly_typeinfo _ti;
slang_assembly_typeinfo_construct (&_ti);
if (!_slang_typeof_operation (op->children, space, &_ti))
{
slang_assembly_typeinfo_destruct (&_ti);
return 0;
}
if (_ti.spec.type == slang_spec_struct)
{
slang_variable *field = _slang_locate_variable (_ti.spec._struct->fields,
op->identifier, 0);
if (field == NULL)
{
slang_assembly_typeinfo_destruct (&_ti);
return 0;
}
if (!slang_type_specifier_copy (&ti->spec, &field->type.specifier))
{
slang_assembly_typeinfo_destruct (&_ti);
return 0;
}
}
else
{
unsigned int rows;
switch (_ti.spec.type)
{
case slang_spec_vec2:
case slang_spec_ivec2:
case slang_spec_bvec2:
rows = 2;
break;
case slang_spec_vec3:
case slang_spec_ivec3:
case slang_spec_bvec3:
rows = 3;
break;
case slang_spec_vec4:
case slang_spec_ivec4:
case slang_spec_bvec4:
rows = 4;
break;
default:
slang_assembly_typeinfo_destruct (&_ti);
return 0;
}
if (!_slang_is_swizzle (op->identifier, rows, &ti->swz))
return 0;
ti->is_swizzled = 1;
ti->can_be_referenced = _ti.can_be_referenced && _slang_is_swizzle_mask (&ti->swz,
rows);
if (_ti.is_swizzled)
{
slang_swizzle swz;
_slang_multiply_swizzles (&swz, &_ti.swz, &ti->swz);
ti->swz = swz;
}
switch (_ti.spec.type)
{
case slang_spec_vec2:
case slang_spec_vec3:
case slang_spec_vec4:
switch (ti->swz.num_components)
{
case 1:
ti->spec.type = slang_spec_float;
break;
case 2:
ti->spec.type = slang_spec_vec2;
break;
case 3:
ti->spec.type = slang_spec_vec3;
break;
case 4:
ti->spec.type = slang_spec_vec4;
break;
}
break;
case slang_spec_ivec2:
case slang_spec_ivec3:
case slang_spec_ivec4:
switch (ti->swz.num_components)
{
case 1:
ti->spec.type = slang_spec_int;
break;
case 2:
ti->spec.type = slang_spec_ivec2;
break;
case 3:
ti->spec.type = slang_spec_ivec3;
break;
case 4:
ti->spec.type = slang_spec_ivec4;
break;
}
break;
case slang_spec_bvec2:
case slang_spec_bvec3:
case slang_spec_bvec4:
switch (ti->swz.num_components)
{
case 1:
ti->spec.type = slang_spec_bool;
break;
case 2:
ti->spec.type = slang_spec_bvec2;
break;
case 3:
ti->spec.type = slang_spec_bvec3;
break;
case 4:
ti->spec.type = slang_spec_bvec4;
break;
}
break;
}
}
slang_assembly_typeinfo_destruct (&_ti);
return 1;
}
break;
case slang_oper_postincrement:
case slang_oper_postdecrement:
if (!_slang_typeof_operation (op->children, space, ti))
return 0;
ti->can_be_referenced = 0;
ti->is_swizzled = 0;
break;
default:
return 0;
}
return 1;
}
/* _slang_typeof_function() */
int _slang_typeof_function (const char *name, slang_operation *params, unsigned int num_params,
slang_assembly_name_space *space, slang_type_specifier *spec, int *exists)
{
slang_function *fun = _slang_locate_function (name, params, num_params, space);
*exists = fun != NULL;
if (fun == NULL)
return 1;
return slang_type_specifier_copy (spec, &fun->header.type.specifier);
}

View file

@ -0,0 +1,67 @@
/*
* 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.
*/
#if !defined SLANG_ASSEMBLE_TYPEINFO_H
#define SLANG_ASSEMBLE_TYPEINFO_H
#include "slang_assemble_constructor.h"
#include "slang_compile.h"
#if defined __cplusplus
extern "C" {
#endif
typedef struct slang_assembly_typeinfo_
{
int can_be_referenced;
int is_swizzled;
slang_swizzle swz;
slang_type_specifier spec;
} slang_assembly_typeinfo;
void slang_assembly_typeinfo_construct (slang_assembly_typeinfo *);
void slang_assembly_typeinfo_destruct (slang_assembly_typeinfo *);
/*
retrieves type information about an operation
returns 1 on success
returns 0 otherwise
*/
int _slang_typeof_operation (slang_operation *, slang_assembly_name_space *,
slang_assembly_typeinfo *);
/*
retrieves type of a function prototype, if one exists
returns 1 on success, even if the function was not found
returns 0 otherwise
*/
int _slang_typeof_function (const char *name, slang_operation *params, unsigned int num_params,
slang_assembly_name_space *space, slang_type_specifier *spec, int *exists);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -33,6 +33,9 @@
#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.
@ -43,22 +46,61 @@
static void slang_variable_construct (slang_variable *);
static int slang_variable_copy (slang_variable *, const slang_variable *);
static void slang_struct_construct (slang_struct *);
static void slang_struct_destruct (slang_struct *);
static int slang_struct_copy (slang_struct *, const 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 */
static void slang_type_specifier_construct (slang_type_specifier *spec)
void slang_type_specifier_construct (slang_type_specifier *spec)
{
spec->type = slang_spec_void;
spec->_struct = NULL;
spec->_array = NULL;
}
static void slang_type_specifier_destruct (slang_type_specifier *spec)
void slang_type_specifier_destruct (slang_type_specifier *spec)
{
if (spec->_struct != NULL)
{
@ -72,7 +114,7 @@ static void slang_type_specifier_destruct (slang_type_specifier *spec)
}
}
static int slang_type_specifier_copy (slang_type_specifier *x, const slang_type_specifier *y)
int slang_type_specifier_copy (slang_type_specifier *x, const slang_type_specifier *y)
{
slang_type_specifier_destruct (x);
slang_type_specifier_construct (x);
@ -80,19 +122,28 @@ static int slang_type_specifier_copy (slang_type_specifier *x, const slang_type_
if (x->type == slang_spec_struct)
{
x->_struct = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct));
slang_struct_construct (x->_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;
}
static int slang_type_specifier_equal (const slang_type_specifier *x, const slang_type_specifier *y)
int slang_type_specifier_equal (const slang_type_specifier *x, const slang_type_specifier *y)
{
if (x->type != y->type)
return 0;
@ -162,8 +213,8 @@ static int slang_variable_scope_copy (slang_variable_scope *x, const slang_varia
}
/* slang_operation */
/* XXX mem! */
static void slang_operation_construct (slang_operation *oper)
int slang_operation_construct_a (slang_operation *oper)
{
oper->type = slang_oper_none;
oper->children = NULL;
@ -171,10 +222,13 @@ static void slang_operation_construct (slang_operation *oper)
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;
}
static void slang_operation_destruct (slang_operation *oper)
void slang_operation_destruct (slang_operation *oper)
{
unsigned int i;
for (i = 0; i < oper->num_children; i++)
@ -188,16 +242,31 @@ static void slang_operation_destruct (slang_operation *oper)
static int slang_operation_copy (slang_operation *x, const slang_operation *y)
{
unsigned int i;
slang_operation_destruct (x);
slang_operation_construct (x);
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++)
slang_operation_construct (x->children + i);
for (i = 0; i < x->num_children; i++)
if (!slang_operation_copy (x->children + i, y->children + i))
return 0;
@ -221,6 +290,7 @@ static void slang_variable_construct (slang_variable *var)
var->name = NULL;
var->array_size = NULL;
var->initializer = NULL;
var->address = ~0;
}
static void slang_variable_destruct (slang_variable *var)
@ -256,7 +326,12 @@ static int slang_variable_copy (slang_variable *x, const slang_variable *y)
x->array_size = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation));
if (x->array_size == NULL)
return 0;
slang_operation_construct (x->array_size);
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;
}
@ -265,13 +340,29 @@ static int slang_variable_copy (slang_variable *x, const slang_variable *y)
x->initializer = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation));
if (x->initializer == NULL)
return 0;
slang_operation_construct (x->initializer);
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)
@ -299,7 +390,17 @@ static int slang_struct_scope_copy (slang_struct_scope *x, const slang_struct_sc
return 0;
x->num_structs = y->num_structs;
for (i = 0; i < x->num_structs; i++)
slang_struct_construct (x->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;
@ -307,8 +408,7 @@ static int slang_struct_scope_copy (slang_struct_scope *x, const slang_struct_sc
return 1;
}
static slang_struct *slang_struct_scope_find (slang_struct_scope *stru, const char *name,
int all_scopes)
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++)
@ -320,14 +420,23 @@ static slang_struct *slang_struct_scope_find (slang_struct_scope *stru, const ch
}
/* slang_struct */
/* XXX mem! */
static void slang_struct_construct (slang_struct *stru)
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)
@ -339,10 +448,14 @@ static void slang_struct_destruct (slang_struct *stru)
slang_alloc_free (stru->structs);
}
static int slang_struct_copy (slang_struct *x, const slang_struct *y)
int slang_struct_copy (slang_struct *x, const slang_struct *y)
{
slang_struct_destruct (x);
slang_struct_construct (x);
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);
@ -386,6 +499,7 @@ static void slang_function_construct (slang_function *func)
func->parameters = (slang_variable_scope *) slang_alloc_malloc (sizeof (slang_variable_scope));
slang_variable_scope_construct (func->parameters);
func->body = NULL;
func->address = ~0;
}
static void slang_function_destruct (slang_function *func)
@ -561,7 +675,7 @@ typedef struct slang_parse_ctx_
int parsing_builtin;
} slang_parse_ctx;
/* --- */
/* _slang_compile() */
static int parse_identifier (slang_parse_ctx *C, char **id)
{
@ -826,7 +940,14 @@ static int parse_type_specifier (slang_parse_ctx *C, slang_type_specifier *spec,
slang_info_log_memory (C->L);
return 0;
}
slang_struct_construct (spec->_struct);
if (!slang_struct_construct_a (spec->_struct))
{
slang_alloc_free (spec->_struct);
spec->_struct = NULL;
slang_alloc_free (name);
slang_info_log_memory (C->L);
return 0;
}
spec->_struct->name = name;
spec->_struct->structs->outer_scope = structs;
}
@ -878,7 +999,14 @@ static int parse_type_specifier (slang_parse_ctx *C, slang_type_specifier *spec,
slang_info_log_memory (C->L);
return 0;
}
slang_operation_construct (var->array_size);
if (!slang_operation_construct_a (var->array_size))
{
slang_alloc_free (var->array_size);
var->array_size = NULL;
slang_type_specifier_destruct (&sp);
slang_info_log_memory (C->L);
return 0;
}
if (!parse_expression (C, var->array_size, scope, structs, funcs))
{
slang_type_specifier_destruct (&sp);
@ -904,8 +1032,9 @@ static int parse_type_specifier (slang_parse_ctx *C, slang_type_specifier *spec,
return 0;
}
s = structs->structs + structs->num_structs;
if (!slang_struct_construct_a (s))
return 0;
structs->num_structs++;
slang_struct_construct (s);
if (!slang_struct_copy (s, spec->_struct))
return 0;
}
@ -931,7 +1060,12 @@ static int parse_type_specifier (slang_parse_ctx *C, slang_type_specifier *spec,
slang_info_log_memory (C->L);
return 0;
}
slang_struct_construct (spec->_struct);
if (!slang_struct_construct_a (spec->_struct))
{
slang_alloc_free (spec->_struct);
spec->_struct = NULL;
return 0;
}
if (!slang_struct_copy (spec->_struct, stru))
return 0;
}
@ -1025,7 +1159,11 @@ static int parse_child_operation (slang_parse_ctx *C, slang_operation *oper, int
slang_info_log_memory (C->L);
return 0;
}
slang_operation_construct (oper->children + oper->num_children);
if (!slang_operation_construct_a (oper->children + oper->num_children))
{
slang_info_log_memory (C->L);
return 0;
}
oper->num_children++;
if (statement)
return parse_statement (C, oper->children + oper->num_children - 1, scope, structs, funcs);
@ -1073,7 +1211,16 @@ static int parse_statement (slang_parse_ctx *C, slang_operation *oper, slang_var
return 0;
}
for (i = 0; i < num_vars; i++)
slang_operation_construct (oper->children + i);
if (!slang_operation_construct_a (oper->children + i))
{
unsigned int j;
for (j = 0; j < i; j++)
slang_operation_destruct (oper->children + j);
slang_alloc_free (oper->children);
oper->children = NULL;
slang_info_log_memory (C->L);
return 0;
}
oper->num_children = num_vars;
for (i = first_var; i < scope->num_variables; i++)
{
@ -1230,39 +1377,10 @@ static int handle_unary_expression (slang_parse_ctx *C, slang_operation *op,
return 1;
}
/* these must match with slang_type_specifier_type enum */
static const char *builtin_constructor_names[] = {
"void",
"bool",
"bvec2",
"bvec3",
"bvec4",
"int",
"ivec2",
"ivec3",
"ivec4",
"float",
"vec2",
"vec3",
"vec4",
"mat2",
"mat3",
"mat4",
"sampler1D",
"sampler2D",
"sampler3D",
"samplerCube",
"sampler1DShadow",
"sampler2DShadow",
NULL
};
static int is_constructor_name (const char *name, slang_struct_scope *structs)
{
const char **p = &builtin_constructor_names[1];
while (*p != NULL)
if (slang_string_compare (*p++, name) == 0)
return 1;
if (slang_type_specifier_type_from_string (name) != slang_spec_void)
return 1;
return slang_struct_scope_find (structs, name, 1) != NULL;
}
@ -1285,8 +1403,12 @@ static int parse_expression (slang_parse_ctx *C, slang_operation *oper, slang_va
return 0;
}
op = ops + num_ops;
if (!slang_operation_construct_a (op))
{
slang_info_log_memory (C->L);
return 0;
}
num_ops++;
slang_operation_construct (op);
op->locals->outer_scope = scope;
switch (op_code)
{
@ -1513,6 +1635,7 @@ static int parse_expression (slang_parse_ctx *C, slang_operation *oper, slang_va
static int parse_parameter_declaration (slang_parse_ctx *C, slang_variable *param,
slang_struct_scope *structs, slang_variable_scope *scope, slang_function_scope *funcs)
{
slang_storage_aggregate agg;
if (!parse_type_qualifier (C, &param->type.qualifier))
return 0;
switch (*C->I++)
@ -1557,10 +1680,24 @@ static int parse_parameter_declaration (slang_parse_ctx *C, slang_variable *para
slang_info_log_memory (C->L);
return 0;
}
slang_operation_construct (param->array_size);
if (!slang_operation_construct_a (param->array_size))
{
slang_alloc_free (param->array_size);
param->array_size = NULL;
slang_info_log_memory (C->L);
return 0;
}
if (!parse_expression (C, param->array_size, scope, structs, funcs))
return 0;
}
slang_storage_aggregate_construct (&agg);
if (!_slang_aggregate_variable (&agg, &param->type.specifier, param->array_size, funcs,
structs))
{
slang_storage_aggregate_destruct (&agg);
return 0;
}
slang_storage_aggregate_destruct (&agg);
return 1;
}
@ -1680,7 +1817,7 @@ static int parse_function_prototype (slang_parse_ctx *C, slang_function *func,
if (func->header.type.specifier.type == slang_spec_struct)
return 0;
func->header.name = slang_string_duplicate (
builtin_constructor_names[func->header.type.specifier.type]);
type_specifier_type_names[func->header.type.specifier.type]);
if (func->header.name == NULL)
{
slang_info_log_memory (C->L);
@ -1728,7 +1865,13 @@ static int parse_function_definition (slang_parse_ctx *C, slang_function *func,
slang_info_log_memory (C->L);
return 0;
}
slang_operation_construct (func->body);
if (!slang_operation_construct_a (func->body))
{
slang_alloc_free (func->body);
func->body = NULL;
slang_info_log_memory (C->L);
return 0;
}
if (!parse_statement (C, func->body, func->parameters, structs, funcs))
return 0;
return 1;
@ -1781,7 +1924,13 @@ static int parse_init_declarator (slang_parse_ctx *C, const slang_fully_specifie
slang_info_log_memory (C->L);
return 0;
}
slang_operation_construct (var->initializer);
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;
@ -1816,13 +1965,32 @@ static int parse_init_declarator (slang_parse_ctx *C, const slang_fully_specifie
slang_info_log_memory (C->L);
return 0;
}
slang_operation_construct (var->array_size);
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;
}
@ -1874,7 +2042,8 @@ static int parse_function (slang_parse_ctx *C, int definition, slang_struct_scop
}
}
/* find a function with a prototype matching the parsed one */
/* 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)
{
@ -1919,6 +2088,37 @@ static int parse_function (slang_parse_ctx *C, int definition, slang_struct_scop
/* return the found function */
*parsed_func_ret = found_func;
}
/* assemble the parsed function */
if (definition)
{
static int x = 0;
const int y = 61; /* core 437 */
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);
if (x == y)
xxx_prolog (&file);
if (!_slang_assemble_function (&file, *parsed_func_ret, &space))
{
slang_assembly_file_destruct (&file);
return 0;
}
if (x == y)
{
_slang_execute (&file);
slang_assembly_file_destruct (&file);
exit (0);
}
}
return 1;
}

View file

@ -68,14 +68,21 @@ typedef enum slang_type_specifier_type_
slang_spec_sampler2DShadow,
slang_spec_struct,
slang_spec_array
} slang_type_specifier_type;
} slang_type_specifier_type;
slang_type_specifier_type slang_type_specifier_type_from_string (const char *);
typedef struct slang_type_specifier_
{
slang_type_specifier_type type;
struct slang_struct_ *_struct; /* spec_struct */
struct slang_type_specifier_ *_array; /* spec_array */
} slang_type_specifier;
} slang_type_specifier;
void slang_type_specifier_construct (slang_type_specifier *);
void slang_type_specifier_destruct (slang_type_specifier *);
int slang_type_specifier_copy (slang_type_specifier *, const slang_type_specifier *);
int slang_type_specifier_equal (const slang_type_specifier *, const slang_type_specifier *);
typedef struct slang_fully_specified_type_
{
@ -164,29 +171,40 @@ typedef struct slang_operation_
float literal; /* bool, literal_int, literal_float */
char *identifier; /* asm, identifier, call, field */
slang_variable_scope *locals;
} slang_operation;
} slang_operation;
int slang_operation_construct_a (slang_operation *);
void slang_operation_destruct (slang_operation *);
typedef struct slang_variable_
{
slang_fully_specified_type type;
char *name;
slang_operation *array_size; /* spec_array */
slang_operation *initializer;
} slang_variable;
slang_operation *initializer;
unsigned int address;
} slang_variable;
slang_variable *_slang_locate_variable (slang_variable_scope *scope, const char *name, int all);
typedef struct slang_struct_scope_
{
struct slang_struct_ *structs;
unsigned int num_structs;
struct slang_struct_scope_ *outer_scope;
} slang_struct_scope;
} slang_struct_scope;
struct slang_struct_ *slang_struct_scope_find (slang_struct_scope *, const char *, int);
typedef struct slang_struct_
{
char *name;
slang_variable_scope *fields;
slang_struct_scope *structs;
} slang_struct;
} slang_struct;
int slang_struct_construct_a (slang_struct *);
int slang_struct_copy (slang_struct *, const slang_struct *);
typedef enum slang_function_kind_
{
@ -201,7 +219,8 @@ typedef struct slang_function_
slang_variable header;
slang_variable_scope *parameters;
unsigned int param_count;
slang_operation *body;
slang_operation *body;
unsigned int address;
} slang_function;
typedef struct slang_function_scope_

View file

@ -0,0 +1,347 @@
/*
* 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_execute.c
* intermediate code interpreter
* \author Michal Krol
*/
#include "imports.h"
#include "slang_utility.h"
#include "slang_assemble.h"
#include "slang_storage.h"
#include "slang_execute.h"
static void dump_instruction (FILE *f, slang_assembly *a, unsigned int i)
{
fprintf (f, "%.5u:\t", i);
switch (a->type)
{
case slang_asm_none:
fprintf (f, "none");
break;
case slang_asm_float_copy:
fprintf (f, "float_copy\t%d, %d", a->param[0], a->param[1]);
break;
case slang_asm_float_move:
fprintf (f, "float_move\t%d, %d", a->param[0], a->param[1]);
break;
case slang_asm_float_push:
fprintf (f, "float_push\t%f", a->literal);
break;
case slang_asm_float_deref:
fprintf (f, "float_deref");
break;
case slang_asm_float_add:
fprintf (f, "float_add");
break;
case slang_asm_float_multiply:
fprintf (f, "float_multiply");
break;
case slang_asm_float_divide:
fprintf (f, "float_divide");
break;
case slang_asm_float_negate:
fprintf (f, "float_negate");
break;
case slang_asm_float_less:
fprintf (f, "float_less");
break;
case slang_asm_float_equal:
fprintf (f, "float_equal\t%d, %d", a->param[0], a->param[1]);
break;
case slang_asm_float_to_int:
fprintf (f, "float_to_int");
break;
case slang_asm_int_copy:
fprintf (f, "int_copy\t%d, %d", a->param[0], a->param[1]);
break;
case slang_asm_int_move:
fprintf (f, "int_move\t%d, %d", a->param[0], a->param[1]);
break;
case slang_asm_int_push:
fprintf (f, "int_push\t%d", (GLint) a->literal);
break;
case slang_asm_int_deref:
fprintf (f, "int_deref");
break;
case slang_asm_int_to_float:
fprintf (f, "int_to_float");
break;
case slang_asm_int_to_addr:
fprintf (f, "int_to_addr");
break;
case slang_asm_bool_copy:
fprintf (f, "bool_copy\t%d, %d", a->param[0], a->param[1]);
break;
case slang_asm_bool_move:
fprintf (f, "bool_move\t%d, %d", a->param[0], a->param[1]);
break;
case slang_asm_bool_push:
fprintf (f, "bool_push\t%d", a->literal != 0.0f);
break;
case slang_asm_bool_deref:
fprintf (f, "bool_deref");
break;
case slang_asm_addr_copy:
fprintf (f, "addr_copy");
break;
case slang_asm_addr_push:
fprintf (f, "addr_push\t%u", a->param[0]);
break;
case slang_asm_addr_deref:
fprintf (f, "addr_deref");
break;
case slang_asm_addr_add:
fprintf (f, "address_add");
break;
case slang_asm_addr_multiply:
fprintf (f, "address_multiply");
break;
case slang_asm_jump:
fprintf (f, "jump\t%u", a->param[0]);
break;
case slang_asm_jump_if_zero:
fprintf (f, "jump_if_zero\t%u", a->param[0]);
break;
case slang_asm_enter:
fprintf (f, "enter\t%u", a->param[0]);
break;
case slang_asm_leave:
fprintf (f, "leave");
break;
case slang_asm_local_alloc:
fprintf (f, "local_alloc\t%u", a->param[0]);
break;
case slang_asm_local_free:
fprintf (f, "local_free\t%u", a->param[0]);
break;
case slang_asm_local_addr:
fprintf (f, "local_addr\t%u, %u", a->param[0], a->param[1]);
break;
case slang_asm_call:
fprintf (f, "call\t%u", a->param[0]);
break;
case slang_asm_return:
fprintf (f, "return");
break;
case slang_asm_discard:
fprintf (f, "discard");
break;
case slang_asm_exit:
fprintf (f, "exit");
break;
}
fprintf (f, "\n");
}
static void dump (const slang_assembly_file *file)
{
unsigned int i;
static unsigned int counter = 0;
FILE *f;
char filename[256];
counter++;
sprintf (filename, "~mesa-slang-assembly-dump-(%u).txt", counter);
f = fopen (filename, "w");
if (f == NULL)
return;
for (i = 0; i < file->count; i++)
dump_instruction (f, file->code + i, i);
fclose (f);
}
int _slang_execute (const slang_assembly_file *file)
{
slang_machine mach;
FILE *f;
mach.ip = 0;
mach.sp = SLANG_MACHINE_STACK_SIZE;
mach.bp = 0;
mach.kill = 0;
mach.exit = 0;
/* assume 32-bit machine */
static_assert(sizeof (GLfloat) == 4);
static_assert(sizeof (GLfloat *) == 4);
static_assert(sizeof (GLuint) == 4);
static_assert(sizeof (GLuint *) == 4);
dump (file);
f = fopen ("~mesa-slang-assembly-execution.txt", "w");
while (!mach.exit)
{
slang_assembly *a = file->code + mach.ip;
if (f != NULL)
{
unsigned int i;
dump_instruction (f, a, mach.ip);
fprintf (f, "\t\tsp=%u bp=%u\n", mach.sp, mach.bp);
for (i = mach.sp; i < SLANG_MACHINE_STACK_SIZE; i++)
fprintf (f, "\t%.5u\t%6f\t%u\n", i, mach.stack._float[i], mach.stack._addr[i]);
fflush (f);
}
mach.ip++;
switch (a->type)
{
case slang_asm_none:
break;
case slang_asm_float_copy:
case slang_asm_int_copy:
case slang_asm_bool_copy:
*(mach.stack._floatp[mach.sp + a->param[0] / 4] + a->param[1] / 4) =
mach.stack._float[mach.sp];
mach.sp++;
break;
case slang_asm_float_move:
case slang_asm_int_move:
case slang_asm_bool_move:
mach.stack._float[mach.sp + a->param[0] / 4] =
mach.stack._float[mach.sp + (mach.stack._addr[mach.sp] + a->param[1]) / 4];
break;
case slang_asm_float_push:
case slang_asm_int_push:
case slang_asm_bool_push:
mach.sp--;
mach.stack._float[mach.sp] = a->literal;
break;
case slang_asm_float_deref:
case slang_asm_int_deref:
case slang_asm_bool_deref:
mach.stack._float[mach.sp] = *mach.stack._floatp[mach.sp];
break;
case slang_asm_float_add:
mach.stack._float[mach.sp + 1] += mach.stack._float[mach.sp];
mach.sp++;
break;
case slang_asm_float_multiply:
mach.stack._float[mach.sp + 1] *= mach.stack._float[mach.sp];
mach.sp++;
break;
case slang_asm_float_divide:
mach.stack._float[mach.sp + 1] /= mach.stack._float[mach.sp];
mach.sp++;
break;
case slang_asm_float_negate:
mach.stack._float[mach.sp] = -mach.stack._float[mach.sp];
break;
case slang_asm_float_less:
mach.stack._float[mach.sp + 1] =
mach.stack._float[mach.sp + 1] < mach.stack._float[mach.sp] ? 1.0f : 0.0f;
mach.sp++;
break;
case slang_asm_float_equal:
mach.sp--;
mach.stack._float[mach.sp] = mach.stack._float[mach.sp + 1 + a->param[0] / 4] ==
mach.stack._float[mach.sp + 1 + a->param[1] / 4] ? 1.0f : 0.0f;
break;
case slang_asm_float_to_int:
mach.stack._float[mach.sp] = (GLfloat) (GLint) mach.stack._float[mach.sp];
break;
case slang_asm_int_to_float:
break;
case slang_asm_int_to_addr:
mach.stack._addr[mach.sp] = (GLuint) (GLint) mach.stack._float[mach.sp];
break;
case slang_asm_addr_copy:
*mach.stack._addrp[mach.sp + 1] = mach.stack._addr[mach.sp];
mach.sp++;
break;
case slang_asm_addr_push:
mach.sp--;
mach.stack._addr[mach.sp] = a->param[0];
break;
case slang_asm_addr_deref:
mach.stack._addr[mach.sp] = *mach.stack._addrp[mach.sp];
break;
case slang_asm_addr_add:
mach.stack._addr[mach.sp + 1] += mach.stack._addr[mach.sp];
mach.sp++;
break;
case slang_asm_addr_multiply:
mach.stack._addr[mach.sp + 1] *= mach.stack._addr[mach.sp];
mach.sp++;
break;
case slang_asm_jump:
mach.ip = a->param[0];
break;
case slang_asm_jump_if_zero:
if (mach.stack._float[mach.sp] == 0.0f)
mach.ip = a->param[0];
mach.sp++;
break;
case slang_asm_enter:
mach.sp--;
mach.stack._addr[mach.sp] = mach.bp;
mach.bp = mach.sp + a->param[0] / 4 + 1;
break;
case slang_asm_leave:
mach.bp = mach.stack._addr[mach.sp];
mach.sp++;
break;
case slang_asm_local_alloc:
mach.sp -= a->param[0] / 4;
break;
case slang_asm_local_free:
mach.sp += a->param[0] / 4;
break;
case slang_asm_local_addr:
mach.sp--;
mach.stack._addr[mach.sp] = (GLuint) mach.stack._addr + mach.bp * 4 -
(a->param[0] + a->param[1]);
break;
case slang_asm_call:
mach.sp--;
mach.stack._addr[mach.sp] = mach.ip;
mach.ip = a->param[0];
break;
case slang_asm_return:
mach.ip = mach.stack._addr[mach.sp];
mach.sp++;
break;
case slang_asm_discard:
mach.kill = 1;
break;
case slang_asm_exit:
mach.exit = 1;
break;
}
}
if (f != NULL)
fclose (f);
return 0;
}

View file

@ -0,0 +1,57 @@
/*
* 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.
*/
#if !defined SLANG_EXECUTE_H
#define SLANG_EXECUTE_H
#if defined __cplusplus
extern "C" {
#endif
#define SLANG_MACHINE_STACK_SIZE 64
typedef struct slang_machine_
{
GLuint ip; /* instruction pointer, for flow control */
GLuint sp; /* stack pointer, for stack access */
GLuint bp; /* base pointer, for local variable access */
GLuint kill; /* discard the fragment */
GLuint exit; /* terminate the shader */
union stack_
{
GLfloat _float[SLANG_MACHINE_STACK_SIZE];
GLfloat *_floatp[SLANG_MACHINE_STACK_SIZE];
GLuint _addr[SLANG_MACHINE_STACK_SIZE];
GLuint *_addrp[SLANG_MACHINE_STACK_SIZE];
} stack;
} slang_machine;
int _slang_execute (const slang_assembly_file *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,255 @@
/*
* 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_storage.c
* slang variable storage
* \author Michal Krol
*/
#include "imports.h"
#include "slang_utility.h"
#include "slang_storage.h"
#include "slang_assemble.h"
/* slang_storage_array */
void slang_storage_array_construct (slang_storage_array *arr)
{
arr->type = slang_stor_aggregate;
arr->aggregate = NULL;
arr->length = 0;
}
void slang_storage_array_destruct (slang_storage_array *arr)
{
if (arr->aggregate != NULL)
{
slang_storage_aggregate_destruct (arr->aggregate);
slang_alloc_free (arr->aggregate);
}
}
/* slang_storage_aggregate */
void slang_storage_aggregate_construct (slang_storage_aggregate *agg)
{
agg->arrays = NULL;
agg->count = 0;
}
void slang_storage_aggregate_destruct (slang_storage_aggregate *agg)
{
unsigned int i;
for (i = 0; i < agg->count; i++)
slang_storage_array_destruct (agg->arrays + i);
slang_alloc_free (agg->arrays);
}
static slang_storage_array *slang_storage_aggregate_push_new (slang_storage_aggregate *agg)
{
slang_storage_array *arr = NULL;
agg->arrays = (slang_storage_array *) slang_alloc_realloc (agg->arrays, agg->count * sizeof (
slang_storage_array), (agg->count + 1) * sizeof (slang_storage_array));
if (agg->arrays != NULL)
{
arr = agg->arrays + agg->count;
slang_storage_array_construct (arr);
agg->count++;
}
return arr;
}
/* _slang_aggregate_variable() */
static int aggregate_vector (slang_storage_aggregate *agg, slang_storage_type basic_type,
unsigned int row_count)
{
slang_storage_array *arr = slang_storage_aggregate_push_new (agg);
if (arr == NULL)
return 0;
arr->type = basic_type;
arr->length = row_count;
return 1;
}
static int aggregate_matrix (slang_storage_aggregate *agg, slang_storage_type basic_type,
unsigned int order)
{
slang_storage_array *arr = slang_storage_aggregate_push_new (agg);
if (arr == NULL)
return 0;
arr->type = slang_stor_aggregate;
arr->length = order;
arr->aggregate = (slang_storage_aggregate *) slang_alloc_malloc (sizeof (
slang_storage_aggregate));
if (arr->aggregate == NULL)
return 0;
slang_storage_aggregate_construct (arr->aggregate);
if (!aggregate_vector (arr->aggregate, basic_type, order))
return 0;
return 1;
}
static int aggregate_variables (slang_storage_aggregate *agg, const slang_variable_scope *vars,
slang_function_scope *funcs, slang_struct_scope *structs)
{
unsigned int i;
for (i = 0; i < vars->num_variables; i++)
if (!_slang_aggregate_variable (agg, &vars->variables[i].type.specifier,
vars->variables[i].array_size, funcs, structs))
return 0;
return 1;
}
int _slang_aggregate_variable (slang_storage_aggregate *agg, slang_type_specifier *spec,
slang_operation *array_size, slang_function_scope *funcs, slang_struct_scope *structs)
{
switch (spec->type)
{
case slang_spec_bool:
return aggregate_vector (agg, slang_stor_bool, 1);
case slang_spec_bvec2:
return aggregate_vector (agg, slang_stor_bool, 2);
case slang_spec_bvec3:
return aggregate_vector (agg, slang_stor_bool, 3);
case slang_spec_bvec4:
return aggregate_vector (agg, slang_stor_bool, 4);
case slang_spec_int:
return aggregate_vector (agg, slang_stor_int, 1);
case slang_spec_ivec2:
return aggregate_vector (agg, slang_stor_int, 2);
case slang_spec_ivec3:
return aggregate_vector (agg, slang_stor_int, 3);
case slang_spec_ivec4:
return aggregate_vector (agg, slang_stor_int, 4);
case slang_spec_float:
return aggregate_vector (agg, slang_stor_float, 1);
case slang_spec_vec2:
return aggregate_vector (agg, slang_stor_float, 2);
case slang_spec_vec3:
return aggregate_vector (agg, slang_stor_float, 3);
case slang_spec_vec4:
return aggregate_vector (agg, slang_stor_float, 4);
case slang_spec_mat2:
return aggregate_matrix (agg, slang_stor_float, 2);
case slang_spec_mat3:
return aggregate_matrix (agg, slang_stor_float, 3);
case slang_spec_mat4:
return aggregate_matrix (agg, slang_stor_float, 4);
case slang_spec_sampler1D:
case slang_spec_sampler2D:
case slang_spec_sampler3D:
case slang_spec_samplerCube:
case slang_spec_sampler1DShadow:
case slang_spec_sampler2DShadow:
return aggregate_vector (agg, slang_stor_int, 1);
case slang_spec_struct:
return aggregate_variables (agg, spec->_struct->fields, funcs, structs);
case slang_spec_array:
{
slang_storage_array *arr;
slang_assembly_file file;
slang_assembly_flow_control flow;
slang_assembly_name_space space;
slang_assembly_local_info info;
slang_assembly_stack_info stk;
arr = slang_storage_aggregate_push_new (agg);
if (arr == NULL)
return 0;
arr->type = slang_stor_aggregate;
arr->aggregate = (slang_storage_aggregate *) slang_alloc_malloc (sizeof (
slang_storage_aggregate));
if (arr->aggregate == NULL)
return 0;
slang_storage_aggregate_construct (arr->aggregate);
if (!_slang_aggregate_variable (arr->aggregate, spec->_array, NULL, funcs, structs))
return 0;
slang_assembly_file_construct (&file);
space.funcs = funcs;
space.structs = structs;
/* XXX: vars! */
space.vars = NULL;
if (!_slang_assemble_operation (&file, array_size, 0, &flow, &space, &info, &stk))
{
slang_assembly_file_destruct (&file);
return 0;
}
/* TODO: evaluate array size */
slang_assembly_file_destruct (&file);
arr->length = 256;
}
return 1;
default:
return 0;
}
}
/* _slang_sizeof_aggregate() */
unsigned int _slang_sizeof_aggregate (const slang_storage_aggregate *agg)
{
unsigned int i, size = 0;
for (i = 0; i < agg->count; i++)
{
unsigned int element_size;
if (agg->arrays[i].type == slang_stor_aggregate)
element_size = _slang_sizeof_aggregate (agg->arrays[i].aggregate);
else
element_size = sizeof (GLfloat);
size += element_size * agg->arrays[i].length;
}
return size;
}
/* _slang_flatten_aggregate () */
int _slang_flatten_aggregate (slang_storage_aggregate *flat, const slang_storage_aggregate *agg)
{
unsigned int i;
for (i = 0; i < agg->count; i++)
{
unsigned int j;
for (j = 0; j < agg->arrays[i].length; j++)
{
if (agg->arrays[i].type == slang_stor_aggregate)
{
if (!_slang_flatten_aggregate (flat, agg->arrays[i].aggregate))
return 0;
}
else
{
slang_storage_array *arr;
arr = slang_storage_aggregate_push_new (flat);
if (arr == NULL)
return 0;
arr->type = agg->arrays[i].type;
arr->length = 1;
}
}
}
return 1;
}

View file

@ -0,0 +1,109 @@
/*
* 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.
*/
#if !defined SLANG_STORAGE_H
#define SLANG_STORAGE_H
#include "slang_compile.h"
#if defined __cplusplus
extern "C" {
#endif
/*
Program variable data storage is kept completely transparent to the front-end compiler. It is
up to the back-end how the data is actually allocated. The slang_storage_type enum
provides the basic information about how the memory is interpreted. This abstract piece
of memory is called a data slot. A data slot of a particular type has a fixed size.
For now, only the three basic types are supported, that is bool, int and float. Other built-in
types like vector or matrix can easily be decomposed into a series of basic types.
*/
typedef enum slang_storage_type_
{
slang_stor_aggregate,
slang_stor_bool,
slang_stor_int,
slang_stor_float
} slang_storage_type;
/*
The slang_storage_array structure groups data slots of the same type into an array. This
array has a fixed length. Arrays are required to have a size equal to the sum of sizes of its
elements. They are also required to support indirect addressing. That is, if B references
first data slot in the array, S is the size of the data slot and I is the integral index that
is not known at compile time, B+I*S references I-th data slot.
This structure is also used to break down built-in data types that are not supported directly.
Vectors, like vec3, are constructed from arrays of their basic types. Matrices are formed of
an array of column vectors, which are in turn processed as other vectors.
*/
typedef struct slang_storage_array_
{
slang_storage_type type;
struct slang_storage_aggregate_ *aggregate; /* slang_stor_aggregate */
unsigned int length;
} slang_storage_array;
void slang_storage_array_construct (slang_storage_array *);
void slang_storage_array_destruct (slang_storage_array *);
/*
The slang_storage_aggregate structure relaxes the indirect addressing requirement for
slang_storage_array structure. Aggregates are always accessed statically - its member
addresses are well-known at compile time. For example, user-defined types are implemented as
aggregates. Aggregates can collect data of a different type.
*/
typedef struct slang_storage_aggregate_
{
slang_storage_array *arrays;
unsigned int count;
} slang_storage_aggregate;
void slang_storage_aggregate_construct (slang_storage_aggregate *);
void slang_storage_aggregate_destruct (slang_storage_aggregate *);
int _slang_aggregate_variable (slang_storage_aggregate *, struct slang_type_specifier_ *,
struct slang_operation_ *, struct slang_function_scope_ *, slang_struct_scope *);
/*
returns total size (in machine units) of the given aggregate
returns 0 on error
*/
unsigned int _slang_sizeof_aggregate (const slang_storage_aggregate *);
/*
converts structured aggregate to a flat one, with arrays of generic type being
one-element long
returns 1 on success
returns 0 otherwise
*/
int _slang_flatten_aggregate (slang_storage_aggregate *, const slang_storage_aggregate *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -187,8 +187,14 @@ SLANG_CPP_SOURCES = \
shader/slang/OSDependent/Linux/ossource.cpp
SLANG_SOURCES = \
shader/slang/slang_assemble.c \
shader/slang/slang_assemble_conditional.c \
shader/slang/slang_assemble_constructor.c \
shader/slang/slang_assemble_typeinfo.c \
shader/slang/slang_compile.c \
shader/slang/slang_execute.c \
shader/slang/slang_preprocess.c \
shader/slang/slang_storage.c \
shader/slang/slang_utility.c
ASM_C_SOURCES = \