2 * Mesa 3-D graphics library
5 * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 * \file slang_compile.c
27 * slang front-end compiler
34 #include "prog_parameter.h"
35 #include "grammar_mesa.h"
36 #include "slang_codegen.h"
37 #include "slang_compile.h"
38 #include "slang_preprocess.h"
39 #include "slang_storage.h"
40 #include "slang_error.h"
42 #include "slang_print.h"
45 * This is a straightforward implementation of the slang front-end
46 * compiler. Lots of error-checking functionality is missing but
47 * every well-formed shader source should compile successfully and
48 * execute as expected. However, some semantically ill-formed shaders
49 * may be accepted resulting in undefined behaviour.
55 * Allocate storage for a variable of 'size' bytes from given pool.
56 * Return the allocated address for the variable.
59 slang_var_pool_alloc(slang_var_pool
* pool
, unsigned int size
)
61 const GLuint addr
= pool
->next_addr
;
62 pool
->next_addr
+= size
;
71 _slang_code_unit_ctr(slang_code_unit
* self
,
72 struct slang_code_object_
* object
)
74 _slang_variable_scope_ctr(&self
->vars
);
75 _slang_function_scope_ctr(&self
->funs
);
76 _slang_struct_scope_ctr(&self
->structs
);
77 self
->object
= object
;
81 _slang_code_unit_dtr(slang_code_unit
* self
)
83 slang_variable_scope_destruct(&self
->vars
);
84 slang_function_scope_destruct(&self
->funs
);
85 slang_struct_scope_destruct(&self
->structs
);
93 _slang_code_object_ctr(slang_code_object
* self
)
97 for (i
= 0; i
< SLANG_BUILTIN_TOTAL
; i
++)
98 _slang_code_unit_ctr(&self
->builtin
[i
], self
);
99 _slang_code_unit_ctr(&self
->unit
, self
);
100 _slang_assembly_file_ctr(&self
->assembly
);
101 slang_machine_ctr(&self
->machine
);
102 self
->varpool
.next_addr
= 0;
103 slang_atom_pool_construct(&self
->atompool
);
104 slang_export_data_table_ctr(&self
->expdata
);
105 self
->expdata
.atoms
= &self
->atompool
;
106 slang_export_code_table_ctr(&self
->expcode
);
107 self
->expcode
.atoms
= &self
->atompool
;
111 _slang_code_object_dtr(slang_code_object
* self
)
115 for (i
= 0; i
< SLANG_BUILTIN_TOTAL
; i
++)
116 _slang_code_unit_dtr(&self
->builtin
[i
]);
117 _slang_code_unit_dtr(&self
->unit
);
118 slang_assembly_file_destruct(&self
->assembly
);
119 slang_machine_dtr(&self
->machine
);
120 slang_atom_pool_destruct(&self
->atompool
);
121 slang_export_data_table_dtr(&self
->expdata
);
122 slang_export_code_table_ctr(&self
->expcode
);
127 static char *out_of_memory
= "Error: Out of memory.\n";
130 slang_info_log_construct(slang_info_log
* log
)
133 log
->dont_free_text
= 0;
137 slang_info_log_destruct(slang_info_log
* log
)
139 if (!log
->dont_free_text
)
140 slang_alloc_free(log
->text
);
144 slang_info_log_message(slang_info_log
* log
, const char *prefix
,
149 if (log
->dont_free_text
)
151 size
= slang_string_length(msg
) + 2;
153 size
+= slang_string_length(prefix
) + 2;
154 if (log
->text
!= NULL
) {
155 GLuint old_len
= slang_string_length(log
->text
);
157 slang_alloc_realloc(log
->text
, old_len
+ 1, old_len
+ size
);
160 log
->text
= (char *) (slang_alloc_malloc(size
));
161 if (log
->text
!= NULL
)
164 if (log
->text
== NULL
)
166 if (prefix
!= NULL
) {
167 slang_string_concat(log
->text
, prefix
);
168 slang_string_concat(log
->text
, ": ");
170 slang_string_concat(log
->text
, msg
);
171 slang_string_concat(log
->text
, "\n");
176 slang_info_log_print(slang_info_log
* log
, const char *msg
, ...)
182 _mesa_vsprintf(buf
, msg
, va
);
184 return slang_info_log_message(log
, NULL
, buf
);
188 slang_info_log_error(slang_info_log
* log
, const char *msg
, ...)
194 _mesa_vsprintf(buf
, msg
, va
);
196 if (slang_info_log_message(log
, "Error", buf
))
198 slang_info_log_memory(log
);
203 slang_info_log_warning(slang_info_log
* log
, const char *msg
, ...)
209 _mesa_vsprintf(buf
, msg
, va
);
211 if (slang_info_log_message(log
, "Warning", buf
))
213 slang_info_log_memory(log
);
218 slang_info_log_memory(slang_info_log
* log
)
220 if (!slang_info_log_message(log
, "Error", "Out of memory.")) {
221 log
->dont_free_text
= 1;
222 log
->text
= out_of_memory
;
227 /* slang_parse_ctx */
229 typedef struct slang_parse_ctx_
234 GLboolean global_scope
; /**< Is object being declared a global? */
235 slang_atom_pool
*atoms
;
236 slang_unit_type type
; /**< Vertex vs. Fragment */
239 /* slang_output_ctx */
241 typedef struct slang_output_ctx_
243 slang_variable_scope
*vars
;
244 slang_function_scope
*funs
;
245 slang_struct_scope
*structs
;
246 slang_assembly_file
*assembly
;
247 slang_var_pool
*global_pool
;
248 slang_machine
*machine
;
249 struct gl_program
*program
;
252 /* _slang_compile() */
255 parse_identifier_str(slang_parse_ctx
* C
, char **id
)
258 C
->I
+= _mesa_strlen(*id
) + 1;
262 parse_identifier(slang_parse_ctx
* C
)
266 id
= (const char *) C
->I
;
267 C
->I
+= _mesa_strlen(id
) + 1;
268 return slang_atom_pool_atom(C
->atoms
, id
);
272 parse_number(slang_parse_ctx
* C
, int *number
)
274 const int radix
= (int) (*C
->I
++);
276 while (*C
->I
!= '\0') {
278 if (*C
->I
>= '0' && *C
->I
<= '9')
279 digit
= (int) (*C
->I
- '0');
280 else if (*C
->I
>= 'A' && *C
->I
<= 'Z')
281 digit
= (int) (*C
->I
- 'A') + 10;
283 digit
= (int) (*C
->I
- 'a') + 10;
284 *number
= *number
* radix
+ digit
;
289 slang_info_log_warning(C
->L
, "%d: literal integer overflow.", *number
);
294 parse_float(slang_parse_ctx
* C
, float *number
)
296 char *integral
= NULL
;
297 char *fractional
= NULL
;
298 char *exponent
= NULL
;
301 parse_identifier_str(C
, &integral
);
302 parse_identifier_str(C
, &fractional
);
303 parse_identifier_str(C
, &exponent
);
305 whole
= (char *) (slang_alloc_malloc((_mesa_strlen(integral
) +
306 _mesa_strlen(fractional
) +
307 _mesa_strlen(exponent
) + 3) * sizeof(char)));
309 slang_info_log_memory(C
->L
);
313 slang_string_copy(whole
, integral
);
314 slang_string_concat(whole
, ".");
315 slang_string_concat(whole
, fractional
);
316 slang_string_concat(whole
, "E");
317 slang_string_concat(whole
, exponent
);
319 *number
= (float) (_mesa_strtod(whole
, (char **) NULL
));
321 slang_alloc_free(whole
);
325 /* revision number - increment after each change affecting emitted output */
329 check_revision(slang_parse_ctx
* C
)
331 if (*C
->I
!= REVISION
) {
332 slang_info_log_error(C
->L
, "Internal compiler error.");
339 static int parse_statement(slang_parse_ctx
*, slang_output_ctx
*,
341 static int parse_expression(slang_parse_ctx
*, slang_output_ctx
*,
343 static int parse_type_specifier(slang_parse_ctx
*, slang_output_ctx
*,
344 slang_type_specifier
*);
347 parse_array_len(slang_parse_ctx
* C
, slang_output_ctx
* O
, GLuint
* len
)
349 slang_operation array_size
;
350 slang_assembly_name_space space
;
353 if (!slang_operation_construct(&array_size
))
355 if (!parse_expression(C
, O
, &array_size
)) {
356 slang_operation_destruct(&array_size
);
360 space
.funcs
= O
->funs
;
361 space
.structs
= O
->structs
;
362 space
.vars
= O
->vars
;
363 result
= _slang_evaluate_int(O
->assembly
, O
->machine
, &space
,
364 &array_size
, len
, C
->atoms
);
365 slang_operation_destruct(&array_size
);
370 calculate_var_size(slang_parse_ctx
* C
, slang_output_ctx
* O
,
371 slang_variable
* var
)
373 slang_storage_aggregate agg
;
375 if (!slang_storage_aggregate_construct(&agg
))
377 if (!_slang_aggregate_variable(&agg
, &var
->type
.specifier
, var
->array_len
,
378 O
->funs
, O
->structs
, O
->vars
, O
->machine
,
379 O
->assembly
, C
->atoms
)) {
380 slang_storage_aggregate_destruct(&agg
);
383 var
->size
= _slang_sizeof_aggregate(&agg
);
384 slang_storage_aggregate_destruct(&agg
);
389 convert_to_array(slang_parse_ctx
* C
, slang_variable
* var
,
390 const slang_type_specifier
* sp
)
392 /* sized array - mark it as array, copy the specifier to the array element and
393 * parse the expression */
394 var
->type
.specifier
.type
= slang_spec_array
;
395 var
->type
.specifier
._array
= (slang_type_specifier
*)
396 slang_alloc_malloc(sizeof(slang_type_specifier
));
397 if (var
->type
.specifier
._array
== NULL
) {
398 slang_info_log_memory(C
->L
);
401 slang_type_specifier_ctr(var
->type
.specifier
._array
);
402 return slang_type_specifier_copy(var
->type
.specifier
._array
, sp
);
405 /* structure field */
408 #define FIELD_ARRAY 2
411 parse_struct_field_var(slang_parse_ctx
* C
, slang_output_ctx
* O
,
412 slang_variable
* var
, const slang_type_specifier
* sp
)
414 var
->a_name
= parse_identifier(C
);
415 if (var
->a_name
== SLANG_ATOM_NULL
)
420 if (!slang_type_specifier_copy(&var
->type
.specifier
, sp
))
424 if (!convert_to_array(C
, var
, sp
))
426 if (!parse_array_len(C
, O
, &var
->array_len
))
433 return calculate_var_size(C
, O
, var
);
437 parse_struct_field(slang_parse_ctx
* C
, slang_output_ctx
* O
,
438 slang_struct
* st
, slang_type_specifier
* sp
)
440 slang_output_ctx o
= *O
;
442 o
.structs
= st
->structs
;
443 if (!parse_type_specifier(C
, &o
, sp
))
447 slang_variable
*var
= slang_variable_scope_grow(st
->fields
);
449 slang_info_log_memory(C
->L
);
452 if (!parse_struct_field_var(C
, &o
, var
, sp
))
455 while (*C
->I
++ != FIELD_NONE
);
461 parse_struct(slang_parse_ctx
* C
, slang_output_ctx
* O
, slang_struct
** st
)
466 /* parse struct name (if any) and make sure it is unique in current scope */
467 a_name
= parse_identifier(C
);
468 if (a_name
== SLANG_ATOM_NULL
)
471 name
= slang_atom_pool_id(C
->atoms
, a_name
);
473 && slang_struct_scope_find(O
->structs
, a_name
, 0) != NULL
) {
474 slang_info_log_error(C
->L
, "%s: duplicate type name.", name
);
478 /* set-up a new struct */
479 *st
= (slang_struct
*) slang_alloc_malloc(sizeof(slang_struct
));
481 slang_info_log_memory(C
->L
);
484 if (!slang_struct_construct(*st
)) {
485 slang_alloc_free(*st
);
487 slang_info_log_memory(C
->L
);
490 (**st
).a_name
= a_name
;
491 (**st
).structs
->outer_scope
= O
->structs
;
493 /* parse individual struct fields */
495 slang_type_specifier sp
;
497 slang_type_specifier_ctr(&sp
);
498 if (!parse_struct_field(C
, O
, *st
, &sp
)) {
499 slang_type_specifier_dtr(&sp
);
502 slang_type_specifier_dtr(&sp
);
504 while (*C
->I
++ != FIELD_NONE
);
506 /* if named struct, copy it to current scope */
507 if (name
[0] != '\0') {
510 O
->structs
->structs
=
511 (slang_struct
*) slang_alloc_realloc(O
->structs
->structs
,
512 O
->structs
->num_structs
*
513 sizeof(slang_struct
),
514 (O
->structs
->num_structs
+
515 1) * sizeof(slang_struct
));
516 if (O
->structs
->structs
== NULL
) {
517 slang_info_log_memory(C
->L
);
520 s
= &O
->structs
->structs
[O
->structs
->num_structs
];
521 if (!slang_struct_construct(s
))
523 O
->structs
->num_structs
++;
524 if (!slang_struct_copy(s
, *st
))
533 #define TYPE_QUALIFIER_NONE 0
534 #define TYPE_QUALIFIER_CONST 1
535 #define TYPE_QUALIFIER_ATTRIBUTE 2
536 #define TYPE_QUALIFIER_VARYING 3
537 #define TYPE_QUALIFIER_UNIFORM 4
538 #define TYPE_QUALIFIER_FIXEDOUTPUT 5
539 #define TYPE_QUALIFIER_FIXEDINPUT 6
542 parse_type_qualifier(slang_parse_ctx
* C
, slang_type_qualifier
* qual
)
545 case TYPE_QUALIFIER_NONE
:
546 *qual
= slang_qual_none
;
548 case TYPE_QUALIFIER_CONST
:
549 *qual
= slang_qual_const
;
551 case TYPE_QUALIFIER_ATTRIBUTE
:
552 *qual
= slang_qual_attribute
;
554 case TYPE_QUALIFIER_VARYING
:
555 *qual
= slang_qual_varying
;
557 case TYPE_QUALIFIER_UNIFORM
:
558 *qual
= slang_qual_uniform
;
560 case TYPE_QUALIFIER_FIXEDOUTPUT
:
561 *qual
= slang_qual_fixedoutput
;
563 case TYPE_QUALIFIER_FIXEDINPUT
:
564 *qual
= slang_qual_fixedinput
;
573 #define TYPE_SPECIFIER_VOID 0
574 #define TYPE_SPECIFIER_BOOL 1
575 #define TYPE_SPECIFIER_BVEC2 2
576 #define TYPE_SPECIFIER_BVEC3 3
577 #define TYPE_SPECIFIER_BVEC4 4
578 #define TYPE_SPECIFIER_INT 5
579 #define TYPE_SPECIFIER_IVEC2 6
580 #define TYPE_SPECIFIER_IVEC3 7
581 #define TYPE_SPECIFIER_IVEC4 8
582 #define TYPE_SPECIFIER_FLOAT 9
583 #define TYPE_SPECIFIER_VEC2 10
584 #define TYPE_SPECIFIER_VEC3 11
585 #define TYPE_SPECIFIER_VEC4 12
586 #define TYPE_SPECIFIER_MAT2 13
587 #define TYPE_SPECIFIER_MAT3 14
588 #define TYPE_SPECIFIER_MAT4 15
589 #define TYPE_SPECIFIER_SAMPLER1D 16
590 #define TYPE_SPECIFIER_SAMPLER2D 17
591 #define TYPE_SPECIFIER_SAMPLER3D 18
592 #define TYPE_SPECIFIER_SAMPLERCUBE 19
593 #define TYPE_SPECIFIER_SAMPLER1DSHADOW 20
594 #define TYPE_SPECIFIER_SAMPLER2DSHADOW 21
595 #define TYPE_SPECIFIER_STRUCT 22
596 #define TYPE_SPECIFIER_TYPENAME 23
599 parse_type_specifier(slang_parse_ctx
* C
, slang_output_ctx
* O
,
600 slang_type_specifier
* spec
)
603 case TYPE_SPECIFIER_VOID
:
604 spec
->type
= slang_spec_void
;
606 case TYPE_SPECIFIER_BOOL
:
607 spec
->type
= slang_spec_bool
;
609 case TYPE_SPECIFIER_BVEC2
:
610 spec
->type
= slang_spec_bvec2
;
612 case TYPE_SPECIFIER_BVEC3
:
613 spec
->type
= slang_spec_bvec3
;
615 case TYPE_SPECIFIER_BVEC4
:
616 spec
->type
= slang_spec_bvec4
;
618 case TYPE_SPECIFIER_INT
:
619 spec
->type
= slang_spec_int
;
621 case TYPE_SPECIFIER_IVEC2
:
622 spec
->type
= slang_spec_ivec2
;
624 case TYPE_SPECIFIER_IVEC3
:
625 spec
->type
= slang_spec_ivec3
;
627 case TYPE_SPECIFIER_IVEC4
:
628 spec
->type
= slang_spec_ivec4
;
630 case TYPE_SPECIFIER_FLOAT
:
631 spec
->type
= slang_spec_float
;
633 case TYPE_SPECIFIER_VEC2
:
634 spec
->type
= slang_spec_vec2
;
636 case TYPE_SPECIFIER_VEC3
:
637 spec
->type
= slang_spec_vec3
;
639 case TYPE_SPECIFIER_VEC4
:
640 spec
->type
= slang_spec_vec4
;
642 case TYPE_SPECIFIER_MAT2
:
643 spec
->type
= slang_spec_mat2
;
645 case TYPE_SPECIFIER_MAT3
:
646 spec
->type
= slang_spec_mat3
;
648 case TYPE_SPECIFIER_MAT4
:
649 spec
->type
= slang_spec_mat4
;
651 case TYPE_SPECIFIER_SAMPLER1D
:
652 spec
->type
= slang_spec_sampler1D
;
654 case TYPE_SPECIFIER_SAMPLER2D
:
655 spec
->type
= slang_spec_sampler2D
;
657 case TYPE_SPECIFIER_SAMPLER3D
:
658 spec
->type
= slang_spec_sampler3D
;
660 case TYPE_SPECIFIER_SAMPLERCUBE
:
661 spec
->type
= slang_spec_samplerCube
;
663 case TYPE_SPECIFIER_SAMPLER1DSHADOW
:
664 spec
->type
= slang_spec_sampler1DShadow
;
666 case TYPE_SPECIFIER_SAMPLER2DSHADOW
:
667 spec
->type
= slang_spec_sampler2DShadow
;
669 case TYPE_SPECIFIER_STRUCT
:
670 spec
->type
= slang_spec_struct
;
671 if (!parse_struct(C
, O
, &spec
->_struct
))
674 case TYPE_SPECIFIER_TYPENAME
:
675 spec
->type
= slang_spec_struct
;
680 a_name
= parse_identifier(C
);
684 stru
= slang_struct_scope_find(O
->structs
, a_name
, 1);
686 slang_info_log_error(C
->L
, "undeclared type name '%s'",
687 slang_atom_pool_id(C
->atoms
, a_name
));
692 (slang_struct
*) slang_alloc_malloc(sizeof(slang_struct
));
693 if (spec
->_struct
== NULL
) {
694 slang_info_log_memory(C
->L
);
697 if (!slang_struct_construct(spec
->_struct
)) {
698 slang_alloc_free(spec
->_struct
);
699 spec
->_struct
= NULL
;
702 if (!slang_struct_copy(spec
->_struct
, stru
))
713 parse_fully_specified_type(slang_parse_ctx
* C
, slang_output_ctx
* O
,
714 slang_fully_specified_type
* type
)
716 if (!parse_type_qualifier(C
, &type
->qualifier
))
718 if (!parse_type_specifier(C
, O
, &type
->specifier
))
725 #define OP_BLOCK_BEGIN_NO_NEW_SCOPE 1
726 #define OP_BLOCK_BEGIN_NEW_SCOPE 2
730 #define OP_CONTINUE 6
733 #define OP_EXPRESSION 9
738 #define OP_PUSH_VOID 14
739 #define OP_PUSH_BOOL 15
740 #define OP_PUSH_INT 16
741 #define OP_PUSH_FLOAT 17
742 #define OP_PUSH_IDENTIFIER 18
743 #define OP_SEQUENCE 19
745 #define OP_ADDASSIGN 21
746 #define OP_SUBASSIGN 22
747 #define OP_MULASSIGN 23
748 #define OP_DIVASSIGN 24
749 /*#define OP_MODASSIGN 25*/
750 /*#define OP_LSHASSIGN 26*/
751 /*#define OP_RSHASSIGN 27*/
752 /*#define OP_ORASSIGN 28*/
753 /*#define OP_XORASSIGN 29*/
754 /*#define OP_ANDASSIGN 30*/
756 #define OP_LOGICALOR 32
757 #define OP_LOGICALXOR 33
758 #define OP_LOGICALAND 34
759 /*#define OP_BITOR 35*/
760 /*#define OP_BITXOR 36*/
761 /*#define OP_BITAND 37*/
763 #define OP_NOTEQUAL 39
765 #define OP_GREATER 41
766 #define OP_LESSEQUAL 42
767 #define OP_GREATEREQUAL 43
768 /*#define OP_LSHIFT 44*/
769 /*#define OP_RSHIFT 45*/
771 #define OP_SUBTRACT 47
772 #define OP_MULTIPLY 48
774 /*#define OP_MODULUS 50*/
775 #define OP_PREINCREMENT 51
776 #define OP_PREDECREMENT 52
779 /*#define OP_COMPLEMENT 55*/
781 #define OP_SUBSCRIPT 57
784 #define OP_POSTINCREMENT 60
785 #define OP_POSTDECREMENT 61
789 * When parsing a compound production, this function is used to parse the
791 * For example, a a while-loop compound will have two children, the
792 * while condition expression and the loop body. So, this function will
793 * be called twice to parse those two sub-expressions.
794 * \param C the parsing context
795 * \param O the output context
796 * \param oper the operation we're parsing
797 * \param statement indicates whether parsing a statement, or expression
798 * \return 1 if success, 0 if error
801 parse_child_operation(slang_parse_ctx
* C
, slang_output_ctx
* O
,
802 slang_operation
* oper
, GLboolean statement
)
806 /* grow child array */
807 ch
= slang_operation_grow(&oper
->num_children
, &oper
->children
);
809 return parse_statement(C
, O
, ch
);
810 return parse_expression(C
, O
, ch
);
813 static int parse_declaration(slang_parse_ctx
* C
, slang_output_ctx
* O
);
816 parse_statement(slang_parse_ctx
* C
, slang_output_ctx
* O
,
817 slang_operation
* oper
)
819 oper
->locals
->outer_scope
= O
->vars
;
821 case OP_BLOCK_BEGIN_NO_NEW_SCOPE
:
822 /* parse child statements, do not create new variable scope */
823 oper
->type
= slang_oper_block_no_new_scope
;
824 while (*C
->I
!= OP_END
)
825 if (!parse_child_operation(C
, O
, oper
, 1))
829 case OP_BLOCK_BEGIN_NEW_SCOPE
:
830 /* parse child statements, create new variable scope */
832 slang_output_ctx o
= *O
;
834 oper
->type
= slang_oper_block_new_scope
;
835 o
.vars
= oper
->locals
;
836 while (*C
->I
!= OP_END
)
837 if (!parse_child_operation(C
, &o
, oper
, 1))
843 /* local variable declaration, individual declarators are stored as
844 * children identifiers
846 oper
->type
= slang_oper_block_no_new_scope
;
848 const unsigned int first_var
= O
->vars
->num_variables
;
850 /* parse the declaration, note that there can be zero or more
851 * than one declarators
853 if (!parse_declaration(C
, O
))
855 if (first_var
< O
->vars
->num_variables
) {
856 const unsigned int num_vars
= O
->vars
->num_variables
- first_var
;
859 oper
->num_children
= num_vars
;
860 oper
->children
= slang_operation_new(num_vars
);
861 if (oper
->children
== NULL
) {
862 slang_info_log_memory(C
->L
);
865 for (i
= first_var
; i
< O
->vars
->num_variables
; i
++) {
866 slang_operation
*o
= &oper
->children
[i
- first_var
];
867 o
->type
= slang_oper_variable_decl
;
868 o
->locals
->outer_scope
= O
->vars
;
869 o
->a_id
= O
->vars
->variables
[i
].a_name
;
875 /* the __asm statement, parse the mnemonic and all its arguments
878 oper
->type
= slang_oper_asm
;
879 oper
->a_id
= parse_identifier(C
);
880 if (strcmp((char*)oper
->a_id
, "dot") == 0) {
881 printf("Assemble dot! **************************\n");
883 if (oper
->a_id
== SLANG_ATOM_NULL
)
885 while (*C
->I
!= OP_END
) {
886 if (!parse_child_operation(C
, O
, oper
, 0))
892 oper
->type
= slang_oper_break
;
895 oper
->type
= slang_oper_continue
;
898 oper
->type
= slang_oper_discard
;
901 oper
->type
= slang_oper_return
;
902 if (!parse_child_operation(C
, O
, oper
, 0))
906 oper
->type
= slang_oper_expression
;
907 if (!parse_child_operation(C
, O
, oper
, 0))
911 oper
->type
= slang_oper_if
;
912 if (!parse_child_operation(C
, O
, oper
, 0))
914 if (!parse_child_operation(C
, O
, oper
, 1))
916 if (!parse_child_operation(C
, O
, oper
, 1))
921 slang_output_ctx o
= *O
;
923 oper
->type
= slang_oper_while
;
924 o
.vars
= oper
->locals
;
925 if (!parse_child_operation(C
, &o
, oper
, 1))
927 if (!parse_child_operation(C
, &o
, oper
, 1))
932 oper
->type
= slang_oper_do
;
933 if (!parse_child_operation(C
, O
, oper
, 1))
935 if (!parse_child_operation(C
, O
, oper
, 0))
940 slang_output_ctx o
= *O
;
942 oper
->type
= slang_oper_for
;
943 o
.vars
= oper
->locals
;
944 if (!parse_child_operation(C
, &o
, oper
, 1))
946 if (!parse_child_operation(C
, &o
, oper
, 1))
948 if (!parse_child_operation(C
, &o
, oper
, 0))
950 if (!parse_child_operation(C
, &o
, oper
, 1))
961 handle_nary_expression(slang_parse_ctx
* C
, slang_operation
* op
,
962 slang_operation
** ops
, unsigned int *total_ops
,
968 (slang_operation
*) slang_alloc_malloc(n
* sizeof(slang_operation
));
969 if (op
->children
== NULL
) {
970 slang_info_log_memory(C
->L
);
973 op
->num_children
= n
;
975 for (i
= 0; i
< n
; i
++)
976 op
->children
[i
] = (*ops
)[*total_ops
- (n
+ 1 - i
)];
977 (*ops
)[*total_ops
- (n
+ 1)] = (*ops
)[*total_ops
- 1];
980 *ops
= (slang_operation
*)
981 slang_alloc_realloc(*ops
,
982 (*total_ops
+ n
) * sizeof(slang_operation
),
983 *total_ops
* sizeof(slang_operation
));
985 slang_info_log_memory(C
->L
);
992 is_constructor_name(const char *name
, slang_atom a_name
,
993 slang_struct_scope
* structs
)
995 if (slang_type_specifier_type_from_string(name
) != slang_spec_void
)
997 return slang_struct_scope_find(structs
, a_name
, 1) != NULL
;
1001 parse_expression(slang_parse_ctx
* C
, slang_output_ctx
* O
,
1002 slang_operation
* oper
)
1004 slang_operation
*ops
= NULL
;
1005 unsigned int num_ops
= 0;
1008 while (*C
->I
!= OP_END
) {
1009 slang_operation
*op
;
1010 const unsigned int op_code
= *C
->I
++;
1012 /* allocate default operation, becomes a no-op if not used */
1013 ops
= (slang_operation
*)
1014 slang_alloc_realloc(ops
,
1015 num_ops
* sizeof(slang_operation
),
1016 (num_ops
+ 1) * sizeof(slang_operation
));
1018 slang_info_log_memory(C
->L
);
1022 if (!slang_operation_construct(op
)) {
1023 slang_info_log_memory(C
->L
);
1027 op
->locals
->outer_scope
= O
->vars
;
1031 op
->type
= slang_oper_void
;
1034 op
->type
= slang_oper_literal_bool
;
1035 if (!parse_number(C
, &number
))
1040 op
->literal
[3] = (GLfloat
) number
;
1043 op
->type
= slang_oper_literal_int
;
1044 if (!parse_number(C
, &number
))
1049 op
->literal
[3] = (GLfloat
) number
;
1052 op
->type
= slang_oper_literal_float
;
1053 if (!parse_float(C
, &op
->literal
[0]))
1057 op
->literal
[3] = op
->literal
[0];
1059 case OP_PUSH_IDENTIFIER
:
1060 op
->type
= slang_oper_identifier
;
1061 op
->a_id
= parse_identifier(C
);
1062 if (op
->a_id
== SLANG_ATOM_NULL
)
1066 op
->type
= slang_oper_sequence
;
1067 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1071 op
->type
= slang_oper_assign
;
1072 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1076 op
->type
= slang_oper_addassign
;
1077 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1081 op
->type
= slang_oper_subassign
;
1082 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1086 op
->type
= slang_oper_mulassign
;
1087 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1091 op
->type
= slang_oper_divassign
;
1092 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1095 /*case OP_MODASSIGN: */
1096 /*case OP_LSHASSIGN: */
1097 /*case OP_RSHASSIGN: */
1098 /*case OP_ORASSIGN: */
1099 /*case OP_XORASSIGN: */
1100 /*case OP_ANDASSIGN: */
1102 op
->type
= slang_oper_select
;
1103 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 3))
1107 op
->type
= slang_oper_logicalor
;
1108 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1112 op
->type
= slang_oper_logicalxor
;
1113 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1117 op
->type
= slang_oper_logicaland
;
1118 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1122 /*case OP_BITXOR: */
1123 /*case OP_BITAND: */
1125 op
->type
= slang_oper_equal
;
1126 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1130 op
->type
= slang_oper_notequal
;
1131 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1135 op
->type
= slang_oper_less
;
1136 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1140 op
->type
= slang_oper_greater
;
1141 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1145 op
->type
= slang_oper_lessequal
;
1146 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1149 case OP_GREATEREQUAL
:
1150 op
->type
= slang_oper_greaterequal
;
1151 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1154 /*case OP_LSHIFT: */
1155 /*case OP_RSHIFT: */
1157 op
->type
= slang_oper_add
;
1158 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1162 op
->type
= slang_oper_subtract
;
1163 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1167 op
->type
= slang_oper_multiply
;
1168 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1172 op
->type
= slang_oper_divide
;
1173 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1176 /*case OP_MODULUS: */
1177 case OP_PREINCREMENT
:
1178 op
->type
= slang_oper_preincrement
;
1179 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 1))
1182 case OP_PREDECREMENT
:
1183 op
->type
= slang_oper_predecrement
;
1184 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 1))
1188 op
->type
= slang_oper_plus
;
1189 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 1))
1193 op
->type
= slang_oper_minus
;
1194 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 1))
1198 op
->type
= slang_oper_not
;
1199 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 1))
1202 /*case OP_COMPLEMENT: */
1204 op
->type
= slang_oper_subscript
;
1205 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 2))
1209 op
->type
= slang_oper_call
;
1210 op
->a_id
= parse_identifier(C
);
1211 if (op
->a_id
== SLANG_ATOM_NULL
)
1213 while (*C
->I
!= OP_END
)
1214 if (!parse_child_operation(C
, O
, op
, 0))
1218 if (!C
->parsing_builtin
1219 && !slang_function_scope_find_by_name(O
->funs
, op
->a_id
, 1)) {
1222 id
= slang_atom_pool_id(C
->atoms
, op
->a_id
);
1223 if (!is_constructor_name(id
, op
->a_id
, O
->structs
)) {
1224 slang_info_log_error(C
->L
, "%s: undeclared function name.", id
);
1230 op
->type
= slang_oper_field
;
1231 op
->a_id
= parse_identifier(C
);
1232 if (op
->a_id
== SLANG_ATOM_NULL
)
1234 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 1))
1237 case OP_POSTINCREMENT
:
1238 op
->type
= slang_oper_postincrement
;
1239 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 1))
1242 case OP_POSTDECREMENT
:
1243 op
->type
= slang_oper_postdecrement
;
1244 if (!handle_nary_expression(C
, op
, &ops
, &num_ops
, 1))
1254 slang_alloc_free(ops
);
1259 /* parameter qualifier */
1260 #define PARAM_QUALIFIER_IN 0
1261 #define PARAM_QUALIFIER_OUT 1
1262 #define PARAM_QUALIFIER_INOUT 2
1264 /* function parameter array presence */
1265 #define PARAMETER_ARRAY_NOT_PRESENT 0
1266 #define PARAMETER_ARRAY_PRESENT 1
1269 parse_parameter_declaration(slang_parse_ctx
* C
, slang_output_ctx
* O
,
1270 slang_variable
* param
)
1272 /* parse and validate the parameter's type qualifiers (there can be
1273 * two at most) because not all combinations are valid
1275 if (!parse_type_qualifier(C
, ¶m
->type
.qualifier
))
1278 case PARAM_QUALIFIER_IN
:
1279 if (param
->type
.qualifier
!= slang_qual_const
1280 && param
->type
.qualifier
!= slang_qual_none
) {
1281 slang_info_log_error(C
->L
, "Invalid type qualifier.");
1285 case PARAM_QUALIFIER_OUT
:
1286 if (param
->type
.qualifier
== slang_qual_none
)
1287 param
->type
.qualifier
= slang_qual_out
;
1289 slang_info_log_error(C
->L
, "Invalid type qualifier.");
1293 case PARAM_QUALIFIER_INOUT
:
1294 if (param
->type
.qualifier
== slang_qual_none
)
1295 param
->type
.qualifier
= slang_qual_inout
;
1297 slang_info_log_error(C
->L
, "Invalid type qualifier.");
1305 /* parse parameter's type specifier and name */
1306 if (!parse_type_specifier(C
, O
, ¶m
->type
.specifier
))
1308 param
->a_name
= parse_identifier(C
);
1309 if (param
->a_name
== SLANG_ATOM_NULL
)
1312 /* if the parameter is an array, parse its size (the size must be
1313 * explicitly defined
1315 if (*C
->I
++ == PARAMETER_ARRAY_PRESENT
) {
1316 slang_type_specifier p
;
1318 slang_type_specifier_ctr(&p
);
1319 if (!slang_type_specifier_copy(&p
, ¶m
->type
.specifier
)) {
1320 slang_type_specifier_dtr(&p
);
1323 if (!convert_to_array(C
, param
, &p
)) {
1324 slang_type_specifier_dtr(&p
);
1327 slang_type_specifier_dtr(&p
);
1328 if (!parse_array_len(C
, O
, ¶m
->array_len
))
1332 /* calculate the parameter size */
1333 if (!calculate_var_size(C
, O
, param
))
1336 /* TODO: allocate the local address here? */
1341 #define FUNCTION_ORDINARY 0
1342 #define FUNCTION_CONSTRUCTOR 1
1343 #define FUNCTION_OPERATOR 2
1345 /* function parameter */
1346 #define PARAMETER_NONE 0
1347 #define PARAMETER_NEXT 1
1350 #define OPERATOR_ADDASSIGN 1
1351 #define OPERATOR_SUBASSIGN 2
1352 #define OPERATOR_MULASSIGN 3
1353 #define OPERATOR_DIVASSIGN 4
1354 /*#define OPERATOR_MODASSIGN 5*/
1355 /*#define OPERATOR_LSHASSIGN 6*/
1356 /*#define OPERATOR_RSHASSIGN 7*/
1357 /*#define OPERATOR_ANDASSIGN 8*/
1358 /*#define OPERATOR_XORASSIGN 9*/
1359 /*#define OPERATOR_ORASSIGN 10*/
1360 #define OPERATOR_LOGICALXOR 11
1361 /*#define OPERATOR_BITOR 12*/
1362 /*#define OPERATOR_BITXOR 13*/
1363 /*#define OPERATOR_BITAND 14*/
1364 #define OPERATOR_LESS 15
1365 #define OPERATOR_GREATER 16
1366 #define OPERATOR_LESSEQUAL 17
1367 #define OPERATOR_GREATEREQUAL 18
1368 /*#define OPERATOR_LSHIFT 19*/
1369 /*#define OPERATOR_RSHIFT 20*/
1370 #define OPERATOR_MULTIPLY 21
1371 #define OPERATOR_DIVIDE 22
1372 /*#define OPERATOR_MODULUS 23*/
1373 #define OPERATOR_INCREMENT 24
1374 #define OPERATOR_DECREMENT 25
1375 #define OPERATOR_PLUS 26
1376 #define OPERATOR_MINUS 27
1377 /*#define OPERATOR_COMPLEMENT 28*/
1378 #define OPERATOR_NOT 29
1382 unsigned int o_code
;
1384 } operator_names
[] = {
1385 {OPERATOR_INCREMENT
, "++"},
1386 {OPERATOR_ADDASSIGN
, "+="},
1387 {OPERATOR_PLUS
, "+"},
1388 {OPERATOR_DECREMENT
, "--"},
1389 {OPERATOR_SUBASSIGN
, "-="},
1390 {OPERATOR_MINUS
, "-"},
1391 {OPERATOR_NOT
, "!"},
1392 {OPERATOR_MULASSIGN
, "*="},
1393 {OPERATOR_MULTIPLY
, "*"},
1394 {OPERATOR_DIVASSIGN
, "/="},
1395 {OPERATOR_DIVIDE
, "/"},
1396 {OPERATOR_LESSEQUAL
, "<="},
1397 /*{ OPERATOR_LSHASSIGN, "<<=" }, */
1398 /*{ OPERATOR_LSHIFT, "<<" }, */
1399 {OPERATOR_LESS
, "<"},
1400 {OPERATOR_GREATEREQUAL
, ">="},
1401 /*{ OPERATOR_RSHASSIGN, ">>=" }, */
1402 /*{ OPERATOR_RSHIFT, ">>" }, */
1403 {OPERATOR_GREATER
, ">"},
1404 /*{ OPERATOR_MODASSIGN, "%=" }, */
1405 /*{ OPERATOR_MODULUS, "%" }, */
1406 /*{ OPERATOR_ANDASSIGN, "&=" }, */
1407 /*{ OPERATOR_BITAND, "&" }, */
1408 /*{ OPERATOR_ORASSIGN, "|=" }, */
1409 /*{ OPERATOR_BITOR, "|" }, */
1410 /*{ OPERATOR_COMPLEMENT, "~" }, */
1411 /*{ OPERATOR_XORASSIGN, "^=" }, */
1412 {OPERATOR_LOGICALXOR
, "^^"},
1413 /*{ OPERATOR_BITXOR, "^" } */
1417 parse_operator_name(slang_parse_ctx
* C
)
1421 for (i
= 0; i
< sizeof(operator_names
) / sizeof(*operator_names
); i
++) {
1422 if (operator_names
[i
].o_code
== (unsigned int) (*C
->I
)) {
1424 slang_atom_pool_atom(C
->atoms
, operator_names
[i
].o_name
);
1425 if (atom
== SLANG_ATOM_NULL
) {
1426 slang_info_log_memory(C
->L
);
1437 parse_function_prototype(slang_parse_ctx
* C
, slang_output_ctx
* O
,
1438 slang_function
* func
)
1440 /* parse function type and name */
1441 if (!parse_fully_specified_type(C
, O
, &func
->header
.type
))
1444 case FUNCTION_ORDINARY
:
1445 func
->kind
= slang_func_ordinary
;
1446 func
->header
.a_name
= parse_identifier(C
);
1447 if (func
->header
.a_name
== SLANG_ATOM_NULL
)
1450 case FUNCTION_CONSTRUCTOR
:
1451 func
->kind
= slang_func_constructor
;
1452 if (func
->header
.type
.specifier
.type
== slang_spec_struct
)
1454 func
->header
.a_name
=
1455 slang_atom_pool_atom(C
->atoms
,
1456 slang_type_specifier_type_to_string
1457 (func
->header
.type
.specifier
.type
));
1458 if (func
->header
.a_name
== SLANG_ATOM_NULL
) {
1459 slang_info_log_memory(C
->L
);
1463 case FUNCTION_OPERATOR
:
1464 func
->kind
= slang_func_operator
;
1465 func
->header
.a_name
= parse_operator_name(C
);
1466 if (func
->header
.a_name
== SLANG_ATOM_NULL
)
1473 /* parse function parameters */
1474 while (*C
->I
++ == PARAMETER_NEXT
) {
1475 slang_variable
*p
= slang_variable_scope_grow(func
->parameters
);
1477 slang_info_log_memory(C
->L
);
1480 if (!parse_parameter_declaration(C
, O
, p
))
1485 /* if the function returns a value, append a hidden __retVal 'out'
1486 * parameter that corresponds to the return value.
1488 if (_slang_function_has_return_value(func
)) {
1489 slang_variable
*p
= slang_variable_scope_grow(func
->parameters
);
1490 slang_atom a_retVal
= slang_atom_pool_atom(C
->atoms
, "__retVal");
1492 p
->a_name
= a_retVal
;
1493 p
->type
= func
->header
.type
;
1494 p
->type
.qualifier
= slang_qual_out
;
1498 /* function formal parameters and local variables share the same
1499 * scope, so save the information about param count in a seperate
1500 * place also link the scope to the global variable scope so when a
1501 * given identifier is not found here, the search process continues
1502 * in the global space
1504 func
->param_count
= func
->parameters
->num_variables
;
1505 func
->parameters
->outer_scope
= O
->vars
;
1511 parse_function_definition(slang_parse_ctx
* C
, slang_output_ctx
* O
,
1512 slang_function
* func
)
1514 slang_output_ctx o
= *O
;
1516 if (!parse_function_prototype(C
, O
, func
))
1519 /* create function's body operation */
1521 (slang_operation
*) slang_alloc_malloc(sizeof(slang_operation
));
1522 if (func
->body
== NULL
) {
1523 slang_info_log_memory(C
->L
);
1526 if (!slang_operation_construct(func
->body
)) {
1527 slang_alloc_free(func
->body
);
1529 slang_info_log_memory(C
->L
);
1533 /* to parse the body the parse context is modified in order to
1534 * capture parsed variables into function's local variable scope
1536 C
->global_scope
= GL_FALSE
;
1537 o
.vars
= func
->parameters
;
1538 if (!parse_statement(C
, &o
, func
->body
))
1541 C
->global_scope
= GL_TRUE
;
1546 initialize_global(slang_assemble_ctx
* A
, slang_variable
* var
)
1548 slang_assembly_file_restore_point point
;
1550 slang_assembly_local_info save_local
= A
->local
;
1551 slang_operation op_id
, op_assign
;
1554 /* save the current assembly */
1555 if (!slang_assembly_file_restore_point_save(A
->file
, &point
))
1558 /* setup the machine */
1560 mach
.ip
= A
->file
->count
;
1562 /* allocate local storage for expression */
1563 A
->local
.ret_size
= 0;
1564 A
->local
.addr_tmp
= 0;
1565 A
->local
.swizzle_tmp
= 4;
1566 if (!slang_assembly_file_push_label(A
->file
, slang_asm_local_alloc
, 20))
1568 if (!slang_assembly_file_push_label(A
->file
, slang_asm_enter
, 20))
1571 /* construct the left side of assignment */
1572 if (!slang_operation_construct(&op_id
))
1574 op_id
.type
= slang_oper_identifier
;
1575 op_id
.a_id
= var
->a_name
;
1577 /* put the variable into operation's scope */
1578 op_id
.locals
->variables
=
1579 (slang_variable
*) slang_alloc_malloc(sizeof(slang_variable
));
1580 if (op_id
.locals
->variables
== NULL
) {
1581 slang_operation_destruct(&op_id
);
1584 op_id
.locals
->num_variables
= 1;
1585 op_id
.locals
->variables
[0] = *var
;
1587 /* construct the assignment expression */
1588 if (!slang_operation_construct(&op_assign
)) {
1589 op_id
.locals
->num_variables
= 0;
1590 slang_operation_destruct(&op_id
);
1593 op_assign
.type
= slang_oper_assign
;
1594 op_assign
.children
=
1595 (slang_operation
*) slang_alloc_malloc(2 * sizeof(slang_operation
));
1596 if (op_assign
.children
== NULL
) {
1597 slang_operation_destruct(&op_assign
);
1598 op_id
.locals
->num_variables
= 0;
1599 slang_operation_destruct(&op_id
);
1602 op_assign
.num_children
= 2;
1603 op_assign
.children
[0] = op_id
;
1604 op_assign
.children
[1] = *var
->initializer
;
1606 /* insert the actual expression */
1607 result
= _slang_assemble_operation(A
, &op_assign
, slang_ref_forbid
);
1609 /* carefully destroy the operations */
1610 op_assign
.num_children
= 0;
1611 slang_alloc_free(op_assign
.children
);
1612 op_assign
.children
= NULL
;
1613 slang_operation_destruct(&op_assign
);
1614 op_id
.locals
->num_variables
= 0;
1615 slang_operation_destruct(&op_id
);
1619 if (!slang_assembly_file_push(A
->file
, slang_asm_exit
))
1622 /* execute the expression */
1623 if (!_slang_execute2(A
->file
, &mach
))
1626 /* restore the old assembly */
1627 if (!slang_assembly_file_restore_point_load(A
->file
, &point
))
1629 A
->local
= save_local
;
1631 /* now we copy the contents of the initialized variable back to the original machine */
1632 _mesa_memcpy((GLubyte
*) A
->mach
->mem
+ var
->address
,
1633 (GLubyte
*) mach
.mem
+ var
->address
, var
->size
);
1638 /* init declarator list */
1639 #define DECLARATOR_NONE 0
1640 #define DECLARATOR_NEXT 1
1642 /* variable declaration */
1643 #define VARIABLE_NONE 0
1644 #define VARIABLE_IDENTIFIER 1
1645 #define VARIABLE_INITIALIZER 2
1646 #define VARIABLE_ARRAY_EXPLICIT 3
1647 #define VARIABLE_ARRAY_UNKNOWN 4
1651 * Parse the initializer for a variable declaration.
1654 parse_init_declarator(slang_parse_ctx
* C
, slang_output_ctx
* O
,
1655 const slang_fully_specified_type
* type
)
1657 slang_variable
*var
;
1659 /* empty init declatator (without name, e.g. "float ;") */
1660 if (*C
->I
++ == VARIABLE_NONE
)
1663 /* make room for the new variable and initialize it */
1664 var
= slang_variable_scope_grow(O
->vars
);
1666 slang_info_log_memory(C
->L
);
1670 /* copy the declarator qualifier type, parse the identifier */
1671 var
->global
= C
->global_scope
;
1672 var
->type
.qualifier
= type
->qualifier
;
1673 var
->a_name
= parse_identifier(C
);
1674 if (var
->a_name
== SLANG_ATOM_NULL
)
1679 /* simple variable declarator - just copy the specifier */
1680 if (!slang_type_specifier_copy(&var
->type
.specifier
, &type
->specifier
))
1683 case VARIABLE_INITIALIZER
:
1684 /* initialized variable - copy the specifier and parse the expression */
1685 if (!slang_type_specifier_copy(&var
->type
.specifier
, &type
->specifier
))
1688 (slang_operation
*) slang_alloc_malloc(sizeof(slang_operation
));
1689 if (var
->initializer
== NULL
) {
1690 slang_info_log_memory(C
->L
);
1693 if (!slang_operation_construct(var
->initializer
)) {
1694 slang_alloc_free(var
->initializer
);
1695 var
->initializer
= NULL
;
1696 slang_info_log_memory(C
->L
);
1699 if (!parse_expression(C
, O
, var
->initializer
))
1703 case VARIABLE_ARRAY_UNKNOWN
:
1704 /* unsized array - mark it as array and copy the specifier to
1707 if (!convert_to_array(C
, var
, &type
->specifier
))
1711 case VARIABLE_ARRAY_EXPLICIT
:
1712 if (!convert_to_array(C
, var
, &type
->specifier
))
1714 if (!parse_array_len(C
, O
, &var
->array_len
))
1722 if (C
->global_scope
/*&& O->program*/)
1723 _slang_codegen_global_variable(var
, O
->program
, C
->type
);
1726 /* allocate global address space for a variable with a known size */
1728 && !(var
->type
.specifier
.type
== slang_spec_array
1729 && var
->array_len
== 0)) {
1730 if (!calculate_var_size(C
, O
, var
))
1732 var
->address
= slang_var_pool_alloc(O
->global_pool
, var
->size
);
1735 /* initialize global variable */
1736 if (C
->global_scope
) {
1737 if (var
->initializer
!= NULL
) {
1738 slang_assemble_ctx A
;
1740 A
.file
= O
->assembly
;
1741 A
.mach
= O
->machine
;
1743 A
.space
.funcs
= O
->funs
;
1744 A
.space
.structs
= O
->structs
;
1745 A
.space
.vars
= O
->vars
;
1746 if (!initialize_global(&A
, var
))
1750 _mesa_memset((GLubyte
*) (O
->machine
->mem
) + var
->address
, 0,
1758 * Parse a list of variable declarations. Each variable may have an
1762 parse_init_declarator_list(slang_parse_ctx
* C
, slang_output_ctx
* O
)
1764 slang_fully_specified_type type
;
1766 /* parse the fully specified type, common to all declarators */
1767 if (!slang_fully_specified_type_construct(&type
))
1769 if (!parse_fully_specified_type(C
, O
, &type
)) {
1770 slang_fully_specified_type_destruct(&type
);
1774 /* parse declarators, pass-in the parsed type */
1776 if (!parse_init_declarator(C
, O
, &type
)) {
1777 slang_fully_specified_type_destruct(&type
);
1781 while (*C
->I
++ == DECLARATOR_NEXT
);
1783 slang_fully_specified_type_destruct(&type
);
1789 * Parse a function definition or declaration.
1790 * \param C parsing context
1791 * \param O output context
1792 * \param definition if non-zero expect a definition, else a declaration
1793 * \param parsed_func_ret returns the parsed function
1794 * \return GL_TRUE if success, GL_FALSE if failure
1797 parse_function(slang_parse_ctx
* C
, slang_output_ctx
* O
, int definition
,
1798 slang_function
** parsed_func_ret
)
1800 slang_function parsed_func
, *found_func
;
1802 /* parse function definition/declaration */
1803 if (!slang_function_construct(&parsed_func
))
1806 if (!parse_function_definition(C
, O
, &parsed_func
)) {
1807 slang_function_destruct(&parsed_func
);
1812 if (!parse_function_prototype(C
, O
, &parsed_func
)) {
1813 slang_function_destruct(&parsed_func
);
1818 /* find a function with a prototype matching the parsed one - only
1819 * the current scope is being searched to allow built-in function
1822 found_func
= slang_function_scope_find(O
->funs
, &parsed_func
, 0);
1823 if (found_func
== NULL
) {
1824 /* New function, add it to the function list */
1825 O
->funs
->functions
=
1826 (slang_function
*) slang_alloc_realloc(O
->funs
->functions
,
1827 O
->funs
->num_functions
*
1828 sizeof(slang_function
),
1829 (O
->funs
->num_functions
+
1830 1) * sizeof(slang_function
));
1831 if (O
->funs
->functions
== NULL
) {
1832 slang_info_log_memory(C
->L
);
1833 slang_function_destruct(&parsed_func
);
1836 O
->funs
->functions
[O
->funs
->num_functions
] = parsed_func
;
1837 O
->funs
->num_functions
++;
1839 /* return the newly parsed function */
1840 *parsed_func_ret
= &O
->funs
->functions
[O
->funs
->num_functions
- 1];
1843 /* previously defined or declared */
1844 /* TODO: check function return type qualifiers and specifiers */
1846 if (found_func
->body
!= NULL
) {
1847 slang_info_log_error(C
->L
, "%s: function already has a body.",
1848 slang_atom_pool_id(C
->atoms
,
1851 slang_function_destruct(&parsed_func
);
1855 /* destroy the existing function declaration and replace it
1856 * with the new one, remember to save the fixup table
1858 parsed_func
.fixups
= found_func
->fixups
;
1859 slang_fixup_table_init(&found_func
->fixups
);
1860 slang_function_destruct(found_func
);
1861 *found_func
= parsed_func
;
1864 /* another declaration of the same function prototype - ignore it */
1865 slang_function_destruct(&parsed_func
);
1868 /* return the found function */
1869 *parsed_func_ret
= found_func
;
1872 /* assemble the parsed function */
1874 slang_assemble_ctx A
;
1876 A
.file
= O
->assembly
;
1877 A
.mach
= O
->machine
;
1879 A
.space
.funcs
= O
->funs
;
1880 A
.space
.structs
= O
->structs
;
1881 A
.space
.vars
= O
->vars
;
1882 A
.program
= O
->program
;
1884 _slang_reset_error();
1887 printf("*************** Assemble function %s ****\n", (char *) (*parsed_func_ret
)->header
.a_name
);
1888 slang_print_var_scope((*parsed_func_ret
)->parameters
,
1889 (*parsed_func_ret
)->param_count
);
1893 if (!_slang_assemble_function(&A
, *parsed_func_ret
)) {
1894 /* propogate the error message back through the info log */
1895 C
->L
->text
= _mesa_strdup(_slang_error_text());
1896 C
->L
->dont_free_text
= GL_FALSE
;
1902 printf("**************************************\n");
1905 _slang_codegen_function(&A
, *parsed_func_ret
);
1912 #define DECLARATION_FUNCTION_PROTOTYPE 1
1913 #define DECLARATION_INIT_DECLARATOR_LIST 2
1916 parse_declaration(slang_parse_ctx
* C
, slang_output_ctx
* O
)
1919 case DECLARATION_INIT_DECLARATOR_LIST
:
1920 if (!parse_init_declarator_list(C
, O
))
1923 case DECLARATION_FUNCTION_PROTOTYPE
:
1925 slang_function
*dummy_func
;
1927 if (!parse_function(C
, O
, 0, &dummy_func
))
1937 /* external declaration */
1938 #define EXTERNAL_NULL 0
1939 #define EXTERNAL_FUNCTION_DEFINITION 1
1940 #define EXTERNAL_DECLARATION 2
1943 parse_code_unit(slang_parse_ctx
* C
, slang_code_unit
* unit
,
1944 struct gl_program
*program
)
1948 /* setup output context */
1949 o
.funs
= &unit
->funs
;
1950 o
.structs
= &unit
->structs
;
1951 o
.vars
= &unit
->vars
;
1952 o
.assembly
= &unit
->object
->assembly
;
1953 o
.global_pool
= &unit
->object
->varpool
;
1954 o
.machine
= &unit
->object
->machine
;
1955 o
.program
= program
;
1957 /* parse individual functions and declarations */
1958 while (*C
->I
!= EXTERNAL_NULL
) {
1960 case EXTERNAL_FUNCTION_DEFINITION
:
1962 slang_function
*func
;
1964 if (!parse_function(C
, &o
, 1, &func
))
1968 case EXTERNAL_DECLARATION
:
1969 if (!parse_declaration(C
, &o
))
1981 compile_binary(const byte
* prod
, slang_code_unit
* unit
,
1982 slang_unit_type type
, slang_info_log
* infolog
,
1983 slang_code_unit
* builtin
, slang_code_unit
* downlink
,
1984 struct gl_program
*program
)
1990 /* setup parse context */
1993 C
.parsing_builtin
= (builtin
== NULL
);
1994 C
.global_scope
= GL_TRUE
;
1995 C
.atoms
= &unit
->object
->atompool
;
1998 if (!check_revision(&C
))
2001 if (downlink
!= NULL
) {
2002 unit
->vars
.outer_scope
= &downlink
->vars
;
2003 unit
->funs
.outer_scope
= &downlink
->funs
;
2004 unit
->structs
.outer_scope
= &downlink
->structs
;
2007 /* parse translation unit */
2008 return parse_code_unit(&C
, unit
, program
);
2012 compile_with_grammar(grammar id
, const char *source
, slang_code_unit
* unit
,
2013 slang_unit_type type
, slang_info_log
* infolog
,
2014 slang_code_unit
* builtin
,
2015 struct gl_program
*program
)
2018 GLuint size
, start
, version
;
2019 slang_string preprocessed
;
2021 /* First retrieve the version number. */
2022 if (!_slang_preprocess_version(source
, &version
, &start
, infolog
))
2025 if (version
> 110) {
2026 slang_info_log_error(infolog
,
2027 "language version specified is not supported.");
2031 /* Now preprocess the source string. */
2032 slang_string_init(&preprocessed
);
2033 if (!_slang_preprocess_directives(&preprocessed
, &source
[start
], infolog
)) {
2034 slang_string_free(&preprocessed
);
2035 slang_info_log_error(infolog
, "failed to preprocess the source.");
2039 /* Finally check the syntax and generate its binary representation. */
2040 if (!grammar_fast_check(id
,
2041 (const byte
*) (slang_string_cstr(&preprocessed
)),
2047 slang_string_free(&preprocessed
);
2048 grammar_get_last_error((byte
*) (buf
), sizeof(buf
), &pos
);
2049 slang_info_log_error(infolog
, buf
);
2050 RETURN_ERROR("syntax error (possibly in library code)", 0);
2052 slang_string_free(&preprocessed
);
2054 /* Syntax is okay - translate it to internal representation. */
2055 if (!compile_binary(prod
, unit
, type
, infolog
, builtin
,
2056 &builtin
[SLANG_BUILTIN_TOTAL
- 1],
2058 grammar_alloc_free(prod
);
2061 grammar_alloc_free(prod
);
2065 LONGSTRING
static const char *slang_shader_syn
=
2066 #include "library/slang_shader_syn.h"
2069 static const byte slang_core_gc
[] = {
2070 #include "library/slang_core_gc.h"
2073 static const byte slang_common_builtin_gc
[] = {
2074 #include "library/slang_common_builtin_gc.h"
2077 static const byte slang_fragment_builtin_gc
[] = {
2078 #include "library/slang_fragment_builtin_gc.h"
2081 static const byte slang_vertex_builtin_gc
[] = {
2082 #include "library/slang_vertex_builtin_gc.h"
2085 #if defined(USE_X86_ASM) || defined(SLANG_X86)
2087 static const byte slang_builtin_vec4_gc
[] = {
2088 #include "library/slang_builtin_vec4_gc.h"
2093 compile_object(grammar
* id
, const char *source
, slang_code_object
* object
,
2094 slang_unit_type type
, slang_info_log
* infolog
,
2095 struct gl_program
*program
)
2097 slang_code_unit
*builtins
= NULL
;
2099 /* load GLSL grammar */
2100 *id
= grammar_load_from_text((const byte
*) (slang_shader_syn
));
2105 grammar_get_last_error(buf
, 1024, &pos
);
2106 slang_info_log_error(infolog
, (const char *) (buf
));
2110 /* set shader type - the syntax is slightly different for different shaders */
2111 if (type
== slang_unit_fragment_shader
2112 || type
== slang_unit_fragment_builtin
)
2113 grammar_set_reg8(*id
, (const byte
*) "shader_type", 1);
2115 grammar_set_reg8(*id
, (const byte
*) "shader_type", 2);
2117 /* enable language extensions */
2118 grammar_set_reg8(*id
, (const byte
*) "parsing_builtin", 1);
2120 /* if parsing user-specified shader, load built-in library */
2121 if (type
== slang_unit_fragment_shader
|| type
== slang_unit_vertex_shader
) {
2122 /* compile core functionality first */
2123 if (!compile_binary(slang_core_gc
,
2124 &object
->builtin
[SLANG_BUILTIN_CORE
],
2125 slang_unit_fragment_builtin
, infolog
,
2129 /* compile common functions and variables, link to core */
2130 if (!compile_binary(slang_common_builtin_gc
,
2131 &object
->builtin
[SLANG_BUILTIN_COMMON
],
2132 slang_unit_fragment_builtin
, infolog
, NULL
,
2133 &object
->builtin
[SLANG_BUILTIN_CORE
], NULL
))
2136 /* compile target-specific functions and variables, link to common */
2137 if (type
== slang_unit_fragment_shader
) {
2138 if (!compile_binary(slang_fragment_builtin_gc
,
2139 &object
->builtin
[SLANG_BUILTIN_TARGET
],
2140 slang_unit_fragment_builtin
, infolog
, NULL
,
2141 &object
->builtin
[SLANG_BUILTIN_COMMON
], NULL
))
2144 else if (type
== slang_unit_vertex_shader
) {
2145 if (!compile_binary(slang_vertex_builtin_gc
,
2146 &object
->builtin
[SLANG_BUILTIN_TARGET
],
2147 slang_unit_vertex_builtin
, infolog
, NULL
,
2148 &object
->builtin
[SLANG_BUILTIN_COMMON
], NULL
))
2152 #if defined(USE_X86_ASM) || defined(SLANG_X86)
2153 /* compile x86 4-component vector overrides, link to target */
2154 if (!compile_binary(slang_builtin_vec4_gc
,
2155 &object
->builtin
[SLANG_BUILTIN_VEC4
],
2156 slang_unit_fragment_builtin
, infolog
, NULL
,
2157 &object
->builtin
[SLANG_BUILTIN_TARGET
]))
2161 /* disable language extensions */
2162 #if NEW_SLANG /* allow-built-ins */
2163 grammar_set_reg8(*id
, (const byte
*) "parsing_builtin", 1);
2165 grammar_set_reg8(*id
, (const byte
*) "parsing_builtin", 0);
2167 builtins
= object
->builtin
;
2170 /* compile the actual shader - pass-in built-in library for external shader */
2171 return compile_with_grammar(*id
, source
, &object
->unit
, type
, infolog
,
2178 slang_create_uniforms(const slang_export_data_table
*exports
,
2179 struct gl_program
*program
)
2181 /* XXX only add uniforms that are actually going to get used */
2183 for (i
= 0; i
< exports
->count
; i
++) {
2184 if (exports
->entries
[i
].access
== slang_exp_uniform
) {
2185 const char *name
= (char *) exports
->entries
[i
].quant
.name
;
2186 GLint j
= _mesa_add_uniform(program
->Parameters
, name
, 4);
2195 compile_shader(GLcontext
*ctx
, slang_code_object
* object
,
2196 slang_unit_type type
, slang_info_log
* infolog
,
2197 struct gl_shader
*shader
)
2199 struct gl_program
*program
= shader
->Programs
[0];
2205 _slang_code_object_dtr(object
);
2206 _slang_code_object_ctr(object
);
2208 success
= compile_object(&id
, shader
->Source
, object
, type
, infolog
, program
);
2210 grammar_destroy(id
);
2214 if (!_slang_build_export_data_table(&object
->expdata
, &object
->unit
.vars
))
2216 if (!_slang_build_export_code_table(&object
->expcode
, &object
->unit
.funs
,
2222 slang_create_uniforms(&object
->expdata
, shader
);
2223 _mesa_print_program(program
);
2224 _mesa_print_program_parameters(ctx
, program
);
2234 _slang_compile(GLcontext
*ctx
, struct gl_shader
*shader
)
2237 slang_info_log info_log
;
2238 slang_code_object obj
;
2239 slang_unit_type type
;
2241 if (shader
->Type
== GL_VERTEX_SHADER
) {
2242 type
= slang_unit_vertex_shader
;
2245 assert(shader
->Type
== GL_FRAGMENT_SHADER
);
2246 type
= slang_unit_fragment_shader
;
2249 /* XXX temporary hack */
2250 if (!shader
->Programs
) {
2252 if (shader
->Type
== GL_VERTEX_SHADER
)
2253 progTarget
= GL_VERTEX_PROGRAM_ARB
;
2255 progTarget
= GL_FRAGMENT_PROGRAM_ARB
;
2257 = (struct gl_program
**) malloc(sizeof(struct gl_program
*));
2258 shader
->Programs
[0] = _mesa_new_program(ctx
, progTarget
, 1);
2259 shader
->NumPrograms
= 1;
2261 shader
->Programs
[0]->Parameters
= _mesa_new_parameter_list();
2262 shader
->Programs
[0]->Varying
= _mesa_new_parameter_list();
2263 shader
->Programs
[0]->Attributes
= _mesa_new_parameter_list();
2266 slang_info_log_construct(&info_log
);
2267 _slang_code_object_ctr(&obj
);
2269 success
= compile_shader(ctx
, &obj
, type
, &info_log
, shader
);
2273 slang_create_uniforms(&object
->expdata
, shader
);
2274 _mesa_print_program(program
);
2275 _mesa_print_program_parameters(ctx
, program
);
2279 /* XXX more work on info log needed here */
2280 if (info_log
.text
) {
2281 if (shader
->InfoLog
) {
2282 free(shader
->InfoLog
);
2283 shader
->InfoLog
= NULL
;
2285 shader
->InfoLog
= strdup(info_log
.text
);
2289 slang_info_log_destruct(&info_log
);
2290 _slang_code_object_dtr(&obj
);